Leaked source code of windows server 2003
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.

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