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.
4521 lines
125 KiB
4521 lines
125 KiB
#include "spprecmp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// BUGBUG - SUNILP The following two are defined in winlogon\setup.h, but we
|
|
// cannot include setup.h so we are putting these two values here
|
|
//
|
|
|
|
#define SETUPTYPE_FULL 1
|
|
#define SETUPTYPE_UPGRADE 4
|
|
|
|
PWSTR LOCAL_MACHINE_KEY_NAME = L"\\registry\\machine";
|
|
PWSTR SETUP_KEY_NAME = L"setup";
|
|
PWSTR ATDISK_NAME = L"atdisk";
|
|
PWSTR ABIOSDISK_NAME = L"abiosdsk";
|
|
PWSTR PRIMARY_DISK_GROUP = L"Primary disk";
|
|
PWSTR VIDEO_GROUP = L"Video";
|
|
PWSTR KEYBOARD_PORT_GROUP = L"Keyboard Port";
|
|
PWSTR POINTER_PORT_GROUP = L"Pointer Port";
|
|
PWSTR DEFAULT_EVENT_LOG = L"%SystemRoot%\\System32\\IoLogMsg.dll";
|
|
PWSTR CODEPAGE_NAME = L"CodePage";
|
|
PWSTR UPGRADE_IN_PROGRESS = L"UpgradeInProgress";
|
|
PWSTR VIDEO_DEVICE0 = L"Device0";
|
|
PWSTR SESSION_MANAGER_KEY = L"Control\\Session Manager";
|
|
PWSTR BOOT_EXECUTE = L"BootExecute";
|
|
PWSTR RESTART_SETUP = L"RestartSetup";
|
|
|
|
|
|
NTSTATUS
|
|
SpSavePreinstallList(
|
|
IN PVOID SifHandle,
|
|
IN PWSTR SystemRoot,
|
|
IN HANDLE hKeySystemHive
|
|
);
|
|
|
|
NTSTATUS
|
|
SpDoRegistryInitialization(
|
|
IN PVOID SifHandle,
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR PartitionPath,
|
|
IN PWSTR SystemRoot,
|
|
IN HANDLE *HiveRootKeys,
|
|
IN PWSTR SetupSourceDevicePath,
|
|
IN PWSTR DirectoryOnSourceDevice,
|
|
IN PWSTR SpecialDevicePath OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SpFormSetupCommandLine(
|
|
IN PVOID SifHandle,
|
|
IN HANDLE hKeySystemHive,
|
|
IN PWSTR SetupSourceDevicePath,
|
|
IN PWSTR DirectoryOnSourceDevice,
|
|
IN PWSTR FullTargetPath,
|
|
IN PWSTR SpecialDevicePath OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SpDriverLoadList(
|
|
IN PVOID SifHandle,
|
|
IN PWSTR SystemRoot,
|
|
IN HANDLE hKeySystemHive,
|
|
IN HANDLE hKeyControlSet
|
|
);
|
|
|
|
NTSTATUS
|
|
SpSaveSKUStuff(
|
|
IN HANDLE hKeySystemHive
|
|
);
|
|
|
|
NTSTATUS
|
|
SpWriteVideoParameters(
|
|
IN PVOID SifHandle,
|
|
IN HANDLE hKeyControlSetServices
|
|
);
|
|
|
|
NTSTATUS
|
|
SpWriteUnattendedVideoParameters(
|
|
IN HANDLE hKeyControlSet
|
|
);
|
|
|
|
NTSTATUS
|
|
SpConfigureNlsParameters(
|
|
IN PVOID SifHandle,
|
|
IN HANDLE hKeyDefaultHive,
|
|
IN HANDLE hKeyControlSetControl
|
|
);
|
|
|
|
NTSTATUS
|
|
SpCreateCodepageEntry(
|
|
IN PVOID SifHandle,
|
|
IN HANDLE hKeyNls,
|
|
IN PWSTR SubkeyName,
|
|
IN PWSTR SifNlsSectionKeyName,
|
|
IN PWSTR EntryName
|
|
);
|
|
|
|
NTSTATUS
|
|
SpConfigureFonts(
|
|
IN PVOID SifHandle,
|
|
IN HANDLE hKeySoftwareHive
|
|
);
|
|
|
|
NTSTATUS
|
|
SpStoreHwInfoForSetup(
|
|
IN HANDLE hKeyControlSetControl
|
|
);
|
|
|
|
NTSTATUS
|
|
SpConfigureMouseKeyboardDrivers(
|
|
IN PVOID SifHandle,
|
|
IN ULONG HwComponent,
|
|
IN PWSTR ClassServiceName,
|
|
IN HANDLE hKeyControlSetServices,
|
|
IN PWSTR ServiceGroup
|
|
);
|
|
|
|
NTSTATUS
|
|
SpCreateServiceEntryIndirect(
|
|
IN HANDLE hKeyControlSetServices,
|
|
IN PVOID SifHandle, OPTIONAL
|
|
IN PWSTR SifSectionName, OPTIONAL
|
|
IN PWSTR KeyName,
|
|
IN ULONG ServiceType,
|
|
IN ULONG ServiceStart,
|
|
IN PWSTR ServiceGroup,
|
|
IN ULONG ServiceError,
|
|
IN PWSTR FileName, OPTIONAL
|
|
OUT PHANDLE SubkeyHandle OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
SpThirdPartyRegistry(
|
|
IN PVOID hKeyControlSetServices
|
|
);
|
|
|
|
NTSTATUS
|
|
SpGetCurrentControlSetKey(
|
|
IN HANDLE hKeySystem,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
OUT HANDLE *hKeyCCSet
|
|
);
|
|
|
|
NTSTATUS
|
|
SpAppendStringToMultiSz(
|
|
IN HANDLE hKey,
|
|
IN PWSTR Subkey,
|
|
IN PWSTR ValueName,
|
|
IN PWSTR StringToAdd
|
|
);
|
|
|
|
NTSTATUS
|
|
SpGetValueKey(
|
|
IN HANDLE hKeyRoot,
|
|
IN PWSTR KeyName,
|
|
IN PWSTR ValueName,
|
|
IN ULONG BufferLength,
|
|
OUT PUCHAR Buffer,
|
|
OUT PULONG ResultLength
|
|
);
|
|
|
|
NTSTATUS
|
|
SpConfigurePcmcia(
|
|
IN HANDLE hKeyControlSet
|
|
);
|
|
|
|
NTSTATUS
|
|
SpPostprocessHives(
|
|
IN PWSTR PartitionPath,
|
|
IN PWSTR Sysroot,
|
|
IN PWSTR *HiveNames,
|
|
IN HANDLE *HiveRootKeys,
|
|
IN unsigned HiveCount
|
|
);
|
|
|
|
NTSTATUS
|
|
SpFixHiveForCarolinaMachine(
|
|
IN HANDLE hKeyControlSetServices,
|
|
IN BOOLEAN SetupHive
|
|
);
|
|
|
|
NTSTATUS
|
|
SpSaveSetupPidList(
|
|
IN HANDLE hKeySystemHive
|
|
);
|
|
|
|
NTSTATUS
|
|
SpSavePageFileInfo(
|
|
IN HANDLE hKeyCCSetControl,
|
|
IN HANDLE hKeySystemHive
|
|
);
|
|
|
|
#define STRING_VALUE(s) REG_SZ,(s),(wcslen((s))+1)*sizeof(WCHAR)
|
|
#define ULONG_VALUE(u) REG_DWORD,&(u),sizeof(ULONG)
|
|
|
|
|
|
VOID
|
|
SpInitializeRegistry(
|
|
IN PVOID SifHandle,
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR SystemRoot,
|
|
IN PWSTR SetupSourceDevicePath,
|
|
IN PWSTR DirectoryOnSourceDevice,
|
|
IN PWSTR SpecialDevicePath OPTIONAL
|
|
)
|
|
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS Status;
|
|
NTSTATUS stat;
|
|
PWSTR pwstrTemp1,pwstrTemp2;
|
|
int h;
|
|
PWSTR PartitionPath;
|
|
|
|
PWSTR HiveNames[SetupHiveMax] = { L"system",L"software",L"default" };
|
|
BOOLEAN HiveLoaded[SetupHiveMax] = { FALSE ,FALSE ,FALSE };
|
|
HANDLE HiveRootKeys[SetupHiveMax] = { NULL ,NULL ,NULL };
|
|
PWSTR HiveRootPaths[SetupHiveMax] = { NULL ,NULL ,NULL };
|
|
|
|
//
|
|
// Put up a screen telling the user what we are doing.
|
|
//
|
|
SpStartScreen(
|
|
SP_SCRN_DOING_REG_CONFIG,
|
|
0,
|
|
8,
|
|
TRUE,
|
|
FALSE,
|
|
DEFAULT_ATTRIBUTE
|
|
);
|
|
|
|
SpDisplayStatusText(SP_STAT_REG_LOADING_HIVES,DEFAULT_STATUS_ATTRIBUTE);
|
|
|
|
//
|
|
// Get the name of the target patition.
|
|
//
|
|
SpNtNameFromRegion(
|
|
TargetRegion,
|
|
(PWSTR)TemporaryBuffer,
|
|
sizeof(TemporaryBuffer),
|
|
PartitionOrdinalCurrent
|
|
);
|
|
|
|
PartitionPath = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
|
|
pwstrTemp1 = (PWSTR)TemporaryBuffer;
|
|
pwstrTemp2 = (PWSTR)((PUCHAR)TemporaryBuffer + (sizeof(TemporaryBuffer) / 2));
|
|
|
|
//
|
|
// Load each template hive we care about from the target tree.
|
|
//
|
|
Status = STATUS_SUCCESS;
|
|
for(h=0; NT_SUCCESS(Status) && (h<SetupHiveMax); h++) {
|
|
|
|
//
|
|
// Form the name of the hive file.
|
|
// This is partitionpath + sysroot + system32\config + the hive name.
|
|
//
|
|
wcscpy(pwstrTemp1,PartitionPath);
|
|
SpConcatenatePaths(pwstrTemp1,SystemRoot);
|
|
SpConcatenatePaths(pwstrTemp1,L"system32\\config");
|
|
SpConcatenatePaths(pwstrTemp1,HiveNames[h]);
|
|
|
|
//
|
|
// Form the path of the key into which we will
|
|
// load the hive. We'll use the convention that
|
|
// a hive will be loaded into \registry\machine\x<hivename>.
|
|
//
|
|
wcscpy(pwstrTemp2,LOCAL_MACHINE_KEY_NAME);
|
|
SpConcatenatePaths(pwstrTemp2,L"x");
|
|
wcscat(pwstrTemp2,HiveNames[h]);
|
|
HiveRootPaths[h] = SpDupStringW(pwstrTemp2);
|
|
ASSERT(HiveRootPaths[h]);
|
|
|
|
//
|
|
// Attempt to load the key.
|
|
//
|
|
HiveLoaded[h] = FALSE;
|
|
Status = SpLoadUnloadKey(NULL,NULL,HiveRootPaths[h],pwstrTemp1);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
HiveLoaded[h] = TRUE;
|
|
|
|
//
|
|
// Now get a key to the root of the hive we just loaded.
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString,pwstrTemp2);
|
|
Status = ZwOpenKey(&HiveRootKeys[h],KEY_ALL_ACCESS,&Obja);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open %ws (%lx)\n",pwstrTemp2,Status));
|
|
HiveRootKeys[h] = NULL;
|
|
}
|
|
} else {
|
|
KdPrint(("SETUP: Unable to load hive %ws to key %ws (%lx)\n",pwstrTemp1,pwstrTemp2,Status));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Go do registry initialization.
|
|
//
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
SpDisplayStatusText(SP_STAT_REG_DOING_HIVES,DEFAULT_STATUS_ATTRIBUTE);
|
|
|
|
Status = SpDoRegistryInitialization(
|
|
SifHandle,
|
|
TargetRegion,
|
|
PartitionPath,
|
|
SystemRoot,
|
|
HiveRootKeys,
|
|
SetupSourceDevicePath,
|
|
DirectoryOnSourceDevice,
|
|
SpecialDevicePath
|
|
);
|
|
|
|
SpDisplayStatusText(SP_STAT_REG_SAVING_HIVES,DEFAULT_STATUS_ATTRIBUTE);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
Status = SpPostprocessHives(
|
|
PartitionPath,
|
|
SystemRoot,
|
|
HiveNames,
|
|
HiveRootKeys,
|
|
3
|
|
);
|
|
}
|
|
}
|
|
|
|
SpDisplayStatusText(SP_STAT_REG_SAVING_HIVES,DEFAULT_STATUS_ATTRIBUTE);
|
|
|
|
//
|
|
// From now on, do not disturb the value of Status.
|
|
//
|
|
// NOTE: DO NOT WRITE ANYTHING INTO HIVES BEYOND THIS POINT!!!
|
|
//
|
|
// In the upgrade case we have performed a little swictheroo in
|
|
// SpPostprocessHives() such that anything written to the system hive
|
|
// ends up in system.sav instead of system!
|
|
//
|
|
for(h=0; h<SetupHiveMax; h++) {
|
|
|
|
if(HiveLoaded[h]) {
|
|
//
|
|
// Hive was loaded.
|
|
//
|
|
if(HiveRootKeys[h]) {
|
|
ZwClose(HiveRootKeys[h]);
|
|
}
|
|
|
|
//
|
|
// Unload the hive now.
|
|
//
|
|
stat = SpLoadUnloadKey(NULL,NULL,HiveRootPaths[h],NULL);
|
|
if(!NT_SUCCESS(stat)) {
|
|
KdPrint(("SETUP: warning: unable to unload key %ws (%lx)\n",HiveRootPaths[h],stat));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free the root key path if necessary.
|
|
//
|
|
if(HiveRootPaths[h]) {
|
|
SpMemFree(HiveRootPaths[h]);
|
|
}
|
|
}
|
|
|
|
SpMemFree(PartitionPath);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
|
|
SpDisplayScreen(SP_SCRN_REGISTRY_CONFIG_FAILED,3,HEADER_HEIGHT+1);
|
|
SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
|
|
|
|
SpkbdDrain();
|
|
while(SpkbdGetKeypress() != KEY_F3) ;
|
|
|
|
SpDone(FALSE,TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpDoRegistryInitialization(
|
|
IN PVOID SifHandle,
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR PartitionPath,
|
|
IN PWSTR SystemRoot,
|
|
IN HANDLE *HiveRootKeys,
|
|
IN PWSTR SetupSourceDevicePath,
|
|
IN PWSTR DirectoryOnSourceDevice,
|
|
IN PWSTR SpecialDevicePath OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize a registry based on user selection for hardware types,
|
|
software options, and user preferences.
|
|
|
|
- Create a command line for GUI setup, to be used by winlogon.
|
|
- Create/munge service list entries for device drivers being installed.
|
|
- Initialize the keyboard layout.
|
|
- Initialize a core set of fonts for use with Windows.
|
|
- Store information about selected ahrdware components for use by GUI setup.
|
|
|
|
Arguments:
|
|
|
|
SifHandle - supplies handle to loaded setup information file.
|
|
|
|
TargetRegion - supplies region descriptor for region to which the system
|
|
is to be installed.
|
|
|
|
PartitionPath - supplies the NT name for the drive of windows nt.
|
|
|
|
SystemRoot - supplies nt path of the windows nt directory.
|
|
|
|
HiveRootKeys - supplies the handles to the root key of the system, software
|
|
and default hives
|
|
|
|
HiveRootPaths - supplies the paths to the root keys of the system, software
|
|
and default hives.
|
|
|
|
SetupSourceDevicePath - supplies nt path to the device setup is using for
|
|
source media (\device\floppy0, \device\cdrom0, etc).
|
|
|
|
DirectoryOnSourceDevice - supplies the directory on the source device
|
|
where setup files are kept.
|
|
|
|
Return Value:
|
|
|
|
Status value indicating outcome of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE hKeyControlSet,hKeyControlSetControl;
|
|
PWSTR FullTargetPath;
|
|
|
|
Status = SpGetCurrentControlSetKey(
|
|
HiveRootKeys[SetupHiveSystem],
|
|
KEY_ALL_ACCESS,
|
|
&hKeyControlSet
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sdoinitreg1;
|
|
}
|
|
|
|
//
|
|
// Open ControlSet\Control.
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString,L"Control");
|
|
Obja.RootDirectory = hKeyControlSet;
|
|
|
|
Status = ZwOpenKey(&hKeyControlSetControl,KEY_ALL_ACCESS,&Obja);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open CurrentControlSet\\Control (%lx)\n",Status));
|
|
goto sdoinitreg2;
|
|
}
|
|
|
|
//
|
|
// Save the Pid list
|
|
//
|
|
SpSaveSetupPidList( HiveRootKeys[SetupHiveSystem] );
|
|
|
|
//
|
|
// Form the setup command line.
|
|
//
|
|
|
|
wcscpy((PWSTR)TemporaryBuffer, PartitionPath);
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer, SystemRoot);
|
|
FullTargetPath = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
|
|
Status = SpFormSetupCommandLine(
|
|
SifHandle,
|
|
HiveRootKeys[SetupHiveSystem],
|
|
SetupSourceDevicePath,
|
|
DirectoryOnSourceDevice,
|
|
FullTargetPath,
|
|
SpecialDevicePath
|
|
);
|
|
SpMemFree(FullTargetPath);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sdoinitreg3;
|
|
}
|
|
|
|
//
|
|
// Save evalution time
|
|
//
|
|
Status = SpSaveSKUStuff(HiveRootKeys[SetupHiveSystem]);
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sdoinitreg3;
|
|
}
|
|
|
|
if(NTUpgrade == UpgradeFull) {
|
|
|
|
SpSavePageFileInfo( hKeyControlSetControl,
|
|
HiveRootKeys[SetupHiveSystem] );
|
|
|
|
//
|
|
// Create a pagefile because this operation can be extremely
|
|
// memory-intensive.
|
|
//
|
|
wcscpy((PWSTR)TemporaryBuffer,PartitionPath);
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer,L"PAGEFILE.SYS");
|
|
FullTargetPath = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
|
|
Status = SpCreatePageFile(FullTargetPath,10*1024*1024,20*1024*1024);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Warning: unable to create pagefile %ws (%lx)",FullTargetPath,Status));
|
|
}
|
|
|
|
SpMemFree(FullTargetPath);
|
|
|
|
Status = SpUpgradeNTRegistry(
|
|
SifHandle,
|
|
PartitionPath,
|
|
SystemRoot,
|
|
HiveRootKeys,
|
|
hKeyControlSet
|
|
);
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sdoinitreg3;
|
|
}
|
|
|
|
//
|
|
// Enable detected scsi miniports, atdisk and abios disk, if necessary
|
|
//
|
|
Status = SpDriverLoadList(SifHandle,SystemRoot,HiveRootKeys[SetupHiveSystem],hKeyControlSet);
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sdoinitreg3;
|
|
}
|
|
|
|
}
|
|
else {
|
|
|
|
//
|
|
// Create service entries for drivers being installed
|
|
// (ie, munge the driver load list).
|
|
//
|
|
Status = SpDriverLoadList(SifHandle,SystemRoot,HiveRootKeys[SetupHiveSystem],hKeyControlSet);
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sdoinitreg3;
|
|
}
|
|
|
|
//
|
|
// Language/locale-specific registry initialization.
|
|
// BUGBUG - jaimes - Need to fix this in the OEM preinstall case
|
|
//
|
|
Status = SplangSetRegistryData(SifHandle,hKeyControlSet,HardwareComponents);
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sdoinitreg3;
|
|
}
|
|
|
|
//
|
|
// Set up the keyboard layout and nls-related stuff.
|
|
//
|
|
Status = SpConfigureNlsParameters(SifHandle,HiveRootKeys[SetupHiveDefault],hKeyControlSetControl);
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sdoinitreg3;
|
|
}
|
|
|
|
//
|
|
// Set up font entries.
|
|
//
|
|
Status = SpConfigureFonts(SifHandle,HiveRootKeys[SetupHiveSoftware]);
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sdoinitreg3;
|
|
}
|
|
|
|
//
|
|
// Store information used by gui setup, describing the hardware
|
|
// selections made by the user.
|
|
//
|
|
Status = SpStoreHwInfoForSetup(hKeyControlSetControl);
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sdoinitreg3;
|
|
}
|
|
if( PreInstall ) {
|
|
ULONG u;
|
|
|
|
u = 1;
|
|
SpSavePreinstallList( SifHandle,
|
|
SystemRoot,
|
|
HiveRootKeys[SetupHiveSystem] );
|
|
|
|
Status = SpOpenSetValueAndClose( hKeyControlSetControl,
|
|
L"Windows",
|
|
L"NoPopupsOnBoot",
|
|
ULONG_VALUE(u) );
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set NoPopupOnBoot. Status = %lx \n",Status));
|
|
}
|
|
|
|
//
|
|
// Add autolfn.exe to bootexecute list.
|
|
//
|
|
Status = SpAppendStringToMultiSz(
|
|
hKeyControlSet,
|
|
SESSION_MANAGER_KEY,
|
|
BOOT_EXECUTE,
|
|
L"autolfn"
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to add autolfn to BootExecute. Status = %lx \n",Status));
|
|
goto sdoinitreg3;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we need to convert to ntfs, set that up here.
|
|
// We can't use the PartitionPath since that is based on
|
|
// *current* disk ordinal -- we need a name based on the *on-disk*
|
|
// ordinal, since the convert occurs after a reboot.
|
|
//
|
|
if(ConvertNtVolumeToNtfs) {
|
|
|
|
wcscpy((PWSTR)TemporaryBuffer,L"autoconv ");
|
|
|
|
SpNtNameFromRegion(
|
|
TargetRegion,
|
|
(PWSTR)TemporaryBuffer+9, // append to the "autoconv " we put there
|
|
512, // just need any reasonable size
|
|
PartitionOrdinalOnDisk
|
|
);
|
|
|
|
wcscat((PWSTR)TemporaryBuffer,L" /fs:NTFS");
|
|
if(ExtendingOemPartition) {
|
|
wcscat((PWSTR)TemporaryBuffer,L" /o");
|
|
}
|
|
|
|
FullTargetPath = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
|
|
Status = SpAppendStringToMultiSz(
|
|
hKeyControlSet,
|
|
SESSION_MANAGER_KEY,
|
|
BOOT_EXECUTE,
|
|
FullTargetPath
|
|
);
|
|
|
|
SpMemFree(FullTargetPath);
|
|
}
|
|
}
|
|
|
|
#if _PPC_
|
|
if( InstallingOnCarolinaMachine ) {
|
|
HANDLE hCCSetServices;
|
|
|
|
|
|
//
|
|
// Open ControlSet001\Services.
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString,L"Services");
|
|
Obja.RootDirectory = hKeyControlSet;
|
|
|
|
Status = ZwOpenKey(&hCCSetServices,KEY_ALL_ACCESS,&Obja);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open ControlSet001\\Services (%lx)\n", Status));
|
|
goto sdoinitreg3;
|
|
}
|
|
Status = SpFixHiveForCarolinaMachine( hCCSetServices, FALSE );
|
|
ZwClose( hCCSetServices );
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to initialize values for Carolina machines (%lx)\n", Status));
|
|
goto sdoinitreg3;
|
|
}
|
|
}
|
|
#endif // _PPC_
|
|
|
|
|
|
Status = SpConfigurePcmcia(hKeyControlSet);
|
|
|
|
sdoinitreg3:
|
|
|
|
ZwClose(hKeyControlSetControl);
|
|
|
|
sdoinitreg2:
|
|
|
|
ZwClose(hKeyControlSet);
|
|
|
|
sdoinitreg1:
|
|
|
|
return(Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
AppendSectionsToIniFile(
|
|
IN PWSTR Filename
|
|
)
|
|
|
|
/**
|
|
|
|
Routine Description:
|
|
|
|
Append the following section(s) to $winnt$.inf file:
|
|
|
|
[NetCardParameterList]
|
|
!NetCardParameterName = ^($(!STF_UNATTENDED_SECTION), 0)
|
|
!NetCardParameterValue = ^($(!STF_UNATTENDED_SECTION), 1)
|
|
[ReadDefaultData]
|
|
set DefaultDataItems = ^($($0),1)
|
|
ifstr(i) $(DefaultDataItems) == {}
|
|
return STATUS_FAILED
|
|
else
|
|
read-syms $($0)
|
|
return STATUS_SUCCESSFUL
|
|
endif
|
|
|
|
such that GUI mode setup inf files can invoke the stubbed section to
|
|
read in user specified data.
|
|
|
|
Arguments:
|
|
|
|
Filename - supplies the fully qualified nt name of the file to be updated.
|
|
|
|
Return Value:
|
|
|
|
Status value indicating outcome of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
OBJECT_ATTRIBUTES DstAttributes;
|
|
UNICODE_STRING DstName;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
HANDLE hDst;
|
|
NTSTATUS Status;
|
|
PCHAR Lines;
|
|
LARGE_INTEGER ByteOffset;
|
|
|
|
//
|
|
// Initialize names and attributes.
|
|
//
|
|
INIT_OBJA(&DstAttributes,&DstName,Filename);
|
|
|
|
//
|
|
// Open/overwrite the target file.
|
|
// Open for generic read and write (read is necessary because
|
|
// we might need to smash locks on the file, and in that case,
|
|
// we will map the file for readwrite, which requires read and write
|
|
// file access).
|
|
//
|
|
|
|
Status = ZwCreateFile(
|
|
&hDst,
|
|
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
|
|
&DstAttributes,
|
|
&IoStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0, // no sharing
|
|
FILE_OPEN,
|
|
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
Lines = (PCHAR)TemporaryBuffer;
|
|
*Lines = '\0';
|
|
strcat(Lines, "\r\n[NetCardParameterList]\r\n");
|
|
strcat(Lines, "!NetCardParameterName = ^($(!STF_UNATTENDED_SECTION), 0)\r\n");
|
|
strcat(Lines, "!NetCardParameterValue = ^($(!STF_UNATTENDED_SECTION), 1)\r\n");
|
|
strcat(Lines, "[ReadDefaultData]\r\n");
|
|
strcat(Lines, "set DefaultDataItems = ^($($0),1)\r\n");
|
|
strcat(Lines, "ifstr(i) $(DefaultDataItems) == {}\r\n");
|
|
strcat(Lines, "return STATUS_FAILED\r\n");
|
|
strcat(Lines, "else\r\n");
|
|
strcat(Lines, "read-syms $($0)\r\n");
|
|
strcat(Lines, "return STATUS_SUCCESSFUL\r\n");
|
|
strcat(Lines, "endif\r\n");
|
|
|
|
//
|
|
// Append lines to the file.
|
|
//
|
|
|
|
ByteOffset.HighPart = -1;
|
|
ByteOffset.LowPart = FILE_WRITE_TO_END_OF_FILE;
|
|
try {
|
|
Status = ZwWriteFile(
|
|
hDst,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
Lines,
|
|
strlen(Lines),
|
|
&ByteOffset,
|
|
NULL
|
|
);
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = STATUS_IN_PAGE_ERROR;
|
|
}
|
|
ZwClose(hDst);
|
|
}
|
|
return (Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
SpFormSetupCommandLine(
|
|
IN PVOID SifHandle,
|
|
IN HANDLE hKeySystemHive,
|
|
IN PWSTR SetupSourceDevicePath,
|
|
IN PWSTR DirectoryOnSourceDevice,
|
|
IN PWSTR FullTargetPath,
|
|
IN PWSTR SpecialDevicePath OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create the command line to invoke GUI setup and store it in
|
|
HKEY_LOCAL_MACHINE\system\<ControlSet>\Setup:CmdLine.
|
|
|
|
The command line is as follows:
|
|
|
|
setup -newsetup
|
|
|
|
Arguments:
|
|
|
|
hKeySystemHive - supplies handle to root of the system hive
|
|
(ie, HKEY_LOCAL_MACHINE\System).
|
|
|
|
SetupSourceDevicePath - supplies the nt device path of the source media
|
|
to be used during setup (\device\floppy0, \device\cdrom0, etc).
|
|
|
|
DirectoryOnSourceDevice - supplies the directory on the source device
|
|
where setup files are kept.
|
|
|
|
FullTargetPath - supplies the NtPartitionName+SystemRoot path on the target device.
|
|
|
|
SpecialDevicePath - if specified, will be passed to setup as the value for
|
|
STF_SPECIAL_PATH. If not specified, STF_SPECIAL_PATH will be "NO"
|
|
|
|
Return Value:
|
|
|
|
Status value indicating outcome of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
PWSTR OptionalDirSpec = NULL;
|
|
PWSTR UserExecuteCmd = NULL;
|
|
PWSTR szLanManNt = WINNT_A_LANMANNT_W;
|
|
PWSTR szWinNt = WINNT_A_WINNT_W;
|
|
PWSTR szYes = WINNT_A_YES_W;
|
|
PWSTR szNo = WINNT_A_NO_W;
|
|
PWSTR SourcePathBuffer;
|
|
PWSTR CmdLine;
|
|
DWORD SetupType,SetupInProgress;
|
|
NTSTATUS Status;
|
|
PWSTR TargetFile;
|
|
PWSTR p;
|
|
|
|
//
|
|
// Can't use TemporaryBuffer because we make subroutine calls
|
|
// below that trash its contents.
|
|
//
|
|
CmdLine = SpMemAlloc(256);
|
|
CmdLine[0] = 0;
|
|
|
|
//
|
|
// Construct the setup command line. Start with the basic part.
|
|
//
|
|
if(p = SpGetSectionKeyIndex(SifHandle,SIF_SETUPDATA,SIF_SETUPCMDPREPEND,0)) {
|
|
wcscat(CmdLine,p);
|
|
wcscat(CmdLine,L" ");
|
|
}
|
|
wcscat(CmdLine,L"setup -newsetup");
|
|
|
|
//
|
|
// Put the setup source in the command line.
|
|
// Note that the source is an NT-style name. GUI Setup handles this properly.
|
|
//
|
|
SourcePathBuffer = SpMemAlloc( (wcslen(SetupSourceDevicePath) +
|
|
wcslen(DirectoryOnSourceDevice) + 2) * sizeof(WCHAR) );
|
|
wcscpy(SourcePathBuffer,SetupSourceDevicePath);
|
|
SpConcatenatePaths(SourcePathBuffer,DirectoryOnSourceDevice);
|
|
|
|
SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_SOURCEPATH_W,
|
|
&SourcePathBuffer,1);
|
|
|
|
//
|
|
// Put a flag indicating whether this is a win3.1 upgrade.
|
|
//
|
|
SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_WIN31UPGRADE_W,
|
|
( (WinUpgradeType == UpgradeWin31) ? &szYes : &szNo),1);
|
|
|
|
//
|
|
// Put a flag indicating whether this is a win95 upgrade.
|
|
//
|
|
SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_WIN95UPGRADE_W,
|
|
( (WinUpgradeType == UpgradeWin95) ? &szYes : &szNo),1);
|
|
|
|
//
|
|
// Put a flag indicating whether this is an NT upgrade.
|
|
//
|
|
SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_NTUPGRADE_W,
|
|
((NTUpgrade == UpgradeFull) ? &szYes : &szNo), 1);
|
|
|
|
//
|
|
// Put a flag indicating whether to upgrade a standard server
|
|
// (an existing standard server, or an existing workstation to
|
|
// a standard server)
|
|
//
|
|
SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_SERVERUPGRADE_W,
|
|
(StandardServerUpgrade ? &szYes : &szNo),1);
|
|
|
|
//
|
|
// Tell gui mode whether this is server or workstation.
|
|
//
|
|
SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_PRODUCT_W,
|
|
(AdvancedServer ? &szLanManNt : &szWinNt),1);
|
|
|
|
//
|
|
// Special path spec.
|
|
//
|
|
SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_BOOTPATH_W,
|
|
(SpecialDevicePath ? &SpecialDevicePath : &szNo), 1);
|
|
|
|
//
|
|
// Go Fetch the Optional Dir Specs...
|
|
//
|
|
OptionalDirSpec = SpGetSectionKeyIndex(WinntSifHandle,SIF_SETUPPARAMS,
|
|
L"OptionalDirs",0);
|
|
|
|
//
|
|
// Check for commad line to execute at end of gui setup
|
|
//
|
|
UserExecuteCmd = SpGetSectionKeyIndex(WinntSifHandle,SIF_SETUPPARAMS,
|
|
L"UserExecute",0);
|
|
|
|
//
|
|
// Unattended mode flag | script filename
|
|
//
|
|
SpAddLineToSection(WinntSifHandle,SIF_DATA,WINNT_D_INSTALL_W,
|
|
((UnattendedOperation || UnattendedGuiOperation) ? &szYes : &szNo), 1);
|
|
|
|
//
|
|
// Before we write the answer to this, we need to know if we successfully
|
|
// have written Winnt.sif into system32\$winnt$.inf
|
|
//
|
|
// Note: we need to do this step by building up the name to pass to the
|
|
// file writing function since the call to AppendSectionsToIniFile requiers
|
|
// it.
|
|
//
|
|
wcscpy((PWSTR)TemporaryBuffer, FullTargetPath);
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer, L"system32");
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer, SIF_UNATTENDED_INF_FILE);
|
|
TargetFile = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
Status = SpWriteSetupTextFile(WinntSifHandle,TargetFile,NULL,NULL);
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// If the write succeeds, we append a stub to the end of the special
|
|
// inf file such that GUI mode setup can call this stub to read in
|
|
// user defined constants.
|
|
//
|
|
Status = AppendSectionsToIniFile(TargetFile);
|
|
}
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeySystemHive,
|
|
SETUP_KEY_NAME,
|
|
L"CmdLine",
|
|
STRING_VALUE(CmdLine)
|
|
);
|
|
}
|
|
|
|
//
|
|
// Free up whatever memory we have allocated
|
|
//
|
|
SpMemFree(TargetFile);
|
|
SpMemFree(CmdLine);
|
|
SpMemFree(SourcePathBuffer);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Set the SetupType value to the right value SETUPTYPE_FULL in the
|
|
// case of initial install and SETUPTYPE_UPGRADE in the case of upgrade.
|
|
//
|
|
|
|
SetupType = (NTUpgrade == UpgradeFull) ? SETUPTYPE_UPGRADE : SETUPTYPE_FULL;
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeySystemHive,
|
|
SETUP_KEY_NAME,
|
|
L"SetupType",
|
|
ULONG_VALUE(SetupType)
|
|
);
|
|
if(!NT_SUCCESS(Status)) {
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Set the SystemSetupInProgress value. Don't rely on the default hives
|
|
// having this set
|
|
//
|
|
|
|
SetupInProgress = 1;
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeySystemHive,
|
|
SETUP_KEY_NAME,
|
|
L"SystemSetupInProgress",
|
|
ULONG_VALUE(SetupInProgress)
|
|
);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpDriverLoadList(
|
|
IN PVOID SifHandle,
|
|
IN PWSTR SystemRoot,
|
|
IN HANDLE hKeySystemHive,
|
|
IN HANDLE hKeyControlSet
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE hKeyControlSetServices;
|
|
PHARDWARE_COMPONENT ScsiHwComponent;
|
|
ULONG u;
|
|
|
|
//
|
|
// Open controlset\services.
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString,L"services");
|
|
Obja.RootDirectory = hKeyControlSet;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKeyControlSetServices,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: unable to open services key (%lx)\n",Status));
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// For each non-third-party miniport driver that loaded,
|
|
// go create a services entry for it.
|
|
//
|
|
if( !PreInstall ||
|
|
( PreinstallScsiHardware == NULL ) ) {
|
|
ScsiHwComponent = ScsiHardware;
|
|
} else {
|
|
ScsiHwComponent = PreinstallScsiHardware;
|
|
}
|
|
for( ; ScsiHwComponent; ScsiHwComponent=ScsiHwComponent->Next) {
|
|
|
|
if(!ScsiHwComponent->ThirdPartyOptionSelected) {
|
|
|
|
//
|
|
// For scsi, the shortname (idstring) is used as
|
|
// the name of the service node key in the registry --
|
|
// we don't look up the service entry in the [SCSI] section
|
|
// of the setup info file.
|
|
//
|
|
Status = SpCreateServiceEntryIndirect(
|
|
hKeyControlSetServices,
|
|
NULL,
|
|
NULL,
|
|
ScsiHwComponent->IdString,
|
|
SERVICE_KERNEL_DRIVER,
|
|
SERVICE_BOOT_START,
|
|
L"SCSI miniport",
|
|
SERVICE_ERROR_NORMAL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto spdrvlist1;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// If there are any atdisks out there, enable atdisk.
|
|
// We have to enable AtDisk if Pcmcia was loaded, even
|
|
// if atdisk doesn't exist. This will allow the user to
|
|
// insert a pcmcia atdisk device, and have it work when
|
|
// they boot. In this case, however, we turn off error
|
|
// logging, so that they won't get an annoying popup
|
|
// when there is no atdisk device in the card slot.
|
|
//
|
|
// Note that atdisk.sys is always copied to the system.
|
|
//
|
|
|
|
Status = SpCreateServiceEntryIndirect(
|
|
hKeyControlSetServices,
|
|
NULL,
|
|
NULL,
|
|
ATDISK_NAME,
|
|
SERVICE_KERNEL_DRIVER,
|
|
( AtDisksExist || PcmciaLoaded )? SERVICE_BOOT_START : SERVICE_DISABLED,
|
|
PRIMARY_DISK_GROUP,
|
|
( AtDisksExist && !AtapiLoaded )? SERVICE_ERROR_NORMAL : SERVICE_ERROR_IGNORE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto spdrvlist1;
|
|
}
|
|
|
|
//
|
|
// If there are any abios disks out there, enable abiosdsk.
|
|
//
|
|
if(AbiosDisksExist) {
|
|
|
|
Status = SpCreateServiceEntryIndirect(
|
|
hKeyControlSetServices,
|
|
NULL,
|
|
NULL,
|
|
ABIOSDISK_NAME,
|
|
SERVICE_KERNEL_DRIVER,
|
|
SERVICE_BOOT_START,
|
|
PRIMARY_DISK_GROUP,
|
|
SERVICE_ERROR_NORMAL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto spdrvlist1;
|
|
}
|
|
}
|
|
|
|
if( NTUpgrade != UpgradeFull ) {
|
|
if( UnattendedOperation ) {
|
|
//
|
|
// Set up the unattended video parameters, if necessary.
|
|
// Ignore errors, since they are not fatal.
|
|
//
|
|
SpWriteUnattendedVideoParameters(hKeyControlSet);
|
|
}
|
|
//
|
|
// Set up video parameters.
|
|
//
|
|
Status = SpWriteVideoParameters(SifHandle,hKeyControlSetServices);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto spdrvlist1;
|
|
}
|
|
|
|
//
|
|
// Enable the relevent keyboard and mouse drivers. If the class drivers
|
|
// are being replaced by third-party ones, then disable the built-in ones.
|
|
//
|
|
Status = SpConfigureMouseKeyboardDrivers(
|
|
SifHandle,
|
|
HwComponentKeyboard,
|
|
L"kbdclass",
|
|
hKeyControlSetServices,
|
|
KEYBOARD_PORT_GROUP
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto spdrvlist1;
|
|
}
|
|
|
|
Status = SpConfigureMouseKeyboardDrivers(
|
|
SifHandle,
|
|
HwComponentMouse,
|
|
L"mouclass",
|
|
hKeyControlSetServices,
|
|
POINTER_PORT_GROUP
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto spdrvlist1;
|
|
}
|
|
|
|
}
|
|
Status = SpThirdPartyRegistry(hKeyControlSetServices);
|
|
|
|
spdrvlist1:
|
|
|
|
ZwClose(hKeyControlSetServices);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpSaveSKUStuff(
|
|
IN HANDLE hKeySystemHive
|
|
)
|
|
{
|
|
LARGE_INTEGER l;
|
|
NTSTATUS Status;
|
|
ULONG NumberOfProcessors;
|
|
BOOLEAN OldStyleRegisteredProcessorMode;
|
|
|
|
//
|
|
// Do not change any of this algorithm without changing
|
|
// SetUpEvaluationSKUStuff() in syssetup.dll (registry.c).
|
|
//
|
|
// Embed the evaluation time and a bool indicating whether
|
|
// this is a server or workstation inside a random large integer.
|
|
//
|
|
// Evaluation time: bits 13-44
|
|
// Product type : bit 58
|
|
//
|
|
// Bit 10 == 1 : Setup works as it does before the 4.0 restriction logic
|
|
// == 0 : GUI Setup writes registered processors based on the
|
|
// contents of bits 5-9
|
|
//
|
|
// Bits 5 - 9 : The maximum number of processors that the system is licensed
|
|
// to use. The value stored is actually ~(MaxProcessors-1)
|
|
//
|
|
//
|
|
// RestrictCpu is used to build protucts this place a very hard
|
|
// limit on the number of processors
|
|
//
|
|
// - a value of 0 means for NTW, the hard limit is 2, and for NTS,
|
|
// the hard limit is 4
|
|
//
|
|
// - a value of 1-32 means that the hard limit is the number
|
|
// specified
|
|
//
|
|
// - a value > 32 means that the hard limit is 32 processors and GUI
|
|
// setup operates on registered processors as it does today
|
|
//
|
|
|
|
l.LowPart = SpComputeSerialNumber();
|
|
l.HighPart = SpComputeSerialNumber();
|
|
|
|
l.QuadPart &= 0xfbffe0000000181f;
|
|
l.QuadPart |= ((ULONGLONG)EvaluationTime) << 13;
|
|
|
|
if ( RestrictCpu == 0 ) {
|
|
OldStyleRegisteredProcessorMode = FALSE;
|
|
if(AdvancedServer) {
|
|
NumberOfProcessors = 4;
|
|
} else {
|
|
NumberOfProcessors = 2;
|
|
}
|
|
} else if ( RestrictCpu <= 32 ) {
|
|
OldStyleRegisteredProcessorMode = FALSE;
|
|
NumberOfProcessors = RestrictCpu;
|
|
} else {
|
|
OldStyleRegisteredProcessorMode = TRUE;
|
|
NumberOfProcessors = 32;
|
|
}
|
|
|
|
//
|
|
// Now NumberOfProcessors is correct. Convert it to the in registry format
|
|
//
|
|
|
|
NumberOfProcessors--;
|
|
|
|
NumberOfProcessors = ~NumberOfProcessors;
|
|
NumberOfProcessors = NumberOfProcessors << 5;
|
|
NumberOfProcessors &= 0x000003e0;
|
|
|
|
//
|
|
// Store NumberOfProcessors into the registry
|
|
//
|
|
|
|
l.LowPart |= NumberOfProcessors;
|
|
|
|
//
|
|
// Tell Gui Mode to do old style registered processors
|
|
//
|
|
|
|
if ( OldStyleRegisteredProcessorMode ) {
|
|
l.LowPart |= 0x00000400;
|
|
}
|
|
|
|
if(AdvancedServer) {
|
|
l.HighPart |= 0x04000000;
|
|
}
|
|
|
|
//
|
|
// Save in registry.
|
|
//
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeySystemHive,
|
|
SETUP_KEY_NAME,
|
|
L"SystemPrefix",
|
|
REG_BINARY,
|
|
&l.QuadPart,
|
|
sizeof(ULONGLONG)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set SystemPrefix (%lx)\n",Status));
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpSetUlongValueFromSif(
|
|
IN PVOID SifHandle,
|
|
IN PWSTR SifSection,
|
|
IN PWSTR SifKey,
|
|
IN ULONG SifIndex,
|
|
IN HANDLE hKey,
|
|
IN PWSTR ValueName
|
|
)
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
PWSTR ValueString;
|
|
LONG Value;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Look up the value.
|
|
//
|
|
ValueString = SpGetSectionKeyIndex(SifHandle,SifSection,SifKey,SifIndex);
|
|
if(!ValueString) {
|
|
SpFatalSifError(SifHandle,SifSection,SifKey,0,SifIndex);
|
|
}
|
|
|
|
Value = SpStringToLong(ValueString,NULL,10);
|
|
|
|
if(Value == -1) {
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
} else {
|
|
|
|
RtlInitUnicodeString(&UnicodeString,ValueName);
|
|
|
|
Status = ZwSetValueKey(hKey,&UnicodeString,0,ULONG_VALUE((ULONG)Value));
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set value %ws (%lx)\n",ValueName,Status));
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpConfigureMouseKeyboardDrivers(
|
|
IN PVOID SifHandle,
|
|
IN ULONG HwComponent,
|
|
IN PWSTR ClassServiceName,
|
|
IN HANDLE hKeyControlSetServices,
|
|
IN PWSTR ServiceGroup
|
|
)
|
|
{
|
|
PHARDWARE_COMPONENT hw;
|
|
NTSTATUS Status;
|
|
ULONG val = SERVICE_DISABLED;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
if( !PreInstall ||
|
|
( PreinstallHardwareComponents[HwComponent] == NULL ) ) {
|
|
hw = HardwareComponents[HwComponent];
|
|
} else {
|
|
hw = PreinstallHardwareComponents[HwComponent];
|
|
}
|
|
for(;hw && NT_SUCCESS( Status ); hw=hw->Next) {
|
|
if(hw->ThirdPartyOptionSelected) {
|
|
|
|
if(IS_FILETYPE_PRESENT(hw->FileTypeBits,HwFileClass)) {
|
|
|
|
if( !PreInstall ) {
|
|
//
|
|
// Disable the built-in class driver.
|
|
//
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyControlSetServices,
|
|
ClassServiceName,
|
|
L"Start",
|
|
ULONG_VALUE(val)
|
|
);
|
|
}
|
|
}
|
|
} else {
|
|
|
|
Status = SpCreateServiceEntryIndirect(
|
|
hKeyControlSetServices,
|
|
SifHandle,
|
|
NonlocalizedComponentNames[HwComponent],
|
|
hw->IdString,
|
|
SERVICE_KERNEL_DRIVER,
|
|
SERVICE_SYSTEM_START,
|
|
ServiceGroup,
|
|
SERVICE_ERROR_IGNORE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
SpWriteUnattendedVideoParameters(
|
|
IN HANDLE hKeyControlSet
|
|
)
|
|
{
|
|
NTSTATUS Status, SavedStatus;
|
|
PWSTR KeyName = L"Control\\GraphicsDrivers\\DetectDisplay";
|
|
PWSTR p;
|
|
ULONG u;
|
|
ULONG i;
|
|
|
|
PWSTR ValueNames[] = {
|
|
WINNT_DISP_CONFIGATLOGON_W,
|
|
WINNT_DISP_BITSPERPEL_W,
|
|
WINNT_DISP_XRESOLUTION_W,
|
|
WINNT_DISP_YRESOLUTION_W,
|
|
WINNT_DISP_VREFRESH_W,
|
|
WINNT_DISP_FLAGS_W,
|
|
WINNT_DISP_AUTOCONFIRM_W,
|
|
WINNT_DISP_INSTALL_W
|
|
};
|
|
PWSTR StringNames[] = {
|
|
WINNT_DISP_INF_FILE_W,
|
|
WINNT_DISP_INF_OPTION_W
|
|
};
|
|
|
|
SavedStatus = STATUS_SUCCESS;
|
|
if( UnattendedSifHandle != NULL ) {
|
|
for( i = 0; i < sizeof(ValueNames)/sizeof(PWSTR); i++ ) {
|
|
p = SpGetSectionKeyIndex(UnattendedSifHandle,
|
|
WINNT_DISPLAY_W,
|
|
ValueNames[i],
|
|
0);
|
|
if( p != NULL ) {
|
|
u = SpStringToLong(p,NULL,0);
|
|
Status = SpOpenSetValueAndClose( hKeyControlSet,
|
|
KeyName,
|
|
ValueNames[i],
|
|
ULONG_VALUE(u) );
|
|
if( !NT_SUCCESS( Status ) ) {
|
|
KdPrint(("SETUP: Unable to write value %ls to key %ls. Status = %lx \n",ValueNames[i], KeyName, Status));
|
|
if( NT_SUCCESS( SavedStatus ) ) {
|
|
SavedStatus = Status;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for( i = 0; i < sizeof(StringNames)/sizeof(PWSTR); i++ ) {
|
|
p = SpGetSectionKeyIndex(UnattendedSifHandle,
|
|
WINNT_DISPLAY_W,
|
|
StringNames[i],
|
|
0);
|
|
if( p != NULL ) {
|
|
|
|
Status = SpOpenSetValueAndClose( hKeyControlSet,
|
|
KeyName,
|
|
StringNames[i],
|
|
STRING_VALUE(p) );
|
|
if( !NT_SUCCESS( Status ) ) {
|
|
KdPrint(("SETUP: Unable to write value %ls to key %ls. Status = %lx \n",StringNames[i], KeyName, Status));
|
|
if( NT_SUCCESS( SavedStatus ) ) {
|
|
SavedStatus = Status;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return( SavedStatus );
|
|
}
|
|
|
|
NTSTATUS
|
|
SpWriteVideoParameters(
|
|
IN PVOID SifHandle,
|
|
IN HANDLE hKeyControlSetServices
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PWSTR KeyName;
|
|
HANDLE hKeyDisplayService;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
ULONG x,y,b,v,i;
|
|
PHARDWARE_COMPONENT pHw;
|
|
|
|
if( !PreInstall ||
|
|
( PreinstallHardwareComponents[HwComponentDisplay] == NULL ) ) {
|
|
pHw = HardwareComponents[HwComponentDisplay];
|
|
} else {
|
|
pHw = PreinstallHardwareComponents[HwComponentDisplay];
|
|
}
|
|
Status = STATUS_SUCCESS;
|
|
for(;pHw && NT_SUCCESS(Status);pHw=pHw->Next) {
|
|
//
|
|
// Third party drivers will have values written into the miniport
|
|
// Device0 key at the discretion of the txtsetup.oem author.
|
|
//
|
|
if(pHw->ThirdPartyOptionSelected) {
|
|
continue;
|
|
// return(STATUS_SUCCESS);
|
|
}
|
|
|
|
KeyName = SpGetSectionKeyIndex(
|
|
SifHandle,
|
|
NonlocalizedComponentNames[HwComponentDisplay],
|
|
pHw->IdString,
|
|
INDEX_INFKEYNAME
|
|
);
|
|
|
|
//
|
|
// If no key name is specified for this display then there's nothing to do.
|
|
// The setup display subsystem can tell us that the mode parameters are
|
|
// not relevent. If so there's nothing to do.
|
|
//
|
|
if(!KeyName || !SpvidGetModeParams(&x,&y,&b,&v,&i)) {
|
|
continue;
|
|
// return(STATUS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// We want to write the parameters for the display mode setup
|
|
// is using into the relevent key in the service list. This will force
|
|
// the right mode for, say, a fixed-frequency monitor attached to
|
|
// a vxl (which might default to a mode not supported by the monitor).
|
|
//
|
|
|
|
INIT_OBJA(&Obja,&UnicodeString,KeyName);
|
|
Obja.RootDirectory = hKeyControlSetServices;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKeyDisplayService,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: unable to open/create key %ws (%lx)\n",KeyName,Status));
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Set the x resolution.
|
|
//
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyDisplayService,
|
|
VIDEO_DEVICE0,
|
|
L"DefaultSettings.XResolution",
|
|
ULONG_VALUE(x)
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// Set the y resolution.
|
|
//
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyDisplayService,
|
|
VIDEO_DEVICE0,
|
|
L"DefaultSettings.YResolution",
|
|
ULONG_VALUE(y)
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// Set the bits per pixel.
|
|
//
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyDisplayService,
|
|
VIDEO_DEVICE0,
|
|
L"DefaultSettings.BitsPerPel",
|
|
ULONG_VALUE(b)
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// Set the vertical refresh.
|
|
//
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyDisplayService,
|
|
VIDEO_DEVICE0,
|
|
L"DefaultSettings.VRefresh",
|
|
ULONG_VALUE(v)
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// Set the interlaced flag.
|
|
//
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyDisplayService,
|
|
VIDEO_DEVICE0,
|
|
L"DefaultSettings.Interlaced",
|
|
ULONG_VALUE(i)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ZwClose(hKeyDisplayService);
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpConfigureNlsParameters(
|
|
IN PVOID SifHandle,
|
|
IN HANDLE hKeyDefaultHive,
|
|
IN HANDLE hKeyControlSetControl
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine configures NLS-related stuff in the registry:
|
|
|
|
- a keyboard layout
|
|
- the primary ansi, oem, and mac codepages
|
|
- the language casetable
|
|
- the oem hal font
|
|
|
|
Arguments:
|
|
|
|
SifHandle - supplies handle to open setup information file.
|
|
|
|
hKeyDefaultHive - supplies handle to root of default user hive.
|
|
|
|
hKeyControlSetControl - supplies handle to the Control subkey of
|
|
the control set being operated on.
|
|
|
|
Return Value:
|
|
|
|
Status value indicating outcome of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHARDWARE_COMPONENT_FILE HwFile;
|
|
PWSTR LayoutId;
|
|
NTSTATUS Status;
|
|
HANDLE hKeyNls;
|
|
PWSTR OemHalFont;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
//
|
|
// We don't allow third-party keyboard layouts.
|
|
//
|
|
ASSERT(!HardwareComponents[HwComponentLayout]->ThirdPartyOptionSelected);
|
|
|
|
//
|
|
// Make an entry in the keyboard layout section in the default user hive.
|
|
// This will match an entry in HKLM\CCS\Control\Nls\Keyboard Layouts,
|
|
// which is 'preloaded' with all the possible layouts.
|
|
//
|
|
if( !PreInstall ||
|
|
(PreinstallHardwareComponents[HwComponentLayout] == NULL) ) {
|
|
LayoutId = HardwareComponents[HwComponentLayout]->IdString;
|
|
} else {
|
|
LayoutId = PreinstallHardwareComponents[HwComponentLayout]->IdString;
|
|
}
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyDefaultHive,
|
|
L"Keyboard Layout\\Preload",
|
|
L"1",
|
|
STRING_VALUE(LayoutId)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Open controlset\Control\Nls.
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString,L"Nls");
|
|
Obja.RootDirectory = hKeyControlSetControl;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKeyNls,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open controlset\\Control\\Nls key (%lx)\n",Status));
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Create an entry for the ansi codepage.
|
|
//
|
|
Status = SpCreateCodepageEntry(
|
|
SifHandle,
|
|
hKeyNls,
|
|
CODEPAGE_NAME,
|
|
SIF_ANSICODEPAGE,
|
|
L"ACP"
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// Create entries for the oem codepage(s).
|
|
//
|
|
Status = SpCreateCodepageEntry(
|
|
SifHandle,
|
|
hKeyNls,
|
|
CODEPAGE_NAME,
|
|
SIF_OEMCODEPAGE,
|
|
L"OEMCP"
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// Create an entry for the mac codepage.
|
|
//
|
|
Status = SpCreateCodepageEntry(
|
|
SifHandle,
|
|
hKeyNls,
|
|
CODEPAGE_NAME,
|
|
SIF_MACCODEPAGE,
|
|
L"MACCP"
|
|
);
|
|
}
|
|
}
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
//
|
|
// Create an entry for the oem hal font.
|
|
//
|
|
|
|
OemHalFont = SpGetSectionKeyIndex(SifHandle,SIF_NLS,SIF_OEMHALFONT,0);
|
|
if(!OemHalFont) {
|
|
SpFatalSifError(SifHandle,SIF_NLS,SIF_OEMHALFONT,0,0);
|
|
}
|
|
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyNls,
|
|
CODEPAGE_NAME,
|
|
L"OEMHAL",
|
|
STRING_VALUE(OemHalFont)
|
|
);
|
|
}
|
|
|
|
//
|
|
// Create an entry for the language case table.
|
|
//
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
Status = SpCreateCodepageEntry(
|
|
SifHandle,
|
|
hKeyNls,
|
|
L"Language",
|
|
SIF_UNICODECASETABLE,
|
|
L"Default"
|
|
);
|
|
}
|
|
|
|
ZwClose(hKeyNls);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpCreateCodepageEntry(
|
|
IN PVOID SifHandle,
|
|
IN HANDLE hKeyNls,
|
|
IN PWSTR SubkeyName,
|
|
IN PWSTR SifNlsSectionKeyName,
|
|
IN PWSTR EntryName
|
|
)
|
|
{
|
|
PWSTR Filename,Identifier;
|
|
NTSTATUS Status;
|
|
ULONG value = 0;
|
|
PWSTR DefaultIdentifier = NULL;
|
|
|
|
while(Filename = SpGetSectionKeyIndex(SifHandle,SIF_NLS,SifNlsSectionKeyName,value)) {
|
|
|
|
value++;
|
|
|
|
Identifier = SpGetSectionKeyIndex(SifHandle,SIF_NLS,SifNlsSectionKeyName,value);
|
|
if(!Identifier) {
|
|
SpFatalSifError(SifHandle,SIF_NLS,SifNlsSectionKeyName,0,value);
|
|
}
|
|
|
|
//
|
|
// Remember first identifier.
|
|
//
|
|
if(DefaultIdentifier == NULL) {
|
|
DefaultIdentifier = Identifier;
|
|
}
|
|
|
|
value++;
|
|
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyNls,
|
|
SubkeyName,
|
|
Identifier,
|
|
STRING_VALUE(Filename)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
return(Status);
|
|
}
|
|
}
|
|
|
|
if(!value) {
|
|
SpFatalSifError(SifHandle,SIF_NLS,SifNlsSectionKeyName,0,0);
|
|
}
|
|
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyNls,
|
|
SubkeyName,
|
|
EntryName,
|
|
STRING_VALUE(DefaultIdentifier)
|
|
);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpConfigureFonts(
|
|
IN PVOID SifHandle,
|
|
IN HANDLE hKeySoftwareHive
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prepare a list of fonts for use with Windows.
|
|
|
|
This routine runs down a list of fonts stored in the setup information
|
|
file and adds each one to the registry, in the area that shadows the
|
|
[Fonts] section of win.ini (HKEY_LOCAL_MACHINE\Software\Microsoft\
|
|
Windows NT\CurrentVersion\Fonts).
|
|
|
|
Eventually it will add the correct resolution (96 or 120 dpi)
|
|
fonts but for now it only deals with the 96 dpi fonts.
|
|
|
|
Arguments:
|
|
|
|
SifHandle - supplies a handle to the open text setup information file.
|
|
|
|
hKeySoftwareHive - supplies handle to root of software registry hive.
|
|
|
|
Return Value:
|
|
|
|
Status value indicating outcome of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS Status;
|
|
HANDLE hKey;
|
|
PWSTR FontList;
|
|
PWSTR FontName;
|
|
PWSTR FontDescription;
|
|
ULONG FontCount,font;
|
|
|
|
//
|
|
// Open HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts.
|
|
//
|
|
INIT_OBJA(
|
|
&Obja,
|
|
&UnicodeString,
|
|
L"Microsoft\\Windows NT\\CurrentVersion\\Fonts"
|
|
);
|
|
|
|
Obja.RootDirectory = hKeySoftwareHive;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKey,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open Fonts key (%lx)\n",Status));
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// For now always use the 96 dpi fonts.
|
|
//
|
|
FontList = L"FontListE";
|
|
|
|
//
|
|
// Process each line in the text setup information file section
|
|
// for the selected font list.
|
|
//
|
|
FontCount = SpCountLinesInSection(SifHandle,FontList);
|
|
if(!FontCount) {
|
|
SpFatalSifError(SifHandle,FontList,NULL,0,0);
|
|
}
|
|
|
|
for(font=0; font<FontCount; font++) {
|
|
|
|
//
|
|
// Fetch the description and the filename.
|
|
//
|
|
FontDescription = SpGetKeyName(SifHandle,FontList,font);
|
|
if(!FontDescription) {
|
|
SpFatalSifError(SifHandle,FontList,NULL,font,(ULONG)(-1));
|
|
}
|
|
|
|
FontName = SpGetSectionLineIndex(SifHandle,FontList,font,0);
|
|
if(!FontName) {
|
|
SpFatalSifError(SifHandle,FontList,NULL,font,0);
|
|
}
|
|
|
|
//
|
|
// Set the entry.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,FontDescription);
|
|
|
|
Status = ZwSetValueKey(hKey,&UnicodeString,0,STRING_VALUE(FontName));
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set %ws to %ws (%lx)\n",FontDescription,FontName,Status));
|
|
break;
|
|
}
|
|
}
|
|
|
|
ZwClose(hKey);
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpStoreHwInfoForSetup(
|
|
IN HANDLE hKeyControlSetControl
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine stored information in the registry which will be used by
|
|
GUI setup to determine which options for mouse, display, and keyboard
|
|
are currently selected.
|
|
|
|
The data is stored in HKEY_LOCAL_MACHINE\System\<control set>\Control\Setup
|
|
in values pointer, video, and keyboard.
|
|
|
|
Arguments:
|
|
|
|
hKeyControlSetControl - supplies handle to open key
|
|
HKEY_LOCAL_MACHINE\System\<Control Set>\Control.
|
|
|
|
Return Value:
|
|
|
|
Status value indicating outcome of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
ASSERT(HardwareComponents[HwComponentMouse]->IdString);
|
|
ASSERT(HardwareComponents[HwComponentDisplay]->IdString);
|
|
ASSERT(HardwareComponents[HwComponentKeyboard]->IdString);
|
|
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyControlSetControl,
|
|
SETUP_KEY_NAME,
|
|
L"pointer",
|
|
STRING_VALUE(HardwareComponents[HwComponentMouse]->IdString)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set control\\setup\\pointer value (%lx)\n",Status));
|
|
return(Status);
|
|
}
|
|
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyControlSetControl,
|
|
SETUP_KEY_NAME,
|
|
L"video",
|
|
STRING_VALUE(HardwareComponents[HwComponentDisplay]->IdString)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set control\\setup\\video value (%lx)\n",Status));
|
|
return(Status);
|
|
}
|
|
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyControlSetControl,
|
|
SETUP_KEY_NAME,
|
|
L"keyboard",
|
|
STRING_VALUE(HardwareComponents[HwComponentKeyboard]->IdString)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set control\\setup\\keyboard value (%lx)\n",Status));
|
|
return(Status);
|
|
}
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpOpenSetValueAndClose(
|
|
IN HANDLE hKeyRoot,
|
|
IN PWSTR SubKeyName, OPTIONAL
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID Value,
|
|
IN ULONG ValueSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Open a subkey, set a value in it, and close the subkey.
|
|
The subkey will be created if it does not exist.
|
|
|
|
Arguments:
|
|
|
|
hKeyRoot - supplies handle to an open registry key.
|
|
|
|
SubKeyName - supplies path relative to hKeyRoot for key in which
|
|
the value is to be set. If this is not specified, then the value
|
|
is set in hKeyRoot.
|
|
|
|
ValueName - supplies the name of the value to be set.
|
|
|
|
ValueType - supplies the data type for the value to be set.
|
|
|
|
Value - supplies a buffer containing the value data.
|
|
|
|
ValueSize - supplies the size of the buffer pointed to by Value.
|
|
|
|
Return Value:
|
|
|
|
Status value indicating outcome of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
HANDLE hSubKey;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Open or create the subkey in which we want to set the value.
|
|
//
|
|
if(SubKeyName) {
|
|
INIT_OBJA(&Obja,&UnicodeString,SubKeyName);
|
|
Obja.RootDirectory = hKeyRoot;
|
|
|
|
Status = ZwCreateKey(
|
|
&hSubKey,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open subkey %ws (%lx)\n",SubKeyName,Status));
|
|
return(Status);
|
|
}
|
|
} else {
|
|
hSubKey = hKeyRoot;
|
|
}
|
|
|
|
//
|
|
// Set the value.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,ValueName);
|
|
|
|
Status = ZwSetValueKey(
|
|
hSubKey,
|
|
&UnicodeString,
|
|
0,
|
|
ValueType,
|
|
Value,
|
|
ValueSize
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set value %ws:%ws (%lx)\n",SubKeyName,ValueName,Status));
|
|
}
|
|
|
|
if(SubKeyName) {
|
|
ZwClose(hSubKey);
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpCreateServiceEntryIndirect(
|
|
IN HANDLE hKeyControlSetServices,
|
|
IN PVOID SifHandle, OPTIONAL
|
|
IN PWSTR SifSectionName, OPTIONAL
|
|
IN PWSTR KeyName,
|
|
IN ULONG ServiceType,
|
|
IN ULONG ServiceStart,
|
|
IN PWSTR ServiceGroup,
|
|
IN ULONG ServiceError,
|
|
IN PWSTR FileName, OPTIONAL
|
|
OUT PHANDLE SubkeyHandle OPTIONAL
|
|
)
|
|
{
|
|
HANDLE hKeyService;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
NTSTATUS Status;
|
|
UNICODE_STRING UnicodeString;
|
|
PWSTR pwstr;
|
|
|
|
//
|
|
// Look in the sif file to get the subkey name within the
|
|
// services list, unless the key name specified by the caller
|
|
// is the actual key name.
|
|
//
|
|
if(SifHandle) {
|
|
pwstr = SpGetSectionKeyIndex(SifHandle,SifSectionName,KeyName,INDEX_INFKEYNAME);
|
|
if(!pwstr) {
|
|
SpFatalSifError(SifHandle,SifSectionName,KeyName,0,INDEX_INFKEYNAME);
|
|
}
|
|
KeyName = pwstr;
|
|
}
|
|
|
|
//
|
|
// Create the subkey in the services key.
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString,KeyName);
|
|
Obja.RootDirectory = hKeyControlSetServices;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKeyService,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open/create key for %ws service (%lx)\n",KeyName,Status));
|
|
goto spcsie1;
|
|
}
|
|
|
|
//
|
|
// Set the service type.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,L"Type");
|
|
|
|
Status = ZwSetValueKey(
|
|
hKeyService,
|
|
&UnicodeString,
|
|
0,
|
|
ULONG_VALUE(ServiceType)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set service %ws Type (%lx)\n",KeyName,Status));
|
|
goto spcsie1;
|
|
}
|
|
|
|
//
|
|
// Set the service start type.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,L"Start");
|
|
|
|
Status = ZwSetValueKey(
|
|
hKeyService,
|
|
&UnicodeString,
|
|
0,
|
|
ULONG_VALUE(ServiceStart)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set service %ws Start (%lx)\n",KeyName,Status));
|
|
goto spcsie1;
|
|
}
|
|
|
|
//
|
|
// Set the service group name.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,L"Group");
|
|
|
|
Status = ZwSetValueKey(
|
|
hKeyService,
|
|
&UnicodeString,
|
|
0,
|
|
STRING_VALUE(ServiceGroup)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set service %ws Group (%lx)\n",KeyName,Status));
|
|
goto spcsie1;
|
|
}
|
|
|
|
//
|
|
// Set the service error type.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,L"ErrorControl");
|
|
|
|
Status = ZwSetValueKey(
|
|
hKeyService,
|
|
&UnicodeString,
|
|
0,
|
|
ULONG_VALUE(ServiceError)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set service %ws ErrorControl (%lx)\n",KeyName,Status));
|
|
goto spcsie1;
|
|
}
|
|
|
|
//
|
|
// If asked to do so, set the service image path.
|
|
//
|
|
if(FileName) {
|
|
|
|
pwstr = (PWSTR)TemporaryBuffer;
|
|
wcscpy(pwstr,L"system32\\drivers");
|
|
SpConcatenatePaths(pwstr,FileName);
|
|
|
|
RtlInitUnicodeString(&UnicodeString,L"ImagePath");
|
|
|
|
Status = ZwSetValueKey(hKeyService,&UnicodeString,0,STRING_VALUE(pwstr));
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
|
|
KdPrint(("SETUP: Unable to set service %w image path (%lx)\n",KeyName,Status));
|
|
goto spcsie1;
|
|
}
|
|
} else {
|
|
if(NTUpgrade == UpgradeFull) {
|
|
//
|
|
// Delete imagepath on upgrade. This makes sure we are getting
|
|
// our driver, and from the right place. Fixes Compaq's SSD stuff,
|
|
// for example. Do something similar for PlugPlayServiceType, in case
|
|
// we are renabling a device that the user disabled (in which case
|
|
// the PlugPlayServiceType could cause us to fail to make up a
|
|
// device instance for a legacy device, and cause the driver to fail
|
|
// to load/initialize.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,L"ImagePath");
|
|
Status = ZwDeleteValueKey(hKeyService,&UnicodeString);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to remove imagepath from service %ws (%lx)\n",KeyName,Status));
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
RtlInitUnicodeString(&UnicodeString,L"PlugPlayServiceType");
|
|
Status = ZwDeleteValueKey(hKeyService,&UnicodeString);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to remove plugplayservicetype from service %ws (%lx)\n",KeyName,Status));
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the caller doesn't want the handle to the service subkey
|
|
// we just created, close the handle. If we are returning an
|
|
// error, always close it.
|
|
//
|
|
spcsie1:
|
|
if(NT_SUCCESS(Status) && SubkeyHandle) {
|
|
*SubkeyHandle = hKeyService;
|
|
} else {
|
|
ZwClose(hKeyService);
|
|
}
|
|
|
|
//
|
|
// Done.
|
|
//
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpThirdPartyRegistry(
|
|
IN PVOID hKeyControlSetServices
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS Status;
|
|
HANDLE hKeyEventLogSystem;
|
|
HwComponentType Component;
|
|
PHARDWARE_COMPONENT Dev;
|
|
PHARDWARE_COMPONENT_REGISTRY Reg;
|
|
PHARDWARE_COMPONENT_FILE File;
|
|
WCHAR NodeName[9];
|
|
ULONG DriverType;
|
|
ULONG DriverStart;
|
|
ULONG DriverErrorControl;
|
|
PWSTR DriverGroup;
|
|
HANDLE hKeyService;
|
|
|
|
//
|
|
// Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\System
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString,L"EventLog\\System");
|
|
Obja.RootDirectory = hKeyControlSetServices;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKeyEventLogSystem,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: SpThirdPartyRegistry: couldn't open eventlog\\system (%lx)",Status));
|
|
return(Status);
|
|
}
|
|
|
|
for(Component=0; Component<=HwComponentMax; Component++) {
|
|
|
|
// no registry stuff applicable to keyboard layout
|
|
if(Component == HwComponentLayout) {
|
|
continue;
|
|
}
|
|
|
|
Dev = (Component == HwComponentMax)
|
|
? ((!PreInstall ||
|
|
(PreinstallScsiHardware==NULL))? ScsiHardware :
|
|
PreinstallScsiHardware)
|
|
: ((!PreInstall ||
|
|
(PreinstallHardwareComponents[Component]==NULL))? HardwareComponents[Component] :
|
|
PreinstallHardwareComponents[Component]);
|
|
|
|
for( ; Dev; Dev = Dev->Next) {
|
|
|
|
//
|
|
// If there is no third-party option selected here, then skip
|
|
// the component.
|
|
//
|
|
|
|
if(!Dev->ThirdPartyOptionSelected) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Iterate through the files for this device. If a file has
|
|
// a ServiceKeyName, create the key and add values in it
|
|
// as appropriate.
|
|
//
|
|
|
|
for(File=Dev->Files; File; File=File->Next) {
|
|
|
|
HwFileType filetype = File->FileType;
|
|
PWSTR p;
|
|
ULONG dw;
|
|
|
|
//
|
|
// If there is to be no node for this file, skip it.
|
|
//
|
|
if(!File->ConfigName) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Calculate the node name. This is the name of the driver
|
|
// without the extension.
|
|
//
|
|
wcsncpy(NodeName,File->Filename,8);
|
|
NodeName[8] = 0;
|
|
if(p = wcschr(NodeName,L'.')) {
|
|
*p = 0;
|
|
}
|
|
|
|
//
|
|
// The driver type and error control are always the same.
|
|
//
|
|
DriverType = SERVICE_KERNEL_DRIVER;
|
|
DriverErrorControl = SERVICE_ERROR_NORMAL;
|
|
|
|
//
|
|
// The start type depends on the component.
|
|
// For scsi, it's boot loader start. For others, it's
|
|
// system start.
|
|
//
|
|
DriverStart = (Component == HwComponentMax)
|
|
? SERVICE_BOOT_START
|
|
: SERVICE_SYSTEM_START;
|
|
|
|
//
|
|
// The group depends on the component.
|
|
//
|
|
switch(Component) {
|
|
|
|
case HwComponentDisplay:
|
|
DriverGroup = L"Video";
|
|
break;
|
|
|
|
case HwComponentMouse:
|
|
if(filetype == HwFileClass) {
|
|
DriverGroup = L"Pointer Class";
|
|
} else {
|
|
DriverGroup = L"Pointer Port";
|
|
}
|
|
break;
|
|
|
|
case HwComponentKeyboard:
|
|
if(filetype == HwFileClass) {
|
|
DriverGroup = L"Keyboard Class";
|
|
} else {
|
|
DriverGroup = L"Keyboard Port";
|
|
}
|
|
break;
|
|
|
|
case HwComponentMax:
|
|
DriverGroup = L"SCSI miniport";
|
|
break;
|
|
|
|
default:
|
|
DriverGroup = L"Base";
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Attempt to create the service entry.
|
|
//
|
|
Status = SpCreateServiceEntryIndirect(
|
|
hKeyControlSetServices,
|
|
NULL,
|
|
NULL,
|
|
NodeName,
|
|
DriverType,
|
|
DriverStart,
|
|
DriverGroup,
|
|
DriverErrorControl,
|
|
File->Filename,
|
|
&hKeyService
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto sp3reg1;
|
|
}
|
|
|
|
//
|
|
// Create a default eventlog configuration.
|
|
//
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyEventLogSystem,
|
|
NodeName,
|
|
L"EventMessageFile",
|
|
REG_EXPAND_SZ,
|
|
DEFAULT_EVENT_LOG,
|
|
(wcslen(DEFAULT_EVENT_LOG)+1)*sizeof(WCHAR)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: SpThirdPartyRegistry: unable to set eventlog %ws EventMessageFile",NodeName));
|
|
ZwClose(hKeyService);
|
|
goto sp3reg1;
|
|
}
|
|
|
|
dw = 7;
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyEventLogSystem,
|
|
NodeName,
|
|
L"TypesSupported",
|
|
ULONG_VALUE(dw)
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: SpThirdPartyRegistry: unable to set eventlog %ws TypesSupported",NodeName));
|
|
ZwClose(hKeyService);
|
|
goto sp3reg1;
|
|
}
|
|
|
|
|
|
for(Reg=File->RegistryValueList; Reg; Reg=Reg->Next) {
|
|
|
|
//
|
|
// If the key name is null or empty, there is no key to create;
|
|
// use the load list node itself in this case. Otherwise create
|
|
// the subkey in the load list node.
|
|
//
|
|
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyService,
|
|
(Reg->KeyName && *Reg->KeyName) ? Reg->KeyName : NULL,
|
|
Reg->ValueName,
|
|
Reg->ValueType,
|
|
Reg->Buffer,
|
|
Reg->BufferSize
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
|
|
KdPrint((
|
|
"SETUP: SpThirdPartyRegistry: unable to set value %ws (%lx)\n",
|
|
Reg->ValueName,
|
|
Status
|
|
));
|
|
|
|
ZwClose(hKeyService);
|
|
goto sp3reg1;
|
|
}
|
|
}
|
|
|
|
ZwClose(hKeyService);
|
|
}
|
|
}
|
|
}
|
|
|
|
sp3reg1:
|
|
|
|
ZwClose(hKeyEventLogSystem);
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpDetermineProduct(
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR SystemRoot,
|
|
OUT PNT_PRODUCT_TYPE ProductType,
|
|
OUT ULONG *MajorVersion,
|
|
OUT ULONG *MinorVersion,
|
|
OUT UPG_PROGRESS_TYPE *UpgradeProgressValue,
|
|
OUT PWSTR *UniqueIdFromReg, OPTIONAL
|
|
OUT PWSTR *Pid OPTIONAL
|
|
)
|
|
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS Status, TempStatus;
|
|
|
|
PWSTR Hive,HiveKey;
|
|
PUCHAR buffer;
|
|
#define BUFFERSIZE (sizeof(KEY_VALUE_PARTIAL_INFORMATION)+256)
|
|
|
|
BOOLEAN HiveLoaded = FALSE;
|
|
PWSTR PartitionPath = NULL;
|
|
HANDLE hKeyRoot = NULL, hKeyCCSet = NULL;
|
|
|
|
ULONG ResultLength;
|
|
// #if 0
|
|
//
|
|
// BUGBUG - REMOVE THIS VARIABLE AFTER CAIRO AND NT 3.51 ARE MERGED.
|
|
//
|
|
BOOLEAN CairoSystem = FALSE;
|
|
// #endif
|
|
|
|
//
|
|
// Allocate buffers.
|
|
//
|
|
Hive = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
|
|
HiveKey = SpMemAlloc(MAX_PATH * sizeof(WCHAR));
|
|
buffer = SpMemAlloc(BUFFERSIZE);
|
|
|
|
//
|
|
// Get the name of the target patition.
|
|
//
|
|
SpNtNameFromRegion(
|
|
TargetRegion,
|
|
(PWSTR)TemporaryBuffer,
|
|
sizeof(TemporaryBuffer),
|
|
PartitionOrdinalCurrent
|
|
);
|
|
|
|
PartitionPath = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
|
|
//
|
|
// Load the system hive
|
|
//
|
|
|
|
wcscpy(Hive,PartitionPath);
|
|
SpConcatenatePaths(Hive,SystemRoot);
|
|
SpConcatenatePaths(Hive,L"system32\\config");
|
|
SpConcatenatePaths(Hive,L"system");
|
|
|
|
//
|
|
// Form the path of the key into which we will
|
|
// load the hive. We'll use the convention that
|
|
// a hive will be loaded into \registry\machine\x<hivename>.
|
|
//
|
|
|
|
wcscpy(HiveKey,LOCAL_MACHINE_KEY_NAME);
|
|
SpConcatenatePaths(HiveKey,L"x");
|
|
wcscat(HiveKey,L"system");
|
|
|
|
//
|
|
// Attempt to load the key.
|
|
//
|
|
Status = SpLoadUnloadKey(NULL,NULL,HiveKey,Hive);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to load hive %ws to key %ws (%lx)\n",Hive,HiveKey,Status));
|
|
goto spdp_1;
|
|
}
|
|
HiveLoaded = TRUE;
|
|
|
|
|
|
//
|
|
// Now get a key to the root of the hive we just loaded.
|
|
//
|
|
|
|
INIT_OBJA(&Obja,&UnicodeString,HiveKey);
|
|
Status = ZwOpenKey(&hKeyRoot,KEY_ALL_ACCESS,&Obja);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open %ws (%lx)\n",HiveKey,Status));
|
|
goto spdp_2;
|
|
}
|
|
|
|
//
|
|
// Get the unique identifier if needed.
|
|
// This value is not always present.
|
|
//
|
|
if(UniqueIdFromReg) {
|
|
|
|
*UniqueIdFromReg = NULL;
|
|
|
|
Status = SpGetValueKey(
|
|
hKeyRoot,
|
|
SETUP_KEY_NAME,
|
|
SIF_UNIQUEID,
|
|
BUFFERSIZE,
|
|
buffer,
|
|
&ResultLength
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
*UniqueIdFromReg = SpDupStringW((PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data));
|
|
}
|
|
// no error if not found.
|
|
}
|
|
|
|
//
|
|
// See if this is a failed upgrade
|
|
//
|
|
*UpgradeProgressValue = UpgradeNotInProgress;
|
|
Status = SpGetValueKey(
|
|
hKeyRoot,
|
|
SETUP_KEY_NAME,
|
|
UPGRADE_IN_PROGRESS,
|
|
BUFFERSIZE,
|
|
buffer,
|
|
&ResultLength
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
DWORD dw;
|
|
if( (dw = *(DWORD *)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data)) < UpgradeMaxValue ) {
|
|
*UpgradeProgressValue = (UPG_PROGRESS_TYPE)dw;
|
|
}
|
|
}
|
|
// #if 0
|
|
//
|
|
// BUGBUG - THIS PIECE OF CODE SHOULD BE REMOVED WHEN CAIRO AND NT 3.51 ARE MERGED
|
|
// THIS CODE WILL PREVENT TEXTMODE SETUP FROM FINDING NT 3.x SYSTEMS
|
|
// WHEN IT IS INSTALLING CAIRO
|
|
//
|
|
//
|
|
// If installing Cairo, find out if the system being examined
|
|
// is NT 3.x or Cairo
|
|
//
|
|
if( CairoSetup ) {
|
|
Status = SpGetValueKey(
|
|
hKeyRoot,
|
|
SETUP_KEY_NAME,
|
|
L"CairoSystem",
|
|
BUFFERSIZE,
|
|
buffer,
|
|
&ResultLength
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
DWORD dw;
|
|
if(
|
|
(dw = *(DWORD *)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data)) == 1
|
|
) {
|
|
CairoSystem = TRUE;
|
|
}
|
|
}
|
|
}
|
|
// #endif
|
|
|
|
//
|
|
// Get the key to the current control set
|
|
//
|
|
|
|
Status = SpGetCurrentControlSetKey(hKeyRoot, KEY_READ, &hKeyCCSet);
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto spdp_3;
|
|
}
|
|
|
|
//
|
|
// Get the Product type field
|
|
//
|
|
|
|
Status = SpGetValueKey(
|
|
hKeyCCSet,
|
|
L"Control\\ProductOptions",
|
|
L"ProductType",
|
|
BUFFERSIZE,
|
|
buffer,
|
|
&ResultLength
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
goto spdp_3;
|
|
}
|
|
|
|
if( _wcsicmp( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data), L"WinNT" ) == 0 ) {
|
|
*ProductType = NtProductWinNt;
|
|
} else if( _wcsicmp( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data), L"LanmanNt" ) == 0 ) {
|
|
*ProductType = NtProductLanManNt;
|
|
} else if( _wcsicmp( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data), L"ServerNt" ) == 0 ) {
|
|
*ProductType = NtProductServer;
|
|
} else {
|
|
KdPrint(( "SETUP: Error, unknown ProductType = %ls. Assuming WinNt \n",
|
|
(PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data) ));
|
|
*ProductType = NtProductWinNt;
|
|
}
|
|
|
|
//
|
|
// Close the hive key
|
|
//
|
|
|
|
ZwClose( hKeyCCSet );
|
|
ZwClose( hKeyRoot );
|
|
hKeyRoot = NULL;
|
|
hKeyCCSet = NULL;
|
|
|
|
//
|
|
// Unload the system hive
|
|
//
|
|
|
|
TempStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL);
|
|
if(!NT_SUCCESS(TempStatus)) {
|
|
KdPrint(("SETUP: warning: unable to unload key %ws (%lx)\n",HiveKey,TempStatus));
|
|
}
|
|
HiveLoaded = FALSE;
|
|
|
|
//
|
|
// Load the software hive
|
|
//
|
|
|
|
wcscpy(Hive,PartitionPath);
|
|
SpConcatenatePaths(Hive,SystemRoot);
|
|
SpConcatenatePaths(Hive,L"system32\\config");
|
|
SpConcatenatePaths(Hive,L"software");
|
|
|
|
//
|
|
// Form the path of the key into which we will
|
|
// load the hive. We'll use the convention that
|
|
// a hive will be loaded into \registry\machine\x<hivename>.
|
|
//
|
|
|
|
wcscpy(HiveKey,LOCAL_MACHINE_KEY_NAME);
|
|
SpConcatenatePaths(HiveKey,L"x");
|
|
wcscat(HiveKey,L"software");
|
|
|
|
//
|
|
// Attempt to load the key.
|
|
//
|
|
Status = SpLoadUnloadKey(NULL,NULL,HiveKey,Hive);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to load hive %ws to key %ws (%lx)\n",Hive,HiveKey,Status));
|
|
goto spdp_1;
|
|
}
|
|
HiveLoaded = TRUE;
|
|
|
|
//
|
|
// Now get a key to the root of the hive we just loaded.
|
|
//
|
|
|
|
INIT_OBJA(&Obja,&UnicodeString,HiveKey);
|
|
Status = ZwOpenKey(&hKeyRoot,KEY_ALL_ACCESS,&Obja);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open %ws (%lx)\n",HiveKey,Status));
|
|
goto spdp_2;
|
|
}
|
|
|
|
//
|
|
// Query the version of the NT
|
|
//
|
|
|
|
Status = SpGetValueKey(
|
|
hKeyRoot,
|
|
L"Microsoft\\Windows NT\\CurrentVersion",
|
|
L"CurrentVersion",
|
|
BUFFERSIZE,
|
|
buffer,
|
|
&ResultLength
|
|
);
|
|
|
|
//
|
|
// Convert the version into a dword
|
|
//
|
|
|
|
{
|
|
WCHAR wcsMajorVersion[] = L"0";
|
|
WCHAR wcsMinorVersion[] = L"00";
|
|
PWSTR Version = (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data);
|
|
if( Version[0] && Version[1] && Version[2] ) {
|
|
wcsMajorVersion[0] = Version[0];
|
|
wcsMinorVersion[0] = Version[2];
|
|
if( Version[3] ) {
|
|
wcsMinorVersion[1] = Version[3];
|
|
}
|
|
}
|
|
*MajorVersion = (ULONG)SpStringToLong( wcsMajorVersion, NULL, 10 );
|
|
*MinorVersion = (ULONG)SpStringToLong( wcsMinorVersion, NULL, 10 );
|
|
// #if 0
|
|
//
|
|
// BUGBUG - REMOVE THIS PIECE OF CODE AFTER CAIRO AND NT 3.x ARE MEREGED
|
|
// THIS CODE WILL PREVENT TEXTMODE SETUP FROM FINDING NT 3.x
|
|
// WHEN IT IS INSTALLING CAIRO
|
|
//
|
|
// If installing Cairo, and the system being examined is also Cairo,
|
|
// then change its major and minor versions.
|
|
// Note that this is a big hack, since we cannot these values in
|
|
// the registry, without changing all hardcoded product version
|
|
// in the .inf files.
|
|
//
|
|
if( CairoSystem ) {
|
|
*MajorVersion = 5;
|
|
*MinorVersion = 0;
|
|
}
|
|
// #endif
|
|
}
|
|
|
|
//
|
|
// Query the PID, if requested
|
|
//
|
|
|
|
if( Pid != NULL ) {
|
|
TempStatus = SpGetValueKey(
|
|
hKeyRoot,
|
|
L"Microsoft\\Windows NT\\CurrentVersion",
|
|
L"ProductId",
|
|
BUFFERSIZE,
|
|
buffer,
|
|
&ResultLength
|
|
);
|
|
|
|
if(!NT_SUCCESS(TempStatus)) {
|
|
//
|
|
// If unable to read PID, assume empty string
|
|
//
|
|
KdPrint(("SETUP: Unable to query PID from hive %ws. Status = (%lx)\n",Hive,TempStatus));
|
|
*Pid = SpDupStringW( L"" );
|
|
} else {
|
|
*Pid = SpDupStringW( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data) );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Let the following do the cleaning up
|
|
|
|
spdp_3:
|
|
|
|
if( hKeyCCSet ) {
|
|
ZwClose( hKeyCCSet );
|
|
}
|
|
|
|
if( hKeyRoot ) {
|
|
ZwClose(hKeyRoot);
|
|
}
|
|
|
|
|
|
spdp_2:
|
|
|
|
|
|
//
|
|
// Unload the currently loaded hive.
|
|
//
|
|
|
|
if( HiveLoaded ) {
|
|
TempStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL);
|
|
if(!NT_SUCCESS(TempStatus)) {
|
|
KdPrint(("SETUP: warning: unable to unload key %ws (%lx)\n",HiveKey,TempStatus));
|
|
}
|
|
}
|
|
|
|
spdp_1:
|
|
SpMemFree(PartitionPath);
|
|
|
|
SpMemFree(Hive);
|
|
SpMemFree(HiveKey);
|
|
SpMemFree(buffer);
|
|
|
|
return( Status );
|
|
#undef BUFFERSIZE
|
|
}
|
|
|
|
NTSTATUS
|
|
SpSetUpgradeStatus(
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR SystemRoot,
|
|
IN UPG_PROGRESS_TYPE UpgradeProgressValue
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS Status, TempStatus;
|
|
|
|
WCHAR Hive[MAX_PATH], HiveKey[MAX_PATH];
|
|
BOOLEAN HiveLoaded = FALSE;
|
|
PWSTR PartitionPath = NULL;
|
|
HANDLE hKeySystemHive;
|
|
DWORD dw;
|
|
|
|
//
|
|
// Get the name of the target patition.
|
|
//
|
|
SpNtNameFromRegion(
|
|
TargetRegion,
|
|
(PWSTR)TemporaryBuffer,
|
|
sizeof(TemporaryBuffer),
|
|
PartitionOrdinalCurrent
|
|
);
|
|
|
|
PartitionPath = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
|
|
//
|
|
// Load the system hive
|
|
//
|
|
|
|
wcscpy(Hive,PartitionPath);
|
|
SpConcatenatePaths(Hive,SystemRoot);
|
|
SpConcatenatePaths(Hive,L"system32\\config");
|
|
SpConcatenatePaths(Hive,L"system");
|
|
|
|
//
|
|
// Form the path of the key into which we will
|
|
// load the hive. We'll use the convention that
|
|
// a hive will be loaded into \registry\machine\x<hivename>.
|
|
//
|
|
|
|
wcscpy(HiveKey,LOCAL_MACHINE_KEY_NAME);
|
|
SpConcatenatePaths(HiveKey,L"x");
|
|
wcscat(HiveKey,L"system");
|
|
|
|
//
|
|
// Attempt to load the key.
|
|
//
|
|
Status = SpLoadUnloadKey(NULL,NULL,HiveKey,Hive);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to load hive %ws to key %ws (%lx)\n",Hive,HiveKey,Status));
|
|
goto spus_1;
|
|
}
|
|
HiveLoaded = TRUE;
|
|
|
|
|
|
//
|
|
// Now get a key to the root of the hive we just loaded.
|
|
//
|
|
|
|
INIT_OBJA(&Obja,&UnicodeString,HiveKey);
|
|
Status = ZwOpenKey(&hKeySystemHive,KEY_ALL_ACCESS,&Obja);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open %ws (%lx)\n",HiveKey,Status));
|
|
goto spus_2;
|
|
}
|
|
|
|
//
|
|
// Set the upgrade status under the setup key.
|
|
//
|
|
|
|
dw = UpgradeProgressValue;
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeySystemHive,
|
|
SETUP_KEY_NAME,
|
|
UPGRADE_IN_PROGRESS,
|
|
ULONG_VALUE(dw)
|
|
);
|
|
|
|
//
|
|
// Flush the key. Ignore the error
|
|
//
|
|
TempStatus = ZwFlushKey(hKeySystemHive);
|
|
if(!NT_SUCCESS(TempStatus)) {
|
|
KdPrint(("SETUP: ZwFlushKey %ws failed (%lx)\n",HiveKey,Status));
|
|
}
|
|
|
|
|
|
//
|
|
// Close the hive key
|
|
//
|
|
ZwClose( hKeySystemHive );
|
|
hKeySystemHive = NULL;
|
|
|
|
//
|
|
// Unload the system hive
|
|
//
|
|
|
|
TempStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL);
|
|
if(!NT_SUCCESS(TempStatus)) {
|
|
KdPrint(("SETUP: warning: unable to unload key %ws (%lx)\n",HiveKey,TempStatus));
|
|
}
|
|
HiveLoaded = FALSE;
|
|
|
|
spus_2:
|
|
|
|
//
|
|
// Unload the currently loaded hive.
|
|
//
|
|
|
|
if( HiveLoaded ) {
|
|
TempStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL);
|
|
if(!NT_SUCCESS(TempStatus)) {
|
|
KdPrint(("SETUP: warning: unable to unload key %ws (%lx)\n",HiveKey,TempStatus));
|
|
}
|
|
}
|
|
|
|
spus_1:
|
|
SpMemFree(PartitionPath);
|
|
return( Status );
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpGetCurrentControlSetKey(
|
|
IN HANDLE hKeySystem,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
OUT HANDLE *hKeyCCSet
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS Status;
|
|
HANDLE hKeySelect = NULL;
|
|
UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)+256];
|
|
ULONG ResultLength;
|
|
ULONG Num;
|
|
WCHAR CurrentControlSet[MAX_PATH];
|
|
|
|
Status = SpGetValueKey(
|
|
hKeySystem,
|
|
L"Select",
|
|
L"Current",
|
|
sizeof(buffer),
|
|
buffer,
|
|
&ResultLength
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
return( Status );
|
|
}
|
|
|
|
Num = *(DWORD *)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data);
|
|
//
|
|
// In default hive Current is 0.
|
|
//
|
|
if(!Num) {
|
|
Num = 1;
|
|
}
|
|
|
|
//
|
|
// Form the currentcontrolset key name
|
|
//
|
|
swprintf(CurrentControlSet,L"%ws%.3d",L"ControlSet",Num);
|
|
|
|
//
|
|
// Open the current control set for the desired access
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString, CurrentControlSet);
|
|
Obja.RootDirectory = hKeySystem;
|
|
Status = ZwOpenKey(hKeyCCSet,DesiredAccess,&Obja);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: SpGetCurrentControlSetKey: couldn't open currentcontrolset key (%lx)\n",Status));
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpAppendStringToMultiSz(
|
|
IN HANDLE hKey,
|
|
IN PWSTR Subkey,
|
|
IN PWSTR ValueName,
|
|
IN PWSTR StringToAdd
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG Length;
|
|
PUCHAR Data;
|
|
|
|
Status = SpGetValueKey(
|
|
hKey,
|
|
Subkey,
|
|
ValueName,
|
|
sizeof(TemporaryBuffer),
|
|
TemporaryBuffer,
|
|
&Length
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
return(Status);
|
|
}
|
|
|
|
Data = ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data;
|
|
Length = ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->DataLength;
|
|
|
|
//
|
|
// Stick on end. For a multi_sz there has to be at least
|
|
// the terminating nul, but just to be safe we'll be robust.
|
|
//
|
|
ASSERT(Length);
|
|
if(!Length) {
|
|
*(PWCHAR)Data = 0;
|
|
Length = sizeof(WCHAR);
|
|
}
|
|
|
|
//
|
|
// Append new string to end and add new terminating 0.
|
|
//
|
|
wcscpy((PWSTR)(Data+Length-sizeof(WCHAR)),StringToAdd);
|
|
Length += (wcslen(StringToAdd)+1)*sizeof(WCHAR);
|
|
*(PWCHAR)(Data+Length-sizeof(WCHAR)) = 0;
|
|
|
|
//
|
|
// Write back out to registry.
|
|
//
|
|
Status = SpOpenSetValueAndClose(
|
|
hKey,
|
|
Subkey,
|
|
ValueName,
|
|
REG_MULTI_SZ,
|
|
Data,
|
|
Length
|
|
);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpGetValueKey(
|
|
IN HANDLE hKeyRoot,
|
|
IN PWSTR KeyName,
|
|
IN PWSTR ValueName,
|
|
IN ULONG BufferLength,
|
|
OUT PUCHAR Buffer,
|
|
OUT PULONG ResultLength
|
|
)
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
NTSTATUS Status;
|
|
HANDLE hKey = NULL;
|
|
|
|
//
|
|
// Open the key for read access
|
|
//
|
|
|
|
INIT_OBJA(&Obja,&UnicodeString,KeyName);
|
|
Obja.RootDirectory = hKeyRoot;
|
|
Status = ZwOpenKey(&hKey,KEY_READ,&Obja);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: SpGetValueKey: couldn't open key %ws for read access (%lx)\n",KeyName, Status));
|
|
}
|
|
else {
|
|
//
|
|
// Find out the value of the Current value
|
|
//
|
|
|
|
RtlInitUnicodeString(&UnicodeString,ValueName);
|
|
Status = ZwQueryValueKey(
|
|
hKey,
|
|
&UnicodeString,
|
|
KeyValuePartialInformation,
|
|
Buffer,
|
|
BufferLength,
|
|
ResultLength
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: SpGetValueKey: couldn't query value %ws in key %ws in select key %ws (%lx)\n",ValueName,KeyName,Status));
|
|
}
|
|
}
|
|
|
|
if( hKey ) {
|
|
ZwClose( hKey );
|
|
}
|
|
return( Status );
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
SpDeleteValueKey(
|
|
IN HANDLE hKeyRoot,
|
|
IN PWSTR KeyName,
|
|
IN PWSTR ValueName
|
|
)
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
NTSTATUS Status;
|
|
HANDLE hKey = NULL;
|
|
|
|
//
|
|
// Open the key for read access
|
|
//
|
|
|
|
INIT_OBJA(&Obja,&UnicodeString,KeyName);
|
|
Obja.RootDirectory = hKeyRoot;
|
|
Status = ZwOpenKey(&hKey,KEY_SET_VALUE,&Obja);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: SpDeleteValueKey: couldn't open key %ws for write access (%lx)\n",KeyName, Status));
|
|
}
|
|
else {
|
|
//
|
|
// Find out the value of the Current value
|
|
//
|
|
|
|
RtlInitUnicodeString(&UnicodeString,ValueName);
|
|
Status = ZwDeleteValueKey(
|
|
hKey,
|
|
&UnicodeString
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: SpDeleteValueKey: couldn't delete value %ws in key %ws (%lx)\n",ValueName,KeyName,Status));
|
|
}
|
|
}
|
|
|
|
if( hKey ) {
|
|
ZwClose( hKey );
|
|
}
|
|
return( Status );
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpConfigurePcmcia(
|
|
IN HANDLE hKeyControlSet
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE hKeyControlSetServices;
|
|
PHARDWARE_COMPONENT ScsiHwComponent;
|
|
ULONG u;
|
|
|
|
//
|
|
// Open controlset\services.
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString,L"services");
|
|
Obja.RootDirectory = hKeyControlSet;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKeyControlSetServices,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: unable to open services key (%lx)\n",Status));
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Disable pcmcia if there are the driver didn't load.
|
|
//
|
|
u = PcmciaLoaded ? SERVICE_BOOT_START : SERVICE_DISABLED;
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeyControlSetServices,
|
|
L"Pcmcia",
|
|
L"Start",
|
|
ULONG_VALUE(u)
|
|
);
|
|
#if DBG
|
|
if(!NT_SUCCESS(Status)) {
|
|
if( PcmciaLoaded ) {
|
|
KdPrint(("SETUP: unable to enable pcmcia (%lx)\n",Status));
|
|
} else {
|
|
KdPrint(("SETUP: unable to disable pcmcia (%lx)\n",Status));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
ZwClose(hKeyControlSetServices);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
BOOLEAN
|
|
SpReadSKUStuff(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read SKU differentiation data from the setup hive we are currently
|
|
running on.
|
|
|
|
In the unnamed key of our driver node, there is a REG_BINARY that
|
|
tells us whether this is stepup mode, and/or whether this is an
|
|
evaluation unit (gives us the time in minutes).
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Boolean value indicating outcome.
|
|
If TRUE, StepUpMode and EvaluationTime globals are filled in.
|
|
If FALSE, product may have been tampered with.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
|
PULONG Values;
|
|
ULONG ResultLength;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
HKEY Key;
|
|
|
|
|
|
|
|
INIT_OBJA(&Obja,&UnicodeString,LOCAL_MACHINE_KEY_NAME);
|
|
Status = ZwOpenKey(&Key,KEY_READ,&Obja);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Failed to open %ws (Status = %lx)\n",LOCAL_MACHINE_KEY_NAME,Status));
|
|
return(FALSE);
|
|
}
|
|
|
|
Status = SpGetValueKey(
|
|
Key,
|
|
L"System\\ControlSet001\\Services\\setupdd",
|
|
L"",
|
|
sizeof(TemporaryBuffer),
|
|
TemporaryBuffer,
|
|
&ResultLength
|
|
);
|
|
|
|
ZwClose(Key);
|
|
|
|
ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer;
|
|
|
|
//
|
|
// This line of code depends on the setup hive setupreg.hiv
|
|
// (see oak\bin\setupreg.ini).
|
|
//
|
|
if(NT_SUCCESS(Status) && (ValueInfo->Type == REG_BINARY) && (ValueInfo->DataLength == 12)) {
|
|
|
|
Values = (PULONG)ValueInfo->Data;
|
|
|
|
//
|
|
// First DWORD is eval time, second is stepup boolean, third is restric cpu val
|
|
//
|
|
EvaluationTime = Values[0];
|
|
StepUpMode = (BOOLEAN)Values[1];
|
|
RestrictCpu = Values[2];
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
VOID
|
|
SpSetDirtyShutdownFlag(
|
|
IN PDISK_REGION TargetRegion,
|
|
IN PWSTR SystemRoot
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PWSTR HiveRootPath;
|
|
PWSTR HiveFilePath;
|
|
BOOLEAN HiveLoaded;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE HiveRootKey;
|
|
UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(DISK_CONFIG_HEADER)];
|
|
ULONG ResultLength;
|
|
PDISK_CONFIG_HEADER DiskHeader;
|
|
|
|
//
|
|
// Get the name of the target patition.
|
|
//
|
|
SpNtNameFromRegion(
|
|
TargetRegion,
|
|
(PWSTR)TemporaryBuffer,
|
|
sizeof(TemporaryBuffer),
|
|
PartitionOrdinalCurrent
|
|
);
|
|
|
|
//
|
|
// Form the name of the hive file.
|
|
// This is partitionpath + sysroot + system32\config + the hive name.
|
|
//
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer, SystemRoot);
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer,L"system32\\config\\system");
|
|
HiveFilePath = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
|
|
//
|
|
// Form the path of the key into which we will
|
|
// load the hive. We'll use the convention that
|
|
// a hive will be loaded into \registry\machine\x<hivename>.
|
|
//
|
|
wcscpy((PWSTR)TemporaryBuffer,LOCAL_MACHINE_KEY_NAME);
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer,L"x");
|
|
wcscat((PWSTR)TemporaryBuffer,L"system");
|
|
HiveRootPath = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
ASSERT(HiveRootPath);
|
|
|
|
//
|
|
// Attempt to load the key.
|
|
//
|
|
HiveLoaded = FALSE;
|
|
Status = SpLoadUnloadKey(NULL,NULL,HiveRootPath,HiveFilePath);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to load hive %ws to key %ws (%lx)\n",HiveFilePath,HiveRootPath,Status));
|
|
goto setdirty1;
|
|
}
|
|
|
|
HiveLoaded = TRUE;
|
|
|
|
//
|
|
// Now get a key to the root of the hive we just loaded.
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString,HiveRootPath);
|
|
Status = ZwOpenKey(&HiveRootKey,KEY_ALL_ACCESS,&Obja);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open %ws (%lx)\n",HiveRootPath,Status));
|
|
goto setdirty1;
|
|
}
|
|
|
|
//
|
|
// Make the appropriate change
|
|
//
|
|
|
|
Status = SpGetValueKey(
|
|
HiveRootKey,
|
|
L"DISK",
|
|
L"Information",
|
|
sizeof(TemporaryBuffer),
|
|
TemporaryBuffer,
|
|
&ResultLength
|
|
);
|
|
|
|
//
|
|
// TemporaryBuffer is 32kb long, and it should be big enough
|
|
// for the data.
|
|
//
|
|
ASSERT( Status != STATUS_BUFFER_OVERFLOW );
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to read value from registry. KeyName = Disk, ValueName = Information, Status = (%lx)\n",Status));
|
|
goto setdirty1;
|
|
}
|
|
|
|
DiskHeader = ( PDISK_CONFIG_HEADER )(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data);
|
|
DiskHeader->DirtyShutdown = TRUE;
|
|
|
|
Status = SpOpenSetValueAndClose( HiveRootKey,
|
|
L"DISK",
|
|
L"Information",
|
|
REG_BINARY,
|
|
DiskHeader,
|
|
((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->DataLength
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to write value to registry. KeyName = Disk, ValueName = Information, Status = (%lx)\n",Status));
|
|
goto setdirty1;
|
|
}
|
|
|
|
setdirty1:
|
|
|
|
//
|
|
// Flush the hive.
|
|
//
|
|
|
|
if(HiveLoaded && HiveRootKey) {
|
|
NTSTATUS stat;
|
|
|
|
stat = ZwFlushKey(HiveRootKey);
|
|
if(!NT_SUCCESS(stat)) {
|
|
KdPrint(("SETUP: ZwFlushKey x%ws failed (%lx)\n", HiveRootPath, Status));
|
|
}
|
|
}
|
|
|
|
if(HiveLoaded) {
|
|
|
|
//
|
|
// We don't want to disturb the value of Status
|
|
// so use a we'll different variable below.
|
|
//
|
|
NTSTATUS stat;
|
|
|
|
if(HiveRootKey!=NULL) {
|
|
ZwClose(HiveRootKey);
|
|
HiveRootKey = NULL;
|
|
}
|
|
|
|
//
|
|
// Unload the hive.
|
|
//
|
|
stat = SpLoadUnloadKey(NULL,NULL,HiveRootPath,NULL);
|
|
|
|
if(!NT_SUCCESS(stat)) {
|
|
KdPrint(("SETUP: warning: unable to unload key %ws (%lx)\n",HiveRootPath,stat));
|
|
}
|
|
|
|
HiveLoaded = FALSE;
|
|
}
|
|
|
|
SpMemFree(HiveRootPath);
|
|
SpMemFree(HiveFilePath);
|
|
|
|
//
|
|
// If we fail to set the DirtyShutdown flag, then we silently fail
|
|
// because there is nothing that the user can do about, and the system
|
|
// is unlikely to boot anyway.
|
|
// This will occur if setup fails to:
|
|
//
|
|
// - Load the system hive
|
|
// - Open System\Disk key
|
|
// - Read the value entry
|
|
// - Write the value entry
|
|
// - Unload the system hive
|
|
//
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: setup was unable to set DirtyShutdown flag. Status = (%lx)\n", Status));
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpPostprocessHives(
|
|
IN PWSTR PartitionPath,
|
|
IN PWSTR Sysroot,
|
|
IN PWSTR *HiveNames,
|
|
IN HANDLE *HiveRootKeys,
|
|
IN unsigned HiveCount
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE hKeyCCS;
|
|
ULONG u;
|
|
unsigned h;
|
|
PWSTR SaveHiveName;
|
|
PWSTR HiveName;
|
|
HANDLE SaveHiveHandle;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
OBJECT_ATTRIBUTES ObjectAttributes2;
|
|
UNICODE_STRING UnicodeString;
|
|
UNICODE_STRING UnicodeString2;
|
|
PWSTR SecurityHives[] = {
|
|
L"sam",
|
|
L"security"
|
|
};
|
|
|
|
//
|
|
// Flush all hives.
|
|
//
|
|
for(h=0; h<HiveCount; h++) {
|
|
Status = ZwFlushKey(HiveRootKeys[h]);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Warning: ZwFlushKey %ws failed (%lx)\n",HiveNames[h],Status));
|
|
}
|
|
}
|
|
|
|
//
|
|
// If GUI setup is supposed to be restartable, we need to add an entry
|
|
// to the BootExecute list, to cause sprestrt.exe to run.
|
|
// Also, we want system.sav to have a RestartSetup=TRUE value in it,
|
|
// but we want the actual system hive to have RestartSetup=FALSE.
|
|
//
|
|
if(RestartableGuiSetup) {
|
|
|
|
Status = SpGetCurrentControlSetKey(
|
|
HiveRootKeys[SetupHiveSystem],
|
|
KEY_READ | KEY_WRITE,
|
|
&hKeyCCS
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
Status = SpAppendStringToMultiSz(
|
|
hKeyCCS,
|
|
SESSION_MANAGER_KEY,
|
|
BOOT_EXECUTE,
|
|
L"sprestrt"
|
|
);
|
|
|
|
NtClose(hKeyCCS);
|
|
}
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
//
|
|
// Add a RestartSetup value, set to TRUE.
|
|
// To understand why we use a different value here in upgrade
|
|
// and non-upgrade case, see discussion below.
|
|
//
|
|
u = (NTUpgrade == UpgradeFull) ? 0 : 1;
|
|
Status = SpOpenSetValueAndClose(
|
|
HiveRootKeys[SetupHiveSystem],
|
|
SETUP_KEY_NAME,
|
|
RESTART_SETUP,
|
|
ULONG_VALUE(u)
|
|
);
|
|
}
|
|
} else {
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
//
|
|
// Save out the hives to *.sav in the initial install case,
|
|
// or *.tmp in the upgrade case.
|
|
//
|
|
for(h=0; NT_SUCCESS(Status) && (h<HiveCount); h++) {
|
|
//
|
|
// Form full pathname of hive file.
|
|
//
|
|
wcscpy((PWSTR)TemporaryBuffer,PartitionPath);
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer,Sysroot);
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer,L"system32\\config");
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer,HiveNames[h]);
|
|
wcscat((PWSTR)TemporaryBuffer,(NTUpgrade == UpgradeFull) ? L".tmp" : L".sav");
|
|
|
|
SaveHiveName = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
|
|
INIT_OBJA(&ObjectAttributes,&UnicodeString,SaveHiveName);
|
|
|
|
Status = ZwCreateFile(
|
|
&SaveHiveHandle,
|
|
FILE_GENERIC_WRITE,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0, // no sharing
|
|
FILE_OVERWRITE_IF,
|
|
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if(NT_SUCCESS(Status)) {
|
|
|
|
Status = ZwSaveKey(HiveRootKeys[h],SaveHiveHandle);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: save key into %ws failed (%lx)\n",SaveHiveName,Status));
|
|
}
|
|
|
|
ZwClose(SaveHiveHandle);
|
|
|
|
} else {
|
|
KdPrint(("SETUP: unable to create file %ws to save hive (%lx)\n",SaveHiveName,Status));
|
|
}
|
|
|
|
//
|
|
// In the upgrade case, there is significant benefit to ensuring that
|
|
// the hives are in the latest format. A hive that has been created
|
|
// via NtSaveKey() is guaranteed to be in the latest format.
|
|
// Since we just did a SaveKey, xxx.tmp is in the latest format,
|
|
// and we should use that as the xxx hive from now on. The existing
|
|
// (old-format) hive can be retained as xxx.sav.
|
|
//
|
|
// NtReplaceKey does exactly what we want, but we have to make sure
|
|
// that there is no .sav file already there, because that causes
|
|
// NtReplaceKey to fail with STATUS_OBJECT_NAME_COLLISION.
|
|
//
|
|
// After NtReplaceKey is done, the hive root keys refer to the .sav
|
|
// on-disk file but the extensionless on-disk file will be used at next
|
|
// boot. Thus we need to be careful about how we write the restart values
|
|
// into the hives.
|
|
//
|
|
if(NT_SUCCESS(Status) && (NTUpgrade == UpgradeFull)) {
|
|
|
|
HiveName = SpDupStringW(SaveHiveName);
|
|
wcscpy(HiveName+wcslen(HiveName)-3,L"sav");
|
|
|
|
SpDeleteFile(HiveName,NULL,NULL);
|
|
|
|
INIT_OBJA(&ObjectAttributes,&UnicodeString,SaveHiveName);
|
|
INIT_OBJA(&ObjectAttributes2,&UnicodeString2,HiveName);
|
|
|
|
Status = ZwReplaceKey(&ObjectAttributes,HiveRootKeys[h],&ObjectAttributes2);
|
|
}
|
|
|
|
SpMemFree(SaveHiveName);
|
|
}
|
|
}
|
|
|
|
if(NT_SUCCESS(Status) && (NTUpgrade == UpgradeFull)) {
|
|
//
|
|
// In the upgarde case, make a backup of the security
|
|
// hives. They need to be restored if the system is restartable.
|
|
//
|
|
|
|
//
|
|
// Initialize the diamond decompression engine.
|
|
// This needs to be done, because SpCopyFileUsingNames() uses
|
|
// the decompression engine.
|
|
//
|
|
SpdInitialize();
|
|
|
|
for( h = 0; h < sizeof(SecurityHives)/sizeof(PWSTR); h++ ) {
|
|
PWSTR p, q;
|
|
|
|
wcscpy((PWSTR)TemporaryBuffer,PartitionPath);
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer,Sysroot);
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer,L"system32\\config");
|
|
SpConcatenatePaths((PWSTR)TemporaryBuffer,SecurityHives[h]);
|
|
p = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
wcscat((PWSTR)TemporaryBuffer, L".sav");
|
|
q = SpDupStringW((PWSTR)TemporaryBuffer);
|
|
Status = SpCopyFileUsingNames( p, q, 0, 0 );
|
|
if( !NT_SUCCESS(Status) ) {
|
|
KdPrint(("SETUP: unable to create backup file %ws. Status = %lx\n", q, Status));
|
|
}
|
|
SpMemFree(p);
|
|
SpMemFree(q);
|
|
if( !NT_SUCCESS(Status) ) {
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Terminate diamond.
|
|
//
|
|
SpdTerminate();
|
|
}
|
|
|
|
|
|
if(NT_SUCCESS(Status) && RestartableGuiSetup) {
|
|
//
|
|
// Set RestartSetup to FALSE in mainline hive.
|
|
// To understand why we use a different value here in upgrade
|
|
// and non-upgrade case, see discussion above.
|
|
//
|
|
u = (NTUpgrade == UpgradeFull) ? 1 : 0;
|
|
Status = SpOpenSetValueAndClose(
|
|
HiveRootKeys[SetupHiveSystem],
|
|
SETUP_KEY_NAME,
|
|
RESTART_SETUP,
|
|
ULONG_VALUE(u)
|
|
);
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
#ifdef _PPC_
|
|
|
|
NTSTATUS
|
|
SpFixHiveForCarolinaMachine(
|
|
IN HANDLE hKeyControlSetServices,
|
|
IN BOOLEAN SetupHive
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Make the appropriate changes to CurrentControlSet\Services\atapi on Carolina
|
|
(IBM Power Series 6050 and 6070). This function should be called only when
|
|
installing on a Power PC, and it was detected that the machine is 6050 or 6070.
|
|
|
|
|
|
Arguments:
|
|
|
|
hKeyControlSetServices - Handle to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
|
|
|
|
SetupHive - If TRUE indicates that the changes are being made in the setup hive, and
|
|
that any key that is created should be volatile.
|
|
If false indicate that the changes are being made on the hive of the
|
|
system being installed, and any key created should be non-volatile.
|
|
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - An nt status value.
|
|
|
|
--*/
|
|
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE hKeyParameters;
|
|
HANDLE hKeyDevice;
|
|
NTSTATUS Status;
|
|
ULONG Value;
|
|
|
|
//
|
|
// Write the values to CurrentControlSet\System\Atapi\Parameters\Device0.
|
|
//
|
|
//
|
|
// First create CurrentControlSet\System\Atapi\Parameters
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,
|
|
L"Atapi\\Parameters");
|
|
InitializeObjectAttributes(&Obja,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
|
|
Obja.RootDirectory = hKeyControlSetServices;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKeyParameters,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
SetupHive? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: unable to open Atapi\\Parameters key (%lx)\n",Status));
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Now create CurrentControlSet\System\Atapi\Parameters\Device0
|
|
//
|
|
|
|
RtlInitUnicodeString(&UnicodeString,
|
|
L"Device0");
|
|
InitializeObjectAttributes(&Obja,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
|
|
Obja.RootDirectory = hKeyParameters;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKeyDevice,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
SetupHive? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: unable to open Atapi\\Parameters key (%lx)\n",Status));
|
|
ZwClose(hKeyParameters);
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Make the changes to CurrentControlSet\System\Atapi\Parameters\Device0.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,L"DriverParameter");
|
|
wcscpy((PWSTR)TemporaryBuffer, L"BaseAddress = 0x1f0; Interrupt = 0x10" );
|
|
Status = ZwSetValueKey(hKeyDevice,&UnicodeString,0,STRING_VALUE((PWSTR)TemporaryBuffer));
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set DriverParameter on Atapi\\Parameters\\Device0. Status = (%lx)\n",Status));
|
|
ZwClose(hKeyParameters);
|
|
ZwClose(hKeyDevice);
|
|
return(Status);
|
|
}
|
|
ZwClose(hKeyDevice);
|
|
|
|
//
|
|
// Now create CurrentControlSet\System\Atapi\Parameters\Device1
|
|
//
|
|
|
|
RtlInitUnicodeString(&UnicodeString,
|
|
L"Device1");
|
|
InitializeObjectAttributes(&Obja,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
|
|
Obja.RootDirectory = hKeyParameters;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKeyDevice,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
SetupHive? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
ZwClose(hKeyParameters);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: unable to open Atapi\\Parameters key (%lx)\n",Status));
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Make the changes to CurrentControlSet\System\Atapi\Parameters\Device1.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,L"DriverParameter");
|
|
wcscpy((PWSTR)TemporaryBuffer, L"BaseAddress = 0x170; Interrupt = 0x11" );
|
|
Status = ZwSetValueKey(hKeyDevice,&UnicodeString,0,STRING_VALUE((PWSTR)TemporaryBuffer));
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to set DriverParameter on Atapi\\Parameters\\Device1. Status = (%lx)\n",Status));
|
|
ZwClose(hKeyDevice);
|
|
return(Status);
|
|
}
|
|
ZwClose(hKeyDevice);
|
|
|
|
return( Status );
|
|
}
|
|
|
|
BOOLEAN
|
|
SpIsCarolinaMachine(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Identifies PPC machines of type Carolina (IBM Power Series 6070).
|
|
The identification is done by looking ate the value 'Identifier'
|
|
under '\Registry\Machine\Hardware\System'.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN indicating whether or not setup is installing on a
|
|
Carolina machine.
|
|
|
|
--*/
|
|
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE KeyHandle;
|
|
NTSTATUS Status;
|
|
UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)+256];
|
|
ULONG ResultLength;
|
|
BOOLEAN CarolinaMachine = FALSE;
|
|
|
|
//
|
|
// Attempt to open the HKEY_LOCAL_MACHINE.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,
|
|
LOCAL_MACHINE_KEY_NAME);
|
|
InitializeObjectAttributes(&Obja,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
|
|
|
|
Status = ZwOpenKey(
|
|
&KeyHandle,
|
|
KEY_READ,
|
|
&Obja);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: SpIsCarolinaMachine: ZwOpenKey %ws returns %lx\n",
|
|
LOCAL_MACHINE_KEY_NAME,
|
|
Status));
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Read the Value 'Identifier', HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTOPN\System
|
|
//
|
|
//
|
|
|
|
Status = SpGetValueKey( KeyHandle,
|
|
L"HARDWARE\\DESCRIPTION\\System",
|
|
L"Identifier",
|
|
sizeof(buffer),
|
|
buffer,
|
|
&ResultLength );
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: SpIsCarolinaMachine(): SpGetValueKey KeyName = %ws, ValueName = %ws, returns %lx\n",
|
|
L"HARDWARE\\DESCRIPTION\\System",
|
|
L"Identifier",
|
|
Status));
|
|
ZwClose( KeyHandle );
|
|
return( FALSE );
|
|
}
|
|
ZwClose( KeyHandle );
|
|
KdPrint(( "SETUP: Machine Identifier = %ws \n",
|
|
(PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data) ));
|
|
return( _wcsicmp( (PWSTR)(((PKEY_VALUE_PARTIAL_INFORMATION)buffer)->Data), L"IBM-6070" ) == 0 );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpFixSetupHiveForCarolinaMachine(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Make the appropriate changes to CurrentControlSet\Services\atdisk and
|
|
CurrentControlSet\Services\atapi, on the setup hive, when setup detects that
|
|
it is installing on Carolina machine (IBM Power Series 6050 and 6070).
|
|
This function should be called only when installing on a Power PC, and it was
|
|
detected that the machine is 6070.
|
|
This function is called during the initialization of textmode setup.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - An nt status value.
|
|
|
|
--*/
|
|
|
|
{
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE KeyHandle;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Attempt to open the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.
|
|
//
|
|
RtlInitUnicodeString(&UnicodeString,
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
|
|
InitializeObjectAttributes(&Obja,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
|
|
|
|
Status = ZwOpenKey(
|
|
&KeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&Obja);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open CurrentControlSet\\Services. Status = %lx\n",
|
|
Status));
|
|
return(FALSE);
|
|
}
|
|
|
|
return( SpFixHiveForCarolinaMachine( KeyHandle, TRUE ) );
|
|
}
|
|
#endif // _PPC_
|
|
|
|
|
|
NTSTATUS
|
|
SpSaveSetupPidList(
|
|
IN HANDLE hKeySystemHive
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Save the Product Id read from setup.ini on HKEY_LOCAL_MACHINE\SYSTEM\Setup\\Pid.
|
|
Also create the key HKEY_LOCAL_MACHINE\SYSTEM\Setup\PidList, and create
|
|
value entries under this key that contain various Pid20 found in the other
|
|
systems installed on this machine (the contents Pid20Array).
|
|
|
|
Arguments:
|
|
|
|
hKeySystemHive - supplies handle to root of the system hive
|
|
(ie, HKEY_LOCAL_MACHINE\System).
|
|
|
|
|
|
Return Value:
|
|
|
|
Status value indicating outcome of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
PWSTR ValueName;
|
|
NTSTATUS Status;
|
|
ULONG i;
|
|
|
|
//
|
|
// First save the Pid read from setup.ini
|
|
//
|
|
if( PidString != NULL ) {
|
|
Status = SpOpenSetValueAndClose( hKeySystemHive,
|
|
L"Setup\\Pid",
|
|
L"Pid",
|
|
STRING_VALUE(PidString)
|
|
);
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to save Pid on SYSTEM\\Setup\\Pid. Status = %lx\n", Status ));
|
|
}
|
|
}
|
|
|
|
//
|
|
// If Pid20Array is empty, then don't bother to create the Pid key
|
|
//
|
|
if( Pid20Array[0] == NULL ) {
|
|
return( STATUS_SUCCESS );
|
|
}
|
|
|
|
//
|
|
// Can't use TemporaryBuffer because we make subroutine calls
|
|
// below that trash its contents.
|
|
// Note that a buffer of size MAX_PATH for a value name is more than enough.
|
|
//
|
|
ValueName = SpMemAlloc((MAX_PATH+1)*sizeof(WCHAR));
|
|
|
|
for( i = 0; Pid20Array[i] != NULL; i++ ) {
|
|
|
|
swprintf( ValueName, L"Pid_%d", i );
|
|
Status = SpOpenSetValueAndClose( hKeySystemHive,
|
|
L"Setup\\PidList",
|
|
ValueName,
|
|
STRING_VALUE(Pid20Array[i])
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to open or create SYSTEM\\Setup\\PidList. ValueName = %ws, ValueData = %ws, Status = %lx\n",
|
|
ValueName, Pid20Array[i] ));
|
|
}
|
|
}
|
|
SpMemFree(ValueName);
|
|
return( STATUS_SUCCESS );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SpSavePreinstallHwInfo(
|
|
IN PVOID SifHandle,
|
|
IN PWSTR SystemRoot,
|
|
IN HANDLE hKeyPreinstall,
|
|
IN ULONG ComponentIndex,
|
|
IN PHARDWARE_COMPONENT pHwList
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
NTSTATUS SaveStatus;
|
|
PHARDWARE_COMPONENT TmpHw;
|
|
PHARDWARE_COMPONENT_FILE File;
|
|
PWSTR OemTag = L"OemComponent";
|
|
PWSTR RetailClass = L"RetailClassToDisable";
|
|
PWSTR ClassName;
|
|
ULONG u;
|
|
WCHAR NodeName[9];
|
|
PWSTR ServiceName;
|
|
|
|
SaveStatus = STATUS_SUCCESS;
|
|
for( TmpHw = pHwList; TmpHw != NULL; TmpHw = TmpHw->Next ) {
|
|
if( !TmpHw->ThirdPartyOptionSelected ) {
|
|
u = 0;
|
|
if( ( ComponentIndex == HwComponentKeyboard ) ||
|
|
( ComponentIndex == HwComponentMouse ) ) {
|
|
ServiceName = SpGetSectionKeyIndex(SifHandle,
|
|
NonlocalizedComponentNames[ComponentIndex],
|
|
TmpHw->IdString,
|
|
INDEX_INFKEYNAME);
|
|
} else {
|
|
ServiceName = TmpHw->IdString;
|
|
}
|
|
|
|
Status = SpOpenSetValueAndClose( hKeyPreinstall,
|
|
ServiceName,
|
|
OemTag,
|
|
ULONG_VALUE(u)
|
|
);
|
|
if( !NT_SUCCESS( Status ) ) {
|
|
KdPrint(("SETUP: Failed to save information for preinstalled retail driver %ls. Status = %lx \n", TmpHw->IdString, Status ));
|
|
if( SaveStatus == STATUS_SUCCESS ) {
|
|
SaveStatus = Status;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// Find the name of the service, save it, and indicate if there is
|
|
// a retail class driver that needs to be disabled if the service
|
|
// initializes successfully.
|
|
//
|
|
if( IS_FILETYPE_PRESENT(TmpHw->FileTypeBits, HwFileClass) ) {
|
|
if( ComponentIndex == HwComponentKeyboard ) {
|
|
ClassName = L"kbdclass";
|
|
} else if( ComponentIndex == HwComponentMouse ) {
|
|
ClassName = L"mouclass";
|
|
} else {
|
|
ClassName = NULL;
|
|
}
|
|
} else {
|
|
ClassName = NULL;
|
|
}
|
|
for(File=TmpHw->Files; File; File=File->Next) {
|
|
PWSTR p;
|
|
|
|
//
|
|
// If there is to be no node for this file, skip it.
|
|
//
|
|
if(!File->ConfigName) {
|
|
continue;
|
|
}
|
|
//
|
|
// Calculate the node name. This is the name of the driver
|
|
// without the extension.
|
|
//
|
|
wcsncpy(NodeName,File->Filename,8);
|
|
NodeName[8] = L'\0';
|
|
if(p = wcschr(NodeName,L'.')) {
|
|
*p = L'\0';
|
|
}
|
|
u = 1;
|
|
Status = SpOpenSetValueAndClose( hKeyPreinstall,
|
|
NodeName,
|
|
OemTag,
|
|
ULONG_VALUE(u)
|
|
);
|
|
if( !NT_SUCCESS( Status ) ) {
|
|
KdPrint(("SETUP: Failed to save information for preinstalled OEM driver %ls. Status = %lx \n", NodeName, Status ));
|
|
if( SaveStatus == STATUS_SUCCESS ) {
|
|
SaveStatus = Status;
|
|
}
|
|
}
|
|
if( ClassName != NULL ) {
|
|
Status = SpOpenSetValueAndClose( hKeyPreinstall,
|
|
NodeName,
|
|
RetailClass,
|
|
STRING_VALUE(ClassName)
|
|
);
|
|
if( !NT_SUCCESS( Status ) ) {
|
|
KdPrint(("SETUP: Failed to save information for preinstalled OEM driver %ls. Status = %lx \n", NodeName, Status ));
|
|
if( SaveStatus == STATUS_SUCCESS ) {
|
|
SaveStatus = Status;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return( SaveStatus );
|
|
}
|
|
|
|
NTSTATUS
|
|
SpSavePreinstallList(
|
|
IN PVOID SifHandle,
|
|
IN PWSTR SystemRoot,
|
|
IN HANDLE hKeySystemHive
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
NTSTATUS SaveStatus;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE hKeyPreinstall;
|
|
ULONG i;
|
|
|
|
//
|
|
// Create setup\preinstall
|
|
//
|
|
INIT_OBJA(&Obja,&UnicodeString,L"Setup\\Preinstall");
|
|
Obja.RootDirectory = hKeySystemHive;
|
|
|
|
Status = ZwCreateKey(
|
|
&hKeyPreinstall,
|
|
KEY_ALL_ACCESS,
|
|
&Obja,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: unable to create Preinstall key. Status = %lx\n",Status));
|
|
return( Status );
|
|
}
|
|
|
|
SaveStatus = STATUS_SUCCESS;
|
|
for( i = 0; i < HwComponentMax; i++ ) {
|
|
if( ( i == HwComponentComputer ) ||
|
|
( i == HwComponentDisplay ) ||
|
|
( i == HwComponentLayout ) ||
|
|
( PreinstallHardwareComponents[i] == NULL ) ) {
|
|
continue;
|
|
}
|
|
|
|
Status = SpSavePreinstallHwInfo( SifHandle,
|
|
SystemRoot,
|
|
hKeyPreinstall,
|
|
i,
|
|
PreinstallHardwareComponents[i] );
|
|
if( !NT_SUCCESS( Status ) ) {
|
|
if( SaveStatus == STATUS_SUCCESS ) {
|
|
SaveStatus = Status;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( PreinstallScsiHardware != NULL ) {
|
|
Status = SpSavePreinstallHwInfo( SifHandle,
|
|
SystemRoot,
|
|
hKeyPreinstall,
|
|
HwComponentMax,
|
|
PreinstallScsiHardware );
|
|
if( !NT_SUCCESS( Status ) ) {
|
|
if( SaveStatus == STATUS_SUCCESS ) {
|
|
SaveStatus = Status;
|
|
}
|
|
}
|
|
}
|
|
ZwClose(hKeyPreinstall);
|
|
return( SaveStatus );
|
|
}
|
|
|
|
NTSTATUS
|
|
SpSavePageFileInfo(
|
|
IN HANDLE hKeyCCSetControl,
|
|
IN HANDLE hKeySystemHive
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is only called on the upgrade case.
|
|
This function replaces the original data of 'PagingFile' on
|
|
CurrentControlSet\Session Manager\Memory Management, with the default
|
|
value '?:\pagefile.sys 15 20'.
|
|
The original value will be saved on HKEY_LOCAL_MACHINE\SYSTEM\Setup\\PageFile,
|
|
and it will be restored at the end of GUI setup.
|
|
|
|
Arguments:
|
|
|
|
hKeyCCSetControl - supplies handle to SYSTEM\CurrentControlSet\Control
|
|
|
|
hKeySystemHive - supplies handle to root of the system hive
|
|
(ie, HKEY_LOCAL_MACHINE\System).
|
|
|
|
|
|
Return Value:
|
|
|
|
Status value indicating outcome of operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PUCHAR Data;
|
|
ULONG Length;
|
|
PWSTR SrcKeyPath = L"Session Manager\\Memory Management";
|
|
PWSTR ValueName = L"PagingFiles";
|
|
|
|
PWSTR Buffer;
|
|
PWSTR NextSrcSubstring;
|
|
PWSTR NextDstSubstring;
|
|
ULONG AuxLength;
|
|
BOOLEAN AtLeastOneFound;
|
|
|
|
//
|
|
// Retrieve the original value of 'PagingFiles'
|
|
//
|
|
|
|
Status = SpGetValueKey( hKeyCCSetControl,
|
|
SrcKeyPath,
|
|
ValueName,
|
|
sizeof(TemporaryBuffer),
|
|
TemporaryBuffer,
|
|
&Length );
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to retrieve %ls on %ls. Status = %lx \n", ValueName, SrcKeyPath, Status ));
|
|
return( Status );
|
|
}
|
|
|
|
Data = ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data;
|
|
Length = ((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->DataLength;
|
|
|
|
|
|
//
|
|
// Save the data in SYSTEM\Setup\PageFile
|
|
//
|
|
|
|
Status = SpOpenSetValueAndClose(
|
|
hKeySystemHive,
|
|
L"Setup\\PageFile",
|
|
ValueName,
|
|
REG_MULTI_SZ,
|
|
Data,
|
|
Length
|
|
);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to save %ls on SYSTEM\\Setup\\PageFile. ValueName, Status = %lx\n", Status ));
|
|
return( Status );
|
|
}
|
|
|
|
//
|
|
// Form a new value entry that contains the information regarding the
|
|
// paging files to be created. The paths to the paging files will be the
|
|
// same ones used in the system before the upgrade. The sizes however,
|
|
// will be changed so that they will have an initial and maximum sizes of
|
|
// 15MB and 20MB respectivelly.
|
|
//
|
|
|
|
//
|
|
// Make a copy of the original value entry, and form the data for the new
|
|
// value entry in the TemporaryBuffer.
|
|
//
|
|
Buffer = SpMemAlloc( Length );
|
|
|
|
RtlMoveMemory( Buffer, Data, Length );
|
|
NextDstSubstring = (PWSTR)TemporaryBuffer;
|
|
|
|
AtLeastOneFound = FALSE;
|
|
for( NextSrcSubstring = Buffer;
|
|
((AuxLength = wcslen( NextSrcSubstring )) != 0) &&
|
|
(NextSrcSubstring + AuxLength < Buffer + Length/sizeof(WCHAR));
|
|
NextSrcSubstring += AuxLength + 1 ) {
|
|
|
|
PWSTR r;
|
|
WCHAR SaveChar;
|
|
PWSTR s;
|
|
ULONG InitialValue;
|
|
ULONG MaxValue;
|
|
|
|
SpStringToLower( NextSrcSubstring );
|
|
r = wcsstr( NextSrcSubstring, L"\\pagefile.sys" );
|
|
if( r != NULL ) {
|
|
r += wcslen( L"\\pagefile.sys" );
|
|
SaveChar = *r;
|
|
*r = (WCHAR)'\0';
|
|
wcscpy( NextDstSubstring, NextSrcSubstring );
|
|
*r = SaveChar;
|
|
InitialValue = SpStringToLong( r, &s, 10 );
|
|
if( (s != NULL) && (*s != (WCHAR)'\0') ) {
|
|
MaxValue = SpStringToLong( s, NULL, 10 );
|
|
} else {
|
|
MaxValue = InitialValue;
|
|
}
|
|
if( MaxValue >= 20 ) {
|
|
wcscat( NextDstSubstring, L" 15 20" );
|
|
AtLeastOneFound = TRUE;
|
|
} else {
|
|
wcscat( NextDstSubstring, r );
|
|
}
|
|
NextDstSubstring += wcslen( NextDstSubstring ) + 1;
|
|
AtLeastOneFound = TRUE;
|
|
}
|
|
}
|
|
SpMemFree( Buffer );
|
|
if( AtLeastOneFound ) {
|
|
*NextDstSubstring = (WCHAR)'\0';
|
|
NextDstSubstring++;
|
|
Length = NextDstSubstring - (PWSTR)(TemporaryBuffer);
|
|
} else {
|
|
wcscpy( (PWSTR)TemporaryBuffer, L"?:\\pagefile.sys 15 20" );
|
|
Length = wcslen( (PWSTR)TemporaryBuffer ) + 1;
|
|
((PWSTR)TemporaryBuffer)[ Length ] = (WCHAR)'\0';
|
|
Length++;
|
|
}
|
|
|
|
//
|
|
// Overwrite the original value of PagingFiles
|
|
//
|
|
|
|
Status = SpOpenSetValueAndClose( hKeyCCSetControl,
|
|
SrcKeyPath,
|
|
ValueName,
|
|
REG_MULTI_SZ,
|
|
TemporaryBuffer,
|
|
Length*sizeof(WCHAR) );
|
|
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
KdPrint(("SETUP: Unable to save %ls on %ls. ValueName, SrcKeyPath, Status = %lx\n", Status ));
|
|
}
|
|
return( Status );
|
|
}
|