2066 lines
62 KiB
C++
2066 lines
62 KiB
C++
|
//*************************************************************
|
||
|
//
|
||
|
// Group Policy Support for registry policies
|
||
|
//
|
||
|
// Microsoft Confidential
|
||
|
// Copyright (c) Microsoft Corporation 1997-1998
|
||
|
// All rights reserved
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
#include "gphdr.h"
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// DeleteRegistryValue()
|
||
|
//
|
||
|
// Purpose: Callback from ParseRegistryFile that deletes
|
||
|
// registry policies
|
||
|
//
|
||
|
// Parameters: lpGPOInfo - GPO Information
|
||
|
// lpKeyName - Key name
|
||
|
// lpValueName - Value name
|
||
|
// dwType - Registry data type
|
||
|
// lpData - Registry data
|
||
|
// pwszGPO - Gpo
|
||
|
// pwszSOM - Sdou that the Gpo is linked to
|
||
|
// pHashTable - Hash table for registry keys
|
||
|
//
|
||
|
// Return: TRUE if successful
|
||
|
// FALSE if an error occurs
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
BOOL DeleteRegistryValue (LPGPOINFO lpGPOInfo, LPTSTR lpKeyName,
|
||
|
LPTSTR lpValueName, DWORD dwType,
|
||
|
DWORD dwDataLength, LPBYTE lpData,
|
||
|
WCHAR *pwszGPO,
|
||
|
WCHAR *pwszSOM, REGHASHTABLE *pHashTable)
|
||
|
{
|
||
|
DWORD dwDisp;
|
||
|
HKEY hSubKey;
|
||
|
LONG lResult;
|
||
|
INT iStrLen;
|
||
|
TCHAR szPolicies1[] = TEXT("Software\\Policies");
|
||
|
TCHAR szPolicies2[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies");
|
||
|
XLastError xe;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Check if there is a keyname
|
||
|
//
|
||
|
|
||
|
if (!lpKeyName || !(*lpKeyName)) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Check if the key is in one of the policies keys
|
||
|
//
|
||
|
|
||
|
iStrLen = lstrlen(szPolicies1);
|
||
|
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE, szPolicies1,
|
||
|
iStrLen, lpKeyName, iStrLen) != CSTR_EQUAL) {
|
||
|
|
||
|
iStrLen = lstrlen(szPolicies2);
|
||
|
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE, szPolicies2,
|
||
|
iStrLen, lpKeyName, iStrLen) != CSTR_EQUAL) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Check if the value name starts with **
|
||
|
//
|
||
|
|
||
|
if (lpValueName && (lstrlen(lpValueName) > 1)) {
|
||
|
|
||
|
if ( (*lpValueName == TEXT('*')) && (*(lpValueName+1) == TEXT('*')) ) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// We found a value that needs to be deleted
|
||
|
//
|
||
|
|
||
|
if (RegCleanUpValue (lpGPOInfo->hKeyRoot, lpKeyName, lpValueName)) {
|
||
|
DebugMsg((DM_VERBOSE, TEXT("DeleteRegistryValue: Deleted %s\\%s"),
|
||
|
lpKeyName, lpValueName));
|
||
|
} else {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("DeleteRegistryValue: Failed to delete %s\\%s"),
|
||
|
lpKeyName, lpValueName));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// ResetPolicies()
|
||
|
//
|
||
|
// Purpose: Resets the Policies and old Policies key to their
|
||
|
// original state.
|
||
|
//
|
||
|
// Parameters: lpGPOInfo - GPT information
|
||
|
// lpArchive - Name of archive file
|
||
|
//
|
||
|
//
|
||
|
// Return: TRUE if successful
|
||
|
// FALSE if an error occurs
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
BOOL ResetPolicies (LPGPOINFO lpGPOInfo, LPTSTR lpArchive)
|
||
|
{
|
||
|
HKEY hKey;
|
||
|
LONG lResult;
|
||
|
DWORD dwDisp, dwValue = 0x91;
|
||
|
XLastError xe;
|
||
|
|
||
|
|
||
|
DebugMsg((DM_VERBOSE, TEXT("ResetPolicies: Entering.")));
|
||
|
|
||
|
|
||
|
//
|
||
|
// Parse the archive file and delete any policies
|
||
|
//
|
||
|
|
||
|
if (!ParseRegistryFile (lpGPOInfo, lpArchive,
|
||
|
DeleteRegistryValue, NULL, NULL, NULL, NULL, FALSE )) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ResetPolicies: Leaving")));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Recreate the new policies key
|
||
|
//
|
||
|
|
||
|
lResult = RegCreateKeyEx (lpGPOInfo->hKeyRoot,
|
||
|
TEXT("Software\\Policies"),
|
||
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
||
|
KEY_WRITE, NULL, &hKey, &dwDisp);
|
||
|
|
||
|
if (lResult == ERROR_SUCCESS) {
|
||
|
|
||
|
//
|
||
|
// Re-apply security
|
||
|
//
|
||
|
|
||
|
RegCloseKey (hKey);
|
||
|
|
||
|
if (!MakeRegKeySecure((lpGPOInfo->dwFlags & GP_MACHINE) ? NULL : lpGPOInfo->hToken,
|
||
|
lpGPOInfo->hKeyRoot,
|
||
|
TEXT("Software\\Policies"))) {
|
||
|
DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to secure reg key.")));
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to create reg key with %d."), lResult));
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Recreate the old policies key
|
||
|
//
|
||
|
|
||
|
lResult = RegCreateKeyEx (lpGPOInfo->hKeyRoot,
|
||
|
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies"),
|
||
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
||
|
KEY_WRITE, NULL, &hKey, &dwDisp);
|
||
|
|
||
|
if (lResult == ERROR_SUCCESS) {
|
||
|
|
||
|
//
|
||
|
// Re-apply security
|
||
|
//
|
||
|
|
||
|
RegCloseKey (hKey);
|
||
|
|
||
|
if (!MakeRegKeySecure((lpGPOInfo->dwFlags & GP_MACHINE) ? NULL : lpGPOInfo->hToken,
|
||
|
lpGPOInfo->hKeyRoot,
|
||
|
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies"))) {
|
||
|
DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to secure reg key.")));
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to create reg key with %d."), lResult));
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// If this is user policy, reset the NoDriveTypeAutoRun default value
|
||
|
//
|
||
|
|
||
|
if (!(lpGPOInfo->dwFlags & GP_MACHINE)) {
|
||
|
|
||
|
|
||
|
if (RegCreateKeyEx (lpGPOInfo->hKeyRoot,
|
||
|
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"),
|
||
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
||
|
KEY_WRITE, NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
|
||
|
|
||
|
RegSetValueEx (hKey, TEXT("NoDriveTypeAutoRun"), 0,
|
||
|
REG_DWORD, (LPBYTE) &dwValue, sizeof(dwValue));
|
||
|
|
||
|
RegCloseKey (hKey);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DebugMsg((DM_VERBOSE, TEXT("ResetPolicies: Leaving.")));
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// ArchiveRegistryValue()
|
||
|
//
|
||
|
// Purpose: Archives a registry value in the specified file
|
||
|
//
|
||
|
// Parameters: hFile - File handle of archive file
|
||
|
// lpKeyName - Key name
|
||
|
// lpValueName - Value name
|
||
|
// dwType - Registry value type
|
||
|
// dwDataLength - Registry value size
|
||
|
// lpData - Registry value
|
||
|
//
|
||
|
// Return: TRUE if successful
|
||
|
// FALSE if an error occurs
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
BOOL ArchiveRegistryValue(HANDLE hFile, LPWSTR lpKeyName,
|
||
|
LPWSTR lpValueName, DWORD dwType,
|
||
|
DWORD dwDataLength, LPBYTE lpData)
|
||
|
{
|
||
|
BOOL bResult = FALSE;
|
||
|
DWORD dwBytesWritten;
|
||
|
DWORD dwTemp;
|
||
|
const WCHAR cOpenBracket = L'[';
|
||
|
const WCHAR cCloseBracket = L']';
|
||
|
const WCHAR cSemiColon = L';';
|
||
|
XLastError xe;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Write the entry to the text file.
|
||
|
//
|
||
|
// Format:
|
||
|
//
|
||
|
// [keyname;valuename;type;datalength;data]
|
||
|
//
|
||
|
|
||
|
// open bracket
|
||
|
if (!WriteFile (hFile, &cOpenBracket, sizeof(WCHAR), &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != sizeof(WCHAR))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write open bracket with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// key name
|
||
|
dwTemp = (lstrlen (lpKeyName) + 1) * sizeof (WCHAR);
|
||
|
if (!WriteFile (hFile, lpKeyName, dwTemp, &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != dwTemp)
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write key name with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// semicolon
|
||
|
if (!WriteFile (hFile, &cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != sizeof(WCHAR))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write semicolon with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
// value name
|
||
|
dwTemp = (lstrlen (lpValueName) + 1) * sizeof (WCHAR);
|
||
|
if (!WriteFile (hFile, lpValueName, dwTemp, &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != dwTemp)
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write value name with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// semicolon
|
||
|
if (!WriteFile (hFile, &cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != sizeof(WCHAR))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write semicolon with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
// type
|
||
|
if (!WriteFile (hFile, &dwType, sizeof(DWORD), &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != sizeof(DWORD))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write data type with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
// semicolon
|
||
|
if (!WriteFile (hFile, &cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != sizeof(WCHAR))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write semicolon with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
// data length
|
||
|
if (!WriteFile (hFile, &dwDataLength, sizeof(DWORD), &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != sizeof(DWORD))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write data type with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
// semicolon
|
||
|
if (!WriteFile (hFile, &cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != sizeof(WCHAR))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write semicolon with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
// data
|
||
|
if (!WriteFile (hFile, lpData, dwDataLength, &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != dwDataLength)
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write data with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
// close bracket
|
||
|
if (!WriteFile (hFile, &cCloseBracket, sizeof(WCHAR), &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != sizeof(WCHAR))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write close bracket with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Sucess
|
||
|
//
|
||
|
|
||
|
bResult = TRUE;
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// ParseRegistryFile()
|
||
|
//
|
||
|
// Purpose: Parses a registry.pol file
|
||
|
//
|
||
|
// Parameters: lpGPOInfo - GPO information
|
||
|
// lpRegistry - Path to registry.pol
|
||
|
// pfnRegFileCallback - Callback function
|
||
|
// hArchive - Handle to archive file
|
||
|
// pwszGPO - Gpo
|
||
|
// pwszSOM - Sdou that the Gpo is linked to
|
||
|
// pHashTable - Hash table for registry keys
|
||
|
//
|
||
|
//
|
||
|
// Return: TRUE if successful
|
||
|
// FALSE if an error occurs
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
BOOL ParseRegistryFile (LPGPOINFO lpGPOInfo, LPTSTR lpRegistry,
|
||
|
PFNREGFILECALLBACK pfnRegFileCallback,
|
||
|
HANDLE hArchive, WCHAR *pwszGPO,
|
||
|
WCHAR *pwszSOM, REGHASHTABLE *pHashTable,
|
||
|
BOOL bRsopPlanningMode)
|
||
|
{
|
||
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||
|
BOOL bResult = FALSE;
|
||
|
DWORD dwTemp, dwBytesRead, dwType, dwDataLength;
|
||
|
LPWSTR lpKeyName = 0, lpValueName = 0, lpTemp;
|
||
|
LPBYTE lpData = NULL;
|
||
|
WCHAR chTemp;
|
||
|
HANDLE hOldToken;
|
||
|
XLastError xe;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Verbose output
|
||
|
//
|
||
|
|
||
|
DebugMsg((DM_VERBOSE, TEXT("ParseRegistryFile: Entering with <%s>."),
|
||
|
lpRegistry));
|
||
|
|
||
|
|
||
|
//
|
||
|
// Open the registry file
|
||
|
//
|
||
|
|
||
|
if(!bRsopPlanningMode) {
|
||
|
if (!ImpersonateUser(lpGPOInfo->hToken, &hOldToken)) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to impersonate user")));
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hFile = CreateFile (lpRegistry, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
||
|
NULL);
|
||
|
|
||
|
if(!bRsopPlanningMode) {
|
||
|
RevertToUser(&hOldToken);
|
||
|
}
|
||
|
|
||
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||
|
if ((GetLastError() == ERROR_FILE_NOT_FOUND) ||
|
||
|
(GetLastError() == ERROR_PATH_NOT_FOUND))
|
||
|
{
|
||
|
bResult = TRUE;
|
||
|
goto Exit;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: CreateFile failed with %d"),
|
||
|
GetLastError()));
|
||
|
CEvents ev(TRUE, EVENT_NO_REGISTRY);
|
||
|
ev.AddArg(lpRegistry); ev.AddArgWin32Error(GetLastError()); ev.Report();
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Allocate buffers to hold the keyname, valuename, and data
|
||
|
//
|
||
|
|
||
|
lpKeyName = (LPWSTR) LocalAlloc (LPTR, MAX_KEYNAME_SIZE * sizeof(WCHAR));
|
||
|
|
||
|
if (!lpKeyName)
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to allocate memory with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
lpValueName = (LPWSTR) LocalAlloc (LPTR, MAX_VALUENAME_SIZE * sizeof(WCHAR));
|
||
|
|
||
|
if (!lpValueName)
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to allocate memory with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read the header block
|
||
|
//
|
||
|
// 2 DWORDS, signature (PReg) and version number and 2 newlines
|
||
|
//
|
||
|
|
||
|
if (!ReadFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesRead, NULL) ||
|
||
|
dwBytesRead != sizeof(dwTemp))
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read signature with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (dwTemp != REGFILE_SIGNATURE)
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Invalid file signature")));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (!ReadFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesRead, NULL) ||
|
||
|
dwBytesRead != sizeof(dwTemp))
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read version number with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (dwTemp != REGISTRY_FILE_VERSION)
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Invalid file version")));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read the data
|
||
|
//
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Read the first character. It will either be a [ or the end
|
||
|
// of the file.
|
||
|
//
|
||
|
|
||
|
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
|
||
|
{
|
||
|
if (GetLastError() != ERROR_HANDLE_EOF)
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read first character with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ((dwBytesRead == 0) || (chTemp != L'['))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read the keyname
|
||
|
//
|
||
|
|
||
|
lpTemp = lpKeyName;
|
||
|
dwTemp = 0;
|
||
|
|
||
|
while (dwTemp < MAX_KEYNAME_SIZE)
|
||
|
{
|
||
|
|
||
|
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read keyname character with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
*lpTemp++ = chTemp;
|
||
|
|
||
|
if (chTemp == TEXT('\0'))
|
||
|
break;
|
||
|
|
||
|
dwTemp++;
|
||
|
}
|
||
|
|
||
|
if (dwTemp >= MAX_KEYNAME_SIZE)
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Keyname exceeded max size")));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read the semi-colon
|
||
|
//
|
||
|
|
||
|
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
|
||
|
{
|
||
|
if (GetLastError() != ERROR_HANDLE_EOF)
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read first character with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ((dwBytesRead == 0) || (chTemp != L';'))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read the valuename
|
||
|
//
|
||
|
|
||
|
lpTemp = lpValueName;
|
||
|
dwTemp = 0;
|
||
|
|
||
|
while (dwTemp < MAX_VALUENAME_SIZE)
|
||
|
{
|
||
|
|
||
|
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read valuename character with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
*lpTemp++ = chTemp;
|
||
|
|
||
|
if (chTemp == TEXT('\0'))
|
||
|
break;
|
||
|
|
||
|
dwTemp++;
|
||
|
}
|
||
|
|
||
|
if (dwTemp >= MAX_VALUENAME_SIZE)
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Valuename exceeded max size")));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read the semi-colon
|
||
|
//
|
||
|
|
||
|
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
|
||
|
{
|
||
|
if (GetLastError() != ERROR_HANDLE_EOF)
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read first character with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ((dwBytesRead == 0) || (chTemp != L';'))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read the type
|
||
|
//
|
||
|
|
||
|
if (!ReadFile (hFile, &dwType, sizeof(DWORD), &dwBytesRead, NULL))
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read type with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Skip semicolon
|
||
|
//
|
||
|
|
||
|
if (!ReadFile (hFile, &dwTemp, sizeof(WCHAR), &dwBytesRead, NULL))
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to skip semicolon with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read the data length
|
||
|
//
|
||
|
|
||
|
if (!ReadFile (hFile, &dwDataLength, sizeof(DWORD), &dwBytesRead, NULL))
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to data length with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Skip semicolon
|
||
|
//
|
||
|
|
||
|
if (!ReadFile (hFile, &dwTemp, sizeof(WCHAR), &dwBytesRead, NULL))
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to skip semicolon with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Allocate memory for data
|
||
|
//
|
||
|
|
||
|
lpData = (LPBYTE) LocalAlloc (LPTR, dwDataLength);
|
||
|
|
||
|
if (!lpData)
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to allocate memory for data with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read data
|
||
|
//
|
||
|
|
||
|
if (!ReadFile (hFile, lpData, dwDataLength, &dwBytesRead, NULL))
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read data with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Skip closing bracket
|
||
|
//
|
||
|
|
||
|
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to skip closing bracket with %d"),
|
||
|
GetLastError()));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (chTemp != L']')
|
||
|
{
|
||
|
xe = ERROR_INVALID_DATA;
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Expected to find ], but found %c"),
|
||
|
chTemp));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Call the callback function
|
||
|
//
|
||
|
|
||
|
if (!pfnRegFileCallback (lpGPOInfo, lpKeyName, lpValueName,
|
||
|
dwType, dwDataLength, lpData,
|
||
|
pwszGPO, pwszSOM, pHashTable ))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Callback function returned false.")));
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Archive the data if appropriate
|
||
|
//
|
||
|
|
||
|
if (hArchive) {
|
||
|
if (!ArchiveRegistryValue(hArchive, lpKeyName, lpValueName,
|
||
|
dwType, dwDataLength, lpData)) {
|
||
|
DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: ArchiveRegistryValue returned false.")));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LocalFree (lpData);
|
||
|
lpData = NULL;
|
||
|
|
||
|
}
|
||
|
|
||
|
bResult = TRUE;
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
//
|
||
|
// Finished
|
||
|
//
|
||
|
|
||
|
if ( !bResult )
|
||
|
{
|
||
|
CEvents ev(TRUE, EVENT_REGISTRY_TEMPLATE_ERROR);
|
||
|
ev.AddArg(lpRegistry ? lpRegistry : TEXT("")); ev.AddArgWin32Error( xe ); ev.Report();
|
||
|
}
|
||
|
|
||
|
DebugMsg((DM_VERBOSE, TEXT("ParseRegistryFile: Leaving.")));
|
||
|
if (lpData) {
|
||
|
LocalFree (lpData);
|
||
|
}
|
||
|
if ( hFile != INVALID_HANDLE_VALUE ) {
|
||
|
CloseHandle (hFile);
|
||
|
}
|
||
|
if ( lpKeyName ) {
|
||
|
LocalFree (lpKeyName);
|
||
|
}
|
||
|
if ( lpValueName ) {
|
||
|
LocalFree (lpValueName);
|
||
|
}
|
||
|
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// ProcessRegistryValue()
|
||
|
//
|
||
|
// Purpose: Callback passed to ParseRegistryFile from ProcessRegistryFiles. Invokes AddRegHashEntry
|
||
|
// with appropriate parameters depending on the registry policy settings.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// pUnused - Not used. It si there only to conform to the signature
|
||
|
// expected by ParseRegistryFile.
|
||
|
// lpKeyName - registry key name
|
||
|
// lpValueName - Registry value name
|
||
|
// dwType - Registry value type
|
||
|
// dwDataLength - Length of registry value data.
|
||
|
// lpData - Regsitry value data
|
||
|
// *pwszGPO - GPO associated with this registry setting
|
||
|
// *pwszSOM - SOM associated with the GPO
|
||
|
// *pHashTable - Hash table containing registry policy data for a policy target.
|
||
|
//
|
||
|
// Return: TRUE if successful
|
||
|
// FALSE if an error occurs
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
BOOL ProcessRegistryValue ( void* pUnused,
|
||
|
LPTSTR lpKeyName,
|
||
|
LPTSTR lpValueName,
|
||
|
DWORD dwType,
|
||
|
DWORD dwDataLength,
|
||
|
LPBYTE lpData,
|
||
|
WCHAR *pwszGPO,
|
||
|
WCHAR *pwszSOM,
|
||
|
REGHASHTABLE *pHashTable)
|
||
|
{
|
||
|
BOOL bLoggingOk = TRUE;
|
||
|
|
||
|
//
|
||
|
// Special case some values
|
||
|
//
|
||
|
|
||
|
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**del."), 6, lpValueName, 6) == 2)
|
||
|
{
|
||
|
LPTSTR lpRealValueName = lpValueName + 6;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Delete one specific value
|
||
|
//
|
||
|
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
|
||
|
lpRealValueName, 0, 0, NULL,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
}
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**delvals."), 10, lpValueName, 10) == 2)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Delete all values in the destination key
|
||
|
//
|
||
|
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEALLVALUES, lpKeyName,
|
||
|
NULL, 0, 0, NULL,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
|
||
|
}
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**DeleteValues"), 14, lpValueName, 14) == 2)
|
||
|
{
|
||
|
TCHAR szValueName[MAX_PATH];
|
||
|
LPTSTR lpName, lpNameTemp;
|
||
|
|
||
|
lpName = (LPTSTR)lpData;
|
||
|
|
||
|
while (*lpName) {
|
||
|
|
||
|
lpNameTemp = szValueName;
|
||
|
|
||
|
while (*lpName && *lpName == TEXT(' ')) {
|
||
|
lpName++;
|
||
|
}
|
||
|
|
||
|
while (*lpName && *lpName != TEXT(';')) {
|
||
|
*lpNameTemp++ = *lpName++;
|
||
|
}
|
||
|
|
||
|
*lpNameTemp= TEXT('\0');
|
||
|
|
||
|
while (*lpName == TEXT(';')) {
|
||
|
lpName++;
|
||
|
}
|
||
|
|
||
|
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
|
||
|
szValueName, 0, 0, NULL,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**DeleteKeys"), 12, lpValueName, 12) == 2)
|
||
|
{
|
||
|
TCHAR szKeyName[MAX_KEYNAME_SIZE];
|
||
|
LPTSTR lpName, lpNameTemp, lpEnd;
|
||
|
|
||
|
lpName = (LPTSTR)lpData;
|
||
|
|
||
|
while (*lpName) {
|
||
|
|
||
|
szKeyName[0] = TEXT('\0');
|
||
|
lpNameTemp = szKeyName;
|
||
|
|
||
|
while (*lpName && *lpName == TEXT(' ')) {
|
||
|
lpName++;
|
||
|
}
|
||
|
|
||
|
while (*lpName && *lpName != TEXT(';')) {
|
||
|
*lpNameTemp++ = *lpName++;
|
||
|
}
|
||
|
|
||
|
*lpNameTemp= TEXT('\0');
|
||
|
|
||
|
while (*lpName == TEXT(';')) {
|
||
|
lpName++;
|
||
|
}
|
||
|
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEKEY, lpKeyName,
|
||
|
NULL, 0, 0, NULL,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
}
|
||
|
}
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**soft."), 7, lpValueName, 7) == 2)
|
||
|
{
|
||
|
//
|
||
|
// In planning mode we will assume the value does not exist in the target computer.
|
||
|
// Therefore, we set it if no value exists in the hash table.
|
||
|
//
|
||
|
// Soft add is dealt with differently in planning mode vs. diag mode.
|
||
|
// In diag mode, check is done while processing policy and it is logged as a add value
|
||
|
// if the key doesn't exist.
|
||
|
// In planning mode, key is not supposed to exist beforehand and the hash table itself is
|
||
|
// used to determine whether to add the key or not.
|
||
|
|
||
|
|
||
|
LPTSTR lpRealValueName = lpValueName + 7;
|
||
|
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_SOFTADDVALUE, lpKeyName,
|
||
|
lpRealValueName, dwType, dwDataLength, lpData,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
|
||
|
}
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**SecureKey"), 11, lpValueName, 11) == 2)
|
||
|
{
|
||
|
// There is nothing to do here.
|
||
|
} else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**Comment:"), 10, lpValueName, 10) == 2)
|
||
|
{
|
||
|
//
|
||
|
// Comment - can be ignored
|
||
|
//
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// AddRegHashEntry needs to log a key being logged but no values.
|
||
|
//
|
||
|
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_ADDVALUE, lpKeyName,
|
||
|
lpValueName, dwType, dwDataLength, lpData,
|
||
|
pwszGPO, pwszSOM, TEXT(""), TRUE );
|
||
|
}
|
||
|
|
||
|
return bLoggingOk;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// ResetRegKeySecurity
|
||
|
//
|
||
|
// Purpose: Resets the security on a user's key
|
||
|
//
|
||
|
// Parameters: hKeyRoot - Handle to the root of the hive
|
||
|
// lpKeyName - Subkey name
|
||
|
//
|
||
|
//
|
||
|
// Return: TRUE if successful
|
||
|
// FALSE if an error occurs
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
BOOL ResetRegKeySecurity (HKEY hKeyRoot, LPTSTR lpKeyName)
|
||
|
{
|
||
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
||
|
DWORD dwSize = 0;
|
||
|
LONG lResult;
|
||
|
HKEY hSubKey;
|
||
|
XLastError xe;
|
||
|
|
||
|
|
||
|
RegGetKeySecurity(hKeyRoot, DACL_SECURITY_INFORMATION, pSD, &dwSize);
|
||
|
|
||
|
if (!dwSize) {
|
||
|
DebugMsg((DM_WARNING, TEXT("ResetRegKeySecurity: RegGetKeySecurity returned 0")));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pSD = LocalAlloc (LPTR, dwSize);
|
||
|
|
||
|
if (!pSD) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ResetRegKeySecurity: Failed to allocate memory")));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
lResult = RegGetKeySecurity(hKeyRoot, DACL_SECURITY_INFORMATION, pSD, &dwSize);
|
||
|
if (lResult != ERROR_SUCCESS) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ResetRegKeySecurity: Failed to query key security with %d"),
|
||
|
lResult));
|
||
|
LocalFree (pSD);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
lResult = RegOpenKeyEx(hKeyRoot,
|
||
|
lpKeyName,
|
||
|
0,
|
||
|
WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
|
||
|
&hSubKey);
|
||
|
|
||
|
if (lResult != ERROR_SUCCESS) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ResetRegKeySecurity: Failed to open sub key with %d"),
|
||
|
lResult));
|
||
|
LocalFree (pSD);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
lResult = RegSetKeySecurity (hSubKey, DACL_SECURITY_INFORMATION, pSD);
|
||
|
|
||
|
RegCloseKey (hSubKey);
|
||
|
LocalFree (pSD);
|
||
|
|
||
|
if (lResult != ERROR_SUCCESS) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ResetRegKeySecure: Failed to set security, error = %d"), lResult));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// SetRegistryValue()
|
||
|
//
|
||
|
// Purpose: Callback from ParseRegistryFile that sets
|
||
|
// registry policies
|
||
|
//
|
||
|
// Parameters: lpGPOInfo - GPO Information
|
||
|
// lpKeyName - Key name
|
||
|
// lpValueName - Value name
|
||
|
// dwType - Registry data type
|
||
|
// lpData - Registry data
|
||
|
// pwszGPO - Gpo
|
||
|
// pwszSOM - Sdou that the Gpo is linked to
|
||
|
// pHashTable - Hash table for registry keys
|
||
|
//
|
||
|
// Return: TRUE if successful
|
||
|
// FALSE if an error occurs
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
BOOL SetRegistryValue (LPGPOINFO lpGPOInfo, LPTSTR lpKeyName,
|
||
|
LPTSTR lpValueName, DWORD dwType,
|
||
|
DWORD dwDataLength, LPBYTE lpData,
|
||
|
WCHAR *pwszGPO,
|
||
|
WCHAR *pwszSOM, REGHASHTABLE *pHashTable)
|
||
|
{
|
||
|
DWORD dwDisp;
|
||
|
HKEY hSubKey;
|
||
|
LONG lResult;
|
||
|
BOOL bLoggingOk = TRUE;
|
||
|
BOOL bRsopLogging = (pHashTable != NULL); // Is diagnostic mode Rsop logging enabled ?
|
||
|
BOOL bUseValueName = FALSE;
|
||
|
BOOL bRegOpSuccess = TRUE;
|
||
|
XLastError xe;
|
||
|
|
||
|
//
|
||
|
// Special case some values
|
||
|
//
|
||
|
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**del."), 6, lpValueName, 6) == 2)
|
||
|
{
|
||
|
LPTSTR lpRealValueName = lpValueName + 6;
|
||
|
|
||
|
//
|
||
|
// Delete one specific value
|
||
|
//
|
||
|
|
||
|
lResult = RegOpenKeyEx (lpGPOInfo->hKeyRoot,
|
||
|
lpKeyName, 0, KEY_WRITE, &hSubKey);
|
||
|
|
||
|
if (lResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
lResult = RegDeleteValue(hSubKey, lpRealValueName);
|
||
|
|
||
|
if ((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND))
|
||
|
{
|
||
|
DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Deleted value <%s>."),
|
||
|
lpRealValueName));
|
||
|
if (lpGPOInfo->dwFlags & GP_VERBOSE) {
|
||
|
CEvents ev(FALSE, EVENT_DELETED_VALUE);
|
||
|
ev.AddArg(lpRealValueName); ev.Report();
|
||
|
}
|
||
|
|
||
|
if ( bRsopLogging ) {
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
|
||
|
lpRealValueName, 0, 0, NULL,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
if (!bLoggingOk) {
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEVALUE <%s>."), lpRealValueName));
|
||
|
pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: Failed to delete value <%s> with %d"),
|
||
|
lpRealValueName, lResult));
|
||
|
xe = lResult;
|
||
|
CEvents ev(TRUE, EVENT_FAIL_DELETE_VALUE);
|
||
|
ev.AddArg(lpRealValueName); ev.AddArgWin32Error(lResult); ev.Report();
|
||
|
bRegOpSuccess = FALSE;
|
||
|
}
|
||
|
|
||
|
RegCloseKey (hSubKey);
|
||
|
}
|
||
|
else if (lResult == ERROR_FILE_NOT_FOUND) {
|
||
|
|
||
|
//
|
||
|
// Log into rsop even if the key is not found
|
||
|
//
|
||
|
|
||
|
if ( bRsopLogging ) {
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
|
||
|
lpRealValueName, 0, 0, NULL,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
if (!bLoggingOk) {
|
||
|
pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEVALUE (notfound) <%s>."), lpRealValueName));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**delvals."), 10, lpValueName, 10) == 2)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Delete all values in the destination key
|
||
|
//
|
||
|
lResult = RegOpenKeyEx (lpGPOInfo->hKeyRoot,
|
||
|
lpKeyName, 0, KEY_WRITE | KEY_READ, &hSubKey);
|
||
|
|
||
|
if (lResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
if (!bRsopLogging)
|
||
|
bRegOpSuccess = DeleteAllValues(hSubKey);
|
||
|
else
|
||
|
bRegOpSuccess = RsopDeleteAllValues(hSubKey, pHashTable, lpKeyName,
|
||
|
pwszGPO, pwszSOM, lpValueName, &bLoggingOk );
|
||
|
|
||
|
DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Deleted all values in <%s>."),
|
||
|
lpKeyName));
|
||
|
RegCloseKey (hSubKey);
|
||
|
|
||
|
if (!bRegOpSuccess) {
|
||
|
xe = GetLastError();
|
||
|
}
|
||
|
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: DeleteAllvalues finished for %s. bRegOpSuccess = %s, bLoggingOk = %s."),
|
||
|
lpKeyName, (bRegOpSuccess ? TEXT("TRUE") : TEXT("FALSE")), (bLoggingOk ? TEXT("TRUE") : TEXT("FALSE"))));
|
||
|
|
||
|
}
|
||
|
else if (lResult == ERROR_FILE_NOT_FOUND) {
|
||
|
|
||
|
//
|
||
|
// Log into rsop even if the key is not found
|
||
|
// as just deleteallvalues
|
||
|
//
|
||
|
|
||
|
if ( bRsopLogging ) {
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEALLVALUES, lpKeyName,
|
||
|
NULL, 0, 0, NULL,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
|
||
|
if (!bLoggingOk) {
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEALLVALUES (notfound) key - <%s>, value <%s>."), lpKeyName, lpValueName));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**DeleteValues"), 14, lpValueName, 14) == 2)
|
||
|
{
|
||
|
TCHAR szValueName[MAX_PATH];
|
||
|
LPTSTR lpName, lpNameTemp;
|
||
|
LONG lKeyResult;
|
||
|
|
||
|
//
|
||
|
// Delete the values (semi-colon separated)
|
||
|
//
|
||
|
|
||
|
lKeyResult = RegOpenKeyEx (lpGPOInfo->hKeyRoot,
|
||
|
lpKeyName, 0, KEY_WRITE, &hSubKey);
|
||
|
|
||
|
lpName = (LPTSTR)lpData;
|
||
|
|
||
|
while (*lpName) {
|
||
|
|
||
|
lpNameTemp = szValueName;
|
||
|
|
||
|
while (*lpName && *lpName == TEXT(' ')) {
|
||
|
lpName++;
|
||
|
}
|
||
|
|
||
|
while (*lpName && *lpName != TEXT(';')) {
|
||
|
*lpNameTemp++ = *lpName++;
|
||
|
}
|
||
|
|
||
|
*lpNameTemp= TEXT('\0');
|
||
|
|
||
|
while (*lpName == TEXT(';')) {
|
||
|
lpName++;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (lKeyResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
lResult = RegDeleteValue (hSubKey, szValueName);
|
||
|
|
||
|
if ((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND))
|
||
|
{
|
||
|
DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Deleted value <%s>."),
|
||
|
szValueName));
|
||
|
if (lpGPOInfo->dwFlags & GP_VERBOSE) {
|
||
|
CEvents ev(FALSE, EVENT_DELETED_VALUE);
|
||
|
ev.AddArg(szValueName); ev.Report();
|
||
|
}
|
||
|
|
||
|
if ( bRsopLogging ) {
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
|
||
|
szValueName, 0, 0, NULL,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
|
||
|
if (!bLoggingOk) {
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEVALUE value <%s>."), szValueName));
|
||
|
pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: Failed to delete value <%s> with %d"),
|
||
|
szValueName, lResult));
|
||
|
CEvents ev(TRUE, EVENT_FAIL_DELETE_VALUE);
|
||
|
ev.AddArg(szValueName); ev.AddArgWin32Error(lResult); ev.Report();
|
||
|
xe = lResult;
|
||
|
bRegOpSuccess = FALSE;
|
||
|
}
|
||
|
}
|
||
|
else if (lKeyResult == ERROR_FILE_NOT_FOUND) {
|
||
|
if ( bRsopLogging ) {
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
|
||
|
szValueName, 0, 0, NULL,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
|
||
|
if (!bLoggingOk) {
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEVALUE value (not found case) <%s>."), szValueName));
|
||
|
pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if (lKeyResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
RegCloseKey (hSubKey);
|
||
|
}
|
||
|
}
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**DeleteKeys"), 12, lpValueName, 12) == 2)
|
||
|
{
|
||
|
TCHAR szKeyName[MAX_KEYNAME_SIZE];
|
||
|
LPTSTR lpName, lpNameTemp, lpEnd;
|
||
|
|
||
|
//
|
||
|
// Delete keys
|
||
|
//
|
||
|
|
||
|
lpName = (LPTSTR)lpData;
|
||
|
|
||
|
while (*lpName) {
|
||
|
|
||
|
szKeyName[0] = TEXT('\0');
|
||
|
lpNameTemp = szKeyName;
|
||
|
|
||
|
while (*lpName && *lpName == TEXT(' ')) {
|
||
|
lpName++;
|
||
|
}
|
||
|
|
||
|
while (*lpName && *lpName != TEXT(';')) {
|
||
|
*lpNameTemp++ = *lpName++;
|
||
|
}
|
||
|
|
||
|
*lpNameTemp= TEXT('\0');
|
||
|
|
||
|
while (*lpName == TEXT(';')) {
|
||
|
lpName++;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (RegDelnode (lpGPOInfo->hKeyRoot,
|
||
|
szKeyName))
|
||
|
{
|
||
|
DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Deleted key <%s>."),
|
||
|
szKeyName));
|
||
|
if (lpGPOInfo->dwFlags & GP_VERBOSE) {
|
||
|
CEvents ev(FALSE, EVENT_DELETED_KEY);
|
||
|
ev.AddArg(szKeyName); ev.Report();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
bRegOpSuccess = FALSE;
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: RegDelnode for key <%s>."), szKeyName));
|
||
|
}
|
||
|
|
||
|
if ( bRsopLogging ) {
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEKEY, szKeyName,
|
||
|
NULL, 0, 0, NULL,
|
||
|
pwszGPO, pwszSOM, lpValueName, TRUE );
|
||
|
if (!bLoggingOk) {
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEKEY <%s>."), szKeyName));
|
||
|
pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**soft."), 7, lpValueName, 7) == 2)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// "soft" value, only set this if it doesn't already
|
||
|
// exist in destination
|
||
|
//
|
||
|
|
||
|
lResult = RegOpenKeyEx (lpGPOInfo->hKeyRoot,
|
||
|
lpKeyName, 0, KEY_QUERY_VALUE, &hSubKey);
|
||
|
|
||
|
if (lResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
TCHAR TmpValueData[MAX_PATH+1];
|
||
|
DWORD dwSize=sizeof(TmpValueData);
|
||
|
|
||
|
lResult = RegQueryValueEx(hSubKey, lpValueName + 7,
|
||
|
NULL,NULL,(LPBYTE) TmpValueData,
|
||
|
&dwSize);
|
||
|
|
||
|
RegCloseKey (hSubKey);
|
||
|
|
||
|
if (lResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
lpValueName += 7;
|
||
|
bUseValueName = TRUE;
|
||
|
goto SetValue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**SecureKey"), 11, lpValueName, 11) == 2)
|
||
|
{
|
||
|
//
|
||
|
// Secure / unsecure a key (user only)
|
||
|
//
|
||
|
if (!(lpGPOInfo->dwFlags & GP_MACHINE))
|
||
|
{
|
||
|
if (*((LPDWORD)lpData) == 1)
|
||
|
{
|
||
|
DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Securing key <%s>."),
|
||
|
lpKeyName));
|
||
|
bRegOpSuccess = MakeRegKeySecure(lpGPOInfo->hToken, lpGPOInfo->hKeyRoot, lpKeyName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Unsecuring key <%s>."),
|
||
|
lpKeyName));
|
||
|
|
||
|
bRegOpSuccess = ResetRegKeySecurity (lpGPOInfo->hKeyRoot, lpKeyName);
|
||
|
}
|
||
|
|
||
|
if (!bRegOpSuccess) {
|
||
|
xe = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("**Comment:"), 10, lpValueName, 10) == 2)
|
||
|
{
|
||
|
//
|
||
|
// Comment - can be ignored
|
||
|
//
|
||
|
|
||
|
DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Found comment %s."),
|
||
|
(lpValueName+10)));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetValue:
|
||
|
//
|
||
|
// Save registry value
|
||
|
//
|
||
|
|
||
|
lResult = RegCreateKeyEx (lpGPOInfo->hKeyRoot,
|
||
|
lpKeyName, 0, NULL, REG_OPTION_NON_VOLATILE,
|
||
|
KEY_WRITE, NULL, &hSubKey, &dwDisp);
|
||
|
|
||
|
if (lResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
|
||
|
if ((dwType == REG_NONE) && (dwDataLength == 0) &&
|
||
|
(*lpValueName == L'\0'))
|
||
|
{
|
||
|
lResult = ERROR_SUCCESS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lResult = RegSetValueEx (hSubKey, lpValueName, 0, dwType,
|
||
|
lpData, dwDataLength);
|
||
|
}
|
||
|
|
||
|
if ( bRsopLogging ) {
|
||
|
bLoggingOk = AddRegHashEntry( pHashTable, REG_ADDVALUE, lpKeyName,
|
||
|
lpValueName, dwType, dwDataLength, lpData,
|
||
|
pwszGPO, pwszSOM, bUseValueName ? lpValueName : TEXT(""), TRUE );
|
||
|
if (!bLoggingOk) {
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_ADDVALUE key <%s>, value <%s>."), lpKeyName, lpValueName));
|
||
|
pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
RegCloseKey (hSubKey);
|
||
|
|
||
|
if (lResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
switch (dwType) {
|
||
|
case REG_SZ:
|
||
|
case REG_EXPAND_SZ:
|
||
|
DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: %s => %s [OK]"),
|
||
|
lpValueName, (LPTSTR)lpData));
|
||
|
if (lpGPOInfo->dwFlags & GP_VERBOSE) {
|
||
|
CEvents ev(FALSE, EVENT_SET_STRING_VALUE);
|
||
|
ev.AddArg(lpValueName); ev.AddArg((LPTSTR)lpData); ev.Report();
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case REG_DWORD:
|
||
|
DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: %s => %d [OK]"),
|
||
|
lpValueName, *((LPDWORD)lpData)));
|
||
|
if (lpGPOInfo->dwFlags & GP_VERBOSE) {
|
||
|
CEvents ev(FALSE, EVENT_SET_DWORD_VALUE);
|
||
|
ev.AddArg(lpValueName); ev.AddArg((DWORD)*lpData); ev.Report();
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case REG_NONE:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: %s was set successfully"),
|
||
|
lpValueName));
|
||
|
if (lpGPOInfo->dwFlags & GP_VERBOSE) {
|
||
|
CEvents ev(FALSE, EVENT_SET_UNKNOWN_VALUE);
|
||
|
ev.AddArg(lpValueName); ev.Report();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("Control Panel\\Colors"), 20, lpKeyName, 20) == 2) {
|
||
|
lpGPOInfo->dwFlags |= GP_REGPOLICY_CPANEL;
|
||
|
|
||
|
} else if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
||
|
TEXT("Control Panel\\Desktop"), 21, lpKeyName, 21) == 2) {
|
||
|
lpGPOInfo->dwFlags |= GP_REGPOLICY_CPANEL;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: Failed to set value <%s> with %d"),
|
||
|
lpValueName, lResult));
|
||
|
xe = lResult;
|
||
|
CEvents ev(TRUE, EVENT_FAILED_SET);
|
||
|
ev.AddArg(lpValueName); ev.AddArgWin32Error(lResult); ev.Report();
|
||
|
bRegOpSuccess = FALSE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DebugMsg((DM_WARNING, TEXT("SetRegistryValue: Failed to open key <%s> with %d"),
|
||
|
lpKeyName, lResult));
|
||
|
xe = lResult;
|
||
|
CEvents ev(TRUE, EVENT_FAILED_CREATE);
|
||
|
ev.AddArg(lpKeyName); ev.AddArgWin32Error(lResult); ev.Report();
|
||
|
bRegOpSuccess = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bLoggingOk && bRegOpSuccess;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// ProcessGPORegistryPolicy()
|
||
|
//
|
||
|
// Purpose: Proceses GPO registry policy
|
||
|
//
|
||
|
// Parameters: lpGPOInfo - GPO information
|
||
|
// pChangedGPOList - Link list of changed GPOs
|
||
|
//
|
||
|
// Notes: This function is called in the context of
|
||
|
// local system, which allows us to create the
|
||
|
// directory, write to the file etc.
|
||
|
//
|
||
|
// Return: TRUE if successful
|
||
|
// FALSE if an error occurs
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
BOOL ProcessGPORegistryPolicy (LPGPOINFO lpGPOInfo,
|
||
|
PGROUP_POLICY_OBJECT pChangedGPOList, HRESULT *phrRsopLogging)
|
||
|
{
|
||
|
PGROUP_POLICY_OBJECT lpGPO;
|
||
|
TCHAR szPath[MAX_PATH];
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
TCHAR szKeyName[100];
|
||
|
LPTSTR lpEnd, lpGPOComment;
|
||
|
HANDLE hFile;
|
||
|
DWORD dwTemp, dwBytesWritten;
|
||
|
REGHASHTABLE *pHashTable = NULL;
|
||
|
WIN32_FIND_DATA findData;
|
||
|
ADMFILEINFO *pAdmFileCache = NULL;
|
||
|
XLastError xe;
|
||
|
|
||
|
//
|
||
|
// Get the path name to the appropriate profile
|
||
|
//
|
||
|
|
||
|
*phrRsopLogging = S_OK;
|
||
|
|
||
|
szPath[0] = TEXT('\0');
|
||
|
dwTemp = ARRAYSIZE(szPath);
|
||
|
|
||
|
if (lpGPOInfo->dwFlags & GP_MACHINE) {
|
||
|
GetAllUsersProfileDirectoryEx(szPath, &dwTemp, TRUE);
|
||
|
} else {
|
||
|
GetUserProfileDirectory(lpGPOInfo->hToken, szPath, &dwTemp);
|
||
|
}
|
||
|
|
||
|
if (szPath[0] == TEXT('\0')) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Failed to get path to profile root")));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Tack on the archive file name
|
||
|
//
|
||
|
|
||
|
DmAssert( lstrlen(szPath) + lstrlen(TEXT("\\ntuser.pol")) < MAX_PATH );
|
||
|
|
||
|
lstrcat (szPath, TEXT("\\ntuser.pol"));
|
||
|
|
||
|
|
||
|
//
|
||
|
// Delete any existing policies
|
||
|
//
|
||
|
|
||
|
if (!ResetPolicies (lpGPOInfo, szPath)) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: ResetPolicies failed.")));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Delete the old archive file
|
||
|
//
|
||
|
|
||
|
SetFileAttributes (szPath, FILE_ATTRIBUTE_NORMAL);
|
||
|
DeleteFile (szPath);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Recreate the archive file
|
||
|
//
|
||
|
|
||
|
hFile = CreateFile (szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_FLAG_SEQUENTIAL_SCAN,
|
||
|
NULL);
|
||
|
|
||
|
|
||
|
if (hFile == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Failed to create archive file with %d"),
|
||
|
GetLastError()));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set the header information in the archive file
|
||
|
//
|
||
|
|
||
|
dwTemp = REGFILE_SIGNATURE;
|
||
|
|
||
|
if (!WriteFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != sizeof(dwTemp))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Failed to write signature with %d"),
|
||
|
GetLastError()));
|
||
|
CloseHandle (hFile);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
dwTemp = REGISTRY_FILE_VERSION;
|
||
|
|
||
|
if (!WriteFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesWritten, NULL) ||
|
||
|
dwBytesWritten != sizeof(dwTemp))
|
||
|
{
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Failed to write version number with %d"),
|
||
|
GetLastError()));
|
||
|
CloseHandle (hFile);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( lpGPOInfo->pWbemServices ) {
|
||
|
|
||
|
//
|
||
|
// If Rsop logging is enabled, setup hash table
|
||
|
//
|
||
|
|
||
|
pHashTable = AllocHashTable();
|
||
|
if ( pHashTable == NULL ) {
|
||
|
CloseHandle (hFile);
|
||
|
*phrRsopLogging = HRESULT_FROM_WIN32(GetLastError());
|
||
|
xe = GetLastError();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now loop through the GPOs applying the registry.pol files
|
||
|
//
|
||
|
|
||
|
lpGPO = pChangedGPOList;
|
||
|
|
||
|
while ( lpGPO ) {
|
||
|
|
||
|
//
|
||
|
// Add the source GPO comment
|
||
|
//
|
||
|
|
||
|
lpGPOComment = (LPTSTR) LocalAlloc (LPTR, (lstrlen(lpGPO->lpDisplayName) + 25) * sizeof(TCHAR));
|
||
|
|
||
|
if (lpGPOComment) {
|
||
|
|
||
|
lstrcpy (szKeyName, TEXT("Software\\Policies\\Microsoft\\Windows\\Group Policy Objects\\"));
|
||
|
lstrcat (szKeyName, lpGPO->szGPOName);
|
||
|
|
||
|
lstrcpy (lpGPOComment, TEXT("**Comment:GPO Name: "));
|
||
|
lstrcat (lpGPOComment, lpGPO->lpDisplayName);
|
||
|
|
||
|
if (!ArchiveRegistryValue(hFile, szKeyName, lpGPOComment, REG_SZ, 0, NULL)) {
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: ArchiveRegistryValue returned false.")));
|
||
|
}
|
||
|
|
||
|
LocalFree (lpGPOComment);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Build the path to registry.pol
|
||
|
//
|
||
|
|
||
|
DmAssert( lstrlen(lpGPO->lpFileSysPath) + lstrlen(c_szRegistryPol) + 1 < MAX_PATH );
|
||
|
|
||
|
lstrcpy (szBuffer, lpGPO->lpFileSysPath);
|
||
|
lpEnd = CheckSlash (szBuffer);
|
||
|
lstrcpy (lpEnd, c_szRegistryPol);
|
||
|
|
||
|
if (!ParseRegistryFile (lpGPOInfo, szBuffer, SetRegistryValue, hFile,
|
||
|
lpGPO->lpDSPath, lpGPO->lpLink, pHashTable, FALSE )) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: ParseRegistryFile failed.")));
|
||
|
CloseHandle (hFile);
|
||
|
FreeHashTable( pHashTable );
|
||
|
// no logging is done in any case
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( lpGPOInfo->pWbemServices ) {
|
||
|
|
||
|
//
|
||
|
// Log Adm data
|
||
|
//
|
||
|
|
||
|
HANDLE hFindFile;
|
||
|
WIN32_FILE_ATTRIBUTE_DATA attrData;
|
||
|
DWORD dwFilePathSize = lstrlen( lpGPO->lpFileSysPath );
|
||
|
TCHAR szComputerName[3*MAX_COMPUTERNAME_LENGTH + 1];
|
||
|
DWORD dwSize;
|
||
|
|
||
|
dwSize = 3*MAX_COMPUTERNAME_LENGTH + 1;
|
||
|
if (!GetComputerName(szComputerName, &dwSize)) {
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Couldn't get the computer Name with error %d."), GetLastError()));
|
||
|
szComputerName[0] = TEXT('\0');
|
||
|
}
|
||
|
|
||
|
|
||
|
dwSize = dwFilePathSize + MAX_PATH;
|
||
|
|
||
|
WCHAR *pwszEnd;
|
||
|
WCHAR *pwszFile = (WCHAR *) LocalAlloc( LPTR, dwSize * sizeof(WCHAR) );
|
||
|
|
||
|
if ( pwszFile == 0 ) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: ParseRegistryFile failed to allocate memory.")));
|
||
|
CloseHandle (hFile);
|
||
|
FreeHashTable( pHashTable );
|
||
|
// no logging is done in any case
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
lstrcpy( pwszFile, lpGPO->lpFileSysPath );
|
||
|
|
||
|
//
|
||
|
// Strip off trailing 'machine' or 'user'
|
||
|
//
|
||
|
|
||
|
pwszEnd = pwszFile + lstrlen( pwszFile );
|
||
|
|
||
|
if ( lpGPOInfo->dwFlags & GP_MACHINE )
|
||
|
pwszEnd -= 7; // length of "machine"
|
||
|
else
|
||
|
pwszEnd -= 4; // length of "user"
|
||
|
|
||
|
lstrcpy( pwszEnd, L"Adm\\*.adm");
|
||
|
|
||
|
//
|
||
|
// Remember end point so that the actual Adm filename can be
|
||
|
// easily concatenated.
|
||
|
//
|
||
|
|
||
|
pwszEnd = pwszEnd + lstrlen( L"Adm\\" );
|
||
|
|
||
|
//
|
||
|
// Enumerate all Adm files
|
||
|
//
|
||
|
|
||
|
hFindFile = FindFirstFile( pwszFile, &findData);
|
||
|
|
||
|
if ( hFindFile != INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
if ( !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
||
|
{
|
||
|
DmAssert( dwFilePathSize + lstrlen(findData.cFileName) + lstrlen( L"\\Adm\\" ) < dwSize );
|
||
|
|
||
|
lstrcpy( pwszEnd, findData.cFileName);
|
||
|
|
||
|
ZeroMemory (&attrData, sizeof(attrData));
|
||
|
|
||
|
if ( GetFileAttributesEx (pwszFile, GetFileExInfoStandard, &attrData ) != 0 ) {
|
||
|
|
||
|
if ( !AddAdmFile( pwszFile, lpGPO->lpDSPath, &attrData.ftLastWriteTime,
|
||
|
szComputerName, &pAdmFileCache ) ) {
|
||
|
DebugMsg((DM_WARNING,
|
||
|
TEXT("ProcessGPORegistryPolicy: AddAdmFile failed.")));
|
||
|
|
||
|
if (pHashTable->hrError == S_OK)
|
||
|
pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
}
|
||
|
} // if findData & file_attr_dir
|
||
|
} while ( FindNextFile(hFindFile, &findData) );// do
|
||
|
|
||
|
FindClose(hFindFile);
|
||
|
|
||
|
} // if hfindfile
|
||
|
|
||
|
LocalFree( pwszFile );
|
||
|
|
||
|
} // if rsoploggingenabled
|
||
|
|
||
|
lpGPO = lpGPO->pNext;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Log registry data to Cimom database
|
||
|
//
|
||
|
|
||
|
if ( lpGPOInfo->pWbemServices ) {
|
||
|
|
||
|
if ( ! LogRegistryRsopData( lpGPOInfo->dwFlags, pHashTable, lpGPOInfo->pWbemServices ) ) {
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Error when logging Registry Rsop data. Continuing.")));
|
||
|
|
||
|
if (pHashTable->hrError == S_OK)
|
||
|
pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
if ( ! LogAdmRsopData( pAdmFileCache, lpGPOInfo->pWbemServices ) ) {
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Error when logging Adm Rsop data. Continuing.")));
|
||
|
|
||
|
if (pHashTable->hrError == S_OK)
|
||
|
pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
*phrRsopLogging = pHashTable->hrError;
|
||
|
}
|
||
|
|
||
|
|
||
|
FreeHashTable( pHashTable );
|
||
|
FreeAdmFileCache( pAdmFileCache );
|
||
|
|
||
|
CloseHandle (hFile);
|
||
|
|
||
|
#if 0
|
||
|
//
|
||
|
// Set the security on the file
|
||
|
//
|
||
|
|
||
|
if (!MakeFileSecure (szPath, 0)) {
|
||
|
DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Failed to set security on the group policy registry file with %d"),
|
||
|
GetLastError()));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// AddAdmFile()
|
||
|
//
|
||
|
// Purpose: Prepends to list of Adm files
|
||
|
//
|
||
|
// Parameters: pwszFile - File path
|
||
|
// pwszGPO - Gpo
|
||
|
// pftWrite - Last write time
|
||
|
// ppAdmFileCache - List of Adm files processed
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
BOOL AddAdmFile( WCHAR *pwszFile, WCHAR *pwszGPO, FILETIME *pftWrite, WCHAR *szComputerName,
|
||
|
ADMFILEINFO **ppAdmFileCache )
|
||
|
{
|
||
|
XPtrLF<WCHAR> xszLongPath;
|
||
|
LPTSTR pwszUNCPath;
|
||
|
|
||
|
DebugMsg((DM_VERBOSE, TEXT("AllocAdmFileInfo: Adding File name <%s> to the Adm list."), pwszFile));
|
||
|
if ((szComputerName) && (*szComputerName) && (!IsUNCPath(pwszFile))) {
|
||
|
xszLongPath = MakePathUNC(pwszFile, szComputerName);
|
||
|
|
||
|
if (!xszLongPath) {
|
||
|
DebugMsg((DM_WARNING, TEXT("AllocAdmFileInfo: Failed to Make the path UNC with error %d."), GetLastError()));
|
||
|
return FALSE;
|
||
|
}
|
||
|
pwszUNCPath = xszLongPath;
|
||
|
}
|
||
|
else
|
||
|
pwszUNCPath = pwszFile;
|
||
|
|
||
|
|
||
|
ADMFILEINFO *pAdmInfo = AllocAdmFileInfo( pwszUNCPath, pwszGPO, pftWrite );
|
||
|
if ( pAdmInfo == NULL )
|
||
|
return FALSE;
|
||
|
|
||
|
pAdmInfo->pNext = *ppAdmFileCache;
|
||
|
*ppAdmFileCache = pAdmInfo;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// FreeAdmFileCache()
|
||
|
//
|
||
|
// Purpose: Frees Adm File list
|
||
|
//
|
||
|
// Parameters: pAdmFileCache - List of Adm files to free
|
||
|
//
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
void FreeAdmFileCache( ADMFILEINFO *pAdmFileCache )
|
||
|
{
|
||
|
ADMFILEINFO *pNext;
|
||
|
|
||
|
while ( pAdmFileCache ) {
|
||
|
pNext = pAdmFileCache->pNext;
|
||
|
FreeAdmFileInfo( pAdmFileCache );
|
||
|
pAdmFileCache = pNext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// AllocAdmFileInfo()
|
||
|
//
|
||
|
// Purpose: Allocates a new struct for ADMFILEINFO
|
||
|
//
|
||
|
// Parameters: pwszFile - File name
|
||
|
// pwszGPO - Gpo
|
||
|
// pftWrite - Last write time
|
||
|
//
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
ADMFILEINFO * AllocAdmFileInfo( WCHAR *pwszFile, WCHAR *pwszGPO, FILETIME *pftWrite )
|
||
|
{
|
||
|
XLastError xe;
|
||
|
|
||
|
ADMFILEINFO *pAdmFileInfo = (ADMFILEINFO *) LocalAlloc( LPTR, sizeof(ADMFILEINFO) );
|
||
|
if ( pAdmFileInfo == NULL ) {
|
||
|
DebugMsg((DM_WARNING, TEXT("AllocAdmFileInfo: Failed to allocate memory.")));
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
pAdmFileInfo->pwszFile = (WCHAR *) LocalAlloc( LPTR, (lstrlen(pwszFile) + 1) * sizeof(WCHAR) );
|
||
|
if ( pAdmFileInfo->pwszFile == NULL ) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("AllocAdmFileInfo: Failed to allocate memory.")));
|
||
|
LocalFree( pAdmFileInfo );
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
pAdmFileInfo->pwszGPO = (WCHAR *) LocalAlloc( LPTR, (lstrlen(pwszGPO) + 1) * sizeof(WCHAR) );
|
||
|
if ( pAdmFileInfo->pwszGPO == NULL ) {
|
||
|
xe = GetLastError();
|
||
|
DebugMsg((DM_WARNING, TEXT("AllocAdmFileInfo: Failed to allocate memory.")));
|
||
|
LocalFree( pAdmFileInfo->pwszFile );
|
||
|
LocalFree( pAdmFileInfo );
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
lstrcpy( pAdmFileInfo->pwszFile, pwszFile );
|
||
|
lstrcpy( pAdmFileInfo->pwszGPO, pwszGPO );
|
||
|
|
||
|
pAdmFileInfo->ftWrite = *pftWrite;
|
||
|
|
||
|
return pAdmFileInfo;
|
||
|
}
|
||
|
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// FreeAdmFileInfo()
|
||
|
//
|
||
|
// Purpose: Deletes a ADMFILEINFO struct
|
||
|
//
|
||
|
// Parameters: pAdmFileInfo - Struct to delete
|
||
|
// pftWrite - Last write time
|
||
|
//
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
void FreeAdmFileInfo( ADMFILEINFO *pAdmFileInfo )
|
||
|
{
|
||
|
if ( pAdmFileInfo ) {
|
||
|
LocalFree( pAdmFileInfo->pwszFile );
|
||
|
LocalFree( pAdmFileInfo->pwszGPO );
|
||
|
LocalFree( pAdmFileInfo );
|
||
|
}
|
||
|
}
|