347 lines
8.8 KiB
C
347 lines
8.8 KiB
C
//*************************************************************
|
|
//
|
|
// 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 );
|
|
|
|
}
|
|
|