Source code of Windows XP (NT5)
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.

1956 lines
50 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. spdrsif.c
  5. Abstract:
  6. Contains all routines involved in reading attributes from the asr.sif
  7. file and constructing partition records.
  8. Terminology
  9. Restrictions:
  10. Revision History:
  11. Initial Code Michael Peterson (v-michpe) 21.Aug.1998
  12. Code cleanup and changes Guhan Suriyanarayanan (guhans) 21.Aug.1999
  13. --*/
  14. #include "spprecmp.h"
  15. #pragma hdrstop
  16. // Module identification for debug traces
  17. #define THIS_MODULE L" spdrsif.c"
  18. #define THIS_MODULE_CODE L"S"
  19. #define ASR_NULL_STRING (L"")
  20. //
  21. // Section names and other data used for retrieving information from the
  22. // asr.sif file
  23. //
  24. const PWSTR SIF_ASR_VERSION_SECTION = L"VERSION";
  25. const PWSTR SIF_ASR_SYSTEMS_SECTION = L"SYSTEMS";
  26. const PWSTR SIF_ASRFLAGS_SECTION = L"ASRFLAGS";
  27. const PWSTR SIF_ASR_BUSES_SECTION = L"BUSES";
  28. const PWSTR SIF_ASR_PARTITIONS_SECTION = L"PARTITIONS";
  29. const PWSTR SIF_ASR_DISKS_SECTION = L"DISKS";
  30. const PWSTR SIF_ASR_MBR_DISKS_SECTION = L"DISKS.MBR";
  31. const PWSTR SIF_ASR_GPT_DISKS_SECTION = L"DISKS.GPT";
  32. const PWSTR SIF_ASR_MBR_PARTITIONS_SECTION = L"PARTITIONS.MBR";
  33. const PWSTR SIF_ASR_GPT_PARTITIONS_SECTION = L"PARTITIONS.GPT";
  34. const PWSTR SIF_ASR_INSTALLFILES_SECTION = L"INSTALLFILES";
  35. const PWSTR SIF_ASR_SIGNATURE_KEY = L"Signature";
  36. const PWSTR SIF_ASR_PROVIDER_KEY = L"Provider";
  37. const PWSTR SIF_ASR_SIFVERSION_KEY = L"ASR-Version";
  38. const PWSTR ASR_SIF_RECOGNISED_SIGNATURE = L"$Windows NT$";
  39. const PWSTR ASR_SIF_RECOGNISED_VERSION = L"1.";
  40. const PWSTR ASR_FLOPPY_DEVICE_ALIAS = L"%FLOPPY%";
  41. const PWSTR ASR_CDROM_DEVICE_ALIAS = L"%CDROM%";
  42. const PWSTR ASR_SOURCE_DEVICE_ALIAS = L"%SETUPSOURCE%";
  43. const PWSTR ASR_SIF_TEMP_DIRECTORY_ALIAS = L"%TEMP%\\";
  44. const PWSTR ASR_SIF_TMP_DIRECTORY_ALIAS = L"%TMP%\\";
  45. const PWSTR ASR_SIF_SYSTEM_ROOT_ALIAS = L"%SystemRoot%\\";
  46. const PWSTR ASR_SIF_SILENT_REPARTITION_VALUE = L"SilentRepartition";
  47. extern const PWSTR ASR_FLOPPY0_DEVICE_PATH;
  48. extern const PWSTR ASR_CDROM0_DEVICE_PATH;
  49. extern const PWSTR ASR_TEMP_DIRECTORY_PATH;
  50. extern ULONG SuiteType;
  51. // Indices for the [SYSTEMS] section.
  52. typedef enum _SIF_SYSTEM_FIELD_INDEX {
  53. SIF_SYSTEM_NAME = 0, // Computer name (not used in textmode ASR)
  54. SIF_SYSTEM_PLATFORM, // x86 or ia64
  55. SIF_SYSTEM_OSVERSION, // Windows version
  56. SIF_SYSTEM_NT_DIRECTORY_NAME, // Windows directory
  57. SIF_SYSTEM_PARTITION_AUTOEXTEND_OPTION, // [optional]
  58. SIF_SYSTEM_PRODUCT_SUITE, // SKU information
  59. //
  60. // Time Zone Information (not used in textmode ASR)
  61. //
  62. SIF_SYSTEM_TIMEZONE_INFORMATION,
  63. SIF_SYSTEM_TIMEZONE_STANDARD_NAME,
  64. SIF_SYSTEM_TIMEZONE_DAYLIGHT_NAME,
  65. SIF_SYSTEM_NUMFIELDS // Must always be last
  66. } SIF_SYSTEM_FIELD_INDEX;
  67. // Indices for the [ASRFLAGS] section.
  68. typedef enum _SIF_ASRFLAGS_FIELD_INDEX {
  69. SIF_ASRFLAGS_SILENT_REPARTITION_OPTION = 0,
  70. SIF_ASRFLAGS_NUMFIELDS // Must always be last
  71. } SIF_ASRFLAGS_FIELD_INDEX;
  72. // Indices for the [BUSES] section.
  73. typedef enum _SIF_BUSES_FIELD_INDEX {
  74. SIF_BUSES_SYSTEMKEY = 0,
  75. SIF_BUSES_BUS_TYPE,
  76. SIF_BUSES_NUMFIELDS // Must always be last
  77. } SIF_BUSES_FIELD_INDEX;
  78. //
  79. // Indices for the [DISKS.MBR] section.
  80. //
  81. // [DISKS.MBR] format
  82. //
  83. // disk-key = 0.system-key, 1.bus-key, 2.critical-flag,
  84. // 3.disk-signature, 4.bytes-per-sector, 5.total-sectors
  85. //
  86. typedef enum _SIF_MBR_DISK_FIELD_INDEX {
  87. SIF_MBR_DISK_SYSTEMKEY = 0,
  88. SIF_MBR_DISK_BUSKEY,
  89. SIF_MBR_DISK_CRITICAL_FLAG,
  90. SIF_MBR_DISK_SIGNATURE,
  91. SIF_MBR_DISK_BYTES_PER_SECTOR,
  92. SIF_MBR_DISK_SECTORS_PER_TRACK,
  93. SIF_MBR_DISK_TRACKS_PER_CYLINDER,
  94. SIF_MBR_DISK_TOTALSECTORS,
  95. SIF_MBR_DISK_NUMFIELDS // Must always be last
  96. } SIF_MBR_DISK_FIELD_INDEX;
  97. //
  98. // Indices for the [DISKS.GPT] section.
  99. //
  100. // [DISKS.GPT] format
  101. //
  102. // disk-key = 0.system-key, 1.bus-key, 2.critical-flag, 3.disk-id,
  103. // 4.min-partition-count, 5.bytes-per-sector, 6.total-sectors
  104. //
  105. typedef enum _SIF_GPT_DISK_FIELD_INDEX {
  106. SIF_GPT_DISK_SYSTEMKEY = 0,
  107. SIF_GPT_DISK_BUSKEY,
  108. SIF_GPT_DISK_CRITICAL_FLAG,
  109. SIF_GPT_DISK_DISK_ID,
  110. SIF_GPT_DISK_MAX_PTN_COUNT,
  111. SIF_GPT_DISK_BYTES_PER_SECTOR,
  112. SIF_GPT_DISK_SECTORS_PER_TRACK,
  113. SIF_GPT_DISK_TRACKS_PER_CYLINDER,
  114. SIF_GPT_DISK_TOTALSECTORS,
  115. SIF_GPT_DISK_NUMFIELDS // Must always be last
  116. } SIF_GPT_DISK_FIELD_INDEX;
  117. //
  118. // Indices for the [PARTITIONS.MBR] section.
  119. //
  120. // [PARTITIONS.MBR]
  121. //
  122. // partition-key = 0.disk-key, 1.slot-index, 2.boot-sys-flag,
  123. // 3."volume-guid", 4.active-flag, 5.partition-type,
  124. // 6.file-system-type, 7.start-sector, 8.sector-count,
  125. // 9.fs-cluster-size
  126. //
  127. typedef enum _SIF_MBR_PARTITION_FIELD_INDEX {
  128. SIF_MBR_PARTITION_DISKKEY = 0,
  129. SIF_MBR_PARTITION_SLOT_INDEX,
  130. SIF_MBR_PARTITION_SYSBOOT_FLAGS,
  131. SIF_MBR_PARTITION_VOLUME_GUID, //optional
  132. SIF_MBR_PARTITION_ACTIVE_FLAG,
  133. SIF_MBR_PARTITION_PTN_TYPE,
  134. SIF_MBR_PARTITION_FS_TYPE,
  135. SIF_MBR_PARTITION_STARTSECTOR,
  136. SIF_MBR_PARTITION_SECTORCOUNT,
  137. SIF_MBR_PARTITION_CLUSTER_SIZE,
  138. SIF_MBR_PARTITION_NUMFIELDS // Must always be last
  139. } SIF_MBR_PARTITION_FIELD_INDEX;
  140. //
  141. // Indices for the [PARTITIONS.GPT] section.
  142. //
  143. // [PARTITIONS.GPT]
  144. //
  145. // partition-key = 0.disk-key, 1.slot-index, 2.boot-sys-flag,
  146. // 3."volume-guid", 4."partition-type-guid", 5."partition-id-guid"
  147. // 6.gpt-attributes, 7."partition-name", 8.file-system-type,
  148. // 9.start-sector, 10.sector-count, 11.fs-cluster-size
  149. //
  150. typedef enum _SIF_GPT_PARTITION_FIELD_INDEX {
  151. SIF_GPT_PARTITION_DISKKEY = 0,
  152. SIF_GPT_PARTITION_SLOT_INDEX,
  153. SIF_GPT_PARTITION_SYSBOOT_FLAGS,
  154. SIF_GPT_PARTITION_VOLUME_GUID, //optional
  155. SIF_GPT_PARTITION_TYPE_GUID,
  156. SIF_GPT_PARTITION_ID_GUID,
  157. SIF_GPT_PARTITION_GPT_ATTRIBUTES,
  158. SIF_GPT_PARTITION_NAME,
  159. SIF_GPT_PARTITION_FS_TYPE,
  160. SIF_GPT_PARTITION_STARTSECTOR,
  161. SIF_GPT_PARTITION_SECTORCOUNT,
  162. SIF_GPT_PARTITION_CLUSTER_SIZE,
  163. SIF_GPT_PARTITION_NUMFIELDS // Must always be last
  164. } SIF_GPT_PARTITION_FIELD_INDEX;
  165. // Indices for the [INSTALLFILES] section.
  166. typedef enum _SIF_INSTALLFILE_FIELD_INDEX {
  167. SIF_INSTALLFILE_SYSTEM_KEY = 0,
  168. SIF_INSTALLFILE_SOURCE_MEDIA_LABEL,
  169. SIF_INSTALLFILE_SOURCE_DEVICE,
  170. SIF_INSTALLFILE_SOURCE_FILE_PATH,
  171. SIF_INSTALLFILE_DESTFILE,
  172. SIF_INSTALLFILE_VENDORSTRING,
  173. SIF_INSTALLFILE_FLAGS,
  174. SIF_INSTALLFILE_NUMFIELDS // Must always be last
  175. } SIF_INSTALLFILE_FIELD_INDEX;
  176. // Global
  177. PVOID Gbl_HandleToDrStateFile;
  178. extern PWSTR Gbl_SifSourcePath;
  179. // Forward Declarations
  180. VOID
  181. SpAsrDbgDumpInstallFileList(IN PSIF_INSTALLFILE_LIST pList);
  182. PSIF_PARTITION_RECORD_LIST
  183. SpAsrCopyPartitionRecordList(PSIF_PARTITION_RECORD_LIST pSrcList);
  184. ///////////////////////////////
  185. // Generic functions for all sections
  186. //
  187. //
  188. // The string returned should not be freed, since it's part of Setup's internal sif
  189. // data structure!
  190. //
  191. PWSTR
  192. SpAsrGetSifDataBySectionAndKey(
  193. IN const PWSTR Section,
  194. IN const PWSTR Key,
  195. IN const ULONG Value,
  196. IN const BOOLEAN NonNullRequired
  197. ) // does not return on error if NonNullRequired is TRUE
  198. {
  199. PWSTR data = NULL;
  200. ASSERT(Section && Key); // debug
  201. data = SpGetSectionKeyIndex(
  202. Gbl_HandleToDrStateFile,
  203. Section,
  204. Key,
  205. Value
  206. );
  207. if (NonNullRequired) {
  208. if (!data || !wcscmp(data, ASR_NULL_STRING)) {
  209. DbgFatalMesg((_asrerr, "SpAsrGetSifDataBySectionAndKey. Data is "
  210. "NULL. Section:[%ws], Key:[%ws], Value:[%lu]\n",
  211. Section, Key, Value));
  212. swprintf(TemporaryBuffer, L"%lu value not specified in %ws "
  213. L"record %ws", Value, Section, Key);
  214. SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD,
  215. TemporaryBuffer, Section);
  216. // does not return
  217. }
  218. }
  219. return data;
  220. }
  221. ULONG
  222. SpAsrGetRecordCount(
  223. IN PWSTR Section,
  224. IN ULONG MinimumValid
  225. )
  226. {
  227. ULONG count;
  228. ASSERT(Section);
  229. count = SpCountLinesInSection(Gbl_HandleToDrStateFile, Section);
  230. if (count < MinimumValid) {
  231. DbgFatalMesg((_asrerr, "SpAsrGetRecordCount. No records in [%ws] section.\n",
  232. Section));
  233. swprintf(TemporaryBuffer, L"No records in section");
  234. SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD,
  235. TemporaryBuffer,
  236. Section);
  237. // does not return
  238. }
  239. return count;
  240. }
  241. PWSTR
  242. SpAsrGetSifKeyBySection(
  243. IN PWSTR Section,
  244. IN ULONG Index
  245. ) // does not return on error
  246. {
  247. PWSTR key;
  248. ULONG count = SpAsrGetRecordCount(Section, 1);
  249. // is index too big?
  250. if (Index > count) {
  251. DbgFatalMesg((_asrerr,
  252. "SpAsrGetSifKeyBySection. Section [%ws]. Index (%lu) greater than NumRecords (%lu)\n",
  253. Section,
  254. Index,
  255. count
  256. ));
  257. swprintf(TemporaryBuffer, L"Index too large: Key not found.");
  258. SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD,
  259. TemporaryBuffer,
  260. Section
  261. );
  262. // does not return
  263. }
  264. key = SpGetKeyName(Gbl_HandleToDrStateFile, Section, Index);
  265. if (!key || !wcscmp(key, ASR_NULL_STRING)) {
  266. DbgFatalMesg((_asrerr,
  267. "SpAsrGetSifKeyBySection. SpGetKeyName failed in Section:[%ws] for Index:%lu.\n",
  268. Section,
  269. Index
  270. ));
  271. swprintf(TemporaryBuffer, L"%ws key not found for record %lu", Section, Index + 1);
  272. SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD,
  273. TemporaryBuffer,
  274. Section
  275. );
  276. // does not return
  277. }
  278. return key;
  279. }
  280. ///////////////////////////////
  281. // [SYSTEMS] section functions
  282. //
  283. #define ASR_PRODUCTSUITES_TO_MATCH (( VER_SUITE_SMALLBUSINESS \
  284. | VER_SUITE_ENTERPRISE \
  285. | VER_SUITE_BACKOFFICE \
  286. | VER_SUITE_COMMUNICATIONS \
  287. | VER_SUITE_SMALLBUSINESS_RESTRICTED \
  288. | VER_SUITE_EMBEDDEDNT \
  289. | VER_SUITE_DATACENTER \
  290. | VER_SUITE_PERSONAL))
  291. //
  292. // This checks to make sure that Windows media being used for the recovery
  293. // is the same SKU as that in asr.sif (so the user isn't trying to recover
  294. // an ADS installation with a PRO CD, for instance), and that the platform
  295. // of the target machine is the same as that in asr.sif (so the user isn't
  296. // trying to recover an ia64 with an x86 asr.sif, for instance)
  297. //
  298. VOID
  299. SpAsrCheckSystemCompatibility()
  300. {
  301. PWSTR sifPlatform = NULL;
  302. WCHAR currentPlatform[10];
  303. DWORD suiteInSif = 0, currentSuite = 0, productInSif = 0;
  304. BOOLEAN validSKU = TRUE;
  305. sifPlatform = SpAsrGetSifDataBySectionAndKey(
  306. SIF_ASR_SYSTEMS_SECTION,
  307. ASR_SIF_SYSTEM_KEY,
  308. SIF_SYSTEM_PLATFORM,
  309. TRUE
  310. );
  311. wcscpy(currentPlatform, L"unknown");
  312. #if defined(_X86_)
  313. wcscpy(currentPlatform, L"x86");
  314. #elif defined(_IA64_)
  315. wcscpy(currentPlatform, L"ia64");
  316. #endif
  317. if (_wcsicmp(sifPlatform, currentPlatform)) {
  318. DbgFatalMesg((_asrerr,
  319. "asr.sif SYSTEM section. Invalid platform [%ws] (does not match the current platform)\n",
  320. sifPlatform
  321. ));
  322. SpAsrRaiseFatalError(
  323. SP_SCRN_DR_INCOMPATIBLE_MEDIA,
  324. L"Invalid platform"
  325. );
  326. }
  327. suiteInSif = STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey(
  328. SIF_ASR_SYSTEMS_SECTION,
  329. ASR_SIF_SYSTEM_KEY,
  330. SIF_SYSTEM_PRODUCT_SUITE,
  331. TRUE
  332. ));
  333. productInSif = HIWORD(suiteInSif);
  334. suiteInSif = LOWORD(suiteInSif) & ASR_PRODUCTSUITES_TO_MATCH;
  335. if (suiteInSif) {
  336. if (!SuiteType) {
  337. //
  338. // SuiteType is set to 0 for PRO and SRV, and so cannot directly be
  339. // used in SpIsProductSuite(). These are the values that SuiteType
  340. // seems to be set to:
  341. //
  342. // PER 0x200 VER_SUITE_PERSONAL
  343. // BLA 0x400 VER_SUITE_BLADE
  344. // PRO 0x0
  345. // SRV 0x0
  346. // ADS 0x2 VER_SUITE_ENTERPRISE
  347. // DTC 0x82 VER_SUITE_DATACENTER | VER_SUITE_ENTERPRISE
  348. //
  349. //
  350. //
  351. // Not sure of the reasoning behind this, but let's make use of this
  352. // fact (cf SpGetHeaderTextId)
  353. //
  354. //
  355. // Since SuiteType is 0, this must be PRO or SRV. This can be determined
  356. // by checking the global AdvancedServer
  357. //
  358. validSKU = (AdvancedServer ?
  359. (
  360. ((productInSif == VER_NT_SERVER) || // must be SRV
  361. (productInSif == VER_NT_DOMAIN_CONTROLLER)) && //
  362. !(suiteInSif | VER_SUITE_ENTERPRISE) // and not ADS or DTC
  363. )
  364. :
  365. ( (productInSif == VER_NT_WORKSTATION) && // must be PRO
  366. !(suiteInSif | VER_SUITE_PERSONAL) // and not PER
  367. )
  368. );
  369. }
  370. else if (
  371. ((productInSif != VER_NT_SERVER) && (productInSif != VER_NT_DOMAIN_CONTROLLER)) ||
  372. !SpIsProductSuite(suiteInSif)
  373. ) {
  374. validSKU = FALSE;
  375. }
  376. }
  377. if (!validSKU) {
  378. DbgFatalMesg((_asrerr,
  379. "asr.sif SYSTEM Section. Invalid suite 0x%08x (does not match the current media).\n",
  380. suiteInSif
  381. ));
  382. SpAsrRaiseFatalError(
  383. SP_SCRN_DR_INCOMPATIBLE_MEDIA,
  384. L"Invalid version"
  385. );
  386. }
  387. }
  388. ULONG
  389. SpAsrGetSystemRecordCount(VOID) // does not return on error
  390. {
  391. return SpAsrGetRecordCount(SIF_ASR_SYSTEMS_SECTION, 1);
  392. }
  393. PWSTR
  394. SpAsrGetNtDirectoryPathBySystemKey(IN PWSTR SystemKey) // does not return on error
  395. {
  396. return SpAsrGetSifDataBySectionAndKey(
  397. SIF_ASR_SYSTEMS_SECTION,
  398. SystemKey,
  399. SIF_SYSTEM_NT_DIRECTORY_NAME,
  400. TRUE
  401. );
  402. }
  403. BOOLEAN
  404. SpAsrGetAutoExtend(IN PWSTR SystemKey)
  405. {
  406. PWSTR value = NULL;
  407. ASSERT(SystemKey);
  408. value = SpGetSectionKeyIndex(
  409. Gbl_HandleToDrStateFile,
  410. SIF_ASR_SYSTEMS_SECTION,
  411. SystemKey,
  412. SIF_SYSTEM_PARTITION_AUTOEXTEND_OPTION
  413. );
  414. if (!value || !wcscmp(value, ASR_NULL_STRING)) {
  415. DbgErrorMesg((_asrwarn, "Auto-extend not specified, assuming Enabled\n"));
  416. return TRUE;
  417. }
  418. else {
  419. return (BOOLEAN) STRING_TO_LONG(value);
  420. }
  421. }
  422. ///////////////////////////////
  423. // [ASRFLAGS] section functions
  424. //
  425. BOOLEAN
  426. SpAsrGetSilentRepartitionFlag(IN PWSTR SystemKey)
  427. {
  428. PWSTR value = NULL;
  429. ASSERT(SystemKey);
  430. value = SpGetSectionKeyIndex(
  431. Gbl_HandleToDrStateFile,
  432. SIF_ASRFLAGS_SECTION,
  433. SystemKey,
  434. SIF_ASRFLAGS_SILENT_REPARTITION_OPTION
  435. );
  436. if (value && !_wcsicmp(value, ASR_SIF_SILENT_REPARTITION_VALUE)) {
  437. DbgErrorMesg((_asrwarn, "SilentRepartition flag is set; will NOT prompt before repartitioning disks!\n"));
  438. return TRUE;
  439. }
  440. DbgStatusMesg((_asrinfo, "SilentRepartition flag not set; will prompt user before repartitioning disks\n"));
  441. return FALSE;
  442. }
  443. ///////////////////////////////
  444. // [VERSION] section functions
  445. //
  446. VOID
  447. SpAsrCheckAsrStateFileVersion()
  448. {
  449. PWSTR signature = NULL,
  450. provider = NULL,
  451. sifVersion = NULL;
  452. signature = SpAsrGetSifDataBySectionAndKey(
  453. SIF_ASR_VERSION_SECTION,
  454. SIF_ASR_SIGNATURE_KEY,
  455. 0,
  456. TRUE
  457. );
  458. provider = SpAsrGetSifDataBySectionAndKey(
  459. SIF_ASR_VERSION_SECTION,
  460. SIF_ASR_PROVIDER_KEY,
  461. 0,
  462. FALSE
  463. ); // ProviderName is optional
  464. sifVersion = SpAsrGetSifDataBySectionAndKey(
  465. SIF_ASR_VERSION_SECTION,
  466. SIF_ASR_SIFVERSION_KEY,
  467. 0,
  468. TRUE
  469. );
  470. DbgStatusMesg((_asrinfo,
  471. "Asr Sif Version. sig:[%ws], provider:[%ws], sifVer:[%ws]\n",
  472. signature,
  473. provider ? provider : L"",
  474. sifVersion
  475. ));
  476. if (_wcsicmp(signature, ASR_SIF_RECOGNISED_SIGNATURE)) {
  477. DbgFatalMesg((_asrerr,
  478. "asr.sif VERSION section. Invalid signature [%ws] (it MUST be $Windows NT$).\n",
  479. signature
  480. ));
  481. SpAsrRaiseFatalError(
  482. SP_TEXT_DR_STATEFILE_ERROR,
  483. L"Invalid signature"
  484. );
  485. }
  486. if (_wcsnicmp(sifVersion, ASR_SIF_RECOGNISED_VERSION, wcslen(ASR_SIF_RECOGNISED_VERSION))) {
  487. DbgFatalMesg((_asrerr,
  488. "asr.sif VERSION Section. Invalid asr.sif version [%ws] (it MUST be 1.x).\n",
  489. sifVersion
  490. ));
  491. SpAsrRaiseFatalError(
  492. SP_TEXT_DR_STATEFILE_ERROR,
  493. L"Invalid version"
  494. );
  495. }
  496. SpAsrCheckSystemCompatibility();
  497. }
  498. /////////////////////////////////
  499. // InstallFiles section functions
  500. //
  501. ULONG
  502. SpAsrGetInstallFilesRecordCount(VOID) // does not return on error
  503. {
  504. return SpAsrGetRecordCount(SIF_ASR_INSTALLFILES_SECTION, 0);
  505. }
  506. PSIF_INSTALLFILE_RECORD
  507. SpAsrGetInstallFileRecord(IN PWSTR InstallFileKey, IN PCWSTR SetupSourceDevicePath)
  508. {
  509. PSIF_INSTALLFILE_RECORD pRec = NULL;
  510. PWSTR tempStr = NULL;
  511. BOOL isValid = FALSE;
  512. if (!InstallFileKey) {
  513. DbgFatalMesg((_asrerr, "SpAsrGetInstallFileRecord. InstallFileKey is NULL\n"));
  514. SpAsrRaiseFatalErrorWs(
  515. SP_SCRN_DR_SIF_BAD_RECORD,
  516. L"InstallFileKey is NULL",
  517. SIF_ASR_INSTALLFILES_SECTION
  518. );
  519. }
  520. pRec = SpAsrMemAlloc(sizeof(SIF_INSTALLFILE_RECORD), TRUE);
  521. pRec->SystemKey = SpAsrGetSifDataBySectionAndKey(
  522. SIF_ASR_INSTALLFILES_SECTION,
  523. InstallFileKey,
  524. SIF_INSTALLFILE_SYSTEM_KEY,
  525. TRUE
  526. );
  527. pRec->CurrKey = InstallFileKey;
  528. pRec->SourceMediaExternalLabel = SpAsrGetSifDataBySectionAndKey(
  529. SIF_ASR_INSTALLFILES_SECTION,
  530. InstallFileKey,
  531. SIF_INSTALLFILE_SOURCE_MEDIA_LABEL,
  532. TRUE
  533. );
  534. tempStr = SpAsrGetSifDataBySectionAndKey(
  535. SIF_ASR_INSTALLFILES_SECTION,
  536. InstallFileKey,
  537. SIF_INSTALLFILE_SOURCE_DEVICE,
  538. TRUE
  539. );
  540. //
  541. // Check if the device is specified as %FLOPPY%, %CDROM% or %SETUPSOURCE%,
  542. // and use the full path (\device\floppy0 or \device\CdRom0 or
  543. // SetupSourceDevicePath) if so.
  544. //
  545. if (!_wcsicmp(tempStr, ASR_FLOPPY_DEVICE_ALIAS)) {
  546. pRec->DiskDeviceName = SpDupStringW(ASR_FLOPPY0_DEVICE_PATH);
  547. }
  548. else if (!_wcsicmp(tempStr, ASR_CDROM_DEVICE_ALIAS)) {
  549. pRec->DiskDeviceName = SpDupStringW(ASR_CDROM0_DEVICE_PATH);
  550. }
  551. else if (!_wcsicmp(tempStr, ASR_SOURCE_DEVICE_ALIAS) && SetupSourceDevicePath) {
  552. pRec->DiskDeviceName = SpDupStringW(SetupSourceDevicePath);
  553. }
  554. else {
  555. //
  556. // It wasn't any of the aliases--he's allowed to specify
  557. // the full device path, so we use it as is.
  558. //
  559. pRec->DiskDeviceName = SpDupStringW(tempStr);
  560. }
  561. pRec->SourceFilePath = (PWSTR) SpAsrGetSifDataBySectionAndKey(
  562. SIF_ASR_INSTALLFILES_SECTION,
  563. InstallFileKey,
  564. SIF_INSTALLFILE_SOURCE_FILE_PATH,
  565. TRUE
  566. );
  567. tempStr = (PWSTR) SpAsrGetSifDataBySectionAndKey(
  568. SIF_ASR_INSTALLFILES_SECTION,
  569. InstallFileKey,
  570. SIF_INSTALLFILE_DESTFILE,
  571. TRUE
  572. );
  573. //
  574. // Set the CopyToDirectory based on the tempStr path
  575. //
  576. if (!_wcsnicmp(tempStr, ASR_SIF_TEMP_DIRECTORY_ALIAS, wcslen(ASR_SIF_TEMP_DIRECTORY_ALIAS))) {
  577. //
  578. // Begins is %TEMP%\
  579. //
  580. pRec->CopyToDirectory = _Temp;
  581. pRec->DestinationFilePath = SpDupStringW((PWSTR)(&tempStr[wcslen(ASR_SIF_TEMP_DIRECTORY_ALIAS)]));
  582. }
  583. else if (!_wcsnicmp(tempStr, ASR_SIF_TMP_DIRECTORY_ALIAS, wcslen(ASR_SIF_TMP_DIRECTORY_ALIAS))) {
  584. //
  585. // Begins is %TMP%\
  586. //
  587. pRec->CopyToDirectory = _Tmp;
  588. pRec->DestinationFilePath = SpDupStringW((PWSTR)(&tempStr[wcslen(ASR_SIF_TMP_DIRECTORY_ALIAS)]));
  589. }
  590. else if (!_wcsnicmp(tempStr, ASR_SIF_SYSTEM_ROOT_ALIAS, wcslen(ASR_SIF_SYSTEM_ROOT_ALIAS))) {
  591. //
  592. // Begins is %SYSTEMROOT%\
  593. //
  594. pRec->CopyToDirectory = _SystemRoot;
  595. pRec->DestinationFilePath = SpDupStringW((PWSTR)(&tempStr[wcslen(ASR_SIF_SYSTEM_ROOT_ALIAS)]));
  596. }
  597. else {
  598. //
  599. // Not specified, or unknown: use default.
  600. //
  601. pRec->CopyToDirectory = _Default;
  602. pRec->DestinationFilePath = SpDupStringW(tempStr);
  603. }
  604. pRec->VendorString = SpAsrGetSifDataBySectionAndKey(
  605. SIF_ASR_INSTALLFILES_SECTION,
  606. InstallFileKey,
  607. SIF_INSTALLFILE_VENDORSTRING,
  608. TRUE
  609. );
  610. tempStr = SpAsrGetSifDataBySectionAndKey(
  611. SIF_ASR_INSTALLFILES_SECTION,
  612. InstallFileKey,
  613. SIF_INSTALLFILE_FLAGS,
  614. FALSE
  615. );
  616. if (tempStr) {
  617. pRec->Flags = STRING_TO_HEX(tempStr);
  618. }
  619. return pRec;
  620. }
  621. VOID
  622. SpAsrInsertInstallFileRecord(
  623. IN SIF_INSTALLFILE_LIST *InstallFileList,
  624. IN PSIF_INSTALLFILE_RECORD pRec
  625. )
  626. {
  627. pRec->Next = InstallFileList->First;
  628. InstallFileList->First = pRec;
  629. InstallFileList->Count += 1;
  630. }
  631. PSIF_INSTALLFILE_RECORD
  632. SpAsrRemoveInstallFileRecord(IN SIF_INSTALLFILE_LIST *InstallFileList)
  633. {
  634. PSIF_INSTALLFILE_RECORD pRec = NULL;
  635. if (InstallFileList->Count > 0) {
  636. pRec = InstallFileList->First;
  637. InstallFileList->First = pRec->Next;
  638. InstallFileList->Count -= 1;
  639. }
  640. return pRec;
  641. }
  642. VOID
  643. SpAsrDeleteInstallFileRecord(
  644. IN OUT PSIF_INSTALLFILE_RECORD pRec
  645. )
  646. {
  647. //
  648. // Free the memory we allocated. The other fields are pointers to
  649. // setup's internal inf data structure, we shouldn't free those
  650. // else they'd get freed twice.
  651. //
  652. if (pRec->DiskDeviceName) {
  653. SpMemFree(pRec->DiskDeviceName);
  654. pRec->DiskDeviceName = NULL;
  655. }
  656. if (pRec->DestinationFilePath) {
  657. SpMemFree(pRec->DestinationFilePath);
  658. pRec->DestinationFilePath = NULL;
  659. }
  660. SpMemFree(pRec);
  661. pRec = NULL;
  662. }
  663. PSIF_INSTALLFILE_LIST
  664. SpAsrInit3rdPartyFileList(IN PCWSTR SetupSourceDevicePath)
  665. {
  666. PSIF_INSTALLFILE_RECORD pRec;
  667. PSIF_INSTALLFILE_LIST pList = NULL;
  668. ULONG count, index;
  669. if ((count = SpAsrGetInstallFilesRecordCount()) == 0) {
  670. return NULL;
  671. }
  672. pList = SpAsrMemAlloc(sizeof(SIF_INSTALLFILE_LIST), TRUE);
  673. for (index = 0; index < count; index++) {
  674. pRec = SpAsrGetInstallFileRecord(SpAsrGetSifKeyBySection(SIF_ASR_INSTALLFILES_SECTION, index), SetupSourceDevicePath);
  675. DbgStatusMesg((_asrinfo, "SpAsrInit3rdPartyFileList. Adding [%ws] to list\n", pRec->SourceFilePath));
  676. SpAsrInsertInstallFileRecord(pList, pRec);
  677. }
  678. return pList;
  679. }
  680. ////////////////////////////
  681. // [BUSES] section function
  682. //
  683. STORAGE_BUS_TYPE
  684. SpAsrGetBusType(IN ULONG Index)
  685. {
  686. STORAGE_BUS_TYPE BusType;
  687. PWSTR BusKey = SpAsrGetSifKeyBySection(SIF_ASR_BUSES_SECTION, Index);
  688. BusType = (STORAGE_BUS_TYPE) (STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  689. SIF_ASR_BUSES_SECTION,
  690. BusKey,
  691. SIF_BUSES_BUS_TYPE,
  692. TRUE
  693. )));
  694. return BusType;
  695. }
  696. ////////////////////////////
  697. // [DISKS] section function
  698. //
  699. //
  700. // Returns the total number of disk records (both MBR and GPT)
  701. //
  702. ULONG
  703. SpAsrGetGptDiskRecordCount(VOID) // does not return on error
  704. {
  705. static ULONG Count = (ULONG) (-1);
  706. if ((ULONG) (-1) == Count) {
  707. Count = SpAsrGetRecordCount(SIF_ASR_GPT_DISKS_SECTION, 0);
  708. }
  709. return Count;
  710. }
  711. ULONG
  712. SpAsrGetMbrDiskRecordCount(VOID) // does not return on error
  713. {
  714. static ULONG Count = (ULONG) (-1);
  715. if ((ULONG) (-1) == Count) {
  716. Count = SpAsrGetRecordCount(SIF_ASR_MBR_DISKS_SECTION, 0);
  717. }
  718. return Count;
  719. }
  720. ULONG
  721. SpAsrGetDiskRecordCount(VOID) // does not return on error
  722. {
  723. static ULONG Total = (ULONG) (-1);
  724. if ((ULONG) (-1) == Total ) {
  725. Total = SpAsrGetMbrDiskRecordCount() + SpAsrGetGptDiskRecordCount();
  726. }
  727. return Total;
  728. }
  729. PWSTR
  730. SpAsrGetDiskKey(
  731. IN PARTITION_STYLE Style, // GPT or MBR
  732. IN ULONG Index
  733. ) // does not return on error
  734. {
  735. switch (Style) {
  736. case PARTITION_STYLE_GPT:
  737. return SpAsrGetSifKeyBySection(SIF_ASR_GPT_DISKS_SECTION, Index);
  738. break;
  739. case PARTITION_STYLE_MBR:
  740. return SpAsrGetSifKeyBySection(SIF_ASR_MBR_DISKS_SECTION, Index);
  741. break;
  742. }
  743. ASSERT(0 && L"Illegal partition style specified");
  744. return NULL;
  745. }
  746. PSIF_DISK_RECORD
  747. SpAsrGetMbrDiskRecord(
  748. IN PWSTR DiskKey
  749. )
  750. {
  751. PSIF_DISK_RECORD pRec;
  752. if (!DiskKey) {
  753. ASSERT(0 && L"SpAsrGetMbrDiskRecord: DiskKey is NULL!");
  754. return NULL;
  755. }
  756. pRec = SpAsrMemAlloc(sizeof(SIF_DISK_RECORD), TRUE);
  757. //
  758. // This is an MBR disk
  759. //
  760. pRec->PartitionStyle = PARTITION_STYLE_MBR;
  761. //
  762. // [DISKS.MBR] format
  763. //
  764. // 0.disk-key = 1.system-key, 2.bus-key, 3.critical-flag,
  765. // 4.disk-signature, 5.bytes-per-sector, 6.total-sectors
  766. //
  767. pRec->CurrDiskKey = DiskKey;
  768. pRec->SystemKey = SpAsrGetSifDataBySectionAndKey(
  769. SIF_ASR_MBR_DISKS_SECTION ,
  770. DiskKey,
  771. SIF_MBR_DISK_SYSTEMKEY,
  772. TRUE
  773. );
  774. pRec->BusKey = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  775. SIF_ASR_MBR_DISKS_SECTION ,
  776. DiskKey,
  777. SIF_MBR_DISK_BUSKEY,
  778. TRUE
  779. ));
  780. pRec->BusType = SpAsrGetBusType(pRec->BusKey - 1); // our key is 1 based, AsrGetBusType index is 0 based
  781. if (ASRMODE_NORMAL != SpAsrGetAsrMode()) {
  782. pRec->IsCritical = TRUE;
  783. }
  784. else {
  785. pRec->IsCritical = (STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  786. SIF_ASR_MBR_DISKS_SECTION ,
  787. DiskKey,
  788. SIF_MBR_DISK_CRITICAL_FLAG,
  789. TRUE
  790. ))) ? TRUE : FALSE;
  791. }
  792. pRec->SifDiskMbrSignature = STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey(
  793. SIF_ASR_MBR_DISKS_SECTION ,
  794. DiskKey,
  795. SIF_MBR_DISK_SIGNATURE,
  796. TRUE
  797. ));
  798. pRec->BytesPerSector = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  799. SIF_ASR_MBR_DISKS_SECTION ,
  800. DiskKey,
  801. SIF_MBR_DISK_BYTES_PER_SECTOR,
  802. TRUE
  803. ));
  804. pRec->SectorsPerTrack = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  805. SIF_ASR_MBR_DISKS_SECTION ,
  806. DiskKey,
  807. SIF_MBR_DISK_SECTORS_PER_TRACK,
  808. TRUE
  809. ));
  810. pRec->TracksPerCylinder = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  811. SIF_ASR_MBR_DISKS_SECTION ,
  812. DiskKey,
  813. SIF_MBR_DISK_TRACKS_PER_CYLINDER,
  814. TRUE
  815. ));
  816. pRec->TotalSectors = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey(
  817. SIF_ASR_MBR_DISKS_SECTION ,
  818. DiskKey,
  819. SIF_MBR_DISK_TOTALSECTORS,
  820. TRUE
  821. ));
  822. return pRec;
  823. }
  824. PSIF_DISK_RECORD
  825. SpAsrGetGptDiskRecord(
  826. IN PWSTR DiskKey
  827. )
  828. {
  829. PSIF_DISK_RECORD pRec = NULL;
  830. PWSTR GuidString = NULL;
  831. if (!DiskKey) {
  832. ASSERT(0 && L"SpAsrGetGptDiskRecord: DiskKey is NULL!");
  833. return NULL;
  834. }
  835. pRec = SpAsrMemAlloc(sizeof(SIF_DISK_RECORD), TRUE);
  836. pRec->PartitionStyle = PARTITION_STYLE_GPT;
  837. //
  838. // [DISKS.GPT] format
  839. //
  840. // 0.disk-key = 1.system-key, 2.bus-key, 3.critical-flag, 4.disk-id,
  841. // 5.min-partition-count, 6.bytes-per-sector, 7.total-sectors
  842. //
  843. pRec->CurrDiskKey = DiskKey;
  844. pRec->SystemKey = SpAsrGetSifDataBySectionAndKey(
  845. SIF_ASR_GPT_DISKS_SECTION,
  846. DiskKey,
  847. SIF_GPT_DISK_SYSTEMKEY,
  848. TRUE
  849. );
  850. pRec->BusKey = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  851. SIF_ASR_GPT_DISKS_SECTION ,
  852. DiskKey,
  853. SIF_GPT_DISK_BUSKEY,
  854. TRUE
  855. ));
  856. pRec->BusType = SpAsrGetBusType(pRec->BusKey - 1); // our key is 1 based, AsrGetBusType index is 0 based
  857. if (ASRMODE_NORMAL != SpAsrGetAsrMode()) {
  858. pRec->IsCritical = TRUE;
  859. }
  860. else {
  861. pRec->IsCritical = (STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  862. SIF_ASR_GPT_DISKS_SECTION ,
  863. DiskKey,
  864. SIF_GPT_DISK_CRITICAL_FLAG,
  865. TRUE
  866. ))) ? TRUE : FALSE;
  867. }
  868. GuidString = SpAsrGetSifDataBySectionAndKey(
  869. SIF_ASR_GPT_DISKS_SECTION ,
  870. DiskKey,
  871. SIF_GPT_DISK_DISK_ID,
  872. TRUE
  873. );
  874. SpAsrGuidFromString(&(pRec->SifDiskGptId), GuidString);
  875. pRec->MaxGptPartitionCount = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  876. SIF_ASR_GPT_DISKS_SECTION ,
  877. DiskKey,
  878. SIF_GPT_DISK_MAX_PTN_COUNT,
  879. TRUE
  880. ));
  881. pRec->BytesPerSector = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  882. SIF_ASR_GPT_DISKS_SECTION ,
  883. DiskKey,
  884. SIF_GPT_DISK_BYTES_PER_SECTOR,
  885. TRUE
  886. ));
  887. pRec->SectorsPerTrack = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  888. SIF_ASR_GPT_DISKS_SECTION ,
  889. DiskKey,
  890. SIF_GPT_DISK_SECTORS_PER_TRACK,
  891. TRUE
  892. ));
  893. pRec->TracksPerCylinder = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  894. SIF_ASR_GPT_DISKS_SECTION ,
  895. DiskKey,
  896. SIF_GPT_DISK_TRACKS_PER_CYLINDER,
  897. TRUE
  898. ));
  899. pRec->TotalSectors = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey(
  900. SIF_ASR_GPT_DISKS_SECTION ,
  901. DiskKey,
  902. SIF_GPT_DISK_TOTALSECTORS,
  903. TRUE
  904. ));
  905. return pRec;
  906. }
  907. PSIF_DISK_RECORD
  908. SpAsrGetDiskRecord(
  909. IN PARTITION_STYLE PartitionStyle,
  910. IN PWSTR DiskKey
  911. )
  912. {
  913. switch (PartitionStyle) {
  914. case PARTITION_STYLE_MBR:
  915. return SpAsrGetMbrDiskRecord(DiskKey);
  916. break;
  917. case PARTITION_STYLE_GPT:
  918. return SpAsrGetGptDiskRecord(DiskKey);
  919. break;
  920. }
  921. ASSERT(0 && L"Invalid partition type specified");
  922. return NULL;
  923. }
  924. PSIF_DISK_RECORD
  925. SpAsrCopyDiskRecord(IN PSIF_DISK_RECORD pInput)
  926. {
  927. PSIF_DISK_RECORD pRec;
  928. pRec = SpAsrMemAlloc(sizeof(SIF_DISK_RECORD), TRUE);
  929. CopyMemory(pRec, pInput, sizeof(SIF_DISK_RECORD));
  930. pRec->PartitionList = NULL;
  931. // copy the list of partitions, if any.
  932. if (pInput->PartitionList) {
  933. pRec->PartitionList = SpAsrCopyPartitionRecordList(pInput->PartitionList);
  934. }
  935. return pRec;
  936. }
  937. ////////////////////////////////
  938. // [PARTITIONS] section function
  939. //
  940. ULONG
  941. SpAsrGetMbrPartitionRecordCount(VOID)
  942. {
  943. return SpAsrGetRecordCount(SIF_ASR_MBR_PARTITIONS_SECTION, 0);
  944. }
  945. ULONG
  946. SpAsrGetGptPartitionRecordCount(VOID)
  947. {
  948. return SpAsrGetRecordCount(SIF_ASR_GPT_PARTITIONS_SECTION, 0);
  949. }
  950. PWSTR
  951. SpAsrGetMbrPartitionKey(ULONG Index)
  952. {
  953. return SpAsrGetSifKeyBySection(
  954. SIF_ASR_MBR_PARTITIONS_SECTION,
  955. Index);
  956. }
  957. PWSTR
  958. SpAsrGetGptPartitionKey(ULONG Index)
  959. {
  960. return SpAsrGetSifKeyBySection(
  961. SIF_ASR_GPT_PARTITIONS_SECTION,
  962. Index);
  963. }
  964. PWSTR
  965. SpAsrGetDiskKeyByMbrPartitionKey(IN PWSTR PartitionKey)
  966. {
  967. return SpAsrGetSifDataBySectionAndKey(
  968. SIF_ASR_MBR_PARTITIONS_SECTION,
  969. PartitionKey,
  970. SIF_MBR_PARTITION_DISKKEY,
  971. TRUE);
  972. }
  973. PWSTR
  974. SpAsrGetDiskKeyByGptPartitionKey(IN PWSTR PartitionKey)
  975. {
  976. return SpAsrGetSifDataBySectionAndKey(
  977. SIF_ASR_GPT_PARTITIONS_SECTION,
  978. PartitionKey,
  979. SIF_GPT_PARTITION_DISKKEY,
  980. TRUE);
  981. }
  982. ULONGLONG
  983. SpAsrGetSectorCountByMbrDiskKey(
  984. IN PWSTR DiskKey
  985. )
  986. {
  987. return STRING_TO_ULONGLONG(SpAsrGetSifDataBySectionAndKey(
  988. SIF_ASR_MBR_DISKS_SECTION,
  989. DiskKey,
  990. SIF_MBR_DISK_TOTALSECTORS,
  991. FALSE
  992. ));
  993. }
  994. ULONGLONG
  995. SpAsrGetSectorCountByGptDiskKey(
  996. IN PWSTR DiskKey
  997. )
  998. {
  999. return STRING_TO_ULONGLONG(SpAsrGetSifDataBySectionAndKey(
  1000. SIF_ASR_GPT_DISKS_SECTION,
  1001. DiskKey,
  1002. SIF_GPT_DISK_TOTALSECTORS,
  1003. FALSE
  1004. ));
  1005. }
  1006. //
  1007. // Reads in a partition record from the [PARTITIONS.MBR] section.
  1008. //
  1009. // [PARTITIONS.MBR]
  1010. //
  1011. // partition-key = 0.disk-key, 1.slot-index, 2.boot-sys-flag,
  1012. // 3."volume-guid", 4.active-flag, 5.partition-type,
  1013. // 6.file-system-type, 7.start-sector, 8.sector-count
  1014. //
  1015. PSIF_PARTITION_RECORD
  1016. SpAsrGetMbrPartitionRecord(IN PWSTR PartitionKey)
  1017. {
  1018. PSIF_PARTITION_RECORD pRec = NULL;
  1019. ULONG bytesPerSector = 0;
  1020. ULONG ntSysMask = 0;
  1021. //
  1022. // PartitionKey better not be null
  1023. //
  1024. if (!PartitionKey) {
  1025. DbgErrorMesg((_asrwarn, "SpAsrGetPartitionRecord. PartitionKey is NULL\n"));
  1026. ASSERT(0 && L"Partition key is NULL");
  1027. return NULL;
  1028. }
  1029. pRec = SpAsrMemAlloc(sizeof(SIF_PARTITION_RECORD), TRUE);
  1030. //
  1031. // Read in the fields
  1032. //
  1033. pRec->CurrPartKey = PartitionKey;
  1034. pRec->PartitionStyle = PARTITION_STYLE_MBR;
  1035. pRec->DiskKey = SpAsrGetDiskKeyByMbrPartitionKey(PartitionKey);
  1036. pRec->PartitionTableEntryIndex = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  1037. SIF_ASR_MBR_PARTITIONS_SECTION,
  1038. PartitionKey,
  1039. SIF_MBR_PARTITION_SLOT_INDEX,
  1040. TRUE
  1041. ));
  1042. pRec->PartitionFlag = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  1043. SIF_ASR_MBR_PARTITIONS_SECTION,
  1044. PartitionKey,
  1045. SIF_MBR_PARTITION_SYSBOOT_FLAGS,
  1046. TRUE
  1047. ));
  1048. pRec->VolumeGuid = SpAsrGetSifDataBySectionAndKey(
  1049. SIF_ASR_MBR_PARTITIONS_SECTION,
  1050. PartitionKey,
  1051. SIF_MBR_PARTITION_VOLUME_GUID,
  1052. FALSE
  1053. );
  1054. pRec->ActiveFlag = (UCHAR) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey(
  1055. SIF_ASR_MBR_PARTITIONS_SECTION,
  1056. PartitionKey,
  1057. SIF_MBR_PARTITION_ACTIVE_FLAG,
  1058. TRUE
  1059. ));
  1060. pRec->PartitionType = (UCHAR) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey(
  1061. SIF_ASR_MBR_PARTITIONS_SECTION,
  1062. PartitionKey,
  1063. SIF_MBR_PARTITION_PTN_TYPE,
  1064. TRUE
  1065. ));
  1066. pRec->FileSystemType = (UCHAR) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey(
  1067. SIF_ASR_MBR_PARTITIONS_SECTION,
  1068. PartitionKey,
  1069. SIF_MBR_PARTITION_FS_TYPE,
  1070. TRUE
  1071. ));
  1072. pRec->StartSector = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey(
  1073. SIF_ASR_MBR_PARTITIONS_SECTION,
  1074. PartitionKey,
  1075. SIF_MBR_PARTITION_STARTSECTOR,
  1076. TRUE
  1077. ));
  1078. pRec->SectorCount = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey(
  1079. SIF_ASR_MBR_PARTITIONS_SECTION,
  1080. PartitionKey,
  1081. SIF_MBR_PARTITION_SECTORCOUNT,
  1082. TRUE
  1083. ));
  1084. pRec->ClusterSize = (DWORD) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey(
  1085. SIF_ASR_MBR_PARTITIONS_SECTION,
  1086. PartitionKey,
  1087. SIF_MBR_PARTITION_CLUSTER_SIZE,
  1088. TRUE
  1089. ));
  1090. if (SpAsrIsBootPartitionRecord(pRec->PartitionFlag)) {
  1091. // do not free!
  1092. PWSTR ntDirPath = SpAsrGetNtDirectoryPathBySystemKey(ASR_SIF_SYSTEM_KEY);
  1093. if (!SpAsrIsValidBootDrive(ntDirPath)) {
  1094. SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD,
  1095. L"ASSERT FAILURE: Improperly formed NT Directory Name",
  1096. SIF_ASR_MBR_PARTITIONS_SECTION
  1097. );
  1098. // does not return
  1099. }
  1100. pRec->NtDirectoryName = SpAsrMemAlloc((SpGetMaxNtDirLen()*sizeof(WCHAR)), TRUE);
  1101. wcsncpy(pRec->NtDirectoryName, ntDirPath + 2, wcslen(ntDirPath) - 2);
  1102. }
  1103. else {
  1104. pRec->NtDirectoryName = NULL;
  1105. }
  1106. bytesPerSector = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  1107. SIF_ASR_MBR_DISKS_SECTION ,
  1108. pRec->DiskKey,
  1109. SIF_MBR_DISK_BYTES_PER_SECTOR,
  1110. TRUE
  1111. ));
  1112. pRec->SizeMB = SpAsrConvertSectorsToMB(pRec->SectorCount, bytesPerSector);
  1113. return pRec;
  1114. }
  1115. PSIF_PARTITION_RECORD
  1116. SpAsrGetGptPartitionRecord(IN PWSTR PartitionKey)
  1117. {
  1118. PSIF_PARTITION_RECORD pRec = NULL;
  1119. ULONG bytesPerSector = 0;
  1120. ULONG ntSysMask = 0;
  1121. PWSTR GuidString = NULL;
  1122. if (!PartitionKey) {
  1123. DbgErrorMesg((_asrwarn, "SpAsrGetPartitionRecord. PartitionKey is NULL\n"));
  1124. ASSERT(0 && L"Partition key is NULL");
  1125. return NULL;
  1126. }
  1127. pRec = SpAsrMemAlloc(sizeof(SIF_PARTITION_RECORD), TRUE);
  1128. //
  1129. // Read in the fields
  1130. //
  1131. pRec->CurrPartKey = PartitionKey;
  1132. pRec->PartitionStyle = PARTITION_STYLE_GPT;
  1133. pRec->DiskKey = SpAsrGetDiskKeyByGptPartitionKey(PartitionKey);
  1134. pRec->PartitionTableEntryIndex = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  1135. SIF_ASR_GPT_PARTITIONS_SECTION,
  1136. PartitionKey,
  1137. SIF_GPT_PARTITION_SLOT_INDEX,
  1138. TRUE
  1139. ));
  1140. pRec->PartitionFlag = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  1141. SIF_ASR_GPT_PARTITIONS_SECTION,
  1142. PartitionKey,
  1143. SIF_GPT_PARTITION_SYSBOOT_FLAGS,
  1144. TRUE
  1145. ));
  1146. pRec->VolumeGuid = SpAsrGetSifDataBySectionAndKey(
  1147. SIF_ASR_GPT_PARTITIONS_SECTION,
  1148. PartitionKey,
  1149. SIF_GPT_PARTITION_VOLUME_GUID,
  1150. FALSE
  1151. );
  1152. GuidString = SpAsrGetSifDataBySectionAndKey(
  1153. SIF_ASR_GPT_PARTITIONS_SECTION,
  1154. PartitionKey,
  1155. SIF_GPT_PARTITION_TYPE_GUID,
  1156. FALSE
  1157. );
  1158. SpAsrGuidFromString(&(pRec->PartitionTypeGuid), GuidString);
  1159. GuidString = SpAsrGetSifDataBySectionAndKey(
  1160. SIF_ASR_GPT_PARTITIONS_SECTION,
  1161. PartitionKey,
  1162. SIF_GPT_PARTITION_ID_GUID,
  1163. FALSE
  1164. );
  1165. SpAsrGuidFromString(&(pRec->PartitionIdGuid), GuidString);
  1166. pRec->PartitionName = SpAsrGetSifDataBySectionAndKey(
  1167. SIF_ASR_GPT_PARTITIONS_SECTION,
  1168. PartitionKey,
  1169. SIF_GPT_PARTITION_NAME,
  1170. FALSE
  1171. );
  1172. pRec->GptAttributes = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey(
  1173. SIF_ASR_GPT_PARTITIONS_SECTION,
  1174. PartitionKey,
  1175. SIF_GPT_PARTITION_GPT_ATTRIBUTES,
  1176. TRUE
  1177. ));
  1178. pRec->FileSystemType = (UCHAR) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey(
  1179. SIF_ASR_GPT_PARTITIONS_SECTION,
  1180. PartitionKey,
  1181. SIF_GPT_PARTITION_FS_TYPE,
  1182. TRUE
  1183. ));
  1184. pRec->StartSector = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey(
  1185. SIF_ASR_GPT_PARTITIONS_SECTION,
  1186. PartitionKey,
  1187. SIF_GPT_PARTITION_STARTSECTOR,
  1188. TRUE
  1189. ));
  1190. pRec->SectorCount = STRING_TO_LONGLONG(SpAsrGetSifDataBySectionAndKey(
  1191. SIF_ASR_GPT_PARTITIONS_SECTION,
  1192. PartitionKey,
  1193. SIF_GPT_PARTITION_SECTORCOUNT,
  1194. TRUE
  1195. ));
  1196. pRec->ClusterSize = (DWORD) STRING_TO_HEX(SpAsrGetSifDataBySectionAndKey(
  1197. SIF_ASR_GPT_PARTITIONS_SECTION,
  1198. PartitionKey,
  1199. SIF_GPT_PARTITION_CLUSTER_SIZE,
  1200. TRUE
  1201. ));
  1202. if (SpAsrIsBootPartitionRecord(pRec->PartitionFlag)) {
  1203. // do not free!
  1204. PWSTR ntDirPath = SpAsrGetNtDirectoryPathBySystemKey(ASR_SIF_SYSTEM_KEY);
  1205. if (!SpAsrIsValidBootDrive(ntDirPath)) {
  1206. SpAsrRaiseFatalErrorWs(SP_SCRN_DR_SIF_BAD_RECORD,
  1207. L"ASSERT FAILURE: Improperly formed NT Directory Name",
  1208. SIF_ASR_GPT_PARTITIONS_SECTION
  1209. );
  1210. // does not return
  1211. }
  1212. pRec->NtDirectoryName = SpAsrMemAlloc((SpGetMaxNtDirLen()*sizeof(WCHAR)), TRUE);
  1213. wcsncpy(pRec->NtDirectoryName, ntDirPath + 2, wcslen(ntDirPath) - 2);
  1214. }
  1215. else {
  1216. pRec->NtDirectoryName = NULL;
  1217. }
  1218. bytesPerSector = STRING_TO_ULONG(SpAsrGetSifDataBySectionAndKey(
  1219. SIF_ASR_GPT_DISKS_SECTION ,
  1220. pRec->DiskKey,
  1221. SIF_GPT_DISK_BYTES_PER_SECTOR,
  1222. TRUE
  1223. ));
  1224. pRec->SizeMB = SpAsrConvertSectorsToMB(pRec->SectorCount, bytesPerSector);
  1225. return pRec;
  1226. }
  1227. PSIF_PARTITION_RECORD
  1228. SpAsrCopyPartitionRecord(IN PSIF_PARTITION_RECORD pInput)
  1229. {
  1230. PSIF_PARTITION_RECORD pRec = NULL;
  1231. if (!pInput) {
  1232. ASSERT(0 && L"SpAsrCopyPartitionRecord: Invalid NULL input parameter");
  1233. return NULL;
  1234. }
  1235. pRec = SpAsrMemAlloc(sizeof(SIF_PARTITION_RECORD), TRUE);
  1236. //
  1237. // Won't return if pRec is NULL
  1238. //
  1239. ASSERT(pRec);
  1240. //
  1241. // Copy the record over
  1242. //
  1243. CopyMemory(pRec, pInput, sizeof(SIF_PARTITION_RECORD));
  1244. //
  1245. // And allocate space for the directory name
  1246. //
  1247. pRec->NtDirectoryName = NULL;
  1248. if (
  1249. SpAsrIsBootPartitionRecord(pRec->PartitionFlag) &&
  1250. pInput->NtDirectoryName
  1251. ) {
  1252. pRec->NtDirectoryName = SpAsrMemAlloc(
  1253. (wcslen(pInput->NtDirectoryName) + 1) * sizeof(WCHAR),
  1254. TRUE
  1255. );
  1256. //
  1257. // Won't return NULL
  1258. //
  1259. ASSERT(pRec->NtDirectoryName);
  1260. wcscpy(pRec->NtDirectoryName, pInput->NtDirectoryName);
  1261. }
  1262. return pRec;
  1263. }
  1264. VOID
  1265. SpAsrInsertPartitionRecord(
  1266. IN PSIF_PARTITION_RECORD_LIST pList,
  1267. IN PSIF_PARTITION_RECORD pRec
  1268. )
  1269. /*++
  1270. Description:
  1271. Inserts a partition record into a list of partition records. Partition
  1272. records are ordered in ascending order by start sector. That is, the
  1273. partition record with the lowest numbered start sector will be the first
  1274. partition record in the list.
  1275. Arguments:
  1276. pList The list into which the record is to be inserted.
  1277. pRec The record to insert.
  1278. Returns:
  1279. None.
  1280. --*/
  1281. {
  1282. SIF_PARTITION_RECORD *curr = NULL, *prev = NULL;
  1283. ASSERT(pList && pRec);
  1284. // set the initial conditions.
  1285. pRec->Next = NULL;
  1286. pRec->Prev = NULL;
  1287. pList->ElementCount += 1;
  1288. // special Case I: Insert into an empty list.
  1289. if( pList->ElementCount == 1 ) {
  1290. pList->First = pList->Last = pRec;
  1291. return;
  1292. }
  1293. // Special Case II: pRec must be inserted before the first element.
  1294. if( pRec->StartSector < pList->First->StartSector ) {
  1295. pRec->Next = pList->First;
  1296. pList->First = pRec;
  1297. pRec->Next->Prev = pRec;
  1298. return;
  1299. }
  1300. // Special Case III: pRec must be appended after the last element
  1301. // because pRec's start sector is greater than the last element
  1302. // on the list (which, by construction, must have the largest
  1303. // start sector).
  1304. //
  1305. if( pList->Last->StartSector < pRec->StartSector ) {
  1306. pRec->Prev = pList->Last;
  1307. pList->Last->Next = pRec;
  1308. pList->Last = pRec;
  1309. return;
  1310. }
  1311. // If we're here, then pRec's start sector must be greater than
  1312. // the start sector of the first element on the list but less than
  1313. // the start sector of the list's last element. We walk the list
  1314. // to find the insertion point, i.e., immediately before the first
  1315. // element in the list whose start sector is greater than that of
  1316. // pRec's.
  1317. curr = prev = pList->First;
  1318. while (pRec->StartSector > curr->StartSector && curr->Next) {
  1319. prev = curr;
  1320. curr = curr->Next;
  1321. }
  1322. // insert pRec between curr and prev
  1323. pRec->Next = curr;
  1324. pRec->Prev = prev;
  1325. curr->Prev = pRec;
  1326. prev->Next = pRec;
  1327. ASSERT (pRec->Prev->Next == pRec);
  1328. ASSERT (pRec->Next->Prev == pRec);
  1329. }
  1330. VOID
  1331. SpAsrRemovePartitionRecord(
  1332. IN PSIF_PARTITION_RECORD_LIST pList,
  1333. IN PSIF_PARTITION_RECORD pRec
  1334. )
  1335. /*++
  1336. Description:
  1337. Unhook a partition record from a list of partition records.
  1338. --*/
  1339. {
  1340. ASSERT(pList && pRec);
  1341. // unhook it from the list.
  1342. if (pRec->Prev) {
  1343. pRec->Prev->Next = pRec->Next;
  1344. }
  1345. if (pRec->Next) {
  1346. pRec->Next->Prev = pRec->Prev;
  1347. }
  1348. // was this the first record in the list?
  1349. if (pList->First == pRec) {
  1350. pList->First = pRec->Next;
  1351. }
  1352. // or the last record?
  1353. if (pList->Last == pRec) {
  1354. pList->Last = pRec->Prev;
  1355. }
  1356. pRec->Next = pRec->Prev = NULL;
  1357. }
  1358. PSIF_PARTITION_RECORD
  1359. SpAsrPopNextPartitionRecord(IN PSIF_PARTITION_RECORD_LIST pList)
  1360. {
  1361. PSIF_PARTITION_RECORD poppedRecord = NULL;
  1362. if (!pList) {
  1363. // ASSERT(0 && L"Trying to pop records off of a NULL list");
  1364. return NULL;
  1365. }
  1366. // get the first node in the list
  1367. if (poppedRecord = pList->First) {
  1368. // advance the First pointer to the next node
  1369. if (pList->First = pList->First->Next) {
  1370. // and make the Prev of the new first-node be NULL
  1371. pList->First->Prev = NULL;
  1372. }
  1373. pList->ElementCount -= 1;
  1374. // the poppedRecord is not part of the list any more
  1375. poppedRecord->Next = NULL;
  1376. poppedRecord->Prev = NULL;
  1377. }
  1378. return poppedRecord;
  1379. }
  1380. PSIF_PARTITION_RECORD_LIST
  1381. SpAsrCopyPartitionRecordList(PSIF_PARTITION_RECORD_LIST pSrcList)
  1382. {
  1383. PSIF_PARTITION_RECORD_LIST pDestList = NULL;
  1384. PSIF_PARTITION_RECORD pRec = NULL, pNew = NULL;
  1385. if (!pSrcList) {
  1386. ASSERT(0 && L"SpAsrCopyPartitionRecordList: Invalid NULL input parameter");
  1387. return NULL;
  1388. }
  1389. pDestList = SpAsrMemAlloc(sizeof(SIF_PARTITION_RECORD_LIST), TRUE);
  1390. //
  1391. // Won't return if pDestList is NULL.
  1392. //
  1393. ASSERT(pDestList);
  1394. pRec = pSrcList->First;
  1395. while (pRec) {
  1396. pNew = SpAsrCopyPartitionRecord(pRec);
  1397. ASSERT(pNew);
  1398. SpAsrInsertPartitionRecord(pDestList, pNew);
  1399. pRec = pRec->Next;
  1400. }
  1401. pDestList->TotalMbRequired = pSrcList->TotalMbRequired;
  1402. return pDestList;
  1403. }
  1404. VOID
  1405. SpAsrCheckAsrSifVersion()
  1406. {
  1407. return;
  1408. }
  1409. //
  1410. // Debug routines
  1411. //
  1412. #if 0
  1413. VOID
  1414. SpAsrDbgDumpSystemRecord(IN PWSTR Key)
  1415. {
  1416. PWSTR osVer = SpAsrGetSifDataBySectionAndKey(SIF_ASR_SYSTEMS_SECTION,
  1417. Key,
  1418. SIF_SYSTEM_OSVERSION,
  1419. FALSE);
  1420. DbgMesg((_asrinfo,
  1421. "Key:%ws = SysName:[%ws], OsVer:[%ws], NtDir:[%ws], AutoExt:[%ws]\n",
  1422. Key,
  1423. SpAsrGetSifDataBySectionAndKey(SIF_ASR_SYSTEMS_SECTION, Key, SIF_SYSTEM_NAME, TRUE),
  1424. osVer? osVer : L"",
  1425. SpAsrGetNtDirectoryPathBySystemKey(Key),
  1426. SpAsrGetAutoExtend(Key)
  1427. ));
  1428. }
  1429. VOID
  1430. SpAsrDbgDumpSystemRecords(VOID)
  1431. {
  1432. ULONG index, count = SpAsrGetSystemRecordCount();
  1433. DbgStatusMesg((_asrinfo, "----- Dumping [SYSTEM] Section (%lu Records): -----\n", count));
  1434. for (index = 0; index < count; index++) {
  1435. SpAsrDbgDumpSystemRecord(SpAsrGetSifKeyBySection(SIF_ASR_SYSTEMS_SECTION, index));
  1436. }
  1437. DbgStatusMesg((_asrinfo, "----- End of [SYSTEM] Section (%lu Records) -----\n", count));
  1438. }
  1439. VOID
  1440. SpAsrDbgDumpDiskRecord(IN PWSTR Key)
  1441. {
  1442. PSIF_DISK_RECORD pRec = NULL;
  1443. if (!Key) {
  1444. return;
  1445. }
  1446. pRec = SpAsrGetDiskRecord(Key);
  1447. if (!pRec) {
  1448. return;
  1449. }
  1450. DbgMesg((_asrinfo,
  1451. "Key:[%ws] = Sys:[%ws] SifDskNum:[%ws], SifDskSig:0x%lx, ScSz:%lu, TtlSc:%I64u",
  1452. pRec->CurrDiskKey,
  1453. pRec->SystemKey,
  1454. pRec->SifDiskSignature,
  1455. pRec->BytesPerSector,
  1456. pRec->TotalSectors
  1457. ));
  1458. if (pRec->ExtendedPartitionStartSector > -1) {
  1459. KdPrintEx((_asrinfo, ", extSS:%I64u, extSC:%I64u",
  1460. pRec->ExtendedPartitionStartSector,
  1461. pRec->ExtendedPartitionSectorCount));
  1462. }
  1463. KdPrintEx((_asrinfo, "\n"));
  1464. SpMemFree(pRec);
  1465. }
  1466. VOID
  1467. SpAsrDbgDumpDiskRecords(VOID)
  1468. {
  1469. ULONG index, count = SpAsrGetMbrDiskRecordCount();
  1470. DbgStatusMesg((_asrinfo, "----- Dumping [DISK.MBR] Section (%lu Records): -----\n", count));
  1471. for (index = 0; index < count; index++) {
  1472. SpAsrDbgDumpDiskRecord(SpAsrGetSifKeyBySection(SIF_ASR_MBR_DISKS_SECTION , index));
  1473. }
  1474. DbgStatusMesg((_asrinfo, "----- End of [DISK.MBR] Section (%lu Records) -----\n", count));
  1475. count = SpAsrGetGptDiskRecordCount();
  1476. DbgStatusMesg((_asrinfo, "----- Dumping [DISK.GPT] Section (%lu Records): -----\n", count));
  1477. for (index = 0; index < count; index++) {
  1478. SpAsrDbgDumpDiskRecord(SpAsrGetSifKeyBySection(SIF_ASR_GPT_DISKS_SECTION , index));
  1479. }
  1480. DbgStatusMesg((_asrinfo, "----- End of [DISK.GPT] Section (%lu Records) -----\n", count));
  1481. }
  1482. VOID
  1483. SpAsrDbgDumpPartitionRecord(IN PARTITION_STYLE PartitinStyle, IN PWSTR Key)
  1484. {
  1485. PSIF_PARTITION_RECORD pRec = SpAsrGetPartitionRecord(Key);
  1486. DbgMesg((_asrinfo,
  1487. "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",
  1488. pRec->CurrPartKey,
  1489. pRec->DiskKey,
  1490. SpAsrIsBootPartitionRecord(pRec->PartitionFlag) ? pRec->NtDirectoryName : L"n/a",
  1491. pRec->VolumeGuid ? pRec->VolumeGuid : L"n/a",
  1492. pRec->ActiveFlag,
  1493. pRec->PartitionType,
  1494. pRec->FileSystemType,
  1495. SpAsrIsBootPartitionRecord(pRec->PartitionFlag) ? "Y" : "N",
  1496. SpAsrIsSystemPartitionRecord(pRec->PartitionFlag) ? "Y" : "N",
  1497. pRec->StartSector,
  1498. pRec->SectorCount,
  1499. pRec->SizeMB
  1500. ));
  1501. SpMemFree(pRec);
  1502. }
  1503. VOID
  1504. SpAsrDbgDumpPartitionList(IN PSIF_PARTITION_RECORD_LIST pList)
  1505. {
  1506. PSIF_PARTITION_RECORD pRec;
  1507. ASSERT(pList);
  1508. DbgStatusMesg((_asrinfo, "----- Dumping Partition List: -----\n"));
  1509. pRec = pList->First;
  1510. while (pRec) {
  1511. SpAsrDbgDumpPartitionRecord(pRec->CurrPartKey);
  1512. pRec = pRec->Next;
  1513. }
  1514. DbgStatusMesg((_asrinfo, "----- End of Partition List -----\n"));
  1515. }
  1516. VOID
  1517. SpAsrDbgDumpPartitionRecords(VOID)
  1518. {
  1519. ULONG index, count = SpAsrGetPartitionRecordCount();
  1520. DbgStatusMesg((_asrinfo, "----- Dumping [PARTITION] Section (%lu Records): -----\n", count));
  1521. for (index = 0; index < count; index++) {
  1522. SpAsrDbgDumpPartitionRecord(SpAsrGetSifKeyBySection(SIF_ASR_MBR_PARTITIONS_SECTION, index));
  1523. }
  1524. DbgStatusMesg((_asrinfo, "----- End of [PARTITION] Section (%lu Records) -----\n", count));
  1525. }
  1526. VOID
  1527. SpAsrDbgDumpInstallFileRecord(IN PWSTR Key)
  1528. {
  1529. PSIF_INSTALLFILE_RECORD pRec = SpAsrGetInstallFileRecord(Key,NULL);
  1530. DbgMesg((_asrinfo,
  1531. "Key:[%ws] = SysKey:[%ws], MediaLabel:[%ws], Media:[%ws], Src:[%ws], Dest:[%ws], Vendor:[%ws]",
  1532. Key,
  1533. pRec->SystemKey,
  1534. pRec->SourceMediaExternalLabel,
  1535. pRec->DiskDeviceName,
  1536. pRec->SourceFilePath,
  1537. pRec->DestinationFilePath,
  1538. pRec->VendorString
  1539. ));
  1540. SpMemFree(pRec);
  1541. }
  1542. VOID
  1543. SpAsrDbgDumpInstallFileRecords(VOID)
  1544. {
  1545. ULONG index, count = SpAsrGetInstallFilesRecordCount();
  1546. DbgStatusMesg((_asrinfo, "----- Dumping [INSTALLFILE] Section (%lu Records): -----\n", count));
  1547. for (index = 0; index < count; index++) {
  1548. SpAsrDbgDumpInstallFileRecord(SpAsrGetSifKeyBySection(SIF_ASR_INSTALLFILES_SECTION, index));
  1549. }
  1550. DbgStatusMesg((_asrinfo, "----- End of [INSTALLFILE] Section (%lu Records) -----\n", count));
  1551. }
  1552. VOID
  1553. SpAsrDbgDumpInstallFileList(IN PSIF_INSTALLFILE_LIST pList)
  1554. {
  1555. PSIF_INSTALLFILE_RECORD pRec;
  1556. if (pList == NULL) {
  1557. DbgStatusMesg((_asrinfo, "No 3rd party files are specified.\n"));
  1558. }
  1559. else {
  1560. DbgStatusMesg((_asrinfo, "----- Dumping Install-file List: -----\n"));
  1561. pRec = pList->First;
  1562. while (pRec) {
  1563. SpAsrDbgDumpInstallFileRecord(pRec->CurrKey);
  1564. pRec = pRec->Next;
  1565. }
  1566. DbgStatusMesg((_asrinfo, "----- End of Install-file List -----\n"));
  1567. }
  1568. }
  1569. VOID
  1570. SpAsrDbgTestSifFunctions(VOID)
  1571. {
  1572. SpAsrDbgDumpSystemRecords();
  1573. SpAsrDbgDumpDiskRecords();
  1574. SpAsrDbgDumpPartitionRecords();
  1575. SpAsrDbgDumpInstallFileRecords();
  1576. }
  1577. #endif // Debug routines