/*++ Copyright (c) 1995 Microsoft Corporation Module Name: migwin95.c Abstract: This file contains the function that do the various migrations from win95. Author: Jaime Sasson 30-Aug-1995 Revision History: --*/ #include "setupp.h" // #include #pragma hdrstop #define StrWin95RegOpenKey "VMMRegOpenKey" #define StrWin95RegCloseKey "VMMRegCloseKey" #define StrWin95RegEnumKey "VMMRegEnumKey" #define StrWin95RegEnumValue "VMMRegEnumValue" #define StrWin95RegQueryValueEx "VMMRegQueryValueEx" #define StrWin95RegMapPredefKeyToFile "VMMRegMapPredefKeyToFile" #define StrWin95RegQueryInfoKey "VMMRegQueryInfoKey" #define StrWin95RegLoadKey "VMMRegLoadKey" #define StrWin95RegUnLoadKey "VMMRegUnLoadKey" #define StrWin95RegDeleteKey "VMMRegDeleteKey" #define StrWin95RegDeleteValue "VMMRegDeleteValue" #define StrWin95CurrentVersion "SOFTWARE\\Microsoft\\Windows\\CurrentVersion" #define StrWin95SystemRoot "SystemRoot" #define StrWin95ProfileListKeyPath "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ProfileList" #define StrWin95ProfileImagePath "ProfileImagePath" #define StrWin95SystemHiveFile "system.dat" #define StrWin95UserHiveFile "user.dat" #define StrNtUserHiveFile "ntuser.dat" #define StrSoftwareKey "SOFTWARE" #define StrProfilesDirectory "profiles" #define StrDefaultUser "Default User" // Note that "Default User" is *not* a localizable string // // Unicode strings // #define StrWinlogonKeyPath L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon" #define StrWin9xFlagName L"Win9xUpg" // // Unicode strings used to log errors // #define szLoadLibrary L"LoadLibrary" #define szGetProcAddress L"GetProcAddress" // // Variables global to the module // HINSTANCE _VmmReg32Handle; FARPROC _Win95RegOpenKey; FARPROC _Win95RegCloseKey; FARPROC _Win95RegEnumKey; FARPROC _Win95RegEnumValue; FARPROC _Win95RegQueryValueEx; FARPROC _Win95RegMapPredefKeyToFile; FARPROC _Win95RegQueryInfoKey; FARPROC _Win95RegLoadKey; FARPROC _Win95RegUnLoadKey; FARPROC _Win95RegDeleteKey; FARPROC _Win95RegDeleteValue; CHAR _Win95SystemDirectory[ MAX_PATH + 1 ]; CHAR _WinNtSystemDirectory[ MAX_PATH + 1 ]; CHAR _Win95ViewersDirectory[ MAX_PATH + 1 ]; CHAR _WinNtViewersDirectory[ MAX_PATH + 1 ]; CHAR _Win95OriginalDriveLetter; LONG CopyWin9xKey( IN HKEY hKeyRootSrc, IN HKEY hKeyRootDst, IN PSTR SrcKeyPath, OPTIONAL IN PSTR DstKeyPath, OPTIONAL IN BOOL CopyAlways, IN BOOL CopyValuesOnly #if DBG , IN PSTR DbgParentKey #endif ); FixWin95DriveLetter( IN OUT PSTR String ); BOOL FixWin95Path( IN PCSTR SourceString, OUT PSTR* ResultString ); #if 0 UINT DeleteQueueCallback( IN PVOID Context, IN UINT Notification, IN UINT Param1, IN UINT Param2 ) { // // If we're being notified that a file delete failed, // and the file isn't there, ignore the error. // if(Notification == SPFILENOTIFY_DELETEERROR) { PFILEPATHS FilePaths = (PFILEPATHS)Param1; if((FilePaths->Win32Error == ERROR_FILE_NOT_FOUND) || (FilePaths->Win32Error == ERROR_PATH_NOT_FOUND)) { return(FILEOP_SKIP); } } // // Want default processing. // return(SetupDefaultQueueCallback(Context,Notification,Param1,Param2)); } BOOL DeleteWin9xFiles( VOID ) { BOOL b; HINF hInf; HSPFILEQ FileQ; PVOID Context; WCHAR Dir[MAX_PATH]; b = FALSE; //hInf = SetupOpenInfFile(L"filelist.inf",NULL,INF_STYLE_WIN4,NULL); hInf = SyssetupInf; if(hInf != INVALID_HANDLE_VALUE) { FileQ = SetupOpenFileQueue(); if(FileQ != INVALID_HANDLE_VALUE) { b = SetupQueueDeleteSectionW( FileQ, hInf, 0, L"Files.DeleteWin9x.System" ); b &= SetupQueueDeleteSectionW( FileQ, hInf, 0, L"Files.DeleteWin9x.System" ); if(b) { b = FALSE; if(Context = SetupInitDefaultQueueCallback(MainWindowHandle)) { b = SetupCommitFileQueue(MainWindowHandle,FileQ,DeleteQueueCallback,Context); SetupTermDefaultQueueCallback(Context); } } SetupCloseFileQueue(FileQ); } //SetupCloseInfFile(hInf); } return(b); } #endif BOOLEAN ResetWin9xUpgValue( ) /*++ Routine Description: Delete the value entry Win9xUpg on HKEY_LOCAL_MACHINE\SOFTWRAE\Microsoft\Windows NT\CurrentVersion\\Winlogon This routine should always be called when setup is upgrading an NT system. Arguments: None. Return Value: BOOLEAN - Returns TRUE if the opearation succeeds. --*/ { ULONG Error; HKEY Key; Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, StrWinlogonKeyPath, 0, MAXIMUM_ALLOWED, &Key ); if( Error != ERROR_SUCCESS ) { return( FALSE ); } Error = RegDeleteValue( Key, StrWin9xFlagName ); if( Error == ERROR_PATH_NOT_FOUND ) { Error = ERROR_SUCCESS; } RegCloseKey( Key ); return( Error == ERROR_SUCCESS ); } BOOLEAN SetWin9xUpgValue( ) /*++ Routine Description: Create the value entry Win9xUpg on HKEY_LOCAL_MACHINE\SOFTWRAE\Microsoft\Windows NT\CurrentVersion\\Winlogon This routine should always be called when setup is installing an NT system on top of Win9x. Arguments: None. Return Value: BOOLEAN - Returns TRUE if the opearation succeeds. --*/ { ULONG Error; HKEY Key; DWORD Value; Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, StrWinlogonKeyPath, 0, MAXIMUM_ALLOWED, &Key ); if( Error != ERROR_SUCCESS ) { return( FALSE ); } Value = 1; Error = RegSetValueEx( Key, StrWin9xFlagName, 0, REG_DWORD, (PBYTE)&Value, sizeof( DWORD ) ); RegCloseKey( Key ); return( Error == ERROR_SUCCESS ); } BOOLEAN DeleteWin9xSubKeys( IN HKEY ParentKeyHandle, IN PCSTR KeyName, OUT PULONG ErrorCode ) /*++ Routine Description: Delete all subkeys of a Win95 key whose name and parent's handle was passed as parameter. The algorithm used in this function guarantees that the maximum number of descendent keys will be deleted. Arguments: ParentKeyHandle - Handle to the parent of the key that is currently being examined. KeyName - Name of the key that is currently being examined. This name can be an empty string (but not a NULL pointer), and in this case ParentKeyHandle refers to the key that is being examined. ErrorCode - Pointer to a variable that will contain an Win32 error code if the function fails. Return Value: BOOLEAN - Returns TRUE if the opearation succeeds. --*/ { HKEY CurrentKey; DWORD iSubKey; CHAR SubKeyName[ MAX_PATH + 1 ]; ULONG SubKeyNameLength; FILETIME ftLastWriteTime; LONG Status; LONG StatusEnum; LONG SavedStatus; // // Do not accept NULL pointer for ErrorCode // if( ErrorCode == NULL ) { return( FALSE ); } // // Do not accept NULL pointer for KeyName. // if( KeyName == NULL ) { *ErrorCode = ERROR_INVALID_PARAMETER; return( FALSE ); } // // Open a handle to the key whose subkeys are to be deleted. // Since we need to delete its subkeys, the handle must have // KEY_ENUMERATE_SUB_KEYS access. // Status = _Win95RegOpenKey( ParentKeyHandle, KeyName, &CurrentKey ); if( Status != ERROR_SUCCESS ) { // // If unable to enumerate the subkeys, return error. // *ErrorCode = Status; return( FALSE ); } // // Traverse the key // iSubKey = 0; SavedStatus = ERROR_SUCCESS; do { // // Get the name of a subkey // SubKeyNameLength = sizeof( SubKeyName ) / sizeof( CHAR ); StatusEnum = _Win95RegEnumKey( CurrentKey, iSubKey, SubKeyName, SubKeyNameLength ); if( StatusEnum == ERROR_SUCCESS ) { // // Delete all children of the subkey. // Just assume that the children will be deleted, and don't check // for failure. // DeleteWin9xSubKeys( CurrentKey, SubKeyName, &Status ); // // Now delete the subkey, and check for failure. // Status = _Win95RegDeleteKey( CurrentKey, SubKeyName ); // // If unable to delete the subkey, then save the error code. // Note that the subkey index is incremented only if the subkey // was not deleted. // if( Status != ERROR_SUCCESS ) { iSubKey++; SavedStatus = Status; } } else { // // If unable to get a subkey name due to ERROR_NO_MORE_ITEMS, // then the key doesn't have subkeys, or all subkeys were already // enumerated. Otherwise, an error has occurred, so just save // the error code. // if( StatusEnum != ERROR_NO_MORE_ITEMS ) { SavedStatus = StatusEnum; } } if( ( StatusEnum != ERROR_SUCCESS ) && ( StatusEnum != ERROR_NO_MORE_ITEMS ) ) { DbgPrint( "SYSSETUP: Win95RegEnumKey() failed, Key Name = %s, Status = %d, iSubKey = %d \n", KeyName, StatusEnum, iSubKey ); } } while( StatusEnum == ERROR_SUCCESS ); // // Close the handle to the key whose subkeys were deleted, and return // the result of the operation. // _Win95RegCloseKey( CurrentKey ); if( SavedStatus != ERROR_SUCCESS ) { *ErrorCode = SavedStatus; return( FALSE ); } return( TRUE ); } BOOLEAN DeleteWin9xValues( IN HKEY ParentKeyHandle, IN PCSTR KeyPath, OUT PULONG ErrorCode ) /*++ Routine Description: Delete all values of a Win95 key. Arguments: ParentKeyHandle - Handle to the parent of the key that contains the values to be deleted. KeyPath - Path to the key that contains the values be deleted. ErrorCode - Pointer to a variable that will contain an Win32 error code if the function fails. Return Value: BOOLEAN - Returns TRUE if the opearation succeeds. --*/ { ULONG Error; HKEY Key; CHAR ValueName[ MAX_PATH + 1 ]; ULONG ValueNameLength; ULONG i, j; *ErrorCode = ERROR_SUCCESS; Error = _Win95RegOpenKey( ParentKeyHandle, KeyPath, &Key ); if( Error != ERROR_SUCCESS ) { DbgPrint( "SYSSETUP: Unable to open key %s. Error = %d \n", KeyPath, Error ); *ErrorCode = Error; return( FALSE ); } // // Enumerate all values in the key and delete each of them // for( i = 0, j = 0;; i++ ) { ValueNameLength = sizeof( ValueName ) / sizeof( CHAR ); Error = _Win95RegEnumValue( Key, j, ValueName, &ValueNameLength, 0, NULL, NULL, NULL ); if( Error != ERROR_SUCCESS ) { if( Error == ERROR_NO_MORE_ITEMS ) { Error = ERROR_SUCCESS; break; } else { DbgPrint("SYSSETUP: unable to enumerate values in key %s. Error = %d\n",KeyPath, Error); j++; continue; } } Error = _Win95RegDeleteValue( Key, ValueName ); if( Error != ERROR_SUCCESS ) { DbgPrint( "SYSSETUP: Unable to delete value = %s, in key = %s. Error = %d \n", ValueName, KeyPath, Error ); if( *ErrorCode == ERROR_SUCCESS ) { *ErrorCode = Error; } j++; continue; } } return( *ErrorCode == ERROR_SUCCESS ); } BOOLEAN DeleteWin9xKey( IN HKEY ParentKeyHandle, IN PCSTR KeyName, OUT PULONG ErrorCode ) /*++ Routine Description: Delete a Win95 key and all its subkeys. Arguments: ParentKeyHandle - Handle to the parent of the key to be deleted. KeyName - Name of the key to be deleted. This name cannot be an empty string. ErrorCode - Pointer to a variable that will contain an Win32 error code if the function fails. Return Value: BOOLEAN - Returns TRUE if the opearation succeeds. --*/ { ULONG Error; if( DeleteWin9xSubKeys( ParentKeyHandle, KeyName, ErrorCode ) ) { Error = _Win95RegDeleteKey( ParentKeyHandle, KeyName ); if( Error != ERROR_SUCCESS ) { *ErrorCode = Error; DbgPrint( "SYSSETUP: Unable to delete Win95 key. Error = %d, KeyName = %s \n", Error, KeyName ); } return( Error == ERROR_SUCCESS ); } return( FALSE ); } ULONG DeleteWin9xValuesInSection( IN HINF InfHandle, IN HKEY SrcPredefinedKey, IN PCSTR SrcKeyPath, IN PCWSTR UnicodeSectionName ) /*++ Routine Description: Delete all the values listed on a section of the inf file, from the win95 registry. Arguments: InfHandle - Handle to the inf file that contains the section that lists the values to be deleted. SrcPredefinedKey - Handle to the the predefined key of the Win95 registry SrcKeyPath - Key on the Win95 registry that contains the values to be deleted. UnicodeSectionName - Unicode string that contains the name of the section in the INF file that lists the names of values to be copied. Return Value: Returns a Win32 error code that indicates the result of the operation. --*/ { INFCONTEXT InfContext; UINT LineCount,LineNo; PCWSTR UnicodeValueName; CHAR ValueName[ MAX_PATH + 1]; ULONG Error = ERROR_SUCCESS; ULONG TempError; HKEY hKeySrc; // // Open a handle to the source key // Error = _Win95RegOpenKey( SrcPredefinedKey, SrcKeyPath, &hKeySrc ); if(Error != ERROR_SUCCESS ) { DbgPrint("SYSSETUP: unable to open key %s in the source hive. Error = %d \n",SrcKeyPath,Error); return( Error ); } // // Get the number of lines in the section that contains the values to // be copied. If the section is empty or doesn't exist, then don't // delete any value. // LineCount = (UINT)SetupGetLineCount(InfHandle,UnicodeSectionName); if((LONG)LineCount <= 0) { _Win95RegCloseKey(hKeySrc); return(Error); } for(LineNo=0; LineNo