//************************************************************* // // Group Policy Support - State functions // // Microsoft Confidential // Copyright (c) Microsoft Corporation 1997-1998 // All rights reserved // //************************************************************* #include "gphdr.h" #include //************************************************************* // // 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; ipNext; 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 xszRsopNameSpace = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)* (dwRSOPNSLength)); // convert the Sids to WMI Names XPtrLF xszWmiNameOld = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(lstrlen(lpwszSidUserOld)+1)); XPtrLF 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; ihKeyRoot, 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; }