ReactOS  0.4.14-dev-614-gbfd8a84
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 
19 const 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 
29 typedef struct _REG_DISK_MOUNT_INFO
30 {
34 
35 #include <poppack.h>
36 
37 typedef enum _DISK_MANAGER
38 {
42 } DISK_MANAGER;
43 
44 typedef enum _PARTITION_TYPE
45 {
53 
57  OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
58 {
59  IO_STATUS_BLOCK StatusBlock;
62  KEVENT Event;
63  PIRP Irp;
67  PAGED_CODE();
68 
69  /* Get device pointers */
72  &FileObject,
73  &DeviceObject);
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 */
115  DeviceObject,
116  NULL,
117  0,
118  Buffer,
119  BufferSize,
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,
135  KernelMode,
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 
164 NTSTATUS
166  IN PDRIVE_LAYOUT_INFORMATION LayoutInfo,
168 {
169  USHORT i;
170  PIRP Irp;
171  KEVENT Event;
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 */
205  DeviceObject,
206  NULL,
207  0,
208  &PartitionInfo,
209  sizeof(PartitionInfo),
210  FALSE,
211  &Event,
212  &IoStatusBlock);
213  if (Irp == NULL)
214  {
217  }
218 
220  if (Status == STATUS_PENDING)
221  {
223  Executive,
224  KernelMode,
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 
319 PULONG
321 {
322  PIRP Irp;
323  KEVENT Event;
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 */
364  DeviceObject,
365  NULL,
366  0,
367  &DeviceNumber,
368  sizeof(DeviceNumber),
369  FALSE,
370  &Event,
371  &IoStatusBlock);
372  if (Irp != NULL)
373  {
375  if (Status == STATUS_PENDING)
376  {
378  Executive,
379  KernelMode,
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 
440 NTSTATUS
442  OUT PUCHAR DriveLetter)
443 {
444  PIRP Irp;
445  KEVENT Event;
447  UNICODE_STRING MountMgr;
453 
454  /* To get next mount letter, we need the MountMgr */
455  RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
456  Status = IoGetDeviceObjectPointer(&MountMgr,
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 */
482  DeviceObject,
483  Target,
485  &LetterInfo,
486  sizeof(LetterInfo),
487  FALSE,
488  &Event,
489  &IoStatusBlock);
490  if (Irp == NULL)
491  {
495  }
496 
498  if (Status == STATUS_PENDING)
499  {
501  Executive,
502  KernelMode,
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 
521 NTSTATUS
523  UCHAR DriveLetter)
524 {
525  PIRP Irp;
526  KEVENT Event;
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");
560  Status = IoGetDeviceObjectPointer(&MountMgr,
562  &FileObject,
563  &DeviceObject);
564  if (!NT_SUCCESS(Status))
565  {
567  return Status;
568  }
569 
570  /* Call the MountMgr */
573  DeviceObject,
574  InputBuffer,
576  NULL,
577  0,
578  FALSE,
579  &Event,
580  &IoStatusBlock);
581  if (Irp == NULL)
582  {
586  }
587 
589  if (Status == STATUS_PENDING)
590  {
592  Executive,
593  KernelMode,
594  FALSE,
595  NULL);
597  }
598 
601 
602  /* Return the MountMgr status */
603  return Status;
604 }
605 
606 UCHAR
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 ;-) */
685  if (NT_SUCCESS(IoCreateSymbolicLink(&DosDevice, DeviceName)))
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 
706 BOOLEAN
708 {
709  PIRP Irp;
710  KEVENT Event;
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) */
733  DeviceObject,
734  NULL,
735  0,
736  &DevName,
737  sizeof(DevName),
738  FALSE,
739  &Event,
740  &IoStatusBlock);
741  if (Irp == NULL)
742  {
744  return FALSE;
745  }
746 
748  if (Status == STATUS_PENDING)
749  {
751  Executive,
752  KernelMode,
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 
765 NTSTATUS
767 {
768  PIRP Irp;
769  KEVENT Event;
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");
808  Status = IoGetDeviceObjectPointer(&MountMgr,
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 */
822  DeviceObject,
823  InputBuffer,
825  OutputBuffer,
826  0x1000,
827  FALSE,
828  &Event,
829  &IoStatusBlock);
830  if (Irp == NULL)
831  {
836  }
837 
839  if (Status == STATUS_PENDING)
840  {
842  Executive,
843  KernelMode,
844  FALSE,
845  NULL);
847  }
848 
852 
853  return Status;
854 }
855 
856 VOID
858 {
859  PIRP Irp;
860  KEVENT Event;
862  UNICODE_STRING MountMgr;
866 
867  /* Get the device pointer to the MountMgr */
868  RtlInitUnicodeString(&MountMgr, L"\\Device\\MountPointManager");
869  Status = IoGetDeviceObjectPointer(&MountMgr,
871  &FileObject,
872  &DeviceObject);
873  if (!NT_SUCCESS(Status))
874  {
875  return;
876  }
877 
878  /* Just send an IOCTL to enable the feature */
881  DeviceObject,
882  NULL,
883  0,
884  NULL,
885  0,
886  FALSE,
887  &Event,
888  &IoStatusBlock);
889  if (Irp == NULL)
890  {
891  return;
892  }
893 
895  if (Status == STATUS_PENDING)
896  {
898  Executive,
899  KernelMode,
900  FALSE,
901  NULL);
903  }
904 
906 
907  return;
908 }
909 
910 VOID
911 FASTCALL
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;
930  PCONFIGURATION_INFORMATION ConfigInfo;
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 */
950  if (IoRemoteBootClient)
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 */
1367  HalpDeleteMountLetter('Z');
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 
1387 NTSTATUS
1388 NTAPI
1390  IN PDISK_GEOMETRY Geometry,
1391  OUT PULONGLONG RealSectorCount)
1392 {
1393  PIRP Irp;
1395  PKEVENT Event;
1396  NTSTATUS Status;
1398  PAGED_CODE();
1399 
1400  /* Allocate a non-paged event */
1402  sizeof(KEVENT),
1403  TAG_FILE_SYSTEM);
1404  if (!Event) return STATUS_INSUFFICIENT_RESOURCES;
1405 
1406  /* Initialize it */
1408 
1409  /* Build the IRP */
1411  DeviceObject,
1412  NULL,
1413  0UL,
1414  Geometry,
1415  sizeof(DISK_GEOMETRY),
1416  FALSE,
1417  Event,
1418  &IoStatusBlock);
1419  if (!Irp)
1420  {
1421  /* Fail, free the event */
1424  }
1425 
1426  /* Call the driver and check if it's pending */
1428  if (Status == STATUS_PENDING)
1429  {
1430  /* Wait on the driver */
1433  }
1434 
1435  /* Check if the driver returned success */
1436  if(NT_SUCCESS(Status))
1437  {
1438  /* Build another IRP */
1440  DeviceObject,
1441  NULL,
1442  0UL,
1443  &PartitionInfo,
1444  sizeof(PARTITION_INFORMATION),
1445  FALSE,
1446  Event,
1447  &IoStatusBlock);
1448  if (!Irp)
1449  {
1450  /* Fail, free the event */
1453  }
1454 
1455  /* Reset event */
1457 
1458  /* Call the driver and check if it's pending */
1460  if (Status == STATUS_PENDING)
1461  {
1462  /* Wait on the driver */
1465  }
1466 
1467  /* Check if the driver returned success */
1468  if(NT_SUCCESS(Status))
1469  {
1470  /* Get the number of sectors */
1471  *RealSectorCount = (PartitionInfo.PartitionLength.QuadPart /
1472  Geometry->BytesPerSector);
1473  }
1474  }
1475 
1476  /* Free the event and return the Status */
1478  return Status;
1479 }
1480 
1481 BOOLEAN
1482 NTAPI
1484  IN ULONGLONG MaxOffset,
1485  IN ULONGLONG MaxSector)
1486 {
1487  ULONGLONG EndingSector;
1488  PAGED_CODE();
1489 
1490  /* Unused partitions are considered valid */
1491  if (Entry->PartitionType == PARTITION_ENTRY_UNUSED) return TRUE;
1492 
1493  /* Get the last sector of the partition */
1495 
1496  /* Check if it's more then the maximum sector */
1497  if (EndingSector > MaxSector)
1498  {
1499  /* Invalid partition */
1500  DPRINT1("FSTUB: entry is invalid\n");
1501  DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1502  DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1503  DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1504  DPRINT1("FSTUB: max %#I64x\n", MaxSector);
1505  return FALSE;
1506  }
1507  else if(GET_STARTING_SECTOR(Entry) > MaxOffset)
1508  {
1509  /* Invalid partition */
1510  DPRINT1("FSTUB: entry is invalid\n");
1511  DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1512  DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1513  DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1514  DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset);
1515  return FALSE;
1516  }
1517 
1518  /* It's fine, return success */
1519  return TRUE;
1520 }
1521 
1522 VOID
1523 NTAPI
1525  IN PLARGE_INTEGER PartitionLength,
1526  IN CCHAR ShiftCount,
1528  IN ULONG NumberOfTracks,
1529  IN ULONG ConventionalCylinders,
1530  OUT PPARTITION_DESCRIPTOR PartitionDescriptor)
1531 {
1532  LARGE_INTEGER FirstSector, SectorCount;
1533  ULONG LastSector, Remainder, SectorsPerCylinder;
1534  ULONG StartingCylinder, EndingCylinder;
1535  ULONG StartingTrack, EndingTrack;
1536  ULONG StartingSector, EndingSector;
1537  PAGED_CODE();
1538 
1539  /* Calculate the number of sectors for each cylinder */
1540  SectorsPerCylinder = SectorsPerTrack * NumberOfTracks;
1541 
1542  /* Calculate the first sector, and the sector count */
1543  FirstSector.QuadPart = PartitionOffset->QuadPart >> ShiftCount;
1544  SectorCount.QuadPart = PartitionLength->QuadPart >> ShiftCount;
1545 
1546  /* Now calculate the last sector */
1547  LastSector = FirstSector.LowPart + SectorCount.LowPart - 1;
1548 
1549  /* Calculate the first and last cylinders */
1550  StartingCylinder = FirstSector.LowPart / SectorsPerCylinder;
1551  EndingCylinder = LastSector / SectorsPerCylinder;
1552 
1553  /* Set the default number of cylinders */
1554  if (!ConventionalCylinders) ConventionalCylinders = 1024;
1555 
1556  /* Normalize the values */
1557  if (StartingCylinder >= ConventionalCylinders)
1558  {
1559  /* Set the maximum to 1023 */
1560  StartingCylinder = ConventionalCylinders - 1;
1561  }
1562  if (EndingCylinder >= ConventionalCylinders)
1563  {
1564  /* Set the maximum to 1023 */
1565  EndingCylinder = ConventionalCylinders - 1;
1566  }
1567 
1568  /* Calculate the starting head and sector that still remain */
1569  Remainder = FirstSector.LowPart % SectorsPerCylinder;
1570  StartingTrack = Remainder / SectorsPerTrack;
1571  StartingSector = Remainder % SectorsPerTrack;
1572 
1573  /* Calculate the ending head and sector that still remain */
1574  Remainder = LastSector % SectorsPerCylinder;
1575  EndingTrack = Remainder / SectorsPerTrack;
1576  EndingSector = Remainder % SectorsPerTrack;
1577 
1578  /* Set cylinder data for the MSB */
1579  PartitionDescriptor->StartingCylinderMsb = (UCHAR)StartingCylinder;
1580  PartitionDescriptor->EndingCylinderMsb = (UCHAR)EndingCylinder;
1581 
1582  /* Set the track data */
1583  PartitionDescriptor->StartingTrack = (UCHAR)StartingTrack;
1584  PartitionDescriptor->EndingTrack = (UCHAR)EndingTrack;
1585 
1586  /* Update cylinder data for the LSB */
1587  StartingCylinder = ((StartingSector + 1) & 0x3F) |
1588  ((StartingCylinder >> 2) & 0xC0);
1589  EndingCylinder = ((EndingSector + 1) & 0x3F) |
1590  ((EndingCylinder >> 2) & 0xC0);
1591 
1592  /* Set the cylinder data for the LSB */
1593  PartitionDescriptor->StartingCylinderLsb = (UCHAR)StartingCylinder;
1594  PartitionDescriptor->EndingCylinderLsb = (UCHAR)EndingCylinder;
1595 }
1596 
1597 VOID
1598 FASTCALL
1600  IN PULONG ConventionalCylinders,
1601  IN PLONGLONG DiskSize)
1602 {
1603  PDISK_GEOMETRY DiskGeometry = NULL;
1605  PKEVENT Event = NULL;
1606  PIRP Irp;
1607  NTSTATUS Status;
1608 
1609  /* Set defaults */
1610  *ConventionalCylinders = 0;
1611  *DiskSize = 0;
1612 
1613  /* Allocate the structure in nonpaged pool */
1614  DiskGeometry = ExAllocatePoolWithTag(NonPagedPool,
1615  sizeof(DISK_GEOMETRY),
1616  TAG_FILE_SYSTEM);
1617  if (!DiskGeometry) goto Cleanup;
1618 
1619  /* Allocate the status block in nonpaged pool */
1621  sizeof(IO_STATUS_BLOCK),
1622  TAG_FILE_SYSTEM);
1623  if (!IoStatusBlock) goto Cleanup;
1624 
1625  /* Allocate the event in nonpaged pool too */
1627  sizeof(KEVENT),
1628  TAG_FILE_SYSTEM);
1629  if (!Event) goto Cleanup;
1630 
1631  /* Initialize the event */
1633 
1634  /* Build the IRP */
1636  DeviceObject,
1637  NULL,
1638  0,
1639  DiskGeometry,
1640  sizeof(DISK_GEOMETRY),
1641  FALSE,
1642  Event,
1643  IoStatusBlock);
1644  if (!Irp) goto Cleanup;
1645 
1646  /* Now call the driver */
1648  if (Status == STATUS_PENDING)
1649  {
1650  /* Wait for it to complete */
1653  }
1654 
1655  /* Check driver status */
1656  if (NT_SUCCESS(Status))
1657  {
1658  /* Return the cylinder count */
1659  *ConventionalCylinders = DiskGeometry->Cylinders.LowPart;
1660 
1661  /* Make sure it's not larger then 1024 */
1662  if (DiskGeometry->Cylinders.LowPart >= 1024)
1663  {
1664  /* Otherwise, normalize the value */
1665  *ConventionalCylinders = 1024;
1666  }
1667 
1668  /* Calculate the disk size */
1669  *DiskSize = DiskGeometry->Cylinders.QuadPart *
1670  DiskGeometry->TracksPerCylinder *
1671  DiskGeometry->SectorsPerTrack *
1672  DiskGeometry->BytesPerSector;
1673  }
1674 
1675 Cleanup:
1676  /* Free all the pointers */
1679  if (DiskGeometry) ExFreePoolWithTag(DiskGeometry, TAG_FILE_SYSTEM);
1680  return;
1681 }
1682 
1683 VOID
1684 FASTCALL
1687  IN ULONG MbrTypeIdentifier,
1688  OUT PVOID *MbrBuffer)
1689 {
1691  PUCHAR Buffer;
1692  ULONG BufferSize;
1693  KEVENT Event;
1695  PIRP Irp;
1696  PPARTITION_DESCRIPTOR PartitionDescriptor;
1697  NTSTATUS Status;
1698  PIO_STACK_LOCATION IoStackLocation;
1699  Offset.QuadPart = 0;
1700 
1701  /* Assume failure */
1702  *MbrBuffer = NULL;
1703 
1704  /* Normalize the buffer size */
1705  BufferSize = max(SectorSize, 512);
1706 
1707  /* Allocate the buffer */
1709  PAGE_SIZE > BufferSize ?
1711  TAG_FILE_SYSTEM);
1712  if (!Buffer) return;
1713 
1714  /* Initialize the Event */
1716 
1717  /* Build the IRP */
1719  DeviceObject,
1720  Buffer,
1721  BufferSize,
1722  &Offset,
1723  &Event,
1724  &IoStatusBlock);
1725  if (!Irp)
1726  {
1727  /* Failed */
1729  return;
1730  }
1731 
1732  /* Make sure to override volume verification */
1733  IoStackLocation = IoGetNextIrpStackLocation(Irp);
1734  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1735 
1736  /* Call the driver */
1738  if (Status == STATUS_PENDING)
1739  {
1740  /* Wait for completion */
1743  }
1744 
1745  /* Check driver Status */
1746  if (NT_SUCCESS(Status))
1747  {
1748  /* Validate the MBR Signature */
1750  {
1751  /* Failed */
1753  return;
1754  }
1755 
1756  /* Get the partition entry */
1757  PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1759 
1760  /* Make sure it's what the caller wanted */
1761  if (PartitionDescriptor->PartitionType != MbrTypeIdentifier)
1762  {
1763  /* It's not, free our buffer */
1765  }
1766  else
1767  {
1768  /* Check if this is a secondary entry */
1769  if (PartitionDescriptor->PartitionType == 0x54)
1770  {
1771  /* Return our buffer, but at sector 63 */
1772  *(PULONG)Buffer = 63;
1773  *MbrBuffer = Buffer;
1774  }
1775  else if (PartitionDescriptor->PartitionType == 0x55)
1776  {
1777  /* EZ Drive, return the buffer directly */
1778  *MbrBuffer = Buffer;
1779  }
1780  else
1781  {
1782  /* Otherwise crash on debug builds */
1783  ASSERT(PartitionDescriptor->PartitionType == 0x55);
1784  }
1785  }
1786  }
1787 }
1788 
1789 VOID
1790 NTAPI
1792  IN ULONGLONG MaxOffset)
1793 {
1794  ULONG PartitionMaxOffset, PartitionLength;
1795  PAGED_CODE();
1796 
1797  /* Compute partition length (according to MBR entry) */
1798  PartitionMaxOffset = GET_STARTING_SECTOR(PartitionDescriptor) + GET_PARTITION_LENGTH(PartitionDescriptor);
1799  /* In case the partition length goes beyond disk size... */
1800  if (PartitionMaxOffset > MaxOffset)
1801  {
1802  /* Resize partition to its maximum real length */
1803  PartitionLength = (ULONG)(PartitionMaxOffset - GET_STARTING_SECTOR(PartitionDescriptor));
1804  SET_PARTITION_LENGTH(PartitionDescriptor, PartitionLength);
1805  }
1806 }
1807 
1808 NTSTATUS
1809 FASTCALL
1814 {
1815  KEVENT Event;
1817  PIRP Irp;
1818  PPARTITION_DESCRIPTOR PartitionDescriptor;
1819  CCHAR Entry;
1820  NTSTATUS Status;
1822  PUCHAR Buffer = NULL;
1823  ULONG BufferSize = 2048, InputSize;
1824  PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo = NULL;
1825  LONG j = -1, i = -1, k;
1826  DISK_GEOMETRY DiskGeometry;
1827  LONGLONG EndSector, MaxSector, StartOffset;
1828  ULONGLONG MaxOffset;
1829  LARGE_INTEGER Offset, VolumeOffset;
1830  BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE, MbrFound = FALSE;
1831  BOOLEAN IsValid, IsEmpty = TRUE;
1832  PVOID MbrBuffer;
1833  PIO_STACK_LOCATION IoStackLocation;
1835  LARGE_INTEGER HiddenSectors64;
1836  VolumeOffset.QuadPart = Offset.QuadPart = 0;
1837  PAGED_CODE();
1838 
1839  /* Allocate the buffer */
1841  BufferSize,
1842  TAG_FILE_SYSTEM);
1844 
1845  /* Normalize the buffer size */
1846  InputSize = max(512, SectorSize);
1847 
1848  /* Check for EZ Drive */
1849  HalExamineMBR(DeviceObject, InputSize, 0x55, &MbrBuffer);
1850  if (MbrBuffer)
1851  {
1852  /* EZ Drive found, bias the offset */
1853  IsEzDrive = TRUE;
1854  ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
1855  Offset.QuadPart = 512;
1856  }
1857 
1858  /* Get drive geometry */
1859  Status = HalpGetFullGeometry(DeviceObject, &DiskGeometry, &MaxOffset);
1860  if (!NT_SUCCESS(Status))
1861  {
1863  *PartitionBuffer = NULL;
1864  return Status;
1865  }
1866 
1867  /* Get the end and maximum sector */
1868  EndSector = MaxOffset;
1869  MaxSector = MaxOffset << 1;
1870  DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n",
1871  MaxOffset, MaxSector);
1872 
1873  /* Allocate our buffer */
1875  if (!Buffer)
1876  {
1877  /* Fail, free the input buffer */
1879  *PartitionBuffer = NULL;
1881  }
1882 
1883  /* Start partition loop */
1884  do
1885  {
1886  /* Assume the partition is valid */
1887  IsValid = TRUE;
1888 
1889  /* Initialize the event */
1891 
1892  /* Clear the buffer and build the IRP */
1893  RtlZeroMemory(Buffer, InputSize);
1895  DeviceObject,
1896  Buffer,
1897  InputSize,
1898  &Offset,
1899  &Event,
1900  &IoStatusBlock);
1901  if (!Irp)
1902  {
1903  /* Failed */
1905  break;
1906  }
1907 
1908  /* Make sure to disable volume verification */
1909  IoStackLocation = IoGetNextIrpStackLocation(Irp);
1910  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1911 
1912  /* Call the driver */
1914  if (Status == STATUS_PENDING)
1915  {
1916  /* Wait for completion */
1919  }
1920 
1921  /* Normalize status code and check for failure */
1923  if (!NT_SUCCESS(Status)) break;
1924 
1925  /* If we biased for EZ-Drive, unbias now */
1926  if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
1927 
1928  /* Make sure this is a valid MBR */
1930  {
1931  /* It's not, fail */
1932  DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1933  "partition table %d\n", j + 1);
1934  break;
1935  }
1936 
1937  /* At this point we have a valid MBR */
1938  MbrFound = TRUE;
1939 
1940  /* Check if we weren't given an offset */
1941  if (!Offset.QuadPart)
1942  {
1943  /* Then read the signature off the disk */
1944  (*PartitionBuffer)->Signature = ((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1];
1945  }
1946 
1947  /* Get the partition descriptor array */
1948  PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1950 
1951  /* Start looping partitions */
1952  j++;
1953  DPRINT("FSTUB: Partition Table %d:\n", j);
1954  for (Entry = 1, k = 0; Entry <= 4; Entry++, PartitionDescriptor++)
1955  {
1956  /* Get the partition type */
1957  PartitionType = PartitionDescriptor->PartitionType;
1958 
1959  /* Print debug messages */
1960  DPRINT("Partition Entry %d,%d: type %#x %s\n",
1961  j,
1962  Entry,
1963  PartitionType,
1964  (PartitionDescriptor->ActiveFlag) ? "Active" : "");
1965  DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1966  GET_STARTING_SECTOR(PartitionDescriptor),
1967  GET_PARTITION_LENGTH(PartitionDescriptor));
1968 
1969  /* Check whether we're facing a protective MBR */
1971  {
1972  /* Partition length might be bigger than disk size */
1973  FstubFixupEfiPartition(PartitionDescriptor,
1974  MaxOffset);
1975  }
1976 
1977  /* Make sure that the partition is valid, unless it's the first */
1978  if (!(HalpIsValidPartitionEntry(PartitionDescriptor,
1979  MaxOffset,
1980  MaxSector)) && (j == 0))
1981  {
1982  /* It's invalid, so fail */
1983  IsValid = FALSE;
1984  break;
1985  }
1986 
1987  /* Check if it's a container */
1989  {
1990  /* Increase the count of containers */
1991  if (++k != 1)
1992  {
1993  /* More then one table is invalid */
1994  DPRINT1("FSTUB: Multiple container partitions found in "
1995  "partition table %d\n - table is invalid\n",
1996  j);
1997  IsValid = FALSE;
1998  break;
1999  }
2000  }
2001 
2002  /* Check if the partition is supposedly empty */
2003  if (IsEmpty)
2004  {
2005  /* But check if it actually has a start and/or length */
2006  if ((GET_STARTING_SECTOR(PartitionDescriptor)) ||
2007  (GET_PARTITION_LENGTH(PartitionDescriptor)))
2008  {
2009  /* So then it's not really empty */
2010  IsEmpty = FALSE;
2011  }
2012  }
2013 
2014  /* Check if the caller wanted only recognized partitions */
2016  {
2017  /* Then check if this one is unused, or a container */
2020  {
2021  /* Skip it, since the caller doesn't want it */
2022  continue;
2023  }
2024  }
2025 
2026  /* Increase the structure count and check if they can fit */
2027  if ((sizeof(DRIVE_LAYOUT_INFORMATION) +
2028  (++i * sizeof(PARTITION_INFORMATION))) >
2029  BufferSize)
2030  {
2031  /* Allocate a new buffer that's twice as big */
2032  DriveLayoutInfo = ExAllocatePoolWithTag(NonPagedPool,
2033  BufferSize << 1,
2034  TAG_FILE_SYSTEM);
2035  if (!DriveLayoutInfo)
2036  {
2037  /* Out of memory, unto this extra structure */
2038  --i;
2040  break;
2041  }
2042 
2043  /* Copy the contents of the old buffer */
2044  RtlMoveMemory(DriveLayoutInfo,
2045  *PartitionBuffer,
2046  BufferSize);
2047 
2048  /* Free the old buffer and set this one as the new one */
2050  *PartitionBuffer = DriveLayoutInfo;
2051 
2052  /* Double the size */
2053  BufferSize <<= 1;
2054  }
2055 
2056  /* Now get the current structure being filled and initialize it */
2057  PartitionInfo = &(*PartitionBuffer)->PartitionEntry[i];
2058  PartitionInfo->PartitionType = PartitionType;
2059  PartitionInfo->RewritePartition = FALSE;
2060 
2061  /* Check if we're dealing with a partition that's in use */
2063  {
2064  /* Check if it's bootable */
2065  PartitionInfo->BootIndicator = PartitionDescriptor->
2066  ActiveFlag & 0x80 ?
2067  TRUE : FALSE;
2068 
2069  /* Check if its' a container */
2071  {
2072  /* Then don't recognize it and use the volume offset */
2073  PartitionInfo->RecognizedPartition = FALSE;
2074  StartOffset = VolumeOffset.QuadPart;
2075  }
2076  else
2077  {
2078  /* Then recognize it and use the partition offset */
2079  PartitionInfo->RecognizedPartition = TRUE;
2080  StartOffset = Offset.QuadPart;
2081  }
2082 
2083  /* Get the starting offset */
2084  PartitionInfo->StartingOffset.QuadPart =
2085  StartOffset +
2086  UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor),
2087  SectorSize);
2088 
2089  /* Calculate the number of hidden sectors */
2090  HiddenSectors64.QuadPart = (PartitionInfo->
2091  StartingOffset.QuadPart -
2092  StartOffset) /
2093  SectorSize;
2094  PartitionInfo->HiddenSectors = HiddenSectors64.LowPart;
2095 
2096  /* Get the partition length */
2097  PartitionInfo->PartitionLength.QuadPart =
2098  UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor),
2099  SectorSize);
2100 
2101  /* Get the partition number */
2102  PartitionInfo->PartitionNumber = (!IsContainerPartition(PartitionType)) ? i + 1 : 0;
2103  }
2104  else
2105  {
2106  /* Otherwise, clear all the relevant fields */
2107  PartitionInfo->BootIndicator = FALSE;
2108  PartitionInfo->RecognizedPartition = FALSE;
2109  PartitionInfo->StartingOffset.QuadPart = 0;
2110  PartitionInfo->PartitionLength.QuadPart = 0;
2111  PartitionInfo->HiddenSectors = 0;
2112 
2113  PartitionInfo->PartitionNumber = 0;
2114  }
2115  }
2116 
2117  /* Finish debug log, and check for failure */
2118  DPRINT("\n");
2119  if (!NT_SUCCESS(Status)) break;
2120 
2121  /* Also check if we hit an invalid entry here */
2122  if (!IsValid)
2123  {
2124  /* We did, so break out of the loop minus one entry */
2125  j--;
2126  break;
2127  }
2128 
2129  /* Reset the offset */
2130  Offset.QuadPart = 0;
2131 
2132  /* Go back to the descriptor array and loop it */
2133  PartitionDescriptor = (PPARTITION_DESCRIPTOR)
2135  for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++)
2136  {
2137  /* Check if this is a container partition, since we skipped them */
2138  if (IsContainerPartition(PartitionDescriptor->PartitionType))
2139  {
2140  /* Get its offset */
2141  Offset.QuadPart = VolumeOffset.QuadPart +
2142  UInt32x32To64(
2143  GET_STARTING_SECTOR(PartitionDescriptor),
2144  SectorSize);
2145 
2146  /* If this is a primary partition, this is the volume offset */
2147  if (IsPrimary) VolumeOffset = Offset;
2148 
2149  /* Also update the maximum sector */
2150  MaxSector = GET_PARTITION_LENGTH(PartitionDescriptor);
2151  DPRINT1("FSTUB: MaxSector now = %I64d\n", MaxSector);
2152  break;
2153  }
2154  }
2155 
2156  /* Loop the next partitions, which are not primary anymore */
2157  IsPrimary = FALSE;
2158  } while (Offset.HighPart | Offset.LowPart);
2159 
2160  /* Check if this is a removable device that's probably a super-floppy */
2161  if ((DiskGeometry.MediaType == RemovableMedia) &&
2162  (j == 0) && (MbrFound) && (IsEmpty))
2163  {
2164  PBOOT_SECTOR_INFO BootSectorInfo = (PBOOT_SECTOR_INFO)Buffer;
2165 
2166  /* Read the jump bytes to detect super-floppy */
2167  if ((BootSectorInfo->JumpByte[0] == 0xeb) ||
2168  (BootSectorInfo->JumpByte[0] == 0xe9))
2169  {
2170  /* Super floppes don't have typical MBRs, so skip them */
2171  DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
2172  "table - disk is a super floppy and has no valid MBR\n",
2173  BootSectorInfo->JumpByte);
2174  j = -1;
2175  }
2176  }
2177 
2178  /* Check if we're still at partition -1 */
2179  if (j == -1)
2180  {
2181  /* The likely cause is the super floppy detection above */
2182  if ((MbrFound) || (DiskGeometry.MediaType == RemovableMedia))
2183  {
2184  /* Print out debugging information */
2185  DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
2186  "super-floppy\n",
2187  DeviceObject);
2188  DPRINT1("FSTUB: Drive has %I64d sectors and is %#016I64x "
2189  "bytes large\n",
2190  EndSector, EndSector * DiskGeometry.BytesPerSector);
2191 
2192  /* We should at least have some sectors */
2193  if (EndSector > 0)
2194  {
2195  /* Get the entry we'll use */
2196  PartitionInfo = &(*PartitionBuffer)->PartitionEntry[0];
2197 
2198  /* Fill it out with data for a super-floppy */
2199  PartitionInfo->RewritePartition = FALSE;
2200  PartitionInfo->RecognizedPartition = TRUE;
2201  PartitionInfo->PartitionType = PARTITION_FAT_16;
2202  PartitionInfo->BootIndicator = FALSE;
2203  PartitionInfo->HiddenSectors = 0;
2204  PartitionInfo->StartingOffset.QuadPart = 0;
2205  PartitionInfo->PartitionLength.QuadPart = (EndSector *
2206  DiskGeometry.
2207  BytesPerSector);
2208 
2209  /* FIXME: REACTOS HACK */
2210  PartitionInfo->PartitionNumber = 0;
2211 
2212  /* Set the signature and set the count back to 0 */
2213  (*PartitionBuffer)->Signature = 1;
2214  i = 0;
2215  }
2216  }
2217  else
2218  {
2219  /* Otherwise, this isn't a super floppy, so set an invalid count */
2220  i = -1;
2221  }
2222  }
2223 
2224  /* Set the partition count */
2225  (*PartitionBuffer)->PartitionCount = ++i;
2226 
2227  /* If we have no count, delete the signature */
2228  if (!i) (*PartitionBuffer)->Signature = 0;
2229 
2230  /* Free the buffer and check for success */
2232  if (!NT_SUCCESS(Status))
2233  {
2235  *PartitionBuffer = NULL;
2236  }
2237 
2238  /* Return status */
2239  return Status;
2240 }
2241 
2242 NTSTATUS
2243 FASTCALL
2248 {
2249  PIRP Irp;
2250  KEVENT Event;
2252  NTSTATUS Status;
2253  LARGE_INTEGER Offset, VolumeOffset;
2254  PUCHAR Buffer = NULL;
2255  ULONG BufferSize;
2256  ULONG i = 0;
2257  ULONG Entry;
2258  PPARTITION_DESCRIPTOR PartitionDescriptor;
2259  BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE;
2260  PVOID MbrBuffer;
2261  PIO_STACK_LOCATION IoStackLocation;
2262  VolumeOffset.QuadPart = Offset.QuadPart = 0;
2263  PAGED_CODE();
2264 
2265  /* Normalize the buffer size */
2266  BufferSize = max(512, SectorSize);
2267 
2268  /* Check for EZ Drive */
2269  HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer);
2270  if (MbrBuffer)
2271  {
2272  /* EZ Drive found, bias the offset */
2273  IsEzDrive = TRUE;
2274  ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
2275  Offset.QuadPart = 512;
2276  }
2277 
2278  /* Allocate our partition buffer */
2281 
2282  /* Initialize the event we'll use and loop partitions */
2284  do
2285  {
2286  /* Reset the event since we reuse it */
2287  KeClearEvent(&Event);
2288 
2289  /* Build the read IRP */
2291  DeviceObject,
2292  Buffer,
2293  BufferSize,
2294  &Offset,
2295  &Event,
2296  &IoStatusBlock);
2297  if (!Irp)
2298  {
2299  /* Fail */
2301  break;
2302  }
2303 
2304  /* Make sure to disable volume verification */
2305  IoStackLocation = IoGetNextIrpStackLocation(Irp);
2306  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2307 
2308  /* Call the driver */
2310  if (Status == STATUS_PENDING)
2311  {
2312  /* Wait for completion */
2315  }
2316 
2317  /* Check for failure */
2318  if (!NT_SUCCESS(Status)) break;
2319 
2320  /* If we biased for EZ-Drive, unbias now */
2321  if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2322 
2323  /* Make sure this is a valid MBR */
2325  {
2326  /* It's not, fail */
2328  break;
2329  }
2330 
2331  /* Get the partition descriptors and loop them */
2332  PartitionDescriptor = (PPARTITION_DESCRIPTOR)
2334  for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++)
2335  {
2336  /* Check if it's unused or a container partition */
2337  if ((PartitionDescriptor->PartitionType ==
2339  (IsContainerPartition(PartitionDescriptor->PartitionType)))
2340  {
2341  /* Go to the next one */
2342  continue;
2343  }
2344 
2345  /* It's a valid partition, so increase the partition count */
2346  if (++i == PartitionNumber)
2347  {
2348  /* We found a match, set the type */
2349  PartitionDescriptor->PartitionType = (UCHAR)PartitionType;
2350 
2351  /* Reset the reusable event */
2352  KeClearEvent(&Event);
2353 
2354  /* Build the write IRP */
2356  DeviceObject,
2357  Buffer,
2358  BufferSize,
2359  &Offset,
2360  &Event,
2361  &IoStatusBlock);
2362  if (!Irp)
2363  {
2364  /* Fail */
2366  break;
2367  }
2368 
2369  /* Disable volume verification */
2370  IoStackLocation = IoGetNextIrpStackLocation(Irp);
2371  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2372 
2373  /* Call the driver */
2375  if (Status == STATUS_PENDING)
2376  {
2377  /* Wait for completion */
2379  Executive,
2380  KernelMode,
2381  FALSE,
2382  NULL);
2384  }
2385 
2386  /* We're done, break out of the loop */
2387  break;
2388  }
2389  }
2390 
2391  /* If we looped all the partitions, break out */
2392  if (Entry <= NUM_PARTITION_TABLE_ENTRIES) break;
2393 
2394  /* Nothing found yet, get the partition array again */
2395  PartitionDescriptor = (PPARTITION_DESCRIPTOR)
2397  for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++)
2398  {
2399  /* Check if this was a container partition (we skipped these) */
2400  if (IsContainerPartition(PartitionDescriptor->PartitionType))
2401  {
2402  /* Update the partition offset */
2403  Offset.QuadPart = VolumeOffset.QuadPart +
2404  GET_STARTING_SECTOR(PartitionDescriptor) *
2405  SectorSize;
2406 
2407  /* If this was the primary partition, update the volume too */
2408  if (IsPrimary) VolumeOffset = Offset;
2409  break;
2410  }
2411  }
2412 
2413  /* Check if we already searched all the partitions */
2415  {
2416  /* Then we failed to find a good MBR */
2418  break;
2419  }
2420 
2421  /* Loop the next partitions, which are not primary anymore */
2422  IsPrimary = FALSE;
2423  } while (i < PartitionNumber);
2424 
2425  /* Everything done, cleanup */
2427  return Status;
2428 }
2429 
2430 NTSTATUS
2431 FASTCALL
2437 {
2438  KEVENT Event;
2440  PIRP Irp;
2442  ULONG BufferSize;
2443  PUSHORT Buffer;
2444  PPTE Entry;
2445  PPARTITION_TABLE PartitionTable;
2446  LARGE_INTEGER Offset, NextOffset, ExtendedOffset, SectorOffset;
2447  LARGE_INTEGER StartOffset, PartitionLength;
2448  ULONG i, j;
2449  CCHAR k;
2450  BOOLEAN IsEzDrive = FALSE, IsSuperFloppy = FALSE, DoRewrite = FALSE, IsMbr;
2451  ULONG ConventionalCylinders;
2452  LONGLONG DiskSize;
2454  PVOID MbrBuffer;
2456  PIO_STACK_LOCATION IoStackLocation;
2459  ExtendedOffset.QuadPart = NextOffset.QuadPart = Offset.QuadPart = 0;
2460  PAGED_CODE();
2461 
2462  /* Normalize the buffer size */
2463  BufferSize = max(512, SectorSize);
2464 
2465  /* Get the partial drive geometry */
2466  xHalGetPartialGeometry(DeviceObject, &ConventionalCylinders, &DiskSize);
2467 
2468  /* Check for EZ Drive */
2469  HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer);
2470  if (MbrBuffer)
2471  {
2472  /* EZ Drive found, bias the offset */
2473  IsEzDrive = TRUE;
2474  ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
2475  Offset.QuadPart = 512;
2476  }
2477 
2478  /* Get the number of bits to shift to multiply by the sector size */
2479  for (k = 0; k < 32; k++) if ((SectorSize >> k) == 1) break;
2480 
2481  /* Check if there's only one partition */
2482  if (PartitionBuffer->PartitionCount == 1)
2483  {
2484  /* Check if it has no starting offset or hidden sectors */
2485  if (!(PartitionInfo->StartingOffset.QuadPart) &&
2486  !(PartitionInfo->HiddenSectors))
2487  {
2488  /* Then it's a super floppy */
2489  IsSuperFloppy = TRUE;
2490 
2491  /* Which also means it must be non-bootable FAT-16 */
2492  if ((PartitionInfo->PartitionNumber) ||
2493  (PartitionInfo->PartitionType != PARTITION_FAT_16) ||
2494  (PartitionInfo->BootIndicator))
2495  {
2496  /* It's not, so we fail */
2497  return STATUS_INVALID_PARAMETER;
2498  }
2499 
2500  /* Check if it needs a rewrite, and disable EZ drive for sure */
2501  if (PartitionInfo->RewritePartition) DoRewrite = TRUE;
2502  IsEzDrive = FALSE;
2503  }
2504  }
2505 
2506  /* Count the number of partition tables */
2507  DiskLayout->TableCount = (PartitionBuffer->PartitionCount + 4 - 1) / 4;
2508 
2509  /* Allocate our partition buffer */
2512 
2513  /* Loop the entries */
2515  for (i = 0; i < DiskLayout->TableCount; i++)
2516  {
2517  /* Set if this is the MBR partition */
2518  IsMbr= (BOOLEAN)!i;
2519 
2520  /* Initialize th event */
2522 
2523  /* Build the read IRP */
2525  DeviceObject,
2526  Buffer,
2527  BufferSize,
2528  &Offset,
2529  &Event,
2530  &IoStatusBlock);
2531  if (!Irp)
2532  {
2533  /* Fail */
2535  break;
2536  }
2537 
2538  /* Make sure to disable volume verification */
2539  IoStackLocation = IoGetNextIrpStackLocation(Irp);
2540  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2541 
2542  /* Call the driver */
2544  if (Status == STATUS_PENDING)
2545  {
2546  /* Wait for completion */
2549  }
2550 
2551  /* Check for failure */
2552  if (!NT_SUCCESS(Status)) break;
2553 
2554  /* If we biased for EZ-Drive, unbias now */
2555  if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2556 
2557  /* Check if this is a normal disk */
2558  if (!IsSuperFloppy)
2559  {
2560  /* Set the boot record signature */
2562 
2563  /* By default, don't require a rewrite */
2564  DoRewrite = FALSE;
2565 
2566  /* Check if we don't have an offset */
2567  if (!Offset.QuadPart)
2568  {
2569  /* Check if the signature doesn't match */
2570  if (((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] !=
2571  PartitionBuffer->Signature)
2572  {
2573  /* Then write the signature and now we need a rewrite */
2574  ((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] =
2575  PartitionBuffer->Signature;
2576  DoRewrite = TRUE;
2577  }
2578  }
2579 
2580  /* Loop the partition table entries */
2581  PartitionTable = &DiskLayout->PartitionTable[i];
2582  for (j = 0; j < 4; j++)
2583  {
2584  /* Get the current entry and type */
2585  TableEntry = &PartitionTable->PartitionEntry[j];
2586  PartitionType = TableEntry->PartitionType;
2587 
2588  /* Check if the entry needs a rewrite */
2589  if (TableEntry->RewritePartition)
2590  {
2591  /* Then we need one too */
2592  DoRewrite = TRUE;
2593 
2594  /* Save the type and if it's a bootable partition */
2595  Entry[j].PartitionType = TableEntry->PartitionType;
2596  Entry[j].ActiveFlag = TableEntry->BootIndicator ? 0x80 : 0;
2597 
2598  /* Make sure it's used */
2600  {
2601  /* Make sure it's not a container (unless primary) */
2602  if ((IsMbr) || !(IsContainerPartition(PartitionType)))
2603  {
2604  /* Use the partition offset */
2605  StartOffset.QuadPart = Offset.QuadPart;
2606  }
2607  else
2608  {
2609  /* Use the extended logical partition offset */
2610  StartOffset.QuadPart = ExtendedOffset.QuadPart;
2611  }
2612 
2613  /* Set the sector offset */
2614  SectorOffset.QuadPart = TableEntry->
2615  StartingOffset.QuadPart -
2616  StartOffset.QuadPart;
2617 
2618  /* Now calculate the starting sector */
2619  StartOffset.QuadPart = SectorOffset.QuadPart >> k;
2620  Entry[j].StartingSector = StartOffset.LowPart;
2621 
2622  /* As well as the length */
2623  PartitionLength.QuadPart = TableEntry->PartitionLength.
2624  QuadPart >> k;
2625  Entry[j].PartitionLength = PartitionLength.LowPart;
2626 
2627  /* Calculate the CHS values */
2628  HalpCalculateChsValues(&TableEntry->StartingOffset,
2629  &TableEntry->PartitionLength,
2630  k,
2632  NumberOfHeads,
2633  ConventionalCylinders,
2635  &Entry[j]);
2636  }
2637  else
2638  {
2639  /* Otherwise set up an empty entry */
2640  Entry[j].StartingSector = 0;
2641  Entry[j].PartitionLength = 0;
2642  Entry[j].StartingTrack = 0;
2643  Entry[j].EndingTrack = 0;
2644  Entry[j].StartingCylinder = 0;
2645  Entry[j].EndingCylinder = 0;
2646  }
2647  }
2648 
2649  /* Check if this is a container partition */
2651  {
2652  /* Then update the offset to use */
2653  NextOffset = TableEntry->StartingOffset;
2654  }
2655  }
2656  }
2657 
2658  /* Check if we need to write back the buffer */
2659  if (DoRewrite)
2660  {
2661  /* We don't need to do this again */
2662  DoRewrite = FALSE;
2663 
2664  /* Initialize the event */
2666 
2667  /* If we unbiased for EZ-Drive, rebias now */
2668  if ((IsEzDrive) && !(Offset.QuadPart)) Offset.QuadPart = 512;
2669 
2670  /* Build the write IRP */
2672  DeviceObject,
2673  Buffer,
2674  BufferSize,
2675  &Offset,
2676  &Event,
2677  &IoStatusBlock);
2678  if (!Irp)
2679  {
2680  /* Fail */
2682  break;
2683  }
2684 
2685  /* Make sure to disable volume verification */
2686  IoStackLocation = IoGetNextIrpStackLocation(Irp);
2687  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2688 
2689  /* Call the driver */
2691  if (Status == STATUS_PENDING)
2692  {
2693  /* Wait for completion */
2695  Executive,
2696  KernelMode,
2697  FALSE,
2698  NULL);
2700  }
2701 
2702  /* Check for failure */
2703  if (!NT_SUCCESS(Status)) break;
2704 
2705  /* If we biased for EZ-Drive, unbias now */
2706  if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2707  }
2708 
2709  /* Update the partition offset and set the extended offset if needed */
2710  Offset = NextOffset;
2711  if (IsMbr) ExtendedOffset = NextOffset;
2712  }
2713 
2714  /* If we had a buffer, free it, then return status */
2716  return Status;
2717 }
2718 
2719 /* PUBLIC FUNCTIONS **********************************************************/
2720 
2721 /*
2722  * @implemented
2723  */
2724 VOID
2725 FASTCALL
2728  IN ULONG MbrTypeIdentifier,
2729  OUT PVOID *MbrBuffer)
2730 {
2731  HALDISPATCH->HalExamineMBR(DeviceObject,
2732  SectorSize,
2733  MbrTypeIdentifier,
2734  MbrBuffer);
2735 }
2736 
2737 /*
2738  * @implemented
2739  */
2740 NTSTATUS
2741 FASTCALL
2746 {
2747  return HALDISPATCH->HalIoReadPartitionTable(DeviceObject,
2748  SectorSize,
2750  PartitionBuffer);
2751 }
2752 
2753 /*
2754  * @implemented
2755  */
2756 NTSTATUS
2757 FASTCALL
2762 {
2763  return HALDISPATCH->HalIoSetPartitionInformation(DeviceObject,
2764  SectorSize,
2766  PartitionType);
2767 }
2768 
2769 /*
2770  * @implemented
2771  */
2772 NTSTATUS
2773 FASTCALL
2779 {
2780  return HALDISPATCH->HalIoWritePartitionTable(DeviceObject,
2781  SectorSize,
2783  NumberOfHeads,
2784  PartitionBuffer);
2785 }
2786 
2787 /*
2788  * @implemented
2789  */
2790 VOID
2791 FASTCALL
2793  IN PSTRING NtDeviceName,
2794  OUT PUCHAR NtSystemPath,
2795  OUT PSTRING NtSystemPathString)
2796 {
2797  HALDISPATCH->HalIoAssignDriveLetters(LoaderBlock,
2798  NtDeviceName,
2799  NtSystemPath,
2800  NtSystemPathString);
2801 }
2802 
2803 /* EOF */
NTSTATUS FASTCALL IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: disksup.c:2758
#define TAG_FILE_SYSTEM
Definition: tag.h:50
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define IN
Definition: typedefs.h:38
#define max(a, b)
Definition: svc.c:63
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
LARGE_INTEGER StartingOffset
Definition: partlist.c:25
#define GET_STARTING_SECTOR(p)
Definition: hal.h:252
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define EFI_PMBR_OSTYPE_EFI
Definition: disksup.c:25
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:282
struct _Entry Entry
Definition: kefuncs.h:640
Definition: hal.h:331
struct _PTE * PPTE
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
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Definition: iorsrce.c:830
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
UCHAR JumpByte[1]
Definition: hal.h:301
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
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:1524
struct _MOUNTMGR_MOUNT_POINT MOUNTMGR_MOUNT_POINT
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
VOID HalpEnableAutomaticDriveLetterAssignment(VOID)
Definition: disksup.c:857
#define IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS
Definition: mountmgr.h:36
#define STATUS_BAD_MASTER_BOOT_RECORD
Definition: ntstatus.h:391
#define PARTITION_TABLE_OFFSET
Definition: hal.h:243
#define IOCTL_MOUNTMGR_CREATE_POINT
Definition: imports.h:118
#define POOL_COLD_ALLOCATION
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:250
ULONG BytesPerSector
Definition: ntdddisk.h:381
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
ULONG TracksPerCylinder
Definition: ntdddisk.h:379
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
_In_ ULONG _In_ ULONG _In_ ULONG NumberOfHeads
Definition: iofuncs.h:2066
WCHAR DeviceName[]
Definition: adapter.cpp:21
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2056
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define FASTCALL
Definition: nt_native.h:50
#define SET_PARTITION_LENGTH(p, l)
Definition: hal.h:267
struct _DISK_LAYOUT * PDISK_LAYOUT
NTSTATUS HalpDeleteMountLetter(UCHAR DriveLetter)
Definition: disksup.c:766
#define PAGED_CODE()
Definition: video.h:57
CHAR InputBuffer[80]
Definition: conmgr.c:33
#define FILE_SHARE_READ
Definition: compat.h:125
PARTITION_INFORMATION PartitionEntry[4]
Definition: hal.h:318
NTSTATUS HalpQueryPartitionType(IN PUNICODE_STRING DeviceName, IN PDRIVE_LAYOUT_INFORMATION LayoutInfo, OUT PPARTITION_TYPE PartitionType)
Definition: disksup.c:165
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
struct _REG_DISK_MOUNT_INFO REG_DISK_MOUNT_INFO
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
uint32_t ULONG_PTR
Definition: typedefs.h:63
VOID FASTCALL xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG MbrTypeIdentifier, OUT PVOID *MbrBuffer)
Definition: disksup.c:1685
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:86
#define sprintf(buf, format,...)
Definition: sprintf.c:55
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:389
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
HANDLE FileHandle
Definition: stats.c:38
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
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ ULONG _In_ ULONG SectorsPerTrack
Definition: iofuncs.h:2066
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define ANSI_NULL
struct _REG_DISK_MOUNT_INFO * PREG_DISK_MOUNT_INFO
#define IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER
Definition: mountmgr.h:34
long LONG
Definition: pedump.c:60
VOID FASTCALL xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PSTRING NtDeviceName, OUT PUCHAR NtSystemPath, OUT PSTRING NtSystemPathString)
Definition: disksup.c:912
#define FILE_READ_DATA
Definition: nt_native.h:628
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
NTSTATUS FASTCALL xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: disksup.c:2244
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:435
_In_ ULONG _In_ BOOLEAN _Out_ struct _DRIVE_LAYOUT_INFORMATION ** PartitionBuffer
Definition: iofuncs.h:2048
#define SectorOffset(L)
Definition: cdprocs.h:1632
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1780
void DPRINT(...)
Definition: polytest.cpp:61
VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1507
Definition: bufpool.h:45
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:132
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
NTSTATUS NTAPI HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject, IN PDISK_GEOMETRY Geometry, OUT PULONGLONG RealSectorCount)
Definition: disksup.c:1389
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
UCHAR HalpNextDriveLetter(IN PUNICODE_STRING DeviceName, IN PSTRING NtDeviceName, OUT PUCHAR NtSystemPath, BOOLEAN IsRemovable)
Definition: disksup.c:607
int64_t LONGLONG
Definition: typedefs.h:66
#define GET_PARTITION_LENGTH(p)
Definition: hal.h:261
NTSTATUS FASTCALL IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: disksup.c:2742
_DISK_MANAGER
Definition: disksup.c:37
NTSTATUS FASTCALL xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: disksup.c:1810
enum _PARTITION_TYPE * PPARTITION_TYPE
#define BOOT_RECORD_SIGNATURE
Definition: parttest.c:17
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
char CCHAR
Definition: typedefs.h:50
UCHAR PartitionType
Definition: hal.h:282
uint64_t ULONGLONG
Definition: typedefs.h:65
ULONG TableCount
Definition: hal.h:323
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:377
ULONG SectorsPerTrack
Definition: ntdddisk.h:380
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:276
#define swprintf(buf, format,...)
Definition: sprintf.c:56
struct _PARTITION_DESCRIPTOR * PPARTITION_DESCRIPTOR
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2101
#define BufferSize
Definition: classpnp.h:419
MEDIA_TYPE MediaType
Definition: ntdddisk.h:378
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
PARTITION_TABLE PartitionTable[1]
Definition: hal.h:325
#define PARTITION_FAT_16
Definition: disk.h:90
_Must_inspect_result_ typedef _In_ ULONG _In_ BOOLEAN Target
Definition: iotypes.h:1068
VOID NTAPI FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor, IN ULONGLONG MaxOffset)
Definition: disksup.c:1791
* PFILE_OBJECT
Definition: iotypes.h:1955
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
static PPARTENTRY SystemPartition
Definition: usetup.c:61
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
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)
NTSTATUS HalpSetMountLetter(IN PUNICODE_STRING DeviceName, UCHAR DriveLetter)
Definition: disksup.c:522
unsigned char UCHAR
Definition: xmlstorage.h:181
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:88
static const WCHAR L[]
Definition: oid.c:1250
BOOLEAN NTAPI HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry, IN ULONGLONG MaxOffset, IN ULONGLONG MaxSector)
Definition: disksup.c:1483
NTSTATUS FASTCALL xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: disksup.c:2432
_In_ ULONG _In_ BOOLEAN ReturnRecognizedPartitions
Definition: iofuncs.h:2046
#define BOOT_SIGNATURE_OFFSET
Definition: hal.h:244
ULONG LowPart
Definition: typedefs.h:104
#define TAG_FSTUB
Definition: tag.h:195
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define STATUS_NO_DATA_DETECTED
Definition: udferr_usr.h:131
static const WCHAR Cleanup[]
Definition: register.c:80
#define SYNCHRONIZE
Definition: nt_native.h:61
ULONG SectorCount
Definition: part_xbox.c:32
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG InputBufferLength
Definition: fltkernel.h:1372
NTSYSAPI VOID NTAPI RtlInitString(PSTRING DestinationString, PCSZ SourceString)
UCHAR ActiveFlag
Definition: hal.h:278
Status
Definition: gdiplustypes.h:24
#define IOCTL_DISK_GET_DRIVE_LAYOUT
Definition: ntdddisk.h:76
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
struct _MOUNTMGR_CREATE_POINT_INPUT MOUNTMGR_CREATE_POINT_INPUT
VOID FASTCALL xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject, IN PULONG ConventionalCylinders, IN PLONGLONG DiskSize)
Definition: disksup.c:1599
#define STATUS_NO_MEDIA
Definition: ntstatus.h:596
BOOLEAN IsSuperFloppy(IN PDISKENTRY DiskEntry)
Definition: partlist.c:679
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
_CRTIMP char *__cdecl _strupr(_Inout_z_ char *_String)
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
unsigned short USHORT
Definition: pedump.c:61
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define IsFTPartition(PartitionType)
Definition: ntdddisk.h:241
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
signed char * PSTR
Definition: retypes.h:7
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
const WCHAR DiskMountString[]
Definition: disksup.c:19
PULONG IopComputeHarddiskDerangements(IN ULONG DiskCount)
Definition: disksup.c:320
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
BOOLEAN HalpIsOldStyleFloppy(PUNICODE_STRING DeviceName)
Definition: disksup.c:707
VOID FASTCALL IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PSTRING NtDeviceName, OUT PUCHAR NtSystemPath, OUT PSTRING NtSystemPathString)
Definition: disksup.c:2792
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 DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:3947
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define BOOLEAN
Definition: pedump.c:73
#define OUT
Definition: typedefs.h:39
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
CHAR PartitionType
Definition: part_xbox.c:33
ret QuadPart
Definition: rtlfuncs.h:3091
#define NUM_PARTITION_TABLE_ENTRIES
Definition: hal.h:247
unsigned int ULONG
Definition: retypes.h:1
enum _DISK_MANAGER DISK_MANAGER
NTSTATUS FASTCALL HalpQueryDriveLayout(IN PUNICODE_STRING DeviceName, OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
Definition: disksup.c:56
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
VOID FASTCALL HalExamineMBR(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG MbrTypeIdentifier, OUT PVOID *MbrBuffer)
Definition: disksup.c:2726
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
NTSTATUS HalpNextMountLetter(IN PUNICODE_STRING DeviceName, OUT PUCHAR DriveLetter)
Definition: disksup.c:441
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_In_ ULONG SectorSize
Definition: halfuncs.h:291
_In_ PCHAR _In_ ULONG DeviceNumber
Definition: classpnp.h:1036
enum _PARTITION_TYPE PARTITION_TYPE
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:42
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define UInt32x32To64(a, b)
Definition: intsafe.h:258
#define UL
Definition: tui.h:83
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
int k
Definition: mpi.c:3369
unsigned short * PUSHORT
Definition: retypes.h:2
NTSTATUS FASTCALL IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: disksup.c:2774
#define HALDISPATCH
Definition: haltypes.h:278
base of all file and directory entries
Definition: entries.h:82
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
struct _BOOT_SECTOR_INFO * PBOOT_SECTOR_INFO
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
#define IOCTL_MOUNTMGR_DELETE_POINTS
Definition: imports.h:124
LONGLONG QuadPart
Definition: typedefs.h:112
_In_ LARGE_INTEGER _Out_opt_ PLARGE_INTEGER Remainder
Definition: rtlfuncs.h:3046
BOOLEAN IoRemoteBootClient
Definition: init.c:67