/*++ Copyright (c) 1993 Microsoft Corporation Module Name: spdrsif.c Abstract: Contains all routines involved in reading attributes from the asr.sif file and constructing partition records. Terminology Restrictions: Revision History: Initial Code Michael Peterson (v-michpe) 21.Aug.1998 Code cleanup and changes Guhan Suriyanarayanan (guhans) 21.Aug.1999 --*/ #include "spprecmp.h" #pragma hdrstop // Module identification for debug traces #define THIS_MODULE L" spdrsif.c" #define THIS_MODULE_CODE L"S" #define ASR_NULL_STRING (L"") // // Section names and other data used for retrieving information from the // asr.sif file // const PWSTR SIF_ASR_VERSION_SECTION = L"VERSION"; const PWSTR SIF_ASR_SYSTEMS_SECTION = L"SYSTEMS"; const PWSTR SIF_ASRFLAGS_SECTION = L"ASRFLAGS"; const PWSTR SIF_ASR_BUSES_SECTION = L"BUSES"; const PWSTR SIF_ASR_PARTITIONS_SECTION = L"PARTITIONS"; const PWSTR SIF_ASR_DISKS_SECTION = L"DISKS"; const PWSTR SIF_ASR_MBR_DISKS_SECTION = L"DISKS.MBR"; const PWSTR SIF_ASR_GPT_DISKS_SECTION = L"DISKS.GPT"; const PWSTR SIF_ASR_MBR_PARTITIONS_SECTION = L"PARTITIONS.MBR"; const PWSTR SIF_ASR_GPT_PARTITIONS_SECTION = L"PARTITIONS.GPT"; const PWSTR SIF_ASR_INSTALLFILES_SECTION = L"INSTALLFILES"; const PWSTR SIF_ASR_SIGNATURE_KEY = L"Signature"; const PWSTR SIF_ASR_PROVIDER_KEY = L"Provider"; const PWSTR SIF_ASR_SIFVERSION_KEY = L"ASR-Version"; const PWSTR ASR_SIF_RECOGNISED_SIGNATURE = L"$Windows NT$"; const PWSTR ASR_SIF_RECOGNISED_VERSION = L"1."; const PWSTR ASR_FLOPPY_DEVICE_ALIAS = L"%FLOPPY%"; const PWSTR ASR_CDROM_DEVICE_ALIAS = L"%CDROM%"; const PWSTR ASR_SOURCE_DEVICE_ALIAS = L"%SETUPSOURCE%"; const PWSTR ASR_SIF_TEMP_DIRECTORY_ALIAS = L"%TEMP%\\"; const PWSTR ASR_SIF_TMP_DIRECTORY_ALIAS = L"%TMP%\\"; const PWSTR ASR_SIF_SYSTEM_ROOT_ALIAS = L"%SystemRoot%\\"; const PWSTR ASR_SIF_SILENT_REPARTITION_VALUE = L"SilentRepartition"; extern const PWSTR ASR_FLOPPY0_DEVICE_PATH; extern const PWSTR ASR_CDROM0_DEVICE_PATH; extern const PWSTR ASR_TEMP_DIRECTORY_PATH; extern ULONG SuiteType; // Indices for the [SYSTEMS] section. typedef enum _SIF_SYSTEM_FIELD_INDEX { SIF_SYSTEM_NAME = 0, // Computer name (not used in textmode ASR) SIF_SYSTEM_PLATFORM, // x86 or ia64 SIF_SYSTEM_OSVERSION, // Windows version SIF_SYSTEM_NT_DIRECTORY_NAME, // Windows directory SIF_SYSTEM_PARTITION_AUTOEXTEND_OPTION, // [optional] SIF_SYSTEM_PRODUCT_SUITE, // SKU information // // Time Zone Information (not used in textmode ASR) // SIF_SYSTEM_TIMEZONE_INFORMATION, SIF_SYSTEM_TIMEZONE_STANDARD_NAME, SIF_SYSTEM_TIMEZONE_DAYLIGHT_NAME, SIF_SYSTEM_NUMFIELDS // Must always be last } SIF_SYSTEM_FIELD_INDEX; // Indices for the [ASRFLAGS] section. typedef enum _SIF_ASRFLAGS_FIELD_INDEX { SIF_ASRFLAGS_SILENT_REPARTITION_OPTION = 0, SIF_ASRFLAGS_NUMFIELDS // Must always be last } SIF_ASRFLAGS_FIELD_INDEX; // Indices for the [BUSES] section. typedef enum _SIF_BUSES_FIELD_INDEX { SIF_BUSES_SYSTEMKEY = 0, SIF_BUSES_BUS_TYPE, SIF_BUSES_NUMFIELDS // Must always be last } SIF_BUSES_FIELD_INDEX; // // Indices for the [DISKS.MBR] section. // // [DISKS.MBR] format // // disk-key = 0.system-key, 1.bus-key, 2.critical-flag, // 3.disk-signature, 4.bytes-per-sector, 5.total-sectors // typedef enum _SIF_MBR_DISK_FIELD_INDEX { SIF_MBR_DISK_SYSTEMKEY = 0, SIF_MBR_DISK_BUSKEY, SIF_MBR_DISK_CRITICAL_FLAG, SIF_MBR_DISK_SIGNATURE, SIF_MBR_DISK_BYTES_PER_SECTOR, SIF_MBR_DISK_SECTORS_PER_TRACK, SIF_MBR_DISK_TRACKS_PER_CYLINDER, SIF_MBR_DISK_TOTALSECTORS, SIF_MBR_DISK_NUMFIELDS // Must always be last } SIF_MBR_DISK_FIELD_INDEX; // // Indices for the [DISKS.GPT] section. // // [DISKS.GPT] format // // disk-key = 0.system-key, 1.bus-key, 2.critical-flag, 3.disk-id, // 4.min-partition-count, 5.bytes-per-sector, 6.total-sectors // typedef enum _SIF_GPT_DISK_FIELD_INDEX { SIF_GPT_DISK_SYSTEMKEY = 0, SIF_GPT_DISK_BUSKEY, SIF_GPT_DISK_CRITICAL_FLAG, SIF_GPT_DISK_DISK_ID, SIF_GPT_DISK_MAX_PTN_COUNT, SIF_GPT_DISK_BYTES_PER_SECTOR, SIF_GPT_DISK_SECTORS_PER_TRACK, SIF_GPT_DISK_TRACKS_PER_CYLINDER, SIF_GPT_DISK_TOTALSECTORS, SIF_GPT_DISK_NUMFIELDS // Must always be last } SIF_GPT_DISK_FIELD_INDEX; // // Indices for the [PARTITIONS.MBR] section. // // [PARTITIONS.MBR] // // partition-key = 0.disk-key, 1.slot-index, 2.boot-sys-flag, // 3."volume-guid", 4.active-flag, 5.partition-type, // 6.file-system-type, 7.start-sector, 8.sector-count, // 9.fs-cluster-size // typedef enum _SIF_MBR_PARTITION_FIELD_INDEX { SIF_MBR_PARTITION_DISKKEY = 0, SIF_MBR_PARTITION_SLOT_INDEX, SIF_MBR_PARTITION_SYSBOOT_FLAGS, SIF_MBR_PARTITION_VOLUME_GUID, //optional SIF_MBR_PARTITION_ACTIVE_FLAG, SIF_MBR_PARTITION_PTN_TYPE, SIF_MBR_PARTITION_FS_TYPE, SIF_MBR_PARTITION_STARTSECTOR, SIF_MBR_PARTITION_SECTORCOUNT, SIF_MBR_PARTITION_CLUSTER_SIZE, SIF_MBR_PARTITION_NUMFIELDS // Must always be last } SIF_MBR_PARTITION_FIELD_INDEX; // // Indices for the [PARTITIONS.GPT] section. // // [PARTITIONS.GPT] // // partition-key = 0.disk-key, 1.slot-index, 2.boot-sys-flag, // 3."volume-guid", 4."partition-type-guid", 5."partition-id-guid" // 6.gpt-attributes, 7."partition-name", 8.file-system-type, // 9.start-sector, 10.sector-count, 11.fs-cluster-size // typedef enum _SIF_GPT_PARTITION_FIELD_INDEX { SIF_GPT_PARTITION_DISKKEY = 0, SIF_GPT_PARTITION_SLOT_INDEX, SIF_GPT_PARTITION_SYSBOOT_FLAGS, SIF_GPT_PARTITION_VOLUME_GUID, //optional SIF_GPT_PARTITION_TYPE_GUID, SIF_GPT_PARTITION_ID_GUID, SIF_GPT_PARTITION_GPT_ATTRIBUTES, SIF_GPT_PARTITION_NAME, SIF_GPT_PARTITION_FS_TYPE, SIF_GPT_PARTITION_STARTSECTOR, SIF_GPT_PARTITION_SECTORCOUNT, SIF_GPT_PARTITION_CLUSTER_SIZE, SIF_GPT_PARTITION_NUMFIELDS // Must always be last } SIF_GPT_PARTITION_FIELD_INDEX; // Indices for the [INSTALLFILES] section. typedef enum _SIF_INSTALLFILE_FIELD_INDEX { SIF_INSTALLFILE_SYSTEM_KEY = 0, SIF_INSTALLFILE_SOURCE_MEDIA_LABEL, SIF_INSTALLFILE_SOURCE_DEVICE, SIF_INSTALLFILE_SOURCE_FILE_PATH, SIF_INSTALLFILE_DESTFILE, SIF_INSTALLFILE_VENDORSTRING, SIF_INSTALLFILE_FLAGS, SIF_INSTALLFILE_NUMFIELDS // Must always be last } SIF_INSTALLFILE_FIELD_INDEX; // Global PVOID Gbl_HandleToDrStateFile; extern PWSTR Gbl_SifSourcePath; // Forward Declarations VOID SpAsrDbgDumpInstallFileList(IN PSIF_INSTALLFILE_LIST pList); PSIF_PARTITION_RECORD_LIST SpAsrCopyPartitionRecordList(PSIF_PARTITION_RECORD_LIST pSrcList); /////////////////////////////// // Generic functions for all sections // // // The string returned should not be freed, since it's part of Setup's internal sif // data structure! // PWSTR SpAsrGetSifDataBySectionAndKey( IN const PWSTR Section, IN const PWSTR Key, IN const ULONG Value, IN const BOOLEAN NonNullRequired ) // does not return on error if NonNullRequired is TRUE { PWSTR data = NULL; ASSERT(Section && Key); // debug data = SpGetSectionKeyIndex( Gbl_HandleToDrStateFile, Section, Key, Value ); if (NonNullRequired) { if (!data || !wcscmp(data, ASR_NULL_STRING)) { DbgFatalMesg((_asrerr, "SpAsrGetSifDataBySectionAndKey. Data is " "NULL. Section:[%ws], Key:[%ws], Value:[%lu]\n", Section, Key, Value)); swprintf(TemporaryBuffer, L"%lu value not specified in %ws " L"record %ws", Value, Section, Key); SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD, TemporaryBuffer, Section); // does not return } } return data; } ULONG SpAsrGetRecordCount( IN PWSTR Section, IN ULONG MinimumValid ) { ULONG count; ASSERT(Section); count = SpCountLinesInSection(Gbl_HandleToDrStateFile, Section); if (count < MinimumValid) { DbgFatalMesg((_asrerr, "SpAsrGetRecordCount. No records in [%ws] section.\n", Section)); swprintf(TemporaryBuffer, L"No records in section"); SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD, TemporaryBuffer, Section); // does not return } return count; } PWSTR SpAsrGetSifKeyBySection( IN PWSTR Section, IN ULONG Index ) // does not return on error { PWSTR key; ULONG count = SpAsrGetRecordCount(Section, 1); // is index too big? if (Index > count) { DbgFatalMesg((_asrerr, "SpAsrGetSifKeyBySection. Section [%ws]. Index (%lu) greater than NumRecords (%lu)\n", Section, Index, count )); swprintf(TemporaryBuffer, L"Index too large: Key not found."); SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD, TemporaryBuffer, Section ); // does not return } key = SpGetKeyName(Gbl_HandleToDrStateFile, Section, Index); if (!key || !wcscmp(key, ASR_NULL_STRING)) { DbgFatalMesg((_asrerr, "SpAsrGetSifKeyBySection. SpGetKeyName failed in Section:[%ws] for Index:%lu.\n", Section, Index )); swprintf(TemporaryBuffer, L"%ws key not found for record %lu", Section, Index + 1); SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD, TemporaryBuffer, Section ); // does not return } return key; } /////////////////////////////// // [SYSTEMS] section functions // #define ASR_PRODUCTSUITES_TO_MATCH (( VER_SUITE_SMALLBUSINESS \ | VER_SUITE_ENTERPRISE \ | VER_SUITE_BACKOFFICE \ | VER_SUITE_COMMUNICATIONS \ | VER_SUITE_SMALLBUSINESS_RESTRICTED \ | VER_SUITE_EMBEDDEDNT \ | VER_SUITE_DATACENTER \ | VER_SUITE_PERSONAL)) // // This checks to make sure that Windows media being used for the recovery // is the same SKU as that in asr.sif (so the user isn't trying to recover // an ADS installation with a PRO CD, for instance), and that the platform // of the target machine is the same as that in asr.sif (so the user isn't // trying to recover an ia64 with an x86 asr.sif, for instance) // VOID SpAsrCheckSystemCompatibility() { PWSTR sifPlatform = NULL; WCHAR currentPlatform[10]; DWORD suiteInSif = 0, currentSuite = 0, productInSif = 0; BOOLEAN validSKU = TRUE; sifPlatform = SpAsrGetSifDataBySectionAndKey( SIF_ASR_SYSTEMS_SECTION, ASR_SIF_SYSTEM_KEY, SIF_SYSTEM_PLATFORM, TRUE ); wcscpy(currentPlatform, L"unknown"); #if defined(_X86_) wcscpy(currentPlatform, L"x86"); #elif defined(_IA64_) wcscpy(currentPlatform, L"ia64"); #endif if (_wcsicmp(sifPlatform, currentPlatform)) { DbgFatalMesg((_asrerr, "asr.sif SYSTEM section. Invalid platform [%ws] (does not match the current platform)\n", sifPlatform )); SpAsrRaiseFatalError( SP_SCRN_DR_INCOMPATIBLE_MEDIA, L"Invalid platform" ); } suiteInSif = STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey( SIF_ASR_SYSTEMS_SECTION, ASR_SIF_SYSTEM_KEY, SIF_SYSTEM_PRODUCT_SUITE, TRUE )); productInSif = HIWORD(suiteInSif); suiteInSif = LOWORD(suiteInSif) & ASR_PRODUCTSUITES_TO_MATCH; if (suiteInSif) { if (!SuiteType) { // // SuiteType is set to 0 for PRO and SRV, and so cannot directly be // used in SpIsProductSuite(). These are the values that SuiteType // seems to be set to: // // PER 0x200 VER_SUITE_PERSONAL // BLA 0x400 VER_SUITE_BLADE // PRO 0x0 // SRV 0x0 // ADS 0x2 VER_SUITE_ENTERPRISE // DTC 0x82 VER_SUITE_DATACENTER | VER_SUITE_ENTERPRISE // // // // Not sure of the reasoning behind this, but let's make use of this // fact (cf SpGetHeaderTextId) // // // Since SuiteType is 0, this must be PRO or SRV. This can be determined // by checking the global AdvancedServer // validSKU = (AdvancedServer ? ( ((productInSif == VER_NT_SERVER) || // must be SRV (productInSif == VER_NT_DOMAIN_CONTROLLER)) && // !(suiteInSif | VER_SUITE_ENTERPRISE) // and not ADS or DTC ) : ( (productInSif == VER_NT_WORKSTATION) && // must be PRO !(suiteInSif | VER_SUITE_PERSONAL) // and not PER ) ); } else if ( ((productInSif != VER_NT_SERVER) && (productInSif != VER_NT_DOMAIN_CONTROLLER)) || !SpIsProductSuite(suiteInSif) ) { validSKU = FALSE; } } if (!validSKU) { DbgFatalMesg((_asrerr, "asr.sif SYSTEM Section. Invalid suite 0x%08x (does not match the current media).\n", suiteInSif )); SpAsrRaiseFatalError( SP_SCRN_DR_INCOMPATIBLE_MEDIA, L"Invalid version" ); } } ULONG SpAsrGetSystemRecordCount(VOID) // does not return on error { return SpAsrGetRecordCount(SIF_ASR_SYSTEMS_SECTION, 1); } PWSTR SpAsrGetNtDirectoryPathBySystemKey(IN PWSTR SystemKey) // does not return on error { return SpAsrGetSifDataBySectionAndKey( SIF_ASR_SYSTEMS_SECTION, SystemKey, SIF_SYSTEM_NT_DIRECTORY_NAME, TRUE ); } BOOLEAN SpAsrGetAutoExtend(IN PWSTR SystemKey) { PWSTR value = NULL; ASSERT(SystemKey); value = SpGetSectionKeyIndex( Gbl_HandleToDrStateFile, SIF_ASR_SYSTEMS_SECTION, SystemKey, SIF_SYSTEM_PARTITION_AUTOEXTEND_OPTION ); if (!value || !wcscmp(value, ASR_NULL_STRING)) { DbgErrorMesg((_asrwarn, "Auto-extend not specified, assuming Enabled\n")); return TRUE; } else { return (BOOLEAN) STRING_TO_LONG(value); } } /////////////////////////////// // [ASRFLAGS] section functions // BOOLEAN SpAsrGetSilentRepartitionFlag(IN PWSTR SystemKey) { PWSTR value = NULL; ASSERT(SystemKey); value = SpGetSectionKeyIndex( Gbl_HandleToDrStateFile, SIF_ASRFLAGS_SECTION, SystemKey, SIF_ASRFLAGS_SILENT_REPARTITION_OPTION ); if (value && !_wcsicmp(value, ASR_SIF_SILENT_REPARTITION_VALUE)) { DbgErrorMesg((_asrwarn, "SilentRepartition flag is set; will NOT prompt before repartitioning disks!\n")); return TRUE; } DbgStatusMesg((_asrinfo, "SilentRepartition flag not set; will prompt user before repartitioning disks\n")); return FALSE; } /////////////////////////////// // [VERSION] section functions // VOID SpAsrCheckAsrStateFileVersion() { PWSTR signature = NULL, provider = NULL, sifVersion = NULL; signature = SpAsrGetSifDataBySectionAndKey( SIF_ASR_VERSION_SECTION, SIF_ASR_SIGNATURE_KEY, 0, TRUE ); provider = SpAsrGetSifDataBySectionAndKey( SIF_ASR_VERSION_SECTION, SIF_ASR_PROVIDER_KEY, 0, FALSE ); // ProviderName is optional sifVersion = SpAsrGetSifDataBySectionAndKey( SIF_ASR_VERSION_SECTION, SIF_ASR_SIFVERSION_KEY, 0, TRUE ); DbgStatusMesg((_asrinfo, "Asr Sif Version. sig:[%ws], provider:[%ws], sifVer:[%ws]\n", signature, provider ? provider : L"", sifVersion )); if (_wcsicmp(signature, ASR_SIF_RECOGNISED_SIGNATURE)) { DbgFatalMesg((_asrerr, "asr.sif VERSION section. Invalid signature [%ws] (it MUST be $Windows NT$).\n", signature )); SpAsrRaiseFatalError( SP_TEXT_DR_STATEFILE_ERROR, L"Invalid signature" ); } if (_wcsnicmp(sifVersion, ASR_SIF_RECOGNISED_VERSION, wcslen(ASR_SIF_RECOGNISED_VERSION))) { DbgFatalMesg((_asrerr, "asr.sif VERSION Section. Invalid asr.sif version [%ws] (it MUST be 1.x).\n", sifVersion )); SpAsrRaiseFatalError( SP_TEXT_DR_STATEFILE_ERROR, L"Invalid version" ); } SpAsrCheckSystemCompatibility(); } ///////////////////////////////// // InstallFiles section functions // ULONG SpAsrGetInstallFilesRecordCount(VOID) // does not return on error { return SpAsrGetRecordCount(SIF_ASR_INSTALLFILES_SECTION, 0); } PSIF_INSTALLFILE_RECORD SpAsrGetInstallFileRecord(IN PWSTR InstallFileKey, IN PCWSTR SetupSourceDevicePath) { PSIF_INSTALLFILE_RECORD pRec = NULL; PWSTR tempStr = NULL; BOOL isValid = FALSE; if (!InstallFileKey) { DbgFatalMesg((_asrerr, "SpAsrGetInstallFileRecord. InstallFileKey is NULL\n")); SpAsrRaiseFatalErrorWs( SP_SCRN_DR_SIF_BAD_RECORD, L"InstallFileKey is NULL", SIF_ASR_INSTALLFILES_SECTION ); } pRec = SpAsrMemAlloc(sizeof(SIF_INSTALLFILE_RECORD), TRUE); pRec->SystemKey = SpAsrGetSifDataBySectionAndKey( SIF_ASR_INSTALLFILES_SECTION, InstallFileKey, SIF_INSTALLFILE_SYSTEM_KEY, TRUE ); pRec->CurrKey = InstallFileKey; pRec->SourceMediaExternalLabel = SpAsrGetSifDataBySectionAndKey( SIF_ASR_INSTALLFILES_SECTION, InstallFileKey, SIF_INSTALLFILE_SOURCE_MEDIA_LABEL, TRUE ); tempStr = SpAsrGetSifDataBySectionAndKey( SIF_ASR_INSTALLFILES_SECTION, InstallFileKey, SIF_INSTALLFILE_SOURCE_DEVICE, TRUE ); // // Check if the device is specified as %FLOPPY%, %CDROM% or %SETUPSOURCE%, // and use the full path (\device\floppy0 or \device\CdRom0 or // SetupSourceDevicePath) if so. // if (!_wcsicmp(tempStr, ASR_FLOPPY_DEVICE_ALIAS)) { pRec->DiskDeviceName = SpDupStringW(ASR_FLOPPY0_DEVICE_PATH); } else if (!_wcsicmp(tempStr, ASR_CDROM_DEVICE_ALIAS)) { pRec->DiskDeviceName = SpDupStringW(ASR_CDROM0_DEVICE_PATH); } else if (!_wcsicmp(tempStr, ASR_SOURCE_DEVICE_ALIAS) && SetupSourceDevicePath) { pRec->DiskDeviceName = SpDupStringW(SetupSourceDevicePath); } else { // // It wasn't any of the aliases--he's allowed to specify // the full device path, so we use it as is. // pRec->DiskDeviceName = SpDupStringW(tempStr); } pRec->SourceFilePath = (PWSTR) SpAsrGetSifDataBySectionAndKey( SIF_ASR_INSTALLFILES_SECTION, InstallFileKey, SIF_INSTALLFILE_SOURCE_FILE_PATH, TRUE ); tempStr = (PWSTR) SpAsrGetSifDataBySectionAndKey( SIF_ASR_INSTALLFILES_SECTION, InstallFileKey, SIF_INSTALLFILE_DESTFILE, TRUE ); // // Set the CopyToDirectory based on the tempStr path // if (!_wcsnicmp(tempStr, ASR_SIF_TEMP_DIRECTORY_ALIAS, wcslen(ASR_SIF_TEMP_DIRECTORY_ALIAS))) { // // Begins is %TEMP%\ // pRec->CopyToDirectory = _Temp; pRec->DestinationFilePath = SpDupStringW((PWSTR)(&tempStr[wcslen(ASR_SIF_TEMP_DIRECTORY_ALIAS)])); } else if (!_wcsnicmp(tempStr, ASR_SIF_TMP_DIRECTORY_ALIAS, wcslen(ASR_SIF_TMP_DIRECTORY_ALIAS))) { // // Begins is %TMP%\ // pRec->CopyToDirectory = _Tmp; pRec->DestinationFilePath = SpDupStringW((PWSTR)(&tempStr[wcslen(ASR_SIF_TMP_DIRECTORY_ALIAS)])); } else if (!_wcsnicmp(tempStr, ASR_SIF_SYSTEM_ROOT_ALIAS, wcslen(ASR_SIF_SYSTEM_ROOT_ALIAS))) { // // Begins is %SYSTEMROOT%\ // pRec->CopyToDirectory = _SystemRoot; pRec->DestinationFilePath = SpDupStringW((PWSTR)(&tempStr[wcslen(ASR_SIF_SYSTEM_ROOT_ALIAS)])); } else { // // Not specified, or unknown: use default. // pRec->CopyToDirectory = _Default; pRec->DestinationFilePath = SpDupStringW(tempStr); } pRec->VendorString = SpAsrGetSifDataBySectionAndKey( SIF_ASR_INSTALLFILES_SECTION, InstallFileKey, SIF_INSTALLFILE_VENDORSTRING, TRUE ); tempStr = SpAsrGetSifDataBySectionAndKey( SIF_ASR_INSTALLFILES_SECTION, InstallFileKey, SIF_INSTALLFILE_FLAGS, FALSE ); if (tempStr) { pRec->Flags = STRING_TO_HEX(tempStr); } return pRec; } VOID SpAsrInsertInstallFileRecord( IN SIF_INSTALLFILE_LIST *InstallFileList, IN PSIF_INSTALLFILE_RECORD pRec ) { pRec->Next = InstallFileList->First; InstallFileList->First = pRec; InstallFileList->Count += 1; } PSIF_INSTALLFILE_RECORD SpAsrRemoveInstallFileRecord(IN SIF_INSTALLFILE_LIST *InstallFileList) { PSIF_INSTALLFILE_RECORD pRec = NULL; if (InstallFileList->Count > 0) { pRec = InstallFileList->First; InstallFileList->First = pRec->Next; InstallFileList->Count -= 1; } return pRec; } VOID SpAsrDeleteInstallFileRecord( IN OUT PSIF_INSTALLFILE_RECORD pRec ) { // // Free the memory we allocated. The other fields are pointers to // setup's internal inf data structure, we shouldn't free those // else they'd get freed twice. // if (pRec->DiskDeviceName) { SpMemFree(pRec->DiskDeviceName); pRec->DiskDeviceName = NULL; } if (pRec->DestinationFilePath) { SpMemFree(pRec->DestinationFilePath); pRec->DestinationFilePath = NULL; } SpMemFree(pRec); pRec = NULL; } PSIF_INSTALLFILE_LIST SpAsrInit3rdPartyFileList(IN PCWSTR SetupSourceDevicePath) { PSIF_INSTALLFILE_RECORD pRec; PSIF_INSTALLFILE_LIST pList = NULL; ULONG count, index; if ((count = SpAsrGetInstallFilesRecordCount()) == 0) { return NULL; } pList = SpAsrMemAlloc(sizeof(SIF_INSTALLFILE_LIST), TRUE); for (index = 0; index < count; index++) { pRec = SpAsrGetInstallFileRecord(SpAsrGetSifKeyBySection(SIF_ASR_INSTALLFILES_SECTION, index), SetupSourceDevicePath); DbgStatusMesg((_asrinfo, "SpAsrInit3rdPartyFileList. Adding [%ws] to list\n", pRec->SourceFilePath)); SpAsrInsertInstallFileRecord(pList, pRec); } return pList; } //////////////////////////// // [BUSES] section function // STORAGE_BUS_TYPE SpAsrGetBusType(IN ULONG Index) { STORAGE_BUS_TYPE BusType; PWSTR BusKey = SpAsrGetSifKeyBySection(SIF_ASR_BUSES_SECTION, Index); BusType = (STORAGE_BUS_TYPE) (STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_BUSES_SECTION, BusKey, SIF_BUSES_BUS_TYPE, TRUE ))); return BusType; } //////////////////////////// // [DISKS] section function // // // Returns the total number of disk records (both MBR and GPT) // ULONG SpAsrGetGptDiskRecordCount(VOID) // does not return on error { static ULONG Count = (ULONG) (-1); if ((ULONG) (-1) == Count) { Count = SpAsrGetRecordCount(SIF_ASR_GPT_DISKS_SECTION, 0); } return Count; } ULONG SpAsrGetMbrDiskRecordCount(VOID) // does not return on error { static ULONG Count = (ULONG) (-1); if ((ULONG) (-1) == Count) { Count = SpAsrGetRecordCount(SIF_ASR_MBR_DISKS_SECTION, 0); } return Count; } ULONG SpAsrGetDiskRecordCount(VOID) // does not return on error { static ULONG Total = (ULONG) (-1); if ((ULONG) (-1) == Total ) { Total = SpAsrGetMbrDiskRecordCount() + SpAsrGetGptDiskRecordCount(); } return Total; } PWSTR SpAsrGetDiskKey( IN PARTITION_STYLE Style, // GPT or MBR IN ULONG Index ) // does not return on error { switch (Style) { case PARTITION_STYLE_GPT: return SpAsrGetSifKeyBySection(SIF_ASR_GPT_DISKS_SECTION, Index); break; case PARTITION_STYLE_MBR: return SpAsrGetSifKeyBySection(SIF_ASR_MBR_DISKS_SECTION, Index); break; } ASSERT(0 && L"Illegal partition style specified"); return NULL; } PSIF_DISK_RECORD SpAsrGetMbrDiskRecord( IN PWSTR DiskKey ) { PSIF_DISK_RECORD pRec; if (!DiskKey) { ASSERT(0 && L"SpAsrGetMbrDiskRecord: DiskKey is NULL!"); return NULL; } pRec = SpAsrMemAlloc(sizeof(SIF_DISK_RECORD), TRUE); // // This is an MBR disk // pRec->PartitionStyle = PARTITION_STYLE_MBR; // // [DISKS.MBR] format // // 0.disk-key = 1.system-key, 2.bus-key, 3.critical-flag, // 4.disk-signature, 5.bytes-per-sector, 6.total-sectors // pRec->CurrDiskKey = DiskKey; pRec->SystemKey = SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_DISKS_SECTION , DiskKey, SIF_MBR_DISK_SYSTEMKEY, TRUE ); pRec->BusKey = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_DISKS_SECTION , DiskKey, SIF_MBR_DISK_BUSKEY, TRUE )); pRec->BusType = SpAsrGetBusType(pRec->BusKey - 1); // our key is 1 based, AsrGetBusType index is 0 based if (ASRMODE_NORMAL != SpAsrGetAsrMode()) { pRec->IsCritical = TRUE; } else { pRec->IsCritical = (STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_DISKS_SECTION , DiskKey, SIF_MBR_DISK_CRITICAL_FLAG, TRUE ))) ? TRUE : FALSE; } pRec->SifDiskMbrSignature = STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_DISKS_SECTION , DiskKey, SIF_MBR_DISK_SIGNATURE, TRUE )); pRec->BytesPerSector = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_DISKS_SECTION , DiskKey, SIF_MBR_DISK_BYTES_PER_SECTOR, TRUE )); pRec->SectorsPerTrack = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_DISKS_SECTION , DiskKey, SIF_MBR_DISK_SECTORS_PER_TRACK, TRUE )); pRec->TracksPerCylinder = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_DISKS_SECTION , DiskKey, SIF_MBR_DISK_TRACKS_PER_CYLINDER, TRUE )); pRec->TotalSectors = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_DISKS_SECTION , DiskKey, SIF_MBR_DISK_TOTALSECTORS, TRUE )); return pRec; } PSIF_DISK_RECORD SpAsrGetGptDiskRecord( IN PWSTR DiskKey ) { PSIF_DISK_RECORD pRec = NULL; PWSTR GuidString = NULL; if (!DiskKey) { ASSERT(0 && L"SpAsrGetGptDiskRecord: DiskKey is NULL!"); return NULL; } pRec = SpAsrMemAlloc(sizeof(SIF_DISK_RECORD), TRUE); pRec->PartitionStyle = PARTITION_STYLE_GPT; // // [DISKS.GPT] format // // 0.disk-key = 1.system-key, 2.bus-key, 3.critical-flag, 4.disk-id, // 5.min-partition-count, 6.bytes-per-sector, 7.total-sectors // pRec->CurrDiskKey = DiskKey; pRec->SystemKey = SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION, DiskKey, SIF_GPT_DISK_SYSTEMKEY, TRUE ); pRec->BusKey = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION , DiskKey, SIF_GPT_DISK_BUSKEY, TRUE )); pRec->BusType = SpAsrGetBusType(pRec->BusKey - 1); // our key is 1 based, AsrGetBusType index is 0 based if (ASRMODE_NORMAL != SpAsrGetAsrMode()) { pRec->IsCritical = TRUE; } else { pRec->IsCritical = (STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION , DiskKey, SIF_GPT_DISK_CRITICAL_FLAG, TRUE ))) ? TRUE : FALSE; } GuidString = SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION , DiskKey, SIF_GPT_DISK_DISK_ID, TRUE ); SpAsrGuidFromString(&(pRec->SifDiskGptId), GuidString); pRec->MaxGptPartitionCount = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION , DiskKey, SIF_GPT_DISK_MAX_PTN_COUNT, TRUE )); pRec->BytesPerSector = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION , DiskKey, SIF_GPT_DISK_BYTES_PER_SECTOR, TRUE )); pRec->SectorsPerTrack = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION , DiskKey, SIF_GPT_DISK_SECTORS_PER_TRACK, TRUE )); pRec->TracksPerCylinder = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION , DiskKey, SIF_GPT_DISK_TRACKS_PER_CYLINDER, TRUE )); pRec->TotalSectors = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION , DiskKey, SIF_GPT_DISK_TOTALSECTORS, TRUE )); return pRec; } PSIF_DISK_RECORD SpAsrGetDiskRecord( IN PARTITION_STYLE PartitionStyle, IN PWSTR DiskKey ) { switch (PartitionStyle) { case PARTITION_STYLE_MBR: return SpAsrGetMbrDiskRecord(DiskKey); break; case PARTITION_STYLE_GPT: return SpAsrGetGptDiskRecord(DiskKey); break; } ASSERT(0 && L"Invalid partition type specified"); return NULL; } PSIF_DISK_RECORD SpAsrCopyDiskRecord(IN PSIF_DISK_RECORD pInput) { PSIF_DISK_RECORD pRec; pRec = SpAsrMemAlloc(sizeof(SIF_DISK_RECORD), TRUE); CopyMemory(pRec, pInput, sizeof(SIF_DISK_RECORD)); pRec->PartitionList = NULL; // copy the list of partitions, if any. if (pInput->PartitionList) { pRec->PartitionList = SpAsrCopyPartitionRecordList(pInput->PartitionList); } return pRec; } //////////////////////////////// // [PARTITIONS] section function // ULONG SpAsrGetMbrPartitionRecordCount(VOID) { return SpAsrGetRecordCount(SIF_ASR_MBR_PARTITIONS_SECTION, 0); } ULONG SpAsrGetGptPartitionRecordCount(VOID) { return SpAsrGetRecordCount(SIF_ASR_GPT_PARTITIONS_SECTION, 0); } PWSTR SpAsrGetMbrPartitionKey(ULONG Index) { return SpAsrGetSifKeyBySection( SIF_ASR_MBR_PARTITIONS_SECTION, Index); } PWSTR SpAsrGetGptPartitionKey(ULONG Index) { return SpAsrGetSifKeyBySection( SIF_ASR_GPT_PARTITIONS_SECTION, Index); } PWSTR SpAsrGetDiskKeyByMbrPartitionKey(IN PWSTR PartitionKey) { return SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_PARTITIONS_SECTION, PartitionKey, SIF_MBR_PARTITION_DISKKEY, TRUE); } PWSTR SpAsrGetDiskKeyByGptPartitionKey(IN PWSTR PartitionKey) { return SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_DISKKEY, TRUE); } ULONGLONG SpAsrGetSectorCountByMbrDiskKey( IN PWSTR DiskKey ) { return STRING_TO_ULONGLONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_DISKS_SECTION, DiskKey, SIF_MBR_DISK_TOTALSECTORS, FALSE )); } ULONGLONG SpAsrGetSectorCountByGptDiskKey( IN PWSTR DiskKey ) { return STRING_TO_ULONGLONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION, DiskKey, SIF_GPT_DISK_TOTALSECTORS, FALSE )); } // // Reads in a partition record from the [PARTITIONS.MBR] section. // // [PARTITIONS.MBR] // // partition-key = 0.disk-key, 1.slot-index, 2.boot-sys-flag, // 3."volume-guid", 4.active-flag, 5.partition-type, // 6.file-system-type, 7.start-sector, 8.sector-count // PSIF_PARTITION_RECORD SpAsrGetMbrPartitionRecord(IN PWSTR PartitionKey) { PSIF_PARTITION_RECORD pRec = NULL; ULONG bytesPerSector = 0; ULONG ntSysMask = 0; // // PartitionKey better not be null // if (!PartitionKey) { DbgErrorMesg((_asrwarn, "SpAsrGetPartitionRecord. PartitionKey is NULL\n")); ASSERT(0 && L"Partition key is NULL"); return NULL; } pRec = SpAsrMemAlloc(sizeof(SIF_PARTITION_RECORD), TRUE); // // Read in the fields // pRec->CurrPartKey = PartitionKey; pRec->PartitionStyle = PARTITION_STYLE_MBR; pRec->DiskKey = SpAsrGetDiskKeyByMbrPartitionKey(PartitionKey); pRec->PartitionTableEntryIndex = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_PARTITIONS_SECTION, PartitionKey, SIF_MBR_PARTITION_SLOT_INDEX, TRUE )); pRec->PartitionFlag = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_PARTITIONS_SECTION, PartitionKey, SIF_MBR_PARTITION_SYSBOOT_FLAGS, TRUE )); pRec->VolumeGuid = SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_PARTITIONS_SECTION, PartitionKey, SIF_MBR_PARTITION_VOLUME_GUID, FALSE ); pRec->ActiveFlag = (UCHAR) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_PARTITIONS_SECTION, PartitionKey, SIF_MBR_PARTITION_ACTIVE_FLAG, TRUE )); pRec->PartitionType = (UCHAR) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_PARTITIONS_SECTION, PartitionKey, SIF_MBR_PARTITION_PTN_TYPE, TRUE )); pRec->FileSystemType = (UCHAR) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_PARTITIONS_SECTION, PartitionKey, SIF_MBR_PARTITION_FS_TYPE, TRUE )); pRec->StartSector = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_PARTITIONS_SECTION, PartitionKey, SIF_MBR_PARTITION_STARTSECTOR, TRUE )); pRec->SectorCount = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_PARTITIONS_SECTION, PartitionKey, SIF_MBR_PARTITION_SECTORCOUNT, TRUE )); pRec->ClusterSize = (DWORD) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_PARTITIONS_SECTION, PartitionKey, SIF_MBR_PARTITION_CLUSTER_SIZE, TRUE )); if (SpAsrIsBootPartitionRecord(pRec->PartitionFlag)) { // do not free! PWSTR ntDirPath = SpAsrGetNtDirectoryPathBySystemKey(ASR_SIF_SYSTEM_KEY); if (!SpAsrIsValidBootDrive(ntDirPath)) { SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD, L"ASSERT FAILURE: Improperly formed NT Directory Name", SIF_ASR_MBR_PARTITIONS_SECTION ); // does not return } pRec->NtDirectoryName = SpAsrMemAlloc((SpGetMaxNtDirLen()*sizeof(WCHAR)), TRUE); wcsncpy(pRec->NtDirectoryName, ntDirPath + 2, wcslen(ntDirPath) - 2); } else { pRec->NtDirectoryName = NULL; } bytesPerSector = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_MBR_DISKS_SECTION , pRec->DiskKey, SIF_MBR_DISK_BYTES_PER_SECTOR, TRUE )); pRec->SizeMB = SpAsrConvertSectorsToMB(pRec->SectorCount, bytesPerSector); return pRec; } PSIF_PARTITION_RECORD SpAsrGetGptPartitionRecord(IN PWSTR PartitionKey) { PSIF_PARTITION_RECORD pRec = NULL; ULONG bytesPerSector = 0; ULONG ntSysMask = 0; PWSTR GuidString = NULL; if (!PartitionKey) { DbgErrorMesg((_asrwarn, "SpAsrGetPartitionRecord. PartitionKey is NULL\n")); ASSERT(0 && L"Partition key is NULL"); return NULL; } pRec = SpAsrMemAlloc(sizeof(SIF_PARTITION_RECORD), TRUE); // // Read in the fields // pRec->CurrPartKey = PartitionKey; pRec->PartitionStyle = PARTITION_STYLE_GPT; pRec->DiskKey = SpAsrGetDiskKeyByGptPartitionKey(PartitionKey); pRec->PartitionTableEntryIndex = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_SLOT_INDEX, TRUE )); pRec->PartitionFlag = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_SYSBOOT_FLAGS, TRUE )); pRec->VolumeGuid = SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_VOLUME_GUID, FALSE ); GuidString = SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_TYPE_GUID, FALSE ); SpAsrGuidFromString(&(pRec->PartitionTypeGuid), GuidString); GuidString = SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_ID_GUID, FALSE ); SpAsrGuidFromString(&(pRec->PartitionIdGuid), GuidString); pRec->PartitionName = SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_NAME, FALSE ); pRec->GptAttributes = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_GPT_ATTRIBUTES, TRUE )); pRec->FileSystemType = (UCHAR) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_FS_TYPE, TRUE )); pRec->StartSector = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_STARTSECTOR, TRUE )); pRec->SectorCount = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_SECTORCOUNT, TRUE )); pRec->ClusterSize = (DWORD) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_PARTITIONS_SECTION, PartitionKey, SIF_GPT_PARTITION_CLUSTER_SIZE, TRUE )); if (SpAsrIsBootPartitionRecord(pRec->PartitionFlag)) { // do not free! PWSTR ntDirPath = SpAsrGetNtDirectoryPathBySystemKey(ASR_SIF_SYSTEM_KEY); if (!SpAsrIsValidBootDrive(ntDirPath)) { SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD, L"ASSERT FAILURE: Improperly formed NT Directory Name", SIF_ASR_GPT_PARTITIONS_SECTION ); // does not return } pRec->NtDirectoryName = SpAsrMemAlloc((SpGetMaxNtDirLen()*sizeof(WCHAR)), TRUE); wcsncpy(pRec->NtDirectoryName, ntDirPath + 2, wcslen(ntDirPath) - 2); } else { pRec->NtDirectoryName = NULL; } bytesPerSector = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey( SIF_ASR_GPT_DISKS_SECTION , pRec->DiskKey, SIF_GPT_DISK_BYTES_PER_SECTOR, TRUE )); pRec->SizeMB = SpAsrConvertSectorsToMB(pRec->SectorCount, bytesPerSector); return pRec; } PSIF_PARTITION_RECORD SpAsrCopyPartitionRecord(IN PSIF_PARTITION_RECORD pInput) { PSIF_PARTITION_RECORD pRec = NULL; if (!pInput) { ASSERT(0 && L"SpAsrCopyPartitionRecord: Invalid NULL input parameter"); return NULL; } pRec = SpAsrMemAlloc(sizeof(SIF_PARTITION_RECORD), TRUE); // // Won't return if pRec is NULL // ASSERT(pRec); // // Copy the record over // CopyMemory(pRec, pInput, sizeof(SIF_PARTITION_RECORD)); // // And allocate space for the directory name // pRec->NtDirectoryName = NULL; if ( SpAsrIsBootPartitionRecord(pRec->PartitionFlag) && pInput->NtDirectoryName ) { pRec->NtDirectoryName = SpAsrMemAlloc( (wcslen(pInput->NtDirectoryName) + 1) * sizeof(WCHAR), TRUE ); // // Won't return NULL // ASSERT(pRec->NtDirectoryName); wcscpy(pRec->NtDirectoryName, pInput->NtDirectoryName); } return pRec; } VOID SpAsrInsertPartitionRecord( IN PSIF_PARTITION_RECORD_LIST pList, IN PSIF_PARTITION_RECORD pRec ) /*++ Description: Inserts a partition record into a list of partition records. Partition records are ordered in ascending order by start sector. That is, the partition record with the lowest numbered start sector will be the first partition record in the list. Arguments: pList The list into which the record is to be inserted. pRec The record to insert. Returns: None. --*/ { SIF_PARTITION_RECORD *curr = NULL, *prev = NULL; ASSERT(pList && pRec); // set the initial conditions. pRec->Next = NULL; pRec->Prev = NULL; pList->ElementCount += 1; // special Case I: Insert into an empty list. if( pList->ElementCount == 1 ) { pList->First = pList->Last = pRec; return; } // Special Case II: pRec must be inserted before the first element. if( pRec->StartSector < pList->First->StartSector ) { pRec->Next = pList->First; pList->First = pRec; pRec->Next->Prev = pRec; return; } // Special Case III: pRec must be appended after the last element // because pRec's start sector is greater than the last element // on the list (which, by construction, must have the largest // start sector). // if( pList->Last->StartSector < pRec->StartSector ) { pRec->Prev = pList->Last; pList->Last->Next = pRec; pList->Last = pRec; return; } // If we're here, then pRec's start sector must be greater than // the start sector of the first element on the list but less than // the start sector of the list's last element. We walk the list // to find the insertion point, i.e., immediately before the first // element in the list whose start sector is greater than that of // pRec's. curr = prev = pList->First; while (pRec->StartSector > curr->StartSector && curr->Next) { prev = curr; curr = curr->Next; } // insert pRec between curr and prev pRec->Next = curr; pRec->Prev = prev; curr->Prev = pRec; prev->Next = pRec; ASSERT (pRec->Prev->Next == pRec); ASSERT (pRec->Next->Prev == pRec); } VOID SpAsrRemovePartitionRecord( IN PSIF_PARTITION_RECORD_LIST pList, IN PSIF_PARTITION_RECORD pRec ) /*++ Description: Unhook a partition record from a list of partition records. --*/ { ASSERT(pList && pRec); // unhook it from the list. if (pRec->Prev) { pRec->Prev->Next = pRec->Next; } if (pRec->Next) { pRec->Next->Prev = pRec->Prev; } // was this the first record in the list? if (pList->First == pRec) { pList->First = pRec->Next; } // or the last record? if (pList->Last == pRec) { pList->Last = pRec->Prev; } pRec->Next = pRec->Prev = NULL; } PSIF_PARTITION_RECORD SpAsrPopNextPartitionRecord(IN PSIF_PARTITION_RECORD_LIST pList) { PSIF_PARTITION_RECORD poppedRecord = NULL; if (!pList) { // ASSERT(0 && L"Trying to pop records off of a NULL list"); return NULL; } // get the first node in the list if (poppedRecord = pList->First) { // advance the First pointer to the next node if (pList->First = pList->First->Next) { // and make the Prev of the new first-node be NULL pList->First->Prev = NULL; } pList->ElementCount -= 1; // the poppedRecord is not part of the list any more poppedRecord->Next = NULL; poppedRecord->Prev = NULL; } return poppedRecord; } PSIF_PARTITION_RECORD_LIST SpAsrCopyPartitionRecordList(PSIF_PARTITION_RECORD_LIST pSrcList) { PSIF_PARTITION_RECORD_LIST pDestList = NULL; PSIF_PARTITION_RECORD pRec = NULL, pNew = NULL; if (!pSrcList) { ASSERT(0 && L"SpAsrCopyPartitionRecordList: Invalid NULL input parameter"); return NULL; } pDestList = SpAsrMemAlloc(sizeof(SIF_PARTITION_RECORD_LIST), TRUE); // // Won't return if pDestList is NULL. // ASSERT(pDestList); pRec = pSrcList->First; while (pRec) { pNew = SpAsrCopyPartitionRecord(pRec); ASSERT(pNew); SpAsrInsertPartitionRecord(pDestList, pNew); pRec = pRec->Next; } pDestList->TotalMbRequired = pSrcList->TotalMbRequired; return pDestList; } VOID SpAsrCheckAsrSifVersion() { return; } // // Debug routines // #if 0 VOID SpAsrDbgDumpSystemRecord(IN PWSTR Key) { PWSTR osVer = SpAsrGetSifDataBySectionAndKey(SIF_ASR_SYSTEMS_SECTION, Key, SIF_SYSTEM_OSVERSION, FALSE); DbgMesg((_asrinfo, "Key:%ws = SysName:[%ws], OsVer:[%ws], NtDir:[%ws], AutoExt:[%ws]\n", Key, SpAsrGetSifDataBySectionAndKey(SIF_ASR_SYSTEMS_SECTION, Key, SIF_SYSTEM_NAME, TRUE), osVer? osVer : L"", SpAsrGetNtDirectoryPathBySystemKey(Key), SpAsrGetAutoExtend(Key) )); } VOID SpAsrDbgDumpSystemRecords(VOID) { ULONG index, count = SpAsrGetSystemRecordCount(); DbgStatusMesg((_asrinfo, "----- Dumping [SYSTEM] Section (%lu Records): -----\n", count)); for (index = 0; index < count; index++) { SpAsrDbgDumpSystemRecord(SpAsrGetSifKeyBySection(SIF_ASR_SYSTEMS_SECTION, index)); } DbgStatusMesg((_asrinfo, "----- End of [SYSTEM] Section (%lu Records) -----\n", count)); } VOID SpAsrDbgDumpDiskRecord(IN PWSTR Key) { PSIF_DISK_RECORD pRec = NULL; if (!Key) { return; } pRec = SpAsrGetDiskRecord(Key); if (!pRec) { return; } DbgMesg((_asrinfo, "Key:[%ws] = Sys:[%ws] SifDskNum:[%ws], SifDskSig:0x%lx, ScSz:%lu, TtlSc:%I64u", pRec->CurrDiskKey, pRec->SystemKey, pRec->SifDiskSignature, pRec->BytesPerSector, pRec->TotalSectors )); if (pRec->ExtendedPartitionStartSector > -1) { KdPrintEx((_asrinfo, ", extSS:%I64u, extSC:%I64u", pRec->ExtendedPartitionStartSector, pRec->ExtendedPartitionSectorCount)); } KdPrintEx((_asrinfo, "\n")); SpMemFree(pRec); } VOID SpAsrDbgDumpDiskRecords(VOID) { ULONG index, count = SpAsrGetMbrDiskRecordCount(); DbgStatusMesg((_asrinfo, "----- Dumping [DISK.MBR] Section (%lu Records): -----\n", count)); for (index = 0; index < count; index++) { SpAsrDbgDumpDiskRecord(SpAsrGetSifKeyBySection(SIF_ASR_MBR_DISKS_SECTION , index)); } DbgStatusMesg((_asrinfo, "----- End of [DISK.MBR] Section (%lu Records) -----\n", count)); count = SpAsrGetGptDiskRecordCount(); DbgStatusMesg((_asrinfo, "----- Dumping [DISK.GPT] Section (%lu Records): -----\n", count)); for (index = 0; index < count; index++) { SpAsrDbgDumpDiskRecord(SpAsrGetSifKeyBySection(SIF_ASR_GPT_DISKS_SECTION , index)); } DbgStatusMesg((_asrinfo, "----- End of [DISK.GPT] Section (%lu Records) -----\n", count)); } VOID SpAsrDbgDumpPartitionRecord(IN PARTITION_STYLE PartitinStyle, IN PWSTR Key) { PSIF_PARTITION_RECORD pRec = SpAsrGetPartitionRecord(Key); DbgMesg((_asrinfo, "Key:[%ws] = Dsk %ws, ntDir:[%ws], volGd:[%ws], actv:0x%x, type:0x%x, fs:0x%x boot:%ws, sys:%ws, SS:%I64u SC:%I64u sz:%I64u\n", pRec->CurrPartKey, pRec->DiskKey, SpAsrIsBootPartitionRecord(pRec->PartitionFlag) ? pRec->NtDirectoryName : L"n/a", pRec->VolumeGuid ? pRec->VolumeGuid : L"n/a", pRec->ActiveFlag, pRec->PartitionType, pRec->FileSystemType, SpAsrIsBootPartitionRecord(pRec->PartitionFlag) ? "Y" : "N", SpAsrIsSystemPartitionRecord(pRec->PartitionFlag) ? "Y" : "N", pRec->StartSector, pRec->SectorCount, pRec->SizeMB )); SpMemFree(pRec); } VOID SpAsrDbgDumpPartitionList(IN PSIF_PARTITION_RECORD_LIST pList) { PSIF_PARTITION_RECORD pRec; ASSERT(pList); DbgStatusMesg((_asrinfo, "----- Dumping Partition List: -----\n")); pRec = pList->First; while (pRec) { SpAsrDbgDumpPartitionRecord(pRec->CurrPartKey); pRec = pRec->Next; } DbgStatusMesg((_asrinfo, "----- End of Partition List -----\n")); } VOID SpAsrDbgDumpPartitionRecords(VOID) { ULONG index, count = SpAsrGetPartitionRecordCount(); DbgStatusMesg((_asrinfo, "----- Dumping [PARTITION] Section (%lu Records): -----\n", count)); for (index = 0; index < count; index++) { SpAsrDbgDumpPartitionRecord(SpAsrGetSifKeyBySection(SIF_ASR_MBR_PARTITIONS_SECTION, index)); } DbgStatusMesg((_asrinfo, "----- End of [PARTITION] Section (%lu Records) -----\n", count)); } VOID SpAsrDbgDumpInstallFileRecord(IN PWSTR Key) { PSIF_INSTALLFILE_RECORD pRec = SpAsrGetInstallFileRecord(Key,NULL); DbgMesg((_asrinfo, "Key:[%ws] = SysKey:[%ws], MediaLabel:[%ws], Media:[%ws], Src:[%ws], Dest:[%ws], Vendor:[%ws]", Key, pRec->SystemKey, pRec->SourceMediaExternalLabel, pRec->DiskDeviceName, pRec->SourceFilePath, pRec->DestinationFilePath, pRec->VendorString )); SpMemFree(pRec); } VOID SpAsrDbgDumpInstallFileRecords(VOID) { ULONG index, count = SpAsrGetInstallFilesRecordCount(); DbgStatusMesg((_asrinfo, "----- Dumping [INSTALLFILE] Section (%lu Records): -----\n", count)); for (index = 0; index < count; index++) { SpAsrDbgDumpInstallFileRecord(SpAsrGetSifKeyBySection(SIF_ASR_INSTALLFILES_SECTION, index)); } DbgStatusMesg((_asrinfo, "----- End of [INSTALLFILE] Section (%lu Records) -----\n", count)); } VOID SpAsrDbgDumpInstallFileList(IN PSIF_INSTALLFILE_LIST pList) { PSIF_INSTALLFILE_RECORD pRec; if (pList == NULL) { DbgStatusMesg((_asrinfo, "No 3rd party files are specified.\n")); } else { DbgStatusMesg((_asrinfo, "----- Dumping Install-file List: -----\n")); pRec = pList->First; while (pRec) { SpAsrDbgDumpInstallFileRecord(pRec->CurrKey); pRec = pRec->Next; } DbgStatusMesg((_asrinfo, "----- End of Install-file List -----\n")); } } VOID SpAsrDbgTestSifFunctions(VOID) { SpAsrDbgDumpSystemRecords(); SpAsrDbgDumpDiskRecords(); SpAsrDbgDumpPartitionRecords(); SpAsrDbgDumpInstallFileRecords(); } #endif // Debug routines