You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
796 lines
18 KiB
796 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Reglukey.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the client side wrappers for the Win32 Registry
|
|
APIs to load, unload and replace keys. That is:
|
|
|
|
- RegLoadKeyA
|
|
- RegLoadKeyW
|
|
- RegUnLoadKeyA
|
|
- RegUnLoadKeyW
|
|
- RegReplaceKeyA
|
|
- RegReplaceKeyW
|
|
|
|
Author:
|
|
|
|
|
|
Ramon J. San Andres (ramonsa) 16-Apr-1992
|
|
|
|
|
|
|
|
--*/
|
|
|
|
#include <rpc.h>
|
|
#include "regrpc.h"
|
|
#include "client.h"
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegLoadKeyA(
|
|
HKEY hKey,
|
|
LPCSTR lpSubKey,
|
|
LPCSTR lpFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Win32 Ansi API for loading a key.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HKEY Handle;
|
|
UNICODE_STRING SubKey;
|
|
UNICODE_STRING File;
|
|
WCHAR UnicodeBuffer[ MAX_PATH ];
|
|
ANSI_STRING AnsiFile;
|
|
NTSTATUS NtStatus;
|
|
LONG Error;
|
|
HKEY TempHandle = NULL;
|
|
|
|
#if DBG
|
|
// OutputDebugString( "Winreg: Entering RegLoadKeyA\n" );
|
|
if ( BreakPointOnEntry ) {
|
|
DbgBreakPoint();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
|
//
|
|
|
|
if( hKey == HKEY_PERFORMANCE_DATA ) {
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
Handle = MapPredefinedHandle( hKey, &TempHandle );
|
|
if ( Handle == NULL ) {
|
|
Error = ERROR_INVALID_HANDLE;
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Convert the SubKey name to a counted Unicode
|
|
//
|
|
if( !RtlCreateUnicodeStringFromAsciiz(&SubKey,lpSubKey) ) {
|
|
NtStatus = STATUS_NO_MEMORY;
|
|
Error = RtlNtStatusToDosError( NtStatus );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Add the NULL to the length so that RPC will transmit the entire
|
|
// thing
|
|
//
|
|
if ( SubKey.Length > 0 ) {
|
|
SubKey.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
|
|
//
|
|
// Convert the file name to a counted Unicode string using the
|
|
// Unicode string on the stack.
|
|
//
|
|
File.Buffer = UnicodeBuffer;
|
|
File.MaximumLength = sizeof( UnicodeBuffer );
|
|
RtlInitAnsiString( &AnsiFile, lpFile );
|
|
NtStatus = RtlAnsiStringToUnicodeString(
|
|
&File,
|
|
&AnsiFile,
|
|
FALSE
|
|
);
|
|
|
|
//
|
|
// If the file name could not be converted, map the results and return.
|
|
//
|
|
if( ! NT_SUCCESS( NtStatus )) {
|
|
// free the allocated unicode string
|
|
RtlFreeUnicodeString( &SubKey );
|
|
|
|
Error = RtlNtStatusToDosError( NtStatus );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Add the NULL to the length so that RPC will transmit the entire
|
|
// thing
|
|
//
|
|
if ( File.Length > 0 ) {
|
|
File.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
//
|
|
// Call the server
|
|
//
|
|
|
|
if( IsLocalHandle( Handle )) {
|
|
|
|
Error = (LONG)LocalBaseRegLoadKey(
|
|
Handle,
|
|
&SubKey,
|
|
&File
|
|
);
|
|
|
|
} else {
|
|
|
|
Error = (LONG)BaseRegLoadKey(
|
|
DereferenceRemoteHandle( Handle ),
|
|
&SubKey,
|
|
&File
|
|
);
|
|
}
|
|
|
|
// free the allocated unicode string
|
|
RtlFreeUnicodeString( &SubKey );
|
|
|
|
ExitCleanup:
|
|
|
|
CLOSE_LOCAL_HANDLE(TempHandle);
|
|
return Error;
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegLoadKeyW(
|
|
HKEY hKey,
|
|
LPCWSTR lpSubKey,
|
|
LPCWSTR lpFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Load the tree in the supplied file into the key referenced by the
|
|
supplied key handle and sub-key. The loaded tree will overwrite all
|
|
of the contents of the supplied sub-key except for its name.
|
|
Pictorially, if the file contains:
|
|
|
|
A
|
|
/ \
|
|
/ \
|
|
B C
|
|
|
|
and the supplied key refers to a key name X, the resultant tree would
|
|
look like:
|
|
|
|
X
|
|
/ \
|
|
/ \
|
|
B C
|
|
|
|
Arguments:
|
|
|
|
hKey - Supplies the predefined handle HKEY_USERS or HKEY_LOCAL_MACHINE.
|
|
lpSubKey is relative to this handle.
|
|
|
|
lpSubKey - Supplies a path name to a new (i.e. non-existant) key
|
|
where the supplied file will be loaded.
|
|
|
|
lpFile - Supplies a pointer to an existing file name whose contents was
|
|
created with RegSaveKey. The file name may not have an extension.
|
|
|
|
Return Value:
|
|
|
|
Returns ERROR_SUCCESS (0) for success; error-code for failure.
|
|
|
|
Notes:
|
|
|
|
The difference between RegRestoreKey and RegLoadKey is that in the
|
|
latter case the supplied file is used as the actual backing store
|
|
whereas in the former case the information in the file is copied into
|
|
the Registry.
|
|
|
|
RegLoadKey requires SeRestorePrivilege.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HKEY Handle;
|
|
UNICODE_STRING SubKey;
|
|
UNICODE_STRING File;
|
|
LONG Error;
|
|
HKEY TempHandle = NULL;
|
|
NTSTATUS Status;
|
|
|
|
|
|
#if DBG
|
|
if ( BreakPointOnEntry ) {
|
|
DbgBreakPoint();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
|
//
|
|
|
|
if( hKey == HKEY_PERFORMANCE_DATA ) {
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
Handle = MapPredefinedHandle( hKey, &TempHandle );
|
|
if ( Handle == NULL ) {
|
|
Error = ERROR_INVALID_HANDLE;
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Convert the subkey to a counted Unicode string.
|
|
// This also acounts for the NULL we are adding at the end
|
|
//
|
|
Status = RtlInitUnicodeStringEx(&SubKey, lpSubKey);
|
|
if( !NT_SUCCESS(Status) ) {
|
|
Error = RtlNtStatusToDosError( Status );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Add the NULL to the length so that RPC will transmit the entire
|
|
// thing
|
|
//
|
|
if ( SubKey.Length > 0 ) {
|
|
SubKey.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
|
|
Status = RtlInitUnicodeStringEx(&File, lpFile);
|
|
if( !NT_SUCCESS(Status) ) {
|
|
Error = RtlNtStatusToDosError( Status );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Add the NULL to the length so that RPC will transmit the entire
|
|
// thing
|
|
//
|
|
if ( File.Length > 0 ) {
|
|
File.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
|
|
//
|
|
// Call the server
|
|
//
|
|
|
|
if( IsLocalHandle( Handle )) {
|
|
|
|
Error = (LONG)LocalBaseRegLoadKey(
|
|
Handle,
|
|
&SubKey,
|
|
&File
|
|
);
|
|
|
|
} else {
|
|
|
|
Error = (LONG)BaseRegLoadKey(
|
|
DereferenceRemoteHandle( Handle ),
|
|
&SubKey,
|
|
&File
|
|
);
|
|
}
|
|
ExitCleanup:
|
|
|
|
CLOSE_LOCAL_HANDLE(TempHandle);
|
|
return Error;
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegUnLoadKeyA(
|
|
HKEY hKey,
|
|
LPCSTR lpSubKey
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Win32 Ansi API for unloading a key.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HKEY Handle;
|
|
UNICODE_STRING SubKey;
|
|
NTSTATUS NtStatus;
|
|
LONG Error;
|
|
HKEY TempHandle = NULL;
|
|
|
|
#if DBG
|
|
if ( BreakPointOnEntry ) {
|
|
DbgBreakPoint();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
|
//
|
|
|
|
if( hKey == HKEY_PERFORMANCE_DATA ) {
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
Handle = MapPredefinedHandle( hKey,&TempHandle );
|
|
if ( Handle == NULL ) {
|
|
Error = ERROR_INVALID_HANDLE;
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Convert the SubKey name to a counted Unicode
|
|
//
|
|
if( !RtlCreateUnicodeStringFromAsciiz(&SubKey,lpSubKey) ) {
|
|
NtStatus = STATUS_NO_MEMORY;
|
|
Error = RtlNtStatusToDosError( NtStatus );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Add the NULL to the length so that RPC will transmit the entire
|
|
// thing
|
|
//
|
|
if ( SubKey.Length > 0 ) {
|
|
SubKey.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
|
|
if( IsLocalHandle( Handle )) {
|
|
|
|
Error = (LONG)LocalBaseRegUnLoadKey(
|
|
Handle,
|
|
&SubKey
|
|
);
|
|
|
|
} else {
|
|
|
|
Error = (LONG)BaseRegUnLoadKey(
|
|
DereferenceRemoteHandle( Handle ),
|
|
&SubKey
|
|
);
|
|
}
|
|
|
|
// free the allocated unicode string
|
|
RtlFreeUnicodeString( &SubKey );
|
|
ExitCleanup:
|
|
|
|
CLOSE_LOCAL_HANDLE(TempHandle);
|
|
return Error;
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegUnLoadKeyW(
|
|
HKEY hKey,
|
|
LPCWSTR lpSubKey
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Unload the specified tree (hive) from the Registry.
|
|
|
|
Arguments:
|
|
|
|
hKey - Supplies a handle to an open key. lpSubKey is relative to this
|
|
handle.
|
|
|
|
lpSubKey - Supplies a path name to the key that is to be unloaded.
|
|
The combination of hKey and lpSubKey must refer to a hive in the
|
|
Registry created with RegRestoreKey or RegLoadKey. This parameter may
|
|
be NULL.
|
|
|
|
Return Value:
|
|
|
|
Returns ERROR_SUCCESS (0) for success; error-code for failure.
|
|
|
|
RegUnLoadKey requires SeRestorePrivilege.
|
|
|
|
--*/
|
|
|
|
{
|
|
HKEY Handle;
|
|
UNICODE_STRING SubKey;
|
|
LONG Error;
|
|
HKEY TempHandle = NULL;
|
|
NTSTATUS Status;
|
|
|
|
#if DBG
|
|
if ( BreakPointOnEntry ) {
|
|
DbgBreakPoint();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
|
//
|
|
|
|
if( hKey == HKEY_PERFORMANCE_DATA ) {
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
Handle = MapPredefinedHandle( hKey, &TempHandle );
|
|
if ( Handle == NULL ) {
|
|
Error = ERROR_INVALID_HANDLE;
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
|
|
Status = RtlInitUnicodeStringEx(&SubKey, lpSubKey);
|
|
if( !NT_SUCCESS(Status) ) {
|
|
Error = RtlNtStatusToDosError( Status );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Add the NULL to the length so that RPC will transmit the entire
|
|
// thing
|
|
//
|
|
if ( SubKey.Length > 0 ) {
|
|
SubKey.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
|
|
//
|
|
// Call the server
|
|
//
|
|
if( IsLocalHandle( Handle )) {
|
|
|
|
Error = (LONG)LocalBaseRegUnLoadKey(
|
|
Handle,
|
|
&SubKey
|
|
);
|
|
|
|
} else {
|
|
|
|
Error = (LONG)BaseRegUnLoadKey(
|
|
DereferenceRemoteHandle( Handle ),
|
|
&SubKey
|
|
);
|
|
}
|
|
|
|
ExitCleanup:
|
|
|
|
CLOSE_LOCAL_HANDLE(TempHandle);
|
|
return Error;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegReplaceKeyA(
|
|
HKEY hKey,
|
|
LPCSTR lpSubKey,
|
|
LPCSTR lpNewFile,
|
|
LPCSTR lpOldFile
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Win32 Ansi API for replacing a key.
|
|
|
|
--*/
|
|
{
|
|
HKEY Handle;
|
|
UNICODE_STRING SubKey;
|
|
UNICODE_STRING NewFile;
|
|
UNICODE_STRING OldFile;
|
|
WCHAR NewUnicodeBuffer[ MAX_PATH ];
|
|
WCHAR OldUnicodeBuffer[ MAX_PATH ];
|
|
ANSI_STRING AnsiFile;
|
|
NTSTATUS NtStatus;
|
|
LONG Error;
|
|
HKEY TempHandle = NULL;
|
|
|
|
#if DBG
|
|
if ( BreakPointOnEntry ) {
|
|
DbgBreakPoint();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
|
//
|
|
|
|
if( hKey == HKEY_PERFORMANCE_DATA ) {
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
Handle = MapPredefinedHandle( hKey, &TempHandle );
|
|
if ( Handle == NULL ) {
|
|
Error = ERROR_INVALID_HANDLE;
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Convert the SubKey name to a counted Unicode
|
|
//
|
|
if( !RtlCreateUnicodeStringFromAsciiz(&SubKey,lpSubKey) ) {
|
|
NtStatus = STATUS_NO_MEMORY;
|
|
Error = RtlNtStatusToDosError( NtStatus );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Convert the new file name to a counted Unicode string using the
|
|
// Unicode string on the stack.
|
|
//
|
|
NewFile.Buffer = NewUnicodeBuffer;
|
|
NewFile.MaximumLength = sizeof( NewUnicodeBuffer );
|
|
RtlInitAnsiString( &AnsiFile, lpNewFile );
|
|
NtStatus = RtlAnsiStringToUnicodeString(
|
|
&NewFile,
|
|
&AnsiFile,
|
|
FALSE
|
|
);
|
|
|
|
//
|
|
// If the file name could not be converted, map the results and return.
|
|
//
|
|
if( ! NT_SUCCESS( NtStatus )) {
|
|
// free the allocated unicode string
|
|
RtlFreeUnicodeString( &SubKey );
|
|
Error = RtlNtStatusToDosError( NtStatus );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Convert the old file name to a counted Unicode string using the
|
|
// Unicode string on the stack.
|
|
//
|
|
OldFile.Buffer = OldUnicodeBuffer;
|
|
OldFile.MaximumLength = sizeof( OldUnicodeBuffer );
|
|
RtlInitAnsiString( &AnsiFile, lpOldFile );
|
|
NtStatus = RtlAnsiStringToUnicodeString(
|
|
&OldFile,
|
|
&AnsiFile,
|
|
FALSE
|
|
);
|
|
|
|
//
|
|
// If the file name could not be converted, map the results and return.
|
|
//
|
|
if( ! NT_SUCCESS( NtStatus )) {
|
|
// free the allocated unicode string
|
|
RtlFreeUnicodeString( &SubKey );
|
|
Error = RtlNtStatusToDosError( NtStatus );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Add the NULL to the length so that RPC will transmit the entire
|
|
// thing
|
|
//
|
|
if ( SubKey.Length > 0 ) {
|
|
SubKey.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
if ( NewFile.Length > 0 ) {
|
|
NewFile.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
if ( OldFile.Length > 0 ) {
|
|
OldFile.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
//
|
|
// Call the server
|
|
//
|
|
|
|
if( IsLocalHandle( Handle )) {
|
|
|
|
Error = (LONG)LocalBaseRegReplaceKey(
|
|
Handle,
|
|
&SubKey,
|
|
&NewFile,
|
|
&OldFile
|
|
);
|
|
|
|
} else {
|
|
|
|
Error = (LONG)BaseRegReplaceKey(
|
|
DereferenceRemoteHandle( Handle ),
|
|
&SubKey,
|
|
&NewFile,
|
|
&OldFile
|
|
);
|
|
}
|
|
|
|
// free the allocated unicode string
|
|
RtlFreeUnicodeString( &SubKey );
|
|
ExitCleanup:
|
|
|
|
CLOSE_LOCAL_HANDLE(TempHandle);
|
|
return Error;
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegReplaceKeyW(
|
|
HKEY hKey,
|
|
LPCWSTR lpSubKey,
|
|
LPCWSTR lpNewFile,
|
|
LPCWSTR lpOldFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Replace an existing tree (hive) in the Registry. The new tree will
|
|
take effect the next time the system is rebooted.
|
|
|
|
Arguments:
|
|
|
|
hKey - Supplies a handle to an open key. lpSubKey is relative to this
|
|
handle.
|
|
|
|
lpSubKey - Supplies a path name to the key that is to be replaced.
|
|
The combination of hKey and lpSubKey must refer to a hive in the
|
|
Registry. This parameter may be NULL.
|
|
|
|
lpNewFile - Supplies a file name for the new hive file.
|
|
|
|
lpOldFile - Supplies a backup file name for the old (existing) hive file.
|
|
|
|
Return Value:
|
|
|
|
Returns ERROR_SUCCESS (0) for success; error-code for failure.
|
|
|
|
Notes:
|
|
|
|
lpNewFile will remain open until after the system is rebooted.
|
|
|
|
RegUnLoadKey requires SeRestorePrivilege.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HKEY Handle;
|
|
UNICODE_STRING SubKey;
|
|
UNICODE_STRING NewFile;
|
|
UNICODE_STRING OldFile;
|
|
LONG Error;
|
|
HKEY TempHandle = NULL;
|
|
NTSTATUS Status;
|
|
|
|
|
|
#if DBG
|
|
if ( BreakPointOnEntry ) {
|
|
DbgBreakPoint();
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
// Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
|
|
//
|
|
|
|
if( hKey == HKEY_PERFORMANCE_DATA ) {
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
Handle = MapPredefinedHandle( hKey, &TempHandle );
|
|
if ( Handle == NULL ) {
|
|
Error = ERROR_INVALID_HANDLE;
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
|
|
Status = RtlInitUnicodeStringEx(&SubKey,lpSubKey);
|
|
if( !NT_SUCCESS(Status) ) {
|
|
Error = RtlNtStatusToDosError( Status );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
Status = RtlInitUnicodeStringEx(&NewFile,lpNewFile);
|
|
if( !NT_SUCCESS(Status) ) {
|
|
Error = RtlNtStatusToDosError( Status );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
Status = RtlInitUnicodeStringEx(&OldFile,lpOldFile);
|
|
if( !NT_SUCCESS(Status) ) {
|
|
Error = RtlNtStatusToDosError( Status );
|
|
goto ExitCleanup;
|
|
}
|
|
|
|
//
|
|
// Add the NULL to the length so that RPC will transmit the entire
|
|
// thing
|
|
//
|
|
if ( SubKey.Length > 0 ) {
|
|
SubKey.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
if ( NewFile.Length > 0 ) {
|
|
NewFile.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
if ( OldFile.Length > 0 ) {
|
|
OldFile.Length += sizeof( UNICODE_NULL );
|
|
}
|
|
|
|
|
|
//
|
|
// Call the server
|
|
//
|
|
|
|
if( IsLocalHandle( Handle )) {
|
|
|
|
Error = (LONG)LocalBaseRegReplaceKey(
|
|
Handle,
|
|
&SubKey,
|
|
&NewFile,
|
|
&OldFile
|
|
);
|
|
|
|
} else {
|
|
|
|
Error = (LONG)BaseRegReplaceKey(
|
|
DereferenceRemoteHandle( Handle ),
|
|
&SubKey,
|
|
&NewFile,
|
|
&OldFile
|
|
);
|
|
}
|
|
|
|
ExitCleanup:
|
|
|
|
CLOSE_LOCAL_HANDLE(TempHandle);
|
|
return Error;
|
|
}
|