1342 lines
29 KiB
C
1342 lines
29 KiB
C
/*++
|
||
|
||
|
||
|
||
Copyright (c) 1992-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
Regkey.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the client side wrappers for the Win32 Registry
|
||
APIs to open, create, flush and close keys. That is:
|
||
|
||
- RegCloseKey
|
||
- RegCreateKeyA
|
||
- RegCreateKeyW
|
||
- RegCreateKeyExA
|
||
- RegCreateKeyExW
|
||
- RegFlushKey
|
||
- RegOpenKeyA
|
||
- RegOpenKeyW
|
||
- RegOpenKeyExA
|
||
- RegOpenKeyExW
|
||
- RegOverridePredefKey
|
||
- RegOpenCurrentUser
|
||
|
||
Author:
|
||
|
||
David J. Gilman (davegi) 15-Nov-1991
|
||
|
||
Notes:
|
||
|
||
See the notes in server\regkey.c.
|
||
|
||
--*/
|
||
|
||
#include <rpc.h>
|
||
#include "regrpc.h"
|
||
#include "client.h"
|
||
#include <wow64reg.h>
|
||
|
||
#if defined(LEAK_TRACK)
|
||
NTSTATUS TrackObject(HKEY hKey);
|
||
#endif // defined(LEAK_TRACK)
|
||
|
||
NTSTATUS DisablePredefinedHandleTable(HKEY Handle);
|
||
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegCloseKey (
|
||
IN HKEY hKey
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win32 RPC wrapper for closeing a key handle.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
if( hKey == NULL ) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
if( IsPredefinedRegistryHandle( hKey )) {
|
||
return( ClosePredefinedHandle( hKey ) );
|
||
}
|
||
|
||
if( IsLocalHandle( hKey )) {
|
||
|
||
#if defined(_WIN64)
|
||
Wow64RegCloseKey (hKey);
|
||
#endif
|
||
return ( LONG ) LocalBaseRegCloseKey( &hKey );
|
||
|
||
} else {
|
||
|
||
hKey = DereferenceRemoteHandle( hKey );
|
||
return ( LONG ) BaseRegCloseKey( &hKey );
|
||
}
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegOverridePredefKey (
|
||
IN HKEY hKey,
|
||
IN HKEY hNewKey
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win32 wrapper to override the normal value for a predefined key.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
if( hKey == NULL ) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
if( !IsPredefinedRegistryHandle( hKey )) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
|
||
Status = RemapPredefinedHandle( hKey, hNewKey );
|
||
|
||
return RtlNtStatusToDosError( Status );
|
||
}
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegCreateKeyA (
|
||
HKEY hKey,
|
||
LPCSTR lpSubKey,
|
||
PHKEY phkResult
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win 3.1 ANSI RPC wrapper for opening an existing key or creating a new one.
|
||
|
||
--*/
|
||
|
||
{
|
||
LONG Error;
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Win3.1ism - Win 3.1 allows the predefined handle to be opened by
|
||
// specifying a pointer to an empty or NULL string for the sub-key.
|
||
//
|
||
|
||
//
|
||
// If the subkey is NULL or points to a NUL string and the handle is
|
||
// predefined, just return the predefined handle (a virtual open)
|
||
// otherwise it's an error.
|
||
//
|
||
|
||
if(( lpSubKey == NULL ) || ( *lpSubKey == '\0' )) {
|
||
|
||
if( IsPredefinedRegistryHandle( hKey )) {
|
||
|
||
*phkResult = hKey;
|
||
return ERROR_SUCCESS;
|
||
|
||
} else {
|
||
|
||
return ERROR_BADKEY;
|
||
}
|
||
}
|
||
|
||
Error = (LONG)RegCreateKeyExA(
|
||
hKey,
|
||
lpSubKey,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
WIN31_REGSAM,
|
||
NULL,
|
||
phkResult,
|
||
NULL
|
||
);
|
||
|
||
return Error;
|
||
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegCreateKeyW (
|
||
HKEY hKey,
|
||
LPCWSTR lpSubKey,
|
||
PHKEY phkResult
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win 3.1 Unicode RPC wrapper for opening an existing key or creating a
|
||
new one.
|
||
|
||
--*/
|
||
|
||
{
|
||
LONG Error;
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
Error = (LONG)RegCreateKeyExW(
|
||
hKey,
|
||
lpSubKey,
|
||
0,
|
||
WIN31_CLASS,
|
||
REG_OPTION_NON_VOLATILE,
|
||
WIN31_REGSAM,
|
||
NULL,
|
||
phkResult,
|
||
NULL
|
||
);
|
||
|
||
return Error;
|
||
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegCreateKeyExA (
|
||
HKEY hKey,
|
||
LPCSTR lpSubKey,
|
||
DWORD Reserved,
|
||
LPSTR lpClass,
|
||
DWORD dwOptions,
|
||
REGSAM samDesired,
|
||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||
PHKEY phkResult,
|
||
LPDWORD lpdwDisposition
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win32 ANSI RPC wrapper for opening an existing key or creating a new one.
|
||
|
||
RegCreateKeyExA converts the LPSECURITY_ATTRIBUTES argument to a
|
||
RPC_SECURITY_ATTRIBUTES argument and calls BaseRegCreateKeyExA.
|
||
|
||
--*/
|
||
|
||
{
|
||
UNICODE_STRING SubKey;
|
||
UNICODE_STRING ClassUnicode;
|
||
PUNICODE_STRING Class;
|
||
ANSI_STRING AnsiString;
|
||
PRPC_SECURITY_ATTRIBUTES pRpcSA;
|
||
RPC_SECURITY_ATTRIBUTES RpcSA;
|
||
NTSTATUS Status;
|
||
LONG Error;
|
||
HKEY TempHandle = NULL;
|
||
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
OutputDebugString( "In RegCreateKeyExA\n" );
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
||
//
|
||
|
||
if(( hKey == HKEY_PERFORMANCE_DATA ) ||
|
||
( hKey == HKEY_PERFORMANCE_TEXT ) ||
|
||
( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
|
||
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
//
|
||
// Ensure Reserved is zero to avoid future compatability problems.
|
||
//
|
||
|
||
if( Reserved != 0 ) {
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// Validate that the sub key is not NULL.
|
||
//
|
||
if( ! lpSubKey ) {
|
||
return ERROR_BADKEY;
|
||
}
|
||
|
||
hKey = MapPredefinedHandle( hKey, &TempHandle );
|
||
if( hKey == NULL ) {
|
||
Error = ERROR_INVALID_HANDLE;
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
//
|
||
// Convert the subkey to a counted Unicode string
|
||
//
|
||
if( !RtlCreateUnicodeStringFromAsciiz(&SubKey,lpSubKey) ) {
|
||
Status = STATUS_NO_MEMORY;
|
||
Error = RtlNtStatusToDosError( Status );
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
//
|
||
// Add size of NULL so that RPC transmits the right
|
||
// stuff.
|
||
//
|
||
SubKey.Length += sizeof( UNICODE_NULL );
|
||
|
||
if (ARGUMENT_PRESENT( lpClass )) {
|
||
|
||
//
|
||
// Convert the class name to a counted Unicode string using a counted
|
||
// Unicode string dynamically allocated by RtlAnsiStringToUnicodeString.
|
||
//
|
||
|
||
RtlInitAnsiString( &AnsiString, lpClass );
|
||
Status = RtlAnsiStringToUnicodeString(
|
||
&ClassUnicode,
|
||
&AnsiString,
|
||
TRUE
|
||
);
|
||
|
||
if( ! NT_SUCCESS( Status )) {
|
||
Error = RtlNtStatusToDosError( Status );
|
||
RtlFreeUnicodeString( &SubKey );
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
Class = &ClassUnicode;
|
||
Class->Length += sizeof( UNICODE_NULL );
|
||
|
||
} else {
|
||
|
||
Class = &ClassUnicode;
|
||
|
||
Class->Length = 0;
|
||
Class->MaximumLength = 0;
|
||
Class->Buffer = NULL;
|
||
}
|
||
|
||
//
|
||
// If the caller supplied a LPSECURITY_ATTRIBUTES argument, map
|
||
// it to the RPCable version.
|
||
//
|
||
|
||
if( ARGUMENT_PRESENT( lpSecurityAttributes )) {
|
||
|
||
pRpcSA = &RpcSA;
|
||
|
||
Error = MapSAToRpcSA( lpSecurityAttributes, pRpcSA );
|
||
|
||
if( Error != ERROR_SUCCESS ) {
|
||
RtlFreeUnicodeString( &SubKey );
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// No PSECURITY_ATTRIBUTES argument, therefore no mapping was done.
|
||
//
|
||
|
||
pRpcSA = NULL;
|
||
}
|
||
|
||
//
|
||
// Call the Base API, passing it the supplied parameters and the
|
||
// counted Unicode strings.
|
||
//
|
||
|
||
if( IsLocalHandle( hKey )) {
|
||
|
||
#if defined(_WIN64)
|
||
DWORD dwTempDisposition = 0;
|
||
if ( lpdwDisposition == NULL )
|
||
lpdwDisposition = &dwTempDisposition;
|
||
|
||
//
|
||
// if wow64 reserve field is set in the access mask, call
|
||
// wow64 function to handle the scenario.
|
||
//
|
||
|
||
if ( samDesired & KEY_WOW64_RES ) {
|
||
|
||
Error = (LONG)Wow64RegCreateKeyEx (
|
||
hKey,
|
||
SubKey.Buffer,
|
||
0, //reserved
|
||
Class->Buffer,
|
||
dwOptions,
|
||
samDesired,
|
||
lpSecurityAttributes,
|
||
phkResult,
|
||
lpdwDisposition
|
||
);
|
||
|
||
} else
|
||
#endif
|
||
|
||
Error = (LONG)LocalBaseRegCreateKey (
|
||
hKey,
|
||
&SubKey,
|
||
Class,
|
||
dwOptions,
|
||
samDesired,
|
||
pRpcSA,
|
||
phkResult,
|
||
lpdwDisposition
|
||
);
|
||
#if defined(_WIN64)
|
||
|
||
if ( ( Error == 0) && ( REG_CREATED_NEW_KEY & *lpdwDisposition) ) //only set dirty if its a newly created key
|
||
Wow64RegSetKeyDirty (*phkResult);
|
||
#endif
|
||
} else {
|
||
|
||
Error = (LONG)BaseRegCreateKey (
|
||
DereferenceRemoteHandle( hKey ),
|
||
&SubKey,
|
||
Class,
|
||
dwOptions,
|
||
samDesired,
|
||
pRpcSA,
|
||
phkResult,
|
||
lpdwDisposition
|
||
);
|
||
|
||
if( Error == ERROR_SUCCESS) {
|
||
|
||
TagRemoteHandle( phkResult );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Free the counted Unicode string allocated by
|
||
// RtlAnsiStringToUnicodeString.
|
||
//
|
||
|
||
if (Class != NULL) {
|
||
RtlFreeUnicodeString( Class );
|
||
}
|
||
|
||
//
|
||
// Free the RPC_SECURITY_DESCRIPTOR buffer and return the
|
||
// Registry return value.
|
||
//
|
||
|
||
if( pRpcSA != NULL ) {
|
||
|
||
RtlFreeHeap(
|
||
RtlProcessHeap( ), 0,
|
||
pRpcSA->RpcSecurityDescriptor.lpSecurityDescriptor
|
||
);
|
||
}
|
||
|
||
RtlFreeUnicodeString( &SubKey );
|
||
|
||
ExitCleanup:
|
||
|
||
CLOSE_LOCAL_HANDLE(TempHandle);
|
||
return Error;
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegCreateKeyExW (
|
||
HKEY hKey,
|
||
LPCWSTR lpSubKey,
|
||
DWORD Reserved,
|
||
LPWSTR lpClass,
|
||
DWORD dwOptions,
|
||
REGSAM samDesired,
|
||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||
PHKEY phkResult,
|
||
LPDWORD lpdwDisposition
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win32 Unicode RPC wrapper for opening an existing key or creating a new one.
|
||
|
||
RegCreateKeyExW converts the LPSECURITY_ATTRIBUTES argument to a
|
||
RPC_SECURITY_ATTRIBUTES argument and calls BaseRegCreateKeyExW.
|
||
|
||
--*/
|
||
|
||
{
|
||
UNICODE_STRING SubKey;
|
||
UNICODE_STRING ClassUnicode;
|
||
PUNICODE_STRING Class;
|
||
PRPC_SECURITY_ATTRIBUTES pRpcSA;
|
||
RPC_SECURITY_ATTRIBUTES RpcSA;
|
||
LONG Error;
|
||
PWSTR AuxBuffer;
|
||
HKEY TempHandle = NULL;
|
||
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
||
//
|
||
|
||
if(( hKey == HKEY_PERFORMANCE_DATA ) ||
|
||
( hKey == HKEY_PERFORMANCE_TEXT ) ||
|
||
( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
//
|
||
// Ensure Reserved is zero to avoid future compatability problems.
|
||
//
|
||
|
||
if( Reserved != 0 ) {
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// Validate that the sub key is not NULL.
|
||
//
|
||
|
||
if( ! lpSubKey ) {
|
||
return ERROR_BADKEY;
|
||
}
|
||
|
||
hKey = MapPredefinedHandle( hKey, &TempHandle );
|
||
if( hKey == NULL ) {
|
||
Error = ERROR_INVALID_HANDLE;
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
//
|
||
// Convert the subkey to a counted Unicode string.
|
||
//
|
||
|
||
RtlInitUnicodeString( &SubKey, lpSubKey );
|
||
|
||
//
|
||
// Add terminating NULL to Length so that RPC transmits it.
|
||
//
|
||
SubKey.Length += sizeof( UNICODE_NULL );
|
||
if( SubKey.Length == 0 ) {
|
||
//
|
||
// overflow in RtlInitUnicodeString
|
||
//
|
||
Error = ERROR_INVALID_PARAMETER;
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
if (ARGUMENT_PRESENT( lpClass )) {
|
||
|
||
//
|
||
// Convert the class name to a counted Unicode string.
|
||
//
|
||
|
||
RtlInitUnicodeString( &ClassUnicode, lpClass );
|
||
Class = &ClassUnicode;
|
||
Class->Length += sizeof( UNICODE_NULL );
|
||
|
||
} else {
|
||
|
||
Class = &ClassUnicode;
|
||
|
||
Class->Length = 0;
|
||
Class->MaximumLength = 0;
|
||
Class->Buffer = NULL;
|
||
}
|
||
|
||
|
||
//
|
||
// If the caller supplied a LPSECURITY_ATTRIBUTES argument, map
|
||
// it and call the private version of the create key API.
|
||
//
|
||
|
||
if( ARGUMENT_PRESENT( lpSecurityAttributes )) {
|
||
|
||
pRpcSA = &RpcSA;
|
||
|
||
Error = MapSAToRpcSA( lpSecurityAttributes, pRpcSA );
|
||
|
||
if( Error != ERROR_SUCCESS ) {
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// No PSECURITY_ATTRIBUTES argument, therefore no mapping was done.
|
||
//
|
||
|
||
pRpcSA = NULL;
|
||
}
|
||
|
||
//
|
||
// Call the Base API, passing it the supplied parameters and the
|
||
// counted Unicode strings.
|
||
//
|
||
|
||
if( IsLocalHandle( hKey )) {
|
||
|
||
#if defined(_WIN64)
|
||
DWORD dwTempDisposition = 0;
|
||
if ( lpdwDisposition == NULL )
|
||
lpdwDisposition = &dwTempDisposition;
|
||
|
||
//
|
||
// if wow64 reserve field is set in the access mask, call
|
||
// wow64 function to handle the scenario.
|
||
//
|
||
|
||
if ( samDesired & KEY_WOW64_RES ) {
|
||
|
||
Error = (LONG)Wow64RegCreateKeyEx (
|
||
hKey,
|
||
SubKey.Buffer,
|
||
0, //reserved
|
||
Class->Buffer,
|
||
dwOptions,
|
||
samDesired,
|
||
lpSecurityAttributes,
|
||
phkResult,
|
||
lpdwDisposition
|
||
);
|
||
} else
|
||
#endif
|
||
Error = (LONG)LocalBaseRegCreateKey (
|
||
hKey,
|
||
&SubKey,
|
||
Class,
|
||
dwOptions,
|
||
samDesired,
|
||
pRpcSA,
|
||
phkResult,
|
||
lpdwDisposition
|
||
);
|
||
#if defined(_WIN64)
|
||
|
||
if ( ( Error == 0) && ( REG_CREATED_NEW_KEY & *lpdwDisposition) ) //only set dirty if its a newly created key
|
||
Wow64RegSetKeyDirty (*phkResult);
|
||
#endif
|
||
} else {
|
||
|
||
Error = (LONG)BaseRegCreateKey (
|
||
DereferenceRemoteHandle( hKey ),
|
||
&SubKey,
|
||
Class,
|
||
dwOptions,
|
||
samDesired,
|
||
pRpcSA,
|
||
phkResult,
|
||
lpdwDisposition
|
||
);
|
||
|
||
if( Error == ERROR_SUCCESS) {
|
||
|
||
TagRemoteHandle( phkResult );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Free the RPC_SECURITY_DESCRIPTOR buffer and return the
|
||
// Registry return value.
|
||
//
|
||
|
||
if( pRpcSA != NULL ) {
|
||
|
||
RtlFreeHeap(
|
||
RtlProcessHeap( ), 0,
|
||
pRpcSA->RpcSecurityDescriptor.lpSecurityDescriptor
|
||
);
|
||
}
|
||
|
||
ExitCleanup:
|
||
|
||
CLOSE_LOCAL_HANDLE(TempHandle);
|
||
return Error;
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegFlushKey (
|
||
IN HKEY hKey
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win32 RPC wrapper for flushing changes to backing store.
|
||
|
||
--*/
|
||
|
||
{
|
||
LONG Error;
|
||
HKEY TempHandle = NULL;
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Flush is a NO-OP for HKEY_PERFORMANCE_DATA.
|
||
//
|
||
|
||
if(( hKey == HKEY_PERFORMANCE_DATA ) ||
|
||
( hKey == HKEY_PERFORMANCE_TEXT ) ||
|
||
( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
hKey = MapPredefinedHandle( hKey, &TempHandle );
|
||
if( hKey == NULL ) {
|
||
Error = ERROR_INVALID_HANDLE;
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
if( IsLocalHandle( hKey )) {
|
||
|
||
Error = (LONG)LocalBaseRegFlushKey( hKey );
|
||
|
||
} else {
|
||
|
||
Error = (LONG)BaseRegFlushKey( DereferenceRemoteHandle( hKey ));
|
||
}
|
||
|
||
ExitCleanup:
|
||
|
||
CLOSE_LOCAL_HANDLE(TempHandle);
|
||
return Error;
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegOpenKeyA (
|
||
HKEY hKey,
|
||
LPCSTR lpSubKey,
|
||
PHKEY phkResult
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win 3.1 ANSI RPC wrapper for opening an existing key.
|
||
|
||
--*/
|
||
|
||
{
|
||
LONG Error;
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
if( phkResult == NULL ) {
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// Win3.1ism - Win 3.1 allows the predefined handle to be opened by
|
||
// specifying a pointer to an empty or NULL string for the sub-key.
|
||
//
|
||
|
||
//
|
||
// If the subkey is NULL or points to a NUL string and the handle is
|
||
// predefined, just return the predefined handle (a virtual open)
|
||
// otherwise return the same handle that was passed in.
|
||
//
|
||
|
||
if(( lpSubKey == NULL ) || ( *lpSubKey == '\0' )) {
|
||
if( !IsPredefinedRegistryHandle( hKey )) {
|
||
*phkResult = hKey;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
/*
|
||
if( IsPredefinedRegistryHandle( hKey )) {
|
||
|
||
*phkResult = hKey;
|
||
return ERROR_SUCCESS;
|
||
|
||
} else {
|
||
|
||
return ERROR_BADKEY;
|
||
}
|
||
*/
|
||
}
|
||
|
||
Error = (LONG)RegOpenKeyExA(
|
||
hKey,
|
||
lpSubKey,
|
||
REG_OPTION_RESERVED,
|
||
WIN31_REGSAM,
|
||
phkResult
|
||
);
|
||
|
||
return Error;
|
||
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegOpenKeyW (
|
||
HKEY hKey,
|
||
LPCWSTR lpSubKey,
|
||
PHKEY phkResult
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win 3.1 Unicode RPC wrapper for opening an existing key.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
LONG Error;
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
OutputDebugString( "In RegOpenKeyW\n" );
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
if( phkResult == NULL ) {
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// Win3.1ism - Win 3.1 allows the predefined handle to be opened by
|
||
// specifying a pointer to an empty or NULL string for the sub-key.
|
||
//
|
||
|
||
//
|
||
// If the subkey is NULL or points to a NUL string and the handle is
|
||
// predefined, just return the predefined handle (a virtual open)
|
||
// otherwise return the handle passed in.
|
||
//
|
||
|
||
if(( lpSubKey == NULL ) || ( *lpSubKey == '\0' )) {
|
||
if( !IsPredefinedRegistryHandle( hKey )) {
|
||
*phkResult = hKey;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
/*
|
||
if( IsPredefinedRegistryHandle( hKey )) {
|
||
|
||
*phkResult = hKey;
|
||
return ERROR_SUCCESS;
|
||
|
||
} else {
|
||
|
||
return ERROR_BADKEY;
|
||
}
|
||
*/
|
||
}
|
||
|
||
Error = (LONG)RegOpenKeyExW(
|
||
hKey,
|
||
lpSubKey,
|
||
REG_OPTION_RESERVED,
|
||
WIN31_REGSAM,
|
||
phkResult
|
||
);
|
||
|
||
return Error;
|
||
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegOpenKeyExA (
|
||
HKEY hKey,
|
||
LPCSTR lpSubKey,
|
||
DWORD dwOptions,
|
||
REGSAM samDesired,
|
||
PHKEY phkResult
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win32 ANSI RPC wrapper for opening an existing key.
|
||
|
||
RegOpenKeyExA converts the lpSubKey argument to a counted Unicode string
|
||
and then calls BaseRegOpenKey.
|
||
|
||
--*/
|
||
|
||
{
|
||
UNICODE_STRING SubKey;
|
||
NTSTATUS Status;
|
||
LONG Error;
|
||
CHAR NullString;
|
||
HKEY TempHandle = NULL;
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
||
//
|
||
|
||
if(( hKey == HKEY_PERFORMANCE_DATA ) ||
|
||
( hKey == HKEY_PERFORMANCE_TEXT ) ||
|
||
( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
//
|
||
// Caller must pass pointer to the variable where the opened handle
|
||
// will be returned
|
||
//
|
||
|
||
if( phkResult == NULL ) {
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// If lpSubKey is NULL, then assume NUL-string as subkey name
|
||
//
|
||
|
||
if( lpSubKey == NULL ) {
|
||
NullString = ( CHAR )'\0';
|
||
lpSubKey = &NullString;
|
||
}
|
||
|
||
//
|
||
// If hKey is a predefined key, and lpSubKey is either a NULL pointer or
|
||
// a NUL string, close the predefined key and clear the associated entry
|
||
// in the PredefinedHandleTable (RegCloseKey will do the job).
|
||
//
|
||
if( IsPredefinedRegistryHandle( hKey ) && (!( samDesired & KEY_WOW64_RES )) &&
|
||
( ( lpSubKey == NULL ) || ( *lpSubKey == '\0' ) ) ) {
|
||
|
||
if ( HKEY_CLASSES_ROOT != hKey ) {
|
||
Error = RegCloseKey( hKey );
|
||
if( Error != ERROR_SUCCESS ) {
|
||
return( Error );
|
||
}
|
||
//
|
||
// Create a handle and save it in the appropriate entry in
|
||
// PredefinedHandleTable.
|
||
// Notice that the client will be impersonated.
|
||
// (MapPredefinedHandle will do all this stuff).
|
||
//
|
||
if( MapPredefinedHandle( hKey, &TempHandle ) == NULL ) {
|
||
Error = ERROR_INVALID_HANDLE;
|
||
goto ExitCleanup;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Return to the user the handle passed in
|
||
//
|
||
*phkResult = hKey;
|
||
Error = ERROR_SUCCESS;
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
|
||
//
|
||
// Validate that the sub key is not NULL.
|
||
//
|
||
|
||
ASSERT( lpSubKey != NULL );
|
||
if( ! lpSubKey ) {
|
||
Error = ERROR_BADKEY;
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
hKey = MapPredefinedHandle( hKey, &TempHandle );
|
||
if( hKey == NULL ) {
|
||
Error = ERROR_INVALID_HANDLE;
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
//
|
||
// Convert the subkey to a counted Unicode string
|
||
//
|
||
if( !RtlCreateUnicodeStringFromAsciiz(&SubKey,lpSubKey) ) {
|
||
Status = STATUS_NO_MEMORY;
|
||
Error = RtlNtStatusToDosError( Status );
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
//
|
||
// Add terminating NULL to Length so that RPC transmits it.
|
||
//
|
||
SubKey.Length += sizeof( UNICODE_NULL );
|
||
|
||
|
||
//
|
||
// Call the Base API, passing it the supplied parameters and the
|
||
// counted Unicode strings.
|
||
//
|
||
|
||
if( IsLocalHandle( hKey )) {
|
||
#if defined(_WIN64)
|
||
|
||
//
|
||
// if wow64 reserve field is set in the access mask, call
|
||
// wow64 function to handle the scenario.
|
||
//
|
||
|
||
if ( samDesired & KEY_WOW64_RES ) {
|
||
|
||
Error = (LONG)Wow64RegOpenKeyEx (
|
||
hKey,
|
||
SubKey.Buffer,
|
||
dwOptions,
|
||
samDesired,
|
||
phkResult
|
||
);
|
||
} else
|
||
#endif
|
||
|
||
Error = (LONG)LocalBaseRegOpenKey (
|
||
hKey,
|
||
&SubKey,
|
||
dwOptions,
|
||
samDesired,
|
||
phkResult
|
||
);
|
||
} else {
|
||
|
||
Error = (LONG)BaseRegOpenKey (
|
||
DereferenceRemoteHandle( hKey ),
|
||
&SubKey,
|
||
dwOptions,
|
||
samDesired,
|
||
phkResult
|
||
);
|
||
|
||
if( Error == ERROR_SUCCESS) {
|
||
|
||
TagRemoteHandle( phkResult );
|
||
}
|
||
}
|
||
|
||
// free the allocated unicode string
|
||
RtlFreeUnicodeString( &SubKey );
|
||
|
||
ExitCleanup:
|
||
|
||
CLOSE_LOCAL_HANDLE(TempHandle);
|
||
return Error;
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegOpenKeyExW (
|
||
HKEY hKey,
|
||
LPCWSTR lpSubKey,
|
||
DWORD dwOptions,
|
||
REGSAM samDesired,
|
||
PHKEY phkResult
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win32 Unicode RPC wrapper for opening an existing key.
|
||
|
||
RegOpenKeyExW converts the lpSubKey argument to a counted Unicode string
|
||
and then calls BaseRegOpenKey.
|
||
|
||
--*/
|
||
|
||
{
|
||
UNICODE_STRING SubKey;
|
||
LONG Error;
|
||
WCHAR NullString;
|
||
HKEY TempHandle = NULL;
|
||
|
||
#if DBG
|
||
if ( BreakPointOnEntry ) {
|
||
DbgBreakPoint();
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
||
//
|
||
|
||
if(( hKey == HKEY_PERFORMANCE_DATA ) ||
|
||
( hKey == HKEY_PERFORMANCE_TEXT ) ||
|
||
( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
//
|
||
// Caller must pass pointer to the variable where the opened handle
|
||
// will be returned
|
||
//
|
||
|
||
if( phkResult == NULL ) {
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// If lpSubKey is NULL, then assume NUL-string as subkey name
|
||
//
|
||
|
||
if( lpSubKey == NULL ) {
|
||
NullString = UNICODE_NULL;
|
||
lpSubKey = &NullString;
|
||
}
|
||
|
||
//
|
||
// If hKey is a predefined key, and lpSubKey is either a NULL pointer or
|
||
// a NUL string, close the predefined key and clear the associated entry
|
||
// in the PredefinedHandleTable (RegCloseKey will do the job).
|
||
//
|
||
if( IsPredefinedRegistryHandle( hKey ) && (!( samDesired & KEY_WOW64_RES )) &&
|
||
( ( lpSubKey == NULL ) || ( *lpSubKey == ( WCHAR )'\0' ) ) ) {
|
||
|
||
if ( HKEY_CLASSES_ROOT != hKey ) {
|
||
Error = RegCloseKey( hKey );
|
||
if( Error != ERROR_SUCCESS ) {
|
||
return( Error );
|
||
}
|
||
//
|
||
// Create a handle and save it in the appropriate entry in
|
||
// PredefinedHandleTable.
|
||
// Notice that the client will be impersonated.
|
||
// (MapPredefinedHandle will do all this stuff).
|
||
//
|
||
if( MapPredefinedHandle( hKey, &TempHandle ) == NULL ) {
|
||
Error = ERROR_INVALID_HANDLE;
|
||
goto ExitCleanup;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Return to the user the handle passed in
|
||
//
|
||
*phkResult = hKey;
|
||
Error = ERROR_SUCCESS;
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
//
|
||
// Validate that the sub key is not NULL.
|
||
//
|
||
|
||
ASSERT( lpSubKey != NULL );
|
||
if( ! lpSubKey ) {
|
||
Error = ERROR_BADKEY;
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
|
||
hKey = MapPredefinedHandle( hKey, &TempHandle );
|
||
if( hKey == NULL ) {
|
||
Error = ERROR_INVALID_HANDLE;
|
||
goto ExitCleanup;
|
||
}
|
||
|
||
//
|
||
// Convert the subkey to a counted Unicode string.
|
||
//
|
||
|
||
RtlInitUnicodeString( &SubKey, lpSubKey );
|
||
|
||
//
|
||
// Add terminating NULL to Length so that RPC transmits it
|
||
//
|
||
SubKey.Length += sizeof (UNICODE_NULL );
|
||
|
||
//
|
||
// Call the Base API, passing it the supplied parameters and the
|
||
// counted Unicode strings.
|
||
//
|
||
|
||
if( IsLocalHandle( hKey )) {
|
||
|
||
#if defined(_WIN64)
|
||
//
|
||
// if wow64 reserve field is set in the access mask, call
|
||
// wow64 function to handle the scenario.
|
||
//
|
||
|
||
if ( samDesired & KEY_WOW64_RES ) {
|
||
|
||
Error = (LONG)Wow64RegOpenKeyEx (
|
||
hKey,
|
||
SubKey.Buffer,
|
||
dwOptions,
|
||
samDesired,
|
||
phkResult
|
||
);
|
||
} else
|
||
#endif
|
||
Error = (LONG)LocalBaseRegOpenKey (
|
||
hKey,
|
||
&SubKey,
|
||
dwOptions,
|
||
samDesired,
|
||
phkResult
|
||
);
|
||
} else {
|
||
|
||
Error = (LONG)BaseRegOpenKey (
|
||
DereferenceRemoteHandle( hKey ),
|
||
&SubKey,
|
||
dwOptions,
|
||
samDesired,
|
||
phkResult
|
||
);
|
||
|
||
if( Error == ERROR_SUCCESS) {
|
||
|
||
TagRemoteHandle( phkResult );
|
||
}
|
||
}
|
||
|
||
ExitCleanup:
|
||
|
||
CLOSE_LOCAL_HANDLE(TempHandle);
|
||
return Error;
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegOpenCurrentUser(
|
||
REGSAM samDesired,
|
||
PHKEY phkResult
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win32 Client-Only function to open the key for HKEY_CURRENT_USER
|
||
for the user that the thread is currently impersonating. Since
|
||
HKEY_CURRENT_USER is cached for all threads in a process, if the
|
||
process is impersonating multiple users, this allows access to
|
||
the appropriate key.
|
||
|
||
Arguments:
|
||
|
||
samDesired - Supplies the requested security access mask.
|
||
|
||
phkResult - Returns an open handle to the key.
|
||
|
||
Return Value:
|
||
|
||
Returns 0 (ERROR_SUCCESS) for success, otherwise a windows error code.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status ;
|
||
|
||
Status = RtlOpenCurrentUser( samDesired, phkResult );
|
||
|
||
#if defined(LEAK_TRACK)
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
if (g_RegLeakTraceInfo.bEnableLeakTrack) {
|
||
(void) TrackObject(*phkResult);
|
||
}
|
||
}
|
||
|
||
#endif // (LEAK_TRACK)
|
||
|
||
return RtlNtStatusToDosError( Status );
|
||
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegDisablePredefinedCache(
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win32 Client-Only function to disable the predefined handle table
|
||
for HKEY_CURRENT_USER for the calling process
|
||
All references to HKEY_CURRENT_USER after this function is called
|
||
will result in a open/close on HKU\<sid>
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
Returns 0 (ERROR_SUCCESS) for success, otherwise a windows error code.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status ;
|
||
|
||
Status = DisablePredefinedHandleTable( HKEY_CURRENT_USER );
|
||
|
||
return RtlNtStatusToDosError( Status );
|
||
}
|
||
|