|
|
//
// REGKYLST.C
//
// Copyright (C) Microsoft Corporation, 1995
//
// Declares the predefined key structures and manages dynamic HKEY structures.
//
#include "pch.h"
#include <limits.h>
// We would rather just have one definition a
#ifdef WANT_DYNKEY_SUPPORT
#define INITED_PREDEFINED_KEY(index, flags) \
{ \ KEY_SIGNATURE, \ KEYF_PREDEFINED | KEYF_INVALID | (flags), \ 0, \ NULL, \ REG_NULL, \ REG_NULL, \ 0, \ 0, \ (index), \ NULL, \ NULL, \ (UINT) -1, \ REG_NULL, \ NULL \ } #else
#define INITED_PREDEFINED_KEY(index, flags) \
{ \ KEY_SIGNATURE, \ KEYF_PREDEFINED | KEYF_INVALID | (flags), \ 0, \ NULL, \ REG_NULL, \ REG_NULL, \ 0, \ 0, \ (index), \ NULL, \ NULL, \ (UINT) -1, \ REG_NULL \ } #endif
KEY g_RgLocalMachineKey = INITED_PREDEFINED_KEY(INDEX_LOCAL_MACHINE, KEYF_HIVESALLOWED); KEY g_RgUsersKey = INITED_PREDEFINED_KEY(INDEX_USERS, KEYF_HIVESALLOWED); #ifdef WANT_DYNKEY_SUPPORT
KEY g_RgDynDataKey = INITED_PREDEFINED_KEY(INDEX_DYN_DATA, 0); #endif
HKEY g_RgPredefinedKeys[] = { NULL, // HKEY_CLASSES_ROOT
NULL, // HKEY_CURRENT_USER
&g_RgLocalMachineKey, // HKEY_LOCAL_MACHINE
&g_RgUsersKey, // HKEY_USERS
NULL, // HKEY_PERFORMANCE_DATA
NULL, // HKEY_CURRENT_CONFIG
#ifdef WANT_DYNKEY_SUPPORT
&g_RgDynDataKey, // HKEY_DYN_DATA
#endif
};
#define NUMBER_PREDEF_KEYS (sizeof(g_RgPredefinedKeys) / sizeof(HKEY))
#ifdef WANT_STATIC_KEYS
#define NUMBER_STATIC_KEYS 32
HKEY g_RgStaticKeyArray = NULL; #endif
// List of all dynamically allocated keys.
HKEY g_RgDynamicKeyList = NULL;
const char g_RgClassesRootSubKey[] = "SOFTWARE\\CLASSES"; const char g_RgCurrentUserSubKey[] = ".DEFAULT";
#ifdef WANT_STATIC_KEYS
//
// RgAllocKeyHandleStructures
//
BOOL INTERNAL RgAllocKeyHandleStructures( VOID ) {
UINT Index; HKEY hKey;
ASSERT(IsNullPtr(g_RgStaticKeyArray)); ASSERT(IsNullPtr(g_RgDynamicKeyList));
//
// Allocate and initialize the static key table.
//
g_RgStaticKeyArray = RgSmAllocMemory(NUMBER_STATIC_KEYS * sizeof(KEY));
if (IsNullPtr(g_RgStaticKeyArray)) return FALSE;
for (Index = NUMBER_STATIC_KEYS, hKey = g_RgStaticKeyArray; Index > 0; Index--, hKey++) { hKey-> Signature = KEY_SIGNATURE; hKey-> Flags = KEYF_STATIC | KEYF_INVALID; hKey-> ReferenceCount = 0; }
return TRUE;
} #endif
#ifdef WANT_FULL_MEMORY_CLEANUP
//
// RgFreeKeyHandleStructures
//
// Releases resources allocated by RgAllocKeyHandleStructures.
//
VOID INTERNAL RgFreeKeyHandleStructures( VOID ) {
HKEY hTempKey; HKEY hKey;
//
// Delete all of the dynamically allocated keys.
//
hKey = g_RgDynamicKeyList;
if (!IsNullPtr(hKey)) { do { hTempKey = hKey; hKey = hKey-> lpNext; #ifdef WANT_DYNKEY_SUPPORT
if (!IsNullPtr(hTempKey-> pProvider)) RgSmFreeMemory(hTempKey-> pProvider); #endif
RgSmFreeMemory(hTempKey); } while (hKey != g_RgDynamicKeyList); }
g_RgDynamicKeyList = NULL;
#ifdef WANT_STATIC_KEYS
//
// Delete the static key table.
//
if (!IsNullPtr(g_RgStaticKeyArray)) { RgSmFreeMemory(g_RgStaticKeyArray); g_RgStaticKeyArray = NULL; } #endif
} #endif
//
// RgCreateKeyHandle
//
// Allocates one KEY structure, initializes some of its members, and links it
// to the list of open key handles.
//
HKEY INTERNAL RgCreateKeyHandle( VOID ) {
#ifdef WANT_STATIC_KEYS
UINT Index; #endif
HKEY hKey;
#ifdef WANT_STATIC_KEYS
//
// Check if any keys are available in the static pool.
//
if (!IsNullPtr(g_RgStaticKeyArray)) {
for (Index = NUMBER_STATIC_KEYS, hKey = g_RgStaticKeyArray; Index > 0; Index--, hKey++) { if (hKey-> Flags & KEYF_INVALID) { ASSERT(hKey-> ReferenceCount == 0); hKey-> Flags &= ~(KEYF_INVALID | KEYF_DELETED | KEYF_ENUMKEYCACHED); return hKey; } }
} #endif
//
// Must allocate a dynamic key. Initialize it and add it to our list.
//
hKey = (HKEY) RgSmAllocMemory(sizeof(KEY));
if (!IsNullPtr(hKey)) {
hKey-> Signature = KEY_SIGNATURE; hKey-> Flags = 0; hKey-> ReferenceCount = 0; #ifdef WANT_DYNKEY_SUPPORT
hKey-> pProvider = NULL; #endif
if (IsNullPtr(g_RgDynamicKeyList)) { hKey-> lpPrev = hKey; hKey-> lpNext = hKey; }
else if (hKey != g_RgDynamicKeyList) { hKey-> lpNext = g_RgDynamicKeyList; hKey-> lpPrev = g_RgDynamicKeyList-> lpPrev; hKey-> lpPrev-> lpNext = hKey; g_RgDynamicKeyList-> lpPrev = hKey; }
g_RgDynamicKeyList = hKey;
}
return hKey;
}
//
// RgDeleteKeyHandle
//
// Decrements the reference count on the given key handle. If the count
// reaches zero and the key was dynamically allocated, then the key is unlinked
// from the key list and the key is freed.
//
VOID INTERNAL RgDestroyKeyHandle( HKEY hKey ) {
ASSERT(!IsNullPtr(hKey));
// Don't allow the reference count to underflow for predefined keys or
// keys marked "never delete".
if (hKey-> ReferenceCount > 0) hKey-> ReferenceCount--;
if (hKey-> ReferenceCount == 0) {
if (!(hKey-> Flags & (KEYF_PREDEFINED | KEYF_NEVERDELETE))) {
#ifdef WANT_STATIC_KEYS
if (hKey-> Flags & KEYF_STATIC) { hKey-> Flags |= KEYF_INVALID; return; } #endif
if (hKey == hKey-> lpNext) g_RgDynamicKeyList = NULL;
else {
hKey-> lpPrev-> lpNext = hKey-> lpNext; hKey-> lpNext-> lpPrev = hKey-> lpPrev;
if (hKey == g_RgDynamicKeyList) g_RgDynamicKeyList = hKey-> lpNext;
}
#ifdef WANT_DYNKEY_SUPPORT
if (!IsNullPtr(hKey-> pProvider)) RgSmFreeMemory(hKey-> pProvider); #endif
hKey-> Signature = 0; RgSmFreeMemory(hKey);
}
}
}
//
// RgValidateAndConvertKeyHandle
//
// Verifies the the given key handle is valid. If the handle is one of the
// special predefined constants, then it is converted to the handle of the
// real KEY structure.
//
int INTERNAL RgValidateAndConvertKeyHandle( LPHKEY lphKey ) {
HKEY hKey; UINT Index; HKEY hRootKey; LPCSTR lpSubKey;
hKey = *lphKey;
//
// Check if this is one of the predefined key handles.
//
if ((DWORD) HKEY_CLASSES_ROOT <= (DWORD) hKey && (DWORD) hKey < (DWORD) HKEY_CLASSES_ROOT + NUMBER_PREDEF_KEYS) {
Index = (UINT) ((DWORD) hKey - (DWORD) HKEY_CLASSES_ROOT); hKey = g_RgPredefinedKeys[Index];
// If the predefined handle is not valid, we'll try to (re)open it for
// use. This isn't pretty, but in the typical case, this code path is
// only executed once per handle.
if (IsNullPtr(hKey) || (hKey-> Flags & KEYF_DELETED)) {
if (Index == INDEX_CLASSES_ROOT) { hRootKey = &g_RgLocalMachineKey; lpSubKey = g_RgClassesRootSubKey; }
else if (Index == INDEX_CURRENT_USER) { hRootKey = &g_RgUsersKey; lpSubKey = g_RgCurrentUserSubKey; }
else if (Index == INDEX_USERS) { goto ReturnKeyAndSuccess; }
else return ERROR_BADKEY;
// Extremely rare case: somebody has deleted one of the predefined
// key paths. We'll clear the predefined bit on this key and throw
// it away.
if (!IsNullPtr(hKey)) { g_RgPredefinedKeys[Index] = NULL; hKey-> Flags &= ~KEYF_PREDEFINED; RgDestroyKeyHandle(hKey); }
// If the base root key for this predefined key is valid, attempt
// to open the key. Mark the key as predefined so that bad apps
// can't close a key more times then it has opened it.
if (!(hRootKey-> Flags & KEYF_INVALID) && RgLookupKey(hRootKey, lpSubKey, &hKey, LK_CREATE) == ERROR_SUCCESS) { g_RgPredefinedKeys[Index] = hKey; hKey-> Flags |= KEYF_PREDEFINED; hKey-> PredefinedKeyIndex = (BYTE) Index; goto ReturnKeyAndSuccess; }
return ERROR_BADKEY;
}
ReturnKeyAndSuccess: *lphKey = hKey; return (hKey-> Flags & KEYF_INVALID) ? ERROR_BADKEY : ERROR_SUCCESS;
}
else {
if (IsBadHugeReadPtr(hKey, sizeof(KEY)) || hKey-> Signature != KEY_SIGNATURE || (hKey-> Flags & KEYF_INVALID)) return ERROR_BADKEY;
return (hKey-> Flags & KEYF_DELETED) ? ERROR_KEY_DELETED : ERROR_SUCCESS;
}
}
//
// RgIncrementKeyReferenceCount
//
// Safely increments the reference count of the specified KEY. If the count
// overflows, then the key is marked as "never delete" since the usage count
// is now unknown.
//
VOID INTERNAL RgIncrementKeyReferenceCount( HKEY hKey ) {
if (hKey-> ReferenceCount != UINT_MAX) hKey-> ReferenceCount++; else { if (!(hKey-> Flags & KEYF_NEVERDELETE)) { TRACE(("RgIncrementKeyReferenceCount: handle %lx has overflowed\n", hKey)); } hKey-> Flags |= KEYF_NEVERDELETE; }
}
//
// RgFindOpenKeyHandle
//
// Searches the list of currently opened keys for a key that refers to the same
// FILE_INFO structure and keynode offset. If found, the HKEY is returned, or
// if not, NULL.
//
HKEY INTERNAL RgFindOpenKeyHandle( LPFILE_INFO lpFileInfo, DWORD KeynodeIndex ) {
UINT Index; LPHKEY lphKey; HKEY hKey;
ASSERT(!IsNullKeynodeIndex(KeynodeIndex));
//
// Check if this is one of the predefined key handles.
//
for (Index = NUMBER_PREDEF_KEYS, lphKey = g_RgPredefinedKeys; Index > 0; Index--, lphKey++) {
hKey = *lphKey;
if (!IsNullPtr(hKey) && hKey-> lpFileInfo == lpFileInfo && hKey-> KeynodeIndex == KeynodeIndex && !(hKey-> Flags & (KEYF_DELETED | KEYF_INVALID))) return hKey;
}
#ifdef WANT_STATIC_KEYS
//
// Check if this is one of the static key handles.
//
if (!IsNullPtr(g_RgStaticKeyArray)) {
for (Index = NUMBER_STATIC_KEYS, hKey = g_RgStaticKeyArray; Index > 0; Index--, hKey++) { if (hKey-> lpFileInfo == lpFileInfo && hKey-> KeynodeIndex == KeynodeIndex && !(hKey-> Flags & (KEYF_DELETED | KEYF_INVALID))) return hKey; }
} #endif
//
// Check if this is one of the dynamic key handles.
//
if (!IsNullPtr((hKey = g_RgDynamicKeyList))) {
do {
if (hKey-> KeynodeIndex == KeynodeIndex && hKey-> lpFileInfo == lpFileInfo && !(hKey-> Flags & KEYF_DELETED)) return hKey;
hKey = hKey-> lpNext;
} while (hKey != g_RgDynamicKeyList);
}
return NULL;
}
//
// RgInvalidateKeyHandles
//
// Generic routine to invalidate key handles based on a set of criteria.
// If any key handle meets any of the given criteria, then it's marked invalid.
//
VOID INTERNAL RgInvalidateKeyHandles( LPFILE_INFO lpFileInfo, UINT PredefinedKeyIndex ) {
UINT Index; LPHKEY lphKey; HKEY hKey;
//
// Invalidate predefined key handles.
//
for (Index = NUMBER_PREDEF_KEYS, lphKey = g_RgPredefinedKeys; Index > 0; Index--, lphKey++) {
hKey = *lphKey;
if (!IsNullPtr(hKey)) { if (hKey-> lpFileInfo == lpFileInfo || hKey-> PredefinedKeyIndex == (BYTE) PredefinedKeyIndex) hKey-> Flags |= (KEYF_DELETED | KEYF_INVALID); }
}
#ifdef WANT_STATIC_KEYS
//
// Invalidate static key handles.
//
if (!IsNullPtr(g_RgStaticKeyArray)) {
for (Index = NUMBER_STATIC_KEYS, hKey = g_RgStaticKeyArray; Index > 0; Index--, hKey++) { if (hKey-> lpFileInfo == lpFileInfo || hKey-> PredefinedKeyIndex == PredefinedKeyIndex) hKey-> Flags |= (KEYF_DELETED | KEYF_INVALID); }
} #endif
//
// Invalidate dynamic key handles.
//
if (!IsNullPtr((hKey = g_RgDynamicKeyList))) {
do {
if (hKey-> lpFileInfo == lpFileInfo || hKey-> PredefinedKeyIndex == (BYTE) PredefinedKeyIndex) hKey-> Flags |= (KEYF_DELETED | KEYF_INVALID);
hKey = hKey-> lpNext;
} while (hKey != g_RgDynamicKeyList);
}
}
#ifdef VXD
#pragma VxD_RARE_CODE_SEG
#endif
//
// VMMRegMapPredefKeyToKey
//
LONG REGAPI VMMRegMapPredefKeyToKey( HKEY hTargetKey, HKEY hPredefKey ) {
int ErrorCode; UINT PredefinedKeyIndex; HKEY hOldKey;
if (!RgLockRegistry()) return ERROR_LOCK_FAILED;
if ((ErrorCode = RgValidateAndConvertKeyHandle(&hTargetKey)) == ERROR_SUCCESS) {
if ((hPredefKey == HKEY_CURRENT_USER && hTargetKey-> PredefinedKeyIndex == INDEX_USERS) || (hPredefKey == HKEY_CURRENT_CONFIG && hTargetKey-> PredefinedKeyIndex == INDEX_LOCAL_MACHINE)) {
PredefinedKeyIndex = (UINT) ((DWORD) hPredefKey - (DWORD) HKEY_CLASSES_ROOT);
hOldKey = g_RgPredefinedKeys[PredefinedKeyIndex];
if (!IsNullPtr(hOldKey)) {
// Invalidate open handles based off the existing predefined
// key handle. Win95 behavior.
RgInvalidateKeyHandles((LPFILE_INFO) -1L, (BYTE) PredefinedKeyIndex);
hOldKey-> Flags &= ~KEYF_PREDEFINED; RgDestroyKeyHandle(hOldKey);
}
hTargetKey-> Flags |= KEYF_PREDEFINED; RgIncrementKeyReferenceCount(hTargetKey); g_RgPredefinedKeys[PredefinedKeyIndex] = hTargetKey;
}
else { DEBUG_OUT(("VMMRegMapPredefKeyToKey: invalid hTargetKey\n")); ErrorCode = ERROR_BADKEY; }
}
RgUnlockRegistry();
return ErrorCode;
}
|