Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

346 lines
8.8 KiB

//*************************************************************
//
// Personal Classes Profile management routines
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 1995
// All rights reserved
//
//*************************************************************
#include "uenv.h"
LPTSTR GetSidString(HANDLE UserToken);
VOID DeleteSidString(LPTSTR SidString);
PSID GetUserSid (HANDLE UserToken);
VOID DeleteUserSid(PSID Sid);
BOOL
MergeUserClasses(
HKEY UserClassStore,
HKEY CommonClassStore,
HKEY MergedClassStore,
BOOL ForceNew);
BOOL
CloneRegistryTree(
HKEY hkSourceTree,
HKEY hkDestinationTree,
LPTSTR lpDestTreeName );
BOOL
AddSharedValuesToSubkeys( HKEY hkShared, LPTSTR pszSubtree );
BOOL
AddSharedValues( HKEY hkShared );
void CreateMachineClassHive( )
{
HKEY hkUser = NULL;
HKEY hkMachine = NULL;
LONG result;
DWORD dwDisp;
result =
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("Software\\Classes"),
0,
KEY_READ,
&hkUser);
if (ERROR_SUCCESS != result)
{
return;
}
result =
RegCreateKeyEx(HKEY_LOCAL_MACHINE,
TEXT("Software\\MachineClasses"),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkMachine,
&dwDisp );
if (ERROR_SUCCESS != result)
{
RegCloseKey( hkUser );
return;
}
CloneRegistryTree(hkUser, hkMachine, NULL);
AddSharedValues( hkMachine );
RegCloseKey( hkUser );
RegCloseKey( hkMachine );
}
LPTSTR
GetUserMergedHivePath(
LPTSTR SidString )
{
// open HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ProfileList
// open ...\SidString
// get value for ProfileImagePath, and if it is reg_expand_sz, expand it
// append Classes as the last component of the hive file name
long result;
HKEY hkProfileListKey;
HKEY hkProfileKey;
TCHAR ProfilePath[256];
TCHAR ExpandedProfilePath[256];
LPTSTR pszProfileDirectory = NULL;
LPTSTR pszReturnedHivePath = NULL;
DWORD dwType;
DWORD dwSize = sizeof( ProfilePath );
result = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
0,
KEY_READ,
&hkProfileListKey );
// Bug 45992
if (ERROR_SUCCESS != result) {
return NULL;
}
result = RegOpenKeyEx( hkProfileListKey,
SidString,
0,
KEY_READ,
&hkProfileKey );
if (ERROR_SUCCESS != result) {
RegCloseKey(hkProfileListKey);
return NULL;
}
result = RegQueryValueEx( hkProfileKey,
L"ProfileImagePath",
NULL,
&dwType,
(BYTE*)&ProfilePath,
&dwSize );
// Close them keys
RegCloseKey(hkProfileListKey);
RegCloseKey(hkProfileKey);
if (ERROR_SUCCESS != result) {
return NULL;
}
if ( dwType == REG_EXPAND_SZ )
{
ExpandEnvironmentStrings( ProfilePath,
ExpandedProfilePath,
sizeof(ExpandedProfilePath)/sizeof(TCHAR) );
pszProfileDirectory = ExpandedProfilePath;
}
else
{
pszProfileDirectory = ProfilePath;
}
pszReturnedHivePath = (LPTSTR) LocalAlloc( LPTR,
(lstrlenW( pszProfileDirectory )+1) * sizeof(TCHAR) +
sizeof( L"\\ClsRoot" ) );
// Bug 45993
if (pszReturnedHivePath)
{
// make up the returned string as the profile directory with \ClsRoot on the end
lstrcpyW( pszReturnedHivePath, pszProfileDirectory );
lstrcatW( pszReturnedHivePath, L"\\ClsRoot" );
}
return pszReturnedHivePath;
}
void
FreeUserMergedHivePath( LPTSTR hivepath )
{
LocalFree( hivepath );
}
// see if the desired hive file already exists. If so, load it and return
// otherwise, create a hive containing a single key, load it and return
BOOL
CreateUserMergedClasses(
LPTSTR SidString,
LPTSTR MergedClassesString,
HKEY * phkMerged )
{
LPTSTR HivePath;
long result;
HKEY DummyKey = NULL;
DWORD dwDisp;
NTSTATUS Status;
BOOLEAN WasEnabled;
HivePath = GetUserMergedHivePath( SidString );
if (!HivePath)
{
return FALSE;
}
// see if the desired hive file already exists. If so, load it and return
if ( 0xFFFFFFFF == GetFileAttributes( HivePath ) )
{
// create a hive containing a single key, load it and return
result = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\DummyKey",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&DummyKey,
&dwDisp );
if (ERROR_SUCCESS != result)
{
FreeUserMergedHivePath( HivePath );
return FALSE;
}
//
// Enable the backup privilege
//
Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, TRUE, FALSE, &WasEnabled);
// do this by doing a RegSaveKey of a small subtree
result = RegSaveKey( DummyKey,
HivePath,
NULL );
result = RegCloseKey( DummyKey );
//
// Restore the privilege to its previous state
//
Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
}
//
// Enable the restore privilege
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
result = RegLoadKey( HKEY_USERS,
MergedClassesString,
HivePath );
// if result is OK, then open the subkey and return it
result = RegOpenKeyEx( HKEY_USERS,
MergedClassesString,
0,
KEY_ALL_ACCESS,
phkMerged );
FreeUserMergedHivePath( HivePath );
// close keys?
//
// Restore the privilege to its previous state
//
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
return TRUE;
}
void MergeUserClassHives( HANDLE Token )
{
HKEY hkUser = NULL;
HKEY hkMachine = NULL;
HKEY hkMerged = NULL;
LONG result;
LPTSTR SidString;
LPTSTR MergedClassesString;
DWORD dwDisp;
BOOL ForceNew = FALSE;
result =
RegCreateKeyEx(HKEY_CURRENT_USER,
TEXT("Software\\Classes"),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_READ,
NULL,
&hkUser,
&dwDisp);
result =
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("Software\\MachineClasses"),
0,
KEY_READ,
&hkMachine);
if ( result == ERROR_FILE_NOT_FOUND )
{
CreateMachineClassHive();
result =
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("Software\\MachineClasses"),
0,
KEY_READ,
&hkMachine);
}
// Bugs 45996 and 45997
SidString = GetSidString( Token );
if (SidString)
{
MergedClassesString = (LPTSTR) LocalAlloc( LPTR,
(lstrlenW( SidString ) + 1) * sizeof(WCHAR) +
sizeof(L"_MergedClasses" ) );
if (MergedClassesString)
{
lstrcpyW( MergedClassesString, SidString );
lstrcatW( MergedClassesString, L"_MergedClasses" );
result = RegOpenKeyEx( HKEY_USERS,
MergedClassesString,
0,
KEY_ALL_ACCESS,
&hkMerged );
if ( result == ERROR_FILE_NOT_FOUND )
{
CreateUserMergedClasses(SidString, MergedClassesString, &hkMerged );
ForceNew = TRUE;
}
MergeUserClasses(hkUser, hkMachine, hkMerged, ForceNew );
LocalFree( MergedClassesString );
}
}
RegCloseKey( hkUser );
RegCloseKey( hkMachine );
RegCloseKey( hkMerged );
DeleteSidString( SidString );
}
void MergeHives( )
{
HANDLE Token;
NTSTATUS Status;
Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_QUERY, &Token );
MergeUserClassHives( Token );
NtClose( Token );
}