You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
911 lines
26 KiB
911 lines
26 KiB
//*************************************************************
|
|
//
|
|
// Hash table for registry Rsop data
|
|
//
|
|
// Microsoft Confidential
|
|
// Copyright (c) Microsoft Corporation 1999
|
|
// All rights reserved
|
|
//
|
|
// History: 7-Jun-99 SitaramR Created
|
|
//
|
|
//*************************************************************
|
|
|
|
#include "uenv.h"
|
|
#include "reghash.h"
|
|
#include "rsop.h"
|
|
#include <strsafe.h>
|
|
|
|
REGKEYENTRY * AllocRegKeyEntry( WCHAR *pwszKeyName );
|
|
void FreeRegKeyEntry( REGKEYENTRY *pKeyEntry );
|
|
REGVALUEENTRY *AllocValueEntry( WCHAR *pwszValueName );
|
|
void FreeValueEntry( REGVALUEENTRY *pValueEntry );
|
|
REGDATAENTRY * AllocDataEntry( REGOPERATION opnType,
|
|
DWORD dwType,
|
|
DWORD dwLen,
|
|
BYTE *pData,
|
|
WCHAR *pwszGPO,
|
|
WCHAR *pwszSOM,
|
|
WCHAR *pwszCommand);
|
|
|
|
void FreeDataEntry( REGDATAENTRY *pDataEntry );
|
|
BOOL DeleteRegTree( REGHASHTABLE *pHashTable,
|
|
WCHAR *pwszKeyName,
|
|
WCHAR *pwszGPO,
|
|
WCHAR *pwszSOM,
|
|
WCHAR *szCommand);
|
|
REGKEYENTRY * FindRegKeyEntry( REGHASHTABLE *pHashTable,
|
|
WCHAR *pwszKeyName,
|
|
BOOL bCreate );
|
|
REGVALUEENTRY * FindValueEntry( REGHASHTABLE *pHashTable,
|
|
WCHAR *pwszKeyName,
|
|
WCHAR *pwszValueName,
|
|
BOOL bCreate );
|
|
BOOL AddDataEntry( REGVALUEENTRY *pValueEntry,
|
|
REGOPERATION opnType,
|
|
DWORD dwType,
|
|
DWORD dwLen,
|
|
BYTE *pData,
|
|
WCHAR *pwszGPO,
|
|
WCHAR *pwszSOM,
|
|
WCHAR *pwszCommand);
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Hash Table for registry policies
|
|
// ----------------------------------
|
|
//
|
|
// This hash table is used to log rsop data for registry policies.
|
|
// A hash table entry is created for each registry entry. The registry entry
|
|
// name itself is used to calculate the hash table.
|
|
//
|
|
// Each Registry entry has a link to each of the values modified by policy.
|
|
// These values are in a link list and sorted by the valueNames.
|
|
//
|
|
// Each Value has the list of Data that are being set on the Values. This
|
|
// sorted by the order of execution. The topmost value will contain the final value.
|
|
// The Data entries have fields that mark the value as deleted and the Command
|
|
// associated with the action. To look for the possible commands look in the
|
|
// ParseRegistryFile.
|
|
//
|
|
// Additionally, in the hash table 2 special case values exist.
|
|
// a. **Command Value. The Data under this value will contain all the commands
|
|
// that are executed under this key.
|
|
//
|
|
// b. An ""(Empty ValueName) This valuename represents the modifications happening
|
|
// to the key itself. For example a key can deleted or added..
|
|
//
|
|
// Note:
|
|
// The szCommand that is passed in has to be non NULL but can be an empty string.
|
|
// There is a dependency on it in AddDataEntry and in logger.cpp. There is an Assert
|
|
// for this in AddRegHashEntry
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// AllocHashTable
|
|
//
|
|
// Purpose: Allocates a new hash table
|
|
//
|
|
// Returns: Pointer to hash table
|
|
//
|
|
//*************************************************************
|
|
|
|
REGHASHTABLE * AllocHashTable()
|
|
{
|
|
DWORD i;
|
|
|
|
REGHASHTABLE *pHashTable = (REGHASHTABLE *) LocalAlloc (LPTR, sizeof(REGHASHTABLE));
|
|
|
|
if ( pHashTable == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocHashTable: Failed to alloc hashtable.")));
|
|
return NULL;
|
|
}
|
|
|
|
for ( i=0; i<HASH_TABLE_SIZE; i++) {
|
|
pHashTable->aHashTable[i] = 0;
|
|
}
|
|
|
|
pHashTable->hrError = S_OK;
|
|
|
|
return pHashTable;
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// FreeHashTable
|
|
//
|
|
// Purpose: Deletes a hash table
|
|
//
|
|
// Parameters: pHashTable - Hash table to delete
|
|
//
|
|
//*************************************************************
|
|
|
|
void FreeHashTable( REGHASHTABLE *pHashTable )
|
|
{
|
|
DWORD i;
|
|
|
|
if ( pHashTable == NULL )
|
|
return;
|
|
|
|
for ( i=0; i<HASH_TABLE_SIZE; i++ ) {
|
|
REGKEYENTRY *pKeyEntry = pHashTable->aHashTable[i];
|
|
|
|
while ( pKeyEntry ) {
|
|
REGKEYENTRY *pNext = pKeyEntry->pNext;
|
|
FreeRegKeyEntry( pKeyEntry );
|
|
pKeyEntry = pNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// AllocRegKey
|
|
//
|
|
// Purpose: Allocates a new registry key entry
|
|
//
|
|
// Returns: Pointer to registr key entry
|
|
//
|
|
//*************************************************************
|
|
|
|
REGKEYENTRY * AllocRegKeyEntry( WCHAR *pwszKeyName )
|
|
{
|
|
REGKEYENTRY *pKeyEntry = (REGKEYENTRY *) LocalAlloc (LPTR, sizeof(REGKEYENTRY));
|
|
if ( pKeyEntry == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocRegKeyEntry: Failed to alloc key entry.")));
|
|
return NULL;
|
|
}
|
|
|
|
DWORD dwKeyNameLength = lstrlen(pwszKeyName) + 1;
|
|
pKeyEntry->pwszKeyName = (WCHAR *) LocalAlloc (LPTR, ( dwKeyNameLength ) * sizeof(WCHAR));
|
|
|
|
if ( pKeyEntry->pwszKeyName == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocRegKeyEntry: Failed to alloc key name.")));
|
|
LocalFree( pKeyEntry );
|
|
return NULL;
|
|
}
|
|
|
|
HRESULT hr = StringCchCopy( pKeyEntry->pwszKeyName, dwKeyNameLength, pwszKeyName );
|
|
|
|
if(FAILED(hr)){
|
|
LocalFree( pKeyEntry->pwszKeyName );
|
|
LocalFree( pKeyEntry );
|
|
return NULL;
|
|
}
|
|
|
|
return pKeyEntry;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// FreeRegKeyEntry
|
|
//
|
|
// Purpose: Deletes a registry key entry
|
|
//
|
|
// Parameters: pKeyEntry - Entry to delete
|
|
//
|
|
//*************************************************************
|
|
|
|
void FreeRegKeyEntry( REGKEYENTRY *pKeyEntry )
|
|
{
|
|
REGVALUEENTRY *pValueEntry = NULL;
|
|
|
|
if ( pKeyEntry == NULL )
|
|
return;
|
|
|
|
LocalFree( pKeyEntry->pwszKeyName );
|
|
|
|
pValueEntry = pKeyEntry->pValueList;
|
|
while ( pValueEntry ) {
|
|
REGVALUEENTRY *pNext = pValueEntry->pNext;
|
|
FreeValueEntry( pValueEntry );
|
|
pValueEntry = pNext;
|
|
}
|
|
|
|
LocalFree( pKeyEntry );
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// AllocValueEntry
|
|
//
|
|
// Purpose: Allocates a new value entry
|
|
//
|
|
// Returns: Pointer to value entry
|
|
//
|
|
//*************************************************************
|
|
|
|
REGVALUEENTRY *AllocValueEntry( WCHAR *pwszValueName )
|
|
{
|
|
REGVALUEENTRY *pValueEntry = (REGVALUEENTRY *) LocalAlloc (LPTR, sizeof(REGVALUEENTRY));
|
|
if ( pValueEntry == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocValueEntry: Failed to alloc value entry.")));
|
|
return NULL;
|
|
}
|
|
|
|
DWORD dwValNameLength = lstrlen(pwszValueName) + 1;
|
|
pValueEntry->pwszValueName = (WCHAR *) LocalAlloc (LPTR, ( dwValNameLength ) * sizeof(WCHAR));
|
|
|
|
if ( pValueEntry->pwszValueName == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocValueEntry: Failed to alloc key name.")));
|
|
LocalFree( pValueEntry );
|
|
return NULL;
|
|
}
|
|
|
|
HRESULT hr = StringCchCopy( pValueEntry->pwszValueName, dwValNameLength, pwszValueName );
|
|
|
|
if(FAILED(hr)){
|
|
LocalFree( pValueEntry->pwszValueName );
|
|
LocalFree( pValueEntry );
|
|
return NULL;
|
|
}
|
|
|
|
return pValueEntry;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// FreeValueEntry
|
|
//
|
|
// Purpose: Deletes a value entry
|
|
//
|
|
// Parameters: pValueEntry - Entry to delete
|
|
//
|
|
//*************************************************************
|
|
|
|
void FreeValueEntry( REGVALUEENTRY *pValueEntry )
|
|
{
|
|
REGDATAENTRY *pDataEntry = NULL;
|
|
|
|
if ( pValueEntry == NULL )
|
|
return;
|
|
|
|
LocalFree( pValueEntry->pwszValueName );
|
|
|
|
pDataEntry = pValueEntry->pDataList;
|
|
while ( pDataEntry ) {
|
|
REGDATAENTRY *pNext = pDataEntry->pNext;
|
|
FreeDataEntry( pDataEntry );
|
|
pDataEntry = pNext;
|
|
}
|
|
|
|
LocalFree( pValueEntry );
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// AllocDataEntry
|
|
//
|
|
// Purpose: Allocates a new data entry
|
|
//
|
|
// Returns: Pointer to data entry
|
|
//
|
|
//*************************************************************
|
|
|
|
REGDATAENTRY * AllocDataEntry( REGOPERATION opnType,
|
|
DWORD dwType,
|
|
DWORD dwLen,
|
|
BYTE *pData,
|
|
WCHAR *pwszGPO,
|
|
WCHAR *pwszSOM,
|
|
WCHAR *pwszCommand)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
|
|
REGDATAENTRY *pDataEntry = (REGDATAENTRY *) LocalAlloc (LPTR, sizeof(REGDATAENTRY));
|
|
if ( pDataEntry == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocDataEntry: Failed to alloc data entry.")));
|
|
return NULL;
|
|
}
|
|
|
|
if ( opnType == REG_ADDVALUE )
|
|
pDataEntry->bDeleted = FALSE;
|
|
else
|
|
pDataEntry->bDeleted = TRUE;
|
|
|
|
pDataEntry->bAdmPolicy = FALSE;
|
|
pDataEntry->dwValueType = dwType;
|
|
pDataEntry->dwDataLen = dwLen;
|
|
|
|
if ( pData ) {
|
|
pDataEntry->pData = (BYTE *) LocalAlloc (LPTR, dwLen);
|
|
if ( pDataEntry->pData == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocDataEntry: Failed to alloc data.")));
|
|
goto Exit;
|
|
}
|
|
|
|
CopyMemory( pDataEntry->pData, pData, dwLen );
|
|
}
|
|
|
|
DmAssert( pwszGPO != NULL && pwszSOM != NULL );
|
|
|
|
DWORD dwGPOLength = lstrlen(pwszGPO) + 1;
|
|
pDataEntry->pwszGPO = (WCHAR *) LocalAlloc (LPTR, ( dwGPOLength ) * sizeof(WCHAR));
|
|
|
|
if ( pDataEntry->pwszGPO == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocDataEntry: Failed to alloc Gpo name.")));
|
|
goto Exit;
|
|
}
|
|
|
|
HRESULT hr = StringCchCopy( pDataEntry->pwszGPO, dwGPOLength, pwszGPO );
|
|
|
|
if(FAILED(hr))
|
|
goto Exit;
|
|
|
|
DWORD dwSOMLength = lstrlen(pwszSOM) + 1;
|
|
pDataEntry->pwszSOM = (WCHAR *) LocalAlloc (LPTR, ( dwSOMLength ) * sizeof(WCHAR));
|
|
|
|
if ( pDataEntry->pwszSOM == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocDataEntry: Failed to alloc Sdou name.")));
|
|
goto Exit;
|
|
}
|
|
|
|
hr = StringCchCopy( pDataEntry->pwszSOM, dwSOMLength, pwszSOM );
|
|
|
|
if(FAILED(hr))
|
|
goto Exit;
|
|
|
|
DWORD dwCmdLength = lstrlen(pwszCommand) + 1;
|
|
pDataEntry->pwszCommand = (WCHAR *) LocalAlloc (LPTR, ( dwCmdLength ) * sizeof(WCHAR));
|
|
|
|
if ( pDataEntry->pwszCommand == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocDataEntry: Failed to alloc Sdou name.")));
|
|
goto Exit;
|
|
}
|
|
|
|
hr = StringCchCopy( pDataEntry->pwszCommand, dwCmdLength, pwszCommand );
|
|
|
|
if(FAILED(hr))
|
|
goto Exit;
|
|
|
|
bResult = TRUE;
|
|
|
|
Exit:
|
|
|
|
if ( !bResult ) {
|
|
LocalFree( pDataEntry->pData );
|
|
LocalFree( pDataEntry->pwszGPO );
|
|
LocalFree( pDataEntry->pwszSOM );
|
|
if (pDataEntry->pwszCommand)
|
|
LocalFree(pDataEntry->pwszCommand);
|
|
LocalFree( pDataEntry);
|
|
return NULL;
|
|
}
|
|
|
|
return pDataEntry;
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// FreeDataEntry
|
|
//
|
|
// Purpose: Deletes a data entry
|
|
//
|
|
// Parameters: pDataEntry - Entry to delete
|
|
//
|
|
//*************************************************************
|
|
|
|
void FreeDataEntry( REGDATAENTRY *pDataEntry )
|
|
{
|
|
if ( pDataEntry ) {
|
|
LocalFree( pDataEntry->pData );
|
|
LocalFree( pDataEntry->pwszGPO );
|
|
LocalFree( pDataEntry->pwszSOM );
|
|
LocalFree( pDataEntry);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// Hash
|
|
//
|
|
// Purpose: Maps a key name to a hash bucket
|
|
//
|
|
// Parameters: pwszName - Key name
|
|
//
|
|
// Returns: Hash bucket
|
|
//
|
|
//*************************************************************
|
|
|
|
DWORD Hash( WCHAR *pwszName )
|
|
{
|
|
DWORD dwLen = lstrlen( pwszName );
|
|
DWORD dwHashValue = 0;
|
|
|
|
for ( ; dwLen>0; pwszName++ ) {
|
|
dwHashValue = toupper(*pwszName) + 31 * dwHashValue;
|
|
dwLen--;
|
|
}
|
|
|
|
return dwHashValue % HASH_TABLE_SIZE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// AddRegHashEntry
|
|
//
|
|
// Purpose: Adds a registry key to the hash table
|
|
//
|
|
// Parameters: pwszName - Key name
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL AddRegHashEntry( REGHASHTABLE *pHashTable,
|
|
REGOPERATION opnType,
|
|
WCHAR *pwszKeyName,
|
|
WCHAR *pwszValueName,
|
|
DWORD dwType,
|
|
DWORD dwDataLen,
|
|
BYTE *pData,
|
|
WCHAR *pwszGPO,
|
|
WCHAR *pwszSOM,
|
|
WCHAR *szCommand,
|
|
BOOL bCreateCommand)
|
|
{
|
|
REGVALUEENTRY *pValueEntry = NULL;
|
|
BOOL bResult = FALSE;
|
|
REGKEYENTRY *pKeyEntry=NULL;
|
|
|
|
|
|
switch (opnType) {
|
|
|
|
case REG_DELETEKEY:
|
|
bResult = DeleteRegTree( pHashTable, pwszKeyName, pwszGPO, pwszSOM, szCommand );
|
|
break;
|
|
|
|
case REG_INTERNAL_DELETESINGLEKEY:
|
|
case REG_DELETEALLVALUES:
|
|
|
|
pKeyEntry = FindRegKeyEntry( pHashTable,
|
|
pwszKeyName,
|
|
FALSE );
|
|
if ( pKeyEntry == NULL ) {
|
|
|
|
//
|
|
// Delete all values is similar to policy being disabled and
|
|
// so do nothing.
|
|
//
|
|
|
|
if (opnType == REG_DELETEALLVALUES) {
|
|
bResult = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
// no command entry in this case.
|
|
return TRUE;
|
|
}
|
|
|
|
pValueEntry = pKeyEntry->pValueList;
|
|
while ( pValueEntry ) {
|
|
|
|
if (lstrcmp(pValueEntry->pwszValueName, TEXT("")) != 0) {
|
|
|
|
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, pValueEntry->pwszValueName, -1, STARCOMMAND, -1) != CSTR_EQUAL) {
|
|
|
|
|
|
//
|
|
// Mark the value as deleted
|
|
//
|
|
|
|
bResult = AddDataEntry( pValueEntry, opnType, 0, 0, NULL,
|
|
pwszGPO, pwszSOM, szCommand );
|
|
if ( !bResult )
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
|
|
//
|
|
// Mark the key as deleted
|
|
//
|
|
|
|
if (opnType == REG_INTERNAL_DELETESINGLEKEY) {
|
|
bResult = AddDataEntry( pValueEntry, opnType, 0, 0, NULL,
|
|
pwszGPO, pwszSOM, szCommand );
|
|
if ( !bResult )
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
pValueEntry = pValueEntry->pNext;
|
|
}
|
|
|
|
bResult = TRUE;
|
|
|
|
break;
|
|
|
|
case REG_ADDVALUE:
|
|
case REG_SOFTADDVALUE:
|
|
|
|
//
|
|
// We have to make a value with no name to represent the creation of key itself..
|
|
//
|
|
|
|
pValueEntry = FindValueEntry( pHashTable, pwszKeyName,
|
|
TEXT(""), TRUE );
|
|
if ( pValueEntry == NULL )
|
|
return FALSE;
|
|
|
|
bResult = AddDataEntry( pValueEntry, opnType, 0, 0, NULL,
|
|
pwszGPO, pwszSOM, szCommand );
|
|
|
|
|
|
if (!bResult)
|
|
return FALSE;
|
|
|
|
if ((!pwszValueName) || (!(*pwszValueName)) ||
|
|
(dwDataLen == 0) || (dwType == REG_NONE))
|
|
break;
|
|
|
|
// fall through
|
|
|
|
case REG_DELETEVALUE:
|
|
pValueEntry = FindValueEntry( pHashTable, pwszKeyName,
|
|
pwszValueName, TRUE );
|
|
if ( pValueEntry == NULL )
|
|
return FALSE;
|
|
|
|
|
|
//
|
|
// In case of SOFTADDVALUE the final decision to add the value is made in
|
|
// AddDataEntry
|
|
//
|
|
|
|
bResult = AddDataEntry( pValueEntry, opnType, dwType, dwDataLen, pData,
|
|
pwszGPO, pwszSOM, szCommand );
|
|
|
|
break;
|
|
default:
|
|
DmAssert(FALSE && "Unknown Case Selector for AddRegHashEntry");
|
|
}
|
|
|
|
|
|
DmAssert(szCommand);
|
|
|
|
//
|
|
// If everything succeeded, then log the command if
|
|
// bCreateCommand is true. This is done creating or adding
|
|
// to a value called **Command. This means that this value is not
|
|
// Settable by adm file..
|
|
//
|
|
|
|
if ((bResult) && (bCreateCommand) && (opnType != REG_INTERNAL_DELETESINGLEKEY) && (*szCommand != TEXT('\0'))) {
|
|
pValueEntry = FindValueEntry( pHashTable, pwszKeyName,
|
|
STARCOMMAND, TRUE );
|
|
|
|
if ( pValueEntry == NULL )
|
|
return FALSE;
|
|
|
|
bResult = AddDataEntry( pValueEntry, REG_ADDVALUE, 0,
|
|
sizeof(TCHAR)*(lstrlen(szCommand)+1), (BYTE *)szCommand,
|
|
pwszGPO, pwszSOM, szCommand);
|
|
}
|
|
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// DeleteRegTree
|
|
//
|
|
// Purpose: Deletes a key and all its subkeys
|
|
//
|
|
// Parameters: pHashTable - Hash table
|
|
// pwszKeyName - Key name to delete
|
|
// pwszGPO - Gpo
|
|
// pwszSOM - Sdou that the Gpo is linked to
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL DeleteRegTree( REGHASHTABLE *pHashTable,
|
|
WCHAR *pwszKeyName,
|
|
WCHAR *pwszGPO,
|
|
WCHAR *pwszSOM,
|
|
WCHAR *szCommand)
|
|
{
|
|
DWORD i=0;
|
|
DWORD dwKeyLen = lstrlen( pwszKeyName );
|
|
|
|
for ( i=0; i<HASH_TABLE_SIZE; i++ ) {
|
|
|
|
REGKEYENTRY *pKeyEntry = pHashTable->aHashTable[i];
|
|
while ( pKeyEntry ) {
|
|
|
|
BOOL bAdd = FALSE;
|
|
DWORD dwKeyLen2 = lstrlen(pKeyEntry->pwszKeyName);
|
|
|
|
if ( dwKeyLen2 >= dwKeyLen
|
|
&& CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
|
pKeyEntry->pwszKeyName, dwKeyLen,
|
|
pwszKeyName, dwKeyLen ) == CSTR_EQUAL) {
|
|
|
|
//
|
|
// It's a prefix if length and strings match, or if one
|
|
// string is bigger and there is a '\' at the right place.
|
|
//
|
|
|
|
if ( dwKeyLen2 > dwKeyLen ) {
|
|
|
|
if ( pKeyEntry->pwszKeyName[dwKeyLen] == L'\\' )
|
|
bAdd = TRUE;
|
|
} else
|
|
bAdd = TRUE;
|
|
|
|
if ( bAdd ) {
|
|
BOOL bResult = AddRegHashEntry( pHashTable,
|
|
REG_INTERNAL_DELETESINGLEKEY,
|
|
pKeyEntry->pwszKeyName,
|
|
NULL, 0, 0, NULL,
|
|
pwszGPO, pwszSOM, szCommand, FALSE );
|
|
if ( !bResult )
|
|
return FALSE;
|
|
}
|
|
|
|
} // if dwKeyLen2 >= dwKeyLen
|
|
|
|
pKeyEntry = pKeyEntry->pNext;
|
|
|
|
} // while
|
|
|
|
} // for
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// FindRegKeyEntry
|
|
//
|
|
// Purpose: Looks up a reg key entry in hash table
|
|
//
|
|
// Parameters: pHashTable - Hash table
|
|
// pwszKeyName - Key name to find
|
|
// bCreate - Should key be created if not found ?
|
|
//
|
|
//*************************************************************
|
|
|
|
REGKEYENTRY * FindRegKeyEntry( REGHASHTABLE *pHashTable,
|
|
WCHAR *pwszKeyName,
|
|
BOOL bCreate )
|
|
{
|
|
DWORD dwHashValue = Hash( pwszKeyName );
|
|
REGKEYENTRY *pCurPtr = pHashTable->aHashTable[dwHashValue];
|
|
REGKEYENTRY *pTrailPtr = NULL;
|
|
|
|
while ( pCurPtr != NULL ) {
|
|
|
|
INT iResult = CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
|
pwszKeyName, -1,
|
|
pCurPtr->pwszKeyName, -1 );
|
|
|
|
if ( iResult == CSTR_EQUAL ) {
|
|
return pCurPtr;
|
|
} else if ( iResult == CSTR_LESS_THAN ) {
|
|
|
|
//
|
|
// Keys are in ascending order, so insert if bCreate
|
|
//
|
|
|
|
if ( bCreate ) {
|
|
|
|
REGKEYENTRY *pKeyEntry = AllocRegKeyEntry( pwszKeyName );
|
|
if ( pKeyEntry == NULL )
|
|
return 0;
|
|
|
|
pKeyEntry->pNext = pCurPtr;
|
|
if ( pTrailPtr == NULL )
|
|
pHashTable->aHashTable[dwHashValue] = pKeyEntry;
|
|
else
|
|
pTrailPtr->pNext = pKeyEntry;
|
|
|
|
return pKeyEntry;
|
|
|
|
} else
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Advance down the list
|
|
//
|
|
|
|
pTrailPtr = pCurPtr;
|
|
pCurPtr = pCurPtr->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// End of list or null list case
|
|
//
|
|
|
|
if ( bCreate ) {
|
|
REGKEYENTRY *pKeyEntry = AllocRegKeyEntry( pwszKeyName );
|
|
if ( pKeyEntry == NULL )
|
|
return 0;
|
|
|
|
pKeyEntry->pNext = 0;
|
|
if ( pTrailPtr == NULL )
|
|
pHashTable->aHashTable[dwHashValue] = pKeyEntry;
|
|
else
|
|
pTrailPtr->pNext = pKeyEntry;
|
|
|
|
return pKeyEntry;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// FindValueEntry
|
|
//
|
|
// Purpose: Looks up a value entry in hash table
|
|
//
|
|
// Parameters: pHashTable - Hash table
|
|
// pwszKeyName - Key name to find
|
|
// pwszValueName - Value name to find
|
|
// bCreate - Should key be created if not found ?
|
|
//
|
|
//*************************************************************
|
|
|
|
REGVALUEENTRY * FindValueEntry( REGHASHTABLE *pHashTable,
|
|
WCHAR *pwszKeyName,
|
|
WCHAR *pwszValueName,
|
|
BOOL bCreate )
|
|
{
|
|
REGVALUEENTRY *pCurPtr = NULL;
|
|
REGVALUEENTRY *pTrailPtr = NULL;
|
|
|
|
REGKEYENTRY *pKeyEntry = FindRegKeyEntry( pHashTable, pwszKeyName, bCreate );
|
|
if ( pKeyEntry == NULL )
|
|
return NULL;
|
|
|
|
pCurPtr = pKeyEntry->pValueList;
|
|
pTrailPtr = NULL;
|
|
|
|
while ( pCurPtr != NULL ) {
|
|
|
|
INT iResult = CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
|
pwszValueName, -1,
|
|
pCurPtr->pwszValueName, -1 );
|
|
|
|
if ( iResult == CSTR_EQUAL ) {
|
|
return pCurPtr;
|
|
} else if ( iResult == CSTR_LESS_THAN ) {
|
|
|
|
//
|
|
// Keys are in ascending order, so insert if bCreate
|
|
//
|
|
|
|
if ( bCreate ) {
|
|
|
|
REGVALUEENTRY *pValueEntry = AllocValueEntry( pwszValueName );
|
|
if ( pValueEntry == NULL )
|
|
return 0;
|
|
|
|
pValueEntry->pNext = pCurPtr;
|
|
if ( pTrailPtr == NULL )
|
|
pKeyEntry->pValueList = pValueEntry;
|
|
else
|
|
pTrailPtr->pNext = pValueEntry;
|
|
|
|
return pValueEntry;
|
|
|
|
} else
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Advance down the list
|
|
//
|
|
|
|
pTrailPtr = pCurPtr;
|
|
pCurPtr = pCurPtr->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// End of list or null list case
|
|
//
|
|
|
|
if ( bCreate ) {
|
|
|
|
REGVALUEENTRY *pValueEntry = AllocValueEntry( pwszValueName );
|
|
if ( pValueEntry == NULL )
|
|
return 0;
|
|
|
|
pValueEntry->pNext = 0;
|
|
if ( pTrailPtr == NULL )
|
|
pKeyEntry->pValueList = pValueEntry;
|
|
else
|
|
pTrailPtr->pNext = pValueEntry;
|
|
|
|
return pValueEntry;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// AddDataEntry
|
|
//
|
|
// Purpose: Adds a data entry to a value entry struct
|
|
//
|
|
// Parameters: pValueEntry - Value entry
|
|
// opnType - Operation type
|
|
// dwType - Type of registry data
|
|
// dwLen - Length of registry data
|
|
// pData - Data
|
|
// pwszGPO - Gpo that set this value
|
|
// pwszSOM - Sdou that the Gpo is linked to
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL AddDataEntry( REGVALUEENTRY *pValueEntry,
|
|
REGOPERATION opnType,
|
|
DWORD dwType,
|
|
DWORD dwLen,
|
|
BYTE *pData,
|
|
WCHAR *pwszGPO,
|
|
WCHAR *pwszSOM,
|
|
WCHAR *pwszCommand)
|
|
{
|
|
REGDATAENTRY *pDataEntry = NULL;
|
|
|
|
if (opnType == REG_SOFTADDVALUE) {
|
|
|
|
//
|
|
// if the data list is null or if the first value (highest precedence value is deleted)
|
|
// then add it to the list
|
|
//
|
|
|
|
if ((pValueEntry->pDataList == NULL) || (pValueEntry->pDataList->pNext->bDeleted))
|
|
opnType = REG_ADDVALUE;
|
|
else
|
|
return TRUE;
|
|
// return without adding the value.
|
|
}
|
|
|
|
|
|
pDataEntry = AllocDataEntry( opnType, dwType, dwLen, pData,
|
|
pwszGPO, pwszSOM, pwszCommand );
|
|
if ( pDataEntry == NULL )
|
|
return FALSE;
|
|
|
|
//
|
|
// Prepend to data list because entries at beginning of list have higher precedence
|
|
//
|
|
|
|
pDataEntry->pNext = pValueEntry->pDataList;
|
|
pValueEntry->pDataList = pDataEntry;
|
|
|
|
return TRUE;
|
|
}
|