#include "precomp.h" #pragma hdrstop #include BOOL LoadInfs( IN HWND hdlg ); BOOL BuildCopyList( IN HWND hdlg ); BOOL LoadAndRunMigrationDlls ( HWND hDlg ); BOOL ProcessCompatibilityData( HWND hDlg ); DWORD ProcessCompatibilitySection( LPVOID InfHandle, LPTSTR SectionName ); DWORD InspectAndLoadThread( IN PVOID ThreadParam ) { HWND hdlg; BOOL b; // // Thread parameter is the handle of the page in the wizard. // hdlg = ThreadParam; b = FALSE; // // If we're running the upgrade checker, fixup the title // right away. // if (CheckUpgradeOnly) { FixUpWizardTitle(GetParent(hdlg)); PropSheet_SetTitle(GetParent(hdlg),0,UIntToPtr( IDS_APPTITLE_CHECKUPGRADE )); } // // Step 1: delete existing local sources. // CleanUpOldLocalSources(hdlg); #ifdef _X86_ //NEC98 // // If NEC98, Backup NT4 files // boot.ini, NTLDR, NTDETECT // if (IsNEC98() && Floppyless) { SaveRestoreBootFiles_NEC98(NEC98SAVEBOOTFILES); } #endif //NEC98 // // Step 2: inspect for HPFS, etc. // if(!InspectFilesystems(hdlg)) { Cancelled = TRUE; } else { // // Step 3: load inf(s). // if(LoadInfs(hdlg)) { // // Put in an "|| CheckUpgradeOnly" on these // function calls because if we're really only // checking the ability to upgrade, we want // to continue even if one of these guys fails. // // // Step 4: Check memory resources. // if( EnoughMemory( hdlg, FALSE ) || CheckUpgradeOnly ) { // // check for services to disable // ProcessCompatibilityData(hdlg); #if defined(UNICODE) && defined(_X86_) // // Run Migration DLLs. // LoadAndRunMigrationDlls (hdlg); #endif // // migrate any important data in boot.ini (like the countdown) // if (Upgrade) { if (IsArc()) { MigrateBootVarData(); } else { #ifdef _X86_ MigrateBootIniData(); #endif } } // // Step 5: build the master file copy list. // if(CheckUpgradeOnly || BuildCopyList(hdlg)) { // // Step 6: look for a valid local source and check disk space. // if(FindLocalSourceAndCheckSpace(hdlg, FALSE, 0) || CheckUpgradeOnly) { // // Step 7: // // At this point we actually know everything we need to know // in order to pass parameters to text mode setup. // if( CheckUpgradeOnly ) { b = TRUE; } else { b = WriteParametersFile(hdlg); if (IsArc()) { #ifdef UNICODE // Always true for ARC, never true for Win9x upgrade if(b) { TCHAR Text[128]; LoadString(hInst,IDS_SETTING_NVRAM,Text,sizeof(Text)/sizeof(TCHAR)); SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text); b = SetUpNvRam(hdlg); } #endif // UNICODE } // if (IsArc()) } #ifdef UNICODE if( b && Upgrade #ifdef _X86_ && Floppyless #endif ) { // // Do the migration of unsupported NT drivers. // We can ignore the return code, since the fuction will inform the user if // migration could not be done. // MigrateUnsupportedNTDrivers( hdlg, TxtsetupSif ); } #endif // UNICODE } } if(!b) { UnloadInfFile(MainInf); MainInf = NULL; if(TxtsetupSif) { UnloadInfFile(TxtsetupSif); TxtsetupSif = NULL; } } } } } PostMessage(hdlg,WMX_INSPECTRESULT,(CheckUpgradeOnly ? TRUE : b),0); return(0); } #if defined(UNICODE) && defined(_X86_) LIST_ENTRY g_HandledData; TCHAR g_MigDllAnswerFilePath[MAX_PATH]; DWORD GlobalCompFlags; UINT g_MigDllIndex = 0; #define HANDLED_REGISTRY 1 #define HANDLED_FILE 2 #define HANDLED_SERVICE 3 typedef struct { LIST_ENTRY ListEntry; LONG Type; PCTSTR RegKey; PCTSTR RegValue; PCTSTR File; PCTSTR Service; } HANDLED_DATA, *PHANDLED_DATA; BOOL ResolveHandledIncompatibilities ( VOID ) { // // At this point, all incompatibilities that will exist in the list are in place. // we can now compare this with our list of handled data and remove // anything a migration dll is taking care of. // PLIST_ENTRY nextHandled; PLIST_ENTRY nextCompData; PHANDLED_DATA handledData; PCOMPATIBILITY_DATA compData; BOOL remove; nextHandled = g_HandledData.Flink; if (!nextHandled) { return TRUE; } while ((ULONG_PTR)nextHandled != (ULONG_PTR)&g_HandledData) { handledData = CONTAINING_RECORD (nextHandled, HANDLED_DATA, ListEntry); nextHandled = handledData->ListEntry.Flink; nextCompData = CompatibilityData.Flink; if (!nextCompData) { return TRUE; } while ((ULONG_PTR)nextCompData != (ULONG_PTR)&CompatibilityData) { compData = CONTAINING_RECORD (nextCompData, COMPATIBILITY_DATA, ListEntry); nextCompData = compData->ListEntry.Flink; remove = FALSE; if (handledData->Type == HANDLED_REGISTRY && compData->RegKey && *compData->RegKey) { if (!lstrcmpi (compData->RegKey, handledData->RegKey)) { if (!handledData->RegValue || !lstrcmpi (compData->RegValue, handledData->RegValue)) { remove = TRUE; } } } if (handledData->Type == HANDLED_SERVICE && compData->ServiceName && *compData->ServiceName) { if (!lstrcmpi (compData->ServiceName, handledData->Service)) { remove = TRUE; } } if (handledData->Type == HANDLED_FILE && compData->FileName && *compData->FileName) { if (!lstrcmpi (compData->FileName, handledData->File)) { remove = TRUE; } } // // Migration dll has handled something. Remove it from the compatibility list. // if (remove) { RemoveEntryList (&compData->ListEntry); } } } return TRUE; } BOOL CallMigDllEntryPoints ( PMIGDLLENUM Enum ) { MIGRATIONDLL dll; LONG rc; if (!MigDllOpen (&dll, Enum->Properties->DllPath, GATHERMODE, FALSE, SOURCEOS_WINNT)) { return FALSE; } __try { rc = ERROR_SUCCESS; if (!MigDllInitializeSrc ( &dll, Enum->Properties->WorkingDirectory, NativeSourcePaths[0], Enum->Properties->SourceMedia, NULL, 0 )) { rc = GetLastError (); } if (rc != ERROR_SUCCESS) { return FALSE; } if (!MigDllGatherSystemSettings ( &dll, g_MigDllAnswerFilePath, NULL, 0 )) { rc = GetLastError (); } if (rc != ERROR_SUCCESS) { return FALSE; } } __finally { MigDllClose (&dll); } return TRUE; } BOOL ParseMigrateInf ( PCWSTR MigInfPath ) { PVOID migInf = NULL; LONG lineCount; LONG i; PCTSTR type; PHANDLED_DATA data; PCTSTR regKey; PCTSTR regValue; PCTSTR file; PCTSTR service; if (LoadInfFile (MigInfPath, FALSE, &migInf) != ERROR_SUCCESS) { return FALSE; } __try { // // Add any compatibility items to the list. // if( !CompatibilityData.Flink ) { InitializeListHead( &CompatibilityData ); } GlobalCompFlags = COMPFLAG_STOPINSTALL; CompatibilityCount += ProcessCompatibilitySection (migInf, TEXT("ServicesToStopInstallation") ); if (CompatibilityCount) { IncompatibilityStopsInstallation = TRUE; } GlobalCompFlags = 0; CompatibilityCount += ProcessCompatibilitySection (migInf, TEXT("ServicesToDisable") ); // // Add Handled compatibility items to the list. // lineCount = InfGetSectionLineCount (migInf, TEXT("Handled")); if (lineCount && lineCount != -1) { for (i=0; i < lineCount; i++) { type = InfGetFieldByIndex (migInf, TEXT("Handled"), i, 0); if (!type) { continue; } if (!lstrcmpi (type, TEXT("Registry"))) { regKey = InfGetFieldByIndex (migInf, TEXT("Handled"), i, 1); regValue = InfGetFieldByIndex (migInf, TEXT("Handled"), i, 2); if (regKey && *regKey) { data = (PHANDLED_DATA) MALLOC (sizeof(HANDLED_DATA)); if (data == NULL) { return FALSE; } ZeroMemory (data, sizeof (HANDLED_DATA)); data->Type = HANDLED_REGISTRY; data->RegKey = regKey; data->RegValue = regValue; InsertTailList (&g_HandledData, &data->ListEntry); } } else if (!lstrcmpi (type, TEXT("File"))) { file = InfGetFieldByIndex (migInf, TEXT("Handled"), i, 1); if (file && *file) { data = (PHANDLED_DATA) MALLOC (sizeof(HANDLED_DATA)); if (data == NULL) { return FALSE; } ZeroMemory (data, sizeof (HANDLED_DATA)); data->Type = HANDLED_FILE; data->File = file; InsertTailList (&g_HandledData, &data->ListEntry); } } else if (!lstrcmpi (type, TEXT("Service"))) { service = InfGetFieldByIndex (migInf, TEXT("Handled"), i, 1); if (service && *service) { data = (PHANDLED_DATA) MALLOC (sizeof(HANDLED_DATA)); if (data == NULL) { return FALSE; } ZeroMemory (data, sizeof (HANDLED_DATA)); data->Type = HANDLED_SERVICE; data->Service = service; InsertTailList (&g_HandledData, &data->ListEntry); } } } } } __finally { UnloadInfFile (migInf); } return TRUE; } VOID SearchDirForMigDlls ( PCTSTR SearchDir, PCTSTR BaseDir, DLLLIST List ) { HANDLE findHandle; WIN32_FIND_DATA findData; MIGRATIONDLL dll; WCHAR path[MAX_PATH]; PWSTR p; WCHAR searchPath[MAX_PATH]; PMIGRATIONINFO migInfo; PMIGDLLPROPERTIES dllProps = NULL; WCHAR workingDir[MAX_PATH]; lstrcpy (searchPath, SearchDir); ConcatenatePaths (searchPath, TEXT("*"), MAX_PATH); findHandle = FindFirstFile (searchPath, &findData); if (findHandle != INVALID_HANDLE_VALUE) { lstrcpy (path, SearchDir); p = _tcschr (path, 0); if (p) { do { if (!lstrcmpi (findData.cFileName, TEXT("migrate.dll"))) { *p = 0; ConcatenatePaths (path, findData.cFileName, MAX_PATH); if (!MigDllOpen (&dll, path, GATHERMODE, FALSE, SOURCEOS_WINNT)) { continue; } if (!MigDllQueryMigrationInfo (&dll, TEXT("c:\\"), &migInfo)) { MigDllClose (&dll); continue; } if (migInfo->SourceOs == OS_WINDOWS9X || migInfo->TargetOs != OS_WINDOWSWHISTLER) { continue; } // // Do we already have a version of this migration dll? // dllProps = MigDllFindDllInList (List, migInfo->StaticProductIdentifier); if (dllProps && dllProps->Info.DllVersion >= migInfo->DllVersion) { MigDllClose (&dll); continue; } else if (dllProps) { MigDllRemoveDllFromList (List, migInfo->StaticProductIdentifier); } // // Move dll locally. // wsprintf (workingDir, TEXT("%s\\mig%u"), BaseDir, g_MigDllIndex); g_MigDllIndex++; MigDllMoveDllLocally (&dll, workingDir); // // Add the dll to the list. // MigDllAddDllToList (List, &dll); MigDllClose (&dll); } else if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && *findData.cFileName != TEXT('.')) { *p = 0; ConcatenatePaths (path, findData.cFileName, MAX_PATH); SearchDirForMigDlls (path, BaseDir, List); } } while (FindNextFile (findHandle, &findData)); } FindClose (findHandle); } } #endif // UNICODE #if defined(UNICODE) && defined(_X86_) BOOL LoadAndRunMigrationDlls ( HWND hDlg ) { HKEY regKey = NULL; DWORD index; DWORD nameSize; DWORD valueSize; DWORD type; TCHAR valueName[MAX_PATH]; TCHAR value[MAX_PATH]; TCHAR baseDir[MAX_PATH]; TCHAR workingDir[MAX_PATH]; PTSTR p; LONG rc; DLLLIST list = NULL; MIGRATIONDLL dll; PMIGDLLPROPERTIES dllProps = NULL; MIGDLLENUM e; PMIGRATIONINFO migInfo; TCHAR migInfPath[MAX_PATH]; HANDLE migInf; TCHAR searchDir[MAX_PATH]; TCHAR tempDir[MAX_PATH]; *g_MigDllAnswerFilePath = 0; // // NT Upgrades only. // if (!ISNT() || !Upgrade) { return TRUE; } /*NTBUG9:394164 // // Win2k > Upgrades only. // if (BuildNumber <= NT40) { return TRUE; } */ __try { if (!MigDllInit ()) { return TRUE; } list = MigDllCreateList (); if (!list) { return TRUE; } InitializeListHead (&g_HandledData); MyGetWindowsDirectory (baseDir, MAX_PATH); ConcatenatePaths (baseDir, TEXT("Setup"), MAX_PATH); lstrcpy (g_MigDllAnswerFilePath, baseDir); lstrcpy (tempDir, baseDir); ConcatenatePaths (g_MigDllAnswerFilePath, TEXT("migdll.txt"), MAX_PATH); if(ActualParamFile[0]){ CopyFile(ActualParamFile, g_MigDllAnswerFilePath, FALSE); } // // Scan registry for migration dlls and load them. // if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE, S_REGKEY_MIGRATION_DLLS_WINNT, 0, KEY_READ | KEY_WRITE, ®Key ) == ERROR_SUCCESS) { // // Enumerate Values. // index = 0; do { nameSize = MAX_PATH; valueSize = MAX_PATH * sizeof (TCHAR); rc = RegEnumValue ( regKey, index, valueName, &nameSize, NULL, &type, (PBYTE) value, &valueSize ); index++; if (rc == ERROR_MORE_DATA) { continue; } if (rc == ERROR_NO_MORE_ITEMS) { break; } if (rc != ERROR_SUCCESS) { return TRUE; } if (!MigDllOpen (&dll, value, GATHERMODE, FALSE, SOURCEOS_WINNT)) { continue; } if (!MigDllQueryMigrationInfo (&dll, tempDir, &migInfo)) { MigDllClose (&dll); continue; } if (migInfo->SourceOs == OS_WINDOWS9X || migInfo->TargetOs != OS_WINDOWSWHISTLER) { continue; } // // Do we already have a version of this migration dll? // dllProps = MigDllFindDllInList (list, migInfo->StaticProductIdentifier); if (dllProps && dllProps->Info.DllVersion >= migInfo->DllVersion) { MigDllClose (&dll); continue; } else { MigDllRemoveDllFromList (list, migInfo->StaticProductIdentifier); } // // Move dll locally. // wsprintf (workingDir, TEXT("%s\\mig%u"), baseDir, g_MigDllIndex); g_MigDllIndex++; MigDllMoveDllLocally (&dll, workingDir); // // Add the dll to the list. // MigDllAddDllToList (list, &dll); MigDllClose (&dll); } while (1); } // // Now, look for dlls shipped with the source. // GetModuleFileName (NULL, searchDir, MAX_PATH); p = _tcsrchr (searchDir, TEXT('\\')); if (p) { p++; lstrcpy (p, TEXT("WINNTMIG")); } SearchDirForMigDlls (searchDir, baseDir, list); // // All dlls are now in the list. Lets run them. // ConcatenatePaths (baseDir, TEXT("dlls.inf"), MAX_PATH); if (MigDllEnumFirst (&e, list)) { WritePrivateProfileString ( TEXT("Version"), TEXT("Signature"), TEXT("\"$Windows NT$\""), baseDir ); do { wsprintf (migInfPath, TEXT("%s\\migrate.inf"), e.Properties->WorkingDirectory); migInf = CreateFile ( migInfPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (migInf == INVALID_HANDLE_VALUE) { continue; } CloseHandle (migInf); WritePrivateProfileString ( TEXT("Version"), TEXT("Signature"), TEXT("\"$Windows NT$\""), migInfPath ); if (!CallMigDllEntryPoints (&e)) { MigDllRemoveDllInEnumFromList (list, &e); } else { ParseMigrateInf (migInfPath); WritePrivateProfileString ( TEXT("DllsToLoad"), e.Properties->Info.StaticProductIdentifier, e.Properties->DllPath, baseDir ); } } while (MigDllEnumNext (&e)); WritePrivateProfileString (NULL, NULL, NULL, baseDir); // // Get rid of compatibility messages handled by migration dlls. // ResolveHandledIncompatibilities (); } } __finally { if (regKey) { RegCloseKey (regKey); } if (list) { MigDllFreeList (list); } } return TRUE; } #endif VOID CleanUpOldLocalSources( IN HWND hdlg ) /*++ Routine Description: Locate and delete old local source trees. All local fixed drives are scanned for \$win_nt$.~ls, and if present, delnoded. On x86, we also check the system partition for \$win_nt$.~bt and give it the same treatment. Arguments: Return Value: --*/ { TCHAR Drive; TCHAR Text[250]; TCHAR Filename[128]; LoadString(hInst,IDS_INSPECTING,Text,sizeof(Text)/sizeof(TCHAR)); SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text); for(Drive=TEXT('A'); Drive<=TEXT('Z'); Drive++) { if(MyGetDriveType(Drive) != DRIVE_FIXED) { continue; } Filename[0] = Drive; Filename[1] = TEXT(':'); Filename[2] = 0; ConcatenatePaths(Filename,LOCAL_SOURCE_DIR,sizeof(Filename)/sizeof(TCHAR)); if(FileExists(Filename, NULL)) { LoadString(hInst,IDS_REMOVING_OLD_TEMPFILES,Text,sizeof(Text)/sizeof(TCHAR)); SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text); MyDelnode(Filename); LoadString(hInst,IDS_INSPECTING,Text,sizeof(Text)/sizeof(TCHAR)); SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text); } } if (!IsArc()) { #ifdef _X86_ MYASSERT (SystemPartitionDriveLetter); Filename[0] = SystemPartitionDriveLetter; Filename[1] = TEXT(':'); Filename[2] = TEXT('\\'); lstrcpy(Filename+3,LOCAL_BOOT_DIR); LoadString(hInst,IDS_REMOVING_OLD_TEMPFILES,Text,sizeof(Text)/sizeof(TCHAR)); SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text); MyDelnode(Filename); // // Clean up backup directory, if it exists. // if(IsNEC98() && Floppyless) { Filename[0] = SystemPartitionDriveLetter; Filename[1] = TEXT(':'); Filename[2] = TEXT('\\'); lstrcpy(Filename+3,LOCAL_BACKUP_DIR); MyDelnode(Filename); } #endif // _X86_ } // if (!IsArc()) } BOOL InspectSources( HWND ParentWnd ) /*++ Routine Description: Check all sources given to ensure that they contain a valid windows NT distribution. We do this simply by looking for DOSNET.INF on each source. Arguments: ParentWnd - Specifies the handle of the parent window for any error messages. Return Value: None. --*/ { UINT i,j; TCHAR Filename[MAX_PATH]; TCHAR Text[512]; UINT OriginalCount; HCURSOR OldCursor; BOOL b = TRUE; OldCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)); OriginalCount = SourceCount; // // if we have a good alternate path then there // is no need to verify the source paths // if (AlternateSourcePath[0]) { lstrcpy(Filename,AlternateSourcePath); ConcatenatePaths(Filename,InfName,MAX_PATH); if(FileExists (Filename, NULL)) { SetCursor (OldCursor); return TRUE; } } // // verify each path // for (i=0; i> 22) << 2; AvailableMB = ((MemoryStatus.dwTotalPhys + ((4*1024*1024)-1)) >> 22) << 2; // // Allow for UMA machine which may reservce 8MB for video // if( AvailableMB < (RequiredMB-8) ) { if (!QuickTest) { UpgRequiredMb = (DWORD)RequiredMB; UpgAvailableMb = (DWORD)AvailableMB; // // Fail. // DebugLog( Winnt32LogInformation, NULL, MSG_NOT_ENOUGH_MEMORY, AvailableMB, RequiredMB ); SendMessage(hdlg,WMX_ERRORMESSAGEUP,TRUE,0); MessageBoxFromMessage( hdlg, MSG_NOT_ENOUGH_MEMORY, FALSE, AppTitleStringId, MB_OK | MB_ICONWARNING, AvailableMB, RequiredMB ); SendMessage(hdlg,WMX_ERRORMESSAGEUP,FALSE,0); } return( FALSE ); } else { if (!QuickTest) { TCHAR Buffer[MAX_PATH]; _stprintf( Buffer, TEXT("Detected %dMB of RAM.\n"), AvailableMB ); DebugLog( Winnt32LogInformation, Buffer, 0 ); } } } return( TRUE ); } BOOL LoadInfWorker( IN HWND hdlg, IN LPCTSTR FilenamePart, OUT PVOID *InfHandle, IN BOOL Winnt32File ) { DWORD d; UINT u; UINT Id; TCHAR infPath[MAX_PATH]; TCHAR FormatString[128]; TCHAR Text[MAX_PATH+128]; BOOL b; LoadString(hInst,IDS_LOADINGINF,Text,sizeof(Text)/sizeof(TCHAR)); SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text); // // use standard searching algorithm to get to the right INF // if (Winnt32File) { b = FindPathToWinnt32File (FilenamePart, infPath, MAX_PATH); } else { b = FindPathToInstallationFile (FilenamePart, infPath, MAX_PATH); } if (b) { d = LoadInfFile(infPath,TRUE,InfHandle); if (d == NO_ERROR) { return TRUE; } } else { d = ERROR_FILE_NOT_FOUND; } switch(d) { case NO_ERROR: Id = 0; break; case ERROR_NOT_ENOUGH_MEMORY: Id = MSG_OUT_OF_MEMORY; break; case ERROR_READ_FAULT: // // I/O error. // Id = MSG_CANT_LOAD_INF_IO; break; case ERROR_INVALID_DATA: Id = MSG_CANT_LOAD_INF_SYNTAXERR; break; default: Id = MSG_CANT_LOAD_INF_GENERIC; break; } if(Id) { SendMessage(hdlg,WMX_ERRORMESSAGEUP,TRUE,0); MessageBoxFromMessage( hdlg, Id, FALSE, AppTitleStringId, MB_OK | MB_ICONERROR | MB_TASKMODAL, infPath ); SendMessage(hdlg,WMX_ERRORMESSAGEUP,FALSE,0); return(FALSE); } return(TRUE); } BOOL WriteFileToLog( const PTCHAR pszFileMetaName, const PTCHAR pszActualFileName ) { HANDLE hActualFile = INVALID_HANDLE_VALUE; BOOL fResult = FALSE; DWORD cbBootIniSize, cbReadBootIniSize; PUCHAR pszBuffer = NULL; PTCHAR pszActualBuffer = NULL; // // Open the boot.ini file, get its size, convert it to the proper // string type internally, and then log it out. // hActualFile = CreateFile( pszActualFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if ( hActualFile == INVALID_HANDLE_VALUE ) goto Exit; cbBootIniSize = GetFileSize( hActualFile, NULL ); // // Buffer we'll be reading the boot.ini into // if ((pszBuffer = MALLOC(cbBootIniSize)) == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto Exit; } if ( !ReadFile( hActualFile, pszBuffer, cbBootIniSize, &cbReadBootIniSize, NULL ) ) goto Exit; // // Ensure that we read as much as we really wanted. // if ( cbBootIniSize != cbReadBootIniSize ) { DebugLog( Winnt32LogError, TEXT("Error: %1 unable to be read entirely.\n"), 0, pszFileMetaName); goto Exit; } #ifdef UNICODE pszActualBuffer = MALLOC( (cbBootIniSize + 3) * sizeof(TCHAR) ); MultiByteToWideChar( CP_ACP, 0, pszBuffer, cbBootIniSize, pszActualBuffer, cbBootIniSize ); #else pszActualBuffer = pszBuffer; #endif pszActualBuffer[cbBootIniSize] = 0; // // And write it out // DebugLog( Winnt32LogInformation, TEXT("%1 ----\n%2\n---- (from %3)\n"), 0, pszFileMetaName, pszActualBuffer, pszActualFileName); fResult = TRUE; SetLastError(ERROR_SUCCESS); Exit: if ( hActualFile != INVALID_HANDLE_VALUE ) { CloseHandle( hActualFile ); hActualFile = INVALID_HANDLE_VALUE; } #ifdef UNICODE if ( pszActualBuffer != NULL ) #else if ( ( pszActualBuffer != pszBuffer ) && ( pszActualBuffer != NULL ) ) #endif { FREE(pszActualBuffer); pszActualBuffer = NULL; } if ( pszBuffer != NULL ) { FREE(pszBuffer); pszBuffer = NULL; } return fResult; } BOOL InspectFilesystems( IN HWND hdlg ) { TCHAR DriveRoot[4]; BOOL b; TCHAR VolumeName[MAX_PATH]; DWORD SerialNumber; DWORD MaxComponent; BOOL Bogus[26]; TCHAR Filesystem[100]; TCHAR Drive; DWORD Flags; int i; DriveRoot[1] = TEXT(':'); DriveRoot[2] = TEXT('\\'); DriveRoot[3] = 0; ZeroMemory(Bogus,sizeof(Bogus)); for(Drive=TEXT('A'); Drive<=TEXT('Z'); Drive++) { if(MyGetDriveType(Drive) != DRIVE_FIXED) { continue; } DriveRoot[0] = Drive; b = GetVolumeInformation( DriveRoot, VolumeName,MAX_PATH, &SerialNumber, &MaxComponent, &Flags, Filesystem, sizeof(Filesystem)/sizeof(TCHAR) ); if(b) { // // On NT, we want to warn about HPFS. // On Win9x, we want to warn about doublespace/drivespace. // if(ISNT()) { if(!lstrcmpi(Filesystem,TEXT("HPFS"))) { Bogus[Drive-TEXT('A')] = TRUE; } } else { if(Flags & FS_VOL_IS_COMPRESSED) { Bogus[Drive-TEXT('A')] = TRUE; } } } } #ifdef _X86_ if(ISNT()) { TCHAR BootIniName[16]; DWORD dwAttributes; // // Disallow HPFS system partition. If someone figured out how // to get an HPFS system partition on an ARC machine, more power // to 'em. // MYASSERT (SystemPartitionDriveLetter); if(SystemPartitionDriveLetter && Bogus[SystemPartitionDriveLetter-TEXT('A')]) { MessageBoxFromMessage( hdlg, MSG_SYSPART_IS_HPFS, FALSE, AppTitleStringId, MB_OK | MB_ICONERROR | MB_TASKMODAL, SystemPartitionDriveLetter ); return(FALSE); } /* If we're upgrading NT, then log the existing boot.ini to the logfiles for this pass. However, if that failed, then there was something wrong - a missing boot.ini during an upgrade is really a bad thing that should be snipped in the bud before we go much further and copy files down, change system state, etc. */ #ifdef PRERELEASE if (Upgrade) { _stprintf(BootIniName, TEXT("%c:\\BOOT.INI"), SystemPartitionDriveLetter); if ( !WriteFileToLog( TEXT("Boot configuration file while inspecting filesystems"), BootIniName ) ) { MessageBoxFromMessage( hdlg, MSG_UPGRADE_INSPECTION_MISSING_BOOT_INI, FALSE, AppTitleStringId, MB_OK | MB_ICONERROR | MB_TASKMODAL, BootIniName ); return FALSE; } } #endif } #endif // // User cannot upgrade a system on an HPFS/DriveSpace drive // MyGetWindowsDirectory(VolumeName,MAX_PATH); if(Upgrade && Bogus[VolumeName[0]-TEXT('A')]) { MessageBoxFromMessage( hdlg, ISNT() ? MSG_SYSTEM_ON_HPFS : MSG_SYSTEM_ON_CVF, FALSE, AppTitleStringId, MB_OK | MB_ICONERROR | MB_TASKMODAL ); return(FALSE); } // // General case, HPFS data partition/compressed drive. // for(b=FALSE,Drive=0; !b && (Drive<26); Drive++) { if(Bogus[Drive]) { b = TRUE; } } if(b) { i = MessageBoxFromMessage( hdlg, ISNT() ? MSG_HPFS_DRIVES_EXIST : MSG_CVFS_EXIST, FALSE, AppTitleStringId, MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL ); if(i == IDNO) { return(FALSE); } } return(TRUE); }