|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
regclass.h
Abstract:
This file contains declarations needed for manipulating the portion of the registry that contains class registrations
Author:
Adam Edwards (adamed) 14-Nov-1997
Notes:
--*/
#if defined( LOCAL )
//
// Declarations
//
#define LENGTH( str ) ( sizeof( str ) - sizeof( UNICODE_NULL ))
#define INIT_SPECIALKEY(x) {LENGTH(x), LENGTH(x), x}
#define REG_CLASSES_FIRST_DISTINCT_ICH 10
#define REG_CHAR_SIZE sizeof(WCHAR)
#define REG_USER_HIVE_NAME L"\\Registry\\User"
#define REG_USER_HIVE_NAMELEN LENGTH(REG_USER_HIVE_NAME)
#define REG_USER_HIVE_NAMECCH (REG_USER_HIVE_NAMELEN / REG_CHAR_SIZE)
#define REG_USER_HIVE_CLASSES_SUFFIX L"_Classes"
#define REG_USER_HIVE_CLASSES_SUFFIXLEN LENGTH(REG_USER_HIVE_CLASSES_SUFFIX)
#define REG_USER_HIVE_CLASSES_SUFFIXCCH (REG_USER_HIVE_CLASSES_SUFFIXLEN / REG_CHAR_SIZE)
#define REG_MACHINE_CLASSES_HIVE_NAME L"\\Registry\\Machine\\Software\\Classes"
#define REG_MACHINE_CLASSES_HIVE_NAMELEN LENGTH(REG_MACHINE_CLASSES_HIVE_NAME)
#define REG_MACHINE_CLASSES_HIVE_NAMECCH (REG_MACHINE_CLASSES_HIVE_NAMELEN / REG_CHAR_SIZE)
#define REG_USER_HIVE_LINK_TREE L"\\Software\\Classes"
#define REG_CLASSES_HIVE_MIN_NAMELEN REG_USER_HIVE_CLASSES_SUFFIXLEN + REG_USER_HIVE_NAMELEN
//
// The difference between these two paths
// \Registry\User\<sid>_Classes and
// \Registry\User\<siid>\Software\Classes
//
// plus extra for the translation from machine to user -- take into account the sid
//
#define REG_CLASSES_SUBTREE_PADDING 128
#define REG_MAX_CLASSKEY_LEN 384
#define REG_MAX_CLASSKEY_CCH (REG_MAX_CLASSKEY_LEN / REG_CHAR_SIZE)
#define REG_MAX_KEY_LEN 512
#define REG_MAX_KEY_CCH (REG_MAX_KEY_LEN / REG_CHAR_SIZE)
#define REG_MAX_KEY_PATHLEN 65535
//
// HKCR Handle Tags for Per-user Class Registration.
//
// Subkeys of HKCR up to and including a class registration parent key are tagged
// by setting two free bits in their handle value (the lower two bits of a handle
// are free to be used as tags). This makes it easy to tell if a key is in
// HKCR and needs special treatment. After the class registration part of a path,
// this marker is not needed since such keys do not require special treatment
// for enumeration, opening, and deletion.
//
//
// Note that for the sake of speed we are using 1 bit instead of a specific pattern of
// two bits. Currently, bit 0 is used to mark remote handles. Bit 2 is used in the
// server only to mark restricted keys. Locally, we use it to mark hkcr keys. More
// Here is a list of valid combinations -- unused bits must be 0. Invalid means that
// in the current implementation, you should never see it in that part of the registry.
//
//
// Local Server Client (application sees these)
// 00 (non HKCR, unused) 00 (unrestricted, unused) 00 (non HKCR, local)
// 01 Invalid (HKCR, unused) 01 Invalid (unrestricted, unused) 01 (non HKCR, remote)
// 10 (HKCR, unused) 10 (restricted, unused) 10 (HKCR, local)
// 11 Invalid (HKCR, unused) 11 Invalid (restricted, unused) 11 Invalid (HKCR, remote)
//
//
// Note that we could use either 10 or 11 to mark HKCR handles -- we chose 10 for simplicity's
// sake since it simply involves oring in a bit. This can be changed in the future
// if yet another bit pattern is needed. Otherwise, clients never see 11 -- they only see
// 00, 01, and 10. Note that these bits must be propagated to the local portion. This is done
// simply by leaving the bits as-is, because local doesn't use any of the bits. Note that
// we would be broken if the bits needed to propagate to server for some reason, since it
// is using bit 2 already. We do not allow HKCR as a remote handle, however, so this is
// not a problem.
//
#define REG_CLASS_HANDLE_MASK 0x3
#define REG_CLASS_HANDLE_VALUE 0x2
#define REG_CLASS_IS_SPECIAL_KEY( Handle ) ( (LONG) ( ( (ULONG_PTR) (Handle) ) & REG_CLASS_HANDLE_VALUE ) )
#define REG_CLASS_SET_SPECIAL_KEY( Handle ) ( (HANDLE) ( ( (ULONG_PTR) (Handle) ) | \
REG_CLASS_HANDLE_VALUE ) )
#define REG_CLASS_RESET_SPECIAL_KEY( Handle ) ( (HANDLE) ( ( ( (ULONG_PTR) (Handle) ) & ~REG_CLASS_HANDLE_MASK )))
#if defined(_REGCLASS_MALLOC_INSTRUMENTED_)
extern RTL_CRITICAL_SECTION gRegClassHeapCritSect; extern DWORD gcbAllocated; extern DWORD gcAllocs; extern DWORD gcbMaxAllocated; extern DWORD gcMaxAllocs; extern PVOID gpvAllocs;
__inline PVOID RegClassHeapAlloc(SIZE_T cbSize) { PVOID pvAllocation;
pvAllocation = RtlAllocateHeap(RtlProcessHeap(), 0, cbSize + sizeof(SIZE_T));
RtlEnterCriticalSection(&gRegClassHeapCritSect);
if (pvAllocation) { gcbAllocated += cbSize; gcAllocs ++; (ULONG_PTR) gpvAllocs ^= (ULONG_PTR) pvAllocation;
if (gcAllocs > gcMaxAllocs) { gcMaxAllocs = gcAllocs; }
if (gcbAllocated > gcbMaxAllocated) { gcbMaxAllocated = gcbAllocated; } }
RtlLeaveCriticalSection(&gRegClassHeapCritSect);
*((SIZE_T*) pvAllocation) = cbSize;
((SIZE_T*) pvAllocation) ++;
return pvAllocation; }
__inline BOOLEAN RegClassHeapFree(PVOID pvAllocation) { BOOLEAN bRetVal; SIZE_T cbSize;
((SIZE_T*) pvAllocation) --;
cbSize = *((SIZE_T*) pvAllocation);
bRetVal = RtlFreeHeap(RtlProcessHeap(), 0, pvAllocation);
RtlEnterCriticalSection(&gRegClassHeapCritSect);
gcbAllocated -= cbSize; gcAllocs --;
(ULONG_PTR) gpvAllocs ^= (ULONG_PTR) pvAllocation;
RtlLeaveCriticalSection(&gRegClassHeapCritSect);
if (!bRetVal) { DbgBreakPoint(); }
return bRetVal; }
#else // defined(_REGCLASS_MALLOC_INSTRUMENTED_)
#define RegClassHeapAlloc(x) RtlAllocateHeap(RtlProcessHeap(), 0, x)
#define RegClassHeapFree(x) RtlFreeHeap(RtlProcessHeap(), 0, x)
#endif // defined(_REGCLASS_MALLOC_INSTRUMENTED_)
enum { LOCATION_MACHINE = 0x1, LOCATION_USER = 0x2, LOCATION_BOTH = 0x3 };
//
// SKeySemantics
//
// This structure is the result of parsing a registry key full path
//
// ATTENTION: This structure, along with the current parsing code, needs to
// be overhauled. Originally, it was designed to do one thing. Now, it
// identifies several parts of keys. The original goal was speed --
// we attempted to touch the least amount of string (memory) possible.
// As more functionality was added to the parser, this became more complex.
// A better solution would pay more attention to a generic, straightforward
// way of parsing the key -- things have become far too convoluted in
// an attempt to be fast.
//
typedef struct _SKeySemantics { /* out */ unsigned _fUser : 1; // this key is rooted in the user hive
/* out */ unsigned _fMachine : 1; // this key is rooted in the machine hive
/* out */ unsigned _fCombinedClasses : 1; // this key is rooted in the combined classes hive
/* out */ unsigned _fClassRegistration : 1; // this key is a class registration key
/* out */ unsigned _fClassRegParent : 1; // this key is a special key (parent of a class reg key)
/* out */ unsigned _fAllocedNameBuf : 1; // nonzero if _pFullPath was realloc'd and needs to be freed
/* out */ USHORT _ichKeyStart; // index to start of a class reg after
// \\software\\classes in the returned full path
/* out */ USHORT _cbPrefixLen; // length of prefix
/* out */ USHORT _cbSpecialKey; // length of special key
/* out */ USHORT _cbClassRegKey; // length of class reg key name
/* in, out */ ULONG _cbFullPath; // size of the KEY_NAME_INFORMATION passed in
/* out */ PKEY_NAME_INFORMATION _pFullPath; // address of an OBJECT_NAME_INFORMATION structure
} SKeySemantics;
//
// External Prototypes
//
//
// Opens the HKCR predefined handle with the combined view
//
error_status_t OpenCombinedClassesRoot( IN REGSAM samDesired, OUT HANDLE * phKey);
//
// Parses a registry key and returns results
//
NTSTATUS BaseRegGetKeySemantics( HKEY hkParent, PUNICODE_STRING pSubKey, SKeySemantics* pKeySemantics); //
// Frees resources associated with an SKeySemantics structure
//
void BaseRegReleaseKeySemantics(SKeySemantics* pKeySemantics);
//
// Opens a class key that exists in either
// HKLM or HKCU
//
NTSTATUS BaseRegOpenClassKey( HKEY hKey, PUNICODE_STRING lpSubKey, DWORD dwOptions, REGSAM samDesired, PHKEY phkResult);
//
// Opens a class key from a specified set
// of locations
//
NTSTATUS BaseRegOpenClassKeyFromLocation( SKeySemantics* pKeyInfo, HKEY hKey, PUNICODE_STRING lpSubKey, REGSAM samDesired, DWORD dwLocation, HKEY* phkResult);
//
// Returns key objects for the user and machine
// versions of a key
//
NTSTATUS BaseRegGetUserAndMachineClass( SKeySemantics* pKeySemantics, HKEY Key, REGSAM samDesired, PHKEY phkMachine, PHKEY phkUser);
//
// Internal Prototypes
//
USHORT BaseRegGetUserPrefixLength( PUNICODE_STRING pFullPath);
USHORT BaseRegCchSpecialKeyLen( PUNICODE_STRING pFullPath, USHORT ichSpecialKeyStart, SKeySemantics* pKeySemantics);
NTSTATUS BaseRegTranslateToMachineClassKey( SKeySemantics* pKeyInfo, PUNICODE_STRING pMachineClassKey, USHORT* pPrefixLen);
NTSTATUS BaseRegTranslateToUserClassKey( SKeySemantics* pKeyInfo, PUNICODE_STRING pUserClassKey, USHORT* pPrefixLen);
NTSTATUS BaseRegOpenClassKeyRoot( SKeySemantics* pKeyInfo, PHKEY phkClassRoot, PUNICODE_STRING pClassKeyPath, BOOL fMachine);
NTSTATUS BaseRegMapClassRegistrationKey( HKEY hKey, PUNICODE_STRING pSubKey, SKeySemantics* pKeyInfo, PUNICODE_STRING pDestSubKey, BOOL* pfRetryOnAccessDenied, PHKEY phkDestResult, PUNICODE_STRING* ppSubKeyResult);
NTSTATUS BaseRegMapClassOnAccessDenied( SKeySemantics* pKeySemantics, PHKEY phkDest, PUNICODE_STRING pDestSubKey, BOOL* pfRetryOnAccessDenied);
NTSTATUS CreateMultipartUserClassKey( IN HKEY hKey, OUT PHKEY phkResult);
NTSTATUS GetFixedKeyInfo( HKEY hkUser, HKEY hkMachine, LPDWORD pdwUserValues, LPDWORD pdwMachineValues, LPDWORD pdwUserMaxDataLen, LPDWORD pdwMachineMaxDataLen, LPDWORD pdwMaxValueNameLen);
BOOL InitializeClassesNameSpace();
extern BOOL gbCombinedClasses;
//
// Inline functions
//
enum { REMOVEPREFIX_DISCARD_INITIAL_PATHSEP = 0, REMOVEPREFIX_KEEP_INITIAL_PATHSEP = 1 };
__inline void KeySemanticsRemovePrefix( SKeySemantics* pKeyInfo, PUNICODE_STRING pDestination, DWORD dwFlags) { BOOL fMoveBack;
fMoveBack = (dwFlags & REMOVEPREFIX_KEEP_INITIAL_PATHSEP) && (pKeyInfo->_pFullPath->Name[pKeyInfo->_ichKeyStart]);
pDestination->Buffer = &(pKeyInfo->_pFullPath->Name[pKeyInfo->_ichKeyStart - (fMoveBack ? 1 : 0)]);
pDestination->Length = (USHORT) pKeyInfo->_pFullPath->NameLength - ((pKeyInfo->_ichKeyStart - (fMoveBack ? 1 : 0)) * REG_CHAR_SIZE); }
__inline void KeySemanticsGetSid( SKeySemantics* pKeyInfo, PUNICODE_STRING pSidString) { pSidString->Buffer = &(pKeyInfo->_pFullPath->Name[REG_USER_HIVE_NAMECCH]);
pSidString->Length = pKeyInfo->_cbPrefixLen - (REG_USER_HIVE_CLASSES_SUFFIXLEN + REG_USER_HIVE_NAMELEN); }
__inline void KeySemanticsTruncatePrefixToClassReg( SKeySemantics* pKeyInfo, USHORT PrefixLen, PUNICODE_STRING pDestination) { pDestination->Length = PrefixLen + (pKeyInfo->_fClassRegistration ? REG_CHAR_SIZE : 0) + pKeyInfo->_cbSpecialKey + pKeyInfo->_cbClassRegKey; }
BOOL ExtractClassKey( IN OUT HKEY *phKey, IN OUT PUNICODE_STRING lpSubKey);
#else // LOCAL
#define REG_CLASS_IS_SPECIAL_KEY( Handle ) 0
#define REG_CLASS_SET_SPECIAL_KEY( Handle ) (Handle)
#define REG_CLASS_RESET_SPECIAL_KEY( Handle ) (Handle)
#endif // LOCAL
|