ReactOS 0.4.16-dev-401-g45b008d
disksup.c
Go to the documentation of this file.
1/*
2* PROJECT: ReactOS Kernel
3* LICENSE: GPL - See COPYING in the top level directory
4* FILE: ntoskrnl/fstub/disksup.c
5* PURPOSE: I/O HAL Routines for Disk Access
6* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7* Eric Kohl
8* Casper S. Hornstrup (chorns@users.sourceforge.net)
9* Pierre Schweitzer
10*/
11
12/* INCLUDES ******************************************************************/
13
14#include <ntoskrnl.h>
15#define NDEBUG
16#include <debug.h>
17#include <internal/hal.h>
18
19const WCHAR DiskMountString[] = L"\\DosDevices\\%C:";
20
21#define AUTO_DRIVE MAXULONG
22
23#define PARTITION_MAGIC 0xaa55
24
25#define EFI_PMBR_OSTYPE_EFI 0xEE
26
27#include <pshpack1.h>
28
29typedef struct _REG_DISK_MOUNT_INFO
30{
34
35#include <poppack.h>
36
37typedef enum _DISK_MANAGER
38{
43
44typedef enum _PARTITION_TYPE
45{
53
58{
59 IO_STATUS_BLOCK StatusBlock;
63 PIRP Irp;
67 PAGED_CODE();
68
69 /* Get device pointers */
74 if (!NT_SUCCESS(Status))
75 {
76 return Status;
77 }
78
79 /* Get attached device object */
82
83 /* Do not handle removable media */
84 if (BooleanFlagOn(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA))
85 {
87 return STATUS_NO_MEDIA;
88 }
89
90 /* We'll loop until our buffer is big enough */
91 Buffer = NULL;
92 BufferSize = 0x1000;
94 do
95 {
96 /* If we already had a buffer, it means it's not big
97 * enough, so free and multiply size by two
98 */
99 if (Buffer != NULL)
100 {
102 BufferSize *= 2;
103 }
104
105 /* Allocate buffer for output buffer */
107 if (Buffer == NULL)
108 {
110 break;
111 }
112
113 /* Build the IRP to query drive layout */
116 NULL,
117 0,
118 Buffer,
120 FALSE,
121 &Event,
122 &StatusBlock);
123 if (Irp == NULL)
124 {
126 break;
127 }
128
129 /* Call the driver and wait if appropriate */
131 if (Status == STATUS_PENDING)
132 {
134 Executive,
136 FALSE,
137 NULL);
138 Status = StatusBlock.Status;
139 }
140 /* If buffer is too small, keep looping */
141 } while (Status == STATUS_BUFFER_TOO_SMALL);
142
143 /* We're done with the device */
145
146 /* If querying worked, then return the buffer to the caller */
147 if (NT_SUCCESS(Status))
148 {
149 ASSERT(Buffer != NULL);
150 *LayoutInfo = Buffer;
151 }
152 /* Else, release the buffer if still allocated and fail */
153 else
154 {
155 if (Buffer != NULL)
156 {
158 }
159 }
160
161 return Status;
162}
163
166 IN PDRIVE_LAYOUT_INFORMATION LayoutInfo,
168{
169 USHORT i;
170 PIRP Irp;
177
178 PAGED_CODE();
179
180 /* Get device pointers */
183 &FileObject,
184 &DeviceObject);
185 if (!NT_SUCCESS(Status))
186 {
187 return Status;
188 }
189
190 /* Get attached device object */
193
194 /* Assume logical partition for removable devices */
195 if (BooleanFlagOn(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA))
196 {
199 return STATUS_SUCCESS;
200 }
201
202 /* For the others, query partition info */
206 NULL,
207 0,
209 sizeof(PartitionInfo),
210 FALSE,
211 &Event,
213 if (Irp == NULL)
214 {
217 }
218
220 if (Status == STATUS_PENDING)
221 {
223 Executive,
225 FALSE,
226 NULL);
228 }
229
230 /* We're done with the device */
232
233 /* If we failed querying partition info, try to return something
234 * if caller didn't provide a precise layout, assume logical
235 * partition and fake success. Otherwise, just fail.
236 */
237 if (!NT_SUCCESS(Status))
238 {
239 if (LayoutInfo == NULL)
240 {
242 return STATUS_SUCCESS;
243 }
244
245 return Status;
246 }
247
248 /* First, handle non MBR style (easy cases) */
249 if (PartitionInfo.PartitionStyle != PARTITION_STYLE_MBR)
250 {
251 /* If not GPT, we don't know what it is */
252 if (PartitionInfo.PartitionStyle != PARTITION_STYLE_GPT)
253 {
255 return STATUS_SUCCESS;
256 }
257
258 /* Check whether that's data partition */
259 if (RtlCompareMemory(&PartitionInfo.Gpt.PartitionType,
260 &PARTITION_BASIC_DATA_GUID,
261 sizeof(GUID)) == sizeof(GUID))
262 {
264 return STATUS_SUCCESS;
265 }
266
267 /* Otherwise, we don't know */
269 return STATUS_SUCCESS;
270 }
271
272 /* If we don't recognize partition type, return unknown */
273 if (!IsRecognizedPartition(PartitionInfo.Mbr.PartitionType))
274 {
276 return STATUS_SUCCESS;
277 }
278
279 /* Check if that's a FT volume */
280 if (IsFTPartition(PartitionInfo.Mbr.PartitionType))
281 {
283 return STATUS_SUCCESS;
284 }
285
286 /* If the caller didn't provide the complete layout, just return */
287 if (LayoutInfo == NULL)
288 {
290 return STATUS_SUCCESS;
291 }
292
293 /* Now, evaluate the partition to the 4 in the input layout */
294 for (i = 0; i < 4; ++i)
295 {
296 /* If we find a partition matching */
297 if (LayoutInfo->PartitionEntry[i].StartingOffset.QuadPart == PartitionInfo.StartingOffset.QuadPart)
298 {
299 /* Return boot if boot flag is set */
300 if (PartitionInfo.Mbr.BootIndicator)
301 {
303 }
304 /* Primary otherwise */
305 else
306 {
308 }
309
310 return STATUS_SUCCESS;
311 }
312 }
313
314 /* Otherwise, assume logical */
316 return STATUS_SUCCESS;
317}
318
319PULONG
321{
322 PIRP Irp;
324 ULONG i, j, k;
325 PULONG Devices;
327 WCHAR Buffer[100];
328 UNICODE_STRING ArcName;
333
334 /* No disks, nothing to do */
335 if (DiskCount == 0)
336 {
337 return NULL;
338 }
339
340 /* Allocate a buffer big enough to hold all the disks */
342 sizeof(ULONG) * DiskCount,
343 TAG_FSTUB);
344 if (Devices == NULL)
345 {
346 return NULL;
347 }
348
349 /* Now, we'll query all the disks */
350 for (i = 0; i < DiskCount; ++i)
351 {
352 /* Using their ARC name */
353 swprintf(Buffer, L"\\ArcName\\multi(0)disk(0)rdisk(%d)", i);
354 RtlInitUnicodeString(&ArcName, Buffer);
355 /* Get the attached DeviceObject */
357 {
360
361 /* And query it for device number */
365 NULL,
366 0,
368 sizeof(DeviceNumber),
369 FALSE,
370 &Event,
372 if (Irp != NULL)
373 {
375 if (Status == STATUS_PENDING)
376 {
378 Executive,
380 FALSE,
381 NULL);
383 }
384
386
387 /* In case of a success remember device number */
388 if (NT_SUCCESS(Status))
389 {
390 Devices[i] = DeviceNumber.DeviceNumber;
391 /* Move on, not to fall into our default case */
392 continue;
393 }
394 }
395 else
396 {
398 }
399
400 /* Default case, for failures, set -1 */
401 Devices[i] = -1;
402 }
403 }
404
405 /* Now, we'll check all device numbers */
406 for (i = 0; i < DiskCount; ++i)
407 {
408 /* First of all, check if we're at the right place */
409 for (j = 0; j < DiskCount; ++j)
410 {
411 if (Devices[j] == i)
412 {
413 break;
414 }
415 }
416
417 /* If not, perform the change */
418 if (j >= DiskCount)
419 {
420 k = 0;
421 while (Devices[k] != -1)
422 {
423 if (++k >= DiskCount)
424 {
425 break;
426 }
427 }
428
429 if (k < DiskCount)
430 {
431 Devices[k] = i;
432 }
433 }
434 }
435
436 /* Return our device derangement map */
437 return Devices;
438}
439
442 OUT PUCHAR DriveLetter)
443{
444 PIRP Irp;
447 UNICODE_STRING MountMgr;
453
454 /* To get next mount letter, we need the MountMgr */
455 RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
458 &FileObject,
459 &DeviceObject);
460 if (!NT_SUCCESS(Status))
461 {
462 return Status;
463 }
464
465 /* Allocate our input buffer */
468 TAG_FSTUB);
469 if (Target == NULL)
470 {
473 }
474
475 /* And fill it with the device hat needs a drive letter */
476 Target->DeviceNameLength = DeviceName->Length;
477 RtlCopyMemory(&Target->DeviceName[0], DeviceName->Buffer, DeviceName->Length);
478
479 /* Call the mount manager */
483 Target,
485 &LetterInfo,
486 sizeof(LetterInfo),
487 FALSE,
488 &Event,
490 if (Irp == NULL)
491 {
495 }
496
498 if (Status == STATUS_PENDING)
499 {
501 Executive,
503 FALSE,
504 NULL);
506 }
507
510
511 DPRINT("Done: %d %c\n", LetterInfo.DriveLetterWasAssigned,
512 LetterInfo.CurrentDriveLetter);
513
514 /* Return the drive letter the MountMgr potentially assigned */
515 *DriveLetter = LetterInfo.CurrentDriveLetter;
516
517 /* Also return the success */
518 return Status;
519}
520
523 UCHAR DriveLetter)
524{
525 PIRP Irp;
528 WCHAR Buffer[30];
533 UNICODE_STRING DosDevice, MountMgr;
535
536 /* Setup the DosDevice name */
537 swprintf(Buffer, L"\\DosDevices\\%c:", DriveLetter);
538 RtlInitUnicodeString(&DosDevice, Buffer);
539
540 /* Allocate the input buffer for the MountMgr */
541 InputBufferLength = DosDevice.Length + DeviceName->Length + sizeof(MOUNTMGR_CREATE_POINT_INPUT);
543 if (InputBuffer == NULL)
544 {
546 }
547
548 /* Fill the input buffer */
549 InputBuffer->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT);
550 InputBuffer->SymbolicLinkNameLength = DosDevice.Length;
551 InputBuffer->DeviceNameOffset = DosDevice.Length + sizeof(MOUNTMGR_CREATE_POINT_INPUT);
552 InputBuffer->DeviceNameLength = DeviceName->Length;
553 RtlCopyMemory(&InputBuffer[1], DosDevice.Buffer, DosDevice.Length);
554 RtlCopyMemory((PVOID)((ULONG_PTR)InputBuffer + InputBuffer->DeviceNameOffset),
555 DeviceName->Buffer,
556 DeviceName->Length);
557
558 /* Get the MountMgr device pointer, to send the IOCTL */
559 RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
562 &FileObject,
563 &DeviceObject);
564 if (!NT_SUCCESS(Status))
565 {
567 return Status;
568 }
569
570 /* Call the MountMgr */
576 NULL,
577 0,
578 FALSE,
579 &Event,
581 if (Irp == NULL)
582 {
586 }
587
589 if (Status == STATUS_PENDING)
590 {
592 Executive,
594 FALSE,
595 NULL);
597 }
598
601
602 /* Return the MountMgr status */
603 return Status;
604}
605
606UCHAR
608 IN PSTRING NtDeviceName,
609 OUT PUCHAR NtSystemPath,
610 BOOLEAN IsRemovable)
611{
612 UCHAR i;
613 WCHAR Buffer[40];
614 UCHAR DriveLetter;
615 UNICODE_STRING FloppyString, CdString, NtDeviceNameU, DosDevice;
616
617 /* Quick path, ask directly the mount manager to assign the next
618 * free drive letter
619 */
620 if (NT_SUCCESS(HalpNextMountLetter(DeviceName, &DriveLetter)))
621 {
622 return DriveLetter;
623 }
624
625 /* We'll allow MountMgr to fail only for non vital path */
626 if (NtDeviceName == NULL || NtSystemPath == NULL)
627 {
628 return -1;
629 }
630
631 /* And for removable devices */
632 if (!IsRemovable)
633 {
634 return 0;
635 }
636
637 /* Removable might be floppy or cdrom */
638 RtlInitUnicodeString(&FloppyString, L"\\Device\\Floppy");
639 RtlInitUnicodeString(&CdString, L"\\Device\\CdRom");
640
641 /* If floppy, start at A */
642 if (RtlPrefixUnicodeString(&FloppyString, DeviceName, TRUE))
643 {
644 DriveLetter = 'A';
645 }
646 /* If CD start C */
647 else if (RtlPrefixUnicodeString(&CdString, DeviceName, TRUE))
648 {
649 DriveLetter = 'D';
650 }
651 /* For the rest start at C */
652 else
653 {
654 DriveLetter = 'C';
655 }
656
657 /* Now, try to assign a drive letter manually with the MountMgr */
658 for (i = DriveLetter; i <= 'Z'; ++i)
659 {
661 {
662 /* If it worked, if we were managing system path, update manually */
663 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NtDeviceNameU, NtDeviceName, TRUE)))
664 {
665 if (RtlEqualUnicodeString(&NtDeviceNameU, DeviceName, TRUE))
666 {
667 *NtSystemPath = i;
668 }
669
670 RtlFreeUnicodeString(&NtDeviceNameU);
671 }
672
673 return i;
674 }
675 }
676
677 /* Last fall back, we're not on a PnP device... */
678 for (i = DriveLetter; i <= 'Z'; ++i)
679 {
680 /* We'll link manually, without MountMgr knowing anything about the device */
681 swprintf(Buffer, L"\\DosDevices\\%c:", i);
682 RtlInitUnicodeString(&DosDevice, Buffer);
683
684 /* If linking worked, then the letter was free ;-) */
686 {
687 /* If it worked, if we were managing system path, update manually */
688 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NtDeviceNameU, NtDeviceName, TRUE)))
689 {
690 if (RtlEqualUnicodeString(&NtDeviceNameU, DeviceName, TRUE))
691 {
692 *NtSystemPath = i;
693 }
694
695 RtlFreeUnicodeString(&NtDeviceNameU);
696 }
697
698 return i;
699 }
700 }
701
702 /* We're done, nothing happened */
703 return 0;
704}
705
708{
709 PIRP Irp;
712 MOUNTDEV_NAME DevName;
716 PAGED_CODE();
717
718 /* Get the attached device object to our device */
721 &FileObject,
722 &DeviceObject)))
723 {
724 return FALSE;
725 }
726
729
730 /* Query its device name (ie, check floppy.sys implements MountMgr interface) */
734 NULL,
735 0,
736 &DevName,
737 sizeof(DevName),
738 FALSE,
739 &Event,
741 if (Irp == NULL)
742 {
744 return FALSE;
745 }
746
748 if (Status == STATUS_PENDING)
749 {
751 Executive,
753 FALSE,
754 NULL);
756 }
757
758 /* If status is not STATUS_BUFFER_OVERFLOW, it means
759 * it's pre-mountmgr driver, aka "Old style".
760 */
762 return (Status != STATUS_BUFFER_OVERFLOW);
763}
764
767{
768 PIRP Irp;
771 WCHAR Buffer[30];
777 UNICODE_STRING DosDevice, MountMgr;
779
780 /* Setup the device name of the letter to delete */
781 swprintf(Buffer, L"\\DosDevices\\%c:", DriveLetter);
782 RtlInitUnicodeString(&DosDevice, Buffer);
783
784 /* Allocate the input buffer for MountMgr */
785 InputBufferLength = DosDevice.Length + sizeof(MOUNTMGR_MOUNT_POINT);
787 if (InputBuffer == NULL)
788 {
790 }
791
792 /* Fill it in */
794 InputBuffer->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
795 InputBuffer->SymbolicLinkNameLength = DosDevice.Length;
796 RtlCopyMemory(&InputBuffer[1], DosDevice.Buffer, DosDevice.Length);
797
798 /* Allocate big enough output buffer (we don't care about the output) */
800 if (OutputBuffer == NULL)
801 {
804 }
805
806 /* Get the device pointer to the MountMgr */
807 RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
810 &FileObject,
811 &DeviceObject);
812 if (!NT_SUCCESS(Status))
813 {
816 return Status;
817 }
818
819 /* Call the mount manager to delete the drive letter */
826 0x1000,
827 FALSE,
828 &Event,
830 if (Irp == NULL)
831 {
836 }
837
839 if (Status == STATUS_PENDING)
840 {
842 Executive,
844 FALSE,
845 NULL);
847 }
848
852
853 return Status;
854}
855
856VOID
858{
859 PIRP Irp;
862 UNICODE_STRING MountMgr;
866
867 /* Get the device pointer to the MountMgr */
868 RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
871 &FileObject,
872 &DeviceObject);
873 if (!NT_SUCCESS(Status))
874 {
875 return;
876 }
877
878 /* Just send an IOCTL to enable the feature */
882 NULL,
883 0,
884 NULL,
885 0,
886 FALSE,
887 &Event,
889 if (Irp == NULL)
890 {
891 return;
892 }
893
895 if (Status == STATUS_PENDING)
896 {
898 Executive,
900 FALSE,
901 NULL);
903 }
904
906
907 return;
908}
909
910VOID
913 IN PSTRING NtDeviceName,
914 OUT PUCHAR NtSystemPath,
915 OUT PSTRING NtSystemPathString)
916{
917 USHORT i;
918 PULONG Devices;
920 WCHAR Buffer[50];
922 UCHAR DriveLetter;
923 BOOLEAN SystemFound;
924 IO_STATUS_BLOCK StatusBlock;
926 ANSI_STRING StringA1, StringA2;
927 PSTR Buffer1, Buffer2, LoadOptions;
929 PDRIVE_LAYOUT_INFORMATION LayoutInfo;
931 UNICODE_STRING StringU1, StringU2, StringU3;
932 ULONG Increment, DiskCount, RealDiskCount, HarddiskCount, PartitionCount, SystemPartition;
933
934 PAGED_CODE();
935
936 /* Get our disk count */
937 ConfigInfo = IoGetConfigurationInformation();
938 DiskCount = ConfigInfo->DiskCount;
939 RealDiskCount = 0;
940
941 /* Allocate two generic string buffers we'll use and reuser later on */
944 if (Buffer1 == NULL || Buffer2 == NULL)
945 {
946 KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
947 }
948
949 /* In case of a remote boot, setup system path */
951 {
952 PSTR Last, Saved;
953
954 /* Find last \ */
955 Last = strrchr(LoaderBlock->NtBootPathName, '\\');
956 Saved = NULL;
957 /* Misformed name, fail */
958 if (Last == NULL)
959 {
960 KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
961 }
962
963 /* In case the name was terminated by a \... */
964 if (Last[1] == ANSI_NULL)
965 {
966 /* Erase it, save position and find the previous \ */
967 *Last = ANSI_NULL;
968 Saved = Last;
969 Last = strrchr(LoaderBlock->NtBootPathName, '\\');
970 *Saved = '\\';
971 }
972
973 /* Misformed name, fail */
974 if (Last == NULL)
975 {
976 KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
977 }
978
979 /* For a remote boot, assign X drive letter */
980 NtSystemPath[0] = 'X';
981 NtSystemPath[1] = ':';
982 /* And copy the end of the boot path */
983 strcpy((PSTR)&NtSystemPath[2], Last);
984
985 /* If we had to remove the trailing \, remove it here too */
986 if (Saved != NULL)
987 {
988 NtSystemPath[strlen((PSTR)NtSystemPath) - 1] = ANSI_NULL;
989 }
990
991 /* Setup output string */
992 RtlInitString(NtSystemPathString, (PSTR)NtSystemPath);
993 }
994
995 /* For each of our disks, create the physical device DOS device */
996 Increment = 0;
997 if (DiskCount != 0)
998 {
999 for (i = 0; i < DiskCount; ++i)
1000 {
1001 /* Setup the origin name */
1002 sprintf(Buffer1, "\\Device\\Harddisk%d\\Partition%d", i, 0);
1003 RtlInitAnsiString(&StringA1, Buffer1);
1004 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&StringU1, &StringA1, TRUE)))
1005 {
1006 /* We cannot fail */
1007 KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
1008 }
1009
1010 /* Open the device */
1012 &StringU1,
1014 NULL,
1015 NULL);
1019 &StatusBlock,
1022 if (NT_SUCCESS(Status))
1023 {
1024 /* If we managed, create the link */
1025 sprintf(Buffer2, "\\DosDevices\\PhysicalDrive%d", i);
1026 RtlInitAnsiString(&StringA2, Buffer2);
1027 Status = RtlAnsiStringToUnicodeString(&StringU2, &StringA2, TRUE);
1028 if (NT_SUCCESS(Status))
1029 {
1030 IoCreateSymbolicLink(&StringU2, &StringU1);
1031 RtlFreeUnicodeString(&StringU2);
1032 }
1033
1035
1036 RealDiskCount = i + 1;
1037 }
1038
1039 RtlFreeUnicodeString(&StringU1);
1040
1041 if (!NT_SUCCESS(Status))
1042 {
1043 if (Increment < 50)
1044 {
1045 ++Increment;
1046 ++DiskCount;
1047 }
1048 }
1049 }
1050 }
1051
1052 /* We done for our buffers */
1053 ExFreePoolWithTag(Buffer1, TAG_FSTUB);
1054 ExFreePoolWithTag(Buffer2, TAG_FSTUB);
1055
1056 /* Upcase our load options, if any */
1057 if (LoaderBlock->LoadOptions != NULL)
1058 {
1059 LoadOptions = _strupr(LoaderBlock->LoadOptions);
1060 }
1061 else
1062 {
1063 LoadOptions = NULL;
1064 }
1065
1066 /* If we boot with /MININT (system hive as volatile) option, assign X letter to boot device */
1067 if (LoadOptions != NULL &&
1068 strstr(LoadOptions, "MININT") != 0 &&
1069 NT_SUCCESS(RtlAnsiStringToUnicodeString(&StringU1, NtDeviceName, TRUE)))
1070 {
1071 if (NT_SUCCESS(HalpSetMountLetter(&StringU1, 'X')))
1072 {
1073 *NtSystemPath = 'X';
1074 }
1075
1076 RtlFreeUnicodeString(&StringU1);
1077 }
1078
1079 /* Compute our disks derangements */
1080 DiskCount -= Increment;
1081 if (RealDiskCount > DiskCount)
1082 {
1083 DiskCount = RealDiskCount;
1084 }
1085 Devices = IopComputeHarddiskDerangements(DiskCount);
1086
1087 /* Now, start browsing all our disks for assigning drive letters
1088 * Here, we'll only handle boot partition and primary partitions
1089 */
1090 HarddiskCount = 0;
1091 for (i = 0; i < DiskCount; ++i)
1092 {
1093 /* Get device ID according to derangements map */
1094 if (Devices != NULL)
1095 {
1096 HarddiskCount = Devices[i];
1097 }
1098
1099 /* Query disk layout */
1100 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
1101 RtlInitUnicodeString(&StringU1, Buffer);
1102 if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
1103 {
1104 LayoutInfo = NULL;
1105 }
1106
1107 /* Assume we didn't find system */
1108 SystemFound = FALSE;
1109 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, 1);
1110 RtlInitUnicodeString(&StringU1, Buffer);
1111 /* Query partition info for our disk */
1112 if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1113 {
1114 /* It failed, retry for all the partitions */
1115 for (PartitionCount = 1; ; ++PartitionCount)
1116 {
1117 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1118 RtlInitUnicodeString(&StringU1, Buffer);
1119 if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1120 {
1121 break;
1122 }
1123
1124 /* We found a primary partition, assign a drive letter */
1126 {
1127 HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
1128 break;
1129 }
1130 }
1131 }
1132 else
1133 {
1134 /* All right */
1135 for (PartitionCount = 2; ; ++PartitionCount)
1136 {
1137 /* If our partition is bootable (MBR) or data (GPT), that's system partition */
1139 {
1140 SystemFound = TRUE;
1141
1142 /* Assign a drive letter and stop here if MBR */
1143 HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
1145 {
1146 break;
1147 }
1148 }
1149
1150 /* Keep looping on all the partitions */
1151 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1152 RtlInitUnicodeString(&StringU1, Buffer);
1153 if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1154 {
1155 /* Mount every primary partition if we didn't find system */
1156 if (!SystemFound)
1157 {
1158 for (PartitionCount = 1; ; ++PartitionCount)
1159 {
1160 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1161 RtlInitUnicodeString(&StringU1, Buffer);
1162 if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1163 {
1164 break;
1165 }
1166
1168 {
1169 HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
1170 break;
1171 }
1172 }
1173 }
1174
1175 break;
1176 }
1177 }
1178 }
1179
1180 /* Free layout, we'll reallocate it for next device */
1181 if (LayoutInfo != NULL)
1182 {
1183 ExFreePoolWithTag(LayoutInfo, TAG_FSTUB);
1184 }
1185
1186 HarddiskCount = i + 1;
1187 }
1188
1189 /* Now, assign logical partitions */
1190 for (i = 0; i < DiskCount; ++i)
1191 {
1192 /* Get device ID according to derangements map */
1193 if (Devices != NULL)
1194 {
1195 HarddiskCount = Devices[i];
1196 }
1197 else
1198 {
1199 HarddiskCount = i;
1200 }
1201
1202 /* Query device layout */
1203 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
1204 RtlInitUnicodeString(&StringU1, Buffer);
1205 if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
1206 {
1207 LayoutInfo = NULL;
1208 }
1209
1210 /* And assign drive letter to logical partitions */
1211 for (PartitionCount = 1; ; ++PartitionCount)
1212 {
1213 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1214 RtlInitUnicodeString(&StringU1, Buffer);
1215 if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1216 {
1217 break;
1218 }
1219
1221 {
1222 HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
1223 }
1224 }
1225
1226 /* Free layout, we'll reallocate it for next device */
1227 if (LayoutInfo != NULL)
1228 {
1229 ExFreePoolWithTag(LayoutInfo, 0);
1230 }
1231 }
1232
1233 /* Now, assign drive letters to everything else */
1234 for (i = 0; i < DiskCount; ++i)
1235 {
1236 /* Get device ID according to derangements map */
1237 if (Devices != NULL)
1238 {
1239 HarddiskCount = Devices[i];
1240 }
1241 else
1242 {
1243 HarddiskCount = i;
1244 }
1245
1246 /* Query device layout */
1247 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
1248 RtlInitUnicodeString(&StringU1, Buffer);
1249 if (!NT_SUCCESS(HalpQueryDriveLayout(&StringU1, &LayoutInfo)))
1250 {
1251 LayoutInfo = NULL;
1252 }
1253
1254 /* Save system partition if any */
1255 SystemPartition = 0;
1256 for (PartitionCount = 1; ; ++PartitionCount)
1257 {
1258 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1259 RtlInitUnicodeString(&StringU1, Buffer);
1260 if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1261 {
1262 break;
1263 }
1264
1266 {
1267 SystemPartition = PartitionCount;
1268 }
1269 }
1270
1271 /* And assign drive letter to anything but system partition */
1272 for (PartitionCount = 1; ; ++PartitionCount)
1273 {
1274 if (PartitionCount != SystemPartition)
1275 {
1276 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1277 RtlInitUnicodeString(&StringU1, Buffer);
1278 if (!NT_SUCCESS(HalpQueryPartitionType(&StringU1, LayoutInfo, &PartitionType)))
1279 {
1280 if (LayoutInfo != NULL)
1281 {
1282 ExFreePoolWithTag(LayoutInfo, 0);
1283 }
1284
1285 break;
1286 }
1287
1289 {
1290 HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, 0);
1291 }
1292 }
1293 }
1294 }
1295
1296 /* We're done with disks, if we have a device map, free it */
1297 if (Devices != NULL)
1298 {
1299 ExFreePoolWithTag(Devices, TAG_FSTUB);
1300 }
1301
1302 /* Now, assign drive letter to floppy drives */
1303 for (i = 0; i < ConfigInfo->FloppyCount; ++i)
1304 {
1305 swprintf(Buffer, L"\\Device\\Floppy%d", i);
1306 RtlInitUnicodeString(&StringU1, Buffer);
1307 if (HalpIsOldStyleFloppy(&StringU1))
1308 {
1309 HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, TRUE);
1310 }
1311 }
1312
1313 /* And CD drives */
1314 for (i = 0; i < ConfigInfo->CdRomCount; ++i)
1315 {
1316 swprintf(Buffer, L"\\Device\\CdRom%d", i);
1317 RtlInitUnicodeString(&StringU1, Buffer);
1318 HalpNextDriveLetter(&StringU1, NtDeviceName, NtSystemPath, TRUE);
1319 }
1320
1321 /* If not remote boot, handle NtDeviceName */
1322 if (!IoRemoteBootClient && NT_SUCCESS(RtlAnsiStringToUnicodeString(&StringU1, NtDeviceName, TRUE)))
1323 {
1324 /* Assign it a drive letter */
1325 DriveLetter = HalpNextDriveLetter(&StringU1, NULL, NULL, TRUE);
1326 if (DriveLetter != 0)
1327 {
1328 if (DriveLetter != 0xFF)
1329 {
1330 *NtSystemPath = DriveLetter;
1331 }
1332 }
1333 /* If it fails through mount manager, retry manually */
1334 else
1335 {
1336 RtlInitUnicodeString(&StringU2, L"\\Device\\Floppy");
1337 RtlInitUnicodeString(&StringU3, L"\\Device\\CdRom");
1338
1339 if (RtlPrefixUnicodeString(&StringU2, &StringU1, TRUE))
1340 {
1341 DriveLetter = 'A';
1342 }
1343 else if (RtlPrefixUnicodeString(&StringU3, &StringU1, TRUE))
1344 {
1345 DriveLetter = 'D';
1346 }
1347 else
1348 {
1349 DriveLetter = 'C';
1350 }
1351
1352 /* Try any drive letter */
1353 while (HalpSetMountLetter(&StringU1, DriveLetter) != STATUS_SUCCESS)
1354 {
1355 ++DriveLetter;
1356
1357 if (DriveLetter > 'Z')
1358 {
1359 break;
1360 }
1361 }
1362
1363 /* If we're beyond Z (ie, no slot left) */
1364 if (DriveLetter > 'Z')
1365 {
1366 /* Delete Z, and reuse it for system */
1368 HalpSetMountLetter(&StringU1, 'Z');
1369 *NtSystemPath = 'Z';
1370 }
1371 else
1372 {
1373 /* Return matching drive letter */
1374 *NtSystemPath = DriveLetter;
1375 }
1376 }
1377
1378 RtlFreeUnicodeString(&StringU1);
1379 }
1380
1381 /* Enable auto assignement for mountmgr */
1383}
1384
1385/* PRIVATE FUNCTIONS *********************************************************/
1386
1388NTAPI
1390 OUT PDISK_GEOMETRY_EX Geometry)
1391{
1392 PIRP Irp;
1394 PKEVENT Event;
1396
1397 PAGED_CODE();
1398
1399 /* Allocate a non-paged event */
1401 sizeof(KEVENT),
1404
1405 /* Initialize it */
1407
1408 /* Build the IRP */
1411 NULL,
1412 0UL,
1413 Geometry,
1414 sizeof(DISK_GEOMETRY_EX),
1415 FALSE,
1416 Event,
1417 &IoStatusBlock);
1418 if (!Irp)
1419 {
1420 /* Fail, free the event */
1423 }
1424
1425 /* Call the driver and check if it's pending */
1427 if (Status == STATUS_PENDING)
1428 {
1429 /* Wait on the driver */
1432 }
1433
1434 /* Free the event and return the Status */
1436 return Status;
1437}
1438
1439BOOLEAN
1440NTAPI
1442 IN ULONGLONG MaxOffset,
1443 IN ULONGLONG MaxSector)
1444{
1445 ULONGLONG EndingSector;
1446 PAGED_CODE();
1447
1448 /* Unused partitions are considered valid */
1449 if (Entry->PartitionType == PARTITION_ENTRY_UNUSED) return TRUE;
1450
1451 /* Get the last sector of the partition */
1453
1454 /* Check if it's more then the maximum sector */
1455 if (EndingSector > MaxSector)
1456 {
1457 /* Invalid partition */
1458 DPRINT1("FSTUB: entry is invalid\n");
1459 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1460 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1461 DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1462 DPRINT1("FSTUB: max %#I64x\n", MaxSector);
1463 return FALSE;
1464 }
1465 else if (GET_STARTING_SECTOR(Entry) > MaxOffset)
1466 {
1467 /* Invalid partition */
1468 DPRINT1("FSTUB: entry is invalid\n");
1469 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1470 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1471 DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1472 DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset);
1473 return FALSE;
1474 }
1475
1476 /* It's fine, return success */
1477 return TRUE;
1478}
1479
1480VOID
1481NTAPI
1483 IN PLARGE_INTEGER PartitionLength,
1484 IN CCHAR ShiftCount,
1486 IN ULONG NumberOfTracks,
1487 IN ULONG ConventionalCylinders,
1488 OUT PPARTITION_DESCRIPTOR PartitionDescriptor)
1489{
1490 LARGE_INTEGER FirstSector, SectorCount;
1491 ULONG LastSector, Remainder, SectorsPerCylinder;
1492 ULONG StartingCylinder, EndingCylinder;
1493 ULONG StartingTrack, EndingTrack;
1494 ULONG StartingSector, EndingSector;
1495 PAGED_CODE();
1496
1497 /* Calculate the number of sectors for each cylinder */
1498 SectorsPerCylinder = SectorsPerTrack * NumberOfTracks;
1499
1500 /* Calculate the first sector, and the sector count */
1501 FirstSector.QuadPart = PartitionOffset->QuadPart >> ShiftCount;
1502 SectorCount.QuadPart = PartitionLength->QuadPart >> ShiftCount;
1503
1504 /* Now calculate the last sector */
1505 LastSector = FirstSector.LowPart + SectorCount.LowPart - 1;
1506
1507 /* Calculate the first and last cylinders */
1508 StartingCylinder = FirstSector.LowPart / SectorsPerCylinder;
1509 EndingCylinder = LastSector / SectorsPerCylinder;
1510
1511 /* Set the default number of cylinders */
1512 if (!ConventionalCylinders) ConventionalCylinders = 1024;
1513
1514 /* Normalize the values */
1515 if (StartingCylinder >= ConventionalCylinders)
1516 {
1517 /* Set the maximum to 1023 */
1518 StartingCylinder = ConventionalCylinders - 1;
1519 }
1520 if (EndingCylinder >= ConventionalCylinders)
1521 {
1522 /* Set the maximum to 1023 */
1523 EndingCylinder = ConventionalCylinders - 1;
1524 }
1525
1526 /* Calculate the starting head and sector that still remain */
1527 Remainder = FirstSector.LowPart % SectorsPerCylinder;
1528 StartingTrack = Remainder / SectorsPerTrack;
1529 StartingSector = Remainder % SectorsPerTrack;
1530
1531 /* Calculate the ending head and sector that still remain */
1532 Remainder = LastSector % SectorsPerCylinder;
1533 EndingTrack = Remainder / SectorsPerTrack;
1534 EndingSector = Remainder % SectorsPerTrack;
1535
1536 /* Set cylinder data for the MSB */
1537 PartitionDescriptor->StartingCylinderMsb = (UCHAR)StartingCylinder;
1538 PartitionDescriptor->EndingCylinderMsb = (UCHAR)EndingCylinder;
1539
1540 /* Set the track data */
1541 PartitionDescriptor->StartingTrack = (UCHAR)StartingTrack;
1542 PartitionDescriptor->EndingTrack = (UCHAR)EndingTrack;
1543
1544 /* Update cylinder data for the LSB */
1545 StartingCylinder = ((StartingSector + 1) & 0x3F) |
1546 ((StartingCylinder >> 2) & 0xC0);
1547 EndingCylinder = ((EndingSector + 1) & 0x3F) |
1548 ((EndingCylinder >> 2) & 0xC0);
1549
1550 /* Set the cylinder data for the LSB */
1551 PartitionDescriptor->StartingCylinderLsb = (UCHAR)StartingCylinder;
1552 PartitionDescriptor->EndingCylinderLsb = (UCHAR)EndingCylinder;
1553}
1554
1555VOID
1558 IN PULONG ConventionalCylinders,
1559 IN PLONGLONG DiskSize)
1560{
1561 PDISK_GEOMETRY DiskGeometry = NULL;
1563 PKEVENT Event = NULL;
1564 PIRP Irp;
1566
1567 /* Set defaults */
1568 *ConventionalCylinders = 0;
1569 *DiskSize = 0;
1570
1571 /* Allocate the structure in nonpaged pool */
1572 DiskGeometry = ExAllocatePoolWithTag(NonPagedPool,
1573 sizeof(DISK_GEOMETRY),
1575 if (!DiskGeometry) goto Cleanup;
1576
1577 /* Allocate the status block in nonpaged pool */
1579 sizeof(IO_STATUS_BLOCK),
1581 if (!IoStatusBlock) goto Cleanup;
1582
1583 /* Allocate the event in nonpaged pool too */
1585 sizeof(KEVENT),
1587 if (!Event) goto Cleanup;
1588
1589 /* Initialize the event */
1591
1592 /* Build the IRP */
1595 NULL,
1596 0,
1597 DiskGeometry,
1598 sizeof(DISK_GEOMETRY),
1599 FALSE,
1600 Event,
1602 if (!Irp) goto Cleanup;
1603
1604 /* Now call the driver */
1606 if (Status == STATUS_PENDING)
1607 {
1608 /* Wait for it to complete */
1611 }
1612
1613 /* Check driver status */
1614 if (NT_SUCCESS(Status))
1615 {
1616 /* Return the cylinder count */
1617 *ConventionalCylinders = DiskGeometry->Cylinders.LowPart;
1618
1619 /* Make sure it's not larger then 1024 */
1620 if (DiskGeometry->Cylinders.LowPart >= 1024)
1621 {
1622 /* Otherwise, normalize the value */
1623 *ConventionalCylinders = 1024;
1624 }
1625
1626 /* Calculate the disk size */
1627 *DiskSize = DiskGeometry->Cylinders.QuadPart *
1628 DiskGeometry->TracksPerCylinder *
1629 DiskGeometry->SectorsPerTrack *
1630 DiskGeometry->BytesPerSector;
1631 }
1632
1633Cleanup:
1634 /* Free all the pointers */
1637 if (DiskGeometry) ExFreePoolWithTag(DiskGeometry, TAG_FILE_SYSTEM);
1638 return;
1639}
1640
1641VOID
1645 IN ULONG MbrTypeIdentifier,
1646 OUT PVOID *MbrBuffer)
1647{
1649 PUCHAR Buffer;
1651 KEVENT Event;
1653 PIRP Irp;
1654 PPARTITION_DESCRIPTOR PartitionDescriptor;
1656 PIO_STACK_LOCATION IoStackLocation;
1657
1658 Offset.QuadPart = 0;
1659
1660 /* Assume failure */
1661 *MbrBuffer = NULL;
1662
1663 /* Normalize the buffer size */
1664 BufferSize = max(512, SectorSize);
1665
1666 /* Allocate the buffer */
1670 if (!Buffer) return;
1671
1672 /* Initialize the Event */
1674
1675 /* Build the IRP */
1678 Buffer,
1679 BufferSize,
1680 &Offset,
1681 &Event,
1682 &IoStatusBlock);
1683 if (!Irp)
1684 {
1685 /* Failed */
1687 return;
1688 }
1689
1690 /* Make sure to override volume verification */
1691 IoStackLocation = IoGetNextIrpStackLocation(Irp);
1692 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1693
1694 /* Call the driver */
1696 if (Status == STATUS_PENDING)
1697 {
1698 /* Wait for completion */
1701 }
1702
1703 /* Check driver Status */
1704 if (NT_SUCCESS(Status))
1705 {
1706 /* Validate the MBR Signature */
1708 {
1709 /* Failed */
1711 return;
1712 }
1713
1714 /* Get the partition entry */
1715 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
1716
1717 /* Make sure it's what the caller wanted */
1718 if (PartitionDescriptor->PartitionType != MbrTypeIdentifier)
1719 {
1720 /* It's not, free our buffer */
1722 }
1723 else
1724 {
1725 /* Check for OnTrack Disk Manager 6.0 / EZ-Drive partitions */
1726
1727 if (PartitionDescriptor->PartitionType == PARTITION_DM)
1728 {
1729 /* Return our buffer, but at sector 63 */
1730 *(PULONG)Buffer = 63;
1731 *MbrBuffer = Buffer;
1732 }
1733 else if (PartitionDescriptor->PartitionType == PARTITION_EZDRIVE)
1734 {
1735 /* EZ-Drive, return the buffer directly */
1736 *MbrBuffer = Buffer;
1737 }
1738 else
1739 {
1740 /* Otherwise crash on debug builds */
1741 ASSERT(PartitionDescriptor->PartitionType == PARTITION_EZDRIVE);
1742 }
1743 }
1744 }
1745}
1746
1747VOID
1748NTAPI
1750 IN ULONGLONG MaxOffset)
1751{
1752 ULONG PartitionMaxOffset, PartitionLength;
1753 PAGED_CODE();
1754
1755 /* Compute partition length (according to MBR entry) */
1756 PartitionMaxOffset = GET_STARTING_SECTOR(PartitionDescriptor) + GET_PARTITION_LENGTH(PartitionDescriptor);
1757 /* In case the partition length goes beyond disk size... */
1758 if (PartitionMaxOffset > MaxOffset)
1759 {
1760 /* Resize partition to its maximum real length */
1761 PartitionLength = (ULONG)(PartitionMaxOffset - GET_STARTING_SECTOR(PartitionDescriptor));
1762 SET_PARTITION_LENGTH(PartitionDescriptor, PartitionLength);
1763 }
1764}
1765
1772{
1773 KEVENT Event;
1775 PIRP Irp;
1776 PPARTITION_DESCRIPTOR PartitionDescriptor;
1777 CCHAR Entry;
1780 PUCHAR Buffer = NULL;
1781 ULONG BufferSize = 2048, InputSize;
1782 PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo = NULL;
1783 LONG j = -1, i = -1, k;
1784 DISK_GEOMETRY_EX DiskGeometryEx;
1785 LONGLONG EndSector, MaxSector, StartOffset;
1786 LARGE_INTEGER Offset, VolumeOffset;
1787 BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE, MbrFound = FALSE;
1788 BOOLEAN IsValid, IsEmpty = TRUE;
1789 PVOID MbrBuffer;
1790 PIO_STACK_LOCATION IoStackLocation;
1792 LARGE_INTEGER HiddenSectors64;
1793
1794 PAGED_CODE();
1795
1796 VolumeOffset.QuadPart = Offset.QuadPart = 0;
1797
1798 /* Allocate the buffer */
1800 BufferSize,
1803
1804 /* Normalize the buffer size */
1805 InputSize = max(512, SectorSize);
1806
1807 /* Check for EZ-Drive */
1808 HalExamineMBR(DeviceObject, InputSize, PARTITION_EZDRIVE, &MbrBuffer);
1809 if (MbrBuffer)
1810 {
1811 /* EZ-Drive found, bias the offset */
1812 IsEzDrive = TRUE;
1814 Offset.QuadPart = 512;
1815 }
1816
1817 /* Get drive geometry */
1818 Status = HalpGetFullGeometry(DeviceObject, &DiskGeometryEx);
1819 if (!NT_SUCCESS(Status))
1820 {
1823 return Status;
1824 }
1825
1826 /* Get the end and maximum sector */
1827 EndSector = DiskGeometryEx.DiskSize.QuadPart / DiskGeometryEx.Geometry.BytesPerSector;
1828 MaxSector = EndSector << 1;
1829 DPRINT("FSTUB: DiskSize = %#I64x, MaxSector = %#I64x\n",
1830 DiskGeometryEx.DiskSize, MaxSector);
1831
1832 /* Allocate our buffer */
1834 if (!Buffer)
1835 {
1836 /* Fail, free the input buffer */
1840 }
1841
1842 /* Start partition loop */
1843 do
1844 {
1845 /* Assume the partition is valid */
1846 IsValid = TRUE;
1847
1848 /* Initialize the event */
1850
1851 /* Clear the buffer and build the IRP */
1852 RtlZeroMemory(Buffer, InputSize);
1855 Buffer,
1856 InputSize,
1857 &Offset,
1858 &Event,
1859 &IoStatusBlock);
1860 if (!Irp)
1861 {
1862 /* Failed */
1864 break;
1865 }
1866
1867 /* Make sure to disable volume verification */
1868 IoStackLocation = IoGetNextIrpStackLocation(Irp);
1869 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1870
1871 /* Call the driver */
1873 if (Status == STATUS_PENDING)
1874 {
1875 /* Wait for completion */
1878 }
1879
1880 /* Normalize status code and check for failure */
1882 if (!NT_SUCCESS(Status)) break;
1883
1884 /* If we biased for EZ-Drive, unbias now */
1885 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
1886
1887 /* Make sure this is a valid MBR */
1889 {
1890 /* It's not, fail */
1891 DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1892 "partition table %d\n", j + 1);
1893 break;
1894 }
1895
1896 /* At this point we have a valid MBR */
1897 MbrFound = TRUE;
1898
1899 /* Check if we weren't given an offset */
1900 if (!Offset.QuadPart)
1901 {
1902 /* Then read the signature off the disk */
1903 (*PartitionBuffer)->Signature = *(PUINT32)&Buffer[DISK_SIGNATURE_OFFSET];
1904 }
1905
1906 /* Get the partition descriptor array */
1907 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
1908
1909 /* Start looping partitions */
1910 j++;
1911 DPRINT("FSTUB: Partition Table %d:\n", j);
1912 for (Entry = 1, k = 0; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
1913 {
1914 /* Get the partition type */
1915 PartitionType = PartitionDescriptor->PartitionType;
1916
1917 /* Print debug messages */
1918 DPRINT("Partition Entry %d,%d: type %#x %s\n",
1919 j,
1920 Entry,
1922 (PartitionDescriptor->ActiveFlag) ? "Active" : "");
1923 DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1924 GET_STARTING_SECTOR(PartitionDescriptor),
1925 GET_PARTITION_LENGTH(PartitionDescriptor));
1926
1927 /* Check whether we're facing a protective MBR */
1929 {
1930 /* Partition length might be bigger than disk size */
1931 FstubFixupEfiPartition(PartitionDescriptor, DiskGeometryEx.DiskSize.QuadPart);
1932 }
1933
1934 /* Make sure that the partition is valid, unless it's the first */
1935 if (!(HalpIsValidPartitionEntry(PartitionDescriptor,
1936 DiskGeometryEx.DiskSize.QuadPart,
1937 MaxSector)) && (j == 0))
1938 {
1939 /* It's invalid, so fail */
1940 IsValid = FALSE;
1941 break;
1942 }
1943
1944 /* Check if it's a container */
1946 {
1947 /* Increase the count of containers */
1948 if (++k != 1)
1949 {
1950 /* More then one table is invalid */
1951 DPRINT1("FSTUB: Multiple container partitions found in "
1952 "partition table %d\n - table is invalid\n",
1953 j);
1954 IsValid = FALSE;
1955 break;
1956 }
1957 }
1958
1959 /* Check if the partition is supposedly empty */
1960 if (IsEmpty)
1961 {
1962 /* But check if it actually has a start and/or length */
1963 if ((GET_STARTING_SECTOR(PartitionDescriptor)) ||
1964 (GET_PARTITION_LENGTH(PartitionDescriptor)))
1965 {
1966 /* So then it's not really empty */
1967 IsEmpty = FALSE;
1968 }
1969 }
1970
1971 /* Check if the caller wanted only recognized partitions */
1973 {
1974 /* Then check if this one is unused, or a container */
1977 {
1978 /* Skip it, since the caller doesn't want it */
1979 continue;
1980 }
1981 }
1982
1983 /* Increase the structure count and check if they can fit */
1984 if ((sizeof(DRIVE_LAYOUT_INFORMATION) +
1985 (++i * sizeof(PARTITION_INFORMATION))) >
1986 BufferSize)
1987 {
1988 /* Allocate a new buffer that's twice as big */
1989 DriveLayoutInfo = ExAllocatePoolWithTag(NonPagedPool,
1990 BufferSize << 1,
1992 if (!DriveLayoutInfo)
1993 {
1994 /* Out of memory, undo this extra structure */
1995 --i;
1997 break;
1998 }
1999
2000 /* Copy the contents of the old buffer */
2001 RtlMoveMemory(DriveLayoutInfo,
2003 BufferSize);
2004
2005 /* Free the old buffer and set this one as the new one */
2007 *PartitionBuffer = DriveLayoutInfo;
2008
2009 /* Double the size */
2010 BufferSize <<= 1;
2011 }
2012
2013 /* Now get the current structure being filled and initialize it */
2014 PartitionInfo = &(*PartitionBuffer)->PartitionEntry[i];
2015 PartitionInfo->PartitionType = PartitionType;
2016 PartitionInfo->RewritePartition = FALSE;
2017
2018 /* Check if we're dealing with a partition that's in use */
2020 {
2021 /* Check if it's bootable */
2022 PartitionInfo->BootIndicator = PartitionDescriptor->
2023 ActiveFlag & 0x80 ?
2024 TRUE : FALSE;
2025
2026 /* Check if its' a container */
2028 {
2029 /* Then don't recognize it and use the volume offset */
2030 PartitionInfo->RecognizedPartition = FALSE;
2031 StartOffset = VolumeOffset.QuadPart;
2032 }
2033 else
2034 {
2035 /* Then recognize it and use the partition offset */
2036 PartitionInfo->RecognizedPartition = TRUE;
2037 StartOffset = Offset.QuadPart;
2038 }
2039
2040 /* Get the starting offset */
2041 PartitionInfo->StartingOffset.QuadPart =
2042 StartOffset +
2043 UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor),
2044 SectorSize);
2045
2046 /* Calculate the number of hidden sectors */
2047 HiddenSectors64.QuadPart = (PartitionInfo->
2048 StartingOffset.QuadPart -
2049 StartOffset) /
2050 SectorSize;
2051 PartitionInfo->HiddenSectors = HiddenSectors64.LowPart;
2052
2053 /* Get the partition length */
2054 PartitionInfo->PartitionLength.QuadPart =
2055 UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor),
2056 SectorSize);
2057
2058 /* Get the partition number */
2059 /* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
2060 PartitionInfo->PartitionNumber = (!IsContainerPartition(PartitionType)) ? i + 1 : 0;
2061 }
2062 else
2063 {
2064 /* Otherwise, clear all the relevant fields */
2065 PartitionInfo->BootIndicator = FALSE;
2066 PartitionInfo->RecognizedPartition = FALSE;
2067 PartitionInfo->StartingOffset.QuadPart = 0;
2068 PartitionInfo->PartitionLength.QuadPart = 0;
2069 PartitionInfo->HiddenSectors = 0;
2070
2071 /* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
2072 PartitionInfo->PartitionNumber = 0;
2073 }
2074 }
2075
2076 /* Finish debug log, and check for failure */
2077 DPRINT("\n");
2078 if (!NT_SUCCESS(Status)) break;
2079
2080 /* Also check if we hit an invalid entry here */
2081 if (!IsValid)
2082 {
2083 /* We did, so break out of the loop minus one entry */
2084 j--;
2085 break;
2086 }
2087
2088 /* Reset the offset */
2089 Offset.QuadPart = 0;
2090
2091 /* Go back to the descriptor array and loop it */
2092 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
2093 for (Entry = 1; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
2094 {
2095 /* Check if this is a container partition, since we skipped them */
2096 if (IsContainerPartition(PartitionDescriptor->PartitionType))
2097 {
2098 /* Get its offset */
2099 Offset.QuadPart = VolumeOffset.QuadPart +
2101 GET_STARTING_SECTOR(PartitionDescriptor),
2102 SectorSize);
2103
2104 /* If this is a primary partition, this is the volume offset */
2105 if (IsPrimary) VolumeOffset = Offset;
2106
2107 /* Also update the maximum sector */
2108 MaxSector = GET_PARTITION_LENGTH(PartitionDescriptor);
2109 DPRINT1("FSTUB: MaxSector now = %I64d\n", MaxSector);
2110 break;
2111 }
2112 }
2113
2114 /* Loop the next partitions, which are not primary anymore */
2115 IsPrimary = FALSE;
2116 } while (Offset.HighPart | Offset.LowPart);
2117
2118 /* Check if this is a removable device that's probably a super-floppy */
2119 if ((DiskGeometryEx.Geometry.MediaType == RemovableMedia) &&
2120 (j == 0) && (MbrFound) && (IsEmpty))
2121 {
2122 PBOOT_SECTOR_INFO BootSectorInfo = (PBOOT_SECTOR_INFO)Buffer;
2123
2124 /* Read the jump bytes to detect super-floppy */
2125 if ((BootSectorInfo->JumpByte[0] == 0xeb) ||
2126 (BootSectorInfo->JumpByte[0] == 0xe9))
2127 {
2128 /* Super floppes don't have typical MBRs, so skip them */
2129 DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
2130 "table - disk is a super floppy and has no valid MBR\n",
2131 BootSectorInfo->JumpByte);
2132 j = -1;
2133 }
2134 }
2135
2136 /* Check if we're still at partition -1 */
2137 if (j == -1)
2138 {
2139 /* The likely cause is the super floppy detection above */
2140 if ((MbrFound) || (DiskGeometryEx.Geometry.MediaType == RemovableMedia))
2141 {
2142 /* Print out debugging information */
2143 DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
2144 "super-floppy\n",
2145 DeviceObject);
2146 DPRINT1("FSTUB: Drive has %I64d sectors and is %#016I64x "
2147 "bytes large\n",
2148 EndSector, DiskGeometryEx.DiskSize);
2149
2150 /* We should at least have some sectors */
2151 if (EndSector > 0)
2152 {
2153 /* Get the entry we'll use */
2154 PartitionInfo = &(*PartitionBuffer)->PartitionEntry[0];
2155
2156 /* Fill it out with data for a super-floppy */
2157 PartitionInfo->RewritePartition = FALSE;
2158 PartitionInfo->RecognizedPartition = TRUE;
2159 PartitionInfo->PartitionType = PARTITION_FAT_16;
2160 PartitionInfo->BootIndicator = FALSE;
2161 PartitionInfo->HiddenSectors = 0;
2162 PartitionInfo->StartingOffset.QuadPart = 0;
2163 PartitionInfo->PartitionLength = DiskGeometryEx.DiskSize;
2164
2165 /* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
2166 PartitionInfo->PartitionNumber = 0;
2167
2168 /* Set the signature and set the count back to 0 */
2169 (*PartitionBuffer)->Signature = 1;
2170 i = 0;
2171 }
2172 }
2173 else
2174 {
2175 /* Otherwise, this isn't a super floppy, so set an invalid count */
2176 i = -1;
2177 }
2178 }
2179
2180 /* Set the partition count */
2181 (*PartitionBuffer)->PartitionCount = ++i;
2182
2183 /* If we have no count, delete the signature */
2184 if (!i) (*PartitionBuffer)->Signature = 0;
2185
2186 /* Free the buffer and check for success */
2188 if (!NT_SUCCESS(Status))
2189 {
2192 }
2193
2194 /* Return status */
2195 return Status;
2196}
2197
2204{
2205 PIRP Irp;
2206 KEVENT Event;
2209 LARGE_INTEGER Offset, VolumeOffset;
2210 PUCHAR Buffer = NULL;
2212 ULONG i = 0;
2213 ULONG Entry;
2214 PPARTITION_DESCRIPTOR PartitionDescriptor;
2215 BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE;
2216 PVOID MbrBuffer;
2217 PIO_STACK_LOCATION IoStackLocation;
2218
2219 PAGED_CODE();
2220
2221 VolumeOffset.QuadPart = Offset.QuadPart = 0;
2222
2223 /* Normalize the buffer size */
2224 BufferSize = max(512, SectorSize);
2225
2226 /* Check for EZ-Drive */
2228 if (MbrBuffer)
2229 {
2230 /* EZ-Drive found, bias the offset */
2231 IsEzDrive = TRUE;
2233 Offset.QuadPart = 512;
2234 }
2235
2236 /* Allocate our partition buffer */
2239
2240 /* Initialize the event we'll use and loop partitions */
2242 do
2243 {
2244 /* Reset the event since we reuse it */
2246
2247 /* Build the read IRP */
2250 Buffer,
2251 BufferSize,
2252 &Offset,
2253 &Event,
2254 &IoStatusBlock);
2255 if (!Irp)
2256 {
2257 /* Fail */
2259 break;
2260 }
2261
2262 /* Make sure to disable volume verification */
2263 IoStackLocation = IoGetNextIrpStackLocation(Irp);
2264 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2265
2266 /* Call the driver */
2268 if (Status == STATUS_PENDING)
2269 {
2270 /* Wait for completion */
2273 }
2274
2275 /* Check for failure */
2276 if (!NT_SUCCESS(Status)) break;
2277
2278 /* If we biased for EZ-Drive, unbias now */
2279 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2280
2281 /* Make sure this is a valid MBR */
2283 {
2284 /* It's not, fail */
2286 break;
2287 }
2288
2289 /* Get the partition descriptors and loop them */
2290 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
2291 for (Entry = 1; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
2292 {
2293 /* Check if it's unused or a container partition */
2294 if ((PartitionDescriptor->PartitionType == PARTITION_ENTRY_UNUSED) ||
2295 (IsContainerPartition(PartitionDescriptor->PartitionType)))
2296 {
2297 /* Go to the next one */
2298 continue;
2299 }
2300
2301 /* It's a valid partition, so increase the partition count */
2302 if (++i == PartitionNumber)
2303 {
2304 /* We found a match, set the type */
2305 PartitionDescriptor->PartitionType = (UCHAR)PartitionType;
2306
2307 /* Reset the reusable event */
2309
2310 /* Build the write IRP */
2313 Buffer,
2314 BufferSize,
2315 &Offset,
2316 &Event,
2317 &IoStatusBlock);
2318 if (!Irp)
2319 {
2320 /* Fail */
2322 break;
2323 }
2324
2325 /* Disable volume verification */
2326 IoStackLocation = IoGetNextIrpStackLocation(Irp);
2327 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2328
2329 /* Call the driver */
2331 if (Status == STATUS_PENDING)
2332 {
2333 /* Wait for completion */
2335 Executive,
2336 KernelMode,
2337 FALSE,
2338 NULL);
2340 }
2341
2342 /* We're done, break out of the loop */
2343 break;
2344 }
2345 }
2346
2347 /* If we looped all the partitions, break out */
2348 if (Entry <= NUM_PARTITION_TABLE_ENTRIES) break;
2349
2350 /* Nothing found yet, get the partition array again */
2351 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
2352 for (Entry = 1; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
2353 {
2354 /* Check if this was a container partition (we skipped these) */
2355 if (IsContainerPartition(PartitionDescriptor->PartitionType))
2356 {
2357 /* Update the partition offset */
2358 Offset.QuadPart = VolumeOffset.QuadPart +
2359 GET_STARTING_SECTOR(PartitionDescriptor) *
2360 SectorSize;
2361
2362 /* If this was the primary partition, update the volume too */
2363 if (IsPrimary) VolumeOffset = Offset;
2364 break;
2365 }
2366 }
2367
2368 /* Check if we already searched all the partitions */
2370 {
2371 /* Then we failed to find a good MBR */
2373 break;
2374 }
2375
2376 /* Loop the next partitions, which are not primary anymore */
2377 IsPrimary = FALSE;
2378 } while (i < PartitionNumber);
2379
2380 /* Everything done, cleanup */
2382 return Status;
2383}
2384
2392{
2393 KEVENT Event;
2395 PIRP Irp;
2398 PUCHAR Buffer;
2399 PPTE Entry;
2400 PPARTITION_TABLE PartitionTable;
2401 LARGE_INTEGER Offset, NextOffset, ExtendedOffset, SectorOffset;
2402 LARGE_INTEGER StartOffset, PartitionLength;
2403 ULONG i, j;
2404 CCHAR k;
2405 BOOLEAN IsEzDrive = FALSE, IsSuperFloppy = FALSE, DoRewrite = FALSE, IsMbr;
2406 ULONG ConventionalCylinders;
2407 LONGLONG DiskSize;
2409 PVOID MbrBuffer;
2411 PIO_STACK_LOCATION IoStackLocation;
2414
2415 PAGED_CODE();
2416
2417 ExtendedOffset.QuadPart = NextOffset.QuadPart = Offset.QuadPart = 0;
2418
2419 /* Normalize the buffer size */
2420 BufferSize = max(512, SectorSize);
2421
2422 /* Get the partial drive geometry */
2423 xHalGetPartialGeometry(DeviceObject, &ConventionalCylinders, &DiskSize);
2424
2425 /* Check for EZ-Drive */
2427 if (MbrBuffer)
2428 {
2429 /* EZ-Drive found, bias the offset */
2430 IsEzDrive = TRUE;
2432 Offset.QuadPart = 512;
2433 }
2434
2435 /* Get the number of bits to shift to multiply by the sector size */
2436 for (k = 0; k < 32; k++) if ((SectorSize >> k) == 1) break;
2437
2438 /* Check if there's only one partition */
2439 if (PartitionBuffer->PartitionCount == 1)
2440 {
2441 /* Check if it has no starting offset or hidden sectors */
2442 if (!(PartitionInfo->StartingOffset.QuadPart) &&
2443 !(PartitionInfo->HiddenSectors))
2444 {
2445 /* Then it's a super floppy */
2447
2448 /* Which also means it must be non-bootable FAT-16 */
2449 if ((PartitionInfo->PartitionNumber) ||
2450 (PartitionInfo->PartitionType != PARTITION_FAT_16) ||
2451 (PartitionInfo->BootIndicator))
2452 {
2453 /* It's not, so we fail */
2455 }
2456
2457 /* Check if it needs a rewrite, and disable EZ-Drive for sure */
2458 if (PartitionInfo->RewritePartition) DoRewrite = TRUE;
2459 IsEzDrive = FALSE;
2460 }
2461 }
2462
2463 /* Count the number of partition tables */
2465
2466 /* Allocate our partition buffer */
2469
2470 /* Loop the entries */
2472 for (i = 0; i < DiskLayout->TableCount; i++)
2473 {
2474 /* Set if this is the MBR partition */
2475 IsMbr= (BOOLEAN)!i;
2476
2477 /* Initialize th event */
2479
2480 /* Build the read IRP */
2483 Buffer,
2484 BufferSize,
2485 &Offset,
2486 &Event,
2487 &IoStatusBlock);
2488 if (!Irp)
2489 {
2490 /* Fail */
2492 break;
2493 }
2494
2495 /* Make sure to disable volume verification */
2496 IoStackLocation = IoGetNextIrpStackLocation(Irp);
2497 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2498
2499 /* Call the driver */
2501 if (Status == STATUS_PENDING)
2502 {
2503 /* Wait for completion */
2506 }
2507
2508 /* Check for failure */
2509 if (!NT_SUCCESS(Status)) break;
2510
2511 /* If we biased for EZ-Drive, unbias now */
2512 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2513
2514 /* Check if this is a normal disk */
2515 if (!IsSuperFloppy)
2516 {
2517 /* Set the boot record signature */
2519
2520 /* By default, don't require a rewrite */
2521 DoRewrite = FALSE;
2522
2523 /* Check if we don't have an offset */
2524 if (!Offset.QuadPart)
2525 {
2526 /* Check if the signature doesn't match */
2528 {
2529 /* Then write the signature and now we need a rewrite */
2531 DoRewrite = TRUE;
2532 }
2533 }
2534
2535 /* Loop the partition table entries */
2536 PartitionTable = &DiskLayout->PartitionTable[i];
2537 for (j = 0; j < NUM_PARTITION_TABLE_ENTRIES; j++)
2538 {
2539 /* Get the current entry and type */
2540 TableEntry = &PartitionTable->PartitionEntry[j];
2541 PartitionType = TableEntry->PartitionType;
2542
2543 /* Check if the entry needs a rewrite */
2544 if (TableEntry->RewritePartition)
2545 {
2546 /* Then we need one too */
2547 DoRewrite = TRUE;
2548
2549 /* Save the type and if it's a bootable partition */
2550 Entry[j].PartitionType = TableEntry->PartitionType;
2551 Entry[j].ActiveFlag = TableEntry->BootIndicator ? 0x80 : 0;
2552
2553 /* Make sure it's used */
2555 {
2556 /* Make sure it's not a container (unless primary) */
2557 if ((IsMbr) || !(IsContainerPartition(PartitionType)))
2558 {
2559 /* Use the partition offset */
2560 StartOffset.QuadPart = Offset.QuadPart;
2561 }
2562 else
2563 {
2564 /* Use the extended logical partition offset */
2565 StartOffset.QuadPart = ExtendedOffset.QuadPart;
2566 }
2567
2568 /* Set the sector offset */
2569 SectorOffset.QuadPart = TableEntry->
2570 StartingOffset.QuadPart -
2571 StartOffset.QuadPart;
2572
2573 /* Now calculate the starting sector */
2574 StartOffset.QuadPart = SectorOffset.QuadPart >> k;
2575 Entry[j].StartingSector = StartOffset.LowPart;
2576
2577 /* As well as the length */
2578 PartitionLength.QuadPart = TableEntry->PartitionLength.
2579 QuadPart >> k;
2580 Entry[j].PartitionLength = PartitionLength.LowPart;
2581
2582 /* Calculate the CHS values */
2583 HalpCalculateChsValues(&TableEntry->StartingOffset,
2584 &TableEntry->PartitionLength,
2585 k,
2588 ConventionalCylinders,
2590 &Entry[j]);
2591 }
2592 else
2593 {
2594 /* Otherwise set up an empty entry */
2595 Entry[j].StartingSector = 0;
2596 Entry[j].PartitionLength = 0;
2597 Entry[j].StartingTrack = 0;
2598 Entry[j].EndingTrack = 0;
2599 Entry[j].StartingCylinder = 0;
2600 Entry[j].EndingCylinder = 0;
2601 }
2602 }
2603
2604 /* Check if this is a container partition */
2606 {
2607 /* Then update the offset to use */
2608 NextOffset = TableEntry->StartingOffset;
2609 }
2610 }
2611 }
2612
2613 /* Check if we need to write back the buffer */
2614 if (DoRewrite)
2615 {
2616 /* We don't need to do this again */
2617 DoRewrite = FALSE;
2618
2619 /* Initialize the event */
2621
2622 /* If we unbiased for EZ-Drive, rebias now */
2623 if (IsEzDrive && !Offset.QuadPart) Offset.QuadPart = 512;
2624
2625 /* Build the write IRP */
2628 Buffer,
2629 BufferSize,
2630 &Offset,
2631 &Event,
2632 &IoStatusBlock);
2633 if (!Irp)
2634 {
2635 /* Fail */
2637 break;
2638 }
2639
2640 /* Make sure to disable volume verification */
2641 IoStackLocation = IoGetNextIrpStackLocation(Irp);
2642 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2643
2644 /* Call the driver */
2646 if (Status == STATUS_PENDING)
2647 {
2648 /* Wait for completion */
2650 Executive,
2651 KernelMode,
2652 FALSE,
2653 NULL);
2655 }
2656
2657 /* Check for failure */
2658 if (!NT_SUCCESS(Status)) break;
2659
2660 /* If we biased for EZ-Drive, unbias now */
2661 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2662 }
2663
2664 /* Update the partition offset and set the extended offset if needed */
2665 Offset = NextOffset;
2666 if (IsMbr) ExtendedOffset = NextOffset;
2667 }
2668
2669 /* If we had a buffer, free it, then return status */
2671 return Status;
2672}
2673
2674/* PUBLIC FUNCTIONS **********************************************************/
2675
2676/*
2677 * @implemented
2678 */
2679VOID
2683 IN ULONG MbrTypeIdentifier,
2684 OUT PVOID *MbrBuffer)
2685{
2686 HALDISPATCH->HalExamineMBR(DeviceObject,
2687 SectorSize,
2688 MbrTypeIdentifier,
2689 MbrBuffer);
2690}
2691
2692/*
2693 * @implemented
2694 */
2701{
2702 return HALDISPATCH->HalIoReadPartitionTable(DeviceObject,
2703 SectorSize,
2706}
2707
2708/*
2709 * @implemented
2710 */
2717{
2718 return HALDISPATCH->HalIoSetPartitionInformation(DeviceObject,
2719 SectorSize,
2722}
2723
2724/*
2725 * @implemented
2726 */
2734{
2735 return HALDISPATCH->HalIoWritePartitionTable(DeviceObject,
2736 SectorSize,
2740}
2741
2742/*
2743 * @implemented
2744 */
2745VOID
2748 IN PSTRING NtDeviceName,
2749 OUT PUCHAR NtSystemPath,
2750 OUT PSTRING NtSystemPathString)
2751{
2752 HALDISPATCH->HalIoAssignDriveLetters(LoaderBlock,
2753 NtDeviceName,
2754 NtSystemPath,
2755 NtSystemPathString);
2756}
2757
2758/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
PPARTENTRY SystemPartition
Definition: reactos.c:49
unsigned int * PUINT32
Definition: basetsd.h:125
unsigned short * PUINT16
Definition: basetsd.h:192
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:87
#define PARTITION_FAT_16
Definition: disk.h:91
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1434
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
#define SectorOffset(L)
Definition: cdprocs.h:1622
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
Definition: bufpool.h:45
_In_ PCHAR _In_ ULONG DeviceNumber
Definition: classpnp.h:1230
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define BufferSize
Definition: mmc.h:75
NTSTATUS FASTCALL IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: disksup.c:2697
enum _PARTITION_TYPE PARTITION_TYPE
VOID FASTCALL IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PSTRING NtDeviceName, OUT PUCHAR NtSystemPath, OUT PSTRING NtSystemPathString)
Definition: disksup.c:2747
NTSTATUS HalpDeleteMountLetter(UCHAR DriveLetter)
Definition: disksup.c:766
struct _REG_DISK_MOUNT_INFO * PREG_DISK_MOUNT_INFO
enum _PARTITION_TYPE * PPARTITION_TYPE
NTSTATUS FASTCALL xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: disksup.c:1768
PULONG IopComputeHarddiskDerangements(IN ULONG DiskCount)
Definition: disksup.c:320
_DISK_MANAGER
Definition: disksup.c:38
@ EZ_Drive
Definition: disksup.c:41
@ NoDiskManager
Definition: disksup.c:39
@ OntrackDiskManager
Definition: disksup.c:40
VOID FASTCALL xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PSTRING NtDeviceName, OUT PUCHAR NtSystemPath, OUT PSTRING NtSystemPathString)
Definition: disksup.c:912
NTSTATUS HalpQueryPartitionType(IN PUNICODE_STRING DeviceName, IN PDRIVE_LAYOUT_INFORMATION LayoutInfo, OUT PPARTITION_TYPE PartitionType)
Definition: disksup.c:165
NTSTATUS NTAPI HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject, OUT PDISK_GEOMETRY_EX Geometry)
Definition: disksup.c:1389
BOOLEAN HalpIsOldStyleFloppy(PUNICODE_STRING DeviceName)
Definition: disksup.c:707
NTSTATUS HalpSetMountLetter(IN PUNICODE_STRING DeviceName, UCHAR DriveLetter)
Definition: disksup.c:522
UCHAR HalpNextDriveLetter(IN PUNICODE_STRING DeviceName, IN PSTRING NtDeviceName, OUT PUCHAR NtSystemPath, BOOLEAN IsRemovable)
Definition: disksup.c:607
VOID NTAPI HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset, IN PLARGE_INTEGER PartitionLength, IN CCHAR ShiftCount, IN ULONG SectorsPerTrack, IN ULONG NumberOfTracks, IN ULONG ConventionalCylinders, OUT PPARTITION_DESCRIPTOR PartitionDescriptor)
Definition: disksup.c:1482
VOID FASTCALL xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject, IN PULONG ConventionalCylinders, IN PLONGLONG DiskSize)
Definition: disksup.c:1557
NTSTATUS FASTCALL IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: disksup.c:2729
const WCHAR DiskMountString[]
Definition: disksup.c:19
NTSTATUS HalpNextMountLetter(IN PUNICODE_STRING DeviceName, OUT PUCHAR DriveLetter)
Definition: disksup.c:441
VOID NTAPI FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor, IN ULONGLONG MaxOffset)
Definition: disksup.c:1749
VOID FASTCALL xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG MbrTypeIdentifier, OUT PVOID *MbrBuffer)
Definition: disksup.c:1643
NTSTATUS FASTCALL xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: disksup.c:2200
#define EFI_PMBR_OSTYPE_EFI
Definition: disksup.c:25
NTSTATUS FASTCALL HalpQueryDriveLayout(IN PUNICODE_STRING DeviceName, OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
Definition: disksup.c:56
BOOLEAN NTAPI HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry, IN ULONGLONG MaxOffset, IN ULONGLONG MaxSector)
Definition: disksup.c:1441
_PARTITION_TYPE
Definition: disksup.c:45
@ UnknownPartition
Definition: disksup.c:50
@ DataPartition
Definition: disksup.c:51
@ PrimaryPartition
Definition: disksup.c:47
@ BootablePartition
Definition: disksup.c:46
@ LogicalPartition
Definition: disksup.c:48
@ FtPartition
Definition: disksup.c:49
enum _DISK_MANAGER DISK_MANAGER
struct _REG_DISK_MOUNT_INFO REG_DISK_MOUNT_INFO
VOID HalpEnableAutomaticDriveLetterAssignment(VOID)
Definition: disksup.c:857
NTSTATUS FASTCALL IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: disksup.c:2713
NTSTATUS FASTCALL xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: disksup.c:2387
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
@ IsEmpty
Definition: atl_ax.c:995
#define FILE_SHARE_READ
Definition: compat.h:136
#define swprintf
Definition: precomp.h:40
static const WCHAR Cleanup[]
Definition: register.c:80
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define NonPagedPoolCacheAligned
Definition: env_spec_w32.h:310
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:46
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
Definition: ntddk_ex.h:208
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define UInt32x32To64(a, b)
Definition: intsafe.h:252
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define IOCTL_MOUNTMGR_DELETE_POINTS
Definition: imports.h:122
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:91
struct _MOUNTMGR_CREATE_POINT_INPUT MOUNTMGR_CREATE_POINT_INPUT
struct _MOUNTMGR_MOUNT_POINT MOUNTMGR_MOUNT_POINT
#define IOCTL_MOUNTMGR_CREATE_POINT
Definition: imports.h:116
@ PARTITION_STYLE_GPT
Definition: imports.h:202
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS
Definition: mountmgr.h:55
#define IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER
Definition: mountmgr.h:53
int k
Definition: mpi.c:3369
#define KernelMode
Definition: asm.h:38
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_READ_DATA
Definition: nt_native.h:628
NTSYSAPI VOID NTAPI RtlInitString(PSTRING DestinationString, PCSZ SourceString)
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define FASTCALL
Definition: nt_native.h:50
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define ANSI_NULL
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:390
#define IsFTPartition(PartitionType)
Definition: ntdddisk.h:315
#define PARTITION_EZDRIVE
Definition: ntdddisk.h:289
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:321
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:342
#define IOCTL_DISK_GET_DRIVE_LAYOUT
Definition: ntdddisk.h:91
@ RemovableMedia
Definition: ntdddisk.h:382
#define PARTITION_DM
Definition: ntdddisk.h:288
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
@ NotificationEvent
BOOLEAN IoRemoteBootClient
Definition: init.c:70
struct _PARTITION_DESCRIPTOR * PPARTITION_DESCRIPTOR
struct _DISK_LAYOUT * PDISK_LAYOUT
#define PARTITION_TABLE_OFFSET
Definition: hal.h:244
#define BOOT_SIGNATURE_OFFSET
Definition: hal.h:245
#define DISK_SIGNATURE_OFFSET
Definition: hal.h:243
struct _PTE * PPTE
#define SET_PARTITION_LENGTH(p, l)
Definition: hal.h:268
#define GET_PARTITION_LENGTH(p)
Definition: hal.h:262
#define GET_STARTING_SECTOR(p)
Definition: hal.h:253
struct _BOOT_SECTOR_INFO * PBOOT_SECTOR_INFO
#define NUM_PARTITION_TABLE_ENTRIES
Definition: hal.h:248
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1069
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define IoCallDriver
Definition: irp.c:1225
#define STATUS_BAD_MASTER_BOOT_RECORD
Definition: ntstatus.h:405
#define STATUS_NO_MEDIA
Definition: ntstatus.h:610
#define L(x)
Definition: ntvdm.h:50
ULONG SectorCount
Definition: part_xbox.c:31
CHAR PartitionType
Definition: part_xbox.c:32
#define HalExamineMBR
Definition: part_xbox.c:325
#define BOOT_RECORD_SIGNATURE
Definition: parttest.c:17
#define BOOLEAN
Definition: pedump.c:73
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
_CRT_RESTORE_GCC_WARNINGS _CRT_DISABLE_GCC_WARNINGS _Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
_CRTIMP char *__cdecl _strupr(_Inout_z_ char *_String)
BOOLEAN IsSuperFloppy(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:600
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:73
base of all file and directory entries
Definition: entries.h:83
UCHAR JumpByte[1]
Definition: hal.h:302
DISK_GEOMETRY Geometry
Definition: winioctl.h:330
LARGE_INTEGER DiskSize
Definition: winioctl.h:331
MEDIA_TYPE MediaType
Definition: ntdddisk.h:401
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:400
ULONG TracksPerCylinder
Definition: ntdddisk.h:402
ULONG SectorsPerTrack
Definition: ntdddisk.h:403
ULONG BytesPerSector
Definition: ntdddisk.h:404
ULONG TableCount
Definition: hal.h:324
PARTITION_TABLE PartitionTable[1]
Definition: hal.h:326
UCHAR PartitionType
Definition: hal.h:283
UCHAR ActiveFlag
Definition: hal.h:279
PARTITION_INFORMATION PartitionEntry[4]
Definition: hal.h:319
Definition: hal.h:333
LARGE_INTEGER StartingOffset
Definition: disksup.c:32
#define max(a, b)
Definition: svc.c:63
#define TAG_FSTUB
Definition: tag.h:54
#define TAG_FILE_SYSTEM
Definition: tag.h:65
#define UL
Definition: tui.h:165
uint32_t * PULONG
Definition: typedefs.h:59
char * PSTR
Definition: typedefs.h:51
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
char CCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_DATA_DETECTED
Definition: udferr_usr.h:131
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_In_ WDFREQUEST _In_ size_t _In_ size_t InputBufferLength
Definition: wdfio.h:322
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_In_ ULONG SectorSize
Definition: halfuncs.h:291
#define HALDISPATCH
Definition: haltypes.h:278
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
_In_ ULONG _In_ ULONG _In_ ULONG NumberOfHeads
Definition: iofuncs.h:2072
_In_ ULONG _In_ BOOLEAN ReturnRecognizedPartitions
Definition: iofuncs.h:2051
_In_ ULONG _In_ ULONG SectorsPerTrack
Definition: iofuncs.h:2071
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
_In_ ULONG _In_ BOOLEAN _Out_ struct _DRIVE_LAYOUT_INFORMATION ** PartitionBuffer
Definition: iofuncs.h:2052
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:4303
#define POOL_COLD_ALLOCATION
* PFILE_OBJECT
Definition: iotypes.h:1998
@ Executive
Definition: ketypes.h:415
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ LARGE_INTEGER _Out_opt_ PLARGE_INTEGER Remainder
Definition: rtlfuncs.h:3062
ret QuadPart
Definition: rtlfuncs.h:3106
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180