diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ole32/olecnfg | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ole32/olecnfg')
-rw-r--r-- | private/ole32/olecnfg/clshive.c | 310 | ||||
-rw-r--r-- | private/ole32/olecnfg/main.c | 374 | ||||
-rw-r--r-- | private/ole32/olecnfg/makefile | 6 | ||||
-rw-r--r-- | private/ole32/olecnfg/olecnfg.c | 996 | ||||
-rw-r--r-- | private/ole32/olecnfg/olecnfg.h | 121 | ||||
-rw-r--r-- | private/ole32/olecnfg/olecnfg.rc | 50 | ||||
-rw-r--r-- | private/ole32/olecnfg/sid.c | 255 | ||||
-rw-r--r-- | private/ole32/olecnfg/sources | 74 | ||||
-rw-r--r-- | private/ole32/olecnfg/treemgmt.c | 882 | ||||
-rw-r--r-- | private/ole32/olecnfg/uenv.h | 26 |
10 files changed, 3094 insertions, 0 deletions
diff --git a/private/ole32/olecnfg/clshive.c b/private/ole32/olecnfg/clshive.c new file mode 100644 index 000000000..08a134d8f --- /dev/null +++ b/private/ole32/olecnfg/clshive.c @@ -0,0 +1,310 @@ +//************************************************************* +// +// 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; + HKEY hkMachine; + LONG result; + DWORD dwDisp; + + result = + RegOpenKeyEx(HKEY_LOCAL_MACHINE, + TEXT("Software\\Classes"), + 0, + KEY_READ, + &hkUser); + result = + RegCreateKeyEx(HKEY_LOCAL_MACHINE, + TEXT("Software\\MachineClasses"), + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hkMachine, + &dwDisp ); + + 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 ); + + // TBD: errors? + + result = RegOpenKeyEx( hkProfileListKey, + SidString, + 0, + KEY_READ, + &hkProfileKey ); + + result = RegQueryValueEx( hkProfileKey, + L"ProfileImagePath", + NULL, + &dwType, + (BYTE*)&ProfilePath, + &dwSize ); + + 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" ) ); + // 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; + DWORD dwDisp; + NTSTATUS Status; + BOOLEAN WasEnabled; + + if (!NT_SUCCESS(Status)) { + // TBD: report error + } + + HivePath = GetUserMergedHivePath( SidString ); + + // 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 ); + + // + // 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; + HKEY hkMachine; + HKEY hkMerged; + 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); + + } + + SidString = GetSidString( Token ); + + MergedClassesString = (LPTSTR) LocalAlloc( LPTR, + (lstrlenW( SidString ) + 1) * sizeof(WCHAR) + + sizeof(L"_MergedClasses" ) ); + // TBD: check for NULL + + 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 ); + + RegCloseKey( hkUser ); + RegCloseKey( hkMachine ); + RegCloseKey( hkMerged ); + + LocalFree( MergedClassesString ); + + DeleteSidString( SidString ); +} + +void MergeHives( ) +{ + HANDLE Token; + NTSTATUS Status; + + Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_QUERY, &Token ); + + MergeUserClassHives( Token ); + + NtClose( Token ); + +} + diff --git a/private/ole32/olecnfg/main.c b/private/ole32/olecnfg/main.c new file mode 100644 index 000000000..45507397b --- /dev/null +++ b/private/ole32/olecnfg/main.c @@ -0,0 +1,374 @@ +// +// +// + +#include "olecnfg.h" + +const char * GlobalKeyNames[] = + { + 0, + "EnableDCOM", + "DefaultLaunchPermission", + "DefaultAccessPermission", + "LegacyAuthenticationLevel" + }; + +const char * ClsidKeyNames[] = + { + 0, + "InprocHandler32", + "InprocServer32", + "LocalServer32", + "LocalService", + "RemoteServerName", + "RunAs", + "ActivateAtStorage", + "LaunchPermission", + "AccessPermission" + }; + +int ArgsLeft; +char ** Args; + +HKEY hRegOle = 0; +HKEY hRegClsid = 0; + +#define IsDigit(c) (IsCharAlphaNumeric(c) && !IsCharAlpha(c)) + +void __cdecl main(int argc, char **argv) +{ + int GlobalKeys[GLOBAL_KEYS+1]; + int Key; + int n; + DWORD Disposition; + long RegStatus; + + memset( GlobalKeys, 0, sizeof(GlobalKeys) ); + + ArgsLeft = argc - 1; + Args = argv + 1; + + if ( (argc > 1) && + ((strcmp( "/?", argv[1] ) == 0) || (strcmp( "-?", argv[1] ) == 0)) ) + { + DisplayHelp(); + return; + } + + // + // With no arguments, display the global registry activation values. + // + if ( ArgsLeft == 0 ) + { + DisplayGlobalSettings(); + return; + } + + // + // Look for specified global registry keys and operations + // + for ( ; ArgsLeft > 0; ) + { + if ( _stricmp( *Args, "EnableDCOM" ) == 0 ) + Key = ENABLE_NETWORK_OLE; + else if ( _stricmp( *Args, "DefaultLaunchPermission" ) == 0 ) + Key = DEFAULT_LAUNCH_PERMISSION; + else if ( _stricmp( *Args, "DefaultAccessPermission" ) == 0 ) + Key = DEFAULT_ACCESS_PERMISSION; + else if ( _stricmp( *Args, "LegacyAuthenticationLevel" ) == 0 ) + Key = LEGACY_AUTHENTICATION_LEVEL; + else + break; + + EAT_ARG(); + + if ( Key >= 100 ) + { + if ( Key == MERGE ) + { + MergeHives( ); + } + else if ( Key == SAVE_USER ) + { + SaveChangesToUser( ); + } + else if ( Key == SAVE_COMMON ) + { + SaveChangesToCommon( ); + } + continue; + } + + if ( Key == DEFAULT_ACCESS_PERMISSION ) + { + GlobalKeys[Key] = YES; + continue; + } + + if ( Key == LEGACY_AUTHENTICATION_LEVEL ) + { + if ( ! IsDigit(**Args) || (**Args < '1') || (**Args > '6') ) + { + printf( "LegacyAuthenticationLevel must be followed by a 1 to 6.\n" ); + return; + } + + GlobalKeys[Key] = **Args; + } + else if ( (GlobalKeys[Key] = ReadYesOrNo()) == INVALID ) + { + printf( "%s must be followed by 'y' or 'n'\n", Args[-1] ); + return; + } + + EAT_ARG(); + } + + // + // Set global keys on or off. + // + for ( Key = 1; Key < sizeof(GlobalKeys)/sizeof(int); Key++ ) + { + if ( (Key == LEGACY_AUTHENTICATION_LEVEL) && (GlobalKeys[Key] != 0) ) + { + if ( ! SetGlobalKey( Key, GlobalKeys[Key] - '0' ) ) + return; + continue; + } + + if ( (GlobalKeys[Key] == YES) || (GlobalKeys[Key] == NO) ) + if ( ! SetGlobalKey( Key, GlobalKeys[Key] ) ) + return; + } + + // + // Process any CLSID/ProgID specification. + // + ParseClsidProgId(); + + if ( hRegOle ) + RegCloseKey( hRegOle ); + if ( hRegClsid ) + RegCloseKey( hRegClsid ); +} + +void ParseClsidProgId() +{ + CLSID_INFO ClsidInfo; + BOOL NoKeys; + int ClsidKey; + + if ( ArgsLeft == 0 ) + return; + + memset( &ClsidInfo, 0, sizeof(CLSID_INFO) ); + + NoKeys = TRUE; + + if ( (ArgsLeft > 0) && (**Args != '{') ) + { + ClsidInfo.ProgId = *Args; + EAT_ARG(); + + if ( (ArgsLeft > 0) && + (**Args != '{') && + (NextClsidKey() == UNKNOWN) ) + { + ClsidInfo.ProgIdDescription = *Args; + EAT_ARG(); + } + } + + if ( (ArgsLeft > 0) && (**Args == '{') ) + { + ClsidInfo.Clsid = *Args; + EAT_ARG(); + + if ( (ArgsLeft > 0) && + (NextClsidKey() == UNKNOWN) ) + { + ClsidInfo.ClsidDescription = *Args; + EAT_ARG(); + } + } + + for (; ArgsLeft > 0;) + { + ClsidKey = NextClsidKey(); + if ( (1 <= ClsidKey) && (ClsidKey <= CLSID_KEYS) ) + NoKeys = FALSE; + + EAT_ARG(); + + switch ( ClsidKey ) + { + case LAUNCH_PERMISSION : + if ( (ClsidInfo.LaunchPermission = ReadYesOrNo()) == INVALID ) + { + printf( "%s must be followed by 'y' or 'n'\n", + ClsidKeyNames[LAUNCH_PERMISSION] ); + goto ErrorReturn; + } + EAT_ARG(); + break; + + case ACCESS_PERMISSION : + ClsidInfo.AccessPermission = YES; + break; + + case ACTIVATE_AT_STORAGE : + if ( (ClsidInfo.ActivateAtStorage = ReadYesOrNo()) == INVALID ) + { + printf( "%s must be followed by 'y' or 'n'\n", + ClsidKeyNames[ACTIVATE_AT_STORAGE] ); + goto ErrorReturn; + } + EAT_ARG(); + break; + + case INPROC_HANDLER32 : + case INPROC_SERVER32 : + case LOCAL_SERVER32 : + case LOCAL_SERVICE : + if ( NextClsidKey() == UNKNOWN ) + { + ClsidInfo.ServerPaths[ClsidKey] = *Args; + EAT_ARG(); + } + else + { + ClsidInfo.ServerPaths[ClsidKey] = ""; + } + break; + + case REMOTE_SERVER_NAME : + if ( NextClsidKey() == UNKNOWN ) + { + ClsidInfo.RemoteServerName = *Args; + EAT_ARG(); + } + else + { + ClsidInfo.RemoteServerName = ""; + } + break; + + case RUN_AS : + if ( NextClsidKey() == UNKNOWN ) + { + ClsidInfo.RunAsUserName = *Args; + EAT_ARG(); + + if ( _stricmp(ClsidInfo.RunAsUserName,"Interactive User") == 0 ) + break; + + if ( _stricmp(ClsidInfo.RunAsUserName,"Interactive") == 0 ) + { + if ( (ArgsLeft > 0) && (_stricmp(*Args,"User") == 0) ) + { + EAT_ARG(); + ClsidInfo.RunAsUserName = "Interactive User"; + break; + } + } + + if ( NextClsidKey() != UNKNOWN ) + { + printf( "RunAs password or '*' must follow the user name.\n" ); + goto ErrorReturn; + } + + ClsidInfo.RunAsPassword = *Args; + EAT_ARG(); + } + else + { + ClsidInfo.RunAsUserName = ""; + } + break; + + default : + printf( "Invalid CLSID/ProgID specification given (%s)\n", Args[-1] ); + goto ErrorReturn; + break; + } // switch + } // for + + // + // Display current CLSID/ProgID settings if no keys were specified and + // only a CLSID or ProgID (but not both) was given. + // + if ( NoKeys && + (ClsidInfo.ProgIdDescription == 0) && + (ClsidInfo.ClsidDescription == 0) && + ((ClsidInfo.Clsid == 0) || (ClsidInfo.ProgId == 0)) ) + DisplayClsidKeys( &ClsidInfo ); + else + UpdateClsidKeys( &ClsidInfo ); + + return; + +ErrorReturn: + printf( "No CLSID/ProgID entries were modified\n" ); +} + +int NextClsidKey() +{ + if ( ArgsLeft == 0 ) + return END_OF_ARGS; + + if ( _stricmp( *Args, "InprocHandler32" ) == 0 ) + return INPROC_HANDLER32; + if ( _stricmp( *Args, "InprocServer32" ) == 0 ) + return INPROC_SERVER32; + if ( _stricmp( *Args, "LocalServer32" ) == 0 ) + return LOCAL_SERVER32; + if ( _stricmp( *Args, "LocalService" ) == 0 ) + return LOCAL_SERVICE; + if ( _stricmp( *Args, "RemoteServerName" ) == 0 ) + return REMOTE_SERVER_NAME; + if ( _stricmp( *Args, "RunAs" ) == 0 ) + return RUN_AS; + if ( _stricmp( *Args, "ActivateAtStorage" ) == 0 ) + return ACTIVATE_AT_STORAGE; + if ( _stricmp( *Args, "LaunchPermission" ) == 0 ) + return LAUNCH_PERMISSION; + if ( _stricmp( *Args, "AccessPermission" ) == 0 ) + return ACCESS_PERMISSION; + + return UNKNOWN; +} + +int ReadYesOrNo() +{ + if ( ArgsLeft == 0 ) + return INVALID; + + if ( (char)CharUpperA((LPSTR)**Args) == 'Y' ) + return YES; + if ( (char)CharUpperA((LPSTR)**Args) == 'N' ) + return NO; + + return INVALID; +} + + +void DisplayHelp() +{ + puts( "\nolecnfg\n" + "\t[EnableDCOM <y,n>]\n" + "\t[DefaultLaunchPermission <y,n>]\n" + "\t[DefaultAccessPermission]\n" + "\t[LegacyAuthenticationLevel <1,2,3,4,5,6>]\n" ); + puts( "\t[[ProgID [Description]] [CLSID [Description]]\n" + "\t\t[InprocHandler32 [Path]]\n" + "\t\t[InprocServer32 [Path]]\n" + "\t\t[LocalServer32 [Path]]\n" + "\t\t[LocalService [Path]]\n" + "\t\t[RemoteServerName [MachineName]]\n" + "\t\t[RunAs [UserName Password]] ]\n" + "\t\t[ActivateAtStorage <y,n>]\n" + "\t\t[LaunchPermission <y,n>]\n" + "\t\t[AccessPermission]\n" + "\t]\n" ); +} diff --git a/private/ole32/olecnfg/makefile b/private/ole32/olecnfg/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ole32/olecnfg/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ole32/olecnfg/olecnfg.c b/private/ole32/olecnfg/olecnfg.c new file mode 100644 index 000000000..b34c85a99 --- /dev/null +++ b/private/ole32/olecnfg/olecnfg.c @@ -0,0 +1,996 @@ +// +// +// + +#include "olecnfg.h" + +BOOL SetGlobalKey( int Key, int Value ) +{ + DWORD RegStatus; + HKEY hReg; + DWORD Disposition; + char * ValueName; + + if ( hRegOle == 0 ) + { + RegStatus = RegCreateKeyEx( + HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\OLE", + 0, + "REG_SZ", + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE, + NULL, + &hRegOle, + &Disposition ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not open HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\OLE for writing\n" ); + return FALSE; + } + } + + // BUGBUG : Extra stuff to do for PersonalClasses and InstallCommon. + + if ( (Key == DEFAULT_LAUNCH_PERMISSION) || + (Key == DEFAULT_ACCESS_PERMISSION) ) + { + RegStatus = RegCreateKeyEx( + hRegOle, + GlobalKeyNames[Key], + 0, + "REG_SZ", + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE, + NULL, + &hReg, + &Disposition ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Unable to open or add global key %s (status %d)\n", + GlobalKeyNames[Key], + RegStatus ); + return FALSE; + } + + ValueName = NULL; + } + else + { + hReg = hRegOle; + ValueName = (char *)GlobalKeyNames[Key]; + } + + if ( Key == LEGACY_AUTHENTICATION_LEVEL ) + { + RegStatus = RegSetValueEx( + hReg, + ValueName, + 0, + REG_DWORD, + (LPBYTE)&Value, + sizeof(DWORD) ); + } + else if ( Key != DEFAULT_ACCESS_PERMISSION ) + { + RegStatus = RegSetValueEx( + hReg, + ValueName, + 0, + REG_SZ, + (LPBYTE)(Value == YES ? "Y" : "N"), + 2 * sizeof(char) ); + } + else + RegStatus = ERROR_SUCCESS; + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Unable to set value for %s (status %d)\n", + GlobalKeyNames[Key], + RegStatus ); + return FALSE; + } + + if ( Key == LEGACY_AUTHENTICATION_LEVEL ) + { + printf( "Global setting %s set to %d.\n", + GlobalKeyNames[Key], + Value ); + } + else if ( Key == DEFAULT_ACCESS_PERMISSION ) + { + printf( "Global setting %s set to on.\n", + GlobalKeyNames[Key] ); + } + else + { + printf( "Global setting %s set to %c.\n", + GlobalKeyNames[Key], + Value == YES ? 'Y' : 'N' ); + } + + return TRUE; +} + +void DisplayGlobalSettings() +{ + HKEY hReg; + DWORD RegStatus; + int Key; + DWORD Type; + DWORD Value; + DWORD BufSize; + char * ValueName; + + RegStatus = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\OLE", + 0, + KEY_READ, + &hRegOle ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not open HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\OLE\n" ); + return; + } + + printf( "\nGlobal OLE registry settings :\n" ); + + for ( Key = 1; Key <= GLOBAL_KEYS; Key++ ) + { + if ( (Key == DEFAULT_LAUNCH_PERMISSION) || + (Key == DEFAULT_ACCESS_PERMISSION) ) + { + RegStatus = RegOpenKeyEx( + hRegOle, + GlobalKeyNames[Key], + 0, + KEY_READ, + &hReg ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( " %-28sN (key does not exist or could not be opened)\n", + GlobalKeyNames[Key] ); + continue; + } + + ValueName = NULL; + } + else + { + hReg = hRegOle; + ValueName = (char *)GlobalKeyNames[Key]; + } + + if ( Key != DEFAULT_ACCESS_PERMISSION ) + { + BufSize = sizeof(DWORD); + + RegStatus = RegQueryValueEx( + hReg, + ValueName, + 0, + &Type, + (LPBYTE) &Value, + &BufSize ); + } + else + RegStatus = ERROR_SUCCESS; + + if ( RegStatus != ERROR_SUCCESS ) + { + if ( Key == DEFAULT_LAUNCH_PERMISSION ) + printf( " %-28sN (key value could not be read)\n", + GlobalKeyNames[Key] ); + else + printf( " %-28s%c (value not present)\n", + GlobalKeyNames[Key], + (Key == LEGACY_AUTHENTICATION_LEVEL) ? '2' : 'N' ); + continue; + } + + if ( Key == LEGACY_AUTHENTICATION_LEVEL ) + { + printf( " %-28s%d\n", + GlobalKeyNames[Key], + Value ); + } + else if ( Key == DEFAULT_ACCESS_PERMISSION ) + { + printf( " %-28son\n", + GlobalKeyNames[Key] ); + } + else + { + printf( " %-28s%c\n", + GlobalKeyNames[Key], + (char)CharUpper((LPSTR)((char *)&Value)[0]) ); + } + } +} + +void DisplayClsidKeys( + CLSID_INFO * ClsidInfo ) +{ + HKEY hProgId; + HKEY hClsid; + HKEY hProgIdClsid; + HKEY hKey; + DWORD RegStatus; + DWORD RegType; + DWORD BufSize; + char ProgIdClsid[64]; + char Value[128]; + int Key; + BOOL HasRunAs; + char Password[64]; + LSA_HANDLE hPolicy; + LSA_OBJECT_ATTRIBUTES ObjAttributes; + LSA_UNICODE_STRING LsaKey; + LSA_UNICODE_STRING * LsaData; + WCHAR wszKey[64]; + WCHAR wszPassword[64]; + NTSTATUS NtStatus; + + RegStatus = RegOpenKeyEx( + HKEY_CLASSES_ROOT, + "CLSID", + 0, + KEY_READ, + &hRegClsid ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not open HKEY_CLASSES_ROOT\\CLSID for reading.\n" ); + return; + } + + if ( ClsidInfo->ProgId ) + { + RegStatus = RegOpenKeyEx( + HKEY_CLASSES_ROOT, + ClsidInfo->ProgId, + 0, + KEY_READ, + &hProgId ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Couldn't open ProgID %s\n", ClsidInfo->ProgId ); + return; + } + + RegStatus = RegOpenKeyEx( + hProgId, + "CLSID", + 0, + KEY_READ, + &hProgIdClsid ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Couldn't open CLSID key for ProgID %s\n", ClsidInfo->ProgId ); + return; + } + + BufSize = sizeof(ProgIdClsid); + + RegStatus = RegQueryValueEx( + hProgIdClsid, + NULL, + 0, + &RegType, + (LPBYTE) ProgIdClsid, + &BufSize ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Couldn't open CLSID value for ProgID %s\n", ClsidInfo->ProgId ); + return; + } + + if ( ClsidInfo->Clsid && + (_stricmp( ClsidInfo->Clsid, ProgIdClsid ) != 0) ) + { + printf( "ProgID %s CLSID key value %s differs from given CLSID %s.\n", + ClsidInfo->ProgId, + ProgIdClsid, + ClsidInfo->Clsid ); + return; + } + else + ClsidInfo->Clsid = ProgIdClsid; + } + + + if ( ! ClsidInfo->Clsid ) + { + printf( "Could not determine CLSID.\n" ); + return; + } + + RegStatus = RegOpenKeyEx( + hRegClsid, + ClsidInfo->Clsid, + 0, + KEY_READ, + &hClsid ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not open CLSID %s\n", ClsidInfo->Clsid ); + return; + } + + putchar( '\n' ); + if ( ClsidInfo->ProgId ) + printf( "Server settings for ProgID %s, ", ClsidInfo->ProgId ); + else + printf( "Server settings for " ); + + printf( "CLSID %s\n", ClsidInfo->Clsid ); + + HasRunAs = FALSE; + + for ( Key = 1; Key <= CLSID_KEYS; Key++ ) + { + RegStatus = RegOpenKeyEx( + hClsid, + ClsidKeyNames[Key], + 0, + KEY_READ, + &hKey ); + + if ( RegStatus != ERROR_SUCCESS ) + continue; + + BufSize = sizeof(Value); + + if ( Key != ACCESS_PERMISSION ) + { + RegStatus = RegQueryValueEx( + hKey, + NULL, + 0, + &RegType, + (LPBYTE) Value, + &BufSize ); + } + else + RegStatus = ERROR_SUCCESS; + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( " %-28s(key exists, but value could not be read)\n", + ClsidKeyNames[Key] ); + continue; + } + + printf( " %-28s%s\n", + ClsidKeyNames[Key], + (Key == ACCESS_PERMISSION) ? "on" : Value ); + + if ( (Key == RUN_AS) && (_stricmp(Value,"Interactive User") != 0) ) + HasRunAs = TRUE; + } + + if ( ! HasRunAs ) + return; + + // + // Give the option of verifying the RunAs password. + // + + printf( "\nCLSID configured with RunAs. Would you like to verify the password? " ); + + if ( (char)CharUpper((LPSTR)getchar()) != 'Y' ) + return; + + while ( getchar() != '\n' ) + ; + + putchar( '\n' ); + + lstrcpyW( wszKey, L"SCM:" ); + MultiByteToWideChar( CP_ACP, + MB_PRECOMPOSED, + ClsidInfo->Clsid, + -1, + &wszKey[lstrlenW(wszKey)], + sizeof(wszKey)/2 - lstrlenW(wszKey) ); + + LsaKey.Length = (lstrlenW(wszKey) + 1) * sizeof(WCHAR); + LsaKey.MaximumLength = sizeof(wszKey); + LsaKey.Buffer = wszKey; + + InitializeObjectAttributes( &ObjAttributes, NULL, 0L, NULL, NULL ); + + // Open the local security policy + NtStatus = LsaOpenPolicy( NULL, + &ObjAttributes, + POLICY_CREATE_SECRET, + &hPolicy ); + + if ( ! NT_SUCCESS( NtStatus ) ) + { + printf( "Could not open RunAs password (0x%x)\n", NtStatus ); + return; + } + + // Retrive private data + NtStatus = LsaRetrievePrivateData( hPolicy, &LsaKey, &LsaData ); + + if ( ! NT_SUCCESS(NtStatus) ) + { + printf( "Could not open RunAs password (0x%x)\n", NtStatus ); + return; + } + + LsaClose(hPolicy); + + for (;;) + { + printf( "Password : " ); + ReadPassword( Password ); + + if ( strcmp( Password, "dcom4ever" ) == 0 ) + { + printf( "\nThe RunAs password is %ws\n", LsaData->Buffer ); + return; + } + + MultiByteToWideChar( CP_ACP, + MB_PRECOMPOSED, + Password, + -1, + wszPassword, + sizeof(wszPassword) ); + + if ( lstrcmpW( wszPassword, LsaData->Buffer ) != 0 ) + { + printf( "\nPassword does not match RunAs password.\n" ); + printf( "Enter another password or hit Control-C to exit.\n\n" ); + } + else + { + printf( "\nPasswords match.\n" ); + return; + } + } +} + +void UpdateClsidKeys( CLSID_INFO * ClsidInfo ) +{ + HKEY hProgId; + HKEY hClsid; + HKEY hProgIdClsid; + HKEY hKey; + DWORD RegStatus; + DWORD Disposition; + DWORD RegType; + char ProgIdClsid[64]; + char Response[64]; + DWORD BufSize; + int n; + + RegStatus = RegOpenKeyEx( + HKEY_CLASSES_ROOT, + "CLSID", + 0, + KEY_READ | KEY_WRITE, + &hRegClsid ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not open HKEY_CLASSES_ROOT\\CLSID for writing\n" ); + return; + } + + hProgId = 0; + hClsid = 0; + + if ( ClsidInfo->ProgId ) + { + RegStatus = RegCreateKeyEx( + HKEY_CLASSES_ROOT, + ClsidInfo->ProgId, + 0, + "REG_SZ", + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE, + NULL, + &hProgId, + &Disposition ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not open or create ProgID key %s.\n", + ClsidInfo->ProgId); + return; + } + + if ( Disposition == REG_CREATED_NEW_KEY ) + printf( "ProgId key %s created.\n", ClsidInfo->ProgId ); + + if ( ClsidInfo->ProgIdDescription ) + { + RegStatus = RegSetValueEx( + hProgId, + NULL, + 0, + REG_SZ, + (LPBYTE) ClsidInfo->ProgIdDescription, + strlen(ClsidInfo->ProgIdDescription) + sizeof(char) ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not set description value for ProgID %s.\n", ClsidInfo->ProgId ); + return; + } + + printf( "Setting description value %s for ProgID %s.\n", + ClsidInfo->ProgIdDescription, + ClsidInfo->ProgId ); + } + + RegStatus = RegCreateKeyEx( + hProgId, + "CLSID", + 0, + "REG_SZ", + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE, + NULL, + &hProgIdClsid, + &Disposition ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not open or create CLSID key for ProgID %s.\n", + ClsidInfo->ProgId ); + return; + } + + // + // Check if a CLSID key value already exists for this ProgID. If so, + // and a CLSID was specified to us then check if they differ. + // + + BufSize = sizeof(ProgIdClsid); + + RegStatus = RegQueryValueEx( + hProgIdClsid, + NULL, + 0, + &RegType, + (LPBYTE) ProgIdClsid, + &BufSize ); + + if ( RegStatus == ERROR_SUCCESS ) + { + if ( ClsidInfo->Clsid && + (_stricmp(ClsidInfo->Clsid, ProgIdClsid) != 0) ) + { + printf( "ProgID %s has existing CLSID key value %s\n", + ClsidInfo->ProgId, + ProgIdClsid ); + printf( "which differs from given CLSID %s.\n", + ClsidInfo->Clsid ); + printf( "Would you like to replace the existing CLSID value with the new CLSID value? " ); + gets( Response ); + if ( (char)CharUpper((LPSTR)Response[0]) != 'Y' ) + ClsidInfo->Clsid = ProgIdClsid; + } + else + ClsidInfo->Clsid = ProgIdClsid; + } + + if ( ! ClsidInfo->Clsid ) + { + printf( "CLSID for ProgID %s not specified.\n", + ClsidInfo->ProgId ); + return; + } + + if ( ClsidInfo->Clsid != ProgIdClsid ) + { + RegStatus = RegSetValueEx( + hProgIdClsid, + NULL, + 0, + REG_SZ, + (LPBYTE) ClsidInfo->Clsid, + strlen(ClsidInfo->Clsid) + sizeof(char) ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not set CLSID value for ProgID %s.\n", ClsidInfo->ProgId ); + return; + } + + printf( "Setting CLSID value %s for ProgID %s.\n", + ClsidInfo->Clsid, + ClsidInfo->ProgId ); + } + } + + RegStatus = RegCreateKeyEx( + hRegClsid, + ClsidInfo->Clsid, + 0, + "REG_SZ", + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE, + NULL, + &hClsid, + &Disposition ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not open or create CLSID key %s.\n", ClsidInfo->Clsid ); + return; + } + + if ( Disposition == REG_CREATED_NEW_KEY ) + printf( "CLSID key %s created.\n", ClsidInfo->Clsid ); + + if ( ClsidInfo->ClsidDescription ) + { + RegStatus = RegSetValueEx( + hClsid, + NULL, + 0, + REG_SZ, + (LPBYTE) ClsidInfo->ClsidDescription, + strlen(ClsidInfo->ClsidDescription) + sizeof(char) ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not set description value for CLSID %s.\n", ClsidInfo->Clsid ); + return; + } + + printf( "Setting description value %s for CLSID %s.\n", + ClsidInfo->ClsidDescription, + ClsidInfo->Clsid ); + } + + // + // Now add and delete individual keys on this CLSID. + // + + if ( (ClsidInfo->LaunchPermission == YES) || + (ClsidInfo->LaunchPermission == NO) ) + { + SetClsidKey( hClsid, + ClsidInfo->Clsid, + ClsidKeyNames[LAUNCH_PERMISSION], + (ClsidInfo->LaunchPermission == YES) ? "Y" : "N" ); + } + + if ( ClsidInfo->AccessPermission == YES ) + { + SetClsidKey( hClsid, + ClsidInfo->Clsid, + ClsidKeyNames[ACCESS_PERMISSION], + NULL ); + } + + if ( (ClsidInfo->ActivateAtStorage == YES) || + (ClsidInfo->ActivateAtStorage == NO) ) + { + SetClsidKey( hClsid, + ClsidInfo->Clsid, + ClsidKeyNames[ACTIVATE_AT_STORAGE], + (ClsidInfo->ActivateAtStorage == YES) ? "Y" : "N" ); + } + + for ( n = 1; n <= CLSID_PATH_KEYS; n++ ) + { + if ( ! ClsidInfo->ServerPaths[n] ) + continue; + if ( ClsidInfo->ServerPaths[n][0] == '\0' ) + DeleteClsidKey( hClsid, + ClsidInfo->Clsid, + ClsidKeyNames[n] ); + else + SetClsidKey( hClsid, + ClsidInfo->Clsid, + ClsidKeyNames[n], + ClsidInfo->ServerPaths[n] ); + } + + if ( ClsidInfo->RemoteServerName ) + { + if ( ClsidInfo->RemoteServerName[0] == '\0' ) + DeleteClsidKey( hClsid, + ClsidInfo->Clsid, + ClsidKeyNames[REMOTE_SERVER_NAME] ); + else + SetClsidKey( hClsid, + ClsidInfo->Clsid, + ClsidKeyNames[REMOTE_SERVER_NAME], + ClsidInfo->RemoteServerName ); + } + + if ( ClsidInfo->RunAsUserName ) + { + DWORD CharRead; + char Password1[64]; + char Password2[64]; + LSA_HANDLE hPolicy; + LSA_OBJECT_ATTRIBUTES ObjAttributes; + LSA_UNICODE_STRING LsaKey; + LSA_UNICODE_STRING LsaData; + WCHAR wszKey[64]; + WCHAR wszPassword[64]; + NTSTATUS NtStatus; + BOOL Status; + BOOL RunAsInteractiveUser; + + RunAsInteractiveUser = (_stricmp(ClsidInfo->RunAsUserName,"Interactive User") == 0); + + if ( ! RunAsInteractiveUser ) + { + InitializeObjectAttributes( &ObjAttributes, NULL, 0L, NULL, NULL ); + + // Open the local security policy + NtStatus = LsaOpenPolicy( NULL, + &ObjAttributes, + POLICY_CREATE_SECRET, + &hPolicy ); + + if ( ! NT_SUCCESS( NtStatus ) ) + { + printf( "Could not setup RunAs (0x%x)\n", NtStatus ); + return; + } + + lstrcpyW( wszKey, L"SCM:" ); + MultiByteToWideChar( CP_ACP, + MB_PRECOMPOSED, + ClsidInfo->Clsid, + -1, + &wszKey[lstrlenW(wszKey)], + sizeof(wszKey)/2 - lstrlenW(wszKey) ); + + LsaKey.Length = (lstrlenW(wszKey) + 1) * sizeof(WCHAR); + LsaKey.MaximumLength = sizeof(wszKey); + LsaKey.Buffer = wszKey; + } + + if ( ClsidInfo->RunAsUserName[0] == '\0' ) + { + DeleteClsidKey( hClsid, + ClsidInfo->Clsid, + ClsidKeyNames[RUN_AS] ); + + LsaStorePrivateData( hPolicy, &LsaKey, NULL ); + } + else + { + Status = SetClsidKey( hClsid, + ClsidInfo->Clsid, + ClsidKeyNames[RUN_AS], + ClsidInfo->RunAsUserName ); + + if ( ! Status ) + return; + + if ( ! RunAsInteractiveUser && (ClsidInfo->RunAsPassword[0] == '*') ) + { + for (;;) + { + printf( "Enter RunAs password for %s : ", ClsidInfo->RunAsUserName ); + ReadPassword( Password1 ); + + printf( "Confirm password : " ); + ReadPassword( Password2 ); + + if ( strcmp( Password1, Password2 ) != 0 ) + { + printf( "Passwords differ, try again or hit Control-C to exit.\n" ); + continue; + } + + if ( Password1[0] == '\0' ) + { + printf( "Do you really want a blank password? " ); + gets( Response ); + if ( (char)CharUpper((LPSTR)Response[0]) != 'Y' ) + continue; + } + + break; + } + + ClsidInfo->RunAsPassword = Password1; + } // if password == "*" + + // Got a good one! + + if ( ! RunAsInteractiveUser ) + { + MultiByteToWideChar( CP_ACP, + MB_PRECOMPOSED, + ClsidInfo->RunAsPassword, + -1, + wszPassword, + sizeof(wszPassword)/2 ); + + LsaData.Length = (lstrlenW(wszPassword) + 1) * sizeof(WCHAR); + LsaData.MaximumLength = sizeof(wszPassword); + LsaData.Buffer = wszPassword; + + // Store private data + NtStatus = LsaStorePrivateData( hPolicy, &LsaKey, &LsaData ); + + if ( ! NT_SUCCESS(NtStatus) ) + { + printf( "Could not store password securely (0x%x)\n", NtStatus ); + return; + } + + LsaClose(hPolicy); + } + } + } + + printf( "CLSID keys updated successfully.\n" ); +} + +BOOL SetClsidKey( + HKEY hClsid, + char * Clsid, + const char * Key, + char * Value ) +{ + HKEY hKey; + DWORD RegStatus; + DWORD Disposition; + DWORD ValueType; + DWORD ValueSize; + char OldValue[256]; + BOOL HasOldValue; + + HasOldValue = FALSE; + + RegStatus = RegCreateKeyEx( + hClsid, + Key, + 0, + "REG_SZ", + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE, + NULL, + &hKey, + &Disposition ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not create key %s for CLSID %s\n", Key, Clsid ); + return FALSE; + } + + if ( Disposition == REG_CREATED_NEW_KEY ) + { + printf( "Added key %s for CLSID %s\n", Key, Clsid ); + } + else + { + ValueSize = sizeof(OldValue); + + RegStatus = RegQueryValueEx( + hKey, + NULL, + 0, + &ValueType, + OldValue, + &ValueSize ); + + HasOldValue = (RegStatus == ERROR_SUCCESS); + } + + if ( ! Value ) + return TRUE; + + RegStatus = RegSetValueEx( + hKey, + NULL, + 0, + REG_SZ, + (LPBYTE) Value, + strlen(Value) + sizeof(char) ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not set value %s for key %s\n", Value, Key ); + return FALSE; + } + + if ( HasOldValue ) + printf( "Changed value from %s to %s for key %s\n", OldValue, Value, Key ); + else + printf( "Added value %s for key %s\n", Value, Key ); + + return TRUE; +} + +BOOL DeleteClsidKey( + HKEY hClsid, + char * Clsid, + const char * Key ) +{ + DWORD RegStatus; + + RegStatus = RegDeleteKey( hClsid, Key ); + + if ( RegStatus != ERROR_SUCCESS ) + { + printf( "Could not delete key %s for CLSID %s\n", Key, Clsid ); + return FALSE; + } + + printf( "Deleted key %s for CLSID %s\n", Key, Clsid ); + return TRUE; +} + +void ReadPassword( char * Password ) +{ + int c, n; + + n = 0; + + for (;;) + { + c = _getch(); + + // ^C + if ( c == 0x3 ) + { + putchar( '\n' ); + ExitProcess( 0 ); + } + + // Backspace + if ( c == 0x8 ) + { + if ( n ) + { + n--; + _putch( 0x8 ); + _putch( ' ' ); + _putch( 0x8 ); + } + continue; + } + + // Return + if ( c == '\r' ) + break; + + Password[n++] = c; + _putch( '*' ); + } + + Password[n] = 0; + putchar( '\n' ); +} + +BOOL ControlCConsoleHandler( DWORD ControlType ) +{ + if ( (ControlType == CTRL_C_EVENT) || (ControlType == CTRL_BREAK_EVENT) ) + { + printf( "RunAs password unchanged\n" ); + ExitProcess( 0 ); + } + + return FALSE; +} + + diff --git a/private/ole32/olecnfg/olecnfg.h b/private/ole32/olecnfg/olecnfg.h new file mode 100644 index 000000000..e7ff03f34 --- /dev/null +++ b/private/ole32/olecnfg/olecnfg.h @@ -0,0 +1,121 @@ +// +// +// + +#ifndef _OLECONFIG_ +#define _OLECONFIG_ + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <ntlsa.h> +#include <windows.h> +#include <stdlib.h> +#include <stdio.h> +#include <conio.h> + +#define ENABLE_NETWORK_OLE 1 +#define DEFAULT_LAUNCH_PERMISSION 2 +#define DEFAULT_ACCESS_PERMISSION 3 +#define LEGACY_AUTHENTICATION_LEVEL 4 + +#define GLOBAL_KEYS 4 + +#define MERGE 101 +#define SAVE_USER 102 +#define SAVE_COMMON 103 + +#define GLOBAL_OPERATIONS 103 + +#define INPROC_HANDLER32 1 +#define INPROC_SERVER32 2 +#define LOCAL_SERVER32 3 +#define LOCAL_SERVICE 4 +#define REMOTE_SERVER_NAME 5 +#define RUN_AS 6 +#define ACTIVATE_AT_STORAGE 7 +#define LAUNCH_PERMISSION 8 +#define ACCESS_PERMISSION 9 + +#define CLSID_KEYS 9 +#define CLSID_PATH_KEYS 4 + +#define UNKNOWN 0 +#define END_OF_ARGS -1 + +#define INVALID -1 +#define NO 1 +#define YES 2 + +#define EAT_ARG() Args++; ArgsLeft--; + +typedef struct + { + char * Clsid; + char * ClsidDescription; + char * ProgId; + char * ProgIdDescription; + + int LaunchPermission; + int AccessPermission; + int ActivateAtStorage; + + char * ServerPaths[CLSID_PATH_KEYS+1]; + char * RemoteServerName; + char * RunAsUserName; + char * RunAsPassword; + } CLSID_INFO; + +extern const char * GlobalKeyNames[]; +extern const char * ClsidKeyNames[]; + +extern int ArgsLeft; +extern char ** Args; +extern char * ProgramName; + +extern HKEY hRegOle; +extern HKEY hRegClsid; + +// main.c +void ParseClsidProgId(); +int NextClsidKey(); +int ReadYesOrNo(); +void DisplayHelp(); + +// oleconfig.c +BOOL SetGlobalKey( + int Key, + int Value ); + +void DisplayGlobalSettings(); + +void DisplayClsidKeys( + CLSID_INFO * ClsidInfo ); + +void UpdateClsidKeys( + CLSID_INFO * ClsidInfo ); + +BOOL SetClsidKey( + HKEY hClsid, + char * Clsid, + const char * Key, + char * Value ); + +BOOL DeleteClsidKey( + HKEY hClsid, + char * Clsid, + const char * Key ); + +void ReadPassword( + char * Password ); + +BOOL ControlCConsoleHandler( + DWORD ControlType ); + +void MergeHives( ); + +void SaveChangesToUser( ); + +void SaveChangesToCommon( ); + +#endif diff --git a/private/ole32/olecnfg/olecnfg.rc b/private/ole32/olecnfg/olecnfg.rc new file mode 100644 index 000000000..5dbcc8a3a --- /dev/null +++ b/private/ole32/olecnfg/olecnfg.rc @@ -0,0 +1,50 @@ +#include <windows.h> +#include <winver.h> + +#define VER_FILEVERSION_STR "4.0\0" +#define VER_FILEVERSION 4,0000,0001,0001 + +#define VER_PRODUCTNAME_STR "Microsoft OLE 4.0 for Windows NT(TM) Operating System\0" +#define VER_COMPANYNAME_STR "Microsoft Corporation\0" +#define VER_LEGALTRADEMARKS_STR "Microsoft(TM) is a registered trademark of Microsoft Corporation. Windows NT(TM) is a trademark of Microsoft Corporation\0" +#define VER_LEGALCOPYRIGHT_STR "Copyright (C) Microsoft Corp. 1992 - 1996\0" +#define VER_PRODUCTVERSION_STR "4.0\0" +#define VER_PRODUCTVERSION 4,0000,001,0001 +#define VER_COMMENT_STR "Microsoft OLE 4.0 for Windows NT(TM) Operating System\0" +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE 0 +#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#define VER_FILEFLAGS 0L +#define VER_FILEOS VOS_NT_WINDOWS32 +#define VER_FILEDESCRIPTION_STR "Microsoft OLE 4.0 for Windows NT(TM) Operating System\0" + + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEFLAGSMASK VER_FILEFLAGSMASK +FILEFLAGS VER_FILEFLAGS +FILEOS VER_FILEOS +FILETYPE VFT_APP +FILESUBTYPE VER_FILESUBTYPE +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "FileDescription", VER_FILEDESCRIPTION_STR + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", "OLECNFG.EXE\0" + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + VALUE "LegalTrademarks", VER_LEGALTRADEMARKS_STR + VALUE "ProductName", VER_PRODUCTNAME_STR + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + VALUE "Comments", VER_COMMENT_STR + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} diff --git a/private/ole32/olecnfg/sid.c b/private/ole32/olecnfg/sid.c new file mode 100644 index 000000000..435df4654 --- /dev/null +++ b/private/ole32/olecnfg/sid.c @@ -0,0 +1,255 @@ +//************************************************************* +// +// SID management functions. +// +// THESE FUNCTIONS ARE WINDOWS NT SPECIFIC!!!!! +// +// 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); + +#define DebugMsg(x) + +/***************************************************************************\ +* GetSidString +* +* Allocates and returns a string representing the sid of the current user +* The returned pointer should be freed using DeleteSidString(). +* +* Returns a pointer to the string or NULL on failure. +* +* History: +* 26-Aug-92 Davidc Created +* +\***************************************************************************/ +LPTSTR GetSidString(HANDLE UserToken) +{ + NTSTATUS NtStatus; + PSID UserSid; + UNICODE_STRING UnicodeString; +#ifndef UNICODE + STRING String; +#endif + + // + // Get the user sid + // + + UserSid = GetUserSid(UserToken); + if (UserSid == NULL) { + DebugMsg((DM_WARNING, TEXT("GetSidString: GetUserSid returned NULL"))); + return NULL; + } + + // + // Convert user SID to a string. + // + + NtStatus = RtlConvertSidToUnicodeString( + &UnicodeString, + UserSid, + (BOOLEAN)TRUE // Allocate + ); + // + // We're finished with the user sid + // + + DeleteUserSid(UserSid); + + // + // See if the conversion to a string worked + // + + if (!NT_SUCCESS(NtStatus)) { + DebugMsg((DM_WARNING, TEXT("GetSidString: RtlConvertSidToUnicodeString failed, status = 0x%x"), + NtStatus)); + return NULL; + } + +#ifdef UNICODE + + + return(UnicodeString.Buffer); + +#else + + // + // Convert the string to ansi + // + + NtStatus = RtlUnicodeStringToAnsiString(&String, &UnicodeString, TRUE); + RtlFreeUnicodeString(&UnicodeString); + if (!NT_SUCCESS(NtStatus)) { + DebugMsg((DM_WARNING, TEXT("GetSidString: RtlUnicodeStringToAnsiString failed, status = 0x%x"), + status)); + return NULL; + } + + + return(String.Buffer); + +#endif + +} + + +/***************************************************************************\ +* DeleteSidString +* +* Frees up a sid string previously returned by GetSidString() +* +* Returns nothing. +* +* History: +* 26-Aug-92 Davidc Created +* +\***************************************************************************/ +VOID DeleteSidString(LPTSTR SidString) +{ + +#ifdef UNICODE + UNICODE_STRING String; + + RtlInitUnicodeString(&String, SidString); + + RtlFreeUnicodeString(&String); +#else + ANSI_STRING String; + + RtlInitAnsiString(&String, SidString); + + RtlFreeAnsiString(&String); +#endif + +} + + + +/***************************************************************************\ +* GetUserSid +* +* Allocs space for the user sid, fills it in and returns a pointer. Caller +* The sid should be freed by calling DeleteUserSid. +* +* Note the sid returned is the user's real sid, not the per-logon sid. +* +* Returns pointer to sid or NULL on failure. +* +* History: +* 26-Aug-92 Davidc Created. +\***************************************************************************/ +PSID GetUserSid (HANDLE UserToken) +{ + PTOKEN_USER pUser; + PSID pSid; + DWORD BytesRequired = 200; + NTSTATUS status; + + + // + // Allocate space for the user info + // + + pUser = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, BytesRequired); + + + if (pUser == NULL) { + DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"), + BytesRequired)); + return NULL; + } + + + // + // Read in the UserInfo + // + + status = NtQueryInformationToken( + UserToken, // Handle + TokenUser, // TokenInformationClass + pUser, // TokenInformation + BytesRequired, // TokenInformationLength + &BytesRequired // ReturnLength + ); + + if (status == STATUS_BUFFER_TOO_SMALL) { + + // + // Allocate a bigger buffer and try again. + // + + pUser = LocalReAlloc(pUser, BytesRequired, LMEM_MOVEABLE); + if (pUser == NULL) { + DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"), + BytesRequired)); + return NULL; + } + + status = NtQueryInformationToken( + UserToken, // Handle + TokenUser, // TokenInformationClass + pUser, // TokenInformation + BytesRequired, // TokenInformationLength + &BytesRequired // ReturnLength + ); + + } + + if (!NT_SUCCESS(status)) { + DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to query user info from user token, status = 0x%x"), + status)); + LocalFree(pUser); + return NULL; + } + + + BytesRequired = RtlLengthSid(pUser->User.Sid); + pSid = LocalAlloc(LMEM_FIXED, BytesRequired); + if (pSid == NULL) { + DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"), + BytesRequired)); + LocalFree(pUser); + return NULL; + } + + + status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid); + + LocalFree(pUser); + + if (!NT_SUCCESS(status)) { + DebugMsg((DM_WARNING, TEXT("GetUserSid: RtlCopySid Failed. status = %d"), + status)); + LocalFree(pSid); + pSid = NULL; + } + + + return pSid; +} + + +/***************************************************************************\ +* DeleteUserSid +* +* Deletes a user sid previously returned by GetUserSid() +* +* Returns nothing. +* +* History: +* 26-Aug-92 Davidc Created +* +\***************************************************************************/ +VOID DeleteUserSid(PSID Sid) +{ + LocalFree(Sid); +} diff --git a/private/ole32/olecnfg/sources b/private/ole32/olecnfg/sources new file mode 100644 index 000000000..2a1675c5b --- /dev/null +++ b/private/ole32/olecnfg/sources @@ -0,0 +1,74 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1989 + + +Revision History: + +!ENDIF + +# +# The TARGETNAME variable is defined by the developer. It is the name of +# the target (component) that is being built by this makefile. It +# should NOT include any path or file extension information. +# + +TARGETNAME=olecnfg + +# +# The TARGETPATH and TARGETTYPE varialbes are defined by the developer. +# The first specifies where the target is to be build. The second specifies +# the type of target (either PROGRAM, DYNLINK or LIBRARY) +# + +TARGETPATH=. +TARGETTYPE=PROGRAM + +# +# The INCLUDES variable specifies any include paths that are specific to +# this source directory. Separate multiple directory paths with single +# semicolons. Relative path specifications are okay. +# + +INCLUDES=. + +# +# The SOURCES variable is defined by the developer. It is a list of all the +# source files for this component. Each source file should be on a separate +# line using the line continuation character. This will minimize merge +# conflicts if two developers adding source files to the same component. +# + +SOURCES=\ + main.c \ + treemgmt.c \ + clshive.c \ + sid.c \ + olecnfg.c \ + olecnfg.rc + +# C_DEFINES= + +LINKLIBS=\ + $(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib \ + $(BASEDIR)\public\sdk\lib\*\ntdll.lib + +UMTYPE=console diff --git a/private/ole32/olecnfg/treemgmt.c b/private/ole32/olecnfg/treemgmt.c new file mode 100644 index 000000000..761c293b0 --- /dev/null +++ b/private/ole32/olecnfg/treemgmt.c @@ -0,0 +1,882 @@ +//************************************************************* +// +// Personal Classes Profile management routines +// +// Microsoft Confidential +// Copyright (c) Microsoft Corporation 1995 +// All rights reserved +// +//************************************************************* + +#include "uenv.h" +#include "windows.h" + +// Local Data Structures + +LPTSTR SpecialSubtrees[] = + { + TEXT("CLSID"), + TEXT("Interface"), + TEXT("TypeLib"), + TEXT("Licenses"), + TEXT("FileType") + }; + +#define MAX_SPECIAL_SUBTREE (sizeof(SpecialSubtrees)/sizeof(LPTSTR)) +// +// Local function proto-types +// +typedef struct _RegKeyInfo { + DWORD SubKeyCount; + DWORD MaxSubKeyLen; + DWORD ValueCount; + DWORD MaxValueNameLen; + DWORD MaxValueLen; + DWORD SDLen; + LPTSTR pSubKeyName; + LPTSTR pValueName; + LPTSTR pValue; + } REGKEYINFO, *PREGKEYINFO; + +//************************************************************* +// +// PrepForEnumRegistryTree() +// +// Purpose: prepare to duplicate a source bunch of keys into the destination. +// +// Parameters: hkSourceTree - source registry tree +// pRegKeyInfo - info block for use doing enumeration +// +// Return: TRUE if successful +// FALSE if an error occurs +// +// History: Date Author Comment +// 1/30/96 GregJen Created +// +//************************************************************* +BOOL +PrepForEnumRegistryTree( + HKEY hkSourceTree, + PREGKEYINFO pRegKeyInfo + ) +{ + LPTSTR pStringsBuffer; + LONG result; + + result = RegQueryInfoKey(hkSourceTree, + NULL, + NULL, + 0, + &pRegKeyInfo->SubKeyCount, + &pRegKeyInfo->MaxSubKeyLen, + NULL, + &pRegKeyInfo->ValueCount, + &pRegKeyInfo->MaxValueNameLen, + &pRegKeyInfo->MaxValueLen, + &pRegKeyInfo->SDLen, + NULL); + + if ( result != ERROR_SUCCESS ) + return FALSE; + + // allocate a block of memory to use for enumerating subkeys and values + pStringsBuffer = (LPTSTR) LocalAlloc( LPTR, + (pRegKeyInfo->MaxSubKeyLen + + pRegKeyInfo->MaxValueNameLen + + pRegKeyInfo->MaxValueLen + 3) + * sizeof( TCHAR ) ); + if ( !pStringsBuffer ) + return FALSE; + + pRegKeyInfo->pSubKeyName = pStringsBuffer; + pRegKeyInfo->pValueName = pStringsBuffer + pRegKeyInfo->MaxSubKeyLen + 1; + pRegKeyInfo->pValue = pRegKeyInfo->pValueName + + pRegKeyInfo->MaxValueNameLen + 1; + +} + +//************************************************************* +// +// CleanupAfterEnumRegistryTree() +// +// Purpose: duplicate a source bunch of keys into the destination. +// +// Parameters: hkSourceTree - source registry tree +// pRegKeyInfo - info block for use doing enumeration +// +// Return: TRUE if successful +// FALSE if an error occurs +// +// History: Date Author Comment +// 1/30/96 GregJen Created +// +//************************************************************* +void +CleanupAfterEnumRegistryTree( + HKEY hkSourceTree, + PREGKEYINFO pRegKeyInfo) +{ + LocalFree( pRegKeyInfo->pSubKeyName ); +} +BOOL +DeleteRegistrySubtree ( + HKEY hkTree ) +{ + HKEY hkCurrentSourceKey; + DWORD idx; + DWORD NameLen; + LONG result = ERROR_SUCCESS; + REGKEYINFO RegKeyInfo; + BOOL Success = FALSE; + + if ( !PrepForEnumRegistryTree( hkTree, &RegKeyInfo ) ) + return FALSE; // nothing to clean up here yet + + // enumerate all the source subkeys + // for each: if dest subkey is older than source, delete it + // if dest subkey does not exist (or was deleted) clone the subkey + // + // Clone all the subkeys + // + for ( idx = 0; + (result == ERROR_SUCCESS) && + ( result != ERROR_MORE_DATA ) && + ( idx < RegKeyInfo.SubKeyCount ); + idx++ ) { + NameLen = RegKeyInfo.MaxSubKeyLen + sizeof( TCHAR ); + result = RegEnumKeyEx( hkTree, + idx, + RegKeyInfo.pSubKeyName, + &NameLen, + NULL, + NULL, + NULL, + NULL ); + + if ( ( result != ERROR_SUCCESS ) && ( result != ERROR_MORE_DATA ) ) + goto cleanup; + + // TBD: open the subkey in the source tree AS CurrentSourceKey + result = RegOpenKeyEx(hkTree, + RegKeyInfo.pSubKeyName, + 0, + KEY_ALL_ACCESS, + &hkCurrentSourceKey); + + DeleteRegistrySubtree( hkCurrentSourceKey ); + + RegCloseKey( hkCurrentSourceKey ); + + RegDeleteKey( hkTree, RegKeyInfo.pSubKeyName ); + + result = ERROR_SUCCESS; + } + +cleanup: + CleanupAfterEnumRegistryTree( hkTree, &RegKeyInfo ); + + return TRUE; +} + +//************************************************************* +// +// CloneRegistryValues() +// +// Purpose: copy the values from under the source key to the dest key +// +// Parameters: SourceTree - source registry tree +// DestinationTree - destintation registry tree +// RegKeyInfo - handy information from the RegEnumKeyEx call. +// +// Return: TRUE if successful +// FALSE if an error occurs +// +// History: Date Author Comment +// 1/14/96 GregJen Created +// +//************************************************************* +BOOL +CloneRegistryValues( + HKEY hkSourceTree, + HKEY hkDestinationTree, + REGKEYINFO RegKeyInfo ) +{ + LONG result = ERROR_SUCCESS; + DWORD idx; + DWORD ValueLen; + DWORD ValueType; + DWORD DataLen; + + for ( idx = 0; + (result == ERROR_SUCCESS) && + ( result != ERROR_MORE_DATA ) && + ( idx < RegKeyInfo.ValueCount ); + idx++ ) + { + DataLen = RegKeyInfo.MaxValueLen + sizeof( TCHAR ); + ValueLen = RegKeyInfo.MaxValueNameLen + sizeof( TCHAR ); + + result = RegEnumValue( hkSourceTree, + idx, + RegKeyInfo.pValueName, + &ValueLen, + NULL, + &ValueType, + (BYTE*) RegKeyInfo.pValue, + &DataLen); + + // TBD: check errors + + // now add the value to the destination key + + result = RegSetValueEx( hkDestinationTree, + RegKeyInfo.pValueName, + 0, + ValueType, + (BYTE*) RegKeyInfo.pValue, + DataLen ); + // TBD: check errors + } + return TRUE; +} +//************************************************************* +// +// CloneRegistryTree() +// +// Purpose: duplicate a source bunch of keys into the destination. +// +// Parameters: SourceTree - source registry tree +// DestinationTree - destintation registry tree +// lpSubKeyName - if present this is a subkey name that +// corresponds to the SourceTree HKEY. +// +// Return: TRUE if successful +// FALSE if an error occurs +// +// History: Date Author Comment +// 1/14/96 GregJen Created +// +//************************************************************* +BOOL +CloneRegistryTree( + HKEY hkSourceTree, + HKEY hkDestinationTree, + LPTSTR lpDestTreeName ) +{ + HKEY hkCurrentSourceKey; + DWORD idx; + DWORD NameLen; + LONG result = ERROR_SUCCESS; + REGKEYINFO RegKeyInfo; + BOOL Success = FALSE; + + if ( !PrepForEnumRegistryTree( hkSourceTree, &RegKeyInfo ) ) + return FALSE; // nothing to clean up here yet + + if ( lpDestTreeName ) { + HKEY hkNewKey; + DWORD dwSDLen = RegKeyInfo.SDLen; + DWORD dwDisp; + SECURITY_INFORMATION SI = DACL_SECURITY_INFORMATION; // for now... + PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR) + LocalAlloc( LPTR, dwSDLen ); + // TBD: check for NULL; + + // Get the registry security information from the old key + result = RegGetKeySecurity( hkSourceTree, + SI, + pSD, + &dwSDLen); + // TBD: check for errors, free pSD + // create a key with the given name, and registry info + result = RegCreateKeyEx( hkDestinationTree, + lpDestTreeName, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + pSD, + &hkNewKey, + &dwDisp ); + // TBD: check for errors, free pSD + + // TBD: and update the hkDestinationTree variable to point to it + + hkDestinationTree = hkNewKey; + LocalFree( pSD ); + } + + // + // clone the values + // + + if ( ! CloneRegistryValues( hkSourceTree, hkDestinationTree, RegKeyInfo ) ) + goto cleanup; + + // + // Clone all the subkeys + // + for ( idx = 0; + (result == ERROR_SUCCESS) && + ( result != ERROR_MORE_DATA ) && + ( idx < RegKeyInfo.SubKeyCount ); + idx++ ) { + NameLen = RegKeyInfo.MaxSubKeyLen + sizeof( TCHAR ); + result = RegEnumKeyEx( hkSourceTree, + idx, + RegKeyInfo.pSubKeyName, + &NameLen, + NULL, + NULL, + NULL, + NULL ); + + if ( ( result != ERROR_SUCCESS ) && ( result != ERROR_MORE_DATA ) ) + goto cleanup; + + // TBD: open the subkey in the source tree AS CurrentSourceKey + result = RegOpenKeyEx(hkSourceTree, + RegKeyInfo.pSubKeyName, + 0, + KEY_READ, + &hkCurrentSourceKey); + + // + // recurse passing the subkey name + // + CloneRegistryTree( hkCurrentSourceKey, + hkDestinationTree, + RegKeyInfo.pSubKeyName ); + + // + // close our open key + // + + RegCloseKey( hkCurrentSourceKey ); + } + + Success = TRUE; + +cleanup: + if ( lpDestTreeName ) + { + RegCloseKey( hkDestinationTree ); + } + + CleanupAfterEnumRegistryTree( hkSourceTree, &RegKeyInfo ); + + return Success; +} + +// TBD: dummy prototypes for now +// dummy testing code +void TestCloneHive( ) +{ + // for testing + HKEY hkSource; + HKEY hkDestination; + LONG result; + + result = + RegOpenKeyEx(HKEY_CLASSES_ROOT, + TEXT(".pps"), + 0, + KEY_READ, + &hkSource); + result = + RegOpenKeyEx(HKEY_CLASSES_ROOT, + TEXT(".paa"), + 0, + KEY_ALL_ACCESS, + &hkDestination); + CloneRegistryTree(hkSource, hkDestination, NULL); +} + +void SaveChangesToUser( ) +{ +} + +void SaveChangesToCommon( ) +{ +} + +BOOL +AddSharedValuesToSubkeys( HKEY hkShared, LPTSTR pszSubtree ) +{ + HKEY hkSourceKey; + HKEY hkCurrentSourceKey; + DWORD idx; + DWORD NameLen; + LONG result = ERROR_SUCCESS; + REGKEYINFO RegKeyInfo; + BOOL Success = FALSE; + + + // for every subkey, set "Shared" value + result = RegOpenKeyEx( hkShared, + pszSubtree, + 0, + KEY_READ, + &hkSourceKey ); + + // TBD: if no subtree in source, skip ahead to next special subtree + if ( result == ERROR_FILE_NOT_FOUND ) + return TRUE; + + if ( !PrepForEnumRegistryTree( hkSourceKey, &RegKeyInfo ) ) + goto cleanup2; + + // enumerate all the source subkeys + // for each: if dest subkey is older than source, delete it + // if dest subkey does not exist (or was deleted) clone the subkey + // + // Clone all the subkeys + // + for ( idx = 0; + (result == ERROR_SUCCESS) && + ( result != ERROR_MORE_DATA ) && + ( idx < RegKeyInfo.SubKeyCount ); + idx++ ) + { + NameLen = RegKeyInfo.MaxSubKeyLen + sizeof( TCHAR ); + result = RegEnumKeyEx( hkSourceKey, + idx, + RegKeyInfo.pSubKeyName, + &NameLen, + NULL, + NULL, + NULL, + NULL ); + + if ( ( result != ERROR_SUCCESS ) && ( result != ERROR_MORE_DATA ) ) + goto cleanup; + + result = RegOpenKeyEx( hkSourceKey, + RegKeyInfo.pSubKeyName, + 0, + KEY_ALL_ACCESS, + &hkCurrentSourceKey ); + + // check for errors + + result = RegSetValueEx( hkCurrentSourceKey, + L"Shared", + 0, + REG_SZ, + (LPBYTE) L"Y", + sizeof( L"Y" ) ); + + RegCloseKey( hkCurrentSourceKey ); + + } + + Success = TRUE; + +cleanup: + CleanupAfterEnumRegistryTree( hkSourceKey, &RegKeyInfo ); + +cleanup2: + RegCloseKey( hkSourceKey ); + + return Success; + +} + +BOOL +AddSharedValues( HKEY hkShared ) +{ + // for each of the special subtrees, add "Shared" values + int idx; + + // now, for each of the special top-level keys, process the level below them + // these keys are: CLSID, Interface, TypeLib, Licenses, FileType + + for ( idx = 0; idx < MAX_SPECIAL_SUBTREE; idx++ ) + { + AddSharedValuesToSubkeys( hkShared, SpecialSubtrees[idx] ); + } + + // now do all the top level keys (file extensions and progids) + AddSharedValuesToSubkeys( hkShared, NULL ); + + return TRUE; +} + + +//************************************************************* +// +// MergeUserClasses() +// +// Purpose: Merges the user's class information with the +// common class information. +// +// Parameters: UserClassStore - Per-user class information +// CommonClassStore - Machine-wide class information +// MergedClassStore - Destination for merged information. +// +// Return: TRUE if successful +// FALSE if an error occurs +// +// Comments: UserClassStore may be a null HKEY, implying +// just copy the information from the common +// portion into the merged portion +// +// History: Date Author Comment +// 1/14/96 GregJen Created +// +//************************************************************* +BOOL +MergeRegistrySubKeys ( + HKEY hkSourceTree, + HKEY hkDestTree ) +{ + HKEY hkCurrentSourceKey; + HKEY hkCurrentDestKey; + DWORD idx; + DWORD NameLen; + LONG result = ERROR_SUCCESS; + REGKEYINFO RegKeyInfo; + BOOL Success = FALSE; + FILETIME SourceFileTime; + FILETIME DestFileTime; + LONG cmp; + + if ( !PrepForEnumRegistryTree( hkSourceTree, &RegKeyInfo ) ) + return FALSE; // nothing to clean up here yet + + // enumerate all the source subkeys + // for each: if dest subkey is older than source, delete it + // if dest subkey does not exist (or was deleted) clone the subkey + // + // Clone all the subkeys + // + for ( idx = 0; + (result == ERROR_SUCCESS) && + ( result != ERROR_MORE_DATA ) && + ( idx < RegKeyInfo.SubKeyCount ); + idx++ ) { + NameLen = RegKeyInfo.MaxSubKeyLen + sizeof( TCHAR ); + result = RegEnumKeyEx( hkSourceTree, + idx, + RegKeyInfo.pSubKeyName, + &NameLen, + NULL, + NULL, + NULL, + &SourceFileTime ); + + if ( ( result != ERROR_SUCCESS ) && ( result != ERROR_MORE_DATA ) ) + goto cleanup; + + // TBD: open the subkey in the source tree AS CurrentSourceKey + result = RegOpenKeyEx(hkSourceTree, + RegKeyInfo.pSubKeyName, + 0, + KEY_READ, + &hkCurrentSourceKey); + + + result = RegOpenKeyEx(hkDestTree, + RegKeyInfo.pSubKeyName, + 0, + KEY_READ, + &hkCurrentDestKey); + + // if current dest key does not exist, + if ( result == ERROR_FILE_NOT_FOUND ) + { + // + // recurse passing the subkey name + // + CloneRegistryTree( hkCurrentSourceKey, + hkDestTree, + RegKeyInfo.pSubKeyName ); + } + // if current dest key is older than current source key, delete dest + // then recreate new + else + { + RegQueryInfoKey( hkCurrentDestKey, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &DestFileTime ); + + + cmp = CompareFileTime( &SourceFileTime, &DestFileTime ); + if ( cmp > 0 ) + { + // delete dest + // + DeleteRegistrySubtree( hkCurrentDestKey ); + + // + // recurse passing the subkey name + // + CloneRegistryTree( hkCurrentSourceKey, + hkDestTree, + RegKeyInfo.pSubKeyName ); + } + } + + // + // close our open key + // + + RegCloseKey( hkCurrentSourceKey ); + + result = ERROR_SUCCESS; + } + +cleanup: + CleanupAfterEnumRegistryTree( hkSourceTree, &RegKeyInfo ); + + return TRUE; +} + + + + +//************************************************************* +// +// MergeUserClasses() +// +// Purpose: Merges the user's class information with the +// common class information. +// +// Parameters: UserClassStore - Per-user class information +// CommonClassStore - Machine-wide class information +// MergedClassStore - Destination for merged information. +// +// Return: TRUE if successful +// FALSE if an error occurs +// +// Comments: UserClassStore may be a null HKEY, implying +// just copy the information from the common +// portion into the merged portion +// +// History: Date Author Comment +// 1/14/96 GregJen Created +// +//************************************************************* +BOOL +MergeRegistrySubtree ( + HKEY hkSourceParent, + HKEY hkDestParent, + LPTSTR pszSubtree ) +{ + HKEY hkCurrentSourceKey; + HKEY hkCurrentDestKey; + LONG result; + DWORD dummy = 0; + + // open the special subtree in the source tree + result = RegOpenKeyEx( hkSourceParent, + pszSubtree, + 0, + KEY_READ, + &hkCurrentSourceKey ); + + // TBD: if no subtree in source, skip ahead to next special subtree + if ( result == ERROR_FILE_NOT_FOUND ) + return TRUE; + + result = RegOpenKeyEx( hkDestParent, + pszSubtree, + 0, + KEY_ALL_ACCESS, + &hkCurrentDestKey ); + // TBD: if no such subtree in dest, do CloneRegistry etc + if ( result == ERROR_FILE_NOT_FOUND ) + { + // + // recurse passing the subkey name + // + CloneRegistryTree( hkCurrentSourceKey, + hkDestParent, + pszSubtree ); + } + // TBD:if timestamp on source is newer than timestamp on dest, + // delete dest and recreate?? + + MergeRegistrySubKeys( hkCurrentSourceKey, + hkCurrentDestKey ); + + // make sure the timestamp on the special trees is updated + result = RegSetValueEx( hkCurrentDestKey, + TEXT("Updated"), + 0, + REG_DWORD, + (BYTE*) &dummy, + sizeof( DWORD ) ); + + + // close special subtrees + RegCloseKey( hkCurrentSourceKey ); + RegCloseKey( hkCurrentDestKey ); + + return TRUE; +} + +long +CompareRegistryTimes( + HKEY hkLHS, + HKEY hkRHS ) +{ + FILETIME LHSTime; + FILETIME RHSTime; + + RegQueryInfoKey( hkLHS, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &LHSTime ); + + RegQueryInfoKey( hkRHS, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &RHSTime ); + + return CompareFileTime( &LHSTime, &RHSTime ); +} + +//************************************************************* +// +// MergeUserClasses() +// +// Purpose: Merges the user's class information with the +// common class information. +// +// Parameters: UserClassStore - Per-user class information +// CommonClassStore - Machine-wide class information +// MergedClassStore - Destination for merged information. +// +// Return: TRUE if successful +// FALSE if an error occurs +// +// Comments: UserClassStore may be a null HKEY, implying +// just copy the information from the common +// portion into the merged portion +// +// History: Date Author Comment +// 1/14/96 GregJen Created +// +//************************************************************* +BOOL +MergeUserClasses( + HKEY UserClassStore, + HKEY CommonClassStore, + HKEY MergedClassStore, + BOOL ForceNew ) +{ + BOOL fNotCorrectUser = FALSE; + HKEY hkOverridingSubtree = CommonClassStore; + HKEY hkMergingSubtree = UserClassStore; + int idx; + + //TBD: check time stamps on source and destination + // if same user, and timestamps are in sync, do nothing + + // if destination does not belong to the current user, then + // delete everything under it + + if ( fNotCorrectUser ) { + DeleteRegistrySubtree( MergedClassStore ); + } + + + if ( !ForceNew && + ( CompareRegistryTimes( MergedClassStore, CommonClassStore ) > 0 ) && + ( CompareRegistryTimes( MergedClassStore, UserClassStore ) > 0 ) ) + { + return TRUE; + } + + // TBD: copy everything from the overriding store into the + // destination store + // At this moment, the common store overrides the user store; + // this will eventually reverse. + + CloneRegistryTree( hkOverridingSubtree, MergedClassStore, NULL ); + + // now, for each of the special top-level keys, process the level below them + // these keys are: CLSID, Interface, TypeLib, Licenses, FileType + + for ( idx = 0; idx < MAX_SPECIAL_SUBTREE; idx++ ) + { + MergeRegistrySubtree( hkMergingSubtree, + MergedClassStore, + SpecialSubtrees[idx] ); + } + + // now do all the top level keys (file extensions and progids) + // TBD: MergeRegistrySubtree( UserClassStore, MergedClassStore ); + MergeRegistrySubtree( hkMergingSubtree, + MergedClassStore, + NULL ); + +return TRUE; +} +// dummy testing code +void TestMergeHives( ) +{ + // for testing + HKEY hkUser; + HKEY hkMachine; + HKEY hkMerged; + LONG result; + DWORD dwCreated; + + result = + RegOpenKeyEx(HKEY_CLASSES_ROOT, + TEXT(".111111\\PerUser"), + 0, + KEY_READ, + &hkUser); + result = + RegOpenKeyEx(HKEY_CLASSES_ROOT, + TEXT(".111111\\MachineClasses"), + 0, + KEY_READ, + &hkMachine); + // note: eventually, this would be created with the + // same security as the per-user part. + + // if the per-user part is missing, just copy the machine to per-user + // + result = + RegCreateKeyEx(HKEY_CLASSES_ROOT, + TEXT(".111111\\MergedClasses"), + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hkMerged, + &dwCreated); + MergeUserClasses(hkUser, hkMachine, hkMerged, TRUE); +} + + diff --git a/private/ole32/olecnfg/uenv.h b/private/ole32/olecnfg/uenv.h new file mode 100644 index 000000000..f950563ca --- /dev/null +++ b/private/ole32/olecnfg/uenv.h @@ -0,0 +1,26 @@ +//************************************************************* +// +// Personal Classes Profile management routines +// +// Microsoft Confidential +// Copyright (c) Microsoft Corporation 1995 +// All rights reserved +// +//************************************************************* + +#define UNICODE 1 + +#include "nt.h" +#include "ntrtl.h" +#include "nturtl.h" +#include "windows.h" +#include "userenv.h" + +LPTSTR GetSidString(HANDLE UserToken); +VOID DeleteSidString(LPTSTR SidString); +PSID GetUserSid (HANDLE UserToken); +VOID DeleteUserSid(PSID Sid); + + + + |