ReactOS 0.4.16-dev-2613-g9533ad7
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#include <internal/hal.h>
16
17#define NDEBUG
18#include <debug.h>
19
20/* See fstubex.c */
21#define EFI_PMBR_OSTYPE_EFI 0xEE
22
23typedef enum _DISK_MANAGER
24{
29
30typedef enum _PARTITION_TYPE
31{
39
40static const UNICODE_STRING FloppyPrefix = RTL_CONSTANT_STRING(L"\\Device\\Floppy");
41static const UNICODE_STRING CdPrefix = RTL_CONSTANT_STRING(L"\\Device\\CdRom");
42
43/* PRIVATE FUNCTIONS *********************************************************/
44
45static NTSTATUS
49{
50 IO_STATUS_BLOCK StatusBlock;
54 PIRP Irp;
58
59 PAGED_CODE();
60
61 /* Get device pointers */
66 if (!NT_SUCCESS(Status))
67 {
68 return Status;
69 }
70
71 /* Get attached device object */
74
75 /* Do not handle removable media */
76 if (BooleanFlagOn(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA))
77 {
79 return STATUS_NO_MEDIA;
80 }
81
82 /* We'll loop until our buffer is big enough */
83 Buffer = NULL;
84 BufferSize = 0x1000;
86 do
87 {
88 /* If we already had a buffer, it means it's not
89 * big enough, so free and multiply size by two */
90 if (Buffer != NULL)
91 {
93 BufferSize *= 2;
94 }
95
96 /* Allocate buffer for output buffer */
98 if (Buffer == NULL)
99 {
101 break;
102 }
103
104 /* Build the IRP to query drive layout */
107 NULL,
108 0,
109 Buffer,
111 FALSE,
112 &Event,
113 &StatusBlock);
114 if (Irp == NULL)
115 {
117 break;
118 }
119
120 /* Call the driver and wait if appropriate */
122 if (Status == STATUS_PENDING)
123 {
125 Executive,
127 FALSE,
128 NULL);
129 Status = StatusBlock.Status;
130 }
131 /* If buffer is too small, keep looping */
132 } while (Status == STATUS_BUFFER_TOO_SMALL);
133
134 /* We're done with the device */
136
137 /* If querying worked, return the buffer to the caller */
138 if (NT_SUCCESS(Status))
139 {
140 ASSERT(Buffer != NULL);
141 *LayoutInfo = Buffer;
142 }
143 /* Else, release the buffer if still allocated and fail */
144 else
145 {
146 if (Buffer != NULL)
147 {
149 }
150 }
151
152 return Status;
153}
154
155static NTSTATUS
160{
161 USHORT i;
162 PIRP Irp;
169
170 PAGED_CODE();
171
172 /* Get device pointers */
175 &FileObject,
176 &DeviceObject);
177 if (!NT_SUCCESS(Status))
178 {
179 return Status;
180 }
181
182 /* Get attached device object */
185
186 /* Assume logical partition for removable devices */
187 if (BooleanFlagOn(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA))
188 {
191 return STATUS_SUCCESS;
192 }
193
194 /* For the others, query partition info */
198 NULL,
199 0,
201 sizeof(PartitionInfo),
202 FALSE,
203 &Event,
205 if (Irp == NULL)
206 {
209 }
210
212 if (Status == STATUS_PENDING)
213 {
215 Executive,
217 FALSE,
218 NULL);
220 }
221
222 /* We're done with the device */
224
225 /* If we failed querying partition info, try to return something
226 * if caller didn't provide a precise layout, assume logical
227 * partition and fake success. Otherwise, just fail. */
228 if (!NT_SUCCESS(Status))
229 {
230 if (LayoutInfo == NULL)
231 {
233 return STATUS_SUCCESS;
234 }
235
236 return Status;
237 }
238
239 /* First, handle non-MBR style (easy case) */
240 if (PartitionInfo.PartitionStyle != PARTITION_STYLE_MBR)
241 {
242 /* If not GPT, we don't know what it is */
243 if (PartitionInfo.PartitionStyle != PARTITION_STYLE_GPT)
244 {
246 return STATUS_SUCCESS;
247 }
248
249 /* Check whether this is a data partition */
250 if (IsEqualGUID(&PartitionInfo.Gpt.PartitionType, &PARTITION_BASIC_DATA_GUID))
251 {
253 return STATUS_SUCCESS;
254 }
255
256 /* Otherwise, we don't know */
258 return STATUS_SUCCESS;
259 }
260
261 /* If we don't recognize partition type, return unknown */
262 if (!IsRecognizedPartition(PartitionInfo.Mbr.PartitionType))
263 {
265 return STATUS_SUCCESS;
266 }
267
268 /* Check if that's a FT volume */
269 if (IsFTPartition(PartitionInfo.Mbr.PartitionType))
270 {
272 return STATUS_SUCCESS;
273 }
274
275 /* If the caller didn't provide the complete layout, just return */
276 if (LayoutInfo == NULL)
277 {
279 return STATUS_SUCCESS;
280 }
281
282 /* Now, evaluate the partition to those in the input layout */
283 for (i = 0; i < NUM_PARTITION_TABLE_ENTRIES; ++i)
284 {
285 /* If we find a partition matching */
286 if (LayoutInfo->PartitionEntry[i].StartingOffset.QuadPart == PartitionInfo.StartingOffset.QuadPart)
287 {
288 /* Return boot if boot flag is set */
289 if (PartitionInfo.Mbr.BootIndicator)
290 {
292 }
293 /* Primary otherwise */
294 else
295 {
297 }
298
299 return STATUS_SUCCESS;
300 }
301 }
302
303 /* Otherwise, assume logical */
305 return STATUS_SUCCESS;
306}
307
308static PULONG
310 _In_ ULONG DiskCount)
311{
312 PIRP Irp;
314 ULONG i, j, k;
315 PULONG Devices;
317 WCHAR Buffer[100];
318 UNICODE_STRING ArcName;
323
324 /* No disks, nothing to do */
325 if (DiskCount == 0)
326 {
327 return NULL;
328 }
329
330 /* Allocate a buffer big enough to hold all the disks */
332 sizeof(ULONG) * DiskCount,
333 TAG_FSTUB);
334 if (Devices == NULL)
335 {
336 return NULL;
337 }
338
339 /* Now, we'll query all the disks */
340 for (i = 0; i < DiskCount; ++i)
341 {
342 /* Using their ARC name */
343 swprintf(Buffer, L"\\ArcName\\multi(0)disk(0)rdisk(%d)", i);
344 RtlInitUnicodeString(&ArcName, Buffer);
345
346 /* Get the attached DeviceObject */
349 &FileObject,
350 &DeviceObject);
351 if (NT_SUCCESS(Status))
352 {
355
356 /* And query it for device number */
360 NULL,
361 0,
363 sizeof(DeviceNumber),
364 FALSE,
365 &Event,
367 if (Irp != NULL)
368 {
370 if (Status == STATUS_PENDING)
371 {
373 Executive,
375 FALSE,
376 NULL);
378 }
379
381
382 /* In case of a success remember device number */
383 if (NT_SUCCESS(Status))
384 {
385 Devices[i] = DeviceNumber.DeviceNumber;
386 /* Move on, not to fall into our default case */
387 continue;
388 }
389 }
390 else
391 {
393 }
394
395 /* Default case, for failures, set -1 */
396 Devices[i] = -1;
397 }
398 }
399
400 /* Now, we'll check all device numbers */
401 for (i = 0; i < DiskCount; ++i)
402 {
403 /* First of all, check if we're at the right place */
404 for (j = 0; j < DiskCount; ++j)
405 {
406 if (Devices[j] == i)
407 {
408 break;
409 }
410 }
411
412 /* If not, perform the change */
413 if (j >= DiskCount)
414 {
415 k = 0;
416 while (Devices[k] != -1)
417 {
418 if (++k >= DiskCount)
419 {
420 break;
421 }
422 }
423
424 if (k < DiskCount)
425 {
426 Devices[k] = i;
427 }
428 }
429 }
430
431 /* Return our device derangement map */
432 return Devices;
433}
434
435static NTSTATUS
438 _Out_ PUCHAR DriveLetter)
439{
440 PIRP Irp;
443 UNICODE_STRING MountMgr;
449
450 /* To get next mount letter, we need the MountMgr */
451 RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
454 &FileObject,
455 &DeviceObject);
456 if (!NT_SUCCESS(Status))
457 {
458 return Status;
459 }
460
461 /* Allocate our input buffer */
464 TAG_FSTUB);
465 if (Target == NULL)
466 {
469 }
470
471 /* And fill it with the device hat needs a drive letter */
472 Target->DeviceNameLength = DeviceName->Length;
473 RtlCopyMemory(&Target->DeviceName[0], DeviceName->Buffer, DeviceName->Length);
474
475 /* Call the MountMgr */
479 Target,
481 &LetterInfo,
482 sizeof(LetterInfo),
483 FALSE,
484 &Event,
486 if (Irp == NULL)
487 {
491 }
492
494 if (Status == STATUS_PENDING)
495 {
497 Executive,
499 FALSE,
500 NULL);
502 }
503
506
507 DPRINT("Done: %d %c\n", LetterInfo.DriveLetterWasAssigned,
508 LetterInfo.CurrentDriveLetter);
509
510 /* Return the drive letter the MountMgr potentially assigned */
511 *DriveLetter = LetterInfo.CurrentDriveLetter;
512
513 /* Also return the success */
514 return Status;
515}
516
517static NTSTATUS
520 _In_ UCHAR DriveLetter)
521{
522 PIRP Irp;
525 WCHAR Buffer[30];
530 UNICODE_STRING DosDevice, MountMgr;
532
533 /* Setup the DosDevice name */
534 swprintf(Buffer, L"\\DosDevices\\%c:", DriveLetter);
535 RtlInitUnicodeString(&DosDevice, Buffer);
536
537 /* Allocate the input buffer for the MountMgr */
538 InputBufferLength = DosDevice.Length + DeviceName->Length + sizeof(MOUNTMGR_CREATE_POINT_INPUT);
540 if (InputBuffer == NULL)
541 {
543 }
544
545 /* Fill the input buffer */
546 InputBuffer->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT);
547 InputBuffer->SymbolicLinkNameLength = DosDevice.Length;
548 InputBuffer->DeviceNameOffset = DosDevice.Length + sizeof(MOUNTMGR_CREATE_POINT_INPUT);
549 InputBuffer->DeviceNameLength = DeviceName->Length;
550 RtlCopyMemory(&InputBuffer[1], DosDevice.Buffer, DosDevice.Length);
551 RtlCopyMemory((PVOID)((ULONG_PTR)InputBuffer + InputBuffer->DeviceNameOffset),
552 DeviceName->Buffer,
553 DeviceName->Length);
554
555 /* Get the MountMgr device pointer, to send the IOCTL */
556 RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
559 &FileObject,
560 &DeviceObject);
561 if (!NT_SUCCESS(Status))
562 {
564 return Status;
565 }
566
567 /* Call the MountMgr */
573 NULL,
574 0,
575 FALSE,
576 &Event,
578 if (Irp == NULL)
579 {
583 }
584
586 if (Status == STATUS_PENDING)
587 {
589 Executive,
591 FALSE,
592 NULL);
594 }
595
598
599 /* Return the MountMgr status */
600 return Status;
601}
602
603static UCHAR
606 _In_ PSTRING NtDeviceName,
607 _Out_ PUCHAR NtSystemPath,
608 _In_ BOOLEAN IsRemovable)
609{
610 UCHAR i;
611 WCHAR Buffer[40];
612 UCHAR DriveLetter;
613 UNICODE_STRING NtDeviceNameU, DosDevice;
614
615 /* Quick path, ask directly the MountMgr
616 * to assign the next free drive letter */
617 if (NT_SUCCESS(HalpNextMountLetter(DeviceName, &DriveLetter)))
618 return DriveLetter;
619
620 /* We'll allow the MountMgr to fail only for non vital path */
621 if (NtDeviceName == NULL || NtSystemPath == NULL)
622 return 0xFF;
623
624 /* And for removable devices */
625 if (!IsRemovable)
626 return 0;
627
628 /* The removable device might be a floppy or CD-ROM */
629
631 DriveLetter = 'A'; /* If floppy, start at A */
633 DriveLetter = 'D'; /* If CD-ROM, start at D */
634 else
635 DriveLetter = 'C'; /* Otherwise, start at C */
636
637 /* Now, try to assign a drive letter manually with the MountMgr */
638 for (i = DriveLetter; i <= 'Z'; ++i)
639 {
641 {
642 /* If it worked, if we were managing system path, update manually */
643 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NtDeviceNameU, NtDeviceName, TRUE)))
644 {
645 if (RtlEqualUnicodeString(&NtDeviceNameU, DeviceName, TRUE))
646 *NtSystemPath = i;
647
648 RtlFreeUnicodeString(&NtDeviceNameU);
649 }
650
651 return i;
652 }
653 }
654
655 /* Last fall back, we're not on a PnP device... */
656 for (i = DriveLetter; i <= 'Z'; ++i)
657 {
658 /* We'll link manually, without the MountMgr knowing anything about the device */
659 swprintf(Buffer, L"\\DosDevices\\%c:", i);
660 RtlInitUnicodeString(&DosDevice, Buffer);
661
662 /* If linking worked, the letter was free ;-) */
664 {
665 /* If it worked, if we were managing system path, update manually */
666 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&NtDeviceNameU, NtDeviceName, TRUE)))
667 {
668 if (RtlEqualUnicodeString(&NtDeviceNameU, DeviceName, TRUE))
669 *NtSystemPath = i;
670
671 RtlFreeUnicodeString(&NtDeviceNameU);
672 }
673
674 return i;
675 }
676 }
677
678 /* We're done, nothing happened */
679 return 0;
680}
681
682static BOOLEAN
685{
686 PIRP Irp;
689 MOUNTDEV_NAME DevName;
693
694 PAGED_CODE();
695
696 /* Get the attached device object to our device */
699 &FileObject,
700 &DeviceObject);
701 if (!NT_SUCCESS(Status))
702 return FALSE;
703
706
707 /* Query its device name (verifies that the floppy driver
708 * for this device implements the MountMgr interface) */
712 NULL,
713 0,
714 &DevName,
715 sizeof(DevName),
716 FALSE,
717 &Event,
719 if (Irp == NULL)
720 {
722 return FALSE;
723 }
724
726 if (Status == STATUS_PENDING)
727 {
729 Executive,
731 FALSE,
732 NULL);
734 }
735
736 /* If status is not STATUS_BUFFER_OVERFLOW, it means
737 * it's a pre-MountMgr driver, aka "Old style" */
739 return (Status != STATUS_BUFFER_OVERFLOW);
740}
741
742static NTSTATUS
744 _In_ UCHAR DriveLetter)
745{
746 PIRP Irp;
749 WCHAR Buffer[30];
755 UNICODE_STRING DosDevice, MountMgr;
757
758 /* Setup the device name of the letter to delete */
759 swprintf(Buffer, L"\\DosDevices\\%c:", DriveLetter);
760 RtlInitUnicodeString(&DosDevice, Buffer);
761
762 /* Allocate the input buffer for the MountMgr */
763 InputBufferLength = DosDevice.Length + sizeof(MOUNTMGR_MOUNT_POINT);
765 if (InputBuffer == NULL)
766 {
768 }
769
770 /* Fill it in */
772 InputBuffer->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
773 InputBuffer->SymbolicLinkNameLength = DosDevice.Length;
774 RtlCopyMemory(&InputBuffer[1], DosDevice.Buffer, DosDevice.Length);
775
776 /* Allocate big enough output buffer (we don't care about the output) */
778 if (OutputBuffer == NULL)
779 {
782 }
783
784 /* Get the device pointer to the MountMgr */
785 RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
788 &FileObject,
789 &DeviceObject);
790 if (!NT_SUCCESS(Status))
791 {
794 return Status;
795 }
796
797 /* Call the MountMgr to delete the drive letter */
804 0x1000,
805 FALSE,
806 &Event,
808 if (Irp == NULL)
809 {
814 }
815
817 if (Status == STATUS_PENDING)
818 {
820 Executive,
822 FALSE,
823 NULL);
825 }
826
830
831 return Status;
832}
833
834static VOID
836{
837 PIRP Irp;
840 UNICODE_STRING MountMgr;
844
845 /* Get the device pointer to the MountMgr */
846 RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
849 &FileObject,
850 &DeviceObject);
851 if (!NT_SUCCESS(Status))
852 {
853 return;
854 }
855
856 /* Just send an IOCTL to enable the feature */
860 NULL,
861 0,
862 NULL,
863 0,
864 FALSE,
865 &Event,
867 if (Irp == NULL)
868 {
869 return;
870 }
871
873 if (Status == STATUS_PENDING)
874 {
876 Executive,
878 FALSE,
879 NULL);
881 }
882
884
885 return;
886}
887
888VOID
891 IN PSTRING NtDeviceName,
892 OUT PUCHAR NtSystemPath,
893 OUT PSTRING NtSystemPathString)
894{
895 PULONG Devices;
898 UCHAR DriveLetter;
899 BOOLEAN BootableFound;
900 IO_STATUS_BLOCK StatusBlock;
902 PSTR LoadOptions;
904 PDRIVE_LAYOUT_INFORMATION LayoutInfo;
907 ULONG i, Increment, DiskCount, RealDiskCount, HarddiskCount, PartitionCount;
908 ULONG SkipPartition;
909 PWSTR Buffer2;
910 WCHAR Buffer[sizeof("\\Device\\Harddisk4294967295\\Partition4294967295")];
911
912 PAGED_CODE();
913
914 /* Get our disk count */
915 ConfigInfo = IoGetConfigurationInformation();
916 DiskCount = ConfigInfo->DiskCount;
917 RealDiskCount = 0;
918
919 /* Allocate a generic string buffer we'll use later on */
920 Buffer2 = ExAllocatePoolWithTag(NonPagedPool, 40 * sizeof(WCHAR), TAG_FSTUB);
921 if (Buffer2 == NULL)
922 {
923 /* We cannot fail */
924 KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
925 }
926
927 /* In case of a remote boot, setup the system path */
929 {
930 PSTR Last, Saved;
931
932 /* Find the last separator */
933 Last = strrchr(LoaderBlock->NtBootPathName, '\\');
934 Saved = NULL;
935 if (Last == NULL)
936 {
937 /* Misformed name, fail */
938 KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
939 }
940
941 /* In case the name was terminated by a separator... */
942 if (Last[1] == ANSI_NULL)
943 {
944 /* Erase it, save its position and find the previous separator */
945 *Last = ANSI_NULL;
946 Saved = Last;
947 Last = strrchr(LoaderBlock->NtBootPathName, '\\');
948 *Saved = '\\';
949 }
950
951 if (Last == NULL)
952 {
953 /* Misformed name, fail */
954 KeBugCheck(ASSIGN_DRIVE_LETTERS_FAILED);
955 }
956
957 /* For a remote boot, assign X drive letter */
958 NtSystemPath[0] = 'X';
959 NtSystemPath[1] = ':';
960 /* And copy the end of the boot path */
961 strcpy((PSTR)&NtSystemPath[2], Last);
962
963 /* If we had to remove the trailing separator, remove it here too */
964 if (Saved != NULL)
965 {
966 NtSystemPath[strlen((PSTR)NtSystemPath) - 1] = ANSI_NULL;
967 }
968
969 /* Setup the system path string */
970 RtlInitString(NtSystemPathString, (PSTR)NtSystemPath);
971 }
972
973 /* For each disk, create the physical drive DOS device */
974 Increment = 0;
975 for (i = 0; i < DiskCount; ++i)
976 {
977 /* Setup the device name */
978 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", i);
980
981 /* Open the device */
983 &DeviceName,
985 NULL,
986 NULL);
990 &StatusBlock,
993 if (NT_SUCCESS(Status))
994 {
995 /* If we succeeded, create the link */
996 UNICODE_STRING LinkName;
997 swprintf(Buffer2, L"\\DosDevices\\PhysicalDrive%d", i);
998 RtlInitUnicodeString(&LinkName, Buffer2);
999
1000 IoCreateSymbolicLink(&LinkName, &DeviceName);
1002
1003 RealDiskCount = i + 1;
1004 }
1005 else
1006 {
1007 /* Try to cope with holes in the \Device\HarddiskX namespace */
1008 if (Increment < 50)
1009 {
1010 ++Increment;
1011 ++DiskCount;
1012 }
1013 }
1014 }
1015
1016 /* We are done with the buffer */
1017 ExFreePoolWithTag(Buffer2, TAG_FSTUB);
1018
1019 /* Upcase the load options, if any */
1020 if (LoaderBlock->LoadOptions != NULL)
1021 LoadOptions = _strupr(LoaderBlock->LoadOptions);
1022 else
1023 LoadOptions = NULL;
1024
1025 /* If we boot with MININT option (system hive as volatile),
1026 * assign the X letter to the OS boot volume. */
1027 if (LoadOptions != NULL &&
1028 strstr(LoadOptions, "MININT") != NULL &&
1030 {
1032 *NtSystemPath = 'X';
1033
1035 }
1036
1037 /* Compute the disks derangements */
1038 DiskCount -= Increment;
1039 DiskCount = max(DiskCount, RealDiskCount);
1040 Devices = IopComputeHarddiskDerangements(DiskCount);
1041
1042 /* Now, start browsing all the disks for assigning drive letters.
1043 * Here, we'll only handle the bootable and primary partitions. */
1044 for (i = 0; i < DiskCount; ++i)
1045 {
1046 /* Get the device ID from the derangements map */
1047 HarddiskCount = (Devices ? Devices[i] : i);
1048
1049 /* Query the disk layout */
1050 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
1052 Status = HalpQueryDriveLayout(&DeviceName, &LayoutInfo);
1053 if (!NT_SUCCESS(Status))
1054 LayoutInfo = NULL;
1055
1056 /* Assume we didn't find a bootable partition */
1057 BootableFound = FALSE;
1058 for (PartitionCount = 1; ; ++PartitionCount)
1059 {
1060 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1063 if (!NT_SUCCESS(Status))
1064 {
1065 /* It failed, retry for all the partitions */
1066 break;
1067 }
1068
1069 /* If the partition is bootable (MBR) or data (GPT), we've found it */
1071 {
1072 BootableFound = TRUE;
1073
1074 /* Assign a drive letter and stop here if MBR */
1075 HalpNextDriveLetter(&DeviceName, NtDeviceName, NtSystemPath, FALSE);
1077 break;
1078 }
1079 /* Keep looping on all the partitions */
1080 }
1081
1082 /* Mount every primary partition if we didn't find a bootable partition */
1083 if (!BootableFound)
1084 {
1085 for (PartitionCount = 1; ; ++PartitionCount)
1086 {
1087 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1090 if (!NT_SUCCESS(Status))
1091 break;
1092
1093 /* We found a primary partition, assign a drive letter */
1095 {
1096 HalpNextDriveLetter(&DeviceName, NtDeviceName, NtSystemPath, FALSE);
1097 break;
1098 }
1099 }
1100 }
1101
1102 /* Free the layout, we'll reallocate it for the next disk */
1103 if (LayoutInfo != NULL)
1104 ExFreePoolWithTag(LayoutInfo, TAG_FSTUB);
1105 }
1106
1107 /* Now, assign drive letters to logical partitions */
1108 for (i = 0; i < DiskCount; ++i)
1109 {
1110 /* Get the device ID from the derangements map */
1111 HarddiskCount = (Devices ? Devices[i] : i);
1112
1113 /* Query the disk layout */
1114 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
1116 Status = HalpQueryDriveLayout(&DeviceName, &LayoutInfo);
1117 if (!NT_SUCCESS(Status))
1118 LayoutInfo = NULL;
1119
1120 /* And assign drive letters to logical partitions */
1121 for (PartitionCount = 1; ; ++PartitionCount)
1122 {
1123 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1126 if (!NT_SUCCESS(Status))
1127 break;
1128
1130 {
1131 HalpNextDriveLetter(&DeviceName, NtDeviceName, NtSystemPath, FALSE);
1132 }
1133 }
1134
1135 /* Free the layout, we'll reallocate it for the next disk */
1136 if (LayoutInfo != NULL)
1137 ExFreePoolWithTag(LayoutInfo, TAG_FSTUB);
1138 }
1139
1140 /* Now, assign drive letters to everything else */
1141 for (i = 0; i < DiskCount; ++i)
1142 {
1143 /* Get the device ID from the derangements map */
1144 HarddiskCount = (Devices ? Devices[i] : i);
1145
1146 /* Query the disk layout */
1147 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition0", HarddiskCount);
1149 Status = HalpQueryDriveLayout(&DeviceName, &LayoutInfo);
1150 if (!NT_SUCCESS(Status))
1151 LayoutInfo = NULL;
1152
1153 /* Save the bootable or first primary (MBR) partition, if any */
1154 SkipPartition = 0;
1155 for (PartitionCount = 1; ; ++PartitionCount)
1156 {
1157 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1160 if (!NT_SUCCESS(Status))
1161 break;
1162
1164 ((PartitionType == PrimaryPartition) && (SkipPartition == 0)))
1165 {
1166 SkipPartition = PartitionCount;
1167 }
1168 }
1169
1170 /* And assign a drive letter to anything but the bootable partition */
1171 for (PartitionCount = 1; ; ++PartitionCount)
1172 {
1173 if (PartitionCount == SkipPartition)
1174 continue;
1175
1176 swprintf(Buffer, L"\\Device\\Harddisk%d\\Partition%d", HarddiskCount, PartitionCount);
1179 if (!NT_SUCCESS(Status))
1180 break;
1181
1183 {
1184 HalpNextDriveLetter(&DeviceName, NtDeviceName, NtSystemPath, FALSE);
1185 }
1186 }
1187
1188 /* Free the layout, we'll reallocate it for the next disk */
1189 if (LayoutInfo != NULL)
1190 ExFreePoolWithTag(LayoutInfo, TAG_FSTUB);
1191 }
1192
1193 /* We're done with the disks; free the derangements map */
1194 if (Devices != NULL)
1195 ExFreePoolWithTag(Devices, TAG_FSTUB);
1196
1197 /* Now, assign drive letters to floppy devices:
1198 * first for legacy, then for MountMgr-aware ones. */
1199 for (i = 0; i < ConfigInfo->FloppyCount; ++i)
1200 {
1201 swprintf(Buffer, L"\\Device\\Floppy%d", i);
1203 if (HalpIsOldStyleFloppy(&DeviceName)) // Legacy device
1204 HalpNextDriveLetter(&DeviceName, NtDeviceName, NtSystemPath, TRUE);
1205 }
1206 for (i = 0; i < ConfigInfo->FloppyCount; ++i)
1207 {
1208 swprintf(Buffer, L"\\Device\\Floppy%d", i);
1210 if (!HalpIsOldStyleFloppy(&DeviceName)) // MountMgr-aware device
1211 HalpNextDriveLetter(&DeviceName, NtDeviceName, NtSystemPath, TRUE);
1212 }
1213
1214 /* And CD-ROM drives */
1215 for (i = 0; i < ConfigInfo->CdRomCount; ++i)
1216 {
1217 swprintf(Buffer, L"\\Device\\CdRom%d", i);
1219 HalpNextDriveLetter(&DeviceName, NtDeviceName, NtSystemPath, TRUE);
1220 }
1221
1222 /* If not remote boot, handle NtDeviceName */
1224 {
1225 /* Assign it a drive letter */
1226 DriveLetter = HalpNextDriveLetter(&DeviceName, NULL, NULL, TRUE);
1227 if (DriveLetter != 0)
1228 {
1229 if (DriveLetter != 0xFF)
1230 *NtSystemPath = DriveLetter;
1231 }
1232 /* If it fails through the MountMgr, retry manually */
1233 else
1234 {
1236 DriveLetter = 'A'; /* If floppy, start at A */
1238 DriveLetter = 'D'; /* If CD-ROM, start at D */
1239 else
1240 DriveLetter = 'C'; /* Otherwise, start at C */
1241
1242 /* Try any drive letter */
1243 while (HalpSetMountLetter(&DeviceName, DriveLetter) != STATUS_SUCCESS)
1244 {
1245 ++DriveLetter;
1246 if (DriveLetter > 'Z')
1247 break;
1248 }
1249
1250 /* If we're beyond Z (no letter left), delete Z and
1251 * reuse it for the OS boot volume (SystemRoot) */
1252 if (DriveLetter > 'Z')
1253 {
1254 DriveLetter = 'Z';
1255 HalpDeleteMountLetter(DriveLetter);
1256 HalpSetMountLetter(&DeviceName, DriveLetter);
1257 }
1258
1259 /* Return the matching drive letter */
1260 *NtSystemPath = DriveLetter;
1261 }
1262
1264 }
1265
1266 /* Enable auto assignment for MountMgr */
1268}
1269
1270static NTSTATUS
1273 _Out_ PDISK_GEOMETRY_EX Geometry)
1274{
1275 PIRP Irp;
1277 PKEVENT Event;
1279
1280 PAGED_CODE();
1281
1282 /* Allocate a non-paged event */
1284 sizeof(KEVENT),
1287
1288 /* Initialize it */
1290
1291 /* Build the IRP */
1294 NULL,
1295 0UL,
1296 Geometry,
1297 sizeof(DISK_GEOMETRY_EX),
1298 FALSE,
1299 Event,
1300 &IoStatusBlock);
1301 if (!Irp)
1302 {
1303 /* Fail, free the event */
1306 }
1307
1308 /* Call the driver and check if it's pending */
1310 if (Status == STATUS_PENDING)
1311 {
1312 /* Wait on the driver */
1315 }
1316
1317 /* Free the event and return the Status */
1319 return Status;
1320}
1321
1322static BOOLEAN
1325 _In_ ULONGLONG MaxOffset,
1326 _In_ ULONGLONG MaxSector)
1327{
1328 ULONGLONG EndingSector;
1329
1330 PAGED_CODE();
1331
1332 /* Unused partitions are considered valid */
1333 if (Entry->PartitionType == PARTITION_ENTRY_UNUSED)
1334 return TRUE;
1335
1336 /* Get the last sector of the partition */
1338
1339 /* Check if it's more than the maximum sector */
1340 if (EndingSector > MaxSector)
1341 {
1342 /* Invalid partition */
1343 DPRINT1("FSTUB: entry is invalid\n");
1344 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1345 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1346 DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1347 DPRINT1("FSTUB: max %#I64x\n", MaxSector);
1348 return FALSE;
1349 }
1350 else if (GET_STARTING_SECTOR(Entry) > MaxOffset)
1351 {
1352 /* Invalid partition */
1353 DPRINT1("FSTUB: entry is invalid\n");
1354 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1355 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1356 DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1357 DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset);
1358 return FALSE;
1359 }
1360
1361 /* It's fine, return success */
1362 return TRUE;
1363}
1364
1365static VOID
1367 _In_ PLARGE_INTEGER PartitionOffset,
1368 _In_ PLARGE_INTEGER PartitionLength,
1369 _In_ CCHAR ShiftCount,
1371 _In_ ULONG NumberOfTracks,
1372 _In_ ULONG ConventionalCylinders,
1373 _Out_ PPARTITION_DESCRIPTOR PartitionDescriptor)
1374{
1375 LARGE_INTEGER FirstSector, SectorCount;
1376 ULONG LastSector, Remainder, SectorsPerCylinder;
1377 ULONG StartingCylinder, EndingCylinder;
1378 ULONG StartingTrack, EndingTrack;
1379 ULONG StartingSector, EndingSector;
1380
1381 PAGED_CODE();
1382
1383 /* Calculate the number of sectors for each cylinder */
1384 SectorsPerCylinder = SectorsPerTrack * NumberOfTracks;
1385
1386 /* Calculate the first sector, and the sector count */
1387 FirstSector.QuadPart = PartitionOffset->QuadPart >> ShiftCount;
1388 SectorCount.QuadPart = PartitionLength->QuadPart >> ShiftCount;
1389
1390 /* Now calculate the last sector */
1391 LastSector = FirstSector.LowPart + SectorCount.LowPart - 1;
1392
1393 /* Calculate the first and last cylinders */
1394 StartingCylinder = FirstSector.LowPart / SectorsPerCylinder;
1395 EndingCylinder = LastSector / SectorsPerCylinder;
1396
1397 /* Set the default number of cylinders */
1398 if (!ConventionalCylinders) ConventionalCylinders = 1024;
1399
1400 /* Normalize the values */
1401 if (StartingCylinder >= ConventionalCylinders)
1402 {
1403 /* Set the maximum to 1023 */
1404 StartingCylinder = ConventionalCylinders - 1;
1405 }
1406 if (EndingCylinder >= ConventionalCylinders)
1407 {
1408 /* Set the maximum to 1023 */
1409 EndingCylinder = ConventionalCylinders - 1;
1410 }
1411
1412 /* Calculate the starting head and sector that still remain */
1413 Remainder = FirstSector.LowPart % SectorsPerCylinder;
1414 StartingTrack = Remainder / SectorsPerTrack;
1415 StartingSector = Remainder % SectorsPerTrack;
1416
1417 /* Calculate the ending head and sector that still remain */
1418 Remainder = LastSector % SectorsPerCylinder;
1419 EndingTrack = Remainder / SectorsPerTrack;
1420 EndingSector = Remainder % SectorsPerTrack;
1421
1422 /* Set cylinder data for the MSB */
1423 PartitionDescriptor->StartingCylinderMsb = (UCHAR)StartingCylinder;
1424 PartitionDescriptor->EndingCylinderMsb = (UCHAR)EndingCylinder;
1425
1426 /* Set the track data */
1427 PartitionDescriptor->StartingTrack = (UCHAR)StartingTrack;
1428 PartitionDescriptor->EndingTrack = (UCHAR)EndingTrack;
1429
1430 /* Update cylinder data for the LSB */
1431 StartingCylinder = ((StartingSector + 1) & 0x3F) |
1432 ((StartingCylinder >> 2) & 0xC0);
1433 EndingCylinder = ((EndingSector + 1) & 0x3F) |
1434 ((EndingCylinder >> 2) & 0xC0);
1435
1436 /* Set the cylinder data for the LSB */
1437 PartitionDescriptor->StartingCylinderLsb = (UCHAR)StartingCylinder;
1438 PartitionDescriptor->EndingCylinderLsb = (UCHAR)EndingCylinder;
1439}
1440
1441VOID
1444 IN PULONG ConventionalCylinders,
1445 IN PLONGLONG DiskSize)
1446{
1447 PDISK_GEOMETRY DiskGeometry = NULL;
1449 PKEVENT Event = NULL;
1450 PIRP Irp;
1452
1453 /* Set defaults */
1454 *ConventionalCylinders = 0;
1455 *DiskSize = 0;
1456
1457 /* Allocate the structure in nonpaged pool */
1458 DiskGeometry = ExAllocatePoolWithTag(NonPagedPool,
1459 sizeof(DISK_GEOMETRY),
1461 if (!DiskGeometry) goto Cleanup;
1462
1463 /* Allocate the status block in nonpaged pool */
1465 sizeof(IO_STATUS_BLOCK),
1467 if (!IoStatusBlock) goto Cleanup;
1468
1469 /* Allocate the event in nonpaged pool too */
1471 sizeof(KEVENT),
1473 if (!Event) goto Cleanup;
1474
1475 /* Initialize the event */
1477
1478 /* Build the IRP */
1481 NULL,
1482 0,
1483 DiskGeometry,
1484 sizeof(DISK_GEOMETRY),
1485 FALSE,
1486 Event,
1488 if (!Irp) goto Cleanup;
1489
1490 /* Now call the driver */
1492 if (Status == STATUS_PENDING)
1493 {
1494 /* Wait for it to complete */
1497 }
1498
1499 /* Check driver status */
1500 if (NT_SUCCESS(Status))
1501 {
1502 /* Return the cylinder count */
1503 *ConventionalCylinders = DiskGeometry->Cylinders.LowPart;
1504
1505 /* Make sure it's not larger than 1024 */
1506 if (DiskGeometry->Cylinders.LowPart >= 1024)
1507 {
1508 /* Otherwise, normalize the value */
1509 *ConventionalCylinders = 1024;
1510 }
1511
1512 /* Calculate the disk size */
1513 *DiskSize = DiskGeometry->Cylinders.QuadPart *
1514 DiskGeometry->TracksPerCylinder *
1515 DiskGeometry->SectorsPerTrack *
1516 DiskGeometry->BytesPerSector;
1517 }
1518
1519Cleanup:
1520 /* Free all the pointers */
1523 if (DiskGeometry) ExFreePoolWithTag(DiskGeometry, TAG_FILE_SYSTEM);
1524 return;
1525}
1526
1527VOID
1531 IN ULONG MbrTypeIdentifier,
1532 OUT PVOID *MbrBuffer)
1533{
1535 PUCHAR Buffer;
1537 KEVENT Event;
1539 PIRP Irp;
1540 PPARTITION_DESCRIPTOR PartitionDescriptor;
1543
1544 Offset.QuadPart = 0;
1545
1546 /* Assume failure */
1547 *MbrBuffer = NULL;
1548
1549 /* Normalize the buffer size */
1550 BufferSize = max(512, SectorSize);
1551
1552 /* Allocate the buffer */
1556 if (!Buffer) return;
1557
1558 /* Initialize the Event */
1560
1561 /* Build the IRP */
1564 Buffer,
1565 BufferSize,
1566 &Offset,
1567 &Event,
1568 &IoStatusBlock);
1569 if (!Irp)
1570 {
1571 /* Failed */
1573 return;
1574 }
1575
1576 /* Make sure to override volume verification */
1579
1580 /* Call the driver */
1582 if (Status == STATUS_PENDING)
1583 {
1584 /* Wait for completion */
1587 }
1588
1589 /* Check driver status */
1590 if (NT_SUCCESS(Status))
1591 {
1592 /* Validate the MBR Signature */
1594 {
1595 /* Failed */
1597 return;
1598 }
1599
1600 /* Get the partition entry */
1601 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
1602
1603 /* Make sure it's what the caller wanted */
1604 if (PartitionDescriptor->PartitionType != MbrTypeIdentifier)
1605 {
1606 /* It's not, free our buffer */
1608 }
1609 else
1610 {
1611 /* Check for OnTrack Disk Manager 6.0 / EZ-Drive partitions */
1612
1613 if (PartitionDescriptor->PartitionType == PARTITION_DM)
1614 {
1615 /* Return our buffer, but at sector 63 */
1616 *(PULONG)Buffer = 63;
1617 *MbrBuffer = Buffer;
1618 }
1619 else if (PartitionDescriptor->PartitionType == PARTITION_EZDRIVE)
1620 {
1621 /* EZ-Drive, return the buffer directly */
1622 *MbrBuffer = Buffer;
1623 }
1624 else
1625 {
1626 /* Otherwise crash on debug builds */
1627 ASSERT(PartitionDescriptor->PartitionType == PARTITION_EZDRIVE);
1628 }
1629 }
1630 }
1631}
1632
1633VOID
1634NTAPI
1636 IN ULONGLONG MaxOffset)
1637{
1638 ULONG PartitionMaxOffset, PartitionLength;
1639 PAGED_CODE();
1640
1641 /* Compute partition length (according to MBR entry) */
1642 PartitionMaxOffset = GET_STARTING_SECTOR(PartitionDescriptor) + GET_PARTITION_LENGTH(PartitionDescriptor);
1643 /* In case the partition length goes beyond disk size... */
1644 if (PartitionMaxOffset > MaxOffset)
1645 {
1646 /* Resize partition to its maximum real length */
1647 PartitionLength = (ULONG)(PartitionMaxOffset - GET_STARTING_SECTOR(PartitionDescriptor));
1648 SET_PARTITION_LENGTH(PartitionDescriptor, PartitionLength);
1649 }
1650}
1651
1658{
1659 KEVENT Event;
1661 PIRP Irp;
1662 PPARTITION_DESCRIPTOR PartitionDescriptor;
1663 CCHAR Entry;
1666 PUCHAR Buffer = NULL;
1667 ULONG BufferSize = 2048, InputSize;
1668 PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo = NULL;
1669 LONG j = -1, i = -1, k;
1670 DISK_GEOMETRY_EX DiskGeometryEx;
1671 LONGLONG EndSector, MaxSector, StartOffset;
1672 LARGE_INTEGER Offset, VolumeOffset;
1673 BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE, MbrFound = FALSE;
1674 BOOLEAN IsValid, IsEmpty = TRUE;
1675 PVOID MbrBuffer;
1678 LARGE_INTEGER HiddenSectors64;
1679
1680 PAGED_CODE();
1681
1682 VolumeOffset.QuadPart = Offset.QuadPart = 0;
1683
1684 /* Allocate the buffer */
1686 BufferSize,
1689
1690 /* Normalize the buffer size */
1691 InputSize = max(512, SectorSize);
1692
1693 /* Check for EZ-Drive */
1694 HalExamineMBR(DeviceObject, InputSize, PARTITION_EZDRIVE, &MbrBuffer);
1695 if (MbrBuffer)
1696 {
1697 /* EZ-Drive found, bias the offset */
1698 IsEzDrive = TRUE;
1700 Offset.QuadPart = 512;
1701 }
1702
1703 /* Get drive geometry */
1704 Status = HalpGetFullGeometry(DeviceObject, &DiskGeometryEx);
1705 if (!NT_SUCCESS(Status))
1706 {
1709 return Status;
1710 }
1711
1712 /* Get the end and maximum sector */
1713 EndSector = DiskGeometryEx.DiskSize.QuadPart / DiskGeometryEx.Geometry.BytesPerSector;
1714 MaxSector = EndSector << 1;
1715 DPRINT("FSTUB: DiskSize = %#I64x, MaxSector = %#I64x\n",
1716 DiskGeometryEx.DiskSize, MaxSector);
1717
1718 /* Allocate our buffer */
1720 if (!Buffer)
1721 {
1722 /* Fail, free the input buffer */
1726 }
1727
1728 /* Start partition loop */
1729 do
1730 {
1731 /* Assume the partition is valid */
1732 IsValid = TRUE;
1733
1734 /* Initialize the event */
1736
1737 /* Clear the buffer and build the IRP */
1738 RtlZeroMemory(Buffer, InputSize);
1741 Buffer,
1742 InputSize,
1743 &Offset,
1744 &Event,
1745 &IoStatusBlock);
1746 if (!Irp)
1747 {
1748 /* Failed */
1750 break;
1751 }
1752
1753 /* Make sure to disable volume verification */
1756
1757 /* Call the driver */
1759 if (Status == STATUS_PENDING)
1760 {
1761 /* Wait for completion */
1764 }
1765
1766 /* Normalize status code and check for failure */
1768 if (!NT_SUCCESS(Status)) break;
1769
1770 /* If we biased for EZ-Drive, unbias now */
1771 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
1772
1773 /* Make sure this is a valid MBR */
1775 {
1776 /* It's not, fail */
1777 DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1778 "partition table %d\n", j + 1);
1779 break;
1780 }
1781
1782 /* At this point we have a valid MBR */
1783 MbrFound = TRUE;
1784
1785 /* Check if we weren't given an offset */
1786 if (!Offset.QuadPart)
1787 {
1788 /* Then read the signature off the disk */
1789 (*PartitionBuffer)->Signature = *(PUINT32)&Buffer[DISK_SIGNATURE_OFFSET];
1790 }
1791
1792 /* Get the partition descriptor array */
1793 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
1794
1795 /* Start looping partitions */
1796 j++;
1797 DPRINT("FSTUB: Partition Table %d:\n", j);
1798 for (Entry = 1, k = 0; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
1799 {
1800 /* Get the partition type */
1801 PartitionType = PartitionDescriptor->PartitionType;
1802
1803 /* Print debug messages */
1804 DPRINT("Partition Entry %d,%d: type %#x %s\n",
1805 j,
1806 Entry,
1808 (PartitionDescriptor->ActiveFlag) ? "Active" : "");
1809 DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1810 GET_STARTING_SECTOR(PartitionDescriptor),
1811 GET_PARTITION_LENGTH(PartitionDescriptor));
1812
1813 /* Check whether we're facing a protective MBR */
1815 {
1816 /* Partition length might be bigger than disk size */
1817 FstubFixupEfiPartition(PartitionDescriptor, DiskGeometryEx.DiskSize.QuadPart);
1818 }
1819
1820 /* Make sure that the partition is valid, unless it's the first */
1821 if (!(HalpIsValidPartitionEntry(PartitionDescriptor,
1822 DiskGeometryEx.DiskSize.QuadPart,
1823 MaxSector)) && (j == 0))
1824 {
1825 /* It's invalid, so fail */
1826 IsValid = FALSE;
1827 break;
1828 }
1829
1830 /* Check if it's a container */
1832 {
1833 /* Increase the count of containers */
1834 if (++k != 1)
1835 {
1836 /* More than one table is invalid */
1837 DPRINT1("FSTUB: Multiple container partitions found in "
1838 "partition table %d\n - table is invalid\n",
1839 j);
1840 IsValid = FALSE;
1841 break;
1842 }
1843 }
1844
1845 /* Check if the partition is supposedly empty */
1846 if (IsEmpty)
1847 {
1848 /* But check if it actually has a start and/or length */
1849 if ((GET_STARTING_SECTOR(PartitionDescriptor)) ||
1850 (GET_PARTITION_LENGTH(PartitionDescriptor)))
1851 {
1852 /* So then it's not really empty */
1853 IsEmpty = FALSE;
1854 }
1855 }
1856
1857 /* Check if the caller wanted only recognized partitions */
1859 {
1860 /* Then check if this one is unused, or a container */
1863 {
1864 /* Skip it, since the caller doesn't want it */
1865 continue;
1866 }
1867 }
1868
1869 /* Increase the structure count and check if they can fit */
1870 if ((sizeof(DRIVE_LAYOUT_INFORMATION) +
1871 (++i * sizeof(PARTITION_INFORMATION))) >
1872 BufferSize)
1873 {
1874 /* Allocate a new buffer that's twice as big */
1875 DriveLayoutInfo = ExAllocatePoolWithTag(NonPagedPool,
1876 BufferSize << 1,
1878 if (!DriveLayoutInfo)
1879 {
1880 /* Out of memory, undo this extra structure */
1881 --i;
1883 break;
1884 }
1885
1886 /* Copy the contents of the old buffer */
1887 RtlMoveMemory(DriveLayoutInfo,
1889 BufferSize);
1890
1891 /* Free the old buffer and set this one as the new one */
1893 *PartitionBuffer = DriveLayoutInfo;
1894
1895 /* Double the size */
1896 BufferSize <<= 1;
1897 }
1898
1899 /* Now get the current structure being filled and initialize it */
1900 PartitionInfo = &(*PartitionBuffer)->PartitionEntry[i];
1901 PartitionInfo->PartitionType = PartitionType;
1902 PartitionInfo->RewritePartition = FALSE;
1903
1904 /* Check if we're dealing with a partition that's in use */
1906 {
1907 /* Check if it's bootable */
1908 PartitionInfo->BootIndicator = !!(PartitionDescriptor->ActiveFlag & 0x80);
1909
1910 /* Check if it's a container */
1912 {
1913 /* Then don't recognize it and use the volume offset */
1914 PartitionInfo->RecognizedPartition = FALSE;
1915 StartOffset = VolumeOffset.QuadPart;
1916 }
1917 else
1918 {
1919 /* Then recognize it and use the partition offset */
1920 PartitionInfo->RecognizedPartition = TRUE;
1921 StartOffset = Offset.QuadPart;
1922 }
1923
1924 /* Get the starting offset */
1925 PartitionInfo->StartingOffset.QuadPart =
1926 StartOffset +
1927 UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor),
1928 SectorSize);
1929
1930 /* Calculate the number of hidden sectors */
1931 HiddenSectors64.QuadPart = (PartitionInfo->
1932 StartingOffset.QuadPart -
1933 StartOffset) /
1934 SectorSize;
1935 PartitionInfo->HiddenSectors = HiddenSectors64.LowPart;
1936
1937 /* Get the partition length */
1938 PartitionInfo->PartitionLength.QuadPart =
1939 UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor),
1940 SectorSize);
1941
1942 /* Get the partition number */
1943 /* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
1944 PartitionInfo->PartitionNumber = (!IsContainerPartition(PartitionType)) ? i + 1 : 0;
1945 }
1946 else
1947 {
1948 /* Otherwise, clear all the relevant fields */
1949 PartitionInfo->BootIndicator = FALSE;
1950 PartitionInfo->RecognizedPartition = FALSE;
1951 PartitionInfo->StartingOffset.QuadPart = 0;
1952 PartitionInfo->PartitionLength.QuadPart = 0;
1953 PartitionInfo->HiddenSectors = 0;
1954
1955 /* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
1956 PartitionInfo->PartitionNumber = 0;
1957 }
1958 }
1959
1960 /* Finish debug log, and check for failure */
1961 DPRINT("\n");
1962 if (!NT_SUCCESS(Status)) break;
1963
1964 /* Also check if we hit an invalid entry here */
1965 if (!IsValid)
1966 {
1967 /* We did, so break out of the loop minus one entry */
1968 j--;
1969 break;
1970 }
1971
1972 /* Reset the offset */
1973 Offset.QuadPart = 0;
1974
1975 /* Go back to the descriptor array and loop it */
1976 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
1977 for (Entry = 1; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
1978 {
1979 /* Check if this is a container partition, since we skipped them */
1980 if (IsContainerPartition(PartitionDescriptor->PartitionType))
1981 {
1982 /* Get its offset */
1983 Offset.QuadPart = VolumeOffset.QuadPart +
1985 GET_STARTING_SECTOR(PartitionDescriptor),
1986 SectorSize);
1987
1988 /* If this is a primary partition, this is the volume offset */
1989 if (IsPrimary) VolumeOffset = Offset;
1990
1991 /* Also update the maximum sector */
1992 MaxSector = GET_PARTITION_LENGTH(PartitionDescriptor);
1993 DPRINT1("FSTUB: MaxSector now = %I64d\n", MaxSector);
1994 break;
1995 }
1996 }
1997
1998 /* Loop the next partitions, which are not primary anymore */
1999 IsPrimary = FALSE;
2000 } while (Offset.HighPart | Offset.LowPart);
2001
2002 /* Check if this is a removable device that's probably a super-floppy */
2003 if ((DiskGeometryEx.Geometry.MediaType == RemovableMedia) &&
2004 (j == 0) && (MbrFound) && (IsEmpty))
2005 {
2006 PBOOT_SECTOR_INFO BootSectorInfo = (PBOOT_SECTOR_INFO)Buffer;
2007
2008 /* Read the jump bytes to detect super-floppy */
2009 if ((BootSectorInfo->JumpByte[0] == 0xeb) ||
2010 (BootSectorInfo->JumpByte[0] == 0xe9))
2011 {
2012 /* Super floppes don't have typical MBRs, so skip them */
2013 DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
2014 "table - disk is a super floppy and has no valid MBR\n",
2015 BootSectorInfo->JumpByte);
2016 j = -1;
2017 }
2018 }
2019
2020 /* Check if we're still at partition -1 */
2021 if (j == -1)
2022 {
2023 /* The likely cause is the super floppy detection above */
2024 if ((MbrFound) || (DiskGeometryEx.Geometry.MediaType == RemovableMedia))
2025 {
2026 /* Print out debugging information */
2027 DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
2028 "super-floppy\n",
2029 DeviceObject);
2030 DPRINT1("FSTUB: Drive has %I64d sectors and is %#016I64x "
2031 "bytes large\n",
2032 EndSector, DiskGeometryEx.DiskSize);
2033
2034 /* We should at least have some sectors */
2035 if (EndSector > 0)
2036 {
2037 /* Get the entry we'll use */
2038 PartitionInfo = &(*PartitionBuffer)->PartitionEntry[0];
2039
2040 /* Fill it out with data for a super-floppy */
2041 PartitionInfo->RewritePartition = FALSE;
2042 PartitionInfo->RecognizedPartition = TRUE;
2043 PartitionInfo->PartitionType = PARTITION_FAT_16;
2044 PartitionInfo->BootIndicator = FALSE;
2045 PartitionInfo->HiddenSectors = 0;
2046 PartitionInfo->StartingOffset.QuadPart = 0;
2047 PartitionInfo->PartitionLength = DiskGeometryEx.DiskSize;
2048
2049 /* FIXME: REACTOS HACK -- Needed for xHalIoAssignDriveLetters() */
2050 PartitionInfo->PartitionNumber = 0;
2051
2052 /* Set the signature and set the count back to 0 */
2053 (*PartitionBuffer)->Signature = 1;
2054 i = 0;
2055 }
2056 }
2057 else
2058 {
2059 /* Otherwise, this isn't a super floppy, so set an invalid count */
2060 i = -1;
2061 }
2062 }
2063
2064 /* Set the partition count */
2065 (*PartitionBuffer)->PartitionCount = ++i;
2066
2067 /* If we have no count, delete the signature */
2068 if (!i) (*PartitionBuffer)->Signature = 0;
2069
2070 /* Free the buffer and check for success */
2072 if (!NT_SUCCESS(Status))
2073 {
2076 }
2077
2078 /* Return status */
2079 return Status;
2080}
2081
2088{
2089 PIRP Irp;
2090 KEVENT Event;
2093 LARGE_INTEGER Offset, VolumeOffset;
2094 PUCHAR Buffer = NULL;
2096 ULONG i = 0;
2097 ULONG Entry;
2098 PPARTITION_DESCRIPTOR PartitionDescriptor;
2099 BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE;
2100 PVOID MbrBuffer;
2102
2103 PAGED_CODE();
2104
2105 VolumeOffset.QuadPart = Offset.QuadPart = 0;
2106
2107 /* Normalize the buffer size */
2108 BufferSize = max(512, SectorSize);
2109
2110 /* Check for EZ-Drive */
2112 if (MbrBuffer)
2113 {
2114 /* EZ-Drive found, bias the offset */
2115 IsEzDrive = TRUE;
2117 Offset.QuadPart = 512;
2118 }
2119
2120 /* Allocate our partition buffer */
2123
2124 /* Initialize the event we'll use and loop partitions */
2126 do
2127 {
2128 /* Reset the event since we reuse it */
2130
2131 /* Build the read IRP */
2134 Buffer,
2135 BufferSize,
2136 &Offset,
2137 &Event,
2138 &IoStatusBlock);
2139 if (!Irp)
2140 {
2141 /* Fail */
2143 break;
2144 }
2145
2146 /* Make sure to disable volume verification */
2149
2150 /* Call the driver */
2152 if (Status == STATUS_PENDING)
2153 {
2154 /* Wait for completion */
2157 }
2158
2159 /* Check for failure */
2160 if (!NT_SUCCESS(Status)) break;
2161
2162 /* If we biased for EZ-Drive, unbias now */
2163 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2164
2165 /* Make sure this is a valid MBR */
2167 {
2168 /* It's not, fail */
2170 break;
2171 }
2172
2173 /* Get the partition descriptors and loop them */
2174 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
2175 for (Entry = 1; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
2176 {
2177 /* Check if it's unused or a container partition */
2178 if ((PartitionDescriptor->PartitionType == PARTITION_ENTRY_UNUSED) ||
2179 (IsContainerPartition(PartitionDescriptor->PartitionType)))
2180 {
2181 /* Go to the next one */
2182 continue;
2183 }
2184
2185 /* It's a valid partition, so increase the partition count */
2186 if (++i == PartitionNumber)
2187 {
2188 /* We found a match, set the type */
2189 PartitionDescriptor->PartitionType = (UCHAR)PartitionType;
2190
2191 /* Reset the reusable event */
2193
2194 /* Build the write IRP */
2197 Buffer,
2198 BufferSize,
2199 &Offset,
2200 &Event,
2201 &IoStatusBlock);
2202 if (!Irp)
2203 {
2204 /* Fail */
2206 break;
2207 }
2208
2209 /* Disable volume verification */
2212
2213 /* Call the driver */
2215 if (Status == STATUS_PENDING)
2216 {
2217 /* Wait for completion */
2219 Executive,
2220 KernelMode,
2221 FALSE,
2222 NULL);
2224 }
2225
2226 /* We're done, break out of the loop */
2227 break;
2228 }
2229 }
2230
2231 /* If we looped all the partitions, break out */
2232 if (Entry <= NUM_PARTITION_TABLE_ENTRIES) break;
2233
2234 /* Nothing found yet, get the partition array again */
2235 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Buffer[PARTITION_TABLE_OFFSET];
2236 for (Entry = 1; Entry <= NUM_PARTITION_TABLE_ENTRIES; Entry++, PartitionDescriptor++)
2237 {
2238 /* Check if this was a container partition (we skipped these) */
2239 if (IsContainerPartition(PartitionDescriptor->PartitionType))
2240 {
2241 /* Update the partition offset */
2242 Offset.QuadPart = VolumeOffset.QuadPart +
2243 GET_STARTING_SECTOR(PartitionDescriptor) *
2244 SectorSize;
2245
2246 /* If this was the primary partition, update the volume too */
2247 if (IsPrimary) VolumeOffset = Offset;
2248 break;
2249 }
2250 }
2251
2252 /* Check if we already searched all the partitions */
2254 {
2255 /* Then we failed to find a good MBR */
2257 break;
2258 }
2259
2260 /* Loop the next partitions, which are not primary anymore */
2261 IsPrimary = FALSE;
2262 } while (i < PartitionNumber);
2263
2264 /* Everything done, cleanup */
2266 return Status;
2267}
2268
2276{
2277 KEVENT Event;
2279 PIRP Irp;
2282 PUCHAR Buffer;
2283 PPTE Entry;
2284 PPARTITION_TABLE PartitionTable;
2285 LARGE_INTEGER Offset, NextOffset, ExtendedOffset, SectorOffset;
2286 LARGE_INTEGER StartOffset, PartitionLength;
2287 ULONG i, j;
2288 CCHAR k;
2289 BOOLEAN IsEzDrive = FALSE, IsSuperFloppy = FALSE, DoRewrite = FALSE, IsMbr;
2290 ULONG ConventionalCylinders;
2291 LONGLONG DiskSize;
2293 PVOID MbrBuffer;
2298
2299 PAGED_CODE();
2300
2301 ExtendedOffset.QuadPart = NextOffset.QuadPart = Offset.QuadPart = 0;
2302
2303 /* Normalize the buffer size */
2304 BufferSize = max(512, SectorSize);
2305
2306 /* Get the partial drive geometry */
2307 xHalGetPartialGeometry(DeviceObject, &ConventionalCylinders, &DiskSize);
2308
2309 /* Check for EZ-Drive */
2311 if (MbrBuffer)
2312 {
2313 /* EZ-Drive found, bias the offset */
2314 IsEzDrive = TRUE;
2316 Offset.QuadPart = 512;
2317 }
2318
2319 /* Get the number of bits to shift to multiply by the sector size */
2320 for (k = 0; k < 32; k++) if ((SectorSize >> k) == 1) break;
2321
2322 /* Check if there's only one partition */
2323 if (PartitionBuffer->PartitionCount == 1)
2324 {
2325 /* Check if it has no starting offset or hidden sectors */
2326 if (!(PartitionInfo->StartingOffset.QuadPart) &&
2327 !(PartitionInfo->HiddenSectors))
2328 {
2329 /* Then it's a super floppy */
2331
2332 /* Which also means it must be non-bootable FAT-16 */
2333 if ((PartitionInfo->PartitionNumber) ||
2334 (PartitionInfo->PartitionType != PARTITION_FAT_16) ||
2335 (PartitionInfo->BootIndicator))
2336 {
2337 /* It's not, so we fail */
2339 }
2340
2341 /* Check if it needs a rewrite, and disable EZ-Drive for sure */
2342 if (PartitionInfo->RewritePartition) DoRewrite = TRUE;
2343 IsEzDrive = FALSE;
2344 }
2345 }
2346
2347 /* Count the number of partition tables */
2349
2350 /* Allocate our partition buffer */
2353
2354 /* Loop the entries */
2356 for (i = 0; i < DiskLayout->TableCount; i++)
2357 {
2358 /* Set if this is the MBR partition */
2359 IsMbr= (BOOLEAN)!i;
2360
2361 /* Initialize th event */
2363
2364 /* Build the read IRP */
2367 Buffer,
2368 BufferSize,
2369 &Offset,
2370 &Event,
2371 &IoStatusBlock);
2372 if (!Irp)
2373 {
2374 /* Fail */
2376 break;
2377 }
2378
2379 /* Make sure to disable volume verification */
2382
2383 /* Call the driver */
2385 if (Status == STATUS_PENDING)
2386 {
2387 /* Wait for completion */
2390 }
2391
2392 /* Check for failure */
2393 if (!NT_SUCCESS(Status)) break;
2394
2395 /* If we biased for EZ-Drive, unbias now */
2396 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2397
2398 /* Check if this is a normal disk */
2399 if (!IsSuperFloppy)
2400 {
2401 /* Set the boot record signature */
2403
2404 /* By default, don't require a rewrite */
2405 DoRewrite = FALSE;
2406
2407 /* Check if we don't have an offset */
2408 if (!Offset.QuadPart)
2409 {
2410 /* Check if the signature doesn't match */
2412 {
2413 /* Then write the signature and now we need a rewrite */
2415 DoRewrite = TRUE;
2416 }
2417 }
2418
2419 /* Loop the partition table entries */
2420 PartitionTable = &DiskLayout->PartitionTable[i];
2421 for (j = 0; j < NUM_PARTITION_TABLE_ENTRIES; j++)
2422 {
2423 /* Get the current entry and type */
2424 TableEntry = &PartitionTable->PartitionEntry[j];
2425 PartitionType = TableEntry->PartitionType;
2426
2427 /* Check if the entry needs a rewrite */
2428 if (TableEntry->RewritePartition)
2429 {
2430 /* Then we need one too */
2431 DoRewrite = TRUE;
2432
2433 /* Save the type and if it's a bootable partition */
2434 Entry[j].PartitionType = TableEntry->PartitionType;
2435 Entry[j].ActiveFlag = TableEntry->BootIndicator ? 0x80 : 0;
2436
2437 /* Make sure it's used */
2439 {
2440 /* Make sure it's not a container (unless primary) */
2441 if ((IsMbr) || !(IsContainerPartition(PartitionType)))
2442 {
2443 /* Use the partition offset */
2444 StartOffset.QuadPart = Offset.QuadPart;
2445 }
2446 else
2447 {
2448 /* Use the extended logical partition offset */
2449 StartOffset.QuadPart = ExtendedOffset.QuadPart;
2450 }
2451
2452 /* Set the sector offset */
2453 SectorOffset.QuadPart = TableEntry->
2454 StartingOffset.QuadPart -
2455 StartOffset.QuadPart;
2456
2457 /* Now calculate the starting sector */
2458 StartOffset.QuadPart = SectorOffset.QuadPart >> k;
2459 Entry[j].StartingSector = StartOffset.LowPart;
2460
2461 /* As well as the length */
2462 PartitionLength.QuadPart = TableEntry->PartitionLength.
2463 QuadPart >> k;
2464 Entry[j].PartitionLength = PartitionLength.LowPart;
2465
2466 /* Calculate the CHS values */
2467 HalpCalculateChsValues(&TableEntry->StartingOffset,
2468 &TableEntry->PartitionLength,
2469 k,
2472 ConventionalCylinders,
2474 &Entry[j]);
2475 }
2476 else
2477 {
2478 /* Otherwise set up an empty entry */
2479 Entry[j].StartingSector = 0;
2480 Entry[j].PartitionLength = 0;
2481 Entry[j].StartingTrack = 0;
2482 Entry[j].EndingTrack = 0;
2483 Entry[j].StartingCylinder = 0;
2484 Entry[j].EndingCylinder = 0;
2485 }
2486 }
2487
2488 /* Check if this is a container partition */
2490 {
2491 /* Then update the offset to use */
2492 NextOffset = TableEntry->StartingOffset;
2493 }
2494 }
2495 }
2496
2497 /* Check if we need to write back the buffer */
2498 if (DoRewrite)
2499 {
2500 /* We don't need to do this again */
2501 DoRewrite = FALSE;
2502
2503 /* Initialize the event */
2505
2506 /* If we unbiased for EZ-Drive, rebias now */
2507 if (IsEzDrive && !Offset.QuadPart) Offset.QuadPart = 512;
2508
2509 /* Build the write IRP */
2512 Buffer,
2513 BufferSize,
2514 &Offset,
2515 &Event,
2516 &IoStatusBlock);
2517 if (!Irp)
2518 {
2519 /* Fail */
2521 break;
2522 }
2523
2524 /* Make sure to disable volume verification */
2527
2528 /* Call the driver */
2530 if (Status == STATUS_PENDING)
2531 {
2532 /* Wait for completion */
2534 Executive,
2535 KernelMode,
2536 FALSE,
2537 NULL);
2539 }
2540
2541 /* Check for failure */
2542 if (!NT_SUCCESS(Status)) break;
2543
2544 /* If we biased for EZ-Drive, unbias now */
2545 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2546 }
2547
2548 /* Update the partition offset and set the extended offset if needed */
2549 Offset = NextOffset;
2550 if (IsMbr) ExtendedOffset = NextOffset;
2551 }
2552
2553 /* If we had a buffer, free it, then return status */
2555 return Status;
2556}
2557
2558/* PUBLIC FUNCTIONS **********************************************************/
2559
2560/*
2561 * @implemented
2562 */
2563VOID
2567 IN ULONG MbrTypeIdentifier,
2568 OUT PVOID *MbrBuffer)
2569{
2570 HALDISPATCH->HalExamineMBR(DeviceObject,
2571 SectorSize,
2572 MbrTypeIdentifier,
2573 MbrBuffer);
2574}
2575
2576/*
2577 * @implemented
2578 */
2585{
2586 return HALDISPATCH->HalIoReadPartitionTable(DeviceObject,
2587 SectorSize,
2590}
2591
2592/*
2593 * @implemented
2594 */
2601{
2602 return HALDISPATCH->HalIoSetPartitionInformation(DeviceObject,
2603 SectorSize,
2606}
2607
2608/*
2609 * @implemented
2610 */
2618{
2619 return HALDISPATCH->HalIoWritePartitionTable(DeviceObject,
2620 SectorSize,
2624}
2625
2626/*
2627 * @implemented
2628 */
2629VOID
2632 IN PSTRING NtDeviceName,
2633 OUT PUCHAR NtSystemPath,
2634 OUT PSTRING NtSystemPathString)
2635{
2636 HALDISPATCH->HalIoAssignDriveLetters(LoaderBlock,
2637 NtDeviceName,
2638 NtSystemPath,
2639 NtSystemPathString);
2640}
2641
2642/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
unsigned int * PUINT32
Definition: basetsd.h:119
unsigned short * PUINT16
Definition: basetsd.h:186
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_NO_MEMORY
Definition: d3dkmdt.h:51
#define BufferSize
Definition: mmc.h:75
static NTSTATUS HalpQueryDriveLayout(_In_ PUNICODE_STRING DeviceName, _Outptr_ PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
Definition: disksup.c:46
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:2631
NTSTATUS FASTCALL xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: disksup.c:1654
enum _PARTITION_TYPE * PPARTITION_TYPE
static VOID HalpEnableAutomaticDriveLetterAssignment(VOID)
Definition: disksup.c:835
static VOID 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:1366
_DISK_MANAGER
Definition: disksup.c:24
@ EZ_Drive
Definition: disksup.c:27
@ NoDiskManager
Definition: disksup.c:25
@ OntrackDiskManager
Definition: disksup.c:26
VOID FASTCALL xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PSTRING NtDeviceName, OUT PUCHAR NtSystemPath, OUT PSTRING NtSystemPathString)
Definition: disksup.c:890
static PULONG IopComputeHarddiskDerangements(_In_ ULONG DiskCount)
Definition: disksup.c:309
static BOOLEAN HalpIsValidPartitionEntry(_In_ PPARTITION_DESCRIPTOR Entry, _In_ ULONGLONG MaxOffset, _In_ ULONGLONG MaxSector)
Definition: disksup.c:1323
VOID FASTCALL xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject, IN PULONG ConventionalCylinders, IN PLONGLONG DiskSize)
Definition: disksup.c:1443
NTSTATUS FASTCALL IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: disksup.c:2613
VOID NTAPI FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor, IN ULONGLONG MaxOffset)
Definition: disksup.c:1635
VOID FASTCALL xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG MbrTypeIdentifier, OUT PVOID *MbrBuffer)
Definition: disksup.c:1529
static NTSTATUS HalpSetMountLetter(_In_ PUNICODE_STRING DeviceName, _In_ UCHAR DriveLetter)
Definition: disksup.c:518
NTSTATUS FASTCALL xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: disksup.c:2084
static const UNICODE_STRING CdPrefix
Definition: disksup.c:41
#define EFI_PMBR_OSTYPE_EFI
Definition: disksup.c:21
_PARTITION_TYPE
Definition: disksup.c:31
@ UnknownPartition
Definition: disksup.c:36
@ DataPartition
Definition: disksup.c:37
@ PrimaryPartition
Definition: disksup.c:33
@ BootablePartition
Definition: disksup.c:32
@ LogicalPartition
Definition: disksup.c:34
@ FtPartition
Definition: disksup.c:35
enum _DISK_MANAGER DISK_MANAGER
static const UNICODE_STRING FloppyPrefix
Definition: disksup.c:40
static NTSTATUS HalpGetFullGeometry(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PDISK_GEOMETRY_EX Geometry)
Definition: disksup.c:1271
static BOOLEAN HalpIsOldStyleFloppy(_In_ PUNICODE_STRING DeviceName)
Definition: disksup.c:683
static NTSTATUS HalpNextMountLetter(_In_ PUNICODE_STRING DeviceName, _Out_ PUCHAR DriveLetter)
Definition: disksup.c:436
NTSTATUS FASTCALL IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: disksup.c:2597
NTSTATUS FASTCALL IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: disksup.c:2581
static NTSTATUS HalpDeleteMountLetter(_In_ UCHAR DriveLetter)
Definition: disksup.c:743
static NTSTATUS HalpQueryPartitionType(_In_ PUNICODE_STRING DeviceName, _In_opt_ PDRIVE_LAYOUT_INFORMATION LayoutInfo, _Out_ PPARTITION_TYPE PartitionType)
Definition: disksup.c:156
static UCHAR HalpNextDriveLetter(_In_ PUNICODE_STRING DeviceName, _In_ PSTRING NtDeviceName, _Out_ PUCHAR NtSystemPath, _In_ BOOLEAN IsRemovable)
Definition: disksup.c:604
NTSTATUS FASTCALL xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: disksup.c:2271
#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 RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define FILE_SHARE_READ
Definition: compat.h:136
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP char *__cdecl strstr(const char *, const char *)
Definition: string.c:3415
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
#define swprintf
Definition: precomp.h:40
static const WCHAR Cleanup[]
Definition: register.c:80
#define L(x)
Definition: resources.c:13
#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 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 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 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 _Outptr_
Definition: no_sal2.h:262
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#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)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define ANSI_NULL
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:394
#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
@ NotificationEvent
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
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:1446
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1407
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:499
#define STATUS_NO_MEDIA
Definition: ntstatus.h:704
UCHAR PartitionType
Definition: part_brfr.c:23
ULONG SectorCount
Definition: part_brfr.c:22
#define PARTITION_ENTRY_UNUSED
Definition: part_mbr.h:50
#define PARTITION_FAT_16
Definition: part_mbr.h:54
#define HalExamineMBR
Definition: part_xbox.c:325
#define BOOT_RECORD_SIGNATURE
Definition: parttest.c:17
short WCHAR
Definition: pedump.c:58
#define BOOLEAN
Definition: pedump.c:73
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
_strupr
Definition: string.h:453
strcpy
Definition: string.h:131
Entry
Definition: section.c:5210
BOOLEAN IsSuperFloppy(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:602
#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
UCHAR JumpByte[1]
Definition: hal.h:302
DISK_GEOMETRY Geometry
Definition: winioctl.h:530
LARGE_INTEGER DiskSize
Definition: winioctl.h:531
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
#define max(a, b)
Definition: svc.c:63
#define TAG_FSTUB
Definition: tag.h:54
#define TAG_FILE_SYSTEM
Definition: tag.h:64
#define STATUS_PENDING
Definition: telnetd.h:14
#define UL
Definition: tui.h:164
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
char * PSTR
Definition: typedefs.h:51
unsigned char UCHAR
Definition: typedefs.h:53
#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_ PIO_STACK_LOCATION IoStackLocation
Definition: usbdlib.h:265
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3281
_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:288
__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:4306
#define POOL_COLD_ALLOCATION
* PFILE_OBJECT
Definition: iotypes.h:1998
@ Executive
Definition: ketypes.h:467
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ LARGE_INTEGER _Out_opt_ PLARGE_INTEGER Remainder
Definition: rtlfuncs.h:3062
ret QuadPart
Definition: rtlfuncs.h:3106