|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
Predefh.c
Abstract:
This module contains routines for opening the Win32 Registry API's predefined handles.
A predefined handle is used as a root to an absolute or relative sub-tree in the real Nt Registry. An absolute predefined handle maps to a specific key within the Registry. A relative predefined handle maps to a key relative to some additional information such as the current user.
Predefined handles are strictly part of the Win32 Registry API. The Nt Registry API knows nothing about them.
A predefined handle can be used anywhere that a non-predefined handle (i.e. one returned from RegCreateKey(), RegOpenKey() or RegConnectRegistry()) can be used.
Author:
David J. Gilman (davegi) 15-Nov-1991
--*/
#include <rpc.h>
#include "regrpc.h"
#include "localreg.h"
#include "regclass.h"
#include "ntconreg.h"
#include "regsec.h"
#ifdef LOCAL
#include "tsappcmp.h"
#if defined(LEAK_TRACK)
#include "regleak.h"
#endif // LEAK_TRACK
#endif
//
// Determine the length of a Unicode string w/o the trailing NULL.
//
#define LENGTH( str ) ( sizeof( str ) - sizeof( UNICODE_NULL ))
//
// Nt Registry name space.
//
#define MACHINE L"\\REGISTRY\\MACHINE"
#define USER L"\\REGISTRY\\USER"
#define CLASSES L"\\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES"
#define CLASSES_SUFFIX L"\\SOFTWARE\\CLASSES"
#define CURRENTCONFIG L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT"
UNICODE_STRING MachineStringKey = { LENGTH( MACHINE ), LENGTH( MACHINE ), MACHINE };
UNICODE_STRING UserStringKey = { LENGTH( USER ), LENGTH( USER ), USER };
UNICODE_STRING ClassesStringKey = { LENGTH( CLASSES ), LENGTH( CLASSES ), CLASSES };
UNICODE_STRING CurrentConfigStringKey = { LENGTH( CURRENTCONFIG ), LENGTH( CURRENTCONFIG ), CURRENTCONFIG };
NTSTATUS InitSecurityAcls(PSECURITY_DESCRIPTOR *SecurityDescriptor) /*++
Routine Description:
Gives GENERIC_ALL to admins and denies WRITE_OWNER | WRITE_DAC from everyone
Arguments:
Return Value:
--*/ { SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY; PSID BuiltInAdministrators = NULL; PSID Everyone = NULL; NTSTATUS Status; ULONG AclSize; ACL *Acl;
*SecurityDescriptor = NULL;
Status = RtlAllocateAndInitializeSid( &WorldAuthority, 1, SECURITY_WORLD_RID, 0,0,0,0,0,0,0, &Everyone ); if( !NT_SUCCESS(Status) ) { goto Exit; }
Status = RtlAllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0,0,0,0,0,0, &BuiltInAdministrators );
if( !NT_SUCCESS(Status) ) { goto Exit; }
AclSize = sizeof (ACL) + (2 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) + GetLengthSid(BuiltInAdministrators) + GetLengthSid(Everyone);
*SecurityDescriptor = (PSECURITY_DESCRIPTOR)RtlAllocateHeap( RtlProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize); if (!*SecurityDescriptor) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; }
Acl = (ACL *)((BYTE *)(*SecurityDescriptor) + SECURITY_DESCRIPTOR_MIN_LENGTH);
Status = RtlCreateAcl( Acl, AclSize, ACL_REVISION); if( !NT_SUCCESS(Status) ) { goto Exit; }
Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION, (KEY_ALL_ACCESS & ~(WRITE_OWNER | WRITE_DAC)), Everyone); if( !NT_SUCCESS(Status) ) { goto Exit; }
Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION, GENERIC_ALL, BuiltInAdministrators); if( !NT_SUCCESS(Status) ) { goto Exit; }
Status = RtlCreateSecurityDescriptor( *SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); if( !NT_SUCCESS(Status) ) { goto Exit; }
Status = RtlSetDaclSecurityDescriptor( *SecurityDescriptor, TRUE, Acl, FALSE);
Exit: if( Everyone ) { RtlFreeSid( Everyone ); } if( BuiltInAdministrators ) { RtlFreeSid( BuiltInAdministrators ); }
return Status; }
error_status_t OpenClassesRoot( IN PREGISTRY_SERVER_NAME ServerName, IN REGSAM samDesired, OUT PRPC_HKEY phKey )
/*++
Routine Description:
Attempts to open the the HKEY_CLASSES_ROOT predefined handle.
Arguments:
ServerName - Not used. samDesired - This access mask describes the desired security access for the key. phKey - Returns a handle to the key \REGISTRY\MACHINE\SOFTWARE\CLASSES.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{ PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; OBJECT_ATTRIBUTES Obja; NTSTATUS Status; UNICODE_STRING UsersHive; UNICODE_STRING UsersMergedHive; error_status_t Res;
UNREFERENCED_PARAMETER( ServerName );
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
#ifdef LOCAL
//
// Multiuser CLASSES key so each user has their own key. If opening
// CLASSES in execute mode - open it under HKEY_CURRENT_USER else
// just let it fall thru here and open the global one.
//
if (gpfnTermsrvOpenUserClasses) { Status = gpfnTermsrvOpenUserClasses(samDesired,phKey); } else { *phKey = NULL; } if (!(*phKey)) { #endif // LOCAL
//
// Initialize the SECURITY_DESCRIPTOR.
//
Status = InitSecurityAcls(&SecurityDescriptor);
if( ! NT_SUCCESS( Status )) { goto error_exit; }
#ifdef LOCAL
if (gbCombinedClasses) { // first try for a per-user HKCR
Res = OpenCombinedClassesRoot( samDesired, phKey );
if ( NT_SUCCESS( Res ) ) { goto error_exit; } } #endif
//
// Initialize the OBJECT_ATTRIBUTES structure so that it creates
// (opens) the key "\REGISTRY\MACHINE\SOFTWARE\CLASSES" with a Security
// Descriptor that allows everyone complete access.
//
InitializeObjectAttributes( &Obja, &ClassesStringKey, OBJ_CASE_INSENSITIVE, NULL, SecurityDescriptor );
Status = NtCreateKey( phKey, samDesired, // MAXIMUM_ALLOWED,
&Obja, 0, NULL, REG_OPTION_NON_VOLATILE, NULL ); #ifdef LOCAL
} #endif // LOCAL
#if DBG
if( ! NT_SUCCESS( Status )) { DbgPrint( "Winreg Server: " "Creating HKEY_CLASSES_ROOT failed, status = 0x%x\n", Status ); } #endif
error_exit: if( SecurityDescriptor != NULL ) { RtlFreeHeap( RtlProcessHeap(), 0, SecurityDescriptor ); } RPC_REVERT_TO_SELF(); return (error_status_t)RtlNtStatusToDosError( Status ); }
error_status_t OpenCurrentUser( IN PREGISTRY_SERVER_NAME ServerName, IN REGSAM samDesired, OUT PRPC_HKEY phKey )
/*++
Routine Description:
Attempts to open the the HKEY_CURRENT_USER predefined handle.
Arguments:
ServerName - Not used. samDesired - This access mask describes the desired security access for the key. phKey - Returns a handle to the key \REGISTRY\USER\*.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{ NTSTATUS Status;
UNREFERENCED_PARAMETER( ServerName );
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
//
// Open the registry key.
//
Status = RtlOpenCurrentUser( samDesired, /* MAXIMUM_ALLOWED, */ phKey );
RPC_REVERT_TO_SELF(); //
// Map the returned status
//
return (error_status_t)RtlNtStatusToDosError( Status ); }
error_status_t OpenLocalMachine( IN PREGISTRY_SERVER_NAME ServerName, IN REGSAM samDesired, OUT PRPC_HKEY phKey )
/*++
Routine Description:
Attempt to open the the HKEY_LOCAL_MACHINE predefined handle.
Arguments:
ServerName - Not used. samDesired - This access mask describes the desired security access for the key. phKey - Returns a handle to the key \REGISTRY\MACHINE.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{ OBJECT_ATTRIBUTES Obja; NTSTATUS Status;
UNREFERENCED_PARAMETER( ServerName );
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
InitializeObjectAttributes( &Obja, &MachineStringKey, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtOpenKey( phKey, samDesired, // MAXIMUM_ALLOWED,
&Obja ); #if DBG
if( ! NT_SUCCESS( Status )) { DbgPrint( "Winreg Server: " "Opening HKEY_LOCAL_MACHINE failed, status = 0x%x\n", Status ); } #endif
if ( NT_SUCCESS( Status ) ) { if (! REGSEC_CHECK_REMOTE( phKey ) ) { *phKey = REGSEC_FLAG_HANDLE( *phKey, CHECK_MACHINE_PATHS ); } }
RPC_REVERT_TO_SELF();
return (error_status_t)RtlNtStatusToDosError( Status ); }
error_status_t OpenUsers( IN PREGISTRY_SERVER_NAME ServerName, IN REGSAM samDesired, OUT PRPC_HKEY phKey )
/*++
Routine Description:
Attempts to open the the HKEY_USERS predefined handle.
Arguments:
ServerName - Not used. samDesired - This access mask describes the desired security access for the key. phKey - Returns a handle to the key \REGISTRY\USER.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{ OBJECT_ATTRIBUTES Obja; NTSTATUS Status;
UNREFERENCED_PARAMETER( ServerName );
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
InitializeObjectAttributes( &Obja, &UserStringKey, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtOpenKey( phKey, samDesired, // MAXIMUM_ALLOWED,
&Obja ); #if DBG
if( ! NT_SUCCESS( Status )) { DbgPrint( "Winreg Server: " "Opening HKEY_USERS failed, status = 0x%x\n", Status ); } #endif
if ( NT_SUCCESS( Status ) ) { if (! REGSEC_CHECK_REMOTE( phKey ) ) { *phKey = REGSEC_FLAG_HANDLE( *phKey, CHECK_USER_PATHS ); } }
RPC_REVERT_TO_SELF();
return (error_status_t)RtlNtStatusToDosError( Status ); }
error_status_t OpenCurrentConfig( IN PREGISTRY_SERVER_NAME ServerName, IN REGSAM samDesired, OUT PRPC_HKEY phKey )
/*++
Routine Description:
Attempts to open the the HKEY_CURRENT_CONFIG predefined handle.
Arguments:
ServerName - Not used. samDesired - This access mask describes the desired security access for the key. phKey - Returns a handle to the key \REGISTRY\MACHINE\SYSTEM\CURRENTCONTROLSET\HARDWARE PROFILES\CURRENT
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{ OBJECT_ATTRIBUTES Obja; NTSTATUS Status;
UNREFERENCED_PARAMETER( ServerName );
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
InitializeObjectAttributes( &Obja, &CurrentConfigStringKey, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtOpenKey( phKey, samDesired, // MAXIMUM_ALLOWED,
&Obja ); #if DBG
if( ! NT_SUCCESS( Status )) { DbgPrint( "Winreg Server: " "Opening HKEY_CURRENT_CONFIG failed, status = 0x%x\n", Status ); } #endif
RPC_REVERT_TO_SELF();
return (error_status_t)RtlNtStatusToDosError( Status ); } error_status_t OpenPerformanceData( IN PREGISTRY_SERVER_NAME ServerName, IN REGSAM samDesired, OUT PRPC_HKEY phKey )
/*++
Routine Description:
Attempts to open the the HKEY_PERFORMANCE_DATA predefined handle.
Arguments:
ServerName - Not used. samDesired - Not used. phKey - Returns a the predefined handle HKEY_PERFORMANCE_DATA.
Return Value:
Returns ERROR_SUCCESS (0) for success; or a DOS (not NT) error-code for failure.
--*/
{ IO_STATUS_BLOCK IoStatusBlock; RTL_RELATIVE_NAME RelativeName; UNICODE_STRING DeviceNameU; OBJECT_ATTRIBUTES ObjectAttributes; STRING DeviceName; NTSTATUS status;
if ( 0 ) { DBG_UNREFERENCED_PARAMETER(ServerName); DBG_UNREFERENCED_PARAMETER(samDesired); }
//
// Impersonate the client.
//
RPC_IMPERSONATE_CLIENT( NULL );
if ( ! REGSEC_CHECK_REMOTE( phKey ) ) { RPC_REVERT_TO_SELF(); return( ERROR_ACCESS_DENIED ); }
// check if we are in the middle of Lodctr/unlodctr.
// if so, don't open the performance data stuff.
{ HANDLE hFileMapping = NULL; WCHAR MapFileName[] = L"Perflib Busy"; DWORD *lpData; BOOL bBusy = FALSE;
hFileMapping = OpenFileMappingW (FILE_MAP_READ, TRUE, (LPCWSTR)MapFileName); if (hFileMapping) { // someone is running lodctr perhaps find out by reading the first DWORD
lpData = MapViewOfFile (hFileMapping, FILE_MAP_READ, 0L, 0L, 0L); if (lpData) { // successfully mapped so read it
// 1 = busy, 0 = not
bBusy = (BOOL)(*lpData); UnmapViewOfFile (lpData); } CloseHandle (hFileMapping); if (bBusy) { *phKey = (RPC_HKEY) HKEY_PERFORMANCE_DATA; RPC_REVERT_TO_SELF(); return ERROR_SUCCESS; } } else { // no lodctr so continue
} } status = PerfOpenKey();
RPC_REVERT_TO_SELF();
*phKey = (RPC_HKEY) HKEY_PERFORMANCE_DATA; return ERROR_SUCCESS;
RPC_REVERT_TO_SELF(); return status; }
error_status_t OpenPerformanceText( IN PREGISTRY_SERVER_NAME ServerName, IN REGSAM samDesired, OUT PRPC_HKEY phKey )
/*++
Routine Description:
Attempts to open the the HKEY_PERFORMANCE_TEXT predefined handle.
Arguments:
ServerName - Not used. samDesired - Not used. phKey - Returns the predefined handle HKEY_PERFORMANCE_TEXT.
Return Value:
Returns ERROR_SUCCESS (0) for success; or a DOS (not NT) error-code for failure.
--*/
{ error_status_t Status = ERROR_SUCCESS;
// No need to call OpenPerformanceData for getting text (HWC 4/1994)
// Status = OpenPerformanceData(ServerName, samDesired, phKey);
// if (Status==ERROR_SUCCESS) {
*phKey = HKEY_PERFORMANCE_TEXT; // }
return(Status); }
error_status_t OpenPerformanceNlsText( IN PREGISTRY_SERVER_NAME ServerName, IN REGSAM samDesired, OUT PRPC_HKEY phKey )
/*++
Routine Description:
Attempts to open the the HKEY_PERFORMANCE_TEXT predefined handle.
Arguments:
ServerName - Not used. samDesired - Not used. phKey - Returns the predefined handle HKEY_PERFORMANCE_NLSTEXT.
Return Value:
Returns ERROR_SUCCESS (0) for success; or a DOS (not NT) error-code for failure.
--*/
{ error_status_t Status = ERROR_SUCCESS;
// No need to call OpenPerformanceData for getting text (HWC 4/1994)
// Status = OpenPerformanceData(ServerName, samDesired, phKey);
// if (Status==ERROR_SUCCESS) {
*phKey = HKEY_PERFORMANCE_NLSTEXT; // }
return(Status); }
error_status_t OpenDynData( IN PREGISTRY_SERVER_NAME ServerName, IN REGSAM samDesired, OUT PRPC_HKEY phKey ) /*++
Routine Description:
Attempts to open the the HKEY_DYN_DATA predefined handle.
There is currently no HKEY_DYN_DATA on NT, thus this function always returns ERROR_CALL_NOT_IMPLEMENTED.
Arguments:
ServerName - Not used. samDesired - This access mask describes the desired security access for the key. phKey - Returns a handle to the key HKEY_DYN_DATA
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
--*/
{ return((error_status_t)ERROR_CALL_NOT_IMPLEMENTED); }
|