NT4/private/windows/screg/winreg/client/regkey.c
2020-09-30 17:12:29 +02:00

1081 lines
23 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
}