You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4975 lines
157 KiB
4975 lines
157 KiB
//*************************************************************
|
|
//
|
|
// Group Policy Support - State functions
|
|
//
|
|
// Microsoft Confidential
|
|
// Copyright (c) Microsoft Corporation 1997-1998
|
|
// All rights reserved
|
|
//
|
|
//*************************************************************
|
|
|
|
#include "gphdr.h"
|
|
#include <strsafe.h>
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetDeletedGPOList()
|
|
//
|
|
// Purpose: Get the list of deleted GPOs
|
|
//
|
|
// Parameters: lpGPOList - List of old GPOs
|
|
// ppDeletedGPOList - Deleted list returned here
|
|
//
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL GetDeletedGPOList (PGROUP_POLICY_OBJECT lpGPOList,
|
|
PGROUP_POLICY_OBJECT *ppDeletedGPOList)
|
|
{
|
|
//
|
|
// It's possible that lpGPOList could be NULL. This is ok.
|
|
//
|
|
|
|
if (!lpGPOList) {
|
|
DebugMsg((DM_VERBOSE, TEXT("GetDeletedList: No old GPOs. Leaving.")));
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// We need to do any delete operations in reverse order
|
|
// of the way there were applied. Also, check that duplicates
|
|
// of same GPO are not being added.
|
|
//
|
|
|
|
while ( lpGPOList ) {
|
|
|
|
PGROUP_POLICY_OBJECT pCurGPO = lpGPOList;
|
|
lpGPOList = lpGPOList->pNext;
|
|
|
|
if ( pCurGPO->lParam & GPO_LPARAM_FLAG_DELETE ) {
|
|
|
|
PGROUP_POLICY_OBJECT lpGPODest = *ppDeletedGPOList;
|
|
BOOL bDup = FALSE;
|
|
|
|
while (lpGPODest) {
|
|
|
|
if (!lstrcmpi (pCurGPO->szGPOName, lpGPODest->szGPOName)) {
|
|
bDup = TRUE;
|
|
break;
|
|
}
|
|
|
|
lpGPODest = lpGPODest->pNext;
|
|
}
|
|
|
|
if (!bDup) {
|
|
|
|
//
|
|
// Not a duplicate, so prepend to deleted list
|
|
//
|
|
|
|
pCurGPO->pNext = *ppDeletedGPOList;
|
|
pCurGPO->pPrev = NULL;
|
|
|
|
if ( *ppDeletedGPOList )
|
|
(*ppDeletedGPOList)->pPrev = pCurGPO;
|
|
|
|
*ppDeletedGPOList = pCurGPO;
|
|
} else
|
|
LocalFree( pCurGPO );
|
|
|
|
} else
|
|
LocalFree( pCurGPO );
|
|
|
|
}
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("GetDeletedGPOList: Finished.")));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ReadGPOList()
|
|
//
|
|
// Purpose: Reads the list of Group Policy Objects from
|
|
// the registry
|
|
//
|
|
// Parameters: pszExtName - GP extension
|
|
// hKeyRoot - Registry handle
|
|
// hKeyRootMach - Registry handle to hklm
|
|
// lpwszSidUser - Sid of user, if non-null then it means
|
|
// per user local setting
|
|
// bShadow - Read from shadow or from history list
|
|
// lpGPOList - pointer to the array of GPOs
|
|
//
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL ReadGPOList ( TCHAR * pszExtName, HKEY hKeyRoot,
|
|
HKEY hKeyRootMach, LPTSTR lpwszSidUser, BOOL bShadow,
|
|
PGROUP_POLICY_OBJECT * lpGPOList)
|
|
{
|
|
INT iIndex = 0;
|
|
LONG lResult;
|
|
HKEY hKey, hSubKey = NULL;
|
|
BOOL bResult = FALSE;
|
|
TCHAR szSubKey[CCH_MAX_DEC];
|
|
DWORD dwOptions, dwVersion;
|
|
GPO_LINK GPOLink;
|
|
LPARAM lParam;
|
|
TCHAR szGPOName[50];
|
|
LPTSTR lpDSPath = NULL, lpFileSysPath = NULL, lpDisplayName = NULL, lpExtensions = NULL, lpLink = NULL;
|
|
DWORD dwDisp, dwSize, dwType, dwTemp, dwMaxSize;
|
|
PGROUP_POLICY_OBJECT lpGPO, lpGPOTemp;
|
|
TCHAR szKey[400];
|
|
XLastError xe;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Set default
|
|
//
|
|
|
|
*lpGPOList = NULL;
|
|
|
|
|
|
//
|
|
// Open the key that holds the GPO list
|
|
//
|
|
|
|
if ( lpwszSidUser == 0 ) {
|
|
hr = StringCchPrintf (szKey, ARRAYSIZE(szKey),
|
|
bShadow ? GP_SHADOW_KEY
|
|
: GP_HISTORY_KEY,
|
|
pszExtName );
|
|
|
|
} else {
|
|
hr = StringCchPrintf (szKey, ARRAYSIZE(szKey),
|
|
bShadow ? GP_SHADOW_SID_KEY
|
|
: GP_HISTORY_SID_KEY,
|
|
lpwszSidUser, pszExtName );
|
|
}
|
|
if ( FAILED(hr) ) {
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegOpenKeyEx ( lpwszSidUser ? hKeyRootMach : hKeyRoot,
|
|
szKey,
|
|
0, KEY_READ, &hKey);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
|
|
if (lResult == ERROR_FILE_NOT_FOUND) {
|
|
return TRUE;
|
|
|
|
} else {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to open reg key with %d."), lResult));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
while (TRUE) {
|
|
|
|
//
|
|
// Enumerate through the subkeys. The keys are named by index number
|
|
// eg: 0, 1, 2, 3, etc...
|
|
//
|
|
|
|
IntToString (iIndex, szSubKey);
|
|
|
|
lResult = RegOpenKeyEx (hKey, szSubKey, 0, KEY_READ, &hSubKey);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
|
|
if (lResult == ERROR_FILE_NOT_FOUND) {
|
|
bResult = TRUE;
|
|
goto Exit;
|
|
|
|
} else {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to open reg key <%s> with %d."), szSubKey, lResult));
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Read the size of the largest value in this key
|
|
//
|
|
|
|
lResult = RegQueryInfoKey (hSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&dwMaxSize, NULL, NULL);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query max size with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// RegQueryInfoKey does not account for trailing 0 in strings
|
|
//
|
|
|
|
dwMaxSize += sizeof( WCHAR );
|
|
|
|
|
|
//
|
|
// Allocate buffers based upon the value above
|
|
//
|
|
|
|
lpDSPath = (LPTSTR) LocalAlloc (LPTR, dwMaxSize);
|
|
|
|
if (!lpDSPath) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to allocate memory with %d."), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
lpFileSysPath = (LPTSTR) LocalAlloc (LPTR, dwMaxSize);
|
|
|
|
if (!lpFileSysPath) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to allocate memory with %d."), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
lpDisplayName = (LPTSTR) LocalAlloc (LPTR, dwMaxSize);
|
|
|
|
if (!lpDisplayName) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to allocate memory with %d."), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
lpExtensions = (LPTSTR) LocalAlloc (LPTR, dwMaxSize);
|
|
|
|
if (!lpExtensions) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to allocate memory with %d."), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
lpLink = (LPTSTR) LocalAlloc (LPTR, dwMaxSize);
|
|
|
|
if (!lpLink) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to allocate memory with %d."), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Read in the GPO
|
|
//
|
|
|
|
dwOptions = 0;
|
|
dwSize = sizeof(dwOptions);
|
|
lResult = RegQueryValueEx (hSubKey, TEXT("Options"), NULL, &dwType,
|
|
(LPBYTE) &dwOptions, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query options reg value with %d."), lResult));
|
|
}
|
|
|
|
|
|
dwVersion = 0;
|
|
dwSize = sizeof(dwVersion);
|
|
lResult = RegQueryValueEx (hSubKey, TEXT("Version"), NULL, &dwType,
|
|
(LPBYTE) &dwVersion, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query Version reg value with %d."), lResult));
|
|
}
|
|
|
|
|
|
dwSize = dwMaxSize;
|
|
lResult = RegQueryValueEx (hSubKey, TEXT("DSPath"), NULL, &dwType,
|
|
(LPBYTE) lpDSPath, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
if (lResult != ERROR_FILE_NOT_FOUND) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query DS reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
LocalFree (lpDSPath);
|
|
lpDSPath = NULL;
|
|
}
|
|
|
|
dwSize = dwMaxSize;
|
|
lResult = RegQueryValueEx (hSubKey, TEXT("FileSysPath"), NULL, &dwType,
|
|
(LPBYTE) lpFileSysPath, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query file sys path reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
dwSize = dwMaxSize;
|
|
lResult = RegQueryValueEx (hSubKey, TEXT("DisplayName"), NULL, &dwType,
|
|
(LPBYTE) lpDisplayName, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query display name reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = dwMaxSize;
|
|
lResult = RegQueryValueEx (hSubKey, TEXT("Extensions"), NULL, &dwType,
|
|
(LPBYTE) lpExtensions, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query extension names reg value with %d."), lResult));
|
|
|
|
LocalFree(lpExtensions);
|
|
lpExtensions = NULL;
|
|
}
|
|
|
|
dwSize = dwMaxSize;
|
|
lResult = RegQueryValueEx (hSubKey, TEXT("Link"), NULL, &dwType,
|
|
(LPBYTE) lpLink, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
if (lResult != ERROR_FILE_NOT_FOUND) {
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query DS Object reg value with %d."), lResult));
|
|
}
|
|
LocalFree(lpLink);
|
|
lpLink = NULL;
|
|
}
|
|
|
|
dwSize = sizeof(szGPOName);
|
|
lResult = RegQueryValueEx (hSubKey, TEXT("GPOName"), NULL, &dwType,
|
|
(LPBYTE) szGPOName, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query GPO name reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
GPOLink = GPLinkUnknown;
|
|
dwSize = sizeof(GPOLink);
|
|
lResult = RegQueryValueEx (hSubKey, TEXT("GPOLink"), NULL, &dwType,
|
|
(LPBYTE) &GPOLink, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query reserved reg value with %d."), lResult));
|
|
}
|
|
|
|
|
|
lParam = 0;
|
|
dwSize = sizeof(lParam);
|
|
lResult = RegQueryValueEx (hSubKey, TEXT("lParam"), NULL, &dwType,
|
|
(LPBYTE) &lParam, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to query lParam reg value with %d."), lResult));
|
|
}
|
|
|
|
|
|
//
|
|
// Add the GPO to the list
|
|
//
|
|
|
|
if (!AddGPO (lpGPOList, 0, TRUE, TRUE, FALSE, dwOptions, dwVersion, lpDSPath, lpFileSysPath,
|
|
lpDisplayName, szGPOName, lpExtensions, 0, 0, GPOLink, lpLink, lParam, FALSE,
|
|
FALSE, FALSE, TRUE)) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPOList: Failed to add GPO to list.")));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Free the buffers allocated above
|
|
//
|
|
|
|
if (lpDSPath) {
|
|
LocalFree (lpDSPath);
|
|
lpDSPath = NULL;
|
|
}
|
|
|
|
LocalFree (lpFileSysPath);
|
|
lpFileSysPath = NULL;
|
|
|
|
LocalFree (lpDisplayName);
|
|
lpDisplayName = NULL;
|
|
|
|
if (lpExtensions) {
|
|
LocalFree(lpExtensions);
|
|
lpExtensions = NULL;
|
|
}
|
|
|
|
if (lpLink) {
|
|
LocalFree(lpLink);
|
|
lpLink = NULL;
|
|
}
|
|
|
|
//
|
|
// Close the subkey handle
|
|
//
|
|
|
|
RegCloseKey (hSubKey);
|
|
hSubKey = NULL;
|
|
|
|
iIndex++;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (lpDSPath) {
|
|
LocalFree (lpDSPath);
|
|
}
|
|
|
|
if (lpFileSysPath) {
|
|
LocalFree (lpFileSysPath);
|
|
}
|
|
|
|
if (lpDisplayName) {
|
|
LocalFree (lpDisplayName);
|
|
}
|
|
|
|
if (lpExtensions) {
|
|
LocalFree(lpExtensions);
|
|
}
|
|
|
|
if (lpLink) {
|
|
LocalFree(lpLink);
|
|
}
|
|
|
|
|
|
if (hSubKey) {
|
|
RegCloseKey (hSubKey);
|
|
}
|
|
|
|
RegCloseKey (hKey);
|
|
|
|
if (!bResult) {
|
|
|
|
//
|
|
// Free any entries in the list
|
|
//
|
|
|
|
lpGPO = *lpGPOList;
|
|
|
|
while (lpGPO) {
|
|
lpGPOTemp = lpGPO->pNext;
|
|
LocalFree (lpGPO);
|
|
lpGPO = lpGPOTemp;
|
|
}
|
|
|
|
*lpGPOList = NULL;
|
|
}
|
|
|
|
|
|
return bResult;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// SaveGPOList()
|
|
//
|
|
// Purpose: Saves the list of Group Policy Objects in
|
|
// the registry
|
|
//
|
|
// Parameters: pszExtName - GP extension
|
|
// lpGPOInfo - Group policy info
|
|
// hKeyRootMach - Registry handle to hklm
|
|
// lpwszSidUser - Sid of user, if non-null then it means
|
|
// per user local setting
|
|
// bShadow - Save to shadow or to history list
|
|
// lpGPOList - Array of GPOs
|
|
//
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL SaveGPOList (TCHAR *pszExtName, LPGPOINFO lpGPOInfo,
|
|
HKEY hKeyRootMach, LPTSTR lpwszSidUser, BOOL bShadow,
|
|
PGROUP_POLICY_OBJECT lpGPOList)
|
|
{
|
|
INT iIndex = 0;
|
|
LONG lResult;
|
|
HKEY hKey = NULL;
|
|
BOOL bResult = FALSE;
|
|
TCHAR szSubKey[400];
|
|
DWORD dwDisp, dwSize;
|
|
XLastError xe;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Start off with an empty key
|
|
//
|
|
if ( lpwszSidUser == 0 ) {
|
|
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey),
|
|
bShadow ? GP_SHADOW_KEY
|
|
: GP_HISTORY_KEY,
|
|
pszExtName);
|
|
} else {
|
|
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey),
|
|
bShadow ? GP_SHADOW_SID_KEY
|
|
: GP_HISTORY_SID_KEY,
|
|
lpwszSidUser, pszExtName);
|
|
}
|
|
if ( FAILED(hr) ) {
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE; // no need to go to exit as hkey is not got yet.
|
|
}
|
|
|
|
if (RegDelnode (lpwszSidUser ? hKeyRootMach : lpGPOInfo->hKeyRoot, szSubKey) != ERROR_SUCCESS) {
|
|
DebugMsg((DM_VERBOSE, TEXT("SaveGPOList: RegDelnode failed.")));
|
|
}
|
|
|
|
|
|
//
|
|
// Check if we have any GPOs to store. It's ok for this to be NULL.
|
|
//
|
|
|
|
if (!lpGPOList) {
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Set the proper security on the registry key
|
|
//
|
|
|
|
if ( !MakeRegKeySecure( (lpGPOInfo->dwFlags & GP_MACHINE) ? NULL : lpGPOInfo->hToken,
|
|
lpwszSidUser ? hKeyRootMach : lpGPOInfo->hKeyRoot,
|
|
szSubKey ) ) {
|
|
DebugMsg((DM_WARNING, TEXT("SaveGpoList: Failed to secure reg key.")));
|
|
CEvents ev(TRUE, EVENT_FAILED_CREATE);
|
|
ev.AddArg(szSubKey);
|
|
ev.AddArgWin32Error(ERROR_ACCESS_DENIED);
|
|
ev.Report();
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Loop through the GPOs saving them in the registry
|
|
//
|
|
|
|
while (lpGPOList) {
|
|
|
|
if ( lpwszSidUser == 0 ) {
|
|
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey),
|
|
bShadow ? TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Shadow\\%ws\\%d")
|
|
: TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\History\\%ws\\%d"),
|
|
pszExtName,
|
|
iIndex);
|
|
} else {
|
|
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey),
|
|
bShadow ? TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\%ws\\Shadow\\%ws\\%d")
|
|
: TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\%ws\\History\\%ws\\%d"),
|
|
lpwszSidUser, pszExtName, iIndex);
|
|
}
|
|
if ( FAILED(hr) ) {
|
|
xe = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
lResult = RegCreateKeyEx (lpwszSidUser ? hKeyRootMach : lpGPOInfo->hKeyRoot,
|
|
szSubKey, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to create reg key with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Save the GPO
|
|
//
|
|
|
|
dwSize = sizeof(lpGPOList->dwOptions);
|
|
lResult = RegSetValueEx (hKey, TEXT("Options"), 0, REG_DWORD,
|
|
(LPBYTE) &lpGPOList->dwOptions, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to set options reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
dwSize = sizeof(lpGPOList->dwVersion);
|
|
lResult = RegSetValueEx (hKey, TEXT("Version"), 0, REG_DWORD,
|
|
(LPBYTE) &lpGPOList->dwVersion, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to set Version reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (lpGPOList->lpDSPath) {
|
|
|
|
dwSize = (lstrlen (lpGPOList->lpDSPath) + 1) * sizeof(TCHAR);
|
|
lResult = RegSetValueEx (hKey, TEXT("DSPath"), 0, REG_SZ,
|
|
(LPBYTE) lpGPOList->lpDSPath, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to set DS reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
dwSize = (lstrlen (lpGPOList->lpFileSysPath) + 1) * sizeof(TCHAR);
|
|
lResult = RegSetValueEx (hKey, TEXT("FileSysPath"), 0, REG_SZ,
|
|
(LPBYTE) lpGPOList->lpFileSysPath, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to set file sys path reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
dwSize = (lstrlen (lpGPOList->lpDisplayName) + 1) * sizeof(TCHAR);
|
|
lResult = RegSetValueEx (hKey, TEXT("DisplayName"), 0, REG_SZ,
|
|
(LPBYTE) lpGPOList->lpDisplayName, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to set display name reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
if (lpGPOList->lpExtensions) {
|
|
|
|
dwSize = (lstrlen (lpGPOList->lpExtensions) + 1) * sizeof(TCHAR);
|
|
lResult = RegSetValueEx (hKey, TEXT("Extensions"), 0, REG_SZ,
|
|
(LPBYTE) lpGPOList->lpExtensions, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to set extension names reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
|
|
if (lpGPOList->lpLink) {
|
|
|
|
dwSize = (lstrlen (lpGPOList->lpLink) + 1) * sizeof(TCHAR);
|
|
lResult = RegSetValueEx (hKey, TEXT("Link"), 0, REG_SZ,
|
|
(LPBYTE) lpGPOList->lpLink, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to set DSObject reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
|
|
dwSize = (lstrlen (lpGPOList->szGPOName) + 1) * sizeof(TCHAR);
|
|
lResult = RegSetValueEx (hKey, TEXT("GPOName"), 0, REG_SZ,
|
|
(LPBYTE) lpGPOList->szGPOName, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to set GPO name reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
dwSize = sizeof(lpGPOList->GPOLink);
|
|
lResult = RegSetValueEx (hKey, TEXT("GPOLink"), 0, REG_DWORD,
|
|
(LPBYTE) &lpGPOList->GPOLink, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to set GPOLink reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
dwSize = sizeof(lpGPOList->lParam);
|
|
lResult = RegSetValueEx (hKey, TEXT("lParam"), 0, REG_DWORD,
|
|
(LPBYTE) &lpGPOList->lParam, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("SaveGPOList: Failed to set lParam reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Close the handle
|
|
//
|
|
|
|
RegCloseKey (hKey);
|
|
hKey = NULL;
|
|
|
|
|
|
//
|
|
// Prep for the next loop
|
|
//
|
|
|
|
iIndex++;
|
|
lpGPOList = lpGPOList->pNext;
|
|
}
|
|
|
|
|
|
//
|
|
// Success
|
|
//
|
|
|
|
bResult = TRUE;
|
|
|
|
Exit:
|
|
|
|
if (hKey) {
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// WriteStatus()
|
|
//
|
|
// Purpose: Saves status in the registry
|
|
//
|
|
// Parameters: lpGPOInfo - GPO info
|
|
// lpExtName - GP extension name
|
|
// dwStatus - Status to write
|
|
// dwTime - Policy time to write
|
|
// dwSlowLink - Link speed to write
|
|
// dwRsopLogging - Rsop Logging to Write
|
|
//
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WriteStatus( TCHAR *lpExtName, LPGPOINFO lpGPOInfo, LPTSTR lpwszSidUser, LPGPEXTSTATUS lpExtStatus )
|
|
{
|
|
HKEY hKey = NULL, hKeyExt = NULL;
|
|
DWORD dwDisp, dwSize;
|
|
LONG lResult;
|
|
BOOL bResult = FALSE;
|
|
TCHAR szKey[400];
|
|
XLastError xe;
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( lpwszSidUser == 0 ) {
|
|
hr = StringCchPrintf (szKey, ARRAYSIZE(szKey),
|
|
GP_EXTENSIONS_KEY,
|
|
lpExtName);
|
|
} else {
|
|
hr = StringCchPrintf (szKey, ARRAYSIZE(szKey),
|
|
GP_EXTENSIONS_SID_KEY,
|
|
lpwszSidUser, lpExtName);
|
|
}
|
|
if ( FAILED(hr) ) {
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE; // no need to go to exit here
|
|
}
|
|
|
|
lResult = RegCreateKeyEx (lpwszSidUser ? HKEY_LOCAL_MACHINE : lpGPOInfo->hKeyRoot,
|
|
szKey, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("WriteStatus: Failed to create reg key with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(lpExtStatus->dwStatus);
|
|
lResult = RegSetValueEx (hKey, TEXT("Status"), 0, REG_DWORD,
|
|
(LPBYTE) &(lpExtStatus->dwStatus), dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("WriteStatus: Failed to set status reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(lpExtStatus->dwRsopStatus);
|
|
lResult = RegSetValueEx (hKey, TEXT("RsopStatus"), 0, REG_DWORD,
|
|
(LPBYTE) &(lpExtStatus->dwRsopStatus), dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("WriteStatus: Failed to set rsop status reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(lpExtStatus->dwTime);
|
|
lResult = RegSetValueEx (hKey, TEXT("LastPolicyTime"), 0, REG_DWORD,
|
|
(LPBYTE) &(lpExtStatus->dwTime), dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("WriteStatus: Failed to set time reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(lpExtStatus->dwSlowLink);
|
|
lResult = RegSetValueEx (hKey, TEXT("PrevSlowLink"), 0, REG_DWORD,
|
|
(LPBYTE) &(lpExtStatus->dwSlowLink), dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("WriteStatus: Failed to set slowlink reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(lpExtStatus->dwRsopLogging);
|
|
lResult = RegSetValueEx (hKey, TEXT("PrevRsopLogging"), 0, REG_DWORD,
|
|
(LPBYTE) &(lpExtStatus->dwRsopLogging), dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("WriteStatus: Failed to set RsopLogging reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
dwSize = sizeof(lpExtStatus->bForceRefresh);
|
|
lResult = RegSetValueEx (hKey, TEXT("ForceRefreshFG"), 0, REG_DWORD,
|
|
(LPBYTE) &(lpExtStatus->bForceRefresh), dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("WriteStatus: Failed to set ForceRefresh reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
bResult = TRUE;
|
|
|
|
Exit:
|
|
if ( hKey != NULL )
|
|
RegCloseKey( hKey );
|
|
|
|
if ( hKeyExt != NULL )
|
|
RegCloseKey( hKeyExt );
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ReadStatus()
|
|
//
|
|
// Purpose: Reads status from the registry
|
|
//
|
|
// Parameters: lpKeyName - Extension name
|
|
// lpGPOInfo - GPO info
|
|
// lpwszSidUser - Sid of user, if non-null then it means
|
|
// per user local setting
|
|
// (out) lpExtStatus - The extension status returned.
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
void ReadStatus ( TCHAR *lpKeyName, LPGPOINFO lpGPOInfo, LPTSTR lpwszSidUser, LPGPEXTSTATUS lpExtStatus )
|
|
{
|
|
HKEY hKey = NULL, hKeyExt = NULL;
|
|
DWORD dwType, dwSize;
|
|
LONG lResult;
|
|
BOOL bResult = FALSE;
|
|
TCHAR szKey[400];
|
|
XLastError xe;
|
|
HRESULT hr = S_OK;
|
|
|
|
memset(lpExtStatus, 0, sizeof(GPEXTSTATUS));
|
|
|
|
if ( lpwszSidUser == 0 ) {
|
|
hr = StringCchPrintf (szKey, ARRAYSIZE(szKey),
|
|
GP_EXTENSIONS_KEY,
|
|
lpKeyName);
|
|
} else {
|
|
hr = StringCchPrintf (szKey, ARRAYSIZE(szKey),
|
|
GP_EXTENSIONS_SID_KEY,
|
|
lpwszSidUser, lpKeyName);
|
|
}
|
|
if ( FAILED(hr) ) {
|
|
xe = ERROR_INSUFFICIENT_BUFFER;
|
|
return; // no need to go to exit here.
|
|
}
|
|
|
|
lResult = RegOpenKeyEx (lpwszSidUser ? HKEY_LOCAL_MACHINE : lpGPOInfo->hKeyRoot,
|
|
szKey,
|
|
0, KEY_READ, &hKey);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
if (lResult != ERROR_FILE_NOT_FOUND) {
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadStatus: Failed to open reg key with %d."), lResult));
|
|
}
|
|
xe = lResult;
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
lResult = RegQueryValueEx( hKey, TEXT("Status"), NULL,
|
|
&dwType, (LPBYTE) &(lpExtStatus->dwStatus),
|
|
&dwSize );
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
if (lResult != ERROR_FILE_NOT_FOUND) {
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadStatus: Failed to read status reg value with %d."), lResult));
|
|
}
|
|
xe = lResult;
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
lResult = RegQueryValueEx( hKey, TEXT("RsopStatus"), NULL,
|
|
&dwType, (LPBYTE) &(lpExtStatus->dwRsopStatus),
|
|
&dwSize );
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
if (lResult != ERROR_FILE_NOT_FOUND) {
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadStatus: Failed to read rsop status reg value with %d."), lResult));
|
|
}
|
|
|
|
// rsop status was not found. treat it as a legacy cse not supporting rsop
|
|
lpExtStatus->dwRsopStatus = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
|
xe = lResult;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
lResult = RegQueryValueEx( hKey, TEXT("LastPolicyTime"), NULL,
|
|
&dwType, (LPBYTE) &(lpExtStatus->dwTime),
|
|
&dwSize );
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadStatus: Failed to read time reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
lResult = RegQueryValueEx( hKey, TEXT("PrevSlowLink"), NULL,
|
|
&dwType, (LPBYTE) &(lpExtStatus->dwSlowLink),
|
|
&dwSize );
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadStatus: Failed to read slowlink reg value with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
dwSize = sizeof(DWORD);
|
|
lResult = RegQueryValueEx( hKey, TEXT("PrevRsopLogging"), NULL,
|
|
&dwType, (LPBYTE) &(lpExtStatus->dwRsopLogging),
|
|
&dwSize );
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadStatus: Failed to read rsop logging reg value with %d."), lResult));
|
|
|
|
//
|
|
// This can fail currently (first time or run first time after upgrade) with File not found.
|
|
// we will treat it as if logging was not turned on.
|
|
}
|
|
|
|
|
|
lpExtStatus->bForceRefresh = FALSE;
|
|
dwSize = sizeof(lpExtStatus->bForceRefresh);
|
|
lResult = RegQueryValueEx( hKey, TEXT("ForceRefreshFG"), NULL,
|
|
&dwType, (LPBYTE) &(lpExtStatus->bForceRefresh),
|
|
&dwSize );
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadStatus: Failed to read ForceRefreshFG value with %d."), lResult));
|
|
|
|
}
|
|
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadStatus: Read Extension's Previous status successfully.")));
|
|
bResult = TRUE;
|
|
|
|
Exit:
|
|
if ( hKey != NULL )
|
|
RegCloseKey( hKey );
|
|
|
|
if ( hKeyExt != NULL )
|
|
RegCloseKey( hKeyExt );
|
|
|
|
lpExtStatus->bStatus = bResult;
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ReadExtStatus()
|
|
//
|
|
// Purpose: Reads all the extensions status
|
|
//
|
|
// Parameters: lpGPOInfo - GPOInfo structure
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE otherwise
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL ReadExtStatus(LPGPOINFO lpGPOInfo)
|
|
{
|
|
LPGPEXT lpExt = lpGPOInfo->lpExtensions;
|
|
|
|
while ( lpExt ) {
|
|
|
|
BOOL bUsePerUserLocalSetting = lpExt->dwUserLocalSetting && !(lpGPOInfo->dwFlags & GP_MACHINE);
|
|
|
|
lpExt->lpPrevStatus = (LPGPEXTSTATUS) LocalAlloc(LPTR, sizeof(GPEXTSTATUS));
|
|
|
|
if (!(lpExt->lpPrevStatus)) {
|
|
DebugMsg((DM_WARNING, TEXT("ReadExtStatus: Couldn't allocate memory")));
|
|
CEvents ev(TRUE, EVENT_OUT_OF_MEMORY);
|
|
ev.AddArgWin32Error(GetLastError()); ev.Report();
|
|
return FALSE;
|
|
// Things that are already allocated will be freed by the caller
|
|
}
|
|
|
|
|
|
DmAssert( !bUsePerUserLocalSetting || lpGPOInfo->lpwszSidUser != 0 );
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadExtStatus: Reading Previous Status for extension %s"), lpExt->lpKeyName));
|
|
|
|
ReadStatus( lpExt->lpKeyName, lpGPOInfo,
|
|
bUsePerUserLocalSetting ? lpGPOInfo->lpwszSidUser : NULL,
|
|
lpExt->lpPrevStatus );
|
|
|
|
lpExt = lpExt->pNext;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// HistoryPresent()
|
|
//
|
|
// Purpose: Checks if the current extension has any cached
|
|
// GPOs
|
|
//
|
|
// Parameters: lpGPOInfo - GPOInfo
|
|
// lpExt - Extension
|
|
// pbPresent - (out) returns true if history is present
|
|
//
|
|
//
|
|
// Return: TRUE on success
|
|
// FALSE otherwise
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL HistoryPresent( LPGPOINFO lpGPOInfo, LPGPEXT lpExt, BOOL *pbPresent )
|
|
{
|
|
TCHAR szKey[400];
|
|
LONG lResult;
|
|
HKEY hKey;
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), GP_HISTORY_KEY, lpExt->lpKeyName );
|
|
if ( FAILED(hr) ) {
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegOpenKeyEx ( lpGPOInfo->hKeyRoot,
|
|
szKey,
|
|
0, KEY_READ, &hKey);
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
|
|
RegCloseKey( hKey );
|
|
*pbPresent = TRUE;
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
//
|
|
// Check if history is cached on per user per machine basis
|
|
//
|
|
|
|
BOOL bUsePerUserLocalSetting = lpExt->dwUserLocalSetting && !(lpGPOInfo->dwFlags & GP_MACHINE);
|
|
|
|
DmAssert( !bUsePerUserLocalSetting || lpGPOInfo->lpwszSidUser != 0 );
|
|
|
|
if ( bUsePerUserLocalSetting ) {
|
|
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), GP_HISTORY_SID_KEY, lpGPOInfo->lpwszSidUser, lpExt->lpKeyName );
|
|
if ( FAILED(hr) ) {
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegOpenKeyEx ( HKEY_LOCAL_MACHINE,
|
|
szKey,
|
|
0, KEY_READ, &hKey);
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
RegCloseKey( hKey );
|
|
*pbPresent = TRUE;
|
|
return TRUE;
|
|
} else {
|
|
*pbPresent = FALSE;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
*pbPresent = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// MigrateMembershipData()
|
|
//
|
|
// Purpose: Moves group membership data from old sid to new
|
|
// sid.
|
|
//
|
|
// Parameters: lpwszSidUserNew - New sid
|
|
// lpwszSidUserOld - Old sid
|
|
//
|
|
// Return: TRUE if success
|
|
// FALSE otherwise
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL MigrateMembershipData( LPTSTR lpwszSidUserNew, LPTSTR lpwszSidUserOld )
|
|
{
|
|
DWORD dwCount = 0;
|
|
DWORD dwSize, dwType, dwMaxSize, dwDisp;
|
|
DWORD i= 0;
|
|
LONG lResult;
|
|
HKEY hKeyRead = NULL, hKeyWrite = NULL;
|
|
BOOL bResult = TRUE;
|
|
LPTSTR lpSid = NULL;
|
|
TCHAR szKeyRead[250];
|
|
TCHAR szKeyWrite[250];
|
|
const DWORD dwGrpLength = 30;
|
|
TCHAR szGroup[dwGrpLength];
|
|
XLastError xe;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = StringCchPrintf( szKeyRead, ARRAYSIZE(szKeyRead), GP_MEMBERSHIP_KEY, lpwszSidUserOld );
|
|
if (FAILED(hr)) {
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKeyRead, 0, KEY_READ, &hKeyRead);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
return TRUE;
|
|
|
|
hr = StringCchPrintf( szKeyWrite, ARRAYSIZE(szKeyWrite), GP_MEMBERSHIP_KEY, lpwszSidUserNew );
|
|
if (FAILED(hr)) {
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegDelnode( HKEY_LOCAL_MACHINE, szKeyWrite );
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_VERBOSE, TEXT("MigrateMembershipData: RegDelnode failed.")));
|
|
bResult = FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, szKeyWrite, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKeyWrite, &dwDisp);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("MigrateMembershipData: Failed to create key with %d."), lResult));
|
|
bResult = FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(dwCount);
|
|
lResult = RegQueryValueEx (hKeyRead, TEXT("Count"), NULL, &dwType,
|
|
(LPBYTE) &dwCount, &dwSize);
|
|
if ( lResult != ERROR_SUCCESS ) {
|
|
xe = lResult;
|
|
DebugMsg((DM_VERBOSE, TEXT("MigrateMembershipData: Failed to read membership count")));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
lResult = RegQueryInfoKey (hKeyRead, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&dwMaxSize, NULL, NULL);
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("MigrateMembershipData: Failed to query max size with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// RegQueryInfoKey does not account for trailing 0 in strings
|
|
//
|
|
|
|
dwMaxSize += sizeof( WCHAR );
|
|
|
|
|
|
//
|
|
// Allocate buffer based upon the largest value
|
|
//
|
|
|
|
lpSid = (LPTSTR) LocalAlloc (LPTR, dwMaxSize);
|
|
|
|
if (!lpSid) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("MigrateMembershipData: Failed to allocate memory with %d."), lResult));
|
|
bResult = FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
for ( i=0; i<dwCount; i++ ) {
|
|
|
|
hr = StringCchPrintf( szGroup, dwGrpLength, TEXT("Group%d"), i );
|
|
if ( FAILED(hr) ) {
|
|
xe = HRESULT_CODE(hr);
|
|
bResult = FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = dwMaxSize;
|
|
lResult = RegQueryValueEx (hKeyRead, szGroup, NULL, &dwType, (LPBYTE) lpSid, &dwSize);
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("MigrateMembershipData: Failed to read value %ws"), szGroup ));
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = (lstrlen(lpSid) + 1) * sizeof(TCHAR);
|
|
lResult = RegSetValueEx (hKeyWrite, szGroup, 0, REG_SZ, (LPBYTE) lpSid, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
bResult = FALSE;
|
|
DebugMsg((DM_WARNING, TEXT("MigrateMembershipData: Failed to write value %ws"), szGroup ));
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
|
|
dwSize = sizeof(dwCount);
|
|
lResult = RegSetValueEx (hKeyWrite, TEXT("Count"), 0, REG_DWORD, (LPBYTE) &dwCount, dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
xe = lResult;
|
|
bResult = FALSE;
|
|
DebugMsg((DM_WARNING, TEXT("MigrateMembershipData: Failed to write count value") ));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
if ( lpSid )
|
|
LocalFree( lpSid );
|
|
|
|
if ( hKeyRead )
|
|
RegCloseKey (hKeyRead);
|
|
|
|
if ( hKeyWrite )
|
|
RegCloseKey (hKeyWrite);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// MigrateGPOData()
|
|
//
|
|
// Purpose: Moves cached GPOs from old sid to new
|
|
// sid.
|
|
//
|
|
// Parameters: lpGPOInfo - GPOInfo
|
|
// lpwszSidUserNew - New sid
|
|
// lpwszSidUserOld - Old sid
|
|
//
|
|
// Return: TRUE if success
|
|
// FALSE otherwise
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL MigrateGPOData( LPGPOINFO lpGPOInfo, LPTSTR lpwszSidUserNew, LPTSTR lpwszSidUserOld )
|
|
{
|
|
TCHAR szKey[250];
|
|
LONG lResult;
|
|
HKEY hKey = NULL;
|
|
DWORD dwIndex = 0;
|
|
TCHAR szExtension[50];
|
|
DWORD dwSize = 50;
|
|
PGROUP_POLICY_OBJECT pGPOList, lpGPO, lpGPOTemp;
|
|
BOOL bResult;
|
|
XLastError xe;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), GP_HISTORY_SID_ROOT_KEY, lpwszSidUserOld );
|
|
if (FAILED(hr)) {
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hKey);
|
|
if ( lResult != ERROR_SUCCESS )
|
|
return TRUE;
|
|
|
|
while (RegEnumKeyEx (hKey, dwIndex, szExtension, &dwSize,
|
|
NULL, NULL, NULL, NULL) == ERROR_SUCCESS ) {
|
|
|
|
if ( ReadGPOList( szExtension, NULL, HKEY_LOCAL_MACHINE,
|
|
lpwszSidUserOld, FALSE, &pGPOList) ) {
|
|
|
|
bResult = SaveGPOList( szExtension, lpGPOInfo, HKEY_LOCAL_MACHINE,
|
|
lpwszSidUserNew, FALSE, pGPOList );
|
|
lpGPO = pGPOList;
|
|
|
|
while (lpGPO) {
|
|
lpGPOTemp = lpGPO->pNext;
|
|
LocalFree (lpGPO);
|
|
lpGPO = lpGPOTemp;
|
|
}
|
|
|
|
if ( !bResult ) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("MigrateGPOData: Failed to save GPO list") ));
|
|
RegCloseKey( hKey );
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
else {
|
|
CEvents ev(TRUE, EVENT_READ_EXT_FAILED); // Fixing bug 569320
|
|
ev.AddArgWin32Error(GetLastError()); ev.Report();
|
|
}
|
|
|
|
dwSize = ARRAYSIZE(szExtension);
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// MigrateStatusData()
|
|
//
|
|
// Purpose: Moves extension status data from old sid to new
|
|
// sid.
|
|
//
|
|
// Parameters: lpGPOInfo - GPOInfo
|
|
// lpwszSidUserNew - New sid
|
|
// lpwszSidUserOld - Old sid
|
|
//
|
|
// Return: TRUE if success
|
|
// FALSE otherwise
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL MigrateStatusData( LPGPOINFO lpGPOInfo, LPTSTR lpwszSidUserNew, LPTSTR lpwszSidUserOld )
|
|
{
|
|
TCHAR szKey[250];
|
|
LONG lResult;
|
|
HKEY hKey = NULL;
|
|
DWORD dwIndex = 0;
|
|
TCHAR szExtension[50];
|
|
DWORD dwSize = 50;
|
|
BOOL bTemp;
|
|
XLastError xe;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), GP_EXTENSIONS_SID_ROOT_KEY, lpwszSidUserOld );
|
|
if (FAILED(hr)) {
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hKey);
|
|
if ( lResult != ERROR_SUCCESS )
|
|
return TRUE;
|
|
|
|
while (RegEnumKeyEx (hKey, dwIndex, szExtension, &dwSize,
|
|
NULL, NULL, NULL, NULL) == ERROR_SUCCESS ) {
|
|
|
|
GPEXTSTATUS gpExtStatus;
|
|
|
|
ReadStatus( szExtension, lpGPOInfo, lpwszSidUserOld, &gpExtStatus);
|
|
|
|
if (gpExtStatus.bStatus) {
|
|
bTemp = WriteStatus( szExtension, lpGPOInfo, lpwszSidUserNew, &gpExtStatus );
|
|
|
|
if ( !bTemp ) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("MigrateStatusData: Failed to save status") ));
|
|
RegCloseKey( hKey );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
dwSize = ARRAYSIZE(szExtension);
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// CheckForChangedSid()
|
|
//
|
|
// Purpose: Checks if the user's sid has changed and if so,
|
|
// moves history data from old sid to new sid.
|
|
//
|
|
// Parameters: lpGPOInfo - GPOInfo
|
|
//
|
|
// Return: TRUE if success
|
|
// FALSE otherwise
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL CheckForChangedSid (LPGPOINFO lpGPOInfo, CLocator *locator)
|
|
{
|
|
TCHAR szKey[400];
|
|
LONG lResult;
|
|
HKEY hKey = NULL;
|
|
LPTSTR lpwszSidUserOld = NULL;
|
|
DWORD dwDisp;
|
|
BOOL bCommit = FALSE; // True, if move of history data should be committed
|
|
XLastError xe;
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// initialize it to FALSE at the beginning and if the Sid has
|
|
// changed we will set it to true later on..
|
|
//
|
|
|
|
lpGPOInfo->bSidChanged = FALSE;
|
|
|
|
if ( lpGPOInfo->dwFlags & GP_MACHINE )
|
|
return TRUE;
|
|
|
|
|
|
if ( lpGPOInfo->lpwszSidUser == 0 ) {
|
|
|
|
lpGPOInfo->lpwszSidUser = GetSidString( lpGPOInfo->hToken );
|
|
if ( lpGPOInfo->lpwszSidUser == 0 ) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: GetSidString failed.")));
|
|
CEvents ev(TRUE, EVENT_FAILED_GET_SID); ev.Report();
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (!(lpGPOInfo->dwFlags & GP_APPLY_DS_POLICY))
|
|
return TRUE;
|
|
|
|
//
|
|
// Check if the key where history is cached exists
|
|
//
|
|
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), GP_POLICY_SID_KEY, lpGPOInfo->lpwszSidUser );
|
|
if (FAILED(hr)) {
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hKey);
|
|
|
|
if ( lResult == ERROR_SUCCESS ) {
|
|
RegCloseKey( hKey );
|
|
return TRUE;
|
|
}
|
|
|
|
if ( lResult != ERROR_FILE_NOT_FOUND ) {
|
|
xe = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: Failed to open registry key with %d."),
|
|
lResult ));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// This is the first time that we are seeing this sid, it can either be a brand new sid or
|
|
// an old sid that has been renamed.
|
|
//
|
|
|
|
lpwszSidUserOld = GetOldSidString( lpGPOInfo->hToken, POLICY_GUID_PATH );
|
|
|
|
if ( !lpwszSidUserOld )
|
|
{
|
|
//
|
|
// Brand new sid
|
|
//
|
|
|
|
if ( !SetOldSidString(lpGPOInfo->hToken, lpGPOInfo->lpwszSidUser, POLICY_GUID_PATH) ) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: WriteSidMapping failed.") ));
|
|
|
|
CEvents ev(TRUE, EVENT_FAILED_WRITE_SID_MAPPING); ev.Report();
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: RegCreateKey failed.") ));
|
|
return TRUE;
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
DeletePolicyState( lpwszSidUserOld );
|
|
}
|
|
|
|
//
|
|
// Need to migrate history data from old sid to new sid
|
|
//
|
|
|
|
if ( !MigrateMembershipData( lpGPOInfo->lpwszSidUser, lpwszSidUserOld ) ) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: MigrateMembershipData failed.") ));
|
|
CEvents ev(TRUE, EVENT_FAILED_MIGRATION); ev.Report();
|
|
goto Exit;
|
|
}
|
|
|
|
if ( !MigrateGPOData( lpGPOInfo, lpGPOInfo->lpwszSidUser, lpwszSidUserOld ) ) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: MigrateGPOData failed.") ));
|
|
CEvents ev(TRUE, EVENT_FAILED_MIGRATION); ev.Report();
|
|
goto Exit;
|
|
}
|
|
|
|
if ( !MigrateStatusData( lpGPOInfo, lpGPOInfo->lpwszSidUser, lpwszSidUserOld ) ) {
|
|
xe = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: MigrateStatusData failed.") ));
|
|
CEvents ev(TRUE, EVENT_FAILED_MIGRATION); ev.Report();
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Migrate Rsop Data, ignore failures
|
|
//
|
|
|
|
if (locator->GetWbemLocator()) {
|
|
DWORD dwRSOPNSLength = lstrlen(RSOP_NS_DIAG_USER_FMT) + lstrlen(lpwszSidUserOld) + 10;
|
|
XPtrLF<WCHAR> xszRsopNameSpace = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*
|
|
(dwRSOPNSLength));
|
|
|
|
// convert the Sids to WMI Names
|
|
XPtrLF<WCHAR> xszWmiNameOld = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(lstrlen(lpwszSidUserOld)+1));
|
|
XPtrLF<WCHAR> xszWmiName = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(lstrlen(lpGPOInfo->lpwszSidUser)+1));
|
|
|
|
|
|
if ((xszRsopNameSpace) && (xszWmiNameOld) && (xszWmiName)) {
|
|
|
|
ConvertSidToWMIName(lpwszSidUserOld, xszWmiNameOld);
|
|
ConvertSidToWMIName(lpGPOInfo->lpwszSidUser, xszWmiName);
|
|
|
|
hr = StringCchPrintf(xszRsopNameSpace, dwRSOPNSLength, RSOP_NS_DIAG_USER_FMT, xszWmiNameOld);
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
CreateAndCopyNameSpace(locator->GetWbemLocator(), xszRsopNameSpace, RSOP_NS_DIAG_USERROOT,
|
|
xszWmiName, NEW_NS_FLAGS_COPY_CLASSES | NEW_NS_FLAGS_COPY_INSTS,
|
|
NULL, NULL);
|
|
|
|
} else {
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: couldn't allocate memory.") ));
|
|
}
|
|
|
|
} else {
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: couldn't get WMI locator.") ));
|
|
}
|
|
|
|
bCommit = TRUE;
|
|
|
|
Exit:
|
|
|
|
if ( bCommit ) {
|
|
|
|
if ( !SetOldSidString(lpGPOInfo->hToken, lpGPOInfo->lpwszSidUser, POLICY_GUID_PATH) )
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: SetOldString failed.") ));
|
|
|
|
lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp);
|
|
|
|
if (lResult == ERROR_SUCCESS)
|
|
RegCloseKey( hKey );
|
|
else
|
|
DebugMsg((DM_WARNING, TEXT("CheckForChangedSid: RegCreateKey failed.") ));
|
|
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), GP_POLICY_SID_KEY, lpwszSidUserOld );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
RegDelnode( HKEY_LOCAL_MACHINE, szKey );
|
|
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), GP_LOGON_SID_KEY, lpwszSidUserOld );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
RegDelnode( HKEY_LOCAL_MACHINE, szKey );
|
|
|
|
|
|
//
|
|
// if we managed to successfully migrate everything
|
|
//
|
|
|
|
lpGPOInfo->bSidChanged = TRUE;
|
|
|
|
|
|
} else {
|
|
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), GP_POLICY_SID_KEY, lpGPOInfo->lpwszSidUser );
|
|
ASSERT(SUCCEEDED(hr));
|
|
RegDelnode( HKEY_LOCAL_MACHINE, szKey );
|
|
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), GP_LOGON_SID_KEY, lpGPOInfo->lpwszSidUser );
|
|
ASSERT(SUCCEEDED(hr));
|
|
RegDelnode( HKEY_LOCAL_MACHINE, szKey );
|
|
|
|
}
|
|
|
|
if ( lpwszSidUserOld )
|
|
LocalFree( lpwszSidUserOld );
|
|
|
|
return bCommit;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ReadGPExtensions()
|
|
//
|
|
// Purpose: Reads the group policy extenions from registry.
|
|
// The actual loading of extension is deferred.
|
|
//
|
|
// Parameters: lpGPOInfo - GP Information
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL ReadGPExtensions (LPGPOINFO lpGPOInfo)
|
|
{
|
|
TCHAR szSubKey[MAX_PATH];
|
|
DWORD dwType;
|
|
HKEY hKey, hKeyOverride;
|
|
DWORD dwIndex = 0;
|
|
DWORD dwSize = 50;
|
|
TCHAR szDisplayName[50];
|
|
TCHAR szKeyName[50];
|
|
TCHAR szDllName[MAX_PATH+1];
|
|
TCHAR szExpDllName[MAX_PATH+1];
|
|
CHAR szFunctionName[100];
|
|
CHAR szRsopFunctionName[100];
|
|
HKEY hKeyExt;
|
|
HINSTANCE hInstDLL;
|
|
LPGPEXT lpExt, lpTemp;
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
|
|
//
|
|
// Check if any extensions are registered
|
|
//
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
GP_EXTENSIONS,
|
|
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
|
|
//
|
|
// Enumerate the keys (each extension has its own key)
|
|
//
|
|
|
|
while (RegEnumKeyEx (hKey, dwIndex, szKeyName, &dwSize,
|
|
NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
|
|
|
|
|
|
//
|
|
// Open the extension's key.
|
|
//
|
|
|
|
if (RegOpenKeyEx (hKey, szKeyName,
|
|
0, KEY_READ, &hKeyExt) == ERROR_SUCCESS) {
|
|
|
|
if ( ValidateGuid( szKeyName ) ) {
|
|
|
|
if ( lstrcmpi(szKeyName, c_szRegistryExtName) != 0 ) {
|
|
|
|
//
|
|
// Every extension, other than RegistryExtension is required to have a value called
|
|
// DllName. This value can be REG_SZ or REG_EXPAND_SZ type.
|
|
//
|
|
|
|
dwSize = sizeof(szDllName);
|
|
if (RegQueryValueEx (hKeyExt, TEXT("DllName"), NULL,
|
|
&dwType, (LPBYTE) szDllName,
|
|
&dwSize) == ERROR_SUCCESS) {
|
|
|
|
BOOL bFuncFound = FALSE;
|
|
BOOL bNewInterface = FALSE;
|
|
|
|
DWORD dwNoMachPolicy = FALSE;
|
|
DWORD dwNoUserPolicy = FALSE;
|
|
DWORD dwNoSlowLink = FALSE;
|
|
DWORD dwNoBackgroundPolicy = FALSE;
|
|
DWORD dwNoGPOChanges = FALSE;
|
|
DWORD dwUserLocalSetting = FALSE;
|
|
DWORD dwRequireRegistry = FALSE;
|
|
DWORD dwEnableAsynch = FALSE;
|
|
DWORD dwMaxChangesInterval = 0;
|
|
DWORD dwLinkTransition = FALSE;
|
|
WCHAR szEventLogSources[MAX_PATH+1];
|
|
DWORD dwSizeEventLogSources = MAX_PATH+1;
|
|
DWORD cchDllName = 0;
|
|
|
|
cchDllName = ExpandEnvironmentStrings (szDllName, szExpDllName, MAX_PATH);
|
|
|
|
//
|
|
// Read new interface name, if failed read old interface name
|
|
//
|
|
|
|
dwSize = sizeof(szFunctionName);
|
|
|
|
if ( cchDllName > 0 )
|
|
{
|
|
if ( RegQueryValueExA (hKeyExt, "ProcessGroupPolicyEx", NULL,
|
|
&dwType, (LPBYTE) szFunctionName,
|
|
&dwSize) == ERROR_SUCCESS ) {
|
|
bFuncFound = TRUE;
|
|
bNewInterface = TRUE;
|
|
|
|
} else if ( RegQueryValueExA (hKeyExt, "ProcessGroupPolicy", NULL,
|
|
&dwType, (LPBYTE) szFunctionName,
|
|
&dwSize) == ERROR_SUCCESS ) {
|
|
bFuncFound = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( bFuncFound) {
|
|
|
|
//
|
|
// Read preferences
|
|
//
|
|
|
|
dwSize = sizeof(szDisplayName);
|
|
if (RegQueryValueEx (hKeyExt, NULL, NULL,
|
|
&dwType, (LPBYTE) szDisplayName,
|
|
&dwSize) != ERROR_SUCCESS) {
|
|
lstrcpyn (szDisplayName, szKeyName, ARRAYSIZE(szDisplayName));
|
|
}
|
|
|
|
dwSize = sizeof(szRsopFunctionName);
|
|
if (RegQueryValueExA (hKeyExt, "GenerateGroupPolicy", NULL,
|
|
&dwType, (LPBYTE) szRsopFunctionName,
|
|
&dwSize) != ERROR_SUCCESS) {
|
|
szRsopFunctionName[0] = 0;
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadGPExtensions: Rsop entry point not found for %s."),
|
|
szExpDllName));
|
|
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyExt, TEXT("NoMachinePolicy"), NULL,
|
|
&dwType, (LPBYTE) &dwNoMachPolicy,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyExt, TEXT("NoUserPolicy"), NULL,
|
|
&dwType, (LPBYTE) &dwNoUserPolicy,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyExt, TEXT("NoSlowLink"), NULL,
|
|
&dwType, (LPBYTE) &dwNoSlowLink,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyExt, TEXT("NoGPOListChanges"), NULL,
|
|
&dwType, (LPBYTE) &dwNoGPOChanges,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyExt, TEXT("NoBackgroundPolicy"), NULL,
|
|
&dwType, (LPBYTE) &dwNoBackgroundPolicy,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyExt, TEXT("PerUserLocalSettings"), NULL,
|
|
&dwType, (LPBYTE) &dwUserLocalSetting,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyExt, TEXT("RequiresSuccessfulRegistry"), NULL,
|
|
&dwType, (LPBYTE) &dwRequireRegistry,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyExt, TEXT("EnableAsynchronousProcessing"), NULL,
|
|
&dwType, (LPBYTE) &dwEnableAsynch,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyExt, TEXT("MaxNoGPOListChangesInterval"), NULL,
|
|
&dwType, (LPBYTE) &dwMaxChangesInterval,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyExt, TEXT("NotifyLinkTransition"), NULL,
|
|
&dwType, (LPBYTE) &dwLinkTransition,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
if (RegQueryValueEx( hKeyExt, TEXT("EventSources"), 0,
|
|
&dwType, (LPBYTE) &(szEventLogSources[0]),
|
|
&dwSizeEventLogSources ) != ERROR_SUCCESS) {
|
|
dwSizeEventLogSources = 0;
|
|
szEventLogSources[0] = TEXT('\0');
|
|
}
|
|
|
|
//
|
|
// Read override policy values, if any
|
|
//
|
|
|
|
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), GP_EXTENSIONS_POLICIES, szKeyName );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
szSubKey,
|
|
0, KEY_READ, &hKeyOverride ) == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyOverride, TEXT("NoSlowLink"), NULL,
|
|
&dwType, (LPBYTE) &dwNoSlowLink,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyOverride, TEXT("NoGPOListChanges"), NULL,
|
|
&dwType, (LPBYTE) &dwNoGPOChanges,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx( hKeyOverride, TEXT("NoBackgroundPolicy"), NULL,
|
|
&dwType, (LPBYTE) &dwNoBackgroundPolicy,
|
|
&dwSize );
|
|
|
|
RegCloseKey( hKeyOverride );
|
|
}
|
|
|
|
}
|
|
|
|
if ( bFuncFound ) {
|
|
DWORD dwExtSize = sizeof(GPEXT)
|
|
+ ((lstrlen(szDisplayName) + 1) * sizeof(TCHAR))
|
|
+ ((lstrlen(szKeyName) + 1) * sizeof(TCHAR))
|
|
+ ((lstrlen(szExpDllName) + 1) * sizeof(TCHAR))
|
|
+ lstrlenA(szFunctionName) + 1
|
|
+ lstrlenA(szRsopFunctionName) + 1;
|
|
lpExt = (LPGPEXT) LocalAlloc (LPTR, dwExtSize);
|
|
if (lpExt) {
|
|
|
|
//
|
|
// Set up all fields
|
|
//
|
|
|
|
lpExt->lpDisplayName = (LPTSTR)((LPBYTE)lpExt + sizeof(GPEXT));
|
|
hr = StringCchCopy( lpExt->lpDisplayName, lstrlen(szDisplayName) + 1, szDisplayName );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
lpExt->lpKeyName = lpExt->lpDisplayName + lstrlen(lpExt->lpDisplayName) + 1;
|
|
hr = StringCchCopy( lpExt->lpKeyName, lstrlen(szKeyName) + 1, szKeyName );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
StringToGuid( szKeyName, &lpExt->guid );
|
|
|
|
lpExt->lpDllName = lpExt->lpKeyName + lstrlen(lpExt->lpKeyName) + 1;
|
|
hr = StringCchCopy (lpExt->lpDllName, lstrlen(szExpDllName) + 1, szExpDllName);
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
lpExt->lpFunctionName = (LPSTR)( (LPBYTE)lpExt->lpDllName + (lstrlen(lpExt->lpDllName) + 1) * sizeof(TCHAR) );
|
|
hr = StringCchCopyA( lpExt->lpFunctionName, lstrlenA(szFunctionName) + 1, szFunctionName );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
if ( szRsopFunctionName[0] == 0 ) {
|
|
lpExt->lpRsopFunctionName = 0;
|
|
} else {
|
|
lpExt->lpRsopFunctionName = (LPSTR)( (LPBYTE)lpExt->lpDllName + (lstrlen(lpExt->lpDllName) + 1) * sizeof(TCHAR)
|
|
+ lstrlenA(szFunctionName) + 1);
|
|
hr = StringCchCopyA( lpExt->lpRsopFunctionName, lstrlenA(szRsopFunctionName) + 1, szRsopFunctionName );
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
|
|
lpExt->hInstance = NULL;
|
|
lpExt->pEntryPoint = NULL;
|
|
lpExt->pEntryPointEx = NULL;
|
|
lpExt->bNewInterface = bNewInterface;
|
|
|
|
lpExt->dwNoMachPolicy = dwNoMachPolicy;
|
|
lpExt->dwNoUserPolicy = dwNoUserPolicy;
|
|
lpExt->dwNoSlowLink = dwNoSlowLink;
|
|
lpExt->dwNoBackgroundPolicy = dwNoBackgroundPolicy;
|
|
lpExt->dwNoGPOChanges = dwNoGPOChanges;
|
|
lpExt->dwUserLocalSetting = dwUserLocalSetting;
|
|
lpExt->dwRequireRegistry = dwRequireRegistry;
|
|
lpExt->dwEnableAsynch = dwEnableAsynch;
|
|
lpExt->dwMaxChangesInterval = dwMaxChangesInterval;
|
|
lpExt->dwLinkTransition = dwLinkTransition;
|
|
|
|
if ( dwSizeEventLogSources )
|
|
{
|
|
lpExt->szEventLogSources = (LPTSTR) LocalAlloc( LPTR, dwSizeEventLogSources+ sizeof(TCHAR) );
|
|
if ( lpExt->szEventLogSources )
|
|
{
|
|
memcpy( lpExt->szEventLogSources, szEventLogSources, dwSizeEventLogSources );
|
|
}
|
|
}
|
|
|
|
lpExt->bRegistryExt = FALSE;
|
|
lpExt->bSkipped = FALSE;
|
|
lpExt->pNext = NULL;
|
|
|
|
//
|
|
// Append to end of extension list
|
|
//
|
|
|
|
if (lpGPOInfo->lpExtensions) {
|
|
|
|
lpTemp = lpGPOInfo->lpExtensions;
|
|
|
|
while (TRUE) {
|
|
if (lpTemp->pNext) {
|
|
lpTemp = lpTemp->pNext;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
lpTemp->pNext = lpExt;
|
|
|
|
} else {
|
|
lpGPOInfo->lpExtensions = lpExt;
|
|
}
|
|
|
|
} else { // if lpExt
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPExtensions: Failed to allocate memory with %d"),
|
|
GetLastError()));
|
|
}
|
|
} else { // if bFuncFound
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPExtensions: Failed to query for the function name.")));
|
|
CEvents ev(TRUE, EVENT_EXT_MISSING_FUNC);
|
|
ev.AddArg(szExpDllName); ev.Report();
|
|
}
|
|
} else { // if RegQueryValueEx DllName
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPExtensions: Failed to query DllName value.")));
|
|
CEvents ev(TRUE, EVENT_EXT_MISSING_DLLNAME);
|
|
ev.AddArg(szKeyName); ev.Report();
|
|
}
|
|
|
|
} // if lstrcmpi(szKeyName, c_szRegistryExtName)
|
|
|
|
} // if validateguid
|
|
|
|
RegCloseKey (hKeyExt);
|
|
} // if RegOpenKey hKeyExt
|
|
|
|
dwSize = ARRAYSIZE(szKeyName);
|
|
dwIndex++;
|
|
} // while RegEnumKeyEx
|
|
|
|
RegCloseKey (hKey);
|
|
} // if RegOpenKey gpext
|
|
|
|
//
|
|
// Add the registry psuedo extension at the beginning
|
|
//
|
|
DWORD dwExtSize = 0;
|
|
if ( LoadString (g_hDllInstance, IDS_REGISTRYNAME, szDisplayName, ARRAYSIZE(szDisplayName)) ) {
|
|
dwExtSize = sizeof(GPEXT)
|
|
+ ((lstrlen(szDisplayName) + 1) * sizeof(TCHAR))
|
|
+ ((lstrlen(c_szRegistryExtName) + 1) * sizeof(TCHAR)) ;
|
|
lpExt = (LPGPEXT) LocalAlloc (LPTR, dwExtSize);
|
|
} else {
|
|
|
|
lpExt = 0;
|
|
}
|
|
|
|
if (lpExt) {
|
|
|
|
DWORD dwNoSlowLink = FALSE;
|
|
DWORD dwNoGPOChanges = TRUE;
|
|
DWORD dwNoBackgroundPolicy = FALSE;
|
|
|
|
lpExt->lpDisplayName = (LPTSTR)((LPBYTE)lpExt + sizeof(GPEXT));
|
|
hr = StringCchCopy( lpExt->lpDisplayName, lstrlen(szDisplayName) + 1, szDisplayName );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
lpExt->lpKeyName = lpExt->lpDisplayName + lstrlen(lpExt->lpDisplayName) + 1;
|
|
hr = StringCchCopy( lpExt->lpKeyName, lstrlen(c_szRegistryExtName) + 1, c_szRegistryExtName );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
StringToGuid( lpExt->lpKeyName, &lpExt->guid );
|
|
|
|
lpExt->lpDllName = L"userenv.dll";
|
|
lpExt->lpFunctionName = NULL;
|
|
lpExt->hInstance = NULL;
|
|
lpExt->pEntryPoint = NULL;
|
|
|
|
//
|
|
// Read override policy values, if any
|
|
//
|
|
|
|
hr = StringCchPrintf (szSubKey, ARRAYSIZE(szSubKey), GP_EXTENSIONS_POLICIES, lpExt->lpKeyName );
|
|
if (FAILED(hr)) {
|
|
LocalFree(lpExt);
|
|
xe = HRESULT_CODE(hr);
|
|
return FALSE;
|
|
}
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
szSubKey,
|
|
0, KEY_READ, &hKeyOverride ) == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof( dwNoGPOChanges );
|
|
RegQueryValueEx( hKeyOverride, TEXT("NoGPOListChanges"), NULL,
|
|
&dwType, (LPBYTE) &dwNoGPOChanges,
|
|
&dwSize );
|
|
|
|
dwSize = sizeof( dwNoBackgroundPolicy );
|
|
RegQueryValueEx( hKeyOverride, TEXT("NoBackgroundPolicy"), NULL,
|
|
&dwType, (LPBYTE) &dwNoBackgroundPolicy,
|
|
&dwSize );
|
|
RegCloseKey( hKeyOverride );
|
|
|
|
}
|
|
|
|
lpExt->dwNoMachPolicy = FALSE;
|
|
lpExt->dwNoUserPolicy = FALSE;
|
|
lpExt->dwNoSlowLink = dwNoSlowLink;
|
|
lpExt->dwNoBackgroundPolicy = dwNoBackgroundPolicy;
|
|
lpExt->dwNoGPOChanges = dwNoGPOChanges;
|
|
lpExt->dwUserLocalSetting = FALSE;
|
|
lpExt->dwRequireRegistry = FALSE;
|
|
lpExt->dwEnableAsynch = FALSE;
|
|
lpExt->dwLinkTransition = FALSE;
|
|
|
|
lpExt->bRegistryExt = TRUE;
|
|
lpExt->bSkipped = FALSE;
|
|
lpExt->bNewInterface = TRUE;
|
|
|
|
lpExt->pNext = lpGPOInfo->lpExtensions;
|
|
lpGPOInfo->lpExtensions = lpExt;
|
|
|
|
} else {
|
|
DebugMsg((DM_WARNING, TEXT("ReadGPExtensions: Failed to allocate memory with %d"),
|
|
GetLastError()));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ReadMembershipList()
|
|
//
|
|
// Purpose: Reads cached memberhip list and checks if the
|
|
// security groups has changed.
|
|
//
|
|
// Parameters: lpGPOInfo - LPGPOINFO struct
|
|
// lpwszSidUser - Sid of user, if non-null then it means
|
|
// per user local setting
|
|
// pGroups - List of token groups
|
|
//
|
|
// Return: TRUE if changed
|
|
// FALSE otherwise
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL ReadMembershipList( LPGPOINFO lpGPOInfo, LPTSTR lpwszSidUser, PTOKEN_GROUPS pGroupsCur )
|
|
{
|
|
DWORD i= 0;
|
|
LONG lResult;
|
|
TCHAR szGroup[30];
|
|
TCHAR szKey[250];
|
|
HKEY hKey = NULL;
|
|
BOOL bDiff = TRUE;
|
|
DWORD dwCountOld = 0;
|
|
DWORD dwSize, dwType, dwMaxSize;
|
|
LPTSTR lpSid = NULL;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwCountCur = 0;
|
|
XLastError xe;
|
|
|
|
//
|
|
// Get current count of groups ignoring groups that have
|
|
// the SE_GROUP_LOGON_ID attribute set as this sid will be different
|
|
// for each logon session.
|
|
//
|
|
|
|
for ( i=0; i < pGroupsCur->GroupCount; i++) {
|
|
if ( (SE_GROUP_LOGON_ID & pGroupsCur->Groups[i].Attributes) == 0 )
|
|
dwCountCur++;
|
|
}
|
|
|
|
//
|
|
// Read from cached group membership list
|
|
//
|
|
|
|
if ( lpwszSidUser == 0 )
|
|
hr = StringCchCopy( szKey, ARRAYSIZE(szKey), TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\GroupMembership") );
|
|
else
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\%ws\\GroupMembership"),
|
|
lpwszSidUser );
|
|
if (FAILED(hr)) {
|
|
xe = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
lResult = RegOpenKeyEx ( lpwszSidUser ? HKEY_LOCAL_MACHINE : lpGPOInfo->hKeyRoot,
|
|
szKey,
|
|
0, KEY_READ, &hKey);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
return TRUE;
|
|
|
|
dwSize = sizeof(dwCountOld);
|
|
lResult = RegQueryValueEx (hKey, TEXT("Count"), NULL, &dwType,
|
|
(LPBYTE) &dwCountOld, &dwSize);
|
|
|
|
if ( lResult != ERROR_SUCCESS ) {
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadMembershipList: Failed to read old group count") ));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Now compare the old and new number of security groups
|
|
//
|
|
|
|
if ( dwCountOld != dwCountCur ) {
|
|
DebugMsg((DM_VERBOSE, TEXT("ReadMembershipList: Old count %d is different from current count %d"),
|
|
dwCountOld, dwCountCur ));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Total group count is the same, now check that each individual group is the same.
|
|
// First read the size of the largest value in this key.
|
|
//
|
|
|
|
lResult = RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&dwMaxSize, NULL, NULL);
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("ReadMembershipList: Failed to query max size with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// RegQueryInfoKey does not account for trailing 0 in strings
|
|
//
|
|
|
|
dwMaxSize += sizeof( WCHAR );
|
|
|
|
|
|
//
|
|
// Allocate buffer based upon the largest value
|
|
//
|
|
|
|
lpSid = (LPTSTR) LocalAlloc (LPTR, dwMaxSize);
|
|
|
|
if (!lpSid) {
|
|
DebugMsg((DM_WARNING, TEXT("ReadMembershipList: Failed to allocate memory with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
for ( i=0; i<dwCountOld; i++ ) {
|
|
|
|
hr = StringCchPrintf( szGroup, ARRAYSIZE(szGroup), TEXT("Group%d"), i );
|
|
if (FAILED(hr)) {
|
|
xe = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = dwMaxSize;
|
|
lResult = RegQueryValueEx (hKey, szGroup, NULL, &dwType,
|
|
(LPBYTE) lpSid, &dwSize);
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("ReadMembershipList: Failed to read value %ws"), szGroup ));
|
|
goto Exit;
|
|
}
|
|
|
|
if ( !GroupInList( lpSid, pGroupsCur ) ) {
|
|
DebugMsg((DM_WARNING, TEXT("ReadMembershipList: Group %ws not in current list of token groups"), lpSid ));
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
|
|
bDiff = FALSE;
|
|
|
|
Exit:
|
|
|
|
if ( lpSid )
|
|
LocalFree( lpSid );
|
|
|
|
if ( hKey )
|
|
RegCloseKey (hKey);
|
|
|
|
return bDiff;
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// SavesMembershipList()
|
|
//
|
|
// Purpose: Caches memberhip list
|
|
//
|
|
// Parameters: lpGPOInfo - LPGPOINFO struct
|
|
// lpwszSidUser - Sid of user, if non-null then it means
|
|
// per user local setting
|
|
// pGroups - List of token groups to cache
|
|
//
|
|
// Notes: The count is saved last because it serves
|
|
// as a commit point for the entire save operation.
|
|
//
|
|
//*************************************************************
|
|
|
|
void SaveMembershipList( LPGPOINFO lpGPOInfo, LPTSTR lpwszSidUser, PTOKEN_GROUPS pGroups )
|
|
{
|
|
TCHAR szKey[250];
|
|
TCHAR szGroup[30];
|
|
DWORD i;
|
|
LONG lResult;
|
|
DWORD dwCount = 0, dwSize, dwDisp;
|
|
NTSTATUS ntStatus;
|
|
UNICODE_STRING unicodeStr;
|
|
HKEY hKey = NULL;
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
|
|
//
|
|
// Start with clean key
|
|
//
|
|
|
|
if ( lpwszSidUser == 0 )
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\GroupMembership") );
|
|
else
|
|
hr = StringCchPrintf( szKey, ARRAYSIZE(szKey), TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\%ws\\GroupMembership"),
|
|
lpwszSidUser );
|
|
if (FAILED(hr)) {
|
|
xe = HRESULT_CODE(hr);
|
|
return;
|
|
}
|
|
|
|
if (RegDelnode ( lpwszSidUser ? HKEY_LOCAL_MACHINE : lpGPOInfo->hKeyRoot, szKey) != ERROR_SUCCESS) {
|
|
DebugMsg((DM_VERBOSE, TEXT("SaveMembershipList: RegDelnode failed.")));
|
|
return;
|
|
}
|
|
|
|
lResult = RegCreateKeyEx ( lpwszSidUser ? HKEY_LOCAL_MACHINE : lpGPOInfo->hKeyRoot,
|
|
szKey, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp);
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("SaveMemberList: Failed to create key with %d."), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
for ( i=0; i < pGroups->GroupCount; i++) {
|
|
|
|
if (SE_GROUP_LOGON_ID & pGroups->Groups[i].Attributes )
|
|
continue;
|
|
|
|
dwCount++;
|
|
|
|
//
|
|
// Convert user SID to a string.
|
|
//
|
|
|
|
ntStatus = RtlConvertSidToUnicodeString( &unicodeStr,
|
|
pGroups->Groups[i].Sid,
|
|
(BOOLEAN)TRUE ); // Allocate
|
|
if ( !NT_SUCCESS(ntStatus) ) {
|
|
DebugMsg((DM_WARNING, TEXT("SaveMembershipList: RtlConvertSidToUnicodeString failed, status = 0x%x"),
|
|
ntStatus));
|
|
goto Exit;
|
|
}
|
|
|
|
hr = StringCchPrintf( szGroup, ARRAYSIZE(szGroup), TEXT("Group%d"), dwCount-1 );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
dwSize = (lstrlen (unicodeStr.Buffer) + 1) * sizeof(TCHAR);
|
|
lResult = RegSetValueEx (hKey, szGroup, 0, REG_SZ,
|
|
(LPBYTE) unicodeStr.Buffer, dwSize);
|
|
|
|
RtlFreeUnicodeString( &unicodeStr );
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("SaveMemberList: Failed to set value %ws with %d."),
|
|
szGroup, lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
} // for
|
|
|
|
//
|
|
// Commit by writing count
|
|
//
|
|
|
|
dwSize = sizeof(dwCount);
|
|
lResult = RegSetValueEx (hKey, TEXT("Count"), 0, REG_DWORD,
|
|
(LPBYTE) &dwCount, dwSize);
|
|
|
|
Exit:
|
|
if (hKey)
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ExtensionHasPerUserLocalSetting()
|
|
//
|
|
// Purpose: Checks registry if extension has per user local setting
|
|
//
|
|
// Parameters: pwszExtension - Extension guid
|
|
// hKeyRoot - Registry root
|
|
//
|
|
// Returns: True if extension has per user local setting
|
|
// False otherwise
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL ExtensionHasPerUserLocalSetting( LPTSTR pszExtension, HKEY hKeyRoot )
|
|
{
|
|
TCHAR szKey[200];
|
|
DWORD dwType, dwSetting = 0, dwSize = sizeof(DWORD);
|
|
LONG lResult;
|
|
HKEY hKey;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = StringCchPrintf ( szKey, ARRAYSIZE(szKey), GP_EXTENSIONS_KEY, pszExtension );
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
lResult = RegOpenKeyEx ( hKeyRoot, szKey, 0, KEY_READ, &hKey);
|
|
if ( lResult != ERROR_SUCCESS )
|
|
return FALSE;
|
|
|
|
lResult = RegQueryValueEx( hKey, TEXT("PerUserLocalSettings"), NULL,
|
|
&dwType, (LPBYTE) &dwSetting,
|
|
&dwSize );
|
|
RegCloseKey( hKey );
|
|
|
|
if (lResult == ERROR_SUCCESS)
|
|
return dwSetting;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetAppliedGPOList()
|
|
//
|
|
// Purpose: Queries for the list of applied Group Policy
|
|
// Objects for the specified user or machine
|
|
// and specified client side extension.
|
|
//
|
|
// Parameters: dwFlags - User or machine policy, if it is GPO_LIST_FLAG_MACHINE
|
|
// then machine policy
|
|
// pMachineName - Name of remote computer in the form \\computername. If null
|
|
// then local computer is used.
|
|
// pSidUser - Security id of user (relevant for user policy). If pMachineName is
|
|
// null and pSidUser is null then it means current logged on user.
|
|
// If pMachine is null and pSidUser is non-null then it means user
|
|
// represented by pSidUser on local machine. If pMachineName is non-null
|
|
// then and if dwFlags specifies user policy, then pSidUser must be
|
|
// non-null.
|
|
// pGuid - Guid of the specified extension
|
|
// ppGPOList - Address of a pointer which receives the link list of GPOs
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
//*************************************************************
|
|
|
|
DWORD GetAppliedGPOList( DWORD dwFlags,
|
|
LPCTSTR pMachineName,
|
|
PSID pSidUser,
|
|
GUID *pGuidExtension,
|
|
PGROUP_POLICY_OBJECT *ppGPOList)
|
|
{
|
|
DWORD dwRet = E_FAIL;
|
|
TCHAR szExtension[64];
|
|
BOOL bOk;
|
|
BOOL bMachine = dwFlags & GPO_LIST_FLAG_MACHINE;
|
|
NTSTATUS ntStatus;
|
|
UNICODE_STRING unicodeStr;
|
|
|
|
*ppGPOList = 0;
|
|
|
|
if ( pGuidExtension == 0 )
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
GuidToString( pGuidExtension, szExtension );
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("GetAppliedGPOList: Entering. Extension = %s"),
|
|
szExtension));
|
|
|
|
if ( pMachineName == NULL ) {
|
|
|
|
//
|
|
// Local case
|
|
//
|
|
|
|
if ( bMachine ) {
|
|
|
|
bOk = ReadGPOList( szExtension,
|
|
HKEY_LOCAL_MACHINE,
|
|
HKEY_LOCAL_MACHINE,
|
|
0,
|
|
FALSE, ppGPOList );
|
|
|
|
return bOk ? ERROR_SUCCESS : E_FAIL;
|
|
|
|
} else {
|
|
|
|
BOOL bUsePerUserLocalSetting = ExtensionHasPerUserLocalSetting( szExtension, HKEY_LOCAL_MACHINE );
|
|
LPTSTR lpwszSidUser = NULL;
|
|
|
|
if ( pSidUser == NULL ) {
|
|
|
|
//
|
|
// Current logged on user
|
|
//
|
|
|
|
if ( bUsePerUserLocalSetting ) {
|
|
|
|
HANDLE hToken = NULL;
|
|
if (!OpenThreadToken (GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) {
|
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
|
|
DebugMsg((DM_WARNING, TEXT("GetAppliedGPOList: Failed to get user token with %d"),
|
|
GetLastError()));
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
lpwszSidUser = GetSidString( hToken );
|
|
CloseHandle( hToken );
|
|
|
|
if ( lpwszSidUser == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("GetAppliedGPOList: GetSidString failed.")));
|
|
return E_FAIL;
|
|
}
|
|
|
|
}
|
|
|
|
bOk = ReadGPOList( szExtension,
|
|
HKEY_CURRENT_USER,
|
|
HKEY_LOCAL_MACHINE,
|
|
lpwszSidUser,
|
|
FALSE, ppGPOList );
|
|
if ( lpwszSidUser )
|
|
DeleteSidString( lpwszSidUser );
|
|
|
|
return bOk ? ERROR_SUCCESS : E_FAIL;
|
|
|
|
} else {
|
|
|
|
//
|
|
// User represented by pSidUser
|
|
//
|
|
|
|
HKEY hSubKey;
|
|
|
|
ntStatus = RtlConvertSidToUnicodeString( &unicodeStr,
|
|
pSidUser,
|
|
(BOOLEAN)TRUE ); // Allocate
|
|
if ( !NT_SUCCESS(ntStatus) )
|
|
return E_FAIL;
|
|
|
|
dwRet = RegOpenKeyEx ( HKEY_USERS, unicodeStr.Buffer, 0, KEY_READ, &hSubKey);
|
|
|
|
if (dwRet != ERROR_SUCCESS) {
|
|
RtlFreeUnicodeString(&unicodeStr);
|
|
|
|
if (dwRet == ERROR_FILE_NOT_FOUND)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return dwRet;
|
|
}
|
|
|
|
bOk = ReadGPOList( szExtension,
|
|
hSubKey,
|
|
HKEY_LOCAL_MACHINE,
|
|
bUsePerUserLocalSetting ? unicodeStr.Buffer : NULL,
|
|
FALSE, ppGPOList );
|
|
|
|
RtlFreeUnicodeString(&unicodeStr);
|
|
RegCloseKey(hSubKey);
|
|
|
|
return bOk ? ERROR_SUCCESS : E_FAIL;
|
|
|
|
} // else if psiduser == null
|
|
|
|
} // else if bmachine
|
|
|
|
} else { // if pmachine == null
|
|
|
|
//
|
|
// Remote case
|
|
//
|
|
|
|
if ( bMachine ) {
|
|
|
|
HKEY hKeyRemote;
|
|
|
|
dwRet = RegConnectRegistry( pMachineName,
|
|
HKEY_LOCAL_MACHINE,
|
|
&hKeyRemote );
|
|
if ( dwRet != ERROR_SUCCESS )
|
|
return dwRet;
|
|
|
|
bOk = ReadGPOList( szExtension,
|
|
hKeyRemote,
|
|
hKeyRemote,
|
|
0,
|
|
FALSE, ppGPOList );
|
|
RegCloseKey( hKeyRemote );
|
|
|
|
dwRet = bOk ? ERROR_SUCCESS : E_FAIL;
|
|
return dwRet;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Remote user
|
|
//
|
|
|
|
HKEY hKeyRemoteMach;
|
|
BOOL bUsePerUserLocalSetting;
|
|
|
|
if ( pSidUser == NULL )
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
ntStatus = RtlConvertSidToUnicodeString( &unicodeStr,
|
|
pSidUser,
|
|
(BOOLEAN)TRUE ); // Allocate
|
|
if ( !NT_SUCCESS(ntStatus) )
|
|
return E_FAIL;
|
|
|
|
dwRet = RegConnectRegistry( pMachineName,
|
|
HKEY_LOCAL_MACHINE,
|
|
&hKeyRemoteMach );
|
|
if ( dwRet != ERROR_SUCCESS ) {
|
|
RtlFreeUnicodeString(&unicodeStr);
|
|
return dwRet;
|
|
}
|
|
|
|
bUsePerUserLocalSetting = ExtensionHasPerUserLocalSetting( szExtension, hKeyRemoteMach );
|
|
|
|
if ( bUsePerUserLocalSetting ) {
|
|
|
|
//
|
|
// Account for per user local settings
|
|
//
|
|
|
|
bOk = ReadGPOList( szExtension,
|
|
hKeyRemoteMach,
|
|
hKeyRemoteMach,
|
|
unicodeStr.Buffer,
|
|
FALSE, ppGPOList );
|
|
|
|
RtlFreeUnicodeString(&unicodeStr);
|
|
RegCloseKey(hKeyRemoteMach);
|
|
|
|
return bOk ? ERROR_SUCCESS : E_FAIL;
|
|
|
|
} else {
|
|
|
|
HKEY hKeyRemote, hSubKeyRemote;
|
|
|
|
RegCloseKey( hKeyRemoteMach );
|
|
|
|
dwRet = RegConnectRegistry( pMachineName,
|
|
HKEY_USERS,
|
|
&hKeyRemote );
|
|
if ( dwRet != ERROR_SUCCESS ) {
|
|
RtlFreeUnicodeString(&unicodeStr);
|
|
return dwRet;
|
|
}
|
|
|
|
dwRet = RegOpenKeyEx (hKeyRemote, unicodeStr.Buffer, 0, KEY_READ, &hSubKeyRemote);
|
|
|
|
RtlFreeUnicodeString(&unicodeStr);
|
|
|
|
if (dwRet != ERROR_SUCCESS) {
|
|
RegCloseKey(hKeyRemote);
|
|
|
|
if (dwRet == ERROR_FILE_NOT_FOUND)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return dwRet;
|
|
}
|
|
|
|
bOk = ReadGPOList( szExtension,
|
|
hSubKeyRemote,
|
|
hSubKeyRemote,
|
|
0,
|
|
FALSE, ppGPOList );
|
|
|
|
RegCloseKey(hSubKeyRemote);
|
|
RegCloseKey(hKeyRemote);
|
|
|
|
return bOk ? ERROR_SUCCESS : E_FAIL;
|
|
|
|
} // else if bUsePerUserLocalSettings
|
|
|
|
} // else if bMachine
|
|
|
|
} // else if pMachName == null
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
#define FORCE_FOREGROUND_LOGGING L"ForceForegroundLogging"
|
|
|
|
#define SITENAME L"Site-Name"
|
|
// dn defined in gpt.h
|
|
#define LOOPBACKDN L"Loopback-Distinguished-Name"
|
|
#define SLOWLINK L"SlowLink"
|
|
#define GPO L"GPO-List"
|
|
#define LOOPBACK L"Loopback-GPO-List"
|
|
#define EXTENSION L"Extension-List"
|
|
#define GPLINKLIST L"GPLink-List"
|
|
#define LOOPBACKGPL L"Loopback-GPLink-List"
|
|
|
|
#define GPOID L"GPOID"
|
|
#define VERSION L"Version"
|
|
#define SOM L"SOM"
|
|
#define WQL L"WQLFilterPass"
|
|
#define ACCESS L"AccessDenied"
|
|
#define DISPLAYNAME L"DisplayName"
|
|
#define DISABLED L"GPO-Disabled"
|
|
#define WQLID L"WQL-Id"
|
|
#define OPTIONS L"Options"
|
|
#define STARTTIME1 L"StartTimeLo"
|
|
#define ENDTIME1 L"EndTimeLo"
|
|
#define STARTTIME2 L"StartTimeHi"
|
|
#define ENDTIME2 L"EndTimeHi"
|
|
#define STATUS L"Status"
|
|
#define LOGSTATUS L"LoggingStatus"
|
|
#define ENABLED L"Enabled"
|
|
#define NOOVERRIDE L"NoOverride"
|
|
#define DSPATH L"DsPath"
|
|
|
|
DWORD RegSaveGPL( HKEY hKeyState,
|
|
LPSCOPEOFMGMT pSOM,
|
|
LPWSTR szGPLKey )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
//
|
|
// delete the existing list of GPLs
|
|
//
|
|
dwError = RegDelnode( hKeyState, szGPLKey );
|
|
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
HKEY hKeyGPL;
|
|
|
|
//
|
|
// recreate the GPL key
|
|
//
|
|
dwError = RegCreateKeyEx( hKeyState,
|
|
szGPLKey,
|
|
0,
|
|
0,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKeyGPL,
|
|
0 );
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
DWORD dwGPLs = 0;
|
|
|
|
while ( pSOM )
|
|
{
|
|
LPGPLINK pGPLink = pSOM->pGpLinkList;
|
|
|
|
while ( pGPLink )
|
|
{
|
|
HKEY hKeyNumber = 0;
|
|
WCHAR szNumber[32];
|
|
|
|
//
|
|
// create the number key of GPLs
|
|
//
|
|
dwError = RegCreateKeyEx( hKeyGPL,
|
|
_itow( dwGPLs, szNumber, 16 ),
|
|
0,
|
|
0,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKeyNumber,
|
|
0 );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Enabled
|
|
//
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
ENABLED,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) &( pGPLink->bEnabled ),
|
|
sizeof( pGPLink->bEnabled ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// NoOverride
|
|
//
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
NOOVERRIDE,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) &( pGPLink->bNoOverride ),
|
|
sizeof( pGPLink->bNoOverride ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// DS PATH
|
|
//
|
|
LPWSTR szTemp = pGPLink->pwszGPO ? pGPLink->pwszGPO : L"";
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
DSPATH,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE*) szTemp,
|
|
( wcslen( szTemp ) + 1 ) * sizeof( WCHAR ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// SOM
|
|
//
|
|
szTemp = pSOM->pwszSOMId ? pSOM->pwszSOMId : L"";
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
SOM,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE*) szTemp,
|
|
( wcslen( szTemp ) + 1 ) * sizeof( WCHAR ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
RegCloseKey( hKeyNumber );
|
|
pGPLink = pGPLink->pNext;
|
|
dwGPLs++;
|
|
}
|
|
|
|
pSOM = pSOM->pNext;
|
|
}
|
|
RegCloseKey( hKeyGPL );
|
|
}
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
DWORD RegCompareGPLs( HKEY hKeyState,
|
|
LPSCOPEOFMGMT pSOM,
|
|
LPWSTR szGPLKey,
|
|
BOOL* pbChanged )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
HKEY hKeyGPL;
|
|
|
|
*pbChanged = FALSE;
|
|
|
|
//
|
|
// open the GPL key
|
|
//
|
|
dwError = RegOpenKeyEx( hKeyState,
|
|
szGPLKey,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKeyGPL );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
*pbChanged = TRUE;
|
|
return dwError;
|
|
}
|
|
|
|
WCHAR szNumber[32];
|
|
HKEY hKeyNumber = 0;
|
|
|
|
//
|
|
// compare each GPL and its corr. key for changes
|
|
//
|
|
DWORD dwGPLs = 0;
|
|
while ( pSOM )
|
|
{
|
|
LPGPLINK pGPLink = pSOM->pGpLinkList;
|
|
WCHAR* szBuffer;
|
|
|
|
szBuffer = NULL;
|
|
|
|
while ( pGPLink && dwError == ERROR_SUCCESS && !*pbChanged )
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
DWORD dwBuffer;
|
|
DWORD dwBufferSize;
|
|
DWORD cbMaxValueLength;
|
|
|
|
if ( szBuffer )
|
|
{
|
|
LocalFree( szBuffer );
|
|
szBuffer = NULL;
|
|
}
|
|
|
|
//
|
|
// open the key corr. to the GPL
|
|
//
|
|
dwError = RegOpenKeyEx( hKeyGPL,
|
|
_itow( dwGPLs, szNumber, 16 ),
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKeyNumber );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Determine the maximum length of data in this key
|
|
// so we can use this to query for values
|
|
//
|
|
dwError = RegQueryInfoKey(
|
|
hKeyNumber,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
&cbMaxValueLength,
|
|
0,
|
|
0 );
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// The string data type of the registry does not include the null terminator
|
|
//
|
|
dwBufferSize = ( cbMaxValueLength + sizeof( WCHAR ) );
|
|
|
|
szBuffer = (WCHAR*) LocalAlloc(LPTR, dwBufferSize);
|
|
|
|
if ( ! szBuffer )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Enabled
|
|
//
|
|
dwType = 0;
|
|
dwBuffer = 0;
|
|
dwSize = sizeof( dwBuffer );
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
ENABLED,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) &dwBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || dwBuffer != pGPLink->bEnabled )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// NoOverride
|
|
//
|
|
dwType = 0;
|
|
dwBuffer = 0;
|
|
dwSize = sizeof( dwBuffer );
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
NOOVERRIDE,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) &dwBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || dwBuffer != pGPLink->bNoOverride )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// DS PATH
|
|
//
|
|
LPWSTR szTemp = pGPLink->pwszGPO ? pGPLink->pwszGPO : L"";
|
|
dwType = 0;
|
|
szBuffer[0] = 0;
|
|
dwSize = dwBufferSize;
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
DSPATH,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) szBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || _wcsicmp( szBuffer, szTemp ) )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// SOM
|
|
//
|
|
szTemp = pSOM->pwszSOMId ? pSOM->pwszSOMId : L"";
|
|
dwType = 0;
|
|
szBuffer[0] = 0;
|
|
dwSize = dwBufferSize;
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
SOM,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) szBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || _wcsicmp( szBuffer, szTemp ) )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
RegCloseKey( hKeyNumber );
|
|
hKeyNumber = 0;
|
|
pGPLink = pGPLink->pNext;
|
|
dwGPLs++;
|
|
}
|
|
|
|
pSOM = pSOM->pNext;
|
|
|
|
if ( szBuffer )
|
|
{
|
|
LocalFree( szBuffer );
|
|
}
|
|
}
|
|
|
|
if ( hKeyNumber )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
}
|
|
RegCloseKey( hKeyGPL );
|
|
|
|
return dwError;
|
|
}
|
|
|
|
DWORD RegSaveGPOs( HKEY hKeyState,
|
|
LPGPCONTAINER pGPOs,
|
|
BOOL bMachine,
|
|
LPWSTR szGPOKey )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
//
|
|
// delete the existing list of GPOs
|
|
//
|
|
dwError = RegDelnode( hKeyState, szGPOKey );
|
|
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
HKEY hKeyGPO;
|
|
|
|
//
|
|
// recreate the GPO key
|
|
//
|
|
dwError = RegCreateKeyEx( hKeyState,
|
|
szGPOKey,
|
|
0,
|
|
0,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKeyGPO,
|
|
0 );
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
DWORD dwGPOs = 0;
|
|
|
|
while ( pGPOs )
|
|
{
|
|
HKEY hKeyNumber = 0;
|
|
WCHAR szNumber[32];
|
|
|
|
//
|
|
// create the number key of GPOs
|
|
//
|
|
dwError = RegCreateKeyEx( hKeyGPO,
|
|
_itow( dwGPOs, szNumber, 16 ),
|
|
0,
|
|
0,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKeyNumber,
|
|
0 );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// version
|
|
//
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
VERSION,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) ( bMachine ? &pGPOs->dwMachVersion : &pGPOs->dwUserVersion ),
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// WQL
|
|
//
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
WQL,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) &pGPOs->bFilterAllowed,
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Access
|
|
//
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
ACCESS,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) &pGPOs->bAccessDenied,
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// disabled
|
|
//
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
DISABLED,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) ( bMachine ? &pGPOs->bMachDisabled : &pGPOs->bUserDisabled ),
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Options
|
|
//
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
OPTIONS,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) &( pGPOs->dwOptions ),
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// GPO GUID
|
|
//
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
GPOID,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE*) pGPOs->pwszGPOName,
|
|
( wcslen( pGPOs->pwszGPOName ) + 1 ) * sizeof( WCHAR ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// SOM
|
|
//
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
SOM,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE*) pGPOs->szSOM,
|
|
( wcslen( pGPOs->szSOM ) + 1 ) * sizeof( WCHAR ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
LPWSTR szTemp;
|
|
|
|
//
|
|
// display name
|
|
//
|
|
szTemp = pGPOs->pwszDisplayName ? pGPOs->pwszDisplayName : L"";
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
DISPLAYNAME,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE*) szTemp,
|
|
( wcslen( szTemp ) + 1 ) * sizeof( WCHAR ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// WQL filter
|
|
//
|
|
szTemp = pGPOs->pwszFilterId ? pGPOs->pwszFilterId : L"";
|
|
dwError = RegSetValueEx(hKeyNumber,
|
|
WQLID,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE*) szTemp,
|
|
( wcslen( szTemp ) + 1 ) * sizeof( WCHAR ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
break;
|
|
}
|
|
|
|
RegCloseKey( hKeyNumber );
|
|
pGPOs = pGPOs->pNext;
|
|
dwGPOs++;
|
|
}
|
|
|
|
RegCloseKey( hKeyGPO );
|
|
}
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
DWORD RegCompareGPOs( HKEY hKeyState,
|
|
LPGPCONTAINER pGPOs,
|
|
BOOL bMachine,
|
|
LPWSTR szGPOKey,
|
|
BOOL* pbChanged,
|
|
BOOL* pbListChanged )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
HKEY hKeyGPO;
|
|
|
|
*pbChanged = FALSE;
|
|
*pbListChanged = FALSE;
|
|
|
|
//
|
|
// open the GPO key
|
|
//
|
|
dwError = RegOpenKeyEx( hKeyState,
|
|
szGPOKey,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKeyGPO );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
*pbChanged = TRUE;
|
|
return dwError;
|
|
}
|
|
|
|
DWORD dwSubKeys = 0;
|
|
|
|
//
|
|
// get the number of sub keys
|
|
//
|
|
dwError = RegQueryInfoKey( hKeyGPO,
|
|
0,
|
|
0,
|
|
0,
|
|
&dwSubKeys,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0 );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
*pbChanged = TRUE;
|
|
*pbListChanged = TRUE;
|
|
RegCloseKey( hKeyGPO );
|
|
return dwError;
|
|
}
|
|
|
|
LPGPCONTAINER pTemp = pGPOs;
|
|
DWORD dwGPOs = 0;
|
|
|
|
//
|
|
// count the number of GPOs
|
|
//
|
|
while ( pTemp )
|
|
{
|
|
dwGPOs++;
|
|
pTemp = pTemp->pNext;
|
|
}
|
|
|
|
//
|
|
// the number of GPOs and the keys should match
|
|
//
|
|
if ( dwGPOs != dwSubKeys )
|
|
{
|
|
*pbChanged = TRUE;
|
|
*pbListChanged = TRUE;
|
|
RegCloseKey( hKeyGPO );
|
|
return dwError;
|
|
}
|
|
|
|
WCHAR szNumber[32];
|
|
HKEY hKeyNumber = 0;
|
|
WCHAR* szBuffer = NULL;
|
|
|
|
//
|
|
// compare each GPO and its corr. key for changes
|
|
//
|
|
dwGPOs = 0;
|
|
|
|
while ( pGPOs && dwError == ERROR_SUCCESS && !*pbChanged )
|
|
{
|
|
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
DWORD dwBuffer;
|
|
|
|
DWORD dwBufferSize;
|
|
DWORD cbMaxValueLength;
|
|
|
|
if ( szBuffer )
|
|
{
|
|
LocalFree( szBuffer );
|
|
szBuffer = NULL;
|
|
}
|
|
|
|
//
|
|
// open the key corr. to the GPO
|
|
//
|
|
dwError = RegOpenKeyEx( hKeyGPO,
|
|
_itow( dwGPOs, szNumber, 16 ),
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKeyNumber );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Determine the maximum length of data in this key
|
|
// so we can use this to query for values
|
|
//
|
|
dwError = RegQueryInfoKey(
|
|
hKeyNumber,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
&cbMaxValueLength,
|
|
0,
|
|
0 );
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// The string data type of the registry does not include the null terminator
|
|
//
|
|
dwBufferSize = ( cbMaxValueLength + sizeof( WCHAR ) );
|
|
|
|
szBuffer = (WCHAR*) LocalAlloc(LPTR, dwBufferSize);
|
|
|
|
if ( ! szBuffer )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// version
|
|
//
|
|
dwType = 0;
|
|
dwBuffer = 0;
|
|
dwSize = sizeof( dwBuffer );
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
VERSION,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) &dwBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || dwBuffer != ( bMachine ? pGPOs->dwMachVersion : pGPOs->dwUserVersion ) )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// WQL
|
|
//
|
|
dwType = 0;
|
|
dwBuffer = 0;
|
|
dwSize = sizeof( dwBuffer );
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
WQL,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) &dwBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || (BOOL) dwBuffer != pGPOs->bFilterAllowed )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Access
|
|
//
|
|
dwType = 0;
|
|
dwBuffer = 0;
|
|
dwSize = sizeof( dwBuffer );
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
ACCESS,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) &dwBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || (BOOL) dwBuffer != pGPOs->bAccessDenied )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// disabled
|
|
//
|
|
dwType = 0;
|
|
dwBuffer = 0;
|
|
dwSize = sizeof( dwBuffer );
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
DISABLED,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) &dwBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || (BOOL) dwBuffer != ( bMachine ? pGPOs->bMachDisabled : pGPOs->bUserDisabled ) )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Options
|
|
//
|
|
dwType = 0;
|
|
dwBuffer = 0;
|
|
dwSize = sizeof( dwBuffer );
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
OPTIONS,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) &dwBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || dwBuffer != pGPOs->dwOptions )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// GPO GUID
|
|
//
|
|
dwType = 0;
|
|
szBuffer[0] = 0;
|
|
dwSize = dwBufferSize;
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
GPOID,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) szBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || _wcsicmp( szBuffer, pGPOs->pwszGPOName ) )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// SOM
|
|
//
|
|
dwType = 0;
|
|
szBuffer[0] = 0;
|
|
dwSize = dwBufferSize;
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
SOM,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) szBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || _wcsicmp( szBuffer, pGPOs->szSOM ) )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
LPWSTR szTemp;
|
|
|
|
//
|
|
// display name
|
|
//
|
|
szTemp = pGPOs->pwszDisplayName ? pGPOs->pwszDisplayName : L"";
|
|
dwType = 0;
|
|
szBuffer[0] = 0;
|
|
dwSize = dwBufferSize;
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
DISPLAYNAME,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) szBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || _wcsicmp( szBuffer, szTemp ) )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// WQL filter
|
|
//
|
|
szTemp = pGPOs->pwszFilterId ? pGPOs->pwszFilterId : L"";
|
|
dwType = 0;
|
|
szBuffer[0] = 0;
|
|
dwSize = dwBufferSize;
|
|
dwError = RegQueryValueEx( hKeyNumber,
|
|
WQLID,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) szBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || _wcsicmp( szBuffer, szTemp ) )
|
|
{
|
|
*pbChanged = TRUE;
|
|
continue;
|
|
}
|
|
|
|
RegCloseKey( hKeyNumber );
|
|
hKeyNumber = 0;
|
|
LocalFree( szBuffer );
|
|
szBuffer = NULL;
|
|
pGPOs = pGPOs->pNext;
|
|
dwGPOs++;
|
|
}
|
|
|
|
if ( szBuffer )
|
|
{
|
|
LocalFree( szBuffer );
|
|
}
|
|
|
|
if ( hKeyNumber )
|
|
{
|
|
RegCloseKey( hKeyNumber );
|
|
}
|
|
RegCloseKey( hKeyGPO );
|
|
|
|
return dwError;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// SavePolicyState()
|
|
//
|
|
// Purpose: Saves enough information about the policy application
|
|
// to determine if RSoP data needs to be re-logged
|
|
//
|
|
// HKLM\Software\Microsoft\Windows\CurrentVersion\Group Policy\State
|
|
// |- Machine
|
|
// | |-SiteName
|
|
// | |-DN
|
|
// | |-GPO
|
|
// | |-0
|
|
// | |-GPOID
|
|
// | |-SOM
|
|
// | |-Version
|
|
// | |-WQL
|
|
// | |-Access
|
|
// | |-1
|
|
// | |-GPOID
|
|
// | |-SOM
|
|
// | |-Version
|
|
// | |-WQL
|
|
// | |-Access
|
|
// | ...
|
|
// | |-N
|
|
// | |-GPOID
|
|
// | |-SOM
|
|
// | |-Version
|
|
// | |-WQL
|
|
// | |-Access
|
|
// |-{UserSID}
|
|
// |-SiteName
|
|
// |-DN
|
|
// |-GPO
|
|
// |-0
|
|
// |-GPOID
|
|
// |-SOM
|
|
// |-Version
|
|
// |-WQL
|
|
// |-Access
|
|
// |-1
|
|
// |-GPOID
|
|
// |-SOM
|
|
// |-Version
|
|
// |-WQL
|
|
// |-Access
|
|
// ...
|
|
// |-N
|
|
// |-GPOID
|
|
// |-SOM
|
|
// |-Version
|
|
// |-WQL
|
|
// |-Access
|
|
// Parameters:
|
|
// pInfo - current state of affairs
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
//*************************************************************
|
|
|
|
DWORD
|
|
SavePolicyState( LPGPOINFO pInfo )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
BOOL bMachine = (pInfo->dwFlags & GP_MACHINE) != 0;
|
|
HKEY hKeyState = 0;
|
|
WCHAR szKeyState[MAX_PATH+1];
|
|
LPWSTR szSite = pInfo->szSiteName ? pInfo->szSiteName : L"";
|
|
LPWSTR szDN = pInfo->lpDNName ? pInfo->lpDNName : L"";
|
|
BOOL bSlowLink = (pInfo->dwFlags & GP_SLOW_LINK) != 0;
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
|
|
//
|
|
// determine the subkey to create
|
|
//
|
|
if ( bMachine )
|
|
{
|
|
hr = StringCchPrintf( szKeyState, sizeof(szKeyState)/sizeof(WCHAR), GP_STATE_KEY, L"Machine" );
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchPrintf( szKeyState, sizeof(szKeyState)/sizeof(WCHAR), GP_STATE_KEY, pInfo->lpwszSidUser );
|
|
}
|
|
if (FAILED(hr)) {
|
|
xe = dwError = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
dwError = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
|
|
szKeyState,
|
|
0,
|
|
0,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKeyState,
|
|
0 );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// reset forced logging in foreground
|
|
//
|
|
if ( !(pInfo->dwFlags & GP_BACKGROUND_THREAD) )
|
|
{
|
|
//
|
|
// set the FORCE_FOREGROUND_LOGGING value
|
|
//
|
|
DWORD dwFalse = 0;
|
|
dwError = RegSetValueEx(hKeyState,
|
|
FORCE_FOREGROUND_LOGGING,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) &dwFalse,
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// set the SITENAME value
|
|
//
|
|
dwError = RegSetValueEx(hKeyState,
|
|
SITENAME,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE*) szSite,
|
|
( wcslen( szSite ) + 1 ) * sizeof( WCHAR ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// set the DN value
|
|
//
|
|
dwError = RegSetValueEx(hKeyState,
|
|
DN,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE*) szDN,
|
|
( wcslen( szDN ) + 1 ) * sizeof( WCHAR ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// slow link
|
|
//
|
|
dwError = RegSetValueEx(hKeyState,
|
|
SLOWLINK,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) ( &bSlowLink ),
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// save the list of GPOs
|
|
//
|
|
dwError = RegSaveGPOs( hKeyState, pInfo->lpGpContainerList, bMachine, GPO );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if ( !bMachine )
|
|
{
|
|
//
|
|
// save the list of Loopback GPOs
|
|
//
|
|
dwError = RegSaveGPOs( hKeyState, pInfo->lpLoopbackGpContainerList, bMachine, LOOPBACK );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// save the list of GPLinks
|
|
//
|
|
dwError = RegSaveGPL( hKeyState, pInfo->lpSOMList, GPLINKLIST );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if ( !bMachine )
|
|
{
|
|
//
|
|
// save the list of Loopback GPLinks
|
|
//
|
|
dwError = RegSaveGPL( hKeyState, pInfo->lpLoopbackSOMList, LOOPBACKGPL );
|
|
}
|
|
|
|
Exit:
|
|
if ( hKeyState )
|
|
{
|
|
RegCloseKey( hKeyState );
|
|
}
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SavePolicyState: Failed Registry operation with %d", dwError ) );
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// SaveLinkState()
|
|
//
|
|
// Purpose: Saves link speed information for the policy application
|
|
//
|
|
// Parameters:
|
|
// pInfo - current state of affairs
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
//*************************************************************
|
|
|
|
DWORD
|
|
SaveLinkState( LPGPOINFO pInfo )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
BOOL bMachine = (pInfo->dwFlags & GP_MACHINE) != 0;
|
|
HKEY hKeyState = 0;
|
|
WCHAR szKeyState[MAX_PATH+1];
|
|
BOOL bSlowLink = (pInfo->dwFlags & GP_SLOW_LINK) != 0;
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
|
|
//
|
|
// determine the subkey to create
|
|
//
|
|
if ( bMachine )
|
|
{
|
|
hr = StringCchPrintf( szKeyState, ARRAYSIZE(szKeyState), GP_STATE_KEY, L"Machine" );
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchPrintf( szKeyState, ARRAYSIZE(szKeyState), GP_STATE_KEY, pInfo->lpwszSidUser );
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
xe = dwError = HRESULT_CODE(hr);
|
|
return dwError;
|
|
}
|
|
|
|
dwError = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
|
|
szKeyState,
|
|
0,
|
|
0,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKeyState,
|
|
0 );
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
//
|
|
// slow link
|
|
//
|
|
dwError = RegSetValueEx(hKeyState,
|
|
SLOWLINK,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) ( &bSlowLink ),
|
|
sizeof( DWORD ) );
|
|
|
|
RegCloseKey( hKeyState );
|
|
}
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SaveLinkState: Failed Registry operation with %d", dwError ) );
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// ComparePolicyState()
|
|
//
|
|
// Purpose: Compares the policy state saved in the registry
|
|
// with the state in LPGPOINFO
|
|
//
|
|
// Parameters:
|
|
// pInfo - current state of affairs
|
|
// pbLinkChanged - has the link speed changed?
|
|
// pbStateChanged - has the state changed?
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
//*************************************************************
|
|
|
|
DWORD
|
|
ComparePolicyState( LPGPOINFO pInfo, BOOL* pbLinkChanged, BOOL* pbStateChanged, BOOL *pbNoState )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
BOOL bMachine = (pInfo->dwFlags & GP_MACHINE) != 0;
|
|
HKEY hKeyState = 0;
|
|
WCHAR szKeyState[MAX_PATH+1];
|
|
DWORD dwBuffer;
|
|
BOOL bSlowLink = (pInfo->dwFlags & GP_SLOW_LINK) != 0;
|
|
BOOL bListChanged = FALSE;
|
|
WCHAR* wszBuffer;
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
|
|
*pbStateChanged = FALSE;
|
|
*pbLinkChanged = FALSE;
|
|
*pbNoState = FALSE;
|
|
wszBuffer = NULL;
|
|
|
|
//
|
|
// determine the subkey to open
|
|
//
|
|
if ( bMachine )
|
|
{
|
|
hr = StringCchPrintf( szKeyState, ARRAYSIZE(szKeyState), GP_STATE_KEY, L"Machine" );
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchPrintf( szKeyState, ARRAYSIZE(szKeyState), GP_STATE_KEY, pInfo->lpwszSidUser );
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
xe = dwError = HRESULT_CODE(hr);
|
|
return dwError;
|
|
}
|
|
|
|
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
szKeyState,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKeyState );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
*pbStateChanged = TRUE;
|
|
*pbNoState = TRUE;
|
|
if (dwError == ERROR_FILE_NOT_FOUND) {
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else {
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
DWORD dwBufferSize;
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
|
|
//
|
|
// Determine the maximum length of data in this key
|
|
// so we can use this to query for values
|
|
//
|
|
dwError = RegQueryInfoKey(
|
|
hKeyState,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
&dwBufferSize,
|
|
0,
|
|
0 );
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
*pbStateChanged = TRUE;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// The string data type of the registry does not include the null terminator
|
|
//
|
|
dwBufferSize += sizeof( WCHAR );
|
|
|
|
wszBuffer = (WCHAR*) LocalAlloc(LPTR, dwBufferSize);
|
|
|
|
if ( ! wszBuffer )
|
|
{
|
|
*pbStateChanged = TRUE;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// check for forced logging in foreground
|
|
//
|
|
if ( !(pInfo->dwFlags & GP_BACKGROUND_THREAD) )
|
|
{
|
|
//
|
|
// get the FORCE_FOREGROUND_LOGGING value
|
|
//
|
|
dwType = 0;
|
|
dwBuffer = 0;
|
|
dwSize = sizeof( dwBuffer );
|
|
dwError = RegQueryValueEx( hKeyState,
|
|
FORCE_FOREGROUND_LOGGING,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) &dwBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || dwBuffer != FALSE )
|
|
{
|
|
*pbStateChanged = TRUE;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// get the SITENAME value
|
|
//
|
|
dwSize = dwBufferSize;
|
|
dwType = 0;
|
|
dwError = RegQueryValueEx( hKeyState,
|
|
SITENAME,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) wszBuffer,
|
|
&dwSize );
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
LPWSTR szSite = pInfo->szSiteName ? pInfo->szSiteName : L"";
|
|
|
|
if ( _wcsicmp( wszBuffer, szSite ) )
|
|
{
|
|
*pbStateChanged = TRUE;
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// get the DN value
|
|
//
|
|
dwSize = dwBufferSize;
|
|
dwType = 0;
|
|
dwError = RegQueryValueEx( hKeyState,
|
|
DN,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) wszBuffer,
|
|
&dwSize );
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
LPWSTR szDN = pInfo->lpDNName ? pInfo->lpDNName : L"";
|
|
|
|
if ( _wcsicmp( wszBuffer, szDN ) )
|
|
{
|
|
*pbStateChanged = TRUE;
|
|
//
|
|
// set forced logging in foreground
|
|
//
|
|
if ( (pInfo->dwFlags & GP_BACKGROUND_THREAD) )
|
|
{
|
|
//
|
|
// set the FORCE_FOREGROUND_LOGGING value
|
|
//
|
|
DWORD dwTrue = TRUE;
|
|
dwError = RegSetValueEx(hKeyState,
|
|
FORCE_FOREGROUND_LOGGING,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) &dwTrue,
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// slow link
|
|
//
|
|
dwType = 0;
|
|
dwBuffer = 0;
|
|
dwSize = sizeof( dwBuffer );
|
|
dwError = RegQueryValueEx( hKeyState,
|
|
SLOWLINK,
|
|
0,
|
|
&dwType,
|
|
(BYTE*) &dwBuffer,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS || dwBuffer != (DWORD)bSlowLink )
|
|
{
|
|
*pbLinkChanged = TRUE;
|
|
}
|
|
|
|
//
|
|
// has the list of GPOs or the GPOs changed
|
|
//
|
|
dwError = RegCompareGPOs( hKeyState,
|
|
pInfo->lpGpContainerList,
|
|
bMachine,
|
|
GPO,
|
|
pbStateChanged,
|
|
&bListChanged );
|
|
//
|
|
// set forced logging in foreground
|
|
//
|
|
if ( (pInfo->dwFlags & GP_BACKGROUND_THREAD) && bListChanged )
|
|
{
|
|
//
|
|
// set the FORCE_FOREGROUND_LOGGING value
|
|
//
|
|
DWORD dwTrue = TRUE;
|
|
dwError = RegSetValueEx(hKeyState,
|
|
FORCE_FOREGROUND_LOGGING,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) &dwTrue,
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if ( dwError == ERROR_SUCCESS && !*pbStateChanged && !bMachine )
|
|
{
|
|
//
|
|
// has the list of loopback GPOs or the GPOs changed
|
|
//
|
|
dwError = RegCompareGPOs( hKeyState,
|
|
pInfo->lpLoopbackGpContainerList,
|
|
bMachine,
|
|
LOOPBACK,
|
|
pbStateChanged,
|
|
&bListChanged );
|
|
//
|
|
// set forced logging in foreground
|
|
//
|
|
if ( (pInfo->dwFlags & GP_BACKGROUND_THREAD) && bListChanged )
|
|
{
|
|
//
|
|
// set the FORCE_FOREGROUND_LOGGING value
|
|
//
|
|
DWORD dwTrue = TRUE;
|
|
dwError = RegSetValueEx(hKeyState,
|
|
FORCE_FOREGROUND_LOGGING,
|
|
0,
|
|
REG_DWORD,
|
|
(BYTE*) &dwTrue,
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( dwError == ERROR_SUCCESS && !*pbStateChanged )
|
|
{
|
|
dwError = RegCompareGPLs( hKeyState,
|
|
pInfo->lpSOMList,
|
|
GPLINKLIST,
|
|
pbStateChanged );
|
|
|
|
if ( dwError == ERROR_SUCCESS && !*pbStateChanged && !bMachine)
|
|
{
|
|
dwError = RegCompareGPLs( hKeyState,
|
|
pInfo->lpLoopbackSOMList,
|
|
LOOPBACKGPL,
|
|
pbStateChanged );
|
|
}
|
|
|
|
if (*pbStateChanged)
|
|
{
|
|
DebugMsg( ( DM_VERBOSE, L"ComparePolicyState: Links have changed") );
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if ( wszBuffer )
|
|
{
|
|
LocalFree( wszBuffer );
|
|
}
|
|
if ( hKeyState )
|
|
{
|
|
RegCloseKey( hKeyState );
|
|
}
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
*pbStateChanged = TRUE;
|
|
DebugMsg( ( DM_WARNING, L"ComparePolicyState: Failed Registry operation with %d", dwError ) );
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// DeletePolicyState()
|
|
//
|
|
// Purpose: deletes the policy state saved in the registry
|
|
//
|
|
// Parameters:
|
|
// szSID - user SID or 0 for machine
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
//*************************************************************
|
|
|
|
DWORD
|
|
DeletePolicyState( LPCWSTR szSid )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
HKEY hKeyState = 0;
|
|
LPWSTR szState = L"Machine";
|
|
|
|
if ( szSid && *szSid )
|
|
{
|
|
szState = (LPWSTR) szSid;
|
|
}
|
|
|
|
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
GP_STATE_ROOT_KEY,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKeyState );
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
dwError = RegDelnode( hKeyState, (LPWSTR) szState );
|
|
|
|
RegCloseKey( hKeyState );
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// SaveLoggingStatus()
|
|
//
|
|
// Purpose: Saving the extension status into the registry
|
|
//
|
|
// Parameters:
|
|
// szSid - Null for machine, otherwise the user sid
|
|
// lpExt - Extension info (null for GP Engine itself)
|
|
// lpRsopExtStatus - A pointer to the RsopExtStatus corresponding
|
|
// to this extension
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
//*************************************************************
|
|
|
|
|
|
DWORD SaveLoggingStatus(LPWSTR szSid, LPGPEXT lpExt, RSOPEXTSTATUS *lpRsopExtStatus)
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
BOOL bMachine = (szSid == 0);
|
|
HKEY hKeyState = 0, hKeyExtState = 0, hKeyExt = 0;
|
|
WCHAR szKeyState[MAX_PATH+1];
|
|
LPWSTR lpExtId;
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
|
|
if ( bMachine )
|
|
{
|
|
hr = StringCchPrintf( szKeyState, ARRAYSIZE(szKeyState), GP_STATE_KEY, L"Machine" );
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchPrintf( szKeyState, ARRAYSIZE(szKeyState), GP_STATE_KEY, szSid );
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
xe = dwError = HRESULT_CODE(hr);
|
|
return dwError;
|
|
}
|
|
|
|
dwError = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
|
|
szKeyState,
|
|
0,
|
|
0,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKeyState,
|
|
0 );
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SaveLoggingStatus: Failed to create state key with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
dwError = RegCreateKeyEx( hKeyState,
|
|
EXTENSION,
|
|
0,
|
|
0,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKeyExtState,
|
|
0 );
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SaveLoggingStatus: Failed to create extension key with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
lpExtId = lpExt ? lpExt->lpKeyName : GPCORE_GUID;
|
|
|
|
dwError = RegCreateKeyEx( hKeyExtState,
|
|
lpExtId,
|
|
0,
|
|
0,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKeyExt,
|
|
0 );
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SaveLoggingStatus: Failed to create CSE key with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
dwError = RegSetValueEx(hKeyExt, STARTTIME1, 0, REG_DWORD,
|
|
(BYTE *)(&((lpRsopExtStatus->ftStartTime).dwLowDateTime)),
|
|
sizeof(DWORD));
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SaveLoggingStatus: Failed to set STARTTIME1 with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
dwError = RegSetValueEx(hKeyExt, STARTTIME2, 0, REG_DWORD,
|
|
(BYTE *)(&((lpRsopExtStatus->ftStartTime).dwHighDateTime)),
|
|
sizeof(DWORD));
|
|
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SaveLoggingStatus: Failed to set STARTTIME2 with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
dwError = RegSetValueEx(hKeyExt, ENDTIME1, 0, REG_DWORD,
|
|
(BYTE *)(&((lpRsopExtStatus->ftEndTime).dwLowDateTime)),
|
|
sizeof(DWORD));
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SaveLoggingStatus: Failed to set ENDTIME1 with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
dwError = RegSetValueEx(hKeyExt, ENDTIME2, 0, REG_DWORD,
|
|
(BYTE *)(&((lpRsopExtStatus->ftEndTime).dwHighDateTime)),
|
|
sizeof(DWORD));
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SaveLoggingStatus: Failed to set ENDTIME2 with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
dwError = RegSetValueEx(hKeyExt, STATUS, 0, REG_DWORD,
|
|
(BYTE *)(&(lpRsopExtStatus->dwStatus)),
|
|
sizeof(DWORD));
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SaveLoggingStatus: Failed to set STATUS with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
dwError = RegSetValueEx(hKeyExt, LOGSTATUS, 0, REG_DWORD,
|
|
(BYTE *)(&(lpRsopExtStatus->dwLoggingStatus)),
|
|
sizeof(DWORD));
|
|
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"SaveLoggingStatus: Failed to set LOGSTATUS with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
if (hKeyExt)
|
|
RegCloseKey(hKeyExt);
|
|
|
|
|
|
if (hKeyExtState)
|
|
RegCloseKey(hKeyExtState);
|
|
|
|
|
|
if (hKeyState)
|
|
RegCloseKey(hKeyState);
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// ReadLoggingStatus()
|
|
//
|
|
// Purpose: Read the extension status into the registry
|
|
//
|
|
// Parameters:
|
|
// szSid - Null for machine, otherwise the user sid
|
|
// szExtId - Extension info (null for GP Engine itself)
|
|
// lpRsopExtStatus - A pointer to the RsopExtStatus (that will be filled up)
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
//
|
|
//*************************************************************
|
|
|
|
DWORD ReadLoggingStatus(LPWSTR szSid, LPWSTR szExtId, RSOPEXTSTATUS *lpRsopExtStatus)
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
BOOL bMachine = (szSid == 0);
|
|
HKEY hKeyExt = 0;
|
|
WCHAR szKeyStateExt[MAX_PATH+1];
|
|
LPWSTR lpExtId;
|
|
DWORD dwType, dwSize;
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
|
|
if ( bMachine )
|
|
{
|
|
hr = StringCchPrintf( szKeyStateExt, ARRAYSIZE(szKeyStateExt), GP_STATE_KEY, L"Machine" );
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchPrintf( szKeyStateExt, ARRAYSIZE(szKeyStateExt), GP_STATE_KEY, szSid );
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
xe = dwError = HRESULT_CODE(hr);
|
|
return dwError;
|
|
}
|
|
|
|
CheckSlash(szKeyStateExt);
|
|
|
|
hr = StringCchCat(szKeyStateExt, ARRAYSIZE(szKeyStateExt), EXTENSION);
|
|
if (FAILED(hr))
|
|
{
|
|
xe = dwError = HRESULT_CODE(hr);
|
|
return dwError;
|
|
}
|
|
|
|
CheckSlash(szKeyStateExt);
|
|
|
|
lpExtId = szExtId ? szExtId : GPCORE_GUID;
|
|
|
|
hr = StringCchCat(szKeyStateExt, ARRAYSIZE(szKeyStateExt), lpExtId);
|
|
if (FAILED(hr))
|
|
{
|
|
xe = dwError = HRESULT_CODE(hr);
|
|
return dwError;
|
|
}
|
|
|
|
// from this point on, go to exit.
|
|
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
szKeyStateExt,
|
|
0,
|
|
KEY_READ,
|
|
&hKeyExt);
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"ReadLoggingStatus: Failed to create state key with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
dwSize = sizeof(DWORD);
|
|
dwError = RegQueryValueEx(hKeyExt, STARTTIME1, 0, &dwType,
|
|
(BYTE *)(&((lpRsopExtStatus->ftStartTime).dwLowDateTime)),
|
|
&dwSize);
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"ReadLoggingStatus: Failed to set STARTTIME1 with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
dwError = RegQueryValueEx(hKeyExt, STARTTIME2, 0, &dwType,
|
|
(BYTE *)(&((lpRsopExtStatus->ftStartTime).dwHighDateTime)),
|
|
&dwSize);
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"ReadLoggingStatus: Failed to set STARTTIME1 with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
dwError = RegQueryValueEx(hKeyExt, ENDTIME1, 0, &dwType,
|
|
(BYTE *)(&((lpRsopExtStatus->ftEndTime).dwLowDateTime)),
|
|
&dwSize);
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"ReadLoggingStatus: Failed to set ENDTIME1 with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
dwError = RegQueryValueEx(hKeyExt, ENDTIME2, 0, &dwType,
|
|
(BYTE *)(&((lpRsopExtStatus->ftEndTime).dwHighDateTime)),
|
|
&dwSize);
|
|
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"ReadLoggingStatus: Failed to set ENDTIME2 with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
dwError = RegQueryValueEx(hKeyExt, STATUS, 0, &dwType,
|
|
(BYTE *)(&(lpRsopExtStatus->dwStatus)),
|
|
&dwSize);
|
|
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"ReadLoggingStatus: Failed to set STATUS with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
dwSize = sizeof(DWORD);
|
|
dwError = RegQueryValueEx(hKeyExt, LOGSTATUS, 0, &dwType,
|
|
(BYTE *)(&(lpRsopExtStatus->dwLoggingStatus)),
|
|
&dwSize);
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_WARNING, L"ReadLoggingStatus: Failed to set LOGSTATUS with %d", dwError ) );
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
if (hKeyExt)
|
|
RegCloseKey(hKeyExt);
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
#define POLICY_KEY L"Software\\Policies\\Microsoft\\Windows NT\\CurrentVersion\\winlogon"
|
|
#define PREFERENCE_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\winlogon"
|
|
#define GP_SYNCFGREFRESH L"SyncForegroundPolicy"
|
|
|
|
BOOL WINAPI
|
|
GetFgPolicySetting( HKEY hKeyRoot )
|
|
{
|
|
HKEY hKeyPolicy = 0;
|
|
HKEY hKeyPreference = 0;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwSize = sizeof( DWORD );
|
|
BOOL bSync = FALSE;
|
|
|
|
//
|
|
// async only on Pro
|
|
//
|
|
OSVERSIONINFOEXW version;
|
|
version.dwOSVersionInfoSize = sizeof(version);
|
|
if ( !GetVersionEx( (LPOSVERSIONINFO) &version ) )
|
|
{
|
|
//
|
|
// conservatively assume non Pro SKU
|
|
//
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
if ( version.wProductType != VER_NT_WORKSTATION )
|
|
{
|
|
//
|
|
// force sync refresh on non Pro SKU
|
|
//
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
dwError = RegOpenKeyEx( hKeyRoot,
|
|
PREFERENCE_KEY,
|
|
0,
|
|
KEY_READ,
|
|
&hKeyPreference );
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
//
|
|
// read the preference value
|
|
//
|
|
RegQueryValueEx(hKeyPreference,
|
|
GP_SYNCFGREFRESH,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE) &bSync,
|
|
&dwSize );
|
|
RegCloseKey( hKeyPreference );
|
|
}
|
|
|
|
dwError = RegOpenKeyEx( hKeyRoot,
|
|
POLICY_KEY,
|
|
0,
|
|
KEY_READ,
|
|
&hKeyPolicy );
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
//
|
|
// read the policy
|
|
//
|
|
RegQueryValueEx(hKeyPolicy,
|
|
GP_SYNCFGREFRESH,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE) &bSync,
|
|
&dwSize );
|
|
RegCloseKey( hKeyPolicy );
|
|
}
|
|
|
|
return bSync;
|
|
}
|
|
|
|
#define PREVREFRESHMODE L"PrevRefreshMode"
|
|
#define NEXTREFRESHMODE L"NextRefreshMode"
|
|
#define PREVREFRESHREASON L"PrevRefreshReason"
|
|
#define NEXTREFRESHREASON L"NextRefreshReason"
|
|
|
|
#define STATE_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\State\\"
|
|
|
|
DWORD WINAPI
|
|
gpGetFgPolicyRefreshInfo(BOOL bPrev,
|
|
LPWSTR szUserSid,
|
|
LPFgPolicyRefreshInfo pInfo )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
WCHAR szKeyState[MAX_PATH+1] = STATE_KEY;
|
|
HKEY hKeyState = 0;
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
|
|
if ( !pInfo )
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
pInfo->mode = GP_ModeUnknown;
|
|
pInfo->reason = GP_ReasonUnknown;
|
|
|
|
//
|
|
// determine the subkey to create
|
|
//
|
|
if ( !szUserSid )
|
|
{
|
|
hr = StringCchCat( szKeyState, ARRAYSIZE(szKeyState), L"Machine" );
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchCat( szKeyState, ARRAYSIZE(szKeyState), szUserSid );
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
xe = dwError = HRESULT_CODE(hr);
|
|
return dwError;
|
|
}
|
|
|
|
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
szKeyState,
|
|
0,
|
|
KEY_READ,
|
|
&hKeyState );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// refresh mode
|
|
//
|
|
dwType = REG_DWORD;
|
|
dwSize = sizeof( DWORD );
|
|
dwError = RegQueryValueEx( hKeyState,
|
|
bPrev ? PREVREFRESHMODE : NEXTREFRESHMODE ,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE) &pInfo->mode,
|
|
&dwSize );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// refresh reason
|
|
//
|
|
dwType = REG_DWORD;
|
|
dwSize = sizeof( DWORD );
|
|
dwError = RegQueryValueEx( hKeyState,
|
|
bPrev ? PREVREFRESHREASON : NEXTREFRESHREASON ,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE) &pInfo->reason,
|
|
&dwSize );
|
|
|
|
Exit:
|
|
//
|
|
// cleanup
|
|
//
|
|
if ( hKeyState )
|
|
{
|
|
RegCloseKey( hKeyState );
|
|
}
|
|
|
|
//
|
|
// assume first logon/startup
|
|
//
|
|
if ( dwError == ERROR_FILE_NOT_FOUND )
|
|
{
|
|
pInfo->mode = GP_ModeSyncForeground;
|
|
pInfo->reason = GP_ReasonFirstPolicy;
|
|
dwError = ERROR_SUCCESS;
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
LPWSTR g_szModes[] =
|
|
{
|
|
L"Unknown",
|
|
L"Synchronous",
|
|
L"Asynchronous",
|
|
};
|
|
|
|
LPWSTR g_szReasons[] =
|
|
{
|
|
L"NoNeedForSync",
|
|
L"FirstPolicyRefresh",
|
|
L"CSERequiresForeground",
|
|
L"CSEReturnedError",
|
|
L"ForcedSyncRefresh",
|
|
L"SyncPolicy",
|
|
L"NonCachedCredentials",
|
|
L"SKU",
|
|
};
|
|
|
|
DWORD WINAPI
|
|
gpSetFgPolicyRefreshInfo(BOOL bPrev,
|
|
LPWSTR szUserSid,
|
|
FgPolicyRefreshInfo info )
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
WCHAR szKeyState[MAX_PATH+1] = STATE_KEY;
|
|
HKEY hKeyState = 0;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD dwSize = sizeof( DWORD );
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
|
|
//
|
|
// determine the subkey to create
|
|
//
|
|
if ( !szUserSid )
|
|
{
|
|
hr = StringCchCat( szKeyState, ARRAYSIZE(szKeyState), L"Machine" );
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchCat( szKeyState, ARRAYSIZE(szKeyState), szUserSid );
|
|
}
|
|
if (FAILED(hr))
|
|
{
|
|
xe = dwError = HRESULT_CODE(hr);
|
|
return dwError;
|
|
}
|
|
|
|
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
szKeyState,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKeyState );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// refresh mode
|
|
//
|
|
dwError = RegSetValueEx(hKeyState,
|
|
bPrev ? PREVREFRESHMODE : NEXTREFRESHMODE ,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE) &info.mode,
|
|
sizeof( DWORD ) );
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// refresh reason
|
|
//
|
|
dwType = REG_DWORD;
|
|
dwSize = sizeof( DWORD );
|
|
dwError = RegSetValueEx(hKeyState,
|
|
bPrev ? PREVREFRESHREASON : NEXTREFRESHREASON ,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE) &info.reason,
|
|
sizeof( DWORD ) );
|
|
|
|
Exit:
|
|
//
|
|
// cleanup
|
|
//
|
|
if ( hKeyState )
|
|
{
|
|
RegCloseKey( hKeyState );
|
|
}
|
|
|
|
if ( dwError == ERROR_SUCCESS )
|
|
{
|
|
DebugMsg( ( DM_VERBOSE,
|
|
L"SetFgRefreshInfo: %s %s Fg policy %s, Reason: %s.",
|
|
bPrev ? L"Previous" : L"Next",
|
|
szUserSid ? L"User" : L"Machine",
|
|
g_szModes[info.mode % ARRAYSIZE( g_szModes )],
|
|
g_szReasons[info.reason % ARRAYSIZE( g_szReasons )] ) );
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
USERENVAPI
|
|
DWORD
|
|
WINAPI
|
|
GetPreviousFgPolicyRefreshInfo( LPWSTR szUserSid,
|
|
FgPolicyRefreshInfo* pInfo )
|
|
|
|
{
|
|
return gpGetFgPolicyRefreshInfo( TRUE, szUserSid, pInfo );
|
|
}
|
|
|
|
USERENVAPI
|
|
DWORD
|
|
WINAPI
|
|
GetNextFgPolicyRefreshInfo( LPWSTR szUserSid,
|
|
FgPolicyRefreshInfo* pInfo )
|
|
{
|
|
return gpGetFgPolicyRefreshInfo( FALSE, szUserSid, pInfo );
|
|
}
|
|
|
|
USERENVAPI
|
|
DWORD
|
|
WINAPI
|
|
GetCurrentFgPolicyRefreshInfo( LPWSTR szUserSid,
|
|
FgPolicyRefreshInfo* pInfo )
|
|
{
|
|
return gpGetFgPolicyRefreshInfo( FALSE, szUserSid, pInfo );
|
|
}
|
|
|
|
USERENVAPI
|
|
DWORD
|
|
WINAPI
|
|
SetPreviousFgPolicyRefreshInfo( LPWSTR szUserSid,
|
|
FgPolicyRefreshInfo info )
|
|
|
|
{
|
|
return gpSetFgPolicyRefreshInfo( TRUE, szUserSid, info );
|
|
}
|
|
|
|
USERENVAPI
|
|
DWORD
|
|
WINAPI
|
|
SetNextFgPolicyRefreshInfo( LPWSTR szUserSid,
|
|
FgPolicyRefreshInfo info )
|
|
{
|
|
return gpSetFgPolicyRefreshInfo( FALSE, szUserSid, info );
|
|
}
|
|
|
|
USERENVAPI
|
|
DWORD
|
|
WINAPI
|
|
ForceSyncFgPolicy( LPWSTR szUserSid )
|
|
{
|
|
FgPolicyRefreshInfo info = { GP_ReasonSyncForced, GP_ModeSyncForeground };
|
|
return gpSetFgPolicyRefreshInfo( FALSE, szUserSid, info );
|
|
}
|
|
|
|
USERENVAPI
|
|
BOOL
|
|
WINAPI
|
|
IsSyncForegroundPolicyRefresh( BOOL bMachine,
|
|
HANDLE hToken )
|
|
{
|
|
BOOL bSyncRefresh;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
bSyncRefresh = GetFgPolicySetting( HKEY_LOCAL_MACHINE );
|
|
if ( bSyncRefresh )
|
|
{
|
|
//
|
|
// policy sez sync
|
|
//
|
|
DebugMsg( ( DM_VERBOSE, L"IsSyncForegroundPolicyRefresh: Synchronous, Reason: policy set to SYNC" ) );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LPWSTR szSid = !bMachine ? GetSidString( hToken ) : 0;
|
|
FgPolicyRefreshInfo info;
|
|
|
|
dwError = GetCurrentFgPolicyRefreshInfo( szSid, &info );
|
|
|
|
if ( szSid )
|
|
{
|
|
DeleteSidString( szSid );
|
|
}
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
//
|
|
// error reading the refresh mode, treat as sync
|
|
//
|
|
DebugMsg( ( DM_VERBOSE, L"IsSyncForegroundPolicyRefresh: Synchronous, Reason: Error 0x%x ", dwError ) );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bSyncRefresh = ( info.mode == GP_ModeAsyncForeground ) ? FALSE : TRUE;
|
|
|
|
DebugMsg( ( DM_VERBOSE,
|
|
L"IsSyncForegroundPolicyRefresh: %s, Reason: %s",
|
|
g_szModes[info.mode % ARRAYSIZE( g_szModes )],
|
|
g_szReasons[info.reason % ARRAYSIZE( g_szReasons )] ) );
|
|
|
|
return bSyncRefresh;
|
|
}
|
|
|