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.

1084 lines
26 KiB

  1. /*++
  2. Copyright (c) 1991-1994 Microsoft Corporation
  3. Module Name:
  4. fd_nt.c
  5. Abstract:
  6. This module wraps fdisk engine functions. This is done
  7. to avoid having files that include both the full windows
  8. and the full nt include file sets.
  9. Functions that manipulate engine structures (REGIONs, for example)
  10. are also placed here.
  11. This file is targeted at NT, not Windows.
  12. Author:
  13. Ted Miller (tedm) 5-Dec-1991
  14. Revision History:
  15. Misc cleanup (BobRi) 22-Jan-1994
  16. --*/
  17. #include "fdisk.h"
  18. #include <string.h>
  19. #include <stdio.h>
  20. // These partition ID's are for systems recognized by WINDISK,
  21. // even though they don't appear in ntdddisk.h.
  22. #define PARTITION_OS2_BOOT 0xa
  23. #define PARTITION_EISA 0x12
  24. WCHAR UnicodeSysIdName[100];
  25. BYTE StringBuffer[100];
  26. // Pagefile support structures.
  27. typedef struct _PAGEFILE_LOCATION {
  28. struct _PAGEFILE_LOCATION *Next;
  29. CHAR DriveLetter;
  30. } PAGEFILE_LOCATION, *PPAGEFILE_LOCATION;
  31. PPAGEFILE_LOCATION PagefileHead = NULL;
  32. // For some reason the file systems don't like being accessed shortly after
  33. // a format or lock event.
  34. #define SLEEP_TIME (1000*2) // 2 seconds
  35. PWSTR
  36. GetWideSysIDName(
  37. IN UCHAR SysID
  38. )
  39. /*++
  40. Routine Description:
  41. Arguments:
  42. Return Value:
  43. --*/
  44. {
  45. ANSI_STRING ansiString;
  46. UNICODE_STRING unicodeString;
  47. DWORD stringId;
  48. // Get the name, which is a byte-string.
  49. switch (SysID) {
  50. case PARTITION_ENTRY_UNUSED:
  51. stringId = IDS_PARTITION_FREE;
  52. break;
  53. case PARTITION_XENIX_1:
  54. stringId = IDS_PARTITION_XENIX1;
  55. break;
  56. case PARTITION_XENIX_2:
  57. stringId = IDS_PARTITION_XENIX2;
  58. break;
  59. case PARTITION_OS2_BOOT:
  60. stringId = IDS_PARTITION_OS2_BOOT;
  61. break;
  62. case PARTITION_EISA:
  63. stringId = IDS_PARTITION_EISA;
  64. break;
  65. case PARTITION_UNIX:
  66. stringId = IDS_PARTITION_UNIX;
  67. break;
  68. case PARTITION_PREP:
  69. #ifdef _PPC_
  70. stringId = IDS_PARTITION_POWERPC;
  71. #else
  72. // If not on a PPC platform, assume this is Eisa related
  73. stringId = IDS_PARTITION_EISA;
  74. #endif
  75. break;
  76. default:
  77. stringId = IDS_UNKNOWN;
  78. break;
  79. }
  80. LoadString(hModule, stringId, StringBuffer, sizeof(StringBuffer));
  81. RtlInitAnsiString(&ansiString, StringBuffer);
  82. //
  83. // Convert to Unicode
  84. //
  85. unicodeString.Buffer = UnicodeSysIdName;
  86. unicodeString.MaximumLength = sizeof(UnicodeSysIdName);
  87. RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, FALSE);
  88. return UnicodeSysIdName;
  89. }
  90. ULONG
  91. MyDiskRegistryGet(
  92. OUT PDISK_REGISTRY *DiskRegistry
  93. )
  94. /*++
  95. Routine Description:
  96. Allocate memory for the size of the disk registry, obtain
  97. the registry contents (if any) and return the pointer to the
  98. allocated memory.
  99. Arguments:
  100. A pointer to a disk registry pointer.
  101. Return Value:
  102. status indicating success or failure.
  103. --*/
  104. {
  105. ULONG length;
  106. PDISK_REGISTRY diskRegistry;
  107. NTSTATUS status;
  108. while (((status = DiskRegistryGet(NULL, &length)) == STATUS_NO_MEMORY)
  109. || (status == STATUS_INSUFFICIENT_RESOURCES))
  110. {
  111. ConfirmOutOfMemory();
  112. }
  113. if (!NT_SUCCESS(status)) {
  114. return EC(status);
  115. }
  116. diskRegistry = Malloc(length);
  117. while (((status = DiskRegistryGet(diskRegistry, &length)) == STATUS_NO_MEMORY)
  118. || (status == STATUS_INSUFFICIENT_RESOURCES))
  119. {
  120. ConfirmOutOfMemory();
  121. }
  122. if (NT_SUCCESS(status)) {
  123. LOG_DISK_REGISTRY("MyDiskRegistryGet", diskRegistry);
  124. *DiskRegistry = diskRegistry;
  125. }
  126. return EC(status);
  127. }
  128. ULONG
  129. FormDiskSignature(
  130. VOID
  131. )
  132. /*++
  133. Routine Description:
  134. Return a ULONG disk signature. This is derived from the current
  135. system time.
  136. Arguments:
  137. None
  138. Return Value:
  139. A 32-bit signature
  140. --*/
  141. {
  142. LARGE_INTEGER time;
  143. static ULONG baseSignature = 0;
  144. if (!baseSignature) {
  145. NtQuerySystemTime(&time);
  146. time.QuadPart = time.QuadPart >> 16;
  147. baseSignature = time.LowPart;
  148. }
  149. return baseSignature++;
  150. }
  151. BOOLEAN
  152. GetVolumeSizeMB(
  153. IN ULONG Disk,
  154. IN ULONG Partition,
  155. OUT PULONG Size
  156. )
  157. /*++
  158. Routine Description:
  159. Given a disk and a partition, query the "volume" to get its size.
  160. By performing the query on the 1st partition of a potential FT set,
  161. the total size of the set will be returned. If the partition isn't
  162. an FT set, it will work too.
  163. Arguments:
  164. Disk - the disk number
  165. Partition - the partition number
  166. Size - the size of the "volume"
  167. Return Value:
  168. TRUE - a size was returned.
  169. FALSE - something failed in getting the size.
  170. --*/
  171. {
  172. BOOLEAN retValue = FALSE;
  173. IO_STATUS_BLOCK statusBlock;
  174. HANDLE handle;
  175. STATUS_CODE sc;
  176. PARTITION_INFORMATION partitionInfo;
  177. LARGE_INTEGER partitionLength;
  178. *Size = 0;
  179. sc = LowOpenPartition(GetDiskName(Disk), Partition, &handle);
  180. if (sc == OK_STATUS) {
  181. sc = NtDeviceIoControlFile(handle,
  182. 0,
  183. NULL,
  184. NULL,
  185. &statusBlock,
  186. IOCTL_DISK_GET_PARTITION_INFO,
  187. NULL,
  188. 0,
  189. &partitionInfo,
  190. sizeof(PARTITION_INFORMATION));
  191. if (sc == OK_STATUS) {
  192. // Convert to MB
  193. partitionLength.QuadPart = partitionInfo.PartitionLength.QuadPart >> 20;
  194. *Size = partitionLength.LowPart;
  195. retValue = TRUE;
  196. }
  197. LowCloseDisk(handle);
  198. }
  199. return retValue;
  200. }
  201. ULONG
  202. GetVolumeTypeAndSize(
  203. IN ULONG Disk,
  204. IN ULONG Partition,
  205. OUT PWSTR *Label,
  206. OUT PWSTR *Type,
  207. OUT PULONG Size
  208. )
  209. /*++
  210. Routine Description:
  211. Given a disk and partition number, determine its size, label and file
  212. system type. This routine will allocate the space for label and file
  213. system type. It is the responsibility of the caller to free this memory.
  214. Arguments:
  215. Disk - the disk number
  216. Partition - the partition number
  217. Label - a pointer to a pointer for a WCHAR string to contain the label
  218. Type - a pointer to a pointer for a WCHAR string to contain the file system
  219. type.
  220. Size - a pointer to a ULONG for the size of the disk in KB.
  221. Return Value:
  222. OK_STATUS - everything was performed.
  223. !OK_STATUS - the error code that was returned in the process of performing
  224. this work.
  225. --*/
  226. {
  227. IO_STATUS_BLOCK statusBlock;
  228. HANDLE handle;
  229. unsigned char buffer[256];
  230. PWSTR label,
  231. name;
  232. ULONG length;
  233. DISK_GEOMETRY diskGeometry;
  234. STATUS_CODE sc;
  235. BOOLEAN firstTime = TRUE;
  236. PFILE_FS_VOLUME_INFORMATION labelInfo = (PFILE_FS_VOLUME_INFORMATION)buffer;
  237. PFILE_FS_ATTRIBUTE_INFORMATION info = (PFILE_FS_ATTRIBUTE_INFORMATION)buffer;
  238. while (1) {
  239. sc = LowOpenPartition(GetDiskName(Disk), Partition, &handle);
  240. if (sc == OK_STATUS) {
  241. sc = NtQueryVolumeInformationFile(handle,
  242. &statusBlock,
  243. buffer,
  244. sizeof(buffer),
  245. FileFsVolumeInformation);
  246. if (sc == OK_STATUS) {
  247. length = labelInfo->VolumeLabelLength;
  248. labelInfo->VolumeLabel[length/sizeof(WCHAR)] = 0;
  249. length = (length+1) * sizeof(WCHAR);
  250. label = Malloc(length);
  251. RtlMoveMemory(label, labelInfo->VolumeLabel, length);
  252. } else {
  253. label = Malloc(sizeof(WCHAR));
  254. *label = 0;
  255. }
  256. *Label = label;
  257. if (sc == OK_STATUS) {
  258. sc = NtQueryVolumeInformationFile(handle,
  259. &statusBlock,
  260. buffer,
  261. sizeof(buffer),
  262. FileFsAttributeInformation);
  263. if (sc == OK_STATUS) {
  264. length = info->FileSystemNameLength;
  265. info->FileSystemName[length/sizeof(WCHAR)] = 0;
  266. length = (length+1)*sizeof(WCHAR);
  267. name = Malloc(length);
  268. RtlMoveMemory(name, info->FileSystemName, length);
  269. } else {
  270. name = Malloc(sizeof(WCHAR));
  271. *name = 0;
  272. }
  273. *Type = name;
  274. }
  275. if (sc == OK_STATUS) {
  276. sc = NtDeviceIoControlFile(handle,
  277. 0,
  278. NULL,
  279. NULL,
  280. &statusBlock,
  281. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  282. NULL,
  283. 0,
  284. (PVOID)&diskGeometry,
  285. sizeof(diskGeometry));
  286. if (NT_SUCCESS(sc)) {
  287. LARGE_INTEGER sizeInBytes;
  288. ULONG cylinderBytes;
  289. cylinderBytes = diskGeometry.TracksPerCylinder *
  290. diskGeometry.SectorsPerTrack *
  291. diskGeometry.BytesPerSector;
  292. sizeInBytes.QuadPart = diskGeometry.Cylinders.QuadPart * cylinderBytes;
  293. // Now convert everything to KB
  294. sizeInBytes.QuadPart = sizeInBytes.QuadPart >> 10;
  295. *Size = (ULONG) sizeInBytes.LowPart;
  296. }
  297. }
  298. DmClose(handle);
  299. sc = OK_STATUS;
  300. break;
  301. } else {
  302. if (firstTime) {
  303. firstTime = FALSE;
  304. } else {
  305. break;
  306. }
  307. Sleep(SLEEP_TIME);
  308. }
  309. }
  310. return EC(sc);
  311. }
  312. ULONG
  313. GetVolumeLabel(
  314. IN ULONG Disk,
  315. IN ULONG Partition,
  316. OUT PWSTR *Label
  317. )
  318. /*++
  319. Routine Description:
  320. Given a disk number and a partition number return the volume label (if
  321. any).
  322. Arguments:
  323. Disk - the disk number
  324. Partition - the partition number
  325. Label - a pointer to a pointer for a WCHAR string to contain the label
  326. Return Value:
  327. OK_STATUS - everything was performed.
  328. !OK_STATUS - the error code that was returned in the process of performing
  329. this work.
  330. --*/
  331. {
  332. IO_STATUS_BLOCK statusBlock;
  333. HANDLE handle;
  334. unsigned char buffer[256];
  335. PWSTR label;
  336. ULONG length;
  337. STATUS_CODE sc;
  338. BOOLEAN firstTime = TRUE;
  339. PFILE_FS_VOLUME_INFORMATION labelInfo = (PFILE_FS_VOLUME_INFORMATION)buffer;
  340. while (1) {
  341. sc = LowOpenPartition(GetDiskName(Disk), Partition, &handle);
  342. if (sc == OK_STATUS) {
  343. sc = NtQueryVolumeInformationFile(handle,
  344. &statusBlock,
  345. buffer,
  346. sizeof(buffer),
  347. FileFsVolumeInformation);
  348. DmClose(handle);
  349. if (sc == OK_STATUS) {
  350. length = labelInfo->VolumeLabelLength;
  351. labelInfo->VolumeLabel[length/sizeof(WCHAR)] = 0;
  352. length = (length+1) * sizeof(WCHAR);
  353. label = Malloc(length);
  354. RtlMoveMemory(label, labelInfo->VolumeLabel, length);
  355. } else {
  356. label = Malloc(sizeof(WCHAR));
  357. sc = OK_STATUS;
  358. *label = 0;
  359. }
  360. *Label = label;
  361. break;
  362. } else {
  363. if (firstTime) {
  364. firstTime = FALSE;
  365. } else {
  366. *Label = NULL;
  367. break;
  368. }
  369. Sleep(SLEEP_TIME);
  370. }
  371. }
  372. return EC(sc);
  373. }
  374. ULONG
  375. GetTypeName(
  376. IN ULONG Disk,
  377. IN ULONG Partition,
  378. OUT PWSTR *Name
  379. )
  380. /*++
  381. Routine Description:
  382. Given a disk number and partition number return the file system type
  383. string.
  384. Arguments:
  385. Disk - the disk number
  386. Partition - the partition number
  387. Name - a pointer to a pointer for a WCHAR string to contain the file system
  388. type.
  389. Return Value:
  390. OK_STATUS - everything was performed.
  391. !OK_STATUS - the error code that was returned in the process of performing
  392. this work.
  393. --*/
  394. {
  395. PWSTR name;
  396. STATUS_CODE sc;
  397. HANDLE handle;
  398. unsigned char buffer[256];
  399. IO_STATUS_BLOCK statusBlock;
  400. ULONG length;
  401. BOOLEAN firstTime = TRUE;
  402. PFILE_FS_ATTRIBUTE_INFORMATION info = (PFILE_FS_ATTRIBUTE_INFORMATION)buffer;
  403. // For some reason, the file systems believe they are locked or need
  404. // to be verified after formats and the like. Therefore this is attempted
  405. // twice before it actually gives up.
  406. while (1) {
  407. sc = LowOpenPartition(GetDiskName(Disk), Partition, &handle);
  408. if (sc == OK_STATUS) {
  409. sc = NtQueryVolumeInformationFile(handle,
  410. &statusBlock,
  411. buffer,
  412. sizeof(buffer),
  413. FileFsAttributeInformation);
  414. DmClose(handle);
  415. if (sc == OK_STATUS) {
  416. length = info->FileSystemNameLength;
  417. info->FileSystemName[length/sizeof(WCHAR)] = 0;
  418. length = (length+1)*sizeof(WCHAR);
  419. name = Malloc(length);
  420. RtlMoveMemory(name, info->FileSystemName, length);
  421. } else {
  422. name = Malloc(sizeof(WCHAR));
  423. *name = 0;
  424. sc = OK_STATUS;
  425. }
  426. *Name = name;
  427. break;
  428. } else {
  429. if (firstTime) {
  430. firstTime = FALSE;
  431. } else {
  432. break;
  433. }
  434. Sleep(SLEEP_TIME);
  435. }
  436. }
  437. return EC(sc);
  438. }
  439. BOOLEAN
  440. IsRemovable(
  441. IN ULONG DiskNumber
  442. )
  443. /*++
  444. Routine Description:
  445. This function determines whether the specified physical
  446. disk is removable.
  447. Arguments:
  448. DiskNumber -- The Physical Disk Number of the disk in question.
  449. Return Value:
  450. TRUE if the disk is removable.
  451. --*/
  452. {
  453. STATUS_CODE sc;
  454. NTSTATUS status;
  455. HANDLE handle;
  456. DISK_GEOMETRY diskGeometry;
  457. IO_STATUS_BLOCK statusBlock;
  458. PCHAR name;
  459. name = GetDiskName(DiskNumber);
  460. sc = LowOpenDisk(name, &handle);
  461. if (sc == OK_STATUS) {
  462. status = NtDeviceIoControlFile(handle,
  463. 0,
  464. NULL,
  465. NULL,
  466. &statusBlock,
  467. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  468. NULL,
  469. 0,
  470. (PVOID)&diskGeometry,
  471. sizeof(diskGeometry));
  472. LowCloseDisk(handle);
  473. if (NT_SUCCESS(status)) {
  474. if (diskGeometry.MediaType == RemovableMedia) {
  475. char ntDeviceName[100];
  476. // Do a dismount/force mount sequence to make sure
  477. // the media hasn't changed since last mount.
  478. // Dismount partition 1 by lock/unlock/close.
  479. sprintf(ntDeviceName, "%s\\Partition1", name);
  480. status= LowOpenNtName(ntDeviceName, &handle);
  481. if (NT_SUCCESS(status)) {
  482. LowLockDrive(handle);
  483. LowUnlockDrive(handle);
  484. LowCloseDisk(handle);
  485. // Now force the mount by opening the device with a '\'
  486. // This is done on partition 1 of the device.
  487. sprintf(ntDeviceName, "%s\\Partition1\\", name);
  488. status= LowOpenNtName(ntDeviceName, &handle);
  489. if (NT_SUCCESS(status)) {
  490. LowCloseDisk(handle);
  491. }
  492. }
  493. return TRUE;
  494. }
  495. }
  496. }
  497. return FALSE;
  498. }
  499. ULONG
  500. GetDriveLetterLinkTarget(
  501. IN PWSTR SourceNameStr,
  502. OUT PWSTR *LinkTarget
  503. )
  504. /*++
  505. Routine Description:
  506. Arguments:
  507. Return Value:
  508. --*/
  509. {
  510. static WCHAR targetNameBuffer[50];
  511. UNICODE_STRING sourceName,
  512. targetName;
  513. NTSTATUS status;
  514. OBJECT_ATTRIBUTES attributes;
  515. HANDLE handle;
  516. RtlInitUnicodeString(&sourceName, SourceNameStr);
  517. InitializeObjectAttributes(&attributes, &sourceName, OBJ_CASE_INSENSITIVE, NULL, NULL);
  518. status = NtOpenSymbolicLinkObject(&handle, READ_CONTROL | SYMBOLIC_LINK_QUERY, &attributes);
  519. if (NT_SUCCESS(status)) {
  520. RtlZeroMemory(targetNameBuffer, 50 * sizeof(WCHAR));
  521. targetName.Buffer = targetNameBuffer;
  522. targetName.MaximumLength = sizeof(targetNameBuffer);
  523. status = NtQuerySymbolicLinkObject(handle, &targetName, NULL);
  524. NtClose(handle);
  525. }
  526. if (NT_SUCCESS(status)) {
  527. *LinkTarget = targetName.Buffer;
  528. } else {
  529. *LinkTarget = NULL;
  530. }
  531. return EC(status);
  532. }
  533. #include "bootmbr.h"
  534. #if X86BOOTCODE_SIZE < MBOOT_CODE_SIZE
  535. #error Something is wrong with the boot code (it's too small)!
  536. #endif
  537. ULONG
  538. MasterBootCode(
  539. IN ULONG Disk,
  540. IN ULONG Signature,
  541. IN BOOLEAN SetBootCode,
  542. IN BOOLEAN SetSignature
  543. )
  544. /*++
  545. Routine Description:
  546. If the zero sector of the disk does not have a valid MBR
  547. signature (i.e. AA55), update it such that it has a valid
  548. MBR and fill in the disk signature and bootcode in the
  549. process.
  550. Arguments:
  551. Disk - the disk ordinal to be affected
  552. SetSignature - if TRUE update the disk signature
  553. Signature - the disk signature for the update
  554. Return Value:
  555. status
  556. --*/
  557. {
  558. HANDLE handle;
  559. STATUS_CODE status;
  560. PUCHAR unalignedSectorBuffer,
  561. sectorBuffer;
  562. ULONG bps,
  563. dummy,
  564. i;
  565. BOOLEAN writeIt;
  566. PCHAR diskName = GetDiskName(Disk);
  567. #ifndef max
  568. #define max(a,b) ((a > b) ? a : b)
  569. #endif
  570. if (SetBootCode) {
  571. writeIt = FALSE;
  572. // allocate sector buffer
  573. status = LowGetDriveGeometry(diskName, &dummy, &bps, &dummy, &dummy);
  574. if (status != OK_STATUS) {
  575. return EC(status);
  576. }
  577. if (bps < 512) {
  578. bps = 512;
  579. }
  580. unalignedSectorBuffer = Malloc(2*bps);
  581. sectorBuffer = (PUCHAR)(((ULONG)unalignedSectorBuffer+bps) & ~(bps-1));
  582. // open entire disk (partition 0)
  583. if ((status = LowOpenDisk(diskName, &handle)) != OK_STATUS) {
  584. return EC(status);
  585. }
  586. // read (at least) first 512 bytes
  587. status = LowReadSectors(handle, bps, 0, 1, sectorBuffer);
  588. if (status == OK_STATUS) {
  589. if ((sectorBuffer[MBOOT_SIG_OFFSET+0] != MBOOT_SIG1)
  590. || (sectorBuffer[MBOOT_SIG_OFFSET+1] != MBOOT_SIG2)) {
  591. // xfer boot code into sectorBuffer
  592. for (i=0; i<MBOOT_CODE_SIZE; i++) {
  593. sectorBuffer[i] = x86BootCode[i];
  594. }
  595. // wipe partition table
  596. for (i=MBOOT_CODE_SIZE; i<MBOOT_SIG_OFFSET; i++) {
  597. sectorBuffer[i] = 0;
  598. }
  599. // set the signature
  600. sectorBuffer[MBOOT_SIG_OFFSET+0] = MBOOT_SIG1;
  601. sectorBuffer[MBOOT_SIG_OFFSET+1] = MBOOT_SIG2;
  602. writeIt = TRUE;
  603. }
  604. if (writeIt) {
  605. status = LowWriteSectors(handle, bps, 0, 1, sectorBuffer);
  606. }
  607. }
  608. LowCloseDisk(handle);
  609. Free(unalignedSectorBuffer);
  610. }
  611. if (SetSignature) {
  612. PDRIVE_LAYOUT_INFORMATION layout;
  613. // Use the IOCTL to set the signature. This code really does
  614. // not know where the MBR exists. (ezDrive extensions).
  615. status = LowGetDiskLayout(diskName, &layout);
  616. if (status == OK_STATUS) {
  617. layout->Signature = Signature;
  618. LowSetDiskLayout(diskName, layout);
  619. }
  620. }
  621. return EC(status);
  622. }
  623. ULONG
  624. UpdateMasterBootCode(
  625. IN ULONG Disk
  626. )
  627. /*++
  628. Routine Description:
  629. This routine updates the zero sector of the disk to insure that boot
  630. code is present.
  631. Arguments:
  632. Disk - the disk number onto which to put the boot code.
  633. Return Value:
  634. status
  635. --*/
  636. {
  637. HANDLE handle;
  638. STATUS_CODE status;
  639. PUCHAR unalignedSectorBuffer,
  640. sectorBuffer;
  641. ULONG bps,
  642. dummy,
  643. i;
  644. PCHAR diskName = GetDiskName(Disk);
  645. #ifndef max
  646. #define max(a,b) ((a > b) ? a : b)
  647. #endif
  648. // allocate sector buffer
  649. status = LowGetDriveGeometry(diskName, &dummy, &bps, &dummy, &dummy);
  650. if (status != OK_STATUS) {
  651. return EC(status);
  652. }
  653. if (bps < 512) {
  654. bps = 512;
  655. }
  656. unalignedSectorBuffer = Malloc(2*bps);
  657. sectorBuffer = (PUCHAR)(((ULONG)unalignedSectorBuffer+bps) & ~(bps-1));
  658. // open entire disk (partition 0)
  659. if ((status = LowOpenDisk(diskName, &handle)) != OK_STATUS) {
  660. return EC(status);
  661. }
  662. // read (at least) first 512 bytes
  663. status = LowReadSectors(handle, bps, 0, 1, sectorBuffer);
  664. if (status == OK_STATUS) {
  665. // xfer boot code into sectorBuffer. This avoids changing the
  666. // disk signature and the partition table information.
  667. for (i=0; i<MBOOT_CODE_SIZE; i++) {
  668. sectorBuffer[i] = x86BootCode[i];
  669. }
  670. status = LowWriteSectors(handle, bps, 0, 1, sectorBuffer);
  671. }
  672. LowCloseDisk(handle);
  673. // free the sector buffer
  674. Free(unalignedSectorBuffer);
  675. return EC(status);
  676. }
  677. #if i386
  678. VOID
  679. MakePartitionActive(
  680. IN PREGION_DESCRIPTOR DiskRegionArray,
  681. IN ULONG RegionCount,
  682. IN ULONG RegionIndex
  683. )
  684. /*++
  685. Routine Description:
  686. Update the information in the internal structures to indicate
  687. that the specified partition is active.
  688. Arguments:
  689. DiskRegionArray
  690. RegionCount
  691. RegionIndex
  692. Return Value:
  693. None
  694. --*/
  695. {
  696. unsigned i;
  697. for (i=0; i<RegionCount; i++) {
  698. if (DiskRegionArray[i].RegionType == REGION_PRIMARY) {
  699. DiskRegionArray[i].Active = FALSE;
  700. SetPartitionActiveFlag(&DiskRegionArray[i], FALSE);
  701. }
  702. }
  703. DiskRegionArray[RegionIndex].Active = (BOOLEAN)0x80;
  704. SetPartitionActiveFlag(&DiskRegionArray[RegionIndex], 0x80);
  705. }
  706. #endif
  707. VOID
  708. LoadExistingPageFileInfo(
  709. IN VOID
  710. )
  711. /*++
  712. Routine Description:
  713. This routine finds all pagefiles in the system and updates the internal
  714. structures.
  715. Arguments:
  716. None
  717. Return Values:
  718. None
  719. --*/
  720. {
  721. NTSTATUS status;
  722. SYSTEM_INFO sysInfo;
  723. UCHAR genericBuffer[0x10000];
  724. PSYSTEM_PAGEFILE_INFORMATION pageFileInfo;
  725. ANSI_STRING ansiPageFileName;
  726. PPAGEFILE_LOCATION pageFileListEntry;
  727. PCHAR p;
  728. GetSystemInfo(&sysInfo);
  729. status = NtQuerySystemInformation(SystemPageFileInformation,
  730. genericBuffer,
  731. sizeof(genericBuffer),
  732. NULL);
  733. if (!NT_SUCCESS(status)) {
  734. // It's possible that this call will fail if the
  735. // the system is running without ANY paging files.
  736. return;
  737. }
  738. pageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION) genericBuffer;
  739. for (;;) {
  740. RtlUnicodeStringToAnsiString(&ansiPageFileName,
  741. &pageFileInfo->PageFileName,
  742. TRUE);
  743. // Since the format of the pagefile name generally
  744. // looks something like "\DosDevices\h:\pagefile.sys",
  745. // just use the first character before the colon
  746. // and assume that's the drive letter.
  747. p = strchr(_strlwr(ansiPageFileName.Buffer), ':');
  748. if ((p-- != NULL) && (*p >= 'a') && (*p <= 'z')) {
  749. pageFileListEntry = Malloc(sizeof(PAGEFILE_LOCATION));
  750. if (pageFileListEntry) {
  751. if (PagefileHead) {
  752. pageFileListEntry->Next = PagefileHead;
  753. } else {
  754. PagefileHead = pageFileListEntry;
  755. pageFileListEntry->Next = NULL;
  756. }
  757. pageFileListEntry->DriveLetter = *p;
  758. }
  759. }
  760. RtlFreeAnsiString(&ansiPageFileName);
  761. if (pageFileInfo->NextEntryOffset == 0) {
  762. break;
  763. }
  764. pageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)((PCHAR) pageFileInfo
  765. + pageFileInfo->NextEntryOffset);
  766. }
  767. }
  768. BOOLEAN
  769. IsPagefileOnDrive(
  770. CHAR DriveLetter
  771. )
  772. /*++
  773. Routine Description:
  774. Walk the page file list and determine if the drive letter given has
  775. a paging file. NOTE: The assumption is that drive letters that
  776. contain paging files can never get changed during the execution of
  777. Disk Administrator. Therefore this list is never updated, but
  778. can be used during the execution of Disk Administrator.
  779. Arguments:
  780. DriveLetter - the drive in question.
  781. Return Value:
  782. TRUE if this drive contains a page file.
  783. --*/
  784. {
  785. PPAGEFILE_LOCATION pageFileListEntry = PagefileHead;
  786. while (pageFileListEntry) {
  787. if (pageFileListEntry->DriveLetter == DriveLetter) {
  788. return TRUE;
  789. }
  790. pageFileListEntry = pageFileListEntry->Next;
  791. }
  792. return FALSE;
  793. }