ReactOS  0.4.10-dev-234-g15c29d0
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 */
10 
11 /* INCLUDES ******************************************************************/
12 
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16 #include <internal/hal.h>
17 
18 /* DEPRECATED FUNCTIONS ******************************************************/
19 
20 #if 1
21 const WCHAR DiskMountString[] = L"\\DosDevices\\%C:";
22 
23 #define AUTO_DRIVE MAXULONG
24 
25 #define PARTITION_MAGIC 0xaa55
26 
27 #define EFI_PMBR_OSTYPE_EFI 0xEE
28 
29 #include <pshpack1.h>
30 
31 typedef struct _REG_DISK_MOUNT_INFO
32 {
36 
37 #include <poppack.h>
38 
39 typedef enum _DISK_MANAGER
40 {
44 } DISK_MANAGER;
45 
46 static BOOLEAN
48  IN ULONG DriveNumber,
52  IN HANDLE hKey,
54  OUT PUCHAR NtSystemPath)
55 {
56  WCHAR DriveNameBuffer[16];
57  UNICODE_STRING DriveName;
58  ULONG i;
61 
62  DPRINT("HalpAssignDrive()\n");
63 
64  if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 26))
65  {
66  /* Force assignment */
68  if ((ObSystemDeviceMap->DriveMap & (1 << DriveNumber)) != 0)
69  {
70  DbgPrint("Drive letter already used!\n");
72  return FALSE;
73  }
75  }
76  else
77  {
78  /* Automatic assignment */
79  DriveNumber = AUTO_DRIVE;
81  for (i = 2; i < 26; i++)
82  {
83  if ((ObSystemDeviceMap->DriveMap & (1 << i)) == 0)
84  {
85  DriveNumber = i;
86  break;
87  }
88  }
90 
91  if (DriveNumber == AUTO_DRIVE)
92  {
93  DbgPrint("No drive letter available!\n");
94  return FALSE;
95  }
96  }
97 
98  DPRINT("DriveNumber %lu\n", DriveNumber);
99 
100  /* Build drive name */
101  swprintf(DriveNameBuffer,
102  L"\\??\\%C:",
103  'A' + DriveNumber);
104  RtlInitUnicodeString(&DriveName,
105  DriveNameBuffer);
106 
107  DPRINT(" %wZ ==> %wZ\n",
108  &DriveName,
109  PartitionName);
110 
111  /* Create symbolic link */
112  Status = IoCreateSymbolicLink(&DriveName,
113  PartitionName);
114 
115  if (hKey &&
116  DriveType == DOSDEVICE_DRIVE_FIXED &&
117  Signature)
118  {
119  DiskMountInfo.Signature = Signature;
120  DiskMountInfo.StartingOffset = StartingOffset;
121  swprintf(DriveNameBuffer, DiskMountString, L'A' + DriveNumber);
122  RtlInitUnicodeString(&DriveName, DriveNameBuffer);
123 
124  Status = ZwSetValueKey(hKey,
125  &DriveName,
126  0,
127  REG_BINARY,
128  &DiskMountInfo,
129  sizeof(DiskMountInfo));
130  if (!NT_SUCCESS(Status))
131  {
132  DPRINT1("ZwCreateValueKey failed for %wZ, status=%x\n", &DriveName, Status);
133  }
134  }
135 
136  /* Check if this is a boot partition */
137  if (RtlCompareUnicodeString(PartitionName, BootDevice, FALSE) == 0)
138  {
139  /* Set NtSystemPath to that partition's disk letter */
140  *NtSystemPath = (UCHAR)('A' + DriveNumber);
141  }
142 
143  return TRUE;
144 }
145 
146 ULONG
148 {
150  UNICODE_STRING ArcName;
151  PWCHAR ArcNameBuffer;
154  POBJECT_DIRECTORY_INFORMATION DirectoryInfo;
155  ULONG Skip;
157  ULONG CurrentRDisk;
158  ULONG RDiskCount;
159  BOOLEAN First = TRUE;
160  ULONG Count;
161 
163  if (DirectoryInfo == NULL)
164  {
165  return 0;
166  }
167 
168  RtlInitUnicodeString(&ArcName, L"\\ArcName");
169  InitializeObjectAttributes(&ObjectAttributes,
170  &ArcName,
171  0,
172  NULL,
173  NULL);
174 
175  Status = ZwOpenDirectoryObject (&DirectoryHandle,
177  &ObjectAttributes);
178  if (!NT_SUCCESS(Status))
179  {
180  DPRINT1("ZwOpenDirectoryObject for %wZ failed, status=%lx\n", &ArcName, Status);
181  ExFreePoolWithTag(DirectoryInfo, TAG_FILE_SYSTEM);
182  return 0;
183  }
184 
185  RDiskCount = 0;
186  Skip = 0;
187  while (NT_SUCCESS(Status))
188  {
189  Status = ZwQueryDirectoryObject (DirectoryHandle,
190  DirectoryInfo,
191  2 * PAGE_SIZE,
192  FALSE,
193  First,
194  &Skip,
195  &ResultLength);
196  First = FALSE;
197  if (NT_SUCCESS(Status))
198  {
199  Count = 0;
200  while (DirectoryInfo[Count].Name.Buffer)
201  {
202  DPRINT("Count %x\n", Count);
203  DirectoryInfo[Count].Name.Buffer[DirectoryInfo[Count].Name.Length / sizeof(WCHAR)] = 0;
204  ArcNameBuffer = DirectoryInfo[Count].Name.Buffer;
205  if (DirectoryInfo[Count].Name.Length >= sizeof(L"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR) &&
206  !_wcsnicmp(ArcNameBuffer, L"multi(0)disk(0)rdisk(", (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR)))
207  {
208  DPRINT("%S\n", ArcNameBuffer);
209  ArcNameBuffer += (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR);
210  CurrentRDisk = 0;
211  while (iswdigit(*ArcNameBuffer))
212  {
213  CurrentRDisk = CurrentRDisk * 10 + *ArcNameBuffer - L'0';
214  ArcNameBuffer++;
215  }
216  if (!_wcsicmp(ArcNameBuffer, L")") &&
217  CurrentRDisk >= RDiskCount)
218  {
219  RDiskCount = CurrentRDisk + 1;
220  }
221  }
222  Count++;
223  }
224  }
225  }
226 
227  ZwClose(DirectoryHandle);
228 
229  ExFreePoolWithTag(DirectoryInfo, TAG_FILE_SYSTEM);
230  return RDiskCount;
231 }
232 
233 NTSTATUS
235 {
236  WCHAR NameBuffer[80];
237  UNICODE_STRING ArcName;
238  UNICODE_STRING LinkName;
240  HANDLE LinkHandle;
242 
243  swprintf(NameBuffer,
244  L"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
245  RDisk);
246 
247  RtlInitUnicodeString(&ArcName, NameBuffer);
248  InitializeObjectAttributes(&ObjectAttributes,
249  &ArcName,
250  0,
251  NULL,
252  NULL);
253  Status = ZwOpenSymbolicLinkObject(&LinkHandle,
255  &ObjectAttributes);
256  if (!NT_SUCCESS(Status))
257  {
258  DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName, Status);
259  return Status;
260  }
261 
262  LinkName.Buffer = NameBuffer;
263  LinkName.Length = 0;
264  LinkName.MaximumLength = sizeof(NameBuffer);
265  Status = ZwQuerySymbolicLinkObject(LinkHandle,
266  &LinkName,
267  NULL);
268  ZwClose(LinkHandle);
269  if (!NT_SUCCESS(Status))
270  {
271  DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status);
272  return Status;
273  }
274  if (LinkName.Length < sizeof(L"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR) ||
275  LinkName.Length >= sizeof(NameBuffer))
276  {
277  return STATUS_UNSUCCESSFUL;
278  }
279 
280  NameBuffer[LinkName.Length / sizeof(WCHAR)] = 0;
281  if (_wcsnicmp(NameBuffer, L"\\Device\\Harddisk", (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR)))
282  {
283  return STATUS_UNSUCCESSFUL;
284  }
285  LinkName.Buffer += (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR);
286 
287  if (!iswdigit(*LinkName.Buffer))
288  {
289  return STATUS_UNSUCCESSFUL;
290  }
291  *DiskNumber = 0;
292  while (iswdigit(*LinkName.Buffer))
293  {
294  *DiskNumber = *DiskNumber * 10 + *LinkName.Buffer - L'0';
295  LinkName.Buffer++;
296  }
297  if (_wcsicmp(LinkName.Buffer, L"\\Partition0"))
298  {
299  return STATUS_UNSUCCESSFUL;
300  }
301  return STATUS_SUCCESS;
302 }
303 
304 NTSTATUS
305 FASTCALL
307  OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
308 {
309  IO_STATUS_BLOCK StatusBlock;
310  DISK_GEOMETRY DiskGeometry;
313  KEVENT Event;
314  PIRP Irp;
316 
317  DPRINT("xHalpQueryDriveLayout %wZ %p\n",
318  DeviceName,
319  LayoutInfo);
320 
321  /* Get the drives sector size */
322  Status = IoGetDeviceObjectPointer(DeviceName,
324  &FileObject,
325  &DeviceObject);
326  if (!NT_SUCCESS(Status))
327  {
328  DPRINT("Status %x\n", Status);
329  return(Status);
330  }
331 
332  KeInitializeEvent(&Event,
334  FALSE);
335 
337  DeviceObject,
338  NULL,
339  0,
340  &DiskGeometry,
341  sizeof(DISK_GEOMETRY),
342  FALSE,
343  &Event,
344  &StatusBlock);
345  if (Irp == NULL)
346  {
347  ObDereferenceObject(FileObject);
349  }
350 
351  Status = IoCallDriver(DeviceObject,
352  Irp);
353  if (Status == STATUS_PENDING)
354  {
355  KeWaitForSingleObject(&Event,
356  Executive,
357  KernelMode,
358  FALSE,
359  NULL);
360  Status = StatusBlock.Status;
361  }
362  if (!NT_SUCCESS(Status))
363  {
364  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
365  {
366  DiskGeometry.BytesPerSector = 512;
367  }
368  else
369  {
370  ObDereferenceObject(FileObject);
371  return(Status);
372  }
373  }
374 
375  DPRINT("DiskGeometry.BytesPerSector: %lu\n",
376  DiskGeometry.BytesPerSector);
377 
378  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
379  {
381 
382  /* Allocate a partition list for a single entry. */
385  if (Buffer != NULL)
386  {
387  RtlZeroMemory(Buffer,
388  sizeof(DRIVE_LAYOUT_INFORMATION));
389  Buffer->PartitionCount = 1;
390  *LayoutInfo = Buffer;
391 
392  Status = STATUS_SUCCESS;
393  }
394  else
395  {
396  Status = STATUS_UNSUCCESSFUL;
397  }
398  }
399  else
400  {
401  /* Read the partition table */
402  Status = IoReadPartitionTable(DeviceObject,
403  DiskGeometry.BytesPerSector,
404  TRUE,
405  LayoutInfo);
406  }
407 
408  ObDereferenceObject(FileObject);
409 
410  return(Status);
411 }
412 
413 VOID
414 FASTCALL
416  IN PSTRING NtDeviceName,
417  OUT PUCHAR NtSystemPath,
418  OUT PSTRING NtSystemPathString)
419 {
420  PDRIVE_LAYOUT_INFORMATION *LayoutArray;
423  IO_STATUS_BLOCK StatusBlock;
424  UNICODE_STRING UnicodeString1;
425  UNICODE_STRING UnicodeString2;
427  PWSTR Buffer1;
428  PWSTR Buffer2;
429  ULONG i, j, k;
430  ULONG DiskNumber;
431  ULONG RDisk;
433  HANDLE hKey;
434  ULONG Length;
435  PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
436  PREG_DISK_MOUNT_INFO DiskMountInfo;
437  ULONG RDiskCount;
439 
440  Status = RtlAnsiStringToUnicodeString(&BootDevice,
441  NtDeviceName,
442  TRUE);
443 
444  DPRINT("xHalIoAssignDriveLetters()\n");
445 
446  ConfigInfo = IoGetConfigurationInformation();
447 
448  RDiskCount = xHalpGetRDiskCount();
449 
450  DPRINT("RDiskCount %lu\n", RDiskCount);
451 
453  64 * sizeof(WCHAR),
455  if (!Buffer1) return;
456 
458  32 * sizeof(WCHAR),
460  if (!Buffer2)
461  {
463  return;
464  }
465 
466  PartialInformation = ExAllocatePoolWithTag(PagedPool,
469  if (!PartialInformation)
470  {
473  return;
474  }
475 
476  DiskMountInfo = (PREG_DISK_MOUNT_INFO) PartialInformation->Data;
477 
478  /* Create or open the 'MountedDevices' key */
479  RtlInitUnicodeString(&UnicodeString1, L"\\Registry\\Machine\\SYSTEM\\MountedDevices");
480  InitializeObjectAttributes(&ObjectAttributes,
481  &UnicodeString1,
483  NULL,
484  NULL);
485  Status = ZwCreateKey(&hKey,
487  &ObjectAttributes,
488  0,
489  NULL,
491  NULL);
492  if (!NT_SUCCESS(Status))
493  {
494  hKey = NULL;
495  DPRINT("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1, Status);
496  }
497 
498  /* Create PhysicalDrive links */
499  DPRINT("Physical disk drives: %lu\n", ConfigInfo->DiskCount);
500  for (i = 0; i < ConfigInfo->DiskCount; i++)
501  {
502  swprintf(Buffer1, L"\\Device\\Harddisk%lu\\Partition0", i);
503  RtlInitUnicodeString(&UnicodeString1, Buffer1);
504 
505  InitializeObjectAttributes(&ObjectAttributes,
506  &UnicodeString1,
507  0,
508  NULL,
509  NULL);
510 
511  Status = ZwOpenFile(&FileHandle,
513  &ObjectAttributes,
514  &StatusBlock,
517  if (NT_SUCCESS(Status))
518  {
519  ZwClose(FileHandle);
520 
521  swprintf(Buffer2, L"\\??\\PhysicalDrive%lu", i);
522  RtlInitUnicodeString(&UnicodeString2, Buffer2);
523 
524  DPRINT("Creating link: %S ==> %S\n",
525  Buffer2,
526  Buffer1);
527 
528  IoCreateSymbolicLink(&UnicodeString2,
529  &UnicodeString1);
530  }
531  }
532 
533  /* Initialize layout array */
534  if (ConfigInfo->DiskCount == 0)
535  goto end_assign_disks;
536  LayoutArray = ExAllocatePoolWithTag(NonPagedPool,
537  ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION), TAG_FILE_SYSTEM);
538  if (!LayoutArray)
539  {
540  ExFreePoolWithTag(PartialInformation, TAG_FILE_SYSTEM);
543  if (hKey) ObCloseHandle(hKey, KernelMode);
544  return;
545  }
546 
547  RtlZeroMemory(LayoutArray,
548  ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
549  for (i = 0; i < ConfigInfo->DiskCount; i++)
550  {
551  swprintf(Buffer1, L"\\Device\\Harddisk%lu\\Partition0", i);
552  RtlInitUnicodeString(&UnicodeString1, Buffer1);
553 
554  Status = xHalQueryDriveLayout(&UnicodeString1, &LayoutArray[i]);
555  if (!NT_SUCCESS(Status))
556  {
557  DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
558  Status);
559  LayoutArray[i] = NULL;
560  continue;
561  }
562  /* We don't use the RewritePartition value while mounting the disks.
563  * We use this value for marking pre-assigned (registry) partitions.
564  */
565  for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
566  {
567  LayoutArray[i]->PartitionEntry[j].RewritePartition = FALSE;
568  }
569  }
570 
571 #ifndef NDEBUG
572  /* Dump layout array */
573  for (i = 0; i < ConfigInfo->DiskCount; i++)
574  {
575  DPRINT("Harddisk %d:\n",
576  i);
577 
578  if (LayoutArray[i] == NULL)
579  continue;
580 
581  DPRINT("Logical partitions: %d\n",
582  LayoutArray[i]->PartitionCount);
583 
584  for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
585  {
586  DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
587  j,
588  LayoutArray[i]->PartitionEntry[j].PartitionNumber,
589  LayoutArray[i]->PartitionEntry[j].BootIndicator,
590  LayoutArray[i]->PartitionEntry[j].PartitionType,
591  LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart,
592  LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart);
593  }
594  }
595 #endif
596 
597  /* Assign pre-assigned (registry) partitions */
598  if (hKey)
599  {
600  for (k = 2; k < 26; k++)
601  {
602  swprintf(Buffer1, DiskMountString, L'A' + k);
603  RtlInitUnicodeString(&UnicodeString1, Buffer1);
604  Status = ZwQueryValueKey(hKey,
605  &UnicodeString1,
607  PartialInformation,
609  &Length);
610  if (NT_SUCCESS(Status) &&
611  PartialInformation->Type == REG_BINARY &&
612  PartialInformation->DataLength == sizeof(REG_DISK_MOUNT_INFO))
613  {
614  DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1, DiskMountInfo->Signature,
615  DiskMountInfo->StartingOffset.u.HighPart, DiskMountInfo->StartingOffset.u.LowPart);
616  {
617  BOOLEAN Found = FALSE;
618  for (i = 0; i < ConfigInfo->DiskCount; i++)
619  {
620  DPRINT("%x\n", LayoutArray[i]->Signature);
621  if (LayoutArray[i] &&
622  LayoutArray[i]->Signature &&
623  LayoutArray[i]->Signature == DiskMountInfo->Signature)
624  {
625  for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
626  {
627  if (LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart == DiskMountInfo->StartingOffset.QuadPart)
628  {
629  if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType) &&
630  LayoutArray[i]->PartitionEntry[j].RewritePartition == FALSE)
631  {
632  swprintf(Buffer2,
633  L"\\Device\\Harddisk%lu\\Partition%lu",
634  i,
635  LayoutArray[i]->PartitionEntry[j].PartitionNumber);
636  RtlInitUnicodeString(&UnicodeString2, Buffer2);
637 
638  /* Assign drive */
639  DPRINT(" %wZ\n", &UnicodeString2);
640  Found = HalpAssignDrive(&UnicodeString2,
641  k,
643  DiskMountInfo->Signature,
644  DiskMountInfo->StartingOffset,
645  NULL,
646  &BootDevice,
647  NtSystemPath);
648  /* Mark the partition as assigned */
649  LayoutArray[i]->PartitionEntry[j].RewritePartition = TRUE;
650  }
651  break;
652  }
653  }
654  }
655  }
656  if (Found == FALSE)
657  {
658  /* We didn't find a partition for this entry, remove them. */
659  Status = ZwDeleteValueKey(hKey, &UnicodeString1);
660  }
661  }
662  }
663  }
664  }
665 
666  /* Assign bootable partition on first harddisk */
667  DPRINT("Assigning bootable primary partition on first harddisk:\n");
668  if (RDiskCount > 0)
669  {
670  Status = xHalpGetDiskNumberFromRDisk(0, &DiskNumber);
671  if (NT_SUCCESS(Status) &&
672  DiskNumber < ConfigInfo->DiskCount &&
673  LayoutArray[DiskNumber])
674  {
675  /* Search for bootable partition */
676  for (j = 0; j < NUM_PARTITION_TABLE_ENTRIES && j < LayoutArray[DiskNumber]->PartitionCount; j++)
677  {
678  if ((LayoutArray[DiskNumber]->PartitionEntry[j].BootIndicator != FALSE) &&
679  IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
680  {
681  if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE)
682  {
683  swprintf(Buffer2,
684  L"\\Device\\Harddisk%lu\\Partition%lu",
685  DiskNumber,
686  LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
687  RtlInitUnicodeString(&UnicodeString2, Buffer2);
688 
689  /* Assign drive */
690  DPRINT(" %wZ\n", &UnicodeString2);
691  HalpAssignDrive(&UnicodeString2,
692  AUTO_DRIVE,
694  LayoutArray[DiskNumber]->Signature,
695  LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
696  hKey,
697  &BootDevice,
698  NtSystemPath);
699  /* Mark the partition as assigned */
700  LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
701  }
702  break;
703  }
704  }
705  }
706  }
707 
708  /* Assign remaining primary partitions */
709  DPRINT("Assigning remaining primary partitions:\n");
710  for (RDisk = 0; RDisk < RDiskCount; RDisk++)
711  {
712  Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber);
713  if (NT_SUCCESS(Status) &&
714  DiskNumber < ConfigInfo->DiskCount &&
715  LayoutArray[DiskNumber])
716  {
717  /* Search for primary partitions */
718  for (j = 0; (j < NUM_PARTITION_TABLE_ENTRIES) && (j < LayoutArray[DiskNumber]->PartitionCount); j++)
719  {
720  if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
721  IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
722  {
723  swprintf(Buffer2,
724  L"\\Device\\Harddisk%lu\\Partition%lu",
725  DiskNumber,
726  LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
727  RtlInitUnicodeString(&UnicodeString2, Buffer2);
728 
729  /* Assign drive */
730  DPRINT(" %wZ\n",
731  &UnicodeString2);
732  HalpAssignDrive(&UnicodeString2,
733  AUTO_DRIVE,
735  LayoutArray[DiskNumber]->Signature,
736  LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
737  hKey,
738  &BootDevice,
739  NtSystemPath);
740  /* Mark the partition as assigned */
741  LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
742  }
743  }
744  }
745  }
746 
747  /* Assign extended (logical) partitions */
748  DPRINT("Assigning extended (logical) partitions:\n");
749  for (RDisk = 0; RDisk < RDiskCount; RDisk++)
750  {
751  Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber);
752  if (NT_SUCCESS(Status) &&
753  DiskNumber < ConfigInfo->DiskCount &&
754  LayoutArray[DiskNumber])
755  {
756  /* Search for extended partitions */
757  for (j = NUM_PARTITION_TABLE_ENTRIES; j < LayoutArray[DiskNumber]->PartitionCount; j++)
758  {
759  if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) &&
760  LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
761  LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0)
762  {
763  swprintf(Buffer2,
764  L"\\Device\\Harddisk%lu\\Partition%lu",
765  DiskNumber,
766  LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
767  RtlInitUnicodeString(&UnicodeString2, Buffer2);
768 
769  /* Assign drive */
770  DPRINT(" %wZ\n",
771  &UnicodeString2);
772  HalpAssignDrive(&UnicodeString2,
773  AUTO_DRIVE,
775  LayoutArray[DiskNumber]->Signature,
776  LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
777  hKey,
778  &BootDevice,
779  NtSystemPath);
780  /* Mark the partition as assigned */
781  LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
782  }
783  }
784  }
785  }
786 
787  /* Assign remaining primary partitions without an arc-name */
788  DPRINT("Assigning remaining primary partitions:\n");
789  for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++)
790  {
791  if (LayoutArray[DiskNumber])
792  {
793  /* Search for primary partitions */
794  for (j = 0; (j < NUM_PARTITION_TABLE_ENTRIES) && (j < LayoutArray[DiskNumber]->PartitionCount); j++)
795  {
796  if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
797  IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
798  {
799  swprintf(Buffer2,
800  L"\\Device\\Harddisk%lu\\Partition%lu",
801  DiskNumber,
802  LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
803  RtlInitUnicodeString(&UnicodeString2, Buffer2);
804 
805  /* Assign drive */
806  DPRINT(" %wZ\n",
807  &UnicodeString2);
808  HalpAssignDrive(&UnicodeString2,
809  AUTO_DRIVE,
811  LayoutArray[DiskNumber]->Signature,
812  LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
813  hKey,
814  &BootDevice,
815  NtSystemPath);
816  /* Mark the partition as assigned */
817  LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
818  }
819  }
820  }
821  }
822 
823  /* Assign extended (logical) partitions without an arc-name */
824  DPRINT("Assigning extended (logical) partitions:\n");
825  for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++)
826  {
827  if (LayoutArray[DiskNumber])
828  {
829  /* Search for extended partitions */
830  for (j = NUM_PARTITION_TABLE_ENTRIES; j < LayoutArray[DiskNumber]->PartitionCount; j++)
831  {
832  if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) &&
833  LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
834  LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0)
835  {
836  swprintf(Buffer2,
837  L"\\Device\\Harddisk%lu\\Partition%lu",
838  DiskNumber,
839  LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
840  RtlInitUnicodeString(&UnicodeString2, Buffer2);
841 
842  /* Assign drive */
843  DPRINT(" %wZ\n",
844  &UnicodeString2);
845  HalpAssignDrive(&UnicodeString2,
846  AUTO_DRIVE,
848  LayoutArray[DiskNumber]->Signature,
849  LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
850  hKey,
851  &BootDevice,
852  NtSystemPath);
853  /* Mark the partition as assigned */
854  LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
855  }
856  }
857  }
858  }
859 
860  /* Assign removable disk drives */
861  DPRINT("Assigning removable disk drives:\n");
862  for (i = 0; i < ConfigInfo->DiskCount; i++)
863  {
864  if (LayoutArray[i])
865  {
866  /* Search for virtual partitions */
867  if (LayoutArray[i]->PartitionCount == 1 &&
868  LayoutArray[i]->PartitionEntry[0].PartitionType == 0)
869  {
870  swprintf(Buffer2, L"\\Device\\Harddisk%lu\\Partition1", i);
871  RtlInitUnicodeString(&UnicodeString2, Buffer2);
872 
873  /* Assign drive */
874  DPRINT(" %wZ\n",
875  &UnicodeString2);
876  HalpAssignDrive(&UnicodeString2,
877  AUTO_DRIVE,
879  0,
881  hKey,
882  &BootDevice,
883  NtSystemPath);
884  }
885  }
886  }
887 
888  /* Free layout array */
889  for (i = 0; i < ConfigInfo->DiskCount; i++)
890  {
891  if (LayoutArray[i] != NULL)
892  ExFreePoolWithTag(LayoutArray[i], TAG_FILE_SYSTEM);
893  }
894  ExFreePoolWithTag(LayoutArray, TAG_FILE_SYSTEM);
895 end_assign_disks:
896 
897  /* Assign floppy drives */
898  DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount);
899  for (i = 0; i < ConfigInfo->FloppyCount; i++)
900  {
901  swprintf(Buffer1, L"\\Device\\Floppy%lu", i);
902  RtlInitUnicodeString(&UnicodeString1, Buffer1);
903 
904  /* Assign drive letters A: or B: or first free drive letter */
905  DPRINT(" %wZ\n",
906  &UnicodeString1);
907  HalpAssignDrive(&UnicodeString1,
908  (i < 2) ? i : AUTO_DRIVE,
910  0,
912  hKey,
913  &BootDevice,
914  NtSystemPath);
915  }
916 
917  /* Assign cdrom drives */
918  DPRINT("CD-Rom drives: %lu\n", ConfigInfo->CdRomCount);
919  for (i = 0; i < ConfigInfo->CdRomCount; i++)
920  {
921  swprintf(Buffer1, L"\\Device\\CdRom%lu", i);
922  RtlInitUnicodeString(&UnicodeString1, Buffer1);
923 
924  /* Assign first free drive letter */
925  DPRINT(" %wZ\n", &UnicodeString1);
926  HalpAssignDrive(&UnicodeString1,
927  AUTO_DRIVE,
929  0,
931  hKey,
932  &BootDevice,
933  NtSystemPath);
934  }
935 
936  /* Anything else to do? */
937 
938  ExFreePoolWithTag(PartialInformation, TAG_FILE_SYSTEM);
941  if (hKey) ObCloseHandle(hKey, KernelMode);
942 }
943 
944 #endif
945 
946 /* PRIVATE FUNCTIONS *********************************************************/
947 
948 NTSTATUS
949 NTAPI
951  IN PDISK_GEOMETRY Geometry,
952  OUT PULONGLONG RealSectorCount)
953 {
954  PIRP Irp;
956  PKEVENT Event;
959  PAGED_CODE();
960 
961  /* Allocate a non-paged event */
963  sizeof(KEVENT),
965  if (!Event) return STATUS_INSUFFICIENT_RESOURCES;
966 
967  /* Initialize it */
969 
970  /* Build the IRP */
972  DeviceObject,
973  NULL,
974  0UL,
975  Geometry,
976  sizeof(DISK_GEOMETRY),
977  FALSE,
978  Event,
979  &IoStatusBlock);
980  if (!Irp)
981  {
982  /* Fail, free the event */
985  }
986 
987  /* Call the driver and check if it's pending */
988  Status = IoCallDriver(DeviceObject, Irp);
989  if (Status == STATUS_PENDING)
990  {
991  /* Wait on the driver */
993  Status = IoStatusBlock.Status;
994  }
995 
996  /* Check if the driver returned success */
997  if(NT_SUCCESS(Status))
998  {
999  /* Build another IRP */
1001  DeviceObject,
1002  NULL,
1003  0UL,
1004  &PartitionInfo,
1005  sizeof(PARTITION_INFORMATION),
1006  FALSE,
1007  Event,
1008  &IoStatusBlock);
1009  if (!Irp)
1010  {
1011  /* Fail, free the event */
1014  }
1015 
1016  /* Reset event */
1017  KeClearEvent(Event);
1018 
1019  /* Call the driver and check if it's pending */
1020  Status = IoCallDriver(DeviceObject, Irp);
1021  if (Status == STATUS_PENDING)
1022  {
1023  /* Wait on the driver */
1025  Status = IoStatusBlock.Status;
1026  }
1027 
1028  /* Check if the driver returned success */
1029  if(NT_SUCCESS(Status))
1030  {
1031  /* Get the number of sectors */
1032  *RealSectorCount = (PartitionInfo.PartitionLength.QuadPart /
1033  Geometry->BytesPerSector);
1034  }
1035  }
1036 
1037  /* Free the event and return the Status */
1039  return Status;
1040 }
1041 
1042 BOOLEAN
1043 NTAPI
1045  IN ULONGLONG MaxOffset,
1046  IN ULONGLONG MaxSector)
1047 {
1048  ULONGLONG EndingSector;
1049  PAGED_CODE();
1050 
1051  /* Unused partitions are considered valid */
1052  if (Entry->PartitionType == PARTITION_ENTRY_UNUSED) return TRUE;
1053 
1054  /* Get the last sector of the partition */
1055  EndingSector = GET_STARTING_SECTOR(Entry) + GET_PARTITION_LENGTH(Entry);
1056 
1057  /* Check if it's more then the maximum sector */
1058  if (EndingSector > MaxSector)
1059  {
1060  /* Invalid partition */
1061  DPRINT1("FSTUB: entry is invalid\n");
1062  DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1063  DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1064  DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1065  DPRINT1("FSTUB: max %#I64x\n", MaxSector);
1066  return FALSE;
1067  }
1068  else if(GET_STARTING_SECTOR(Entry) > MaxOffset)
1069  {
1070  /* Invalid partition */
1071  DPRINT1("FSTUB: entry is invalid\n");
1072  DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1073  DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1074  DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1075  DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset);
1076  return FALSE;
1077  }
1078 
1079  /* It's fine, return success */
1080  return TRUE;
1081 }
1082 
1083 VOID
1084 NTAPI
1086  IN PLARGE_INTEGER PartitionLength,
1087  IN CCHAR ShiftCount,
1089  IN ULONG NumberOfTracks,
1090  IN ULONG ConventionalCylinders,
1091  OUT PPARTITION_DESCRIPTOR PartitionDescriptor)
1092 {
1093  LARGE_INTEGER FirstSector, SectorCount;
1094  ULONG LastSector, Remainder, SectorsPerCylinder;
1095  ULONG StartingCylinder, EndingCylinder;
1096  ULONG StartingTrack, EndingTrack;
1097  ULONG StartingSector, EndingSector;
1098  PAGED_CODE();
1099 
1100  /* Calculate the number of sectors for each cylinder */
1101  SectorsPerCylinder = SectorsPerTrack * NumberOfTracks;
1102 
1103  /* Calculate the first sector, and the sector count */
1104  FirstSector.QuadPart = PartitionOffset->QuadPart >> ShiftCount;
1105  SectorCount.QuadPart = PartitionLength->QuadPart >> ShiftCount;
1106 
1107  /* Now calculate the last sector */
1108  LastSector = FirstSector.LowPart + SectorCount.LowPart - 1;
1109 
1110  /* Calculate the first and last cylinders */
1111  StartingCylinder = FirstSector.LowPart / SectorsPerCylinder;
1112  EndingCylinder = LastSector / SectorsPerCylinder;
1113 
1114  /* Set the default number of cylinders */
1115  if (!ConventionalCylinders) ConventionalCylinders = 1024;
1116 
1117  /* Normalize the values */
1118  if (StartingCylinder >= ConventionalCylinders)
1119  {
1120  /* Set the maximum to 1023 */
1121  StartingCylinder = ConventionalCylinders - 1;
1122  }
1123  if (EndingCylinder >= ConventionalCylinders)
1124  {
1125  /* Set the maximum to 1023 */
1126  EndingCylinder = ConventionalCylinders - 1;
1127  }
1128 
1129  /* Calculate the starting head and sector that still remain */
1130  Remainder = FirstSector.LowPart % SectorsPerCylinder;
1131  StartingTrack = Remainder / SectorsPerTrack;
1132  StartingSector = Remainder % SectorsPerTrack;
1133 
1134  /* Calculate the ending head and sector that still remain */
1135  Remainder = LastSector % SectorsPerCylinder;
1136  EndingTrack = Remainder / SectorsPerTrack;
1137  EndingSector = Remainder % SectorsPerTrack;
1138 
1139  /* Set cylinder data for the MSB */
1140  PartitionDescriptor->StartingCylinderMsb = (UCHAR)StartingCylinder;
1141  PartitionDescriptor->EndingCylinderMsb = (UCHAR)EndingCylinder;
1142 
1143  /* Set the track data */
1144  PartitionDescriptor->StartingTrack = (UCHAR)StartingTrack;
1145  PartitionDescriptor->EndingTrack = (UCHAR)EndingTrack;
1146 
1147  /* Update cylinder data for the LSB */
1148  StartingCylinder = ((StartingSector + 1) & 0x3F) |
1149  ((StartingCylinder >> 2) & 0xC0);
1150  EndingCylinder = ((EndingSector + 1) & 0x3F) |
1151  ((EndingCylinder >> 2) & 0xC0);
1152 
1153  /* Set the cylinder data for the LSB */
1154  PartitionDescriptor->StartingCylinderLsb = (UCHAR)StartingCylinder;
1155  PartitionDescriptor->EndingCylinderLsb = (UCHAR)EndingCylinder;
1156 }
1157 
1158 VOID
1159 FASTCALL
1161  IN PULONG ConventionalCylinders,
1162  IN PLONGLONG DiskSize)
1163 {
1164  PDISK_GEOMETRY DiskGeometry = NULL;
1166  PKEVENT Event = NULL;
1167  PIRP Irp;
1168  NTSTATUS Status;
1169 
1170  /* Set defaults */
1171  *ConventionalCylinders = 0;
1172  *DiskSize = 0;
1173 
1174  /* Allocate the structure in nonpaged pool */
1175  DiskGeometry = ExAllocatePoolWithTag(NonPagedPool,
1176  sizeof(DISK_GEOMETRY),
1177  TAG_FILE_SYSTEM);
1178  if (!DiskGeometry) goto Cleanup;
1179 
1180  /* Allocate the status block in nonpaged pool */
1181  IoStatusBlock = ExAllocatePoolWithTag(NonPagedPool,
1182  sizeof(IO_STATUS_BLOCK),
1183  TAG_FILE_SYSTEM);
1184  if (!IoStatusBlock) goto Cleanup;
1185 
1186  /* Allocate the event in nonpaged pool too */
1188  sizeof(KEVENT),
1189  TAG_FILE_SYSTEM);
1190  if (!Event) goto Cleanup;
1191 
1192  /* Initialize the event */
1194 
1195  /* Build the IRP */
1197  DeviceObject,
1198  NULL,
1199  0,
1200  DiskGeometry,
1201  sizeof(DISK_GEOMETRY),
1202  FALSE,
1203  Event,
1204  IoStatusBlock);
1205  if (!Irp) goto Cleanup;
1206 
1207  /* Now call the driver */
1208  Status = IoCallDriver(DeviceObject, Irp);
1209  if (Status == STATUS_PENDING)
1210  {
1211  /* Wait for it to complete */
1213  Status = IoStatusBlock->Status;
1214  }
1215 
1216  /* Check driver status */
1217  if (NT_SUCCESS(Status))
1218  {
1219  /* Return the cylinder count */
1220  *ConventionalCylinders = DiskGeometry->Cylinders.LowPart;
1221 
1222  /* Make sure it's not larger then 1024 */
1223  if (DiskGeometry->Cylinders.LowPart >= 1024)
1224  {
1225  /* Otherwise, normalize the value */
1226  *ConventionalCylinders = 1024;
1227  }
1228 
1229  /* Calculate the disk size */
1230  *DiskSize = DiskGeometry->Cylinders.QuadPart *
1231  DiskGeometry->TracksPerCylinder *
1232  DiskGeometry->SectorsPerTrack *
1233  DiskGeometry->BytesPerSector;
1234  }
1235 
1236 Cleanup:
1237  /* Free all the pointers */
1238  if (Event) ExFreePoolWithTag(Event, TAG_FILE_SYSTEM);
1239  if (IoStatusBlock) ExFreePoolWithTag(IoStatusBlock, TAG_FILE_SYSTEM);
1240  if (DiskGeometry) ExFreePoolWithTag(DiskGeometry, TAG_FILE_SYSTEM);
1241  return;
1242 }
1243 
1244 VOID
1245 FASTCALL
1248  IN ULONG MbrTypeIdentifier,
1249  OUT PVOID *MbrBuffer)
1250 {
1252  PUCHAR Buffer;
1253  ULONG BufferSize;
1254  KEVENT Event;
1256  PIRP Irp;
1257  PPARTITION_DESCRIPTOR PartitionDescriptor;
1258  NTSTATUS Status;
1259  PIO_STACK_LOCATION IoStackLocation;
1260  Offset.QuadPart = 0;
1261 
1262  /* Assume failure */
1263  *MbrBuffer = NULL;
1264 
1265  /* Normalize the buffer size */
1266  BufferSize = max(SectorSize, 512);
1267 
1268  /* Allocate the buffer */
1270  PAGE_SIZE > BufferSize ?
1271  PAGE_SIZE : BufferSize,
1272  TAG_FILE_SYSTEM);
1273  if (!Buffer) return;
1274 
1275  /* Initialize the Event */
1277 
1278  /* Build the IRP */
1280  DeviceObject,
1281  Buffer,
1282  BufferSize,
1283  &Offset,
1284  &Event,
1285  &IoStatusBlock);
1286  if (!Irp)
1287  {
1288  /* Failed */
1290  return;
1291  }
1292 
1293  /* Make sure to override volume verification */
1294  IoStackLocation = IoGetNextIrpStackLocation(Irp);
1295  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1296 
1297  /* Call the driver */
1298  Status = IoCallDriver(DeviceObject, Irp);
1299  if (Status == STATUS_PENDING)
1300  {
1301  /* Wait for completion */
1303  Status = IoStatusBlock.Status;
1304  }
1305 
1306  /* Check driver Status */
1307  if (NT_SUCCESS(Status))
1308  {
1309  /* Validate the MBR Signature */
1311  {
1312  /* Failed */
1314  return;
1315  }
1316 
1317  /* Get the partition entry */
1318  PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1319  &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]);
1320 
1321  /* Make sure it's what the caller wanted */
1322  if (PartitionDescriptor->PartitionType != MbrTypeIdentifier)
1323  {
1324  /* It's not, free our buffer */
1326  }
1327  else
1328  {
1329  /* Check if this is a secondary entry */
1330  if (PartitionDescriptor->PartitionType == 0x54)
1331  {
1332  /* Return our buffer, but at sector 63 */
1333  *(PULONG)Buffer = 63;
1334  *MbrBuffer = Buffer;
1335  }
1336  else if (PartitionDescriptor->PartitionType == 0x55)
1337  {
1338  /* EZ Drive, return the buffer directly */
1339  *MbrBuffer = Buffer;
1340  }
1341  else
1342  {
1343  /* Otherwise crash on debug builds */
1344  ASSERT(PartitionDescriptor->PartitionType == 0x55);
1345  }
1346  }
1347  }
1348 }
1349 
1350 VOID
1351 NTAPI
1353  IN ULONGLONG MaxOffset)
1354 {
1355  ULONG PartitionMaxOffset, PartitionLength;
1356  PAGED_CODE();
1357 
1358  /* Compute partition length (according to MBR entry) */
1359  PartitionMaxOffset = GET_STARTING_SECTOR(PartitionDescriptor) + GET_PARTITION_LENGTH(PartitionDescriptor);
1360  /* In case the partition length goes beyond disk size... */
1361  if (PartitionMaxOffset > MaxOffset)
1362  {
1363  /* Resize partition to its maximum real length */
1364  PartitionLength = (ULONG)(PartitionMaxOffset - GET_STARTING_SECTOR(PartitionDescriptor));
1365  SET_PARTITION_LENGTH(PartitionDescriptor, PartitionLength);
1366  }
1367 }
1368 
1369 NTSTATUS
1370 FASTCALL
1375 {
1376  KEVENT Event;
1378  PIRP Irp;
1379  PPARTITION_DESCRIPTOR PartitionDescriptor;
1380  CCHAR Entry;
1381  NTSTATUS Status;
1383  PUCHAR Buffer = NULL;
1384  ULONG BufferSize = 2048, InputSize;
1385  PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo = NULL;
1386  LONG j = -1, i = -1, k;
1387  DISK_GEOMETRY DiskGeometry;
1388  LONGLONG EndSector, MaxSector, StartOffset;
1389  ULONGLONG MaxOffset;
1390  LARGE_INTEGER Offset, VolumeOffset;
1391  BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE, MbrFound = FALSE;
1392  BOOLEAN IsValid, IsEmpty = TRUE;
1393  PVOID MbrBuffer;
1394  PIO_STACK_LOCATION IoStackLocation;
1395  PBOOT_SECTOR_INFO BootSectorInfo = (PBOOT_SECTOR_INFO)Buffer;
1397  LARGE_INTEGER HiddenSectors64;
1398  VolumeOffset.QuadPart = Offset.QuadPart = 0;
1399  PAGED_CODE();
1400 
1401  /* Allocate the buffer */
1402  *PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool,
1403  BufferSize,
1404  TAG_FILE_SYSTEM);
1405  if (!(*PartitionBuffer)) return STATUS_INSUFFICIENT_RESOURCES;
1406 
1407  /* Normalize the buffer size */
1408  InputSize = max(512, SectorSize);
1409 
1410  /* Check for EZ Drive */
1411  HalExamineMBR(DeviceObject, InputSize, 0x55, &MbrBuffer);
1412  if (MbrBuffer)
1413  {
1414  /* EZ Drive found, bias the offset */
1415  IsEzDrive = TRUE;
1416  ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
1417  Offset.QuadPart = 512;
1418  }
1419 
1420  /* Get drive geometry */
1421  Status = HalpGetFullGeometry(DeviceObject, &DiskGeometry, &MaxOffset);
1422  if (!NT_SUCCESS(Status))
1423  {
1424  ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
1425  *PartitionBuffer = NULL;
1426  return Status;
1427  }
1428 
1429  /* Get the end and maximum sector */
1430  EndSector = MaxOffset;
1431  MaxSector = MaxOffset << 1;
1432  DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n",
1433  MaxOffset, MaxSector);
1434 
1435  /* Allocate our buffer */
1436  Buffer = ExAllocatePoolWithTag(NonPagedPool, InputSize, TAG_FILE_SYSTEM);
1437  if (!Buffer)
1438  {
1439  /* Fail, free the input buffer */
1440  ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
1441  *PartitionBuffer = NULL;
1443  }
1444 
1445  /* Start partition loop */
1446  do
1447  {
1448  /* Assume the partition is valid */
1449  IsValid = TRUE;
1450 
1451  /* Initialize the event */
1453 
1454  /* Clear the buffer and build the IRP */
1455  RtlZeroMemory(Buffer, InputSize);
1457  DeviceObject,
1458  Buffer,
1459  InputSize,
1460  &Offset,
1461  &Event,
1462  &IoStatusBlock);
1463  if (!Irp)
1464  {
1465  /* Failed */
1467  break;
1468  }
1469 
1470  /* Make sure to disable volume verification */
1471  IoStackLocation = IoGetNextIrpStackLocation(Irp);
1472  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1473 
1474  /* Call the driver */
1475  Status = IoCallDriver(DeviceObject, Irp);
1476  if (Status == STATUS_PENDING)
1477  {
1478  /* Wait for completion */
1480  Status = IoStatusBlock.Status;
1481  }
1482 
1483  /* Normalize status code and check for failure */
1484  if (Status == STATUS_NO_DATA_DETECTED) Status = STATUS_SUCCESS;
1485  if (!NT_SUCCESS(Status)) break;
1486 
1487  /* If we biased for EZ-Drive, unbias now */
1488  if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
1489 
1490  /* Make sure this is a valid MBR */
1492  {
1493  /* It's not, fail */
1494  DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1495  "partition table %d\n", j + 1);
1496  break;
1497  }
1498 
1499  /* At this point we have a valid MBR */
1500  MbrFound = TRUE;
1501 
1502  /* Check if we weren't given an offset */
1503  if (!Offset.QuadPart)
1504  {
1505  /* Then read the signature off the disk */
1506  (*PartitionBuffer)->Signature = ((PULONG)Buffer)
1507  [PARTITION_TABLE_OFFSET / 2 - 1];
1508  }
1509 
1510  /* Get the partition descriptor array */
1511  PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1513 
1514  /* Start looping partitions */
1515  j++;
1516  DPRINT("FSTUB: Partition Table %d:\n", j);
1517  for (Entry = 1, k = 0; Entry <= 4; Entry++, PartitionDescriptor++)
1518  {
1519  /* Get the partition type */
1520  PartitionType = PartitionDescriptor->PartitionType;
1521 
1522  /* Print debug messages */
1523  DPRINT("Partition Entry %d,%d: type %#x %s\n",
1524  j,
1525  Entry,
1526  PartitionType,
1527  (PartitionDescriptor->ActiveFlag) ? "Active" : "");
1528  DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1529  GET_STARTING_SECTOR(PartitionDescriptor),
1530  GET_PARTITION_LENGTH(PartitionDescriptor));
1531 
1532  /* Check whether we're facing a protective MBR */
1533  if (PartitionType == EFI_PMBR_OSTYPE_EFI)
1534  {
1535  /* Partition length might be bigger than disk size */
1536  FstubFixupEfiPartition(PartitionDescriptor,
1537  MaxOffset);
1538  }
1539 
1540  /* Make sure that the partition is valid, unless it's the first */
1541  if (!(HalpIsValidPartitionEntry(PartitionDescriptor,
1542  MaxOffset,
1543  MaxSector)) && !(j))
1544  {
1545  /* It's invalid, so fail */
1546  IsValid = FALSE;
1547  break;
1548  }
1549 
1550  /* Check if it's a container */
1551  if (IsContainerPartition(PartitionType))
1552  {
1553  /* Increase the count of containers */
1554  if (++k != 1)
1555  {
1556  /* More then one table is invalid */
1557  DPRINT1("FSTUB: Multiple container partitions found in "
1558  "partition table %d\n - table is invalid\n",
1559  j);
1560  IsValid = FALSE;
1561  break;
1562  }
1563  }
1564 
1565  /* Check if the partition is supposedly empty */
1566  if (IsEmpty)
1567  {
1568  /* But check if it actually has a start and/or length */
1569  if ((GET_STARTING_SECTOR(PartitionDescriptor)) ||
1570  (GET_PARTITION_LENGTH(PartitionDescriptor)))
1571  {
1572  /* So then it's not really empty */
1573  IsEmpty = FALSE;
1574  }
1575  }
1576 
1577  /* Check if the caller wanted only recognized partitions */
1578  if (ReturnRecognizedPartitions)
1579  {
1580  /* Then check if this one is unused, or a container */
1581  if ((PartitionType == PARTITION_ENTRY_UNUSED) ||
1582  IsContainerPartition(PartitionType))
1583  {
1584  /* Skip it, since the caller doesn't want it */
1585  continue;
1586  }
1587  }
1588 
1589  /* Increase the structure count and check if they can fit */
1590  if ((sizeof(DRIVE_LAYOUT_INFORMATION) +
1591  (++i * sizeof(PARTITION_INFORMATION))) >
1592  BufferSize)
1593  {
1594  /* Allocate a new buffer that's twice as big */
1595  DriveLayoutInfo = ExAllocatePoolWithTag(NonPagedPool,
1596  BufferSize << 1,
1597  TAG_FILE_SYSTEM);
1598  if (!DriveLayoutInfo)
1599  {
1600  /* Out of memory, unto this extra structure */
1601  --i;
1603  break;
1604  }
1605 
1606  /* Copy the contents of the old buffer */
1607  RtlMoveMemory(DriveLayoutInfo,
1608  *PartitionBuffer,
1609  BufferSize);
1610 
1611  /* Free the old buffer and set this one as the new one */
1612  ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
1613  *PartitionBuffer = DriveLayoutInfo;
1614 
1615  /* Double the size */
1616  BufferSize <<= 1;
1617  }
1618 
1619  /* Now get the current structure being filled and initialize it */
1620  PartitionInfo = &(*PartitionBuffer)->PartitionEntry[i];
1621  PartitionInfo->PartitionType = PartitionType;
1622  PartitionInfo->RewritePartition = FALSE;
1623 
1624  /* Check if we're dealing with a partition that's in use */
1625  if (PartitionType != PARTITION_ENTRY_UNUSED)
1626  {
1627  /* Check if it's bootable */
1628  PartitionInfo->BootIndicator = PartitionDescriptor->
1629  ActiveFlag & 0x80 ?
1630  TRUE : FALSE;
1631 
1632  /* Check if its' a container */
1633  if (IsContainerPartition(PartitionType))
1634  {
1635  /* Then don't recognize it and use the volume offset */
1636  PartitionInfo->RecognizedPartition = FALSE;
1637  StartOffset = VolumeOffset.QuadPart;
1638  }
1639  else
1640  {
1641  /* Then recognize it and use the partition offset */
1642  PartitionInfo->RecognizedPartition = TRUE;
1643  StartOffset = Offset.QuadPart;
1644  }
1645 
1646  /* Get the starting offset */
1647  PartitionInfo->StartingOffset.QuadPart =
1648  StartOffset +
1649  UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor),
1650  SectorSize);
1651 
1652  /* Calculate the number of hidden sectors */
1653  HiddenSectors64.QuadPart = (PartitionInfo->
1654  StartingOffset.QuadPart -
1655  StartOffset) /
1656  SectorSize;
1657  PartitionInfo->HiddenSectors = HiddenSectors64.LowPart;
1658 
1659  /* Get the partition length */
1660  PartitionInfo->PartitionLength.QuadPart =
1661  UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor),
1662  SectorSize);
1663 
1664  /* Get the partition number */
1665  PartitionInfo->PartitionNumber = (!IsContainerPartition(PartitionType)) ? i + 1 : 0;
1666  }
1667  else
1668  {
1669  /* Otherwise, clear all the relevant fields */
1670  PartitionInfo->BootIndicator = FALSE;
1671  PartitionInfo->RecognizedPartition = FALSE;
1672  PartitionInfo->StartingOffset.QuadPart = 0;
1673  PartitionInfo->PartitionLength.QuadPart = 0;
1674  PartitionInfo->HiddenSectors = 0;
1675 
1676  PartitionInfo->PartitionNumber = 0;
1677  }
1678  }
1679 
1680  /* Finish debug log, and check for failure */
1681  DPRINT("\n");
1682  if (!NT_SUCCESS(Status)) break;
1683 
1684  /* Also check if we hit an invalid entry here */
1685  if (!IsValid)
1686  {
1687  /* We did, so break out of the loop minus one entry */
1688  j--;
1689  break;
1690  }
1691 
1692  /* Reset the offset */
1693  Offset.QuadPart = 0;
1694 
1695  /* Go back to the descriptor array and loop it */
1696  PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1697  &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]);
1698  for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++)
1699  {
1700  /* Check if this is a container partition, since we skipped them */
1701  if (IsContainerPartition(PartitionDescriptor->PartitionType))
1702  {
1703  /* Get its offset */
1704  Offset.QuadPart = VolumeOffset.QuadPart +
1705  UInt32x32To64(
1706  GET_STARTING_SECTOR(PartitionDescriptor),
1707  SectorSize);
1708 
1709  /* If this is a primary partition, this is the volume offset */
1710  if (IsPrimary) VolumeOffset = Offset;
1711 
1712  /* Also update the maximum sector */
1713  MaxSector = GET_PARTITION_LENGTH(PartitionDescriptor);
1714  DPRINT1("FSTUB: MaxSector now = %I64d\n", MaxSector);
1715  break;
1716  }
1717  }
1718 
1719  /* Loop the next partitions, which are not primary anymore */
1720  IsPrimary = FALSE;
1721  } while (Offset.HighPart | Offset.LowPart);
1722 
1723  /* Check if this is a removable device that's probably a super-floppy */
1724  if ((DiskGeometry.MediaType == RemovableMedia) &&
1725  !(j) &&
1726  (MbrFound) &&
1727  (IsEmpty))
1728  {
1729  /* Read the jump bytes to detect super-floppy */
1730  if ((BootSectorInfo->JumpByte[0] == 0xeb) ||
1731  (BootSectorInfo->JumpByte[0] == 0xe9))
1732  {
1733  /* Super floppes don't have typical MBRs, so skip them */
1734  DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
1735  "table - disk is a super floppy and has no valid MBR\n",
1736  BootSectorInfo->JumpByte);
1737  j = -1;
1738  }
1739  }
1740 
1741  /* Check if we're still at partition -1 */
1742  if (j == -1)
1743  {
1744  /* The likely cause is the super floppy detection above */
1745  if ((MbrFound) || (DiskGeometry.MediaType == RemovableMedia))
1746  {
1747  /* Print out debugging information */
1748  DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
1749  "super-floppy\n",
1750  DeviceObject);
1751  DPRINT1("FSTUB: Drive has %I64d sectors and is %#016I64x "
1752  "bytes large\n",
1753  EndSector, EndSector * DiskGeometry.BytesPerSector);
1754 
1755  /* We should at least have some sectors */
1756  if (EndSector > 0)
1757  {
1758  /* Get the entry we'll use */
1759  PartitionInfo = &(*PartitionBuffer)->PartitionEntry[0];
1760 
1761  /* Fill it out with data for a super-floppy */
1762  PartitionInfo->RewritePartition = FALSE;
1763  PartitionInfo->RecognizedPartition = TRUE;
1764  PartitionInfo->PartitionType = PARTITION_FAT_16;
1765  PartitionInfo->BootIndicator = FALSE;
1766  PartitionInfo->HiddenSectors = 0;
1767  PartitionInfo->StartingOffset.QuadPart = 0;
1768  PartitionInfo->PartitionLength.QuadPart = (EndSector *
1769  DiskGeometry.
1770  BytesPerSector);
1771 
1772  /* FIXME: REACTOS HACK */
1773  PartitionInfo->PartitionNumber = 0;
1774 
1775  /* Set the signature and set the count back to 0 */
1776  (*PartitionBuffer)->Signature = 1;
1777  i = 0;
1778  }
1779  }
1780  else
1781  {
1782  /* Otherwise, this isn't a super floppy, so set an invalid count */
1783  i = -1;
1784  }
1785  }
1786 
1787  /* Set the partition count */
1788  (*PartitionBuffer)->PartitionCount = ++i;
1789 
1790  /* If we have no count, delete the signature */
1791  if (!i) (*PartitionBuffer)->Signature = 0;
1792 
1793  /* Free the buffer and check for success */
1794  if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
1795  if (!NT_SUCCESS(Status))
1796  {
1797  ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
1798  *PartitionBuffer = NULL;
1799  }
1800 
1801  /* Return status */
1802  return Status;
1803 }
1804 
1805 NTSTATUS
1806 FASTCALL
1811 {
1812  PIRP Irp;
1813  KEVENT Event;
1815  NTSTATUS Status;
1816  LARGE_INTEGER Offset, VolumeOffset;
1817  PUCHAR Buffer = NULL;
1818  ULONG BufferSize;
1819  ULONG i = 0;
1820  ULONG Entry;
1821  PPARTITION_DESCRIPTOR PartitionDescriptor;
1822  BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE;
1823  PVOID MbrBuffer;
1824  PIO_STACK_LOCATION IoStackLocation;
1825  VolumeOffset.QuadPart = Offset.QuadPart = 0;
1826  PAGED_CODE();
1827 
1828  /* Normalize the buffer size */
1829  BufferSize = max(512, SectorSize);
1830 
1831  /* Check for EZ Drive */
1832  HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer);
1833  if (MbrBuffer)
1834  {
1835  /* EZ Drive found, bias the offset */
1836  IsEzDrive = TRUE;
1837  ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
1838  Offset.QuadPart = 512;
1839  }
1840 
1841  /* Allocate our partition buffer */
1843  if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
1844 
1845  /* Initialize the event we'll use and loop partitions */
1847  do
1848  {
1849  /* Reset the event since we reuse it */
1850  KeClearEvent(&Event);
1851 
1852  /* Build the read IRP */
1854  DeviceObject,
1855  Buffer,
1856  BufferSize,
1857  &Offset,
1858  &Event,
1859  &IoStatusBlock);
1860  if (!Irp)
1861  {
1862  /* Fail */
1864  break;
1865  }
1866 
1867  /* Make sure to disable volume verification */
1868  IoStackLocation = IoGetNextIrpStackLocation(Irp);
1869  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1870 
1871  /* Call the driver */
1872  Status = IoCallDriver(DeviceObject, Irp);
1873  if (Status == STATUS_PENDING)
1874  {
1875  /* Wait for completion */
1877  Status = IoStatusBlock.Status;
1878  }
1879 
1880  /* Check for failure */
1881  if (!NT_SUCCESS(Status)) break;
1882 
1883  /* If we biased for EZ-Drive, unbias now */
1884  if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
1885 
1886  /* Make sure this is a valid MBR */
1888  {
1889  /* It's not, fail */
1891  break;
1892  }
1893 
1894  /* Get the partition descriptors and loop them */
1895  PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1896  &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]);
1897  for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++)
1898  {
1899  /* Check if it's unused or a container partition */
1900  if ((PartitionDescriptor->PartitionType ==
1902  (IsContainerPartition(PartitionDescriptor->PartitionType)))
1903  {
1904  /* Go to the next one */
1905  continue;
1906  }
1907 
1908  /* It's a valid partition, so increase the partition count */
1909  if (++i == PartitionNumber)
1910  {
1911  /* We found a match, set the type */
1912  PartitionDescriptor->PartitionType = (UCHAR)PartitionType;
1913 
1914  /* Reset the reusable event */
1915  KeClearEvent(&Event);
1916 
1917  /* Build the write IRP */
1919  DeviceObject,
1920  Buffer,
1921  BufferSize,
1922  &Offset,
1923  &Event,
1924  &IoStatusBlock);
1925  if (!Irp)
1926  {
1927  /* Fail */
1929  break;
1930  }
1931 
1932  /* Disable volume verification */
1933  IoStackLocation = IoGetNextIrpStackLocation(Irp);
1934  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1935 
1936  /* Call the driver */
1937  Status = IoCallDriver(DeviceObject, Irp);
1938  if (Status == STATUS_PENDING)
1939  {
1940  /* Wait for completion */
1941  KeWaitForSingleObject(&Event,
1942  Executive,
1943  KernelMode,
1944  FALSE,
1945  NULL);
1946  Status = IoStatusBlock.Status;
1947  }
1948 
1949  /* We're done, break out of the loop */
1950  break;
1951  }
1952  }
1953 
1954  /* If we looped all the partitions, break out */
1955  if (Entry <= NUM_PARTITION_TABLE_ENTRIES) break;
1956 
1957  /* Nothing found yet, get the partition array again */
1958  PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1959  &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]);
1960  for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++)
1961  {
1962  /* Check if this was a container partition (we skipped these) */
1963  if (IsContainerPartition(PartitionDescriptor->PartitionType))
1964  {
1965  /* Update the partition offset */
1966  Offset.QuadPart = VolumeOffset.QuadPart +
1967  GET_STARTING_SECTOR(PartitionDescriptor) *
1968  SectorSize;
1969 
1970  /* If this was the primary partition, update the volume too */
1971  if (IsPrimary) VolumeOffset = Offset;
1972  break;
1973  }
1974  }
1975 
1976  /* Check if we already searched all the partitions */
1977  if (Entry > NUM_PARTITION_TABLE_ENTRIES)
1978  {
1979  /* Then we failed to find a good MBR */
1981  break;
1982  }
1983 
1984  /* Loop the next partitions, which are not primary anymore */
1985  IsPrimary = FALSE;
1986  } while (i < PartitionNumber);
1987 
1988  /* Everything done, cleanup */
1989  if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
1990  return Status;
1991 }
1992 
1993 NTSTATUS
1994 FASTCALL
2000 {
2001  KEVENT Event;
2003  PIRP Irp;
2005  ULONG BufferSize;
2006  PUSHORT Buffer;
2007  PPTE Entry;
2008  PPARTITION_TABLE PartitionTable;
2009  LARGE_INTEGER Offset, NextOffset, ExtendedOffset, SectorOffset;
2010  LARGE_INTEGER StartOffset, PartitionLength;
2011  ULONG i, j;
2012  CCHAR k;
2013  BOOLEAN IsEzDrive = FALSE, IsSuperFloppy = FALSE, DoRewrite = FALSE, IsMbr;
2014  ULONG ConventionalCylinders;
2015  LONGLONG DiskSize;
2016  PDISK_LAYOUT DiskLayout = (PDISK_LAYOUT)PartitionBuffer;
2017  PVOID MbrBuffer;
2019  PIO_STACK_LOCATION IoStackLocation;
2020  PPARTITION_INFORMATION PartitionInfo = PartitionBuffer->PartitionEntry;
2022  ExtendedOffset.QuadPart = NextOffset.QuadPart = Offset.QuadPart = 0;
2023  PAGED_CODE();
2024 
2025  /* Normalize the buffer size */
2026  BufferSize = max(512, SectorSize);
2027 
2028  /* Get the partial drive geometry */
2029  xHalGetPartialGeometry(DeviceObject, &ConventionalCylinders, &DiskSize);
2030 
2031  /* Check for EZ Drive */
2032  HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer);
2033  if (MbrBuffer)
2034  {
2035  /* EZ Drive found, bias the offset */
2036  IsEzDrive = TRUE;
2037  ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
2038  Offset.QuadPart = 512;
2039  }
2040 
2041  /* Get the number of bits to shift to multiply by the sector size */
2042  for (k = 0; k < 32; k++) if ((SectorSize >> k) == 1) break;
2043 
2044  /* Check if there's only one partition */
2045  if (PartitionBuffer->PartitionCount == 1)
2046  {
2047  /* Check if it has no starting offset or hidden sectors */
2048  if (!(PartitionInfo->StartingOffset.QuadPart) &&
2049  !(PartitionInfo->HiddenSectors))
2050  {
2051  /* Then it's a super floppy */
2052  IsSuperFloppy = TRUE;
2053 
2054  /* Which also means it must be non-bootable FAT-16 */
2055  if ((PartitionInfo->PartitionNumber) ||
2056  (PartitionInfo->PartitionType != PARTITION_FAT_16) ||
2057  (PartitionInfo->BootIndicator))
2058  {
2059  /* It's not, so we fail */
2060  return STATUS_INVALID_PARAMETER;
2061  }
2062 
2063  /* Check if it needs a rewrite, and disable EZ drive for sure */
2064  if (PartitionInfo->RewritePartition) DoRewrite = TRUE;
2065  IsEzDrive = FALSE;
2066  }
2067  }
2068 
2069  /* Count the number of partition tables */
2070  DiskLayout->TableCount = (PartitionBuffer->PartitionCount + 4 - 1) / 4;
2071 
2072  /* Allocate our partition buffer */
2074  if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
2075 
2076  /* Loop the entries */
2077  Entry = (PPTE)&Buffer[PARTITION_TABLE_OFFSET];
2078  for (i = 0; i < DiskLayout->TableCount; i++)
2079  {
2080  /* Set if this is the MBR partition */
2081  IsMbr= (BOOLEAN)!i;
2082 
2083  /* Initialize th event */
2085 
2086  /* Build the read IRP */
2088  DeviceObject,
2089  Buffer,
2090  BufferSize,
2091  &Offset,
2092  &Event,
2093  &IoStatusBlock);
2094  if (!Irp)
2095  {
2096  /* Fail */
2098  break;
2099  }
2100 
2101  /* Make sure to disable volume verification */
2102  IoStackLocation = IoGetNextIrpStackLocation(Irp);
2103  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2104 
2105  /* Call the driver */
2106  Status = IoCallDriver(DeviceObject, Irp);
2107  if (Status == STATUS_PENDING)
2108  {
2109  /* Wait for completion */
2111  Status = IoStatusBlock.Status;
2112  }
2113 
2114  /* Check for failure */
2115  if (!NT_SUCCESS(Status)) break;
2116 
2117  /* If we biased for EZ-Drive, unbias now */
2118  if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2119 
2120  /* Check if this is a normal disk */
2121  if (!IsSuperFloppy)
2122  {
2123  /* Set the boot record signature */
2125 
2126  /* By default, don't require a rewrite */
2127  DoRewrite = FALSE;
2128 
2129  /* Check if we don't have an offset */
2130  if (!Offset.QuadPart)
2131  {
2132  /* Check if the signature doesn't match */
2133  if (((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] !=
2134  PartitionBuffer->Signature)
2135  {
2136  /* Then write the signature and now w need a rewrite */
2137  ((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] =
2138  PartitionBuffer->Signature;
2139  DoRewrite = TRUE;
2140  }
2141  }
2142 
2143  /* Loop the partition table entries */
2144  PartitionTable = &DiskLayout->PartitionTable[i];
2145  for (j = 0; j < 4; j++)
2146  {
2147  /* Get the current entry and type */
2148  TableEntry = &PartitionTable->PartitionEntry[j];
2149  PartitionType = TableEntry->PartitionType;
2150 
2151  /* Check if the entry needs a rewrite */
2152  if (TableEntry->RewritePartition)
2153  {
2154  /* Then we need one too */
2155  DoRewrite = TRUE;
2156 
2157  /* Save the type and if it's a bootable partition */
2158  Entry[j].PartitionType = TableEntry->PartitionType;
2159  Entry[j].ActiveFlag = TableEntry->BootIndicator ? 0x80 : 0;
2160 
2161  /* Make sure it's used */
2162  if (PartitionType != PARTITION_ENTRY_UNUSED)
2163  {
2164  /* Make sure it's not a container (unless primary) */
2165  if ((IsMbr) || !(IsContainerPartition(PartitionType)))
2166  {
2167  /* Use the partition offset */
2168  StartOffset.QuadPart = Offset.QuadPart;
2169  }
2170  else
2171  {
2172  /* Use the extended logical partition offset */
2173  StartOffset.QuadPart = ExtendedOffset.QuadPart;
2174  }
2175 
2176  /* Set the sector offset */
2177  SectorOffset.QuadPart = TableEntry->
2178  StartingOffset.QuadPart -
2179  StartOffset.QuadPart;
2180 
2181  /* Now calculate the starting sector */
2182  StartOffset.QuadPart = SectorOffset.QuadPart >> k;
2183  Entry[j].StartingSector = StartOffset.LowPart;
2184 
2185  /* As well as the length */
2186  PartitionLength.QuadPart = TableEntry->PartitionLength.
2187  QuadPart >> k;
2188  Entry[j].PartitionLength = PartitionLength.LowPart;
2189 
2190  /* Calculate the CHS values */
2192  &TableEntry->PartitionLength,
2193  k,
2194  SectorsPerTrack,
2195  NumberOfHeads,
2196  ConventionalCylinders,
2198  &Entry[j]);
2199  }
2200  else
2201  {
2202  /* Otherwise set up an empty entry */
2203  Entry[j].StartingSector = 0;
2204  Entry[j].PartitionLength = 0;
2205  Entry[j].StartingTrack = 0;
2206  Entry[j].EndingTrack = 0;
2207  Entry[j].StartingCylinder = 0;
2208  Entry[j].EndingCylinder = 0;
2209  }
2210  }
2211 
2212  /* Check if this is a container partition */
2213  if (IsContainerPartition(PartitionType))
2214  {
2215  /* Then update the offset to use */
2216  NextOffset = TableEntry->StartingOffset;
2217  }
2218  }
2219  }
2220 
2221  /* Check if we need to write back the buffer */
2222  if (DoRewrite)
2223  {
2224  /* We don't need to do this again */
2225  DoRewrite = FALSE;
2226 
2227  /* Initialize the event */
2229 
2230  /* If we unbiased for EZ-Drive, rebias now */
2231  if ((IsEzDrive) && !(Offset.QuadPart)) Offset.QuadPart = 512;
2232 
2233  /* Build the write IRP */
2235  DeviceObject,
2236  Buffer,
2237  BufferSize,
2238  &Offset,
2239  &Event,
2240  &IoStatusBlock);
2241  if (!Irp)
2242  {
2243  /* Fail */
2245  break;
2246  }
2247 
2248  /* Make sure to disable volume verification */
2249  IoStackLocation = IoGetNextIrpStackLocation(Irp);
2250  IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2251 
2252  /* Call the driver */
2253  Status = IoCallDriver(DeviceObject, Irp);
2254  if (Status == STATUS_PENDING)
2255  {
2256  /* Wait for completion */
2257  KeWaitForSingleObject(&Event,
2258  Executive,
2259  KernelMode,
2260  FALSE,
2261  NULL);
2262  Status = IoStatusBlock.Status;
2263  }
2264 
2265  /* Check for failure */
2266  if (!NT_SUCCESS(Status)) break;
2267 
2268  /* If we biased for EZ-Drive, unbias now */
2269  if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2270  }
2271 
2272  /* Update the partition offset and set the extended offset if needed */
2273  Offset = NextOffset;
2274  if (IsMbr) ExtendedOffset = NextOffset;
2275  }
2276 
2277  /* If we had a buffer, free it, then return status */
2278  if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
2279  return Status;
2280 }
2281 
2282 /* PUBLIC FUNCTIONS **********************************************************/
2283 
2284 /*
2285  * @implemented
2286  */
2287 VOID
2288 FASTCALL
2291  IN ULONG MbrTypeIdentifier,
2292  OUT PVOID *MbrBuffer)
2293 {
2294  HALDISPATCH->HalExamineMBR(DeviceObject,
2295  SectorSize,
2296  MbrTypeIdentifier,
2297  MbrBuffer);
2298 }
2299 
2300 /*
2301  * @implemented
2302  */
2303 NTSTATUS
2304 FASTCALL
2309 {
2310  return HALDISPATCH->HalIoReadPartitionTable(DeviceObject,
2311  SectorSize,
2312  ReturnRecognizedPartitions,
2313  PartitionBuffer);
2314 }
2315 
2316 /*
2317  * @implemented
2318  */
2319 NTSTATUS
2320 FASTCALL
2325 {
2326  return HALDISPATCH->HalIoSetPartitionInformation(DeviceObject,
2327  SectorSize,
2328  PartitionNumber,
2329  PartitionType);
2330 }
2331 
2332 /*
2333  * @implemented
2334  */
2335 NTSTATUS
2336 FASTCALL
2342 {
2343  return HALDISPATCH->HalIoWritePartitionTable(DeviceObject,
2344  SectorSize,
2345  SectorsPerTrack,
2346  NumberOfHeads,
2347  PartitionBuffer);
2348 }
2349 
2350 /*
2351  * @implemented
2352  */
2353 VOID
2354 FASTCALL
2356  IN PSTRING NtDeviceName,
2357  OUT PUCHAR NtSystemPath,
2358  OUT PSTRING NtSystemPathString)
2359 {
2360  HALDISPATCH->HalIoAssignDriveLetters(LoaderBlock,
2361  NtDeviceName,
2362  NtSystemPath,
2363  NtSystemPathString);
2364 }
2365 
2366 /* EOF */
DWORD *typedef PVOID
Definition: winlogon.h:52
IN CINT OUT PVOID IN ULONG OUT PULONG ResultLength
Definition: conport.c:47
NTSTATUS FASTCALL IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: disksup.c:2321
#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
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
#define TRUE
Definition: types.h:120
LARGE_INTEGER StartingOffset
Definition: partlist.c:24
#define GET_STARTING_SECTOR(p)
Definition: hal.h:252
LARGE_INTEGER PartitionLength
Definition: ntdddisk.h:391
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define EFI_PMBR_OSTYPE_EFI
Definition: disksup.c:27
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:282
struct _Entry Entry
Definition: kefuncs.h:640
Definition: hal.h:331
#define DbgPrint
Definition: loader.c:25
struct _PTE * PPTE
USHORT MaximumLength
Definition: env_spec_w32.h:370
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
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
USHORT StartingCylinder
Definition: hal.h:335
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Definition: iorsrce.c:830
#define REG_BINARY
Definition: nt_native.h:1496
_In_ PIRP Irp
Definition: csq.h:116
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
__wchar_t WCHAR
Definition: xmlstorage.h:180
UCHAR JumpByte[1]
Definition: hal.h:301
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
return STATUS_SUCCESS
Definition: btrfs.c:2690
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:1085
unsigned char * PUCHAR
Definition: retypes.h:3
#define iswdigit(_c)
Definition: ctype.h:667
Definition: bl.h:252
#define DOSDEVICE_DRIVE_CDROM
Definition: obtypes.h:168
#define STATUS_BAD_MASTER_BOOT_RECORD
Definition: ntstatus.h:391
#define PARTITION_TABLE_OFFSET
Definition: hal.h:243
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
ULONG xHalpGetRDiskCount(VOID)
Definition: disksup.c:147
PVOID *typedef PWSTR
Definition: winlogon.h:57
static HANDLE DirectoryHandle
Definition: ObType.c:48
NTSYSAPI NTSTATUS NTAPI ZwOpenDirectoryObject(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
UINT DriveType
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1208
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:245
ULONG BytesPerSector
Definition: ntdddisk.h:373
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
ULONG TracksPerCylinder
Definition: ntdddisk.h:371
uint16_t * PWCHAR
Definition: typedefs.h:54
_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
#define WCHAR
Definition: msvc.h:43
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 BufferSize
Definition: acefiex.h:377
#define SYMBOLIC_LINK_ALL_ACCESS
Definition: nt_native.h:1267
struct _LARGE_INTEGER::@2136 u
#define SET_PARTITION_LENGTH(p, l)
Definition: hal.h:267
struct _DISK_LAYOUT * PDISK_LAYOUT
#define PAGED_CODE()
Definition: video.h:57
#define FILE_SHARE_READ
Definition: compat.h:125
PARTITION_INFORMATION PartitionEntry[4]
Definition: hal.h:318
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
struct _REG_DISK_MOUNT_INFO REG_DISK_MOUNT_INFO
VOID FASTCALL xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG MbrTypeIdentifier, OUT PVOID *MbrBuffer)
Definition: disksup.c:1246
ACPI_EFI_EVENT Event
Definition: acefiex.h:633
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:86
UCHAR StartingTrack
Definition: hal.h:334
ULONG DriveMap
Definition: obtypes.h:528
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:389
WCHAR First[]
Definition: FormatMessage.c:11
UCHAR PartitionType
Definition: hal.h:336
#define DOSDEVICE_DRIVE_REMOVABLE
Definition: obtypes.h:165
GLenum GLclampf GLint i
Definition: glfuncs.h:14
ULONG StartingSector
Definition: hal.h:339
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 FALSE
Definition: types.h:117
struct _REG_DISK_MOUNT_INFO * PREG_DISK_MOUNT_INFO
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:415
#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:1807
UINTN * BufferSize
Definition: acefiex.h:370
_In_ ULONG _In_ BOOLEAN _Out_ struct _DRIVE_LAYOUT_INFORMATION ** PartitionBuffer
Definition: iofuncs.h:2048
#define SectorOffset(L)
Definition: cdprocs.h:1632
#define AUTO_DRIVE
Definition: disksup.c:23
smooth NULL
Definition: ftsmooth.c:416
PARTITION_INFORMATION PartitionEntry[1]
Definition: ntdddisk.h:464
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1774
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
NTSTATUS NTAPI HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject, IN PDISK_GEOMETRY Geometry, OUT PULONGLONG RealSectorCount)
Definition: disksup.c:950
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
int64_t LONGLONG
Definition: typedefs.h:66
#define GET_PARTITION_LENGTH(p)
Definition: hal.h:261
unsigned char BOOLEAN
NTSTATUS FASTCALL IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: disksup.c:2305
_DISK_MANAGER
Definition: disksup.c:39
NTSTATUS FASTCALL xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: disksup.c:1371
LONG NTSTATUS
Definition: precomp.h:26
#define DOSDEVICE_DRIVE_FIXED
Definition: obtypes.h:166
#define BOOT_RECORD_SIGNATURE
Definition: parttest.c:17
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define STATUS_PENDING
Definition: ntstatus.h:82
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:390
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:369
ULONG SectorsPerTrack
Definition: ntdddisk.h:372
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:271
USHORT EndingCylinder
Definition: hal.h:338
#define swprintf(buf, format,...)
Definition: sprintf.c:56
struct _PARTITION_DESCRIPTOR * PPARTITION_DESCRIPTOR
unsigned short * PUSHORT
Definition: retypes.h:2
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2101
MEDIA_TYPE MediaType
Definition: ntdddisk.h:370
PARTITION_TABLE PartitionTable[1]
Definition: hal.h:325
#define PARTITION_FAT_16
Definition: disk.h:90
static BOOLEAN HalpAssignDrive(IN PUNICODE_STRING PartitionName, IN ULONG DriveNumber, IN UCHAR DriveType, IN ULONG Signature, IN LARGE_INTEGER StartingOffset, IN HANDLE hKey, IN PUNICODE_STRING BootDevice, OUT PUCHAR NtSystemPath)
Definition: disksup.c:47
VOID NTAPI FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor, IN ULONGLONG MaxOffset)
Definition: disksup.c:1352
* PFILE_OBJECT
Definition: iotypes.h:1949
UINTN VOID * Buffer
Definition: acefiex.h:370
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
BOOLEAN RewritePartition
Definition: ntdddisk.h:397
_In_ PUNICODE_STRING Name
Definition: mrx.h:218
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)
unsigned char UCHAR
Definition: xmlstorage.h:181
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3369
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:88
static const WCHAR L[]
Definition: oid.c:1087
BOOLEAN NTAPI HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry, IN ULONGLONG MaxOffset, IN ULONGLONG MaxSector)
Definition: disksup.c:1044
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
VOID UINTN Length
Definition: acefiex.h:744
NTSTATUS FASTCALL xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: disksup.c:1995
_In_ ULONG _In_ BOOLEAN ReturnRecognizedPartitions
Definition: iofuncs.h:2046
NTSYSAPI LONGLONG WINAPI RtlConvertLongToLargeInteger(LONG)
Definition: largeint.c:31
#define BOOT_SIGNATURE_OFFSET
Definition: hal.h:244
ULONG LowPart
Definition: typedefs.h:104
#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
PDEVICE_MAP ObSystemDeviceMap
Definition: obinit.c:46
ULONG SectorCount
Definition: part_xbox.c:32
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
UCHAR ActiveFlag
Definition: hal.h:278
Status
Definition: gdiplustypes.h:24
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
VOID FASTCALL xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject, IN PULONG ConventionalCylinders, IN PLONGLONG DiskSize)
Definition: disksup.c:1160
static HANDLE FileHandle
Definition: cabinet.c:48
DWORD *typedef HANDLE
Definition: winlogon.h:52
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
UCHAR EndingTrack
Definition: hal.h:337
ULONG PartitionLength
Definition: hal.h:340
UCHAR ActiveFlag
Definition: hal.h:333
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define DIRECTORY_ALL_ACCESS
Definition: nt_native.h:1259
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:21
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
NTSTATUS xHalpGetDiskNumberFromRDisk(ULONG RDisk, PULONG DiskNumber)
Definition: disksup.c:234
VOID FASTCALL IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PSTRING NtDeviceName, OUT PUCHAR NtSystemPath, OUT PSTRING NtSystemPathString)
Definition: disksup.c:2355
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:3914
#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 PartitionType
Definition: part_xbox.c:33
PVOID PIRP
Definition: usb.h:38
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
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:2289
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
BOOLEAN RecognizedPartition
Definition: ntdddisk.h:396
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_In_ ULONG SectorSize
Definition: halfuncs.h:291
return Found
Definition: dirsup.c:1270
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
KGUARDED_MUTEX ObpDeviceMapLock
Definition: oblife.c:24
IN PVOID IN PVOID IN PCHAR IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
Definition: srb.h:462
static const WCHAR Signature[]
Definition: parser.c:141
static DISK_MOUNT_INFO DiskMountInfo[MAX_DISK_TYPE]
Definition: disk.c:478
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define UInt32x32To64(a, b)
Definition: intsafe.h:258
#define UL
Definition: tui.h:70
int k
Definition: mpi.c:3369
NTSTATUS FASTCALL IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: disksup.c:2337
#define HALDISPATCH
Definition: haltypes.h:278
base of all file and directory entries
Definition: entries.h:82
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
struct _BOOT_SECTOR_INFO * PBOOT_SECTOR_INFO
NTSYSAPI NTSTATUS NTAPI ZwOpenSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
LONGLONG QuadPart
Definition: typedefs.h:112
_In_ LARGE_INTEGER _Out_opt_ PLARGE_INTEGER Remainder
Definition: rtlfuncs.h:3046
NTSTATUS FASTCALL xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName, OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
Definition: disksup.c:306