1081 lines
23 KiB
C
1081 lines
23 KiB
C
/*++
|
||
|
||
Copyright (c) 1992 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
|
||
|
||
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"
|
||
|
||
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 )) {
|
||
|
||
return ( LONG ) LocalBaseRegCloseKey( &hKey );
|
||
|
||
} else {
|
||
|
||
hKey = DereferenceRemoteHandle( hKey );
|
||
return ( LONG ) BaseRegCloseKey( &hKey );
|
||
}
|
||
}
|
||
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
PUNICODE_STRING SubKey;
|
||
UNICODE_STRING ClassUnicode;
|
||
PUNICODE_STRING Class;
|
||
ANSI_STRING AnsiString;
|
||
PRPC_SECURITY_ATTRIBUTES pRpcSA;
|
||
RPC_SECURITY_ATTRIBUTES RpcSA;
|
||
NTSTATUS Status;
|
||
LONG Error;
|
||
|
||
|
||
#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.
|
||
//
|
||
|
||
ASSERT( lpSubKey != NULL );
|
||
if( ! lpSubKey ) {
|
||
return ERROR_BADKEY;
|
||
}
|
||
|
||
hKey = MapPredefinedHandle( hKey );
|
||
if( hKey == NULL ) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
//
|
||
// Convert the subkey to a counted Unicode string using the static
|
||
// Unicode string in the TEB.
|
||
//
|
||
|
||
SubKey = &NtCurrentTeb( )->StaticUnicodeString;
|
||
ASSERT( SubKey != NULL );
|
||
RtlInitAnsiString( &AnsiString, lpSubKey );
|
||
Status = RtlAnsiStringToUnicodeString(
|
||
SubKey,
|
||
&AnsiString,
|
||
FALSE
|
||
);
|
||
|
||
if( ! NT_SUCCESS( Status )) {
|
||
return RtlNtStatusToDosError( Status );
|
||
}
|
||
|
||
//
|
||
// 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 )) {
|
||
return RtlNtStatusToDosError( Status );
|
||
}
|
||
|
||
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 ) {
|
||
return Error;
|
||
}
|
||
|
||
} 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 )) {
|
||
|
||
Error = (LONG)LocalBaseRegCreateKey (
|
||
hKey,
|
||
SubKey,
|
||
Class,
|
||
dwOptions,
|
||
samDesired,
|
||
pRpcSA,
|
||
phkResult,
|
||
lpdwDisposition
|
||
);
|
||
} 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
|
||
);
|
||
}
|
||
|
||
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;
|
||
|
||
|
||
#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.
|
||
//
|
||
|
||
ASSERT( lpSubKey != NULL );
|
||
if( ! lpSubKey ) {
|
||
return ERROR_BADKEY;
|
||
}
|
||
|
||
hKey = MapPredefinedHandle( hKey );
|
||
if( hKey == NULL ) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
//
|
||
// 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 (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 ) {
|
||
return Error;
|
||
}
|
||
|
||
} 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 )) {
|
||
|
||
Error = (LONG)LocalBaseRegCreateKey (
|
||
hKey,
|
||
&SubKey,
|
||
Class,
|
||
dwOptions,
|
||
samDesired,
|
||
pRpcSA,
|
||
phkResult,
|
||
lpdwDisposition
|
||
);
|
||
|
||
} 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
|
||
);
|
||
}
|
||
|
||
return Error;
|
||
}
|
||
|
||
LONG
|
||
APIENTRY
|
||
RegFlushKey (
|
||
IN HKEY hKey
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Win32 RPC wrapper for flushing changes to backing store.
|
||
|
||
--*/
|
||
|
||
{
|
||
#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 );
|
||
if( hKey == NULL ) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
if( IsLocalHandle( hKey )) {
|
||
|
||
return (LONG)LocalBaseRegFlushKey( hKey );
|
||
|
||
} else {
|
||
|
||
return (LONG)BaseRegFlushKey( DereferenceRemoteHandle( hKey ));
|
||
}
|
||
}
|
||
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
PUNICODE_STRING SubKey;
|
||
ANSI_STRING AnsiString;
|
||
NTSTATUS Status;
|
||
LONG Error;
|
||
CHAR NullString;
|
||
|
||
|
||
#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 ) &&
|
||
( ( lpSubKey == NULL ) || ( *lpSubKey == '\0' ) ) ) {
|
||
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 ) == NULL ) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
//
|
||
// Return to the user the handle passed in
|
||
//
|
||
*phkResult = hKey;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
|
||
//
|
||
// Validate that the sub key is not NULL.
|
||
//
|
||
|
||
ASSERT( lpSubKey != NULL );
|
||
if( ! lpSubKey ) {
|
||
return ERROR_BADKEY;
|
||
}
|
||
|
||
hKey = MapPredefinedHandle( hKey );
|
||
if( hKey == NULL ) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
//
|
||
// Convert the subkey to a counted Unicode string using the static
|
||
// Unicode string in the TEB.
|
||
//
|
||
|
||
SubKey = &NtCurrentTeb( )->StaticUnicodeString;
|
||
ASSERT( SubKey != NULL );
|
||
RtlInitAnsiString( &AnsiString, lpSubKey );
|
||
Status = RtlAnsiStringToUnicodeString(
|
||
SubKey,
|
||
&AnsiString,
|
||
FALSE
|
||
);
|
||
|
||
if( ! NT_SUCCESS( Status )) {
|
||
return RtlNtStatusToDosError( Status );
|
||
}
|
||
|
||
//
|
||
// 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 )) {
|
||
|
||
Error = (LONG)LocalBaseRegOpenKey (
|
||
hKey,
|
||
SubKey,
|
||
dwOptions,
|
||
samDesired,
|
||
phkResult
|
||
);
|
||
} else {
|
||
|
||
Error = (LONG)BaseRegOpenKey (
|
||
DereferenceRemoteHandle( hKey ),
|
||
SubKey,
|
||
dwOptions,
|
||
samDesired,
|
||
phkResult
|
||
);
|
||
|
||
if( Error == ERROR_SUCCESS) {
|
||
|
||
TagRemoteHandle( phkResult );
|
||
}
|
||
}
|
||
|
||
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;
|
||
|
||
#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 ) &&
|
||
( ( lpSubKey == NULL ) || ( *lpSubKey == ( WCHAR )'\0' ) ) ) {
|
||
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 ) == NULL ) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
//
|
||
// Return to the user the handle passed in
|
||
//
|
||
*phkResult = hKey;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// Validate that the sub key is not NULL.
|
||
//
|
||
|
||
ASSERT( lpSubKey != NULL );
|
||
if( ! lpSubKey ) {
|
||
return ERROR_BADKEY;
|
||
}
|
||
|
||
|
||
hKey = MapPredefinedHandle( hKey );
|
||
if( hKey == NULL ) {
|
||
return ERROR_INVALID_HANDLE;
|
||
}
|
||
|
||
//
|
||
// 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 )) {
|
||
|
||
Error = (LONG)LocalBaseRegOpenKey (
|
||
hKey,
|
||
&SubKey,
|
||
dwOptions,
|
||
samDesired,
|
||
phkResult
|
||
);
|
||
} else {
|
||
|
||
Error = (LONG)BaseRegOpenKey (
|
||
DereferenceRemoteHandle( hKey ),
|
||
&SubKey,
|
||
dwOptions,
|
||
samDesired,
|
||
phkResult
|
||
);
|
||
|
||
if( Error == ERROR_SUCCESS) {
|
||
|
||
TagRemoteHandle( phkResult );
|
||
}
|
||
}
|
||
|
||
return Error;
|
||
}
|