mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1753 lines
49 KiB
1753 lines
49 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Spntupg.c
|
|
|
|
Abstract:
|
|
|
|
initializing and maintaining list of nts to upgrade
|
|
|
|
Author:
|
|
|
|
Sunil Pai (sunilp) 10-Nov-1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "spprecmp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
//
|
|
// In unattended operation, we will fetch a value from
|
|
// the unattended script that tells us how to proceed.
|
|
//
|
|
typedef enum {
|
|
UUAttended,
|
|
UUDoUpgrade,
|
|
UUDoSingleUpgrade,
|
|
UUDontUpgrade
|
|
} UUType;
|
|
|
|
UUType UnattendedUpgradeType;
|
|
|
|
#define SP_UPGRADE_DONTMATCH ((ULONG)(-1))
|
|
#define SP_UPGRADE_NOMATCH ((ULONG)(-2))
|
|
|
|
//
|
|
// Major/minor version numbers of the system we're upgrading *from*
|
|
// if upgrading.
|
|
//
|
|
ULONG OldMajorVersion,OldMinorVersion;
|
|
|
|
//**************************************************************
|
|
// S E L E C T I N G N T T O U P G R A D E S T U F F
|
|
//**************************************************************
|
|
|
|
#define MENU_LEFT_X 3
|
|
#define MENU_WIDTH (VideoVars.ScreenWidth-(2*MENU_LEFT_X))
|
|
#define MENU_INDENT 4
|
|
|
|
//
|
|
// Define a Unicode string type to be used for storing drive letter
|
|
// specifications in upgrade messages (useful because we may not
|
|
// have a drive letter, but rather a localizable designator stating
|
|
// that the partition is a mirror (eg. "(Mirror):"))
|
|
//
|
|
typedef WCHAR DRIVELTR_STRING[32];
|
|
|
|
VOID
|
|
pSpStepUpValidate(
|
|
IN BOOLEAN Server
|
|
);
|
|
|
|
VOID
|
|
SpGetUpgDriveLetter(
|
|
IN WCHAR DriveLetter,
|
|
IN PWCHAR Buffer,
|
|
IN ULONG BufferSize,
|
|
IN BOOL AddColon
|
|
);
|
|
|
|
VOID
|
|
SppUpgradeWarnHpfs(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SpCantFindBuildToUpgrade(
|
|
VOID
|
|
);
|
|
|
|
ENUMUPGRADETYPE
|
|
SpFindNtToUpgrade(
|
|
IN PVOID SifHandle,
|
|
OUT PDISK_REGION *TargetRegion,
|
|
OUT PWSTR *TargetPath,
|
|
OUT PDISK_REGION *SystemPartitionRegion,
|
|
OUT PWSTR *SystemPartitionDirectory
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This goes through the list of NTs on the system and finds out which are
|
|
upgradeable. Presents the information to the user and selects if he
|
|
wishes to upgrade an installed NT / install a fresh NT into the same
|
|
directory / select a different location for Windows NT.
|
|
|
|
If the chosen target is too full user is offered to exit setup to create
|
|
space/ choose new target.
|
|
|
|
|
|
Arguments:
|
|
|
|
SifHandle: Handle the txtsetup.sif
|
|
|
|
TargetRegion: Variable to receive the partition of the Windows NT to install
|
|
NULL if not chosen. Caller should not free.
|
|
|
|
TargetPath: Variable to receive the target path of Windows NT. NULL if
|
|
not decided. Caller can free.
|
|
|
|
SystemPartitionRegion:
|
|
Variable to receive the system partition of the Windows NT
|
|
NULL if not chosen. Caller should not free.
|
|
|
|
|
|
Return Value:
|
|
|
|
UpgradeFull: If user chooses to upgrade an NT
|
|
|
|
UpgradeInstallFresh: If user chooses to install fresh into an existing NT
|
|
tree.
|
|
|
|
DontUpgrade: If user chooses to cancel upgrade and choose a fresh
|
|
tree for installation
|
|
|
|
|
|
--*/
|
|
{
|
|
ENUMUPGRADETYPE UpgradeType;
|
|
NT_PRODUCT_TYPE ProductType;
|
|
UPG_PROGRESS_TYPE UpgradeProgressValue;
|
|
NTSTATUS NtStatus;
|
|
ULONG j, UpgradeBootSets = 0, PidIndex = 0, ChosenBootSet;
|
|
ULONG BootSets = 0;
|
|
ULONG FreeKBRequired;
|
|
ULONG FreeKBRequiredSysPart;
|
|
|
|
PWSTR *BootVars[MAXBOOTVARS];
|
|
BOOLEAN *UpgradeableList = NULL;
|
|
BOOLEAN *FailedUpgradeList = NULL;
|
|
PDISK_REGION *SysPartRegionList = NULL;
|
|
PDISK_REGION *OsPartRegionList = NULL;
|
|
PULONG OldMajorVersions = NULL;
|
|
PULONG OldMinorVersions = NULL;
|
|
NT_PRODUCT_TYPE *ProductTypeList = NULL;
|
|
ULONG TotalSizeOfFilesOnOsWinnt;
|
|
PWSTR UniqueIdFromSif;
|
|
PWSTR UniqueIdFromReg;
|
|
ULONG MatchedSetIndex;
|
|
|
|
//
|
|
// Initialize
|
|
//
|
|
|
|
UpgradeType = DontUpgrade;
|
|
UniqueIdFromSif = NULL;
|
|
MatchedSetIndex = SP_UPGRADE_DONTMATCH;
|
|
|
|
UnattendedUpgradeType = UUAttended;
|
|
if(UnattendedOperation) {
|
|
|
|
PWSTR p;
|
|
|
|
p = SpGetSectionKeyIndex(UnattendedSifHandle,SIF_UNATTENDED,L"NtUpgrade",0);
|
|
if(p) {
|
|
if(!_wcsicmp(p,L"yes")) {
|
|
UnattendedUpgradeType = UUDoUpgrade;
|
|
|
|
UniqueIdFromSif = SpGetSectionKeyIndex(
|
|
UnattendedSifHandle,
|
|
SIF_DATA,
|
|
SIF_UNIQUEID,
|
|
0
|
|
);
|
|
|
|
if(UniqueIdFromSif) {
|
|
MatchedSetIndex = SP_UPGRADE_NOMATCH;
|
|
}
|
|
|
|
} else {
|
|
if(!_wcsicmp(p,L"no")) {
|
|
UnattendedUpgradeType = UUDontUpgrade;
|
|
} else {
|
|
if(!_wcsicmp(p,L"single")) {
|
|
UnattendedUpgradeType = UUDoSingleUpgrade;
|
|
UniqueIdFromSif = SpGetSectionKeyIndex(
|
|
UnattendedSifHandle,
|
|
SIF_DATA,
|
|
SIF_UNIQUEID,
|
|
0
|
|
);
|
|
|
|
if(UniqueIdFromSif) {
|
|
MatchedSetIndex = SP_UPGRADE_NOMATCH;
|
|
}
|
|
}
|
|
// else get attended behavior
|
|
}
|
|
}
|
|
} else {
|
|
//
|
|
// Not specified; default is No.
|
|
//
|
|
UnattendedUpgradeType = UUDontUpgrade;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Init BootVars and find out all the possible upgradeable boot sets.
|
|
//
|
|
|
|
BootSets = SpFindNtBootSets ( BootVars,
|
|
&UpgradeableList,
|
|
&SysPartRegionList,
|
|
&OsPartRegionList
|
|
);
|
|
|
|
FailedUpgradeList = SpMemAlloc( BootSets*sizeof( BOOLEAN * ) );
|
|
ProductTypeList = SpMemAlloc( BootSets*sizeof( NT_PRODUCT_TYPE ) );
|
|
OldMajorVersions = SpMemAlloc(BootSets*sizeof(ULONG));
|
|
OldMinorVersions = SpMemAlloc(BootSets*sizeof(ULONG));
|
|
Pid20Array = SpMemAlloc((BootSets+1)*sizeof( PWSTR ));
|
|
Pid20Array[BootSets] = NULL;
|
|
|
|
for ( j = 0, PidIndex = 0; j < BootSets ; j++ ) {
|
|
PWSTR Pid;
|
|
|
|
Pid20Array[j] = NULL;
|
|
Pid20Array[j+1] = NULL;
|
|
OldMajorVersions[j] = 0;
|
|
OldMinorVersions[j] = 0;
|
|
ProductTypeList[j] = 0;
|
|
if (!UpgradeableList[j]) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Reinitialize
|
|
//
|
|
|
|
FailedUpgradeList[j] = FALSE;
|
|
UpgradeableList[j] = FALSE;
|
|
|
|
//
|
|
// try loading the registry and getting the following information
|
|
// out of it:
|
|
//
|
|
// 1) Product type: WINNT | LANMANNT | SERVERNT
|
|
// 2) Major and Minor Version Number
|
|
// 3) The upgrade progress type
|
|
// 4) The unique identifier winnt32.exe put in there (if any)
|
|
//
|
|
// Based on the information, we will update the UpgradeableList and
|
|
// initialize FailedUpgradeList.
|
|
//
|
|
|
|
Pid = NULL;
|
|
NtStatus = SpDetermineProduct(
|
|
OsPartRegionList[j],
|
|
BootVars[OSLOADFILENAME][j],
|
|
&ProductType,
|
|
&OldMajorVersions[j],
|
|
&OldMinorVersions[j],
|
|
&UpgradeProgressValue,
|
|
&UniqueIdFromReg,
|
|
&Pid
|
|
);
|
|
|
|
if(NT_SUCCESS(NtStatus)) {
|
|
//
|
|
// BUGBUG - This should be removed in the future
|
|
// Do not allow Cairo setup to find NT 3.x systems
|
|
//
|
|
if( !CairoSetup ) {
|
|
if( !StepUpMode ) {
|
|
ProductTypeList[j] = ProductType;
|
|
if( ((OldMajorVersions[j] < WinntMajorVer) || ((OldMajorVersions[j] == WinntMajorVer) && (OldMinorVersions[j] <= WinntMinorVer)))) {
|
|
UpgradeableList[j] = AdvancedServer ? TRUE : ( ProductType == NtProductWinNt );
|
|
if( UpgradeableList[j] ) {
|
|
UpgradeBootSets++;
|
|
ChosenBootSet = j;
|
|
//
|
|
// Save the Pid only if it is Pid20
|
|
//
|
|
if( wcslen( Pid ) == 20 ) {
|
|
Pid20Array[PidIndex] = Pid;
|
|
PidIndex++;
|
|
}
|
|
} else {
|
|
//
|
|
// If the system is not upgradable, then we don't need the PID
|
|
//
|
|
SpMemFree( Pid );
|
|
}
|
|
FailedUpgradeList[j] = (UpgradeProgressValue == UpgradeInProgress);
|
|
}
|
|
} else {
|
|
//
|
|
// Step-up mode. Require the presence of NT 3.x.
|
|
//
|
|
ProductTypeList[j] = ProductType;
|
|
if(OldMajorVersions[j] == 3) {
|
|
//
|
|
// If the system found is not of the same type of the system being installed,
|
|
// then mark the system found as non-upgradeable.
|
|
//
|
|
UpgradeableList[j] = AdvancedServer ? ( ProductType != NtProductWinNt ) : ( ProductType == NtProductWinNt );
|
|
if( UpgradeableList[j] ) {
|
|
UpgradeBootSets++;
|
|
ChosenBootSet = j;
|
|
//
|
|
// Save the Pid only if it is Pid20
|
|
//
|
|
if( wcslen( Pid ) == 20 ) {
|
|
Pid20Array[PidIndex] = Pid;
|
|
PidIndex++;
|
|
}
|
|
} else {
|
|
//
|
|
// If the system is not upgradable, then we don't need the PID
|
|
//
|
|
SpMemFree( Pid );
|
|
}
|
|
FailedUpgradeList[j] = (UpgradeProgressValue == UpgradeInProgress);
|
|
}
|
|
}
|
|
} else {
|
|
//
|
|
// BUGBUG - REMOVE THIS PIECE OF CODE AFTER CAIRO and NT 3.51 ARE MERGED
|
|
// This is Cairo setup
|
|
// OldMajorVersion must be 5
|
|
// OldMinorVersion must be 0
|
|
// Note that Pid of Cairo systems are not saved. This will be automatically fixed
|
|
// when the code below is merged with the code above
|
|
//
|
|
|
|
ProductTypeList[j] = ProductType;
|
|
if( (OldMajorVersions[j] == 5) &&
|
|
(OldMinorVersions[j] == 0) ) {
|
|
UpgradeableList[j] = AdvancedServer ? ( ProductType != NtProductWinNt ) : ( ProductType == NtProductWinNt );
|
|
if( UpgradeableList[j] ) {
|
|
UpgradeBootSets++;
|
|
ChosenBootSet = j;
|
|
}
|
|
FailedUpgradeList[j] = (UpgradeProgressValue == UpgradeInProgress);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine if this installation matches the one we're supposed
|
|
// to upgrade in the winnt32 unattended case.
|
|
//
|
|
if(UniqueIdFromReg) {
|
|
|
|
if((MatchedSetIndex == SP_UPGRADE_NOMATCH)
|
|
&& !wcscmp(UniqueIdFromSif,UniqueIdFromReg)) {
|
|
MatchedSetIndex = j;
|
|
}
|
|
|
|
SpMemFree(UniqueIdFromReg);
|
|
UniqueIdFromReg = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if(StepUpMode && !UpgradeBootSets) {
|
|
|
|
pSpStepUpValidate(AdvancedServer);
|
|
}
|
|
|
|
//
|
|
// Load up the value of the minimum space needed on the winnt drive
|
|
// before we can upgrade it to the new version.
|
|
//
|
|
|
|
SpFetchUpgradeDiskSpaceReq(
|
|
SifHandle,
|
|
&FreeKBRequired,
|
|
&FreeKBRequiredSysPart
|
|
);
|
|
|
|
//
|
|
// Find out how many valid boot sets there are which we can upgrade
|
|
//
|
|
|
|
|
|
if( UpgradeBootSets == 1 ) {
|
|
//
|
|
// Make sure the build matches in the unattended case.
|
|
//
|
|
if(( (UnattendedUpgradeType == UUDoUpgrade)
|
|
|| (UnattendedUpgradeType == UUDoSingleUpgrade))
|
|
&& (MatchedSetIndex == SP_UPGRADE_NOMATCH))
|
|
{
|
|
SpCantFindBuildToUpgrade();
|
|
}
|
|
|
|
OldMajorVersion = OldMajorVersions[ChosenBootSet];
|
|
OldMinorVersion = OldMinorVersions[ChosenBootSet];
|
|
|
|
#ifndef _X86_
|
|
//
|
|
// On non-x86 platformrs, specially alpha machines that in general
|
|
// have small system partitions (~3 MB), we should compute the size
|
|
// of the files on \os\winnt (currently, osloader.exe and hall.dll),
|
|
// and consider this size as available disk space. We can do this
|
|
// since these files will be overwritten by the new ones.
|
|
// This fixes the problem that we see on Alpha, when the system
|
|
// partition is too full.
|
|
//
|
|
SpFindSizeOfFilesInOsWinnt( SifHandle,
|
|
SysPartRegionList[ChosenBootSet],
|
|
&TotalSizeOfFilesOnOsWinnt );
|
|
|
|
//
|
|
// Transform the size into KB
|
|
//
|
|
TotalSizeOfFilesOnOsWinnt /= 1024;
|
|
#else
|
|
TotalSizeOfFilesOnOsWinnt = 0;
|
|
#endif
|
|
|
|
//
|
|
// There are three different dialogs depending on whether
|
|
// 1) This is a failed upgrade
|
|
// 2) There is not enough space on the drive
|
|
// 3) Everything is okay
|
|
//
|
|
|
|
if( FailedUpgradeList[ChosenBootSet] ) {
|
|
|
|
UpgradeType = SppNTSingleFailedUpgrade(
|
|
OsPartRegionList[ChosenBootSet],
|
|
BootVars[OSLOADFILENAME][ChosenBootSet],
|
|
BootVars[LOADIDENTIFIER][ChosenBootSet]
|
|
);
|
|
|
|
}
|
|
else if( ( OsPartRegionList[ChosenBootSet]->FreeSpaceKB < FreeKBRequired ) ||
|
|
( ( SysPartRegionList[ChosenBootSet]->FreeSpaceKB +
|
|
TotalSizeOfFilesOnOsWinnt ) < FreeKBRequiredSysPart ) ) {
|
|
|
|
//
|
|
// If below routine returns user automatically wants to choose
|
|
// a new path
|
|
//
|
|
|
|
if(UnattendedUpgradeType != UUDontUpgrade) {
|
|
SppNTSingleUpgradeDiskFull(
|
|
OsPartRegionList[ChosenBootSet],
|
|
BootVars[OSLOADFILENAME][ChosenBootSet],
|
|
BootVars[LOADIDENTIFIER][ChosenBootSet],
|
|
SysPartRegionList[ChosenBootSet],
|
|
FreeKBRequired,
|
|
FreeKBRequiredSysPart
|
|
);
|
|
} else {
|
|
UpgradeType = DontUpgrade;
|
|
}
|
|
|
|
}
|
|
else {
|
|
|
|
//
|
|
// If it is a fresh attempt at upgrade ask the user if he
|
|
// wants to upgrade or not
|
|
|
|
UpgradeType = SppSelectNTSingleUpgrade(
|
|
OsPartRegionList[ChosenBootSet],
|
|
BootVars[OSLOADFILENAME][ChosenBootSet],
|
|
BootVars[LOADIDENTIFIER][ChosenBootSet],
|
|
ProductTypeList[ChosenBootSet]
|
|
);
|
|
}
|
|
|
|
}
|
|
else if (UpgradeBootSets > 1) {
|
|
|
|
while(1) {
|
|
|
|
//
|
|
// Find out if the user wants to upgrade one of the Windows
|
|
// NT found
|
|
//
|
|
ChosenBootSet = MatchedSetIndex;
|
|
|
|
UpgradeType = SppSelectNTMultiUpgrade(
|
|
BootVars,
|
|
BootSets,
|
|
UpgradeableList,
|
|
SysPartRegionList,
|
|
OsPartRegionList,
|
|
&ChosenBootSet,
|
|
ProductTypeList
|
|
);
|
|
|
|
//
|
|
// If user has chosen to cancel upgrade, break out
|
|
//
|
|
|
|
if(UpgradeType == DontUpgrade) {
|
|
break;
|
|
}
|
|
|
|
#ifndef _X86_
|
|
//
|
|
// On non-x86 platformrs, specially alpha machines that in general
|
|
// have small system partitions (~3 MB), we should compute the size
|
|
// of the files on \os\winnt (currently, osloader.exe and hall.dll),
|
|
// and consider this size as available disk space. We can do this
|
|
// since these files will be overwritten by the new ones.
|
|
// This fixes the problem that we see on Alpha, when the system
|
|
// partition is too full.
|
|
//
|
|
SpFindSizeOfFilesInOsWinnt( SifHandle,
|
|
SysPartRegionList[ChosenBootSet],
|
|
&TotalSizeOfFilesOnOsWinnt );
|
|
|
|
//
|
|
// Transform the size into KB
|
|
//
|
|
TotalSizeOfFilesOnOsWinnt /= 1024;
|
|
|
|
#else
|
|
TotalSizeOfFilesOnOsWinnt = 0;
|
|
#endif
|
|
|
|
OldMajorVersion = OldMajorVersions[ChosenBootSet];
|
|
OldMinorVersion = OldMinorVersions[ChosenBootSet];
|
|
|
|
//
|
|
// If the user has chosen to upgrade/install fresh a windows nt
|
|
// into an existing directory then check the following conditions
|
|
//
|
|
// 1. If we are trying to upgrade and we have a failed upgrade in
|
|
// the same place. In this case we have to warn the user about
|
|
// the failed upgrade.
|
|
//
|
|
// 2. The disk space is insufficient for the operation selected.
|
|
//
|
|
//
|
|
// BUGBUG (lonnym, 04/18/94), It is possible that we detect the failed
|
|
// upgrade, but disk space is also low. We currently don't handle this
|
|
// possibility, and Setup falls down later on if it occurs.
|
|
//
|
|
|
|
if( (UpgradeType == UpgradeFull) && FailedUpgradeList[ChosenBootSet] ) {
|
|
UpgradeType = SppNTMultiFailedUpgrade(
|
|
OsPartRegionList[ChosenBootSet],
|
|
BootVars[OSLOADFILENAME][ChosenBootSet],
|
|
BootVars[LOADIDENTIFIER][ChosenBootSet]
|
|
);
|
|
|
|
}
|
|
else if( ( OsPartRegionList[ChosenBootSet]->FreeSpaceKB < FreeKBRequired ) ||
|
|
( ( SysPartRegionList[ChosenBootSet]->FreeSpaceKB +
|
|
TotalSizeOfFilesOnOsWinnt ) < FreeKBRequiredSysPart ) ) {
|
|
|
|
UpgradeType = DontUpgrade;
|
|
SppNTMultiUpgradeDiskFull(
|
|
OsPartRegionList[ChosenBootSet],
|
|
BootVars[OSLOADFILENAME][ChosenBootSet],
|
|
BootVars[LOADIDENTIFIER][ChosenBootSet],
|
|
SysPartRegionList[ChosenBootSet],
|
|
FreeKBRequired,
|
|
FreeKBRequiredSysPart
|
|
);
|
|
}
|
|
|
|
//
|
|
// If everything is still ok, break out
|
|
//
|
|
|
|
if(UpgradeType != DontUpgrade) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Depending on upgrade selection made do the setup needed before
|
|
// we do the upgrade
|
|
//
|
|
|
|
if( UpgradeType != DontUpgrade ) {
|
|
NTSTATUS Status;
|
|
PWSTR p1,p2,p3;
|
|
ULONG u;
|
|
|
|
if( UpgradeType == UpgradeFull ) {
|
|
|
|
//
|
|
// HPFS warning. SppUpgradeWarnHpfs might not return.
|
|
//
|
|
SppUpgradeWarnHpfs();
|
|
|
|
//
|
|
// If Upgrade type is UpgradeInstallFresh then backup the hives
|
|
// else just set the upgrade status to upgrading in the current
|
|
// system hive
|
|
//
|
|
while(TRUE) {
|
|
Status = SpSetUpgradeStatus(
|
|
OsPartRegionList[ChosenBootSet],
|
|
BootVars[OSLOADFILENAME][ChosenBootSet],
|
|
UpgradeInProgress
|
|
);
|
|
//
|
|
// If we fail to set the upgrade status, some of our logic
|
|
// to know that we were trying to install before will be
|
|
// broken, however this is not critical and we can ignore
|
|
// the error.
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
break;
|
|
}
|
|
|
|
if(!SpNonCriticalError(SifHandle, SP_SCRN_UPGRADE_STATUS_FAILED, NULL, NULL)) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return the region we are installing onto
|
|
//
|
|
*TargetRegion = OsPartRegionList[ChosenBootSet];
|
|
*TargetPath = SpDupStringW(BootVars[OSLOADFILENAME][ChosenBootSet]);
|
|
*SystemPartitionRegion = SysPartRegionList[ChosenBootSet];
|
|
StandardServerUpgrade = ( AdvancedServer &&
|
|
( ProductTypeList[ChosenBootSet] == NtProductWinNt ) ||
|
|
( ProductTypeList[ChosenBootSet] == NtProductServer )
|
|
);
|
|
|
|
//
|
|
// Process the osloader variable to extract the system partition path.
|
|
// The var vould be of the form ...partition(1)\os\nt\... or
|
|
// ...partition(1)os\nt\...
|
|
// So we search forward for the first \ and then backwards for
|
|
// the closest ) to find the start of the directory. We then
|
|
// search backwards in the resulting string for the last \ to find
|
|
// the end of the directory.
|
|
//
|
|
u = 0;
|
|
p3 = BootVars[OSLOADER][ChosenBootSet];
|
|
if(p1 = wcschr(p3,L'\\')) {
|
|
|
|
//
|
|
// Make p1 point to the first character of the directory.
|
|
//
|
|
while((p1 > p3) && (*(p1-1) != L')')) {
|
|
p1--;
|
|
}
|
|
|
|
//
|
|
// Make p2 point one character past the end of
|
|
// the directory. P2 will always be non-null because
|
|
// p1 was non-null (see above).
|
|
//
|
|
p2 = wcsrchr(p1, L'\\');
|
|
|
|
u = p2 - p1;
|
|
}
|
|
|
|
if(u == 0) {
|
|
*SystemPartitionDirectory = SpDupStringW(L"");
|
|
} else {
|
|
p3 = SpMemAlloc((u+1)*sizeof(WCHAR));
|
|
ASSERT(p3);
|
|
wcsncpy(p3, p1, u);
|
|
p3[u] = 0;
|
|
if(*p3 == L'\\') {
|
|
p1 = p3;
|
|
} else {
|
|
p1 = SpMemAlloc((u+2)*sizeof(WCHAR));
|
|
*p1 = L'\\';
|
|
wcscpy(p1+1,p3);
|
|
}
|
|
*SystemPartitionDirectory = p1;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Do cleanup
|
|
//
|
|
if(OldMajorVersions) {
|
|
SpMemFree(OldMajorVersions);
|
|
}
|
|
if(OldMinorVersions) {
|
|
SpMemFree(OldMinorVersions);
|
|
}
|
|
if ( UpgradeableList ) {
|
|
SpMemFree( UpgradeableList );
|
|
}
|
|
if ( FailedUpgradeList ) {
|
|
SpMemFree( FailedUpgradeList );
|
|
}
|
|
if ( SysPartRegionList ) {
|
|
SpMemFree( SysPartRegionList );
|
|
}
|
|
if ( OsPartRegionList ) {
|
|
SpMemFree( OsPartRegionList );
|
|
}
|
|
if ( ProductTypeList ) {
|
|
SpMemFree( ProductTypeList );
|
|
}
|
|
|
|
CLEAR_CLIENT_SCREEN();
|
|
return ( UpgradeType );
|
|
}
|
|
|
|
|
|
VOID
|
|
pSpStepUpValidate(
|
|
IN BOOLEAN Server
|
|
)
|
|
{
|
|
ULONG CdCount;
|
|
ULONG i;
|
|
BOOLEAN b;
|
|
ULONG Prompt;
|
|
ULONG ValidKeys[3] = { ASCI_CR, KEY_F3, 0 };
|
|
LARGE_INTEGER DelayTime;
|
|
PWSTR FileName;
|
|
|
|
//
|
|
// Directories that must be present at the root to indicate
|
|
// a 3.x CD.
|
|
//
|
|
PWSTR ListAll[] = { L"i386",L"mips",L"support",L"drvlib" };
|
|
|
|
#if 0
|
|
//
|
|
// We don't bother checking these, but if we needed to,
|
|
// here's some more lists.
|
|
//
|
|
PWSTR List31[] = { L"disk2",L"setup.txt" }; // NT3.1 -- all
|
|
PWSTR List35xSrv[] = { L"cdrom.s",L"disk4.s",L"disk11.s" }; // NT3.5x -- server
|
|
PWSTR List35xWks[] = { L"cdrom.w",L"disk5.w",L"disk10.w" }; // NT3.5x -- workstation
|
|
#endif
|
|
|
|
Prompt = SP_SCRN_STEP_UP_NO_QUALIFY;
|
|
|
|
//
|
|
// See if there is a CD-ROM drive. If not we can't continue.
|
|
//
|
|
if(CdCount = IoGetConfigurationInformation()->CdRomCount) {
|
|
|
|
do {
|
|
//
|
|
// Tell the user what's going on. This screen also contains
|
|
// a prompt to insert a qualifying CD-ROM.
|
|
//
|
|
while(1) {
|
|
|
|
SpStartScreen(Prompt,3,HEADER_HEIGHT+1,FALSE,FALSE,DEFAULT_ATTRIBUTE);
|
|
|
|
SpContinueScreen(
|
|
Server ? SP_SCRN_STEP_UP_PROMPT_SRV : SP_SCRN_STEP_UP_PROMPT_WKS,
|
|
3,
|
|
1,
|
|
FALSE,
|
|
DEFAULT_ATTRIBUTE
|
|
);
|
|
|
|
SpContinueScreen(SP_SCRN_STEP_UP_INSTRUCTIONS,3,1,FALSE,DEFAULT_ATTRIBUTE);
|
|
|
|
SpDisplayStatusOptions(
|
|
DEFAULT_STATUS_ATTRIBUTE,
|
|
SP_STAT_ENTER_EQUALS_CONTINUE,
|
|
SP_STAT_F3_EQUALS_EXIT,
|
|
0
|
|
);
|
|
|
|
if(SpWaitValidKey(ValidKeys,NULL,NULL) == KEY_F3) {
|
|
SpConfirmExit();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
CLEAR_CLIENT_SCREEN();
|
|
SpDisplayStatusText(SP_STAT_PLEASE_WAIT,DEFAULT_STATUS_ATTRIBUTE);
|
|
|
|
//
|
|
// Wait 5 sec for the CD to become ready
|
|
//
|
|
DelayTime.HighPart = -1;
|
|
DelayTime.LowPart = (ULONG)(-50000000);
|
|
KeDelayExecutionThread(KernelMode,FALSE,&DelayTime);
|
|
|
|
//
|
|
// Check for relevent files/dirs on each CD-ROM drive.
|
|
//
|
|
for(i=0; i<CdCount; i++) {
|
|
|
|
swprintf((PWSTR)TemporaryBuffer,L"\\Device\\Cdrom%u",i);
|
|
|
|
b = SpNFilesExist(
|
|
(PWSTR)TemporaryBuffer,
|
|
ListAll,
|
|
sizeof(ListAll)/sizeof(ListAll[0]),
|
|
TRUE
|
|
);
|
|
|
|
if(b) {
|
|
//
|
|
// Now make sure it's NOT a 4.0 CD.
|
|
//
|
|
FileName = Server ? L"cdrom_s.40" : L"cdrom_w.40";
|
|
|
|
if(!SpNFilesExist((PWSTR)TemporaryBuffer,&FileName,1,FALSE)) {
|
|
//
|
|
// OK, validated. Continue.
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we get here then the CD the user inserted is bogus
|
|
// or the user didn't insert a CD. Reprompt. The while loop
|
|
// condition makes this essentially an infinite loop.
|
|
//
|
|
} while(Prompt = SP_SCRN_STEP_UP_BAD_CD);
|
|
}
|
|
|
|
SpStartScreen(
|
|
SP_SCRN_STEP_UP_FATAL,
|
|
3,
|
|
HEADER_HEIGHT+1,
|
|
FALSE,
|
|
FALSE,
|
|
DEFAULT_ATTRIBUTE
|
|
);
|
|
|
|
SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
|
|
SpkbdDrain();
|
|
while(SpkbdGetKeypress() != KEY_F3);
|
|
SpDone(FALSE,FALSE);
|
|
}
|
|
|
|
|
|
ENUMUPGRADETYPE
|
|
SppSelectNTSingleUpgrade(
|
|
IN PDISK_REGION Region,
|
|
IN PWSTR OsLoadFileName,
|
|
IN PWSTR LoadIdentifier,
|
|
IN NT_PRODUCT_TYPE ProductType
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Inform a user that Setup has found a previous Windows NT installation.
|
|
The user has the option to upgrade this or specify that he wants to
|
|
install Windows NT fresh.
|
|
|
|
Arguments:
|
|
|
|
Region - Region descriptor for the NT found
|
|
|
|
OsLoadFileName - Directory for the NT found
|
|
|
|
LoadIdentifier - Multi boot load identifier used for this NT.
|
|
|
|
ProductType - Type of the Windows NT installation found.
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ValidKeys[] = { KEY_F3,ASCI_CR, 0 };
|
|
ULONG Mnemonics[] = {
|
|
// MnemonicOverwrite,
|
|
MnemonicNewVersion,
|
|
0
|
|
};
|
|
|
|
ULONG c;
|
|
DRIVELTR_STRING UpgDriveLetter;
|
|
|
|
ASSERT(Region->PartitionedSpace);
|
|
ASSERT(wcslen(OsLoadFileName) >= 2);
|
|
|
|
switch(UnattendedUpgradeType) {
|
|
case UUDoUpgrade:
|
|
case UUDoSingleUpgrade:
|
|
return(UpgradeFull);
|
|
case UUDontUpgrade:
|
|
return(DontUpgrade);
|
|
}
|
|
|
|
SpGetUpgDriveLetter(Region->DriveLetter,
|
|
UpgDriveLetter,
|
|
sizeof(UpgDriveLetter),
|
|
FALSE
|
|
);
|
|
|
|
while(1) {
|
|
|
|
SpStartScreen(
|
|
SP_SCRN_WINNT_UPGRADE,
|
|
3,
|
|
HEADER_HEIGHT+1,
|
|
FALSE,
|
|
FALSE,
|
|
DEFAULT_ATTRIBUTE,
|
|
UpgDriveLetter,
|
|
OsLoadFileName,
|
|
LoadIdentifier
|
|
);
|
|
|
|
SpDisplayStatusOptions(
|
|
DEFAULT_STATUS_ATTRIBUTE,
|
|
SP_STAT_F3_EQUALS_EXIT,
|
|
SP_STAT_ENTER_EQUALS_UPGRADE,
|
|
// SP_STAT_O_EQUALS_OVERWRITE,
|
|
SP_STAT_N_EQUALS_NEW_VERSION,
|
|
0
|
|
);
|
|
|
|
switch(c=SpWaitValidKey(ValidKeys,NULL,Mnemonics)) {
|
|
|
|
case KEY_F3:
|
|
SpConfirmExit();
|
|
break;
|
|
case ASCI_CR:
|
|
if( !AdvancedServer ||
|
|
( ProductType != NtProductWinNt ) ||
|
|
SppWarnUpgradeWorkstationToServer( SP_SCRN_SINGLE_UPGRADE_WINNT_TO_AS )
|
|
) {
|
|
return(UpgradeFull);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// must have entered O for overwrite or N for new version
|
|
//
|
|
if(c == (MnemonicOverwrite | KEY_MNEMONIC)){
|
|
return( UpgradeInstallFresh );
|
|
}
|
|
else {
|
|
return( DontUpgrade );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ENUMUPGRADETYPE
|
|
SppNTSingleFailedUpgrade(
|
|
PDISK_REGION Region,
|
|
PWSTR OsLoadFileName,
|
|
PWSTR LoadIdentifier
|
|
)
|
|
{
|
|
ULONG ValidKeys[] = { KEY_F3,ASCI_CR, 0 };
|
|
ULONG Mnemonics[] = {
|
|
// MnemonicOverwrite,
|
|
MnemonicNewVersion,
|
|
0
|
|
};
|
|
ULONG c;
|
|
DRIVELTR_STRING UpgDriveLetter;
|
|
|
|
ASSERT(Region->PartitionedSpace);
|
|
ASSERT(wcslen(OsLoadFileName) >= 2);
|
|
|
|
if((UnattendedUpgradeType == UUDoUpgrade) ||
|
|
(UnattendedUpgradeType == UUDoSingleUpgrade)) {
|
|
return( UpgradeFull );
|
|
}
|
|
if(UnattendedUpgradeType != UUDontUpgrade) {
|
|
return( DontUpgrade );
|
|
}
|
|
SpGetUpgDriveLetter(Region->DriveLetter,
|
|
UpgDriveLetter,
|
|
sizeof(UpgDriveLetter),
|
|
FALSE
|
|
);
|
|
|
|
while(1) {
|
|
|
|
SpStartScreen(
|
|
SP_SCRN_WINNT_FAILED_UPGRADE,
|
|
3,
|
|
HEADER_HEIGHT+1,
|
|
FALSE,
|
|
FALSE,
|
|
DEFAULT_ATTRIBUTE,
|
|
UpgDriveLetter,
|
|
OsLoadFileName,
|
|
LoadIdentifier
|
|
);
|
|
|
|
SpDisplayStatusOptions(
|
|
DEFAULT_STATUS_ATTRIBUTE,
|
|
SP_STAT_F3_EQUALS_EXIT,
|
|
SP_STAT_ENTER_EQUALS_UPGRADE,
|
|
// SP_STAT_O_EQUALS_OVERWRITE,
|
|
SP_STAT_N_EQUALS_NEW_VERSION,
|
|
0
|
|
);
|
|
|
|
switch(c=SpWaitValidKey(ValidKeys,NULL,Mnemonics)) {
|
|
|
|
case KEY_F3:
|
|
SpConfirmExit();
|
|
break;
|
|
case ASCI_CR:
|
|
return(UpgradeFull);
|
|
default:
|
|
//
|
|
// must have entered O for overwrite or N for new version
|
|
//
|
|
if(c == (MnemonicOverwrite | KEY_MNEMONIC)){
|
|
return( UpgradeInstallFresh );
|
|
}
|
|
else {
|
|
return( DontUpgrade );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
SppNTSingleUpgradeDiskFull(
|
|
PDISK_REGION OsRegion,
|
|
PWSTR OsLoadFileName,
|
|
PWSTR LoadIdentifier,
|
|
PDISK_REGION SysPartRegion,
|
|
ULONG MinOsFree,
|
|
ULONG MinSysFree
|
|
)
|
|
{
|
|
|
|
ULONG ValidKeys[] = { KEY_F3,0 };
|
|
ULONG Mnemonics[] = { MnemonicNewVersion,0 };
|
|
PWCHAR Drive1, Drive2;
|
|
DRIVELTR_STRING OsRgnDrive, OsRgnDriveFull, SysRgnDriveFull;
|
|
WCHAR Drive1Free[MAX_PATH], Drive1FreeNeeded[MAX_PATH];
|
|
WCHAR Drive2Free[MAX_PATH], Drive2FreeNeeded[MAX_PATH];
|
|
BOOLEAN FirstDefined = FALSE, SecondDefined = FALSE;
|
|
|
|
ASSERT(OsRegion->PartitionedSpace);
|
|
ASSERT(SysPartRegion->PartitionedSpace);
|
|
ASSERT(wcslen(OsLoadFileName) >= 2);
|
|
|
|
SpGetUpgDriveLetter(OsRegion->DriveLetter,
|
|
OsRgnDrive,
|
|
sizeof(OsRgnDrive),
|
|
FALSE
|
|
);
|
|
|
|
if((OsRegion == SysPartRegion) ||
|
|
(OsRegion->FreeSpaceKB < MinOsFree)) {
|
|
//
|
|
// Then we'll be needing the full (colon
|
|
// added) version of the drive letter
|
|
//
|
|
SpGetUpgDriveLetter(OsRegion->DriveLetter,
|
|
OsRgnDriveFull,
|
|
sizeof(OsRgnDrive),
|
|
TRUE
|
|
);
|
|
}
|
|
|
|
if( OsRegion == SysPartRegion ) {
|
|
Drive1 = OsRgnDriveFull;
|
|
swprintf(Drive1Free, L"%d", OsRegion->FreeSpaceKB);
|
|
swprintf(Drive1FreeNeeded, L"%d", MinOsFree);
|
|
FirstDefined = TRUE;
|
|
}
|
|
else {
|
|
if(SysPartRegion->FreeSpaceKB < MinSysFree) {
|
|
SpGetUpgDriveLetter(SysPartRegion->DriveLetter,
|
|
SysRgnDriveFull,
|
|
sizeof(SysRgnDriveFull),
|
|
TRUE
|
|
);
|
|
Drive1 = SysRgnDriveFull;
|
|
swprintf(Drive1Free, L"%d", SysPartRegion->FreeSpaceKB);
|
|
swprintf(Drive1FreeNeeded, L"%d", MinSysFree);
|
|
FirstDefined = TRUE;
|
|
}
|
|
if(OsRegion->FreeSpaceKB < MinOsFree) {
|
|
|
|
if(!FirstDefined) {
|
|
Drive1 = OsRgnDriveFull;
|
|
swprintf(Drive1Free, L"%d", OsRegion->FreeSpaceKB);
|
|
swprintf(Drive1FreeNeeded, L"%d", MinOsFree);
|
|
FirstDefined = TRUE;
|
|
|
|
}
|
|
else {
|
|
Drive2 = OsRgnDriveFull;
|
|
swprintf(Drive2Free, L"%d", OsRegion->FreeSpaceKB);
|
|
swprintf(Drive2FreeNeeded, L"%d", MinOsFree);
|
|
SecondDefined = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
while(1) {
|
|
|
|
SpStartScreen(
|
|
SP_SCRN_WINNT_DRIVE_FULL,
|
|
3,
|
|
HEADER_HEIGHT+1,
|
|
FALSE,
|
|
FALSE,
|
|
DEFAULT_ATTRIBUTE,
|
|
OsRgnDrive,
|
|
OsLoadFileName,
|
|
LoadIdentifier,
|
|
FirstDefined ? Drive1 : L"",
|
|
FirstDefined ? Drive1FreeNeeded : L"",
|
|
FirstDefined ? Drive1Free : L"",
|
|
SecondDefined ? Drive2 : L"",
|
|
SecondDefined ? Drive2FreeNeeded : L"",
|
|
SecondDefined ? Drive2Free : L""
|
|
);
|
|
|
|
SpDisplayStatusOptions(
|
|
DEFAULT_STATUS_ATTRIBUTE,
|
|
SP_STAT_F3_EQUALS_EXIT,
|
|
SP_STAT_N_EQUALS_NEW_VERSION,
|
|
0
|
|
);
|
|
|
|
switch(SpWaitValidKey(ValidKeys,NULL,Mnemonics)) {
|
|
|
|
case KEY_F3:
|
|
SpConfirmExit();
|
|
break;
|
|
default:
|
|
//
|
|
// Must have chosen N for new version
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ENUMUPGRADETYPE
|
|
SppSelectNTMultiUpgrade(
|
|
IN PWSTR **BootVars,
|
|
IN ULONG BootSets,
|
|
IN BOOLEAN *UpgradeableList,
|
|
IN PDISK_REGION *SysPartRegionList,
|
|
IN PDISK_REGION *OsPartRegionList,
|
|
IN OUT PULONG BootSetChosen,
|
|
IN NT_PRODUCT_TYPE *ProductTypeList
|
|
)
|
|
{
|
|
PVOID Menu;
|
|
ULONG MenuTopY;
|
|
ULONG ValidKeys[] = { KEY_F3, ASCI_CR, 0 };
|
|
ULONG Mnemonics[] = {
|
|
// MnemonicOverwrite,
|
|
MnemonicNewVersion,
|
|
0
|
|
};
|
|
ULONG Keypress;
|
|
ULONG i,FirstUpgradeSet;
|
|
DRIVELTR_STRING *DriveLetters;
|
|
BOOL bDone;
|
|
ENUMUPGRADETYPE ret;
|
|
|
|
switch(UnattendedUpgradeType) {
|
|
case UUDoUpgrade:
|
|
//
|
|
// Make sure we found the system to be upgraded.
|
|
// If the boot set is SP_UPGRADE_NOMATCH, then a match
|
|
// was required but none was found. If the boot set is
|
|
// SP_UPGRAGE_DONTMATCH, then no ,match is required
|
|
// and we simply locate the first upgradeable boot set, if any.
|
|
// Otherwise, if we found a match, we verify that the build is upgradeable.
|
|
//
|
|
if((*BootSetChosen == SP_UPGRADE_NOMATCH)
|
|
|| ((*BootSetChosen != SP_UPGRADE_DONTMATCH) && !UpgradeableList[*BootSetChosen])) {
|
|
SpCantFindBuildToUpgrade();
|
|
}
|
|
|
|
if(*BootSetChosen == SP_UPGRADE_DONTMATCH) {
|
|
|
|
for( i = 0; i < BootSets; i++ ) {
|
|
if( UpgradeableList[i] ) {
|
|
*BootSetChosen = i; // select first installation that is upgradeable
|
|
return(UpgradeFull);
|
|
}
|
|
}
|
|
return(DontUpgrade);
|
|
}
|
|
|
|
return(UpgradeFull);
|
|
|
|
case UUDontUpgrade:
|
|
return(DontUpgrade);
|
|
}
|
|
|
|
//
|
|
// Build up array of drive letters for all menu options
|
|
//
|
|
DriveLetters = SpMemAlloc(BootSets * sizeof(DRIVELTR_STRING));
|
|
for(i = 0; i < BootSets; i++) {
|
|
if( UpgradeableList[i] ) {
|
|
SpGetUpgDriveLetter(
|
|
OsPartRegionList[i]->DriveLetter,
|
|
DriveLetters[i],
|
|
sizeof(DRIVELTR_STRING),
|
|
FALSE
|
|
);
|
|
}
|
|
}
|
|
|
|
bDone = FALSE;
|
|
while(!bDone) {
|
|
|
|
//
|
|
// Display the text that goes above the menu on the partitioning screen.
|
|
//
|
|
SpDisplayScreen(SP_SCRN_WINNT_UPGRADE_LIST,3,CLIENT_TOP+1);
|
|
|
|
//
|
|
// Calculate menu placement. Leave one blank line
|
|
// and one line for a frame.
|
|
//
|
|
MenuTopY = NextMessageTopLine+2;
|
|
|
|
//
|
|
// Create a menu.
|
|
//
|
|
|
|
Menu = SpMnCreate(
|
|
MENU_LEFT_X,
|
|
MenuTopY,
|
|
MENU_WIDTH,
|
|
VideoVars.ScreenHeight-MenuTopY-2-STATUS_HEIGHT
|
|
);
|
|
|
|
ASSERT(Menu);
|
|
|
|
//
|
|
// Build up a menu of partitions and free spaces.
|
|
//
|
|
|
|
FirstUpgradeSet = BootSets;
|
|
for(i = 0; i < BootSets; i++ ) {
|
|
if( UpgradeableList[i] ) {
|
|
swprintf(
|
|
(PWSTR)TemporaryBuffer,
|
|
L"%ws:%ws %ws",
|
|
DriveLetters[i],
|
|
BootVars[OSLOADFILENAME][i],
|
|
BootVars[LOADIDENTIFIER][i]
|
|
);
|
|
|
|
SpMnAddItem(Menu,(PWSTR)TemporaryBuffer,MENU_LEFT_X+MENU_INDENT,MENU_WIDTH-(2*MENU_INDENT),TRUE,i);
|
|
if(FirstUpgradeSet == BootSets) {
|
|
FirstUpgradeSet = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initialize the status line.
|
|
//
|
|
SpDisplayStatusOptions(
|
|
DEFAULT_STATUS_ATTRIBUTE,
|
|
SP_STAT_F3_EQUALS_EXIT,
|
|
SP_STAT_ENTER_EQUALS_UPGRADE,
|
|
// SP_STAT_O_EQUALS_OVERWRITE,
|
|
SP_STAT_N_EQUALS_NEW_VERSION,
|
|
0
|
|
);
|
|
|
|
//
|
|
// Display the menu
|
|
//
|
|
SpMnDisplay(
|
|
Menu,
|
|
FirstUpgradeSet,
|
|
TRUE,
|
|
ValidKeys,
|
|
Mnemonics,
|
|
NULL,
|
|
&Keypress,
|
|
BootSetChosen
|
|
);
|
|
|
|
//
|
|
// Now act on the user's selection.
|
|
//
|
|
switch(Keypress) {
|
|
|
|
case KEY_F3:
|
|
SpConfirmExit();
|
|
break;
|
|
|
|
case ASCI_CR:
|
|
if( !AdvancedServer ||
|
|
( ProductTypeList[ *BootSetChosen ] != NtProductWinNt ) ||
|
|
SppWarnUpgradeWorkstationToServer( SP_SCRN_MULTI_UPGRADE_WINNT_TO_AS )
|
|
) {
|
|
ret = UpgradeFull;
|
|
bDone = TRUE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if(Keypress == (MnemonicOverwrite | KEY_MNEMONIC)) {
|
|
// SpMnDestroy(Menu);
|
|
ret = UpgradeInstallFresh;
|
|
}
|
|
else {
|
|
// SpMnDestroy(Menu);
|
|
ret = DontUpgrade;
|
|
}
|
|
bDone = TRUE;
|
|
}
|
|
SpMnDestroy(Menu);
|
|
}
|
|
SpMemFree(DriveLetters);
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
ENUMUPGRADETYPE
|
|
SppNTMultiFailedUpgrade(
|
|
PDISK_REGION OsPartRegion,
|
|
PWSTR OsLoadFileName,
|
|
PWSTR LoadIdentifier
|
|
)
|
|
{
|
|
ULONG ValidKeys[] = { KEY_F3,ASCI_CR,ASCI_ESC, 0 };
|
|
ULONG c;
|
|
DRIVELTR_STRING UpgDriveLetter;
|
|
|
|
ASSERT(OsPartRegion->PartitionedSpace);
|
|
ASSERT(wcslen(OsLoadFileName) >= 2);
|
|
|
|
if( UnattendedUpgradeType == UUDoUpgrade ) {
|
|
return(UpgradeFull);
|
|
}
|
|
|
|
SpGetUpgDriveLetter(OsPartRegion->DriveLetter,
|
|
UpgDriveLetter,
|
|
sizeof(UpgDriveLetter),
|
|
FALSE
|
|
);
|
|
|
|
while(1) {
|
|
|
|
SpStartScreen(
|
|
SP_SCRN_WINNT_FAILED_UPGRADE1,
|
|
3,
|
|
HEADER_HEIGHT+1,
|
|
FALSE,
|
|
FALSE,
|
|
DEFAULT_ATTRIBUTE,
|
|
UpgDriveLetter,
|
|
OsLoadFileName,
|
|
LoadIdentifier
|
|
);
|
|
|
|
SpDisplayStatusOptions(
|
|
DEFAULT_STATUS_ATTRIBUTE,
|
|
SP_STAT_F3_EQUALS_EXIT,
|
|
SP_STAT_ENTER_EQUALS_UPGRADE,
|
|
SP_STAT_ESC_EQUALS_CANCEL,
|
|
0
|
|
);
|
|
|
|
switch(c=SpWaitValidKey(ValidKeys,NULL,NULL)) {
|
|
|
|
case KEY_F3:
|
|
SpConfirmExit();
|
|
break;
|
|
case ASCI_CR:
|
|
return(UpgradeFull);
|
|
|
|
case ASCI_ESC:
|
|
return(DontUpgrade);
|
|
|
|
default:
|
|
//
|
|
// dont know how we can get here
|
|
//
|
|
return(DontUpgrade);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
SppNTMultiUpgradeDiskFull(
|
|
PDISK_REGION OsRegion,
|
|
PWSTR OsLoadFileName,
|
|
PWSTR LoadIdentifier,
|
|
PDISK_REGION SysPartRegion,
|
|
ULONG MinOsFree,
|
|
ULONG MinSysFree
|
|
)
|
|
{
|
|
|
|
ULONG ValidKeys[] = { KEY_F3,ASCI_ESC, 0 };
|
|
PWCHAR Drive1, Drive2;
|
|
DRIVELTR_STRING OsRgnDrive, OsRgnDriveFull, SysRgnDriveFull;
|
|
WCHAR Drive1Free[MAX_PATH], Drive1FreeNeeded[MAX_PATH];
|
|
WCHAR Drive2Free[MAX_PATH], Drive2FreeNeeded[MAX_PATH];
|
|
BOOLEAN FirstDefined = FALSE, SecondDefined = FALSE;
|
|
|
|
|
|
ASSERT(OsRegion->PartitionedSpace);
|
|
ASSERT(SysPartRegion->PartitionedSpace);
|
|
ASSERT(wcslen(OsLoadFileName) >= 2);
|
|
|
|
SpGetUpgDriveLetter(OsRegion->DriveLetter,
|
|
OsRgnDrive,
|
|
sizeof(OsRgnDrive),
|
|
FALSE
|
|
);
|
|
|
|
if((OsRegion == SysPartRegion) ||
|
|
(OsRegion->FreeSpaceKB < MinOsFree)) {
|
|
//
|
|
// Then we'll be needing the full (colon
|
|
// added) version of the drive letter
|
|
//
|
|
SpGetUpgDriveLetter(OsRegion->DriveLetter,
|
|
OsRgnDriveFull,
|
|
sizeof(OsRgnDrive),
|
|
TRUE
|
|
);
|
|
}
|
|
|
|
if( OsRegion == SysPartRegion ) {
|
|
Drive1 = OsRgnDriveFull;
|
|
swprintf(Drive1Free, L"%d", OsRegion->FreeSpaceKB);
|
|
swprintf(Drive1FreeNeeded, L"%d", MinOsFree);
|
|
FirstDefined = TRUE;
|
|
}
|
|
else {
|
|
if(SysPartRegion->FreeSpaceKB < MinSysFree) {
|
|
SpGetUpgDriveLetter(SysPartRegion->DriveLetter,
|
|
SysRgnDriveFull,
|
|
sizeof(SysRgnDriveFull),
|
|
TRUE
|
|
);
|
|
Drive1 = SysRgnDriveFull;
|
|
swprintf(Drive1Free, L"%d", SysPartRegion->FreeSpaceKB);
|
|
swprintf(Drive1FreeNeeded, L"%d", MinSysFree);
|
|
FirstDefined = TRUE;
|
|
}
|
|
if(OsRegion->FreeSpaceKB < MinOsFree) {
|
|
|
|
if(!FirstDefined) {
|
|
Drive1 = OsRgnDriveFull;
|
|
swprintf(Drive1Free, L"%d", OsRegion->FreeSpaceKB);
|
|
swprintf(Drive1FreeNeeded, L"%d", MinOsFree);
|
|
FirstDefined = TRUE;
|
|
|
|
}
|
|
else {
|
|
Drive2 = OsRgnDriveFull;
|
|
swprintf(Drive2Free, L"%d", OsRegion->FreeSpaceKB);
|
|
swprintf(Drive2FreeNeeded, L"%d", MinOsFree);
|
|
SecondDefined = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
while(1) {
|
|
|
|
SpStartScreen(
|
|
SP_SCRN_WINNT_DRIVE_FULL1,
|
|
3,
|
|
HEADER_HEIGHT+1,
|
|
FALSE,
|
|
FALSE,
|
|
DEFAULT_ATTRIBUTE,
|
|
OsRgnDrive,
|
|
OsLoadFileName,
|
|
LoadIdentifier,
|
|
FirstDefined ? Drive1 : L"",
|
|
FirstDefined ? Drive1FreeNeeded : L"",
|
|
FirstDefined ? Drive1Free : L"",
|
|
SecondDefined ? Drive2 : L"",
|
|
SecondDefined ? Drive2FreeNeeded : L"",
|
|
SecondDefined ? Drive2Free : L""
|
|
);
|
|
|
|
SpDisplayStatusOptions(
|
|
DEFAULT_STATUS_ATTRIBUTE,
|
|
SP_STAT_F3_EQUALS_EXIT,
|
|
SP_STAT_ESC_EQUALS_CANCEL,
|
|
0
|
|
);
|
|
|
|
switch(SpWaitValidKey(ValidKeys,NULL,NULL)) {
|
|
|
|
case KEY_F3:
|
|
SpConfirmExit();
|
|
break;
|
|
case ASCI_ESC:
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
SpGetUpgDriveLetter(
|
|
IN WCHAR DriveLetter,
|
|
IN PWCHAR Buffer,
|
|
IN ULONG BufferSize,
|
|
IN BOOL AddColon
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This returns a unicode string containing the drive letter specified by
|
|
DriveLetter (if nonzero). If DriveLetter is 0, then we assume that we
|
|
are looking at a mirrored partition, and retrieve a localized string of
|
|
the form '(Mirror)'. If 'AddColon' is TRUE, then drive letters get a
|
|
colon appended (eg, "C:").
|
|
|
|
|
|
Arguments:
|
|
|
|
DriveLetter: Unicode drive letter, or 0 to denote a mirrored partition.
|
|
|
|
Buffer: Buffer to receive the unicode string
|
|
|
|
BufferSize: Size of the buffer.
|
|
|
|
AddColon: Boolean specifying whether colon should be added (has no
|
|
effect if DriveLetter is 0).
|
|
|
|
|
|
Returns:
|
|
|
|
Buffer contains the formatted Unicode string.
|
|
|
|
--*/
|
|
{
|
|
if(DriveLetter) {
|
|
if(BufferSize >= 2) {
|
|
*(Buffer++) = DriveLetter;
|
|
if(AddColon && BufferSize >= 3) {
|
|
*(Buffer++) = L':';
|
|
}
|
|
}
|
|
*Buffer = 0;
|
|
} else {
|
|
SpFormatMessage(Buffer, BufferSize, SP_UPG_MIRROR_DRIVELETTER);
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
SppWarnUpgradeWorkstationToServer(
|
|
IN ULONG MsgId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Inform a user that that the installation that he/she selected to upgrade
|
|
is an NT Workstation, and that after the upgrade it will become a
|
|
Standard Server.
|
|
The user has the option to upgrade this or specify that he wants to
|
|
install Windows NT fresh.
|
|
|
|
Arguments:
|
|
|
|
MsgId - Screen to be displayed to the user.
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - Returns TRUE if the user wants to continue the upgrade, or
|
|
FALSE if the user wants to select another system to upgrade or
|
|
install fress.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ValidKeys[] = { ASCI_CR, ASCI_ESC, 0 };
|
|
ULONG c;
|
|
|
|
while(1) {
|
|
|
|
SpStartScreen(
|
|
MsgId,
|
|
3,
|
|
HEADER_HEIGHT+1,
|
|
FALSE,
|
|
FALSE,
|
|
DEFAULT_ATTRIBUTE
|
|
);
|
|
|
|
SpDisplayStatusOptions(
|
|
DEFAULT_STATUS_ATTRIBUTE,
|
|
SP_STAT_ENTER_EQUALS_CONTINUE,
|
|
SP_STAT_ESC_EQUALS_CANCEL,
|
|
0
|
|
);
|
|
|
|
switch(c=SpWaitValidKey(ValidKeys,NULL,NULL)) {
|
|
|
|
case KEY_F3:
|
|
SpConfirmExit();
|
|
break;
|
|
|
|
case ASCI_ESC:
|
|
return( FALSE );
|
|
|
|
case ASCI_CR:
|
|
return(TRUE);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
SppUpgradeWarnHpfs(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Inform the user that upgrading will mean the end of access to HPFS
|
|
drives.
|
|
|
|
A warning is only displayed if the user is upgrading from nt3.x,
|
|
there were hpfs partitions detected, and this is an attended installation.
|
|
|
|
NOTE: actually we don;t check for nt < 4, because people with nt3.51+newshell
|
|
will actually have a version of 4.0.
|
|
|
|
Don't call this routine unless the user elected to upgrade
|
|
(UpgradeType == UpgradeFull).
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
The user may opt to exit, in which case this routine will not return.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ValidKeys[2] = { KEY_F3, 0 };
|
|
ULONG Mnemonics[2] = { MnemonicUpgrade, 0 };
|
|
|
|
if(AnyHpfsDrives && !UnattendedOperation /*&& (OldMajorVersion < 4)*/) {
|
|
|
|
while(1) {
|
|
|
|
SpDisplayScreen(SP_SCRN_HPFS_UPGRADE,3,HEADER_HEIGHT+1);
|
|
|
|
SpDisplayStatusOptions(
|
|
DEFAULT_STATUS_ATTRIBUTE,
|
|
SP_STAT_F3_EQUALS_EXIT,
|
|
SP_STAT_U_EQUALS_CONTINUE_UPGRADE,
|
|
0
|
|
);
|
|
|
|
if(SpWaitValidKey(ValidKeys,NULL,Mnemonics) != KEY_F3) {
|
|
//
|
|
// Must be u=upgrade
|
|
//
|
|
return;
|
|
}
|
|
|
|
SpConfirmExit();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
SpCantFindBuildToUpgrade(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Inform the user that we were unable to locate the build from which
|
|
he initiated unattended installation via winnt32.
|
|
|
|
This is a fatal condition.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Does not return.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ValidKeys[2] = { KEY_F3, 0 };
|
|
|
|
CLEAR_CLIENT_SCREEN();
|
|
|
|
SpDisplayScreen(SP_SCRN_CANT_FIND_UPGRADE,3,HEADER_HEIGHT+1);
|
|
SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
|
|
|
|
SpWaitValidKey(ValidKeys,NULL,NULL);
|
|
|
|
SpDone(FALSE,FALSE);
|
|
}
|