Leaked source code of windows server 2003
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

//*************************************************************
//
// 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;
}