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.

641 lines
18 KiB

  1. #if defined(REMOTE_BOOT)
  2. /*++
  3. Copyright (c) 1989 Microsoft Corporation
  4. Module Name:
  5. sminit.c
  6. Abstract:
  7. Session Manager Initialization
  8. Author:
  9. Mark Lucovsky (markl) 04-Oct-1989
  10. Revision History:
  11. --*/
  12. #include "smsrvp.h"
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <safeboot.h>
  16. #include <ntdddisk.h>
  17. VOID
  18. SmpGetHarddiskBootPartition(
  19. OUT PULONG DiskNumber,
  20. OUT PULONG PartitionNumber
  21. )
  22. /*++
  23. Routine Description:
  24. This routine searches the each partition on each hard disk for
  25. one which has the active bit set, returning the first one encountered.
  26. Arguments:
  27. DiskNumber - The harddisk number.
  28. PartitionNumber - The partition number.
  29. Return Value:
  30. None
  31. --*/
  32. {
  33. PARTITION_INFORMATION PartitionInfo;
  34. WCHAR NameBuffer[80];
  35. HANDLE Handle;
  36. NTSTATUS Status;
  37. IO_STATUS_BLOCK IoStatus;
  38. OBJECT_ATTRIBUTES ObjectAttributes;
  39. UNICODE_STRING UnicodeString;
  40. *DiskNumber = 0;
  41. while (TRUE) {
  42. //
  43. // First check if there is any disk there at all by opening partition 0
  44. //
  45. *PartitionNumber = 0;
  46. swprintf(NameBuffer, L"\\Device\\Harddisk%d\\Partition%d", *DiskNumber, *PartitionNumber);
  47. RtlInitUnicodeString(&UnicodeString, NameBuffer);
  48. InitializeObjectAttributes(
  49. &ObjectAttributes,
  50. &UnicodeString,
  51. OBJ_CASE_INSENSITIVE,
  52. NULL,
  53. NULL
  54. );
  55. Status = NtCreateFile( &Handle,
  56. (ACCESS_MASK)FILE_GENERIC_READ,
  57. &ObjectAttributes,
  58. &IoStatus,
  59. NULL,
  60. FILE_ATTRIBUTE_NORMAL,
  61. FILE_SHARE_READ,
  62. FILE_OPEN,
  63. FILE_SYNCHRONOUS_IO_NONALERT,
  64. NULL,
  65. 0
  66. );
  67. if (!NT_SUCCESS(Status)) {
  68. KdPrint(("SMSS: GetBootPartition: Harddisk%d\\Partition0 for read failed (Status 0x%x).\n", *DiskNumber, Status));
  69. *PartitionNumber = 1;
  70. *DiskNumber = 0;
  71. return;
  72. }
  73. NtClose(Handle);
  74. //
  75. // Now, for each partition, check if it is marked 'active'
  76. //
  77. while (TRUE) {
  78. *PartitionNumber = *PartitionNumber + 1;
  79. swprintf(NameBuffer, L"\\Device\\Harddisk%d\\Partition%d", *DiskNumber, *PartitionNumber);
  80. RtlInitUnicodeString(&UnicodeString, NameBuffer);
  81. InitializeObjectAttributes(
  82. &ObjectAttributes,
  83. &UnicodeString,
  84. OBJ_CASE_INSENSITIVE,
  85. NULL,
  86. NULL
  87. );
  88. Status = NtCreateFile( &Handle,
  89. (ACCESS_MASK)FILE_GENERIC_READ,
  90. &ObjectAttributes,
  91. &IoStatus,
  92. NULL,
  93. FILE_ATTRIBUTE_NORMAL,
  94. FILE_SHARE_READ,
  95. FILE_OPEN,
  96. FILE_SYNCHRONOUS_IO_NONALERT,
  97. NULL,
  98. 0
  99. );
  100. if (!NT_SUCCESS(Status)) {
  101. break;
  102. }
  103. Status = NtDeviceIoControlFile(Handle,
  104. NULL,
  105. NULL,
  106. NULL,
  107. &IoStatus,
  108. IOCTL_DISK_GET_PARTITION_INFO,
  109. NULL,
  110. 0,
  111. &PartitionInfo,
  112. sizeof(PARTITION_INFORMATION)
  113. );
  114. NtClose(Handle);
  115. if (!NT_SUCCESS(Status)) {
  116. break;
  117. }
  118. if (PartitionInfo.BootIndicator) {
  119. return;
  120. }
  121. }
  122. *DiskNumber = *DiskNumber + 1;
  123. }
  124. }
  125. VOID
  126. SmpPartitionDisk(
  127. IN ULONG DiskNumber,
  128. OUT PULONG PartitionNumber
  129. )
  130. /*++
  131. Routine Description:
  132. This routine
  133. Arguments:
  134. DiskNumber - The harddisk number.
  135. PartitionNumber - The partition number.
  136. Return Value:
  137. None
  138. --*/
  139. {
  140. OBJECT_ATTRIBUTES ObjectAttributes;
  141. UNICODE_STRING UnicodeString;
  142. HANDLE Handle;
  143. IO_STATUS_BLOCK IoStatusBlock;
  144. PUCHAR AlignedBuffer;
  145. ULONG Length;
  146. PDRIVE_LAYOUT_INFORMATION DriveLayout;
  147. PDRIVE_LAYOUT_INFORMATION OrigDriveLayout;
  148. PPARTITION_INFORMATION Pte;
  149. PPARTITION_INFORMATION StartPte;
  150. ULONG LargestPart;
  151. ULONG StartPart;
  152. ULONG Part;
  153. LARGE_INTEGER LargestBlock;
  154. LARGE_INTEGER OffsetEnd;
  155. UCHAR TmpBuffer[80];
  156. NTSTATUS Status;
  157. BOOLEAN MadeChanges;
  158. BOOLEAN WasEnabled;
  159. //
  160. // Get the layout of the drive.
  161. //
  162. swprintf((PWSTR)TmpBuffer, L"\\Device\\Harddisk%d\\Partition0", DiskNumber);
  163. RtlInitUnicodeString(&UnicodeString, (PWSTR)TmpBuffer);
  164. InitializeObjectAttributes(
  165. &ObjectAttributes,
  166. &UnicodeString,
  167. OBJ_CASE_INSENSITIVE,
  168. NULL,
  169. NULL
  170. );
  171. Status = NtCreateFile( &Handle,
  172. (ACCESS_MASK)FILE_GENERIC_READ,
  173. &ObjectAttributes,
  174. &IoStatusBlock,
  175. NULL,
  176. FILE_ATTRIBUTE_NORMAL,
  177. FILE_SHARE_READ,
  178. FILE_OPEN,
  179. FILE_SYNCHRONOUS_IO_NONALERT,
  180. NULL,
  181. 0
  182. );
  183. if (!NT_SUCCESS(Status)) {
  184. KdPrint(("SMSS: Could not open Harddisk%d\\Partition0 for read (Status 0x%x).\n", DiskNumber, Status));
  185. return;
  186. }
  187. //
  188. // We really only need 4 partition numbers worth, but for debugging
  189. // purposes I want to see more than just the first 4, so get the first 20.
  190. //
  191. Length = sizeof(DRIVE_LAYOUT_INFORMATION) + 20 * sizeof(PARTITION_INFORMATION);
  192. DriveLayout = (PDRIVE_LAYOUT_INFORMATION)RtlAllocateHeap(RtlProcessHeap(),
  193. MAKE_TAG( INIT_TAG ),
  194. Length
  195. );
  196. if (DriveLayout == NULL) {
  197. KdPrint(("SMSS: Could not allocate memory for drive layout (Status 0x%x).\n", Status));
  198. NtClose(Handle);
  199. return;
  200. }
  201. OrigDriveLayout = (PDRIVE_LAYOUT_INFORMATION)RtlAllocateHeap(RtlProcessHeap(),
  202. MAKE_TAG( INIT_TAG ),
  203. Length
  204. );
  205. if (OrigDriveLayout == NULL) {
  206. KdPrint(("SMSS: Could not allocate memory for drive layout 2 (Status 0x%x).\n", Status));
  207. RtlFreeHeap( RtlProcessHeap(), 0, DriveLayout );
  208. NtClose(Handle);
  209. return;
  210. }
  211. Status = NtDeviceIoControlFile(
  212. Handle,
  213. NULL,
  214. NULL,
  215. NULL,
  216. &IoStatusBlock,
  217. IOCTL_DISK_GET_DRIVE_LAYOUT,
  218. NULL,
  219. 0,
  220. (PUCHAR)DriveLayout,
  221. Length
  222. );
  223. if (!NT_SUCCESS(Status)) {
  224. KdPrint(("SMSS: Could not get drive layout (Status 0x%x).\n", Status));
  225. RtlFreeHeap( RtlProcessHeap(), 0, OrigDriveLayout );
  226. RtlFreeHeap( RtlProcessHeap(), 0, DriveLayout );
  227. NtClose(Handle);
  228. return;
  229. }
  230. memcpy(OrigDriveLayout, DriveLayout, Length);
  231. #if DBG
  232. KdPrint(("SMSS:Starting drive layout\n"));
  233. for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
  234. Pte = &(DriveLayout->PartitionEntry[Part]);
  235. KdPrint(("SMSS: Partition: %d\n", Part + 1));
  236. KdPrint(("SMSS: Pte->PartitionType = 0x%x\n", Pte->PartitionType));
  237. KdPrint(("SMSS: Pte->StartingOffset = 0x%x\n", Pte->StartingOffset));
  238. KdPrint(("SMSS: Pte->PartitionLength = 0x%x\n", Pte->PartitionLength));
  239. KdPrint(("SMSS: Pte->HiddenSectors = 0x%x\n", Pte->HiddenSectors));
  240. KdPrint(("SMSS: Pte->PartitionNumber = 0x%x\n", Pte->PartitionNumber));
  241. KdPrint(("SMSS: Pte->BootIndicator = 0x%x\n", Pte->BootIndicator));
  242. KdPrint(("SMSS: Pte->RecognizedPartition = 0x%x\n\n", Pte->RecognizedPartition));
  243. }
  244. #endif
  245. //
  246. // Just ignore extended partitions
  247. //
  248. DriveLayout->PartitionCount = 4;
  249. //
  250. // Go thru the partitions, and for any recognized type, label it as unused.
  251. //
  252. for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
  253. Pte = &(DriveLayout->PartitionEntry[Part]);
  254. if (!IsRecognizedPartition(Pte->PartitionType) &&
  255. !IsContainerPartition(Pte->PartitionType)) {
  256. continue;
  257. }
  258. Pte->PartitionType = PARTITION_ENTRY_UNUSED;
  259. Pte->BootIndicator = FALSE;
  260. }
  261. #if DBG
  262. KdPrint(("SMSS: Layout after clearing known partitions.\n"));
  263. for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
  264. Pte = &(DriveLayout->PartitionEntry[Part]);
  265. KdPrint(("SMSS: Partition: %d\n", Part + 1));
  266. KdPrint(("SMSS: Pte->PartitionType = 0x%x\n", Pte->PartitionType));
  267. KdPrint(("SMSS: Pte->StartingOffset = 0x%x\n", Pte->StartingOffset));
  268. KdPrint(("SMSS: Pte->PartitionLength = 0x%x\n", Pte->PartitionLength));
  269. KdPrint(("SMSS: Pte->HiddenSectors = 0x%x\n", Pte->HiddenSectors));
  270. KdPrint(("SMSS: Pte->PartitionNumber = 0x%x\n", Pte->PartitionNumber));
  271. KdPrint(("SMSS: Pte->BootIndicator = 0x%x\n", Pte->BootIndicator));
  272. KdPrint(("SMSS: Pte->RecognizedPartition = 0x%x\n\n", Pte->RecognizedPartition));
  273. }
  274. #endif
  275. //
  276. // Merge unused partitions that are adjacent.
  277. //
  278. for (StartPart = 0; StartPart < DriveLayout->PartitionCount; StartPart++) {
  279. StartPte = &(DriveLayout->PartitionEntry[StartPart]);
  280. if ((StartPte->PartitionType != PARTITION_ENTRY_UNUSED) ||
  281. RtlLargeIntegerEqualTo(StartPte->PartitionLength, RtlConvertUlongToLargeInteger(0))) {
  282. continue;
  283. }
  284. OffsetEnd = RtlLargeIntegerAdd(StartPte->StartingOffset, StartPte->PartitionLength);
  285. for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
  286. if (Part == StartPart) {
  287. continue;
  288. }
  289. Pte = &(DriveLayout->PartitionEntry[Part]);
  290. if (RtlLargeIntegerEqualTo(OffsetEnd, Pte->StartingOffset)) {
  291. //
  292. // Merge the blocks
  293. //
  294. StartPte->PartitionLength = RtlLargeIntegerAdd(StartPte->PartitionLength,
  295. Pte->PartitionLength
  296. );
  297. OffsetEnd = RtlLargeIntegerAdd(OffsetEnd, Pte->PartitionLength);
  298. Pte->PartitionType = PARTITION_ENTRY_UNUSED;
  299. Pte->StartingOffset = RtlConvertUlongToLargeInteger(0);
  300. Pte->PartitionLength = RtlConvertUlongToLargeInteger(0);
  301. Pte->HiddenSectors = 0;
  302. Pte->PartitionNumber = 0;
  303. Pte->BootIndicator = FALSE;
  304. Pte->RecognizedPartition = FALSE;
  305. Part = (ULONG)-1; // will get ++'d to 0 at the bottom of the loop.
  306. }
  307. }
  308. }
  309. //
  310. // Find the largest block that is unused.
  311. //
  312. LargestPart = 0;
  313. LargestBlock = RtlConvertUlongToLargeInteger(0);
  314. for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
  315. Pte = &(DriveLayout->PartitionEntry[Part]);
  316. if ((Pte->PartitionType == PARTITION_ENTRY_UNUSED) &&
  317. RtlLargeIntegerGreaterThan(Pte->PartitionLength, LargestBlock)) {
  318. LargestPart = Part;
  319. LargestBlock = Pte->PartitionLength;
  320. }
  321. }
  322. #if DBG
  323. KdPrint(("SMSS: Layout after merging largest block.\n"));
  324. for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
  325. Pte = &(DriveLayout->PartitionEntry[Part]);
  326. KdPrint(("SMSS: Partition: %d\n", Part + 1));
  327. KdPrint(("SMSS: Pte->PartitionType = 0x%x\n", Pte->PartitionType));
  328. KdPrint(("SMSS: Pte->StartingOffset = 0x%x\n", Pte->StartingOffset));
  329. KdPrint(("SMSS: Pte->PartitionLength = 0x%x\n", Pte->PartitionLength));
  330. KdPrint(("SMSS: Pte->HiddenSectors = 0x%x\n", Pte->HiddenSectors));
  331. KdPrint(("SMSS: Pte->PartitionNumber = 0x%x\n", Pte->PartitionNumber));
  332. KdPrint(("SMSS: Pte->BootIndicator = 0x%x\n", Pte->BootIndicator));
  333. KdPrint(("SMSS: Pte->RecognizedPartition = 0x%x\n\n", Pte->RecognizedPartition));
  334. }
  335. #endif
  336. //
  337. // Set the partition type for the new partition
  338. //
  339. DriveLayout->PartitionEntry[LargestPart].PartitionType = PARTITION_IFS;
  340. DriveLayout->PartitionEntry[LargestPart].BootIndicator = TRUE;
  341. #if DBG
  342. KdPrint(("SMSS: Final Layout\n"));
  343. for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
  344. Pte = &(DriveLayout->PartitionEntry[Part]);
  345. KdPrint(("SMSS: Partition: %d\n", Part + 1));
  346. KdPrint(("SMSS: Pte->PartitionType = 0x%x\n", Pte->PartitionType));
  347. KdPrint(("SMSS: Pte->StartingOffset = 0x%x\n", Pte->StartingOffset));
  348. KdPrint(("SMSS: Pte->PartitionLength = 0x%x\n", Pte->PartitionLength));
  349. KdPrint(("SMSS: Pte->HiddenSectors = 0x%x\n", Pte->HiddenSectors));
  350. KdPrint(("SMSS: Pte->PartitionNumber = 0x%x\n", Pte->PartitionNumber));
  351. KdPrint(("SMSS: Pte->BootIndicator = 0x%x\n", Pte->BootIndicator));
  352. KdPrint(("SMSS: Pte->RecognizedPartition = 0x%x\n\n", Pte->RecognizedPartition));
  353. }
  354. #endif
  355. MadeChanges = FALSE;
  356. for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
  357. if (memcmp(&(DriveLayout->PartitionEntry[Part]),
  358. &(OrigDriveLayout->PartitionEntry[Part]),
  359. sizeof(PARTITION_INFORMATION))) {
  360. MadeChanges = TRUE;
  361. break;
  362. }
  363. }
  364. if (MadeChanges) {
  365. KdPrint(("SMSS: Repartitioning disk.\n"));
  366. //
  367. // Mark partitions for rewrite.
  368. //
  369. for (Part = 0; Part < DriveLayout->PartitionCount; Part++) {
  370. DriveLayout->PartitionEntry[Part].RewritePartition = TRUE;
  371. }
  372. //
  373. // Submit IOCTL to set new partition information
  374. //
  375. Status = NtDeviceIoControlFile(
  376. Handle,
  377. NULL,
  378. NULL,
  379. NULL,
  380. &IoStatusBlock,
  381. IOCTL_DISK_SET_DRIVE_LAYOUT,
  382. DriveLayout,
  383. Length,
  384. NULL,
  385. 0
  386. );
  387. if (!NT_SUCCESS(Status)) {
  388. RtlFreeHeap( RtlProcessHeap(), 0, OrigDriveLayout );
  389. RtlFreeHeap( RtlProcessHeap(), 0, DriveLayout );
  390. NtClose(Handle);
  391. KdPrint(("SMSS: Could not set drive layout (Status 0x%x).\n", Status));
  392. return;
  393. }
  394. }
  395. *PartitionNumber = DriveLayout->PartitionEntry[LargestPart].PartitionNumber;
  396. RtlFreeHeap( RtlProcessHeap(), 0, OrigDriveLayout );
  397. RtlFreeHeap( RtlProcessHeap(), 0, DriveLayout );
  398. NtClose(Handle);
  399. return;
  400. }
  401. VOID
  402. SmpFindCSCPartition(
  403. IN ULONG DiskNumber,
  404. OUT PULONG PartitionNumber
  405. )
  406. /*++
  407. Routine Description:
  408. This routine searches the each partition on each hard disk for
  409. one which has the CSC directory.
  410. Arguments:
  411. DiskNumber - The harddisk number.
  412. PartitionNumber - The partition number. Will be 0 if no CSC directory is found on the disk.
  413. Return Value:
  414. None
  415. --*/
  416. {
  417. WCHAR NameBuffer[80];
  418. HANDLE Handle;
  419. NTSTATUS Status;
  420. IO_STATUS_BLOCK IoStatus;
  421. OBJECT_ATTRIBUTES ObjectAttributes;
  422. UNICODE_STRING UnicodeString;
  423. ULONG Part;
  424. Part = 0;
  425. *PartitionNumber = 0;
  426. while (TRUE) {
  427. Part++;
  428. //
  429. // First see if the partition exists by opening it.
  430. //
  431. swprintf(NameBuffer,
  432. L"\\Device\\Harddisk%d\\Partition%d",
  433. DiskNumber,
  434. Part
  435. );
  436. RtlInitUnicodeString(&UnicodeString, NameBuffer);
  437. InitializeObjectAttributes(
  438. &ObjectAttributes,
  439. &UnicodeString,
  440. OBJ_CASE_INSENSITIVE,
  441. NULL,
  442. NULL
  443. );
  444. Status = NtCreateFile( &Handle,
  445. (ACCESS_MASK)FILE_GENERIC_READ,
  446. &ObjectAttributes,
  447. &IoStatus,
  448. NULL,
  449. FILE_ATTRIBUTE_NORMAL,
  450. FILE_SHARE_READ,
  451. FILE_OPEN,
  452. FILE_SYNCHRONOUS_IO_NONALERT,
  453. NULL,
  454. 0
  455. );
  456. if (!NT_SUCCESS(Status)) {
  457. return;
  458. }
  459. NtClose(Handle);
  460. wcscat(NameBuffer, REMOTE_BOOT_IMIRROR_PATH_W REMOTE_BOOT_CSC_SUBDIR_W);
  461. RtlInitUnicodeString(&UnicodeString, NameBuffer);
  462. InitializeObjectAttributes(
  463. &ObjectAttributes,
  464. &UnicodeString,
  465. OBJ_CASE_INSENSITIVE,
  466. NULL,
  467. NULL
  468. );
  469. Status = NtOpenFile(&Handle,
  470. FILE_READ_DATA | SYNCHRONIZE,
  471. &ObjectAttributes,
  472. &IoStatus,
  473. FILE_SHARE_READ,
  474. FILE_DIRECTORY_FILE
  475. );
  476. if (NT_SUCCESS(Status)) {
  477. NtClose(Handle);
  478. *PartitionNumber = Part;
  479. return;
  480. }
  481. }
  482. }
  483. #endif // defined(REMOTE_BOOT)