📄 reg.c
字号:
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/advapi32/reg/reg.c
* PURPOSE: Registry functions
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
* Thomas Weidenmueller <w3seek@reactos.com>
* UPDATE HISTORY:
* Created 01/11/98
* 19990309 EA Stubs
* 20050502 Fireball imported some stuff from WINE
*/
/* INCLUDES *****************************************************************/
#include <advapi32.h>
#define NDEBUG
#include <wine/debug.h>
/* DEFINES ******************************************************************/
#define MAX_DEFAULT_HANDLES 6
#define REG_MAX_NAME_SIZE 256
#define REG_MAX_DATA_SIZE 2048
/* GLOBALS ******************************************************************/
static RTL_CRITICAL_SECTION HandleTableCS;
static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
static HANDLE ProcessHeap;
static BOOLEAN DefaultHandlesDisabled = FALSE;
static BOOLEAN DefaultHandleHKUDisabled = FALSE;
/* PROTOTYPES ***************************************************************/
static NTSTATUS MapDefaultKey (PHANDLE ParentKey, HKEY Key);
static VOID CloseDefaultKeys(VOID);
#define ClosePredefKey(Handle) \
if ((ULONG_PTR)Handle & 0x1) { \
NtClose(Handle); \
}
#define IsPredefKey(HKey) \
(((ULONG)(HKey) & 0xF0000000) == 0x80000000)
#define GetPredefKeyIndex(HKey) \
((ULONG)(HKey) & 0x0FFFFFFF)
static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle);
static NTSTATUS OpenUsersKey (PHANDLE KeyHandle);
static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
/* FUNCTIONS ****************************************************************/
/* check if value type needs string conversion (Ansi<->Unicode) */
__inline static int is_string( DWORD type )
{
return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
}
/************************************************************************
* RegInitDefaultHandles
*/
BOOL
RegInitialize (VOID)
{
TRACE("RegInitialize()\n");
ProcessHeap = RtlGetProcessHeap();
RtlZeroMemory (DefaultHandleTable,
MAX_DEFAULT_HANDLES * sizeof(HANDLE));
RtlInitializeCriticalSection (&HandleTableCS);
return TRUE;
}
/************************************************************************
* RegInit
*/
BOOL
RegCleanup (VOID)
{
TRACE("RegCleanup()\n");
CloseDefaultKeys ();
RtlDeleteCriticalSection (&HandleTableCS);
return TRUE;
}
static NTSTATUS
OpenPredefinedKey(IN ULONG Index,
OUT HANDLE Handle)
{
NTSTATUS Status;
switch (Index)
{
case 0: /* HKEY_CLASSES_ROOT */
Status = OpenClassesRootKey (Handle);
break;
case 1: /* HKEY_CURRENT_USER */
Status = RtlOpenCurrentUser (MAXIMUM_ALLOWED,
Handle);
break;
case 2: /* HKEY_LOCAL_MACHINE */
Status = OpenLocalMachineKey (Handle);
break;
case 3: /* HKEY_USERS */
Status = OpenUsersKey (Handle);
break;
#if 0
case 4: /* HKEY_PERFORMANCE_DATA */
Status = OpenPerformanceDataKey (Handle);
break;
#endif
case 5: /* HKEY_CURRENT_CONFIG */
Status = OpenCurrentConfigKey (Handle);
break;
case 6: /* HKEY_DYN_DATA */
Status = STATUS_NOT_IMPLEMENTED;
break;
default:
WARN("MapDefaultHandle() no handle creator\n");
Status = STATUS_INVALID_PARAMETER;
break;
}
return Status;
}
static NTSTATUS
MapDefaultKey (OUT PHANDLE RealKey,
IN HKEY Key)
{
PHANDLE Handle;
ULONG Index;
BOOLEAN DoOpen, DefDisabled;
NTSTATUS Status = STATUS_SUCCESS;
TRACE("MapDefaultKey (Key %x)\n", Key);
if (!IsPredefKey(Key))
{
*RealKey = (HANDLE)((ULONG_PTR)Key & ~0x1);
return STATUS_SUCCESS;
}
/* Handle special cases here */
Index = GetPredefKeyIndex(Key);
if (Index >= MAX_DEFAULT_HANDLES)
{
return STATUS_INVALID_PARAMETER;
}
RtlEnterCriticalSection (&HandleTableCS);
if (Key == HKEY_CURRENT_USER)
DefDisabled = DefaultHandleHKUDisabled;
else
DefDisabled = DefaultHandlesDisabled;
if (!DefDisabled)
{
Handle = &DefaultHandleTable[Index];
DoOpen = (*Handle == NULL);
}
else
{
Handle = RealKey;
DoOpen = TRUE;
}
if (DoOpen)
{
/* create/open the default handle */
Status = OpenPredefinedKey(Index,
Handle);
}
if (NT_SUCCESS(Status))
{
if (!DefDisabled)
*RealKey = *Handle;
else
*(PULONG_PTR)Handle |= 0x1;
}
RtlLeaveCriticalSection (&HandleTableCS);
return Status;
}
static VOID
CloseDefaultKeys (VOID)
{
ULONG i;
RtlEnterCriticalSection (&HandleTableCS);
for (i = 0; i < MAX_DEFAULT_HANDLES; i++)
{
if (DefaultHandleTable[i] != NULL)
{
NtClose (DefaultHandleTable[i]);
DefaultHandleTable[i] = NULL;
}
}
RtlLeaveCriticalSection (&HandleTableCS);
}
static NTSTATUS
OpenClassesRootKey (PHANDLE KeyHandle)
{
OBJECT_ATTRIBUTES Attributes;
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\CLASSES");
TRACE("OpenClassesRootKey()\n");
InitializeObjectAttributes (&Attributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
return NtOpenKey (KeyHandle,
MAXIMUM_ALLOWED,
&Attributes);
}
static NTSTATUS
OpenLocalMachineKey (PHANDLE KeyHandle)
{
OBJECT_ATTRIBUTES Attributes;
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine");
NTSTATUS Status;
TRACE("OpenLocalMachineKey()\n");
InitializeObjectAttributes (&Attributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey (KeyHandle,
MAXIMUM_ALLOWED,
&Attributes);
TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
return Status;
}
static NTSTATUS
OpenUsersKey (PHANDLE KeyHandle)
{
OBJECT_ATTRIBUTES Attributes;
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\User");
TRACE("OpenUsersKey()\n");
InitializeObjectAttributes (&Attributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
return NtOpenKey (KeyHandle,
MAXIMUM_ALLOWED,
&Attributes);
}
static NTSTATUS
OpenCurrentConfigKey (PHANDLE KeyHandle)
{
OBJECT_ATTRIBUTES Attributes;
UNICODE_STRING KeyName =
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
TRACE("OpenCurrentConfigKey()\n");
InitializeObjectAttributes (&Attributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
return NtOpenKey (KeyHandle,
MAXIMUM_ALLOWED,
&Attributes);
}
/************************************************************************
* RegDisablePredefinedCache
*
* @implemented
*/
LONG WINAPI
RegDisablePredefinedCache(VOID)
{
RtlEnterCriticalSection (&HandleTableCS);
DefaultHandleHKUDisabled = TRUE;
RtlLeaveCriticalSection (&HandleTableCS);
return ERROR_SUCCESS;
}
/************************************************************************
* RegDisablePredefinedCacheEx
*
* @implemented
*/
LONG STDCALL
RegDisablePredefinedCacheEx(VOID)
{
RtlEnterCriticalSection (&HandleTableCS);
DefaultHandlesDisabled = TRUE;
DefaultHandleHKUDisabled = TRUE;
RtlLeaveCriticalSection (&HandleTableCS);
return ERROR_SUCCESS;
}
/************************************************************************
* RegOverridePredefKey
*
* @implemented
*/
LONG STDCALL
RegOverridePredefKey(IN HKEY hKey,
IN HKEY hNewHKey OPTIONAL)
{
LONG ErrorCode = ERROR_SUCCESS;
if ((hKey == HKEY_CLASSES_ROOT ||
hKey == HKEY_CURRENT_CONFIG ||
hKey == HKEY_CURRENT_USER ||
hKey == HKEY_LOCAL_MACHINE ||
hKey == HKEY_PERFORMANCE_DATA ||
hKey == HKEY_USERS) &&
!IsPredefKey(hNewHKey))
{
PHANDLE Handle;
ULONG Index;
Index = GetPredefKeyIndex(hKey);
Handle = &DefaultHandleTable[Index];
if (hNewHKey == NULL)
{
/* restore the default mapping */
NTSTATUS Status = OpenPredefinedKey(Index,
&hNewHKey);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError(Status);
}
ASSERT(hNewHKey != NULL);
}
RtlEnterCriticalSection (&HandleTableCS);
/* close the currently mapped handle if existing */
if (*Handle != NULL)
{
NtClose(*Handle);
}
/* update the mapping */
*Handle = hNewHKey;
RtlLeaveCriticalSection (&HandleTableCS);
}
else
ErrorCode = ERROR_INVALID_HANDLE;
return ErrorCode;
}
/************************************************************************
* RegCloseKey
*
* @implemented
*/
LONG STDCALL
RegCloseKey (HKEY hKey)
{
NTSTATUS Status;
/* don't close null handle or a pseudo handle */
if ((!hKey) || (((ULONG)hKey & 0xF0000000) == 0x80000000))
{
return ERROR_INVALID_HANDLE;
}
Status = NtClose (hKey);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError (Status);
}
return ERROR_SUCCESS;
}
static NTSTATUS
RegpCopyTree(IN HKEY hKeySrc,
IN HKEY hKeyDest)
{
typedef struct
{
LIST_ENTRY ListEntry;
HANDLE hKeySrc;
HANDLE hKeyDest;
} REGP_COPY_KEYS, *PREGP_COPY_KEYS;
LIST_ENTRY copyQueueHead;
PREGP_COPY_KEYS copyKeys, newCopyKeys;
union
{
KEY_VALUE_FULL_INFORMATION *KeyValue;
KEY_NODE_INFORMATION *KeyNode;
PVOID Buffer;
} Info;
ULONG Index, BufferSizeRequired, BufferSize = 0x200;
NTSTATUS Status = STATUS_SUCCESS;
NTSTATUS Status2 = STATUS_SUCCESS;
InitializeListHead(©QueueHead);
Info.Buffer = RtlAllocateHeap(ProcessHeap,
0,
BufferSize);
if (Info.Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
copyKeys = RtlAllocateHeap(ProcessHeap,
0,
sizeof(REGP_COPY_KEYS));
if (copyKeys != NULL)
{
copyKeys->hKeySrc = hKeySrc;
copyKeys->hKeyDest = hKeyDest;
InsertHeadList(©QueueHead,
©Keys->ListEntry);
/* FIXME - copy security from hKeySrc to hKeyDest or just for the subkeys? */
do
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -