- Assign first the partitions to drive letters, which have a registry entry in Mounte...
[reactos.git] / reactos / ntoskrnl / io / disk.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/disk.c
5 * PURPOSE: I/O Support for Hal Disk (Partition Table/MBR) Routines.
6 *
7 * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
8 * Casper S. Hornstrup (chorns@users.sourceforge.net)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* LOCAL MACROS and TYPES ***************************************************/
18
19 #define AUTO_DRIVE ((ULONG)-1)
20
21 #define PARTITION_MAGIC 0xaa55
22
23 #define PARTITION_TBL_SIZE 4
24
25 #include <pshpack1.h>
26
27 typedef struct _PARTITION
28 {
29 unsigned char BootFlags; /* bootable? 0=no, 128=yes */
30 unsigned char StartingHead; /* beginning head number */
31 unsigned char StartingSector; /* beginning sector number */
32 unsigned char StartingCylinder; /* 10 bit nmbr, with high 2 bits put in begsect */
33 unsigned char PartitionType; /* Operating System type indicator code */
34 unsigned char EndingHead; /* ending head number */
35 unsigned char EndingSector; /* ending sector number */
36 unsigned char EndingCylinder; /* also a 10 bit nmbr, with same high 2 bit trick */
37 unsigned int StartingBlock; /* first sector relative to start of disk */
38 unsigned int SectorCount; /* number of sectors in partition */
39 } PARTITION, *PPARTITION;
40
41
42 typedef struct _PARTITION_SECTOR
43 {
44 UCHAR BootCode[440]; /* 0x000 */
45 ULONG Signature; /* 0x1B8 */
46 UCHAR Reserved[2]; /* 0x1BC */
47 PARTITION Partition[PARTITION_TBL_SIZE]; /* 0x1BE */
48 USHORT Magic; /* 0x1FE */
49 } PARTITION_SECTOR, *PPARTITION_SECTOR;
50
51 typedef struct _REG_DISK_MOUNT_INFO
52 {
53 ULONG Signature;
54 LARGE_INTEGER StartingOffset;
55 } REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO;
56
57 #include <poppack.h>
58
59
60 typedef enum _DISK_MANAGER
61 {
62 NoDiskManager,
63 OntrackDiskManager,
64 EZ_Drive
65 } DISK_MANAGER;
66
67 HAL_DISPATCH EXPORTED HalDispatchTable =
68 {
69 HAL_DISPATCH_VERSION,
70 (pHalQuerySystemInformation) NULL, // HalQuerySystemInformation
71 (pHalSetSystemInformation) NULL, // HalSetSystemInformation
72 (pHalQueryBusSlots) NULL, // HalQueryBusSlots
73 0,
74 (pHalExamineMBR) HalExamineMBR,
75 (pHalIoAssignDriveLetters) xHalIoAssignDriveLetters,
76 (pHalIoReadPartitionTable) xHalIoReadPartitionTable,
77 (pHalIoSetPartitionInformation) xHalIoSetPartitionInformation,
78 (pHalIoWritePartitionTable) xHalIoWritePartitionTable,
79 (pHalHandlerForBus) NULL, // HalReferenceHandlerForBus
80 (pHalReferenceBusHandler) NULL, // HalReferenceBusHandler
81 (pHalReferenceBusHandler) NULL, // HalDereferenceBusHandler
82 (pHalInitPnpDriver) NULL, //HalInitPnpDriver;
83 (pHalInitPowerManagement) NULL, //HalInitPowerManagement;
84 (pHalGetDmaAdapter) NULL, //HalGetDmaAdapter;
85 (pHalGetInterruptTranslator) NULL, //HalGetInterruptTranslator;
86 (pHalStartMirroring) NULL, //HalStartMirroring;
87 (pHalEndMirroring) NULL, //HalEndMirroring;
88 (pHalMirrorPhysicalMemory) NULL, //HalMirrorPhysicalMemory;
89 (pHalEndOfBoot) NULL, //HalEndOfBoot;
90 (pHalMirrorVerify) NULL //HalMirrorVerify;
91 };
92
93 HAL_PRIVATE_DISPATCH EXPORTED HalPrivateDispatchTable =
94 {
95 HAL_PRIVATE_DISPATCH_VERSION
96 };
97
98 const WCHAR DiskMountString[] = L"\\DosDevices\\%C:";
99
100 /* FUNCTIONS *****************************************************************/
101
102 NTSTATUS
103 FASTCALL
104 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName,
105 OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
106 {
107 IO_STATUS_BLOCK StatusBlock;
108 DISK_GEOMETRY DiskGeometry;
109 PDEVICE_OBJECT DeviceObject = NULL;
110 PFILE_OBJECT FileObject;
111 KEVENT Event;
112 PIRP Irp;
113 NTSTATUS Status;
114
115 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
116 DeviceName,
117 LayoutInfo);
118
119 /* Get the drives sector size */
120 Status = IoGetDeviceObjectPointer(DeviceName,
121 FILE_READ_DATA,
122 &FileObject,
123 &DeviceObject);
124 if (!NT_SUCCESS(Status))
125 {
126 DPRINT("Status %x\n", Status);
127 return(Status);
128 }
129
130 KeInitializeEvent(&Event,
131 NotificationEvent,
132 FALSE);
133
134 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
135 DeviceObject,
136 NULL,
137 0,
138 &DiskGeometry,
139 sizeof(DISK_GEOMETRY),
140 FALSE,
141 &Event,
142 &StatusBlock);
143 if (Irp == NULL)
144 {
145 ObDereferenceObject(FileObject);
146 return(STATUS_INSUFFICIENT_RESOURCES);
147 }
148
149 Status = IoCallDriver(DeviceObject,
150 Irp);
151 if (Status == STATUS_PENDING)
152 {
153 KeWaitForSingleObject(&Event,
154 Executive,
155 KernelMode,
156 FALSE,
157 NULL);
158 Status = StatusBlock.Status;
159 }
160 if (!NT_SUCCESS(Status))
161 {
162 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
163 {
164 DiskGeometry.BytesPerSector = 512;
165 }
166 else
167 {
168 ObDereferenceObject(FileObject);
169 return(Status);
170 }
171 }
172
173 DPRINT("DiskGeometry.BytesPerSector: %d\n",
174 DiskGeometry.BytesPerSector);
175
176 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
177 {
178 PDRIVE_LAYOUT_INFORMATION Buffer;
179
180 /* Allocate a partition list for a single entry. */
181 Buffer = ExAllocatePool(NonPagedPool,
182 sizeof(DRIVE_LAYOUT_INFORMATION));
183 if (Buffer != NULL)
184 {
185 RtlZeroMemory(Buffer,
186 sizeof(DRIVE_LAYOUT_INFORMATION));
187 Buffer->PartitionCount = 1;
188 *LayoutInfo = Buffer;
189
190 Status = STATUS_SUCCESS;
191 }
192 else
193 {
194 Status = STATUS_UNSUCCESSFUL;
195 }
196 }
197 else
198 {
199 /* Read the partition table */
200 Status = IoReadPartitionTable(DeviceObject,
201 DiskGeometry.BytesPerSector,
202 FALSE,
203 LayoutInfo);
204 }
205
206 ObDereferenceObject(FileObject);
207
208 return(Status);
209 }
210
211
212 static NTSTATUS
213 xHalpReadSector (IN PDEVICE_OBJECT DeviceObject,
214 IN ULONG SectorSize,
215 IN PLARGE_INTEGER SectorOffset,
216 IN PVOID Sector)
217 {
218 IO_STATUS_BLOCK StatusBlock;
219 KEVENT Event;
220 PIRP Irp;
221 NTSTATUS Status;
222
223 DPRINT("xHalpReadSector() called\n");
224
225 ASSERT(DeviceObject);
226 ASSERT(Sector);
227
228 KeInitializeEvent(&Event,
229 NotificationEvent,
230 FALSE);
231
232 /* Read the sector */
233 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
234 DeviceObject,
235 Sector,
236 SectorSize,
237 SectorOffset,
238 &Event,
239 &StatusBlock);
240
241 Status = IoCallDriver(DeviceObject,
242 Irp);
243 if (Status == STATUS_PENDING)
244 {
245 KeWaitForSingleObject(&Event,
246 Executive,
247 KernelMode,
248 FALSE,
249 NULL);
250 Status = StatusBlock.Status;
251 }
252
253 if (!NT_SUCCESS(Status))
254 {
255 DPRINT("Reading sector failed (Status 0x%08lx)\n",
256 Status);
257 return Status;
258 }
259
260 return Status;
261 }
262
263
264 static NTSTATUS
265 xHalpWriteSector (IN PDEVICE_OBJECT DeviceObject,
266 IN ULONG SectorSize,
267 IN PLARGE_INTEGER SectorOffset,
268 IN PVOID Sector)
269 {
270 IO_STATUS_BLOCK StatusBlock;
271 KEVENT Event;
272 PIRP Irp;
273 NTSTATUS Status;
274
275 DPRINT("xHalpWriteSector() called\n");
276
277 KeInitializeEvent(&Event,
278 NotificationEvent,
279 FALSE);
280
281 /* Write the sector */
282 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
283 DeviceObject,
284 Sector,
285 SectorSize,
286 SectorOffset,
287 &Event,
288 &StatusBlock);
289
290 Status = IoCallDriver(DeviceObject,
291 Irp);
292 if (Status == STATUS_PENDING)
293 {
294 KeWaitForSingleObject(&Event,
295 Executive,
296 KernelMode,
297 FALSE,
298 NULL);
299 Status = StatusBlock.Status;
300 }
301
302 if (!NT_SUCCESS(Status))
303 {
304 DPRINT("Writing sector failed (Status 0x%08lx)\n",
305 Status);
306 }
307
308 return Status;
309 }
310
311
312 VOID FASTCALL
313 HalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
314 IN ULONG SectorSize,
315 IN ULONG MBRTypeIdentifier,
316 OUT PVOID *Buffer)
317 {
318 LARGE_INTEGER SectorOffset;
319 PPARTITION_SECTOR Sector;
320 NTSTATUS Status;
321
322 DPRINT("HalExamineMBR()\n");
323
324 *Buffer = NULL;
325
326 if (SectorSize < 512)
327 SectorSize = 512;
328 if (SectorSize > 4096)
329 SectorSize = 4096;
330
331 Sector = (PPARTITION_SECTOR) ExAllocatePool (PagedPool,
332 SectorSize);
333 if (Sector == NULL)
334 {
335 DPRINT ("Partition sector allocation failed\n");
336 return;
337 }
338
339 #if defined(__GNUC__)
340 SectorOffset.QuadPart = 0LL;
341 #else
342 SectorOffset.QuadPart = 0;
343 #endif
344 Status = xHalpReadSector (DeviceObject,
345 SectorSize,
346 &SectorOffset,
347 (PVOID)Sector);
348 if (!NT_SUCCESS(Status))
349 {
350 DPRINT("xHalpReadSector() failed (Status %lx)\n", Status);
351 ExFreePool(Sector);
352 return;
353 }
354
355 if (Sector->Magic != PARTITION_MAGIC)
356 {
357 DPRINT("Invalid MBR magic value\n");
358 ExFreePool(Sector);
359 return;
360 }
361
362 if (Sector->Partition[0].PartitionType != MBRTypeIdentifier)
363 {
364 DPRINT("Invalid MBRTypeIdentifier\n");
365 ExFreePool(Sector);
366 return;
367 }
368
369 if (Sector->Partition[0].PartitionType == 0x54)
370 {
371 /* Found 'Ontrack Disk Manager'. Shift all sectors by 63 */
372 DPRINT("Found 'Ontrack Disk Manager'!\n");
373 *((PULONG)Sector) = 63;
374 }
375
376 *Buffer = (PVOID)Sector;
377 }
378
379
380 static VOID
381 HalpAssignDrive(IN PUNICODE_STRING PartitionName,
382 IN ULONG DriveNumber,
383 IN UCHAR DriveType,
384 IN ULONG Signature,
385 IN LARGE_INTEGER StartingOffset,
386 IN HANDLE hKey)
387 {
388 WCHAR DriveNameBuffer[16];
389 UNICODE_STRING DriveName;
390 ULONG i;
391 NTSTATUS Status;
392 REG_DISK_MOUNT_INFO DiskMountInfo;
393
394 DPRINT("HalpAssignDrive()\n");
395
396 if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 26))
397 {
398 /* Force assignment */
399 if ((ObSystemDeviceMap->DriveMap & (1 << DriveNumber)) != 0)
400 {
401 DbgPrint("Drive letter already used!\n");
402 return;
403 }
404 }
405 else
406 {
407 /* Automatic assignment */
408 DriveNumber = AUTO_DRIVE;
409
410 for (i = 2; i < 26; i++)
411 {
412 if ((ObSystemDeviceMap->DriveMap & (1 << i)) == 0)
413 {
414 DriveNumber = i;
415 break;
416 }
417 }
418
419 if (DriveNumber == AUTO_DRIVE)
420 {
421 DbgPrint("No drive letter available!\n");
422 return;
423 }
424 }
425
426 DPRINT("DriveNumber %d\n", DriveNumber);
427
428 /* Update the System Device Map */
429 ObSystemDeviceMap->DriveMap |= (1 << DriveNumber);
430 ObSystemDeviceMap->DriveType[DriveNumber] = DriveType;
431
432 /* Build drive name */
433 swprintf(DriveNameBuffer,
434 L"\\??\\%C:",
435 'A' + DriveNumber);
436 RtlInitUnicodeString(&DriveName,
437 DriveNameBuffer);
438
439 DPRINT(" %wZ ==> %wZ\n",
440 &DriveName,
441 PartitionName);
442
443 /* Create symbolic link */
444 Status = IoCreateSymbolicLink(&DriveName,
445 PartitionName);
446
447 if (DriveType == DOSDEVICE_DRIVE_FIXED && hKey)
448 {
449 DiskMountInfo.Signature = Signature;
450 DiskMountInfo.StartingOffset = StartingOffset;
451 swprintf(DriveNameBuffer, DiskMountString, L'A' + DriveNumber);
452 RtlInitUnicodeString(&DriveName, DriveNameBuffer);
453
454 Status = ZwSetValueKey(hKey,
455 &DriveName,
456 0,
457 REG_BINARY,
458 &DiskMountInfo,
459 sizeof(DiskMountInfo));
460 if (!NT_SUCCESS(Status))
461 {
462 DPRINT1("ZwCreateValueKey failed for %wZ, status=%x\n", &DriveName, Status);
463 }
464 }
465 }
466
467 ULONG
468 xHalpGetRDiskCount(VOID)
469 {
470 NTSTATUS Status;
471 UNICODE_STRING ArcName;
472 PWCHAR ArcNameBuffer;
473 OBJECT_ATTRIBUTES ObjectAttributes;
474 HANDLE DirectoryHandle;
475 POBJECT_DIRECTORY_INFORMATION DirectoryInfo;
476 ULONG Skip;
477 ULONG ResultLength;
478 ULONG CurrentRDisk;
479 ULONG RDiskCount;
480 BOOLEAN First = TRUE;
481 ULONG Count;
482
483 DirectoryInfo = ExAllocatePool(PagedPool, 2 * PAGE_SIZE);
484 if (DirectoryInfo == NULL)
485 {
486 return 0;
487 }
488
489 RtlInitUnicodeString(&ArcName, L"\\ArcName");
490 InitializeObjectAttributes(&ObjectAttributes,
491 &ArcName,
492 0,
493 NULL,
494 NULL);
495
496 Status = ZwOpenDirectoryObject (&DirectoryHandle,
497 SYMBOLIC_LINK_ALL_ACCESS,
498 &ObjectAttributes);
499 if (!NT_SUCCESS(Status))
500 {
501 DPRINT1("ZwOpenDirectoryObject for %wZ failed, status=%lx\n", &ArcName, Status);
502 ExFreePool(DirectoryInfo);
503 return 0;
504 }
505
506 RDiskCount = 0;
507 Skip = 0;
508 while (NT_SUCCESS(Status))
509 {
510 Status = NtQueryDirectoryObject (DirectoryHandle,
511 DirectoryInfo,
512 2 * PAGE_SIZE,
513 FALSE,
514 First,
515 &Skip,
516 &ResultLength);
517 First = FALSE;
518 if (NT_SUCCESS(Status))
519 {
520 Count = 0;
521 while (DirectoryInfo[Count].ObjectName.Buffer)
522 {
523 DPRINT("Count %x\n", Count);
524 DirectoryInfo[Count].ObjectName.Buffer[DirectoryInfo[Count].ObjectName.Length / sizeof(WCHAR)] = 0;
525 ArcNameBuffer = DirectoryInfo[Count].ObjectName.Buffer;
526 if (DirectoryInfo[Count].ObjectName.Length >= sizeof(L"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR) &&
527 !_wcsnicmp(ArcNameBuffer, L"multi(0)disk(0)rdisk(", (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR)))
528 {
529 DPRINT("%S\n", ArcNameBuffer);
530 ArcNameBuffer += (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR);
531 CurrentRDisk = 0;
532 while (iswdigit(*ArcNameBuffer))
533 {
534 CurrentRDisk = CurrentRDisk * 10 + *ArcNameBuffer - L'0';
535 ArcNameBuffer++;
536 }
537 if (!_wcsicmp(ArcNameBuffer, L")") &&
538 CurrentRDisk >= RDiskCount)
539 {
540 RDiskCount = CurrentRDisk + 1;
541 }
542 }
543 Count++;
544 }
545 }
546 }
547 ExFreePool(DirectoryInfo);
548 return RDiskCount;
549 }
550
551 NTSTATUS
552 xHalpGetDiskNumberFromRDisk(ULONG RDisk, PULONG DiskNumber)
553 {
554 WCHAR NameBuffer[80];
555 UNICODE_STRING ArcName;
556 UNICODE_STRING LinkName;
557 OBJECT_ATTRIBUTES ObjectAttributes;
558 HANDLE LinkHandle;
559 NTSTATUS Status;
560
561 swprintf(NameBuffer,
562 L"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
563 RDisk);
564
565 RtlInitUnicodeString(&ArcName, NameBuffer);
566 InitializeObjectAttributes(&ObjectAttributes,
567 &ArcName,
568 0,
569 NULL,
570 NULL);
571 Status = ZwOpenSymbolicLinkObject(&LinkHandle,
572 SYMBOLIC_LINK_ALL_ACCESS,
573 &ObjectAttributes);
574 if (!NT_SUCCESS(Status))
575 {
576 DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName, Status);
577 return Status;
578 }
579
580 LinkName.Buffer = NameBuffer;
581 LinkName.Length = 0;
582 LinkName.MaximumLength = sizeof(NameBuffer);
583 Status = ZwQuerySymbolicLinkObject(LinkHandle,
584 &LinkName,
585 NULL);
586 ZwClose(LinkHandle);
587 if (!NT_SUCCESS(Status))
588 {
589 DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status);
590 return Status;
591 }
592 if (LinkName.Length < sizeof(L"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR) ||
593 LinkName.Length >= sizeof(NameBuffer))
594 {
595 return STATUS_UNSUCCESSFUL;
596 }
597
598 NameBuffer[LinkName.Length / sizeof(WCHAR)] = 0;
599 if (_wcsnicmp(NameBuffer, L"\\Device\\Harddisk", (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR)))
600 {
601 return STATUS_UNSUCCESSFUL;
602 }
603 LinkName.Buffer += (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR);
604
605 if (!iswdigit(*LinkName.Buffer))
606 {
607 return STATUS_UNSUCCESSFUL;
608 }
609 *DiskNumber = 0;
610 while (iswdigit(*LinkName.Buffer))
611 {
612 *DiskNumber = *DiskNumber * 10 + *LinkName.Buffer - L'0';
613 LinkName.Buffer++;
614 }
615 if (_wcsicmp(LinkName.Buffer, L"\\Partition0"))
616 {
617 return STATUS_UNSUCCESSFUL;
618 }
619 return STATUS_SUCCESS;
620 }
621
622
623 VOID FASTCALL
624 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
625 IN PSTRING NtDeviceName,
626 OUT PUCHAR NtSystemPath,
627 OUT PSTRING NtSystemPathString)
628 {
629 PDRIVE_LAYOUT_INFORMATION *LayoutArray;
630 PCONFIGURATION_INFORMATION ConfigInfo;
631 OBJECT_ATTRIBUTES ObjectAttributes;
632 IO_STATUS_BLOCK StatusBlock;
633 UNICODE_STRING UnicodeString1;
634 UNICODE_STRING UnicodeString2;
635 HANDLE FileHandle;
636 PWSTR Buffer1;
637 PWSTR Buffer2;
638 ULONG i, j, k;
639 ULONG DiskNumber;
640 ULONG RDisk;
641 NTSTATUS Status;
642 HANDLE hKey;
643 ULONG Length;
644 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
645 PREG_DISK_MOUNT_INFO DiskMountInfo;
646 ULONG RDiskCount;
647
648 DPRINT("xHalIoAssignDriveLetters()\n");
649
650 ConfigInfo = IoGetConfigurationInformation();
651
652 RDiskCount = xHalpGetRDiskCount();
653
654 DPRINT1("RDiskCount %d\n", RDiskCount);
655
656 Buffer1 = (PWSTR)ExAllocatePool(PagedPool,
657 64 * sizeof(WCHAR));
658 Buffer2 = (PWSTR)ExAllocatePool(PagedPool,
659 32 * sizeof(WCHAR));
660
661 PartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(PagedPool,
662 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO));
663
664 DiskMountInfo = (PREG_DISK_MOUNT_INFO) PartialInformation->Data;
665
666 /* Open or Create the 'MountedDevices' key */
667 RtlInitUnicodeString(&UnicodeString1, L"\\Registry\\Machine\\SYSTEM\\MountedDevices");
668 InitializeObjectAttributes(&ObjectAttributes,
669 &UnicodeString1,
670 OBJ_CASE_INSENSITIVE,
671 NULL,
672 NULL);
673 Status = ZwOpenKey(&hKey,
674 KEY_ALL_ACCESS,
675 &ObjectAttributes);
676 if (!NT_SUCCESS(Status))
677 {
678 Status = ZwCreateKey(&hKey,
679 KEY_ALL_ACCESS,
680 &ObjectAttributes,
681 0,
682 NULL,
683 REG_OPTION_NON_VOLATILE,
684 NULL);
685 }
686 if (!NT_SUCCESS(Status))
687 {
688 hKey = NULL;
689 DPRINT1("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1, Status);
690 }
691
692 /* Create PhysicalDrive links */
693 DPRINT("Physical disk drives: %d\n", ConfigInfo->DiskCount);
694 for (i = 0; i < ConfigInfo->DiskCount; i++)
695 {
696 swprintf(Buffer1,
697 L"\\Device\\Harddisk%d\\Partition0",
698 i);
699 RtlInitUnicodeString(&UnicodeString1,
700 Buffer1);
701
702 InitializeObjectAttributes(&ObjectAttributes,
703 &UnicodeString1,
704 0,
705 NULL,
706 NULL);
707
708 Status = ZwOpenFile(&FileHandle,
709 0x10001,
710 &ObjectAttributes,
711 &StatusBlock,
712 1,
713 FILE_SYNCHRONOUS_IO_NONALERT);
714 if (NT_SUCCESS(Status))
715 {
716 ZwClose(FileHandle);
717
718 swprintf(Buffer2,
719 L"\\??\\PhysicalDrive%d",
720 i);
721 RtlInitUnicodeString(&UnicodeString2,
722 Buffer2);
723
724 DPRINT("Creating link: %S ==> %S\n",
725 Buffer2,
726 Buffer1);
727
728 IoCreateSymbolicLink(&UnicodeString2,
729 &UnicodeString1);
730 }
731 }
732
733 /* Initialize layout array */
734 LayoutArray = ExAllocatePool(NonPagedPool,
735 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
736 RtlZeroMemory(LayoutArray,
737 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
738 for (i = 0; i < ConfigInfo->DiskCount; i++)
739 {
740 swprintf(Buffer1,
741 L"\\Device\\Harddisk%d\\Partition0",
742 i);
743 RtlInitUnicodeString(&UnicodeString1,
744 Buffer1);
745
746 Status = xHalQueryDriveLayout(&UnicodeString1,
747 &LayoutArray[i]);
748 if (!NT_SUCCESS(Status))
749 {
750 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
751 Status);
752 LayoutArray[i] = NULL;
753 continue;
754 }
755 /* We don't use the RewritePartition value while mounting the disks.
756 * We use this value for marking pre-assigned (registry) partitions.
757 */
758 for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
759 {
760 LayoutArray[i]->PartitionEntry[j].RewritePartition = FALSE;
761 }
762 }
763
764 #ifndef NDEBUG
765 /* Dump layout array */
766 for (i = 0; i < ConfigInfo->DiskCount; i++)
767 {
768 DPRINT("Harddisk %d:\n",
769 i);
770
771 if (LayoutArray[i] == NULL)
772 continue;
773
774 DPRINT("Logical partitions: %d\n",
775 LayoutArray[i]->PartitionCount);
776
777 for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
778 {
779 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
780 j,
781 LayoutArray[i]->PartitionEntry[j].PartitionNumber,
782 LayoutArray[i]->PartitionEntry[j].BootIndicator,
783 LayoutArray[i]->PartitionEntry[j].PartitionType,
784 LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart,
785 LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart);
786 }
787 }
788 #endif
789
790 /* Assign pre-assigned (registry) partitions */
791 if (hKey)
792 {
793 for (k = 2; k < 26; k++)
794 {
795 swprintf(Buffer1, DiskMountString, L'A' + k);
796 RtlInitUnicodeString(&UnicodeString1, Buffer1);
797 Status = ZwQueryValueKey(hKey,
798 &UnicodeString1,
799 KeyValuePartialInformation,
800 PartialInformation,
801 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO),
802 &Length);
803 if (NT_SUCCESS(Status) &&
804 PartialInformation->Type == REG_BINARY &&
805 PartialInformation->DataLength == sizeof(REG_DISK_MOUNT_INFO))
806 {
807 DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1, DiskMountInfo->Signature,
808 DiskMountInfo->StartingOffset.u.HighPart, DiskMountInfo->StartingOffset.u.LowPart);
809 for (i = 0; i < ConfigInfo->DiskCount; i++)
810 {
811 DPRINT("%x\n", LayoutArray[i]->Signature);
812 if (LayoutArray[i] &&
813 LayoutArray[i]->Signature == DiskMountInfo->Signature)
814 {
815 for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
816 {
817 if (LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart == DiskMountInfo->StartingOffset.QuadPart)
818 {
819 if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType))
820 {
821 swprintf(Buffer2,
822 L"\\Device\\Harddisk%d\\Partition%d",
823 i,
824 LayoutArray[i]->PartitionEntry[j].PartitionNumber);
825 RtlInitUnicodeString(&UnicodeString2,
826 Buffer2);
827
828 /* Assign drive */
829 DPRINT(" %wZ\n", &UnicodeString2);
830 HalpAssignDrive(&UnicodeString2,
831 k,
832 DOSDEVICE_DRIVE_FIXED,
833 DiskMountInfo->Signature,
834 DiskMountInfo->StartingOffset,
835 NULL);
836 /* Mark the partition as assigned */
837 LayoutArray[i]->PartitionEntry[j].RewritePartition = TRUE;
838 }
839 break;
840 }
841 }
842 break;
843 }
844 }
845 }
846 }
847 }
848
849 /* Assign bootable partition on first harddisk */
850 DPRINT("Assigning bootable primary partition on first harddisk:\n");
851 if (RDiskCount > 0)
852 {
853 Status = xHalpGetDiskNumberFromRDisk(0, &DiskNumber);
854 if (NT_SUCCESS(Status) &&
855 DiskNumber < ConfigInfo->DiskCount &&
856 LayoutArray[DiskNumber])
857 {
858 /* Search for bootable partition */
859 for (j = 0; j < PARTITION_TBL_SIZE && j < LayoutArray[DiskNumber]->PartitionCount; j++)
860 {
861 if ((LayoutArray[DiskNumber]->PartitionEntry[j].BootIndicator == TRUE) &&
862 IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
863 {
864 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE)
865 {
866 swprintf(Buffer2,
867 L"\\Device\\Harddisk%lu\\Partition%d",
868 DiskNumber,
869 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
870 RtlInitUnicodeString(&UnicodeString2,
871 Buffer2);
872
873 /* Assign drive */
874 DPRINT1(" %wZ\n", &UnicodeString2);
875 HalpAssignDrive(&UnicodeString2,
876 AUTO_DRIVE,
877 DOSDEVICE_DRIVE_FIXED,
878 LayoutArray[DiskNumber]->Signature,
879 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
880 hKey);
881 /* Mark the partition as assigned */
882 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
883 }
884 break;
885 }
886 }
887 }
888 }
889
890 /* Assign remaining primary partitions */
891 DPRINT("Assigning remaining primary partitions:\n");
892 for (RDisk = 0; RDisk < RDiskCount; RDisk++)
893 {
894 Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber);
895 if (NT_SUCCESS(Status) &&
896 DiskNumber < ConfigInfo->DiskCount &&
897 LayoutArray[DiskNumber])
898 {
899 /* Search for primary partitions */
900 for (j = 0; (j < PARTITION_TBL_SIZE) && (j < LayoutArray[DiskNumber]->PartitionCount); j++)
901 {
902 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
903 IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
904 {
905 swprintf(Buffer2,
906 L"\\Device\\Harddisk%d\\Partition%d",
907 DiskNumber,
908 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
909 RtlInitUnicodeString(&UnicodeString2,
910 Buffer2);
911
912 /* Assign drive */
913 DPRINT(" %wZ\n",
914 &UnicodeString2);
915 HalpAssignDrive(&UnicodeString2,
916 AUTO_DRIVE,
917 DOSDEVICE_DRIVE_FIXED,
918 LayoutArray[DiskNumber]->Signature,
919 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
920 hKey);
921 /* Mark the partition as assigned */
922 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
923 }
924 }
925 }
926 }
927
928 /* Assign extended (logical) partitions */
929 DPRINT("Assigning extended (logical) partitions:\n");
930 for (RDisk = 0; RDisk < RDiskCount; RDisk++)
931 {
932 Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber);
933 if (NT_SUCCESS(Status) &&
934 DiskNumber < ConfigInfo->DiskCount &&
935 LayoutArray[DiskNumber])
936 {
937 /* Search for extended partitions */
938 for (j = PARTITION_TBL_SIZE; j < LayoutArray[DiskNumber]->PartitionCount; j++)
939 {
940 if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) &&
941 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
942 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0)
943 {
944 swprintf(Buffer2,
945 L"\\Device\\Harddisk%d\\Partition%d",
946 DiskNumber,
947 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
948 RtlInitUnicodeString(&UnicodeString2,
949 Buffer2);
950
951 /* Assign drive */
952 DPRINT(" %wZ\n",
953 &UnicodeString2);
954 HalpAssignDrive(&UnicodeString2,
955 AUTO_DRIVE,
956 DOSDEVICE_DRIVE_FIXED,
957 LayoutArray[DiskNumber]->Signature,
958 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
959 hKey);
960 /* Mark the partition as assigned */
961 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
962 }
963 }
964 }
965 }
966
967 /* Assign remaining primary partitions without an arc-name */
968 DPRINT("Assigning remaining primary partitions:\n");
969 for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++)
970 {
971 if (LayoutArray[DiskNumber])
972 {
973 /* Search for primary partitions */
974 for (j = 0; (j < PARTITION_TBL_SIZE) && (j < LayoutArray[DiskNumber]->PartitionCount); j++)
975 {
976 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
977 IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
978 {
979 swprintf(Buffer2,
980 L"\\Device\\Harddisk%d\\Partition%d",
981 DiskNumber,
982 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
983 RtlInitUnicodeString(&UnicodeString2,
984 Buffer2);
985
986 /* Assign drive */
987 DPRINT(" %wZ\n",
988 &UnicodeString2);
989 HalpAssignDrive(&UnicodeString2,
990 AUTO_DRIVE,
991 DOSDEVICE_DRIVE_FIXED,
992 LayoutArray[DiskNumber]->Signature,
993 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
994 hKey);
995 /* Mark the partition as assigned */
996 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
997 }
998 }
999 }
1000 }
1001
1002 /* Assign extended (logical) partitions without an arc-name */
1003 DPRINT("Assigning extended (logical) partitions:\n");
1004 for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++)
1005 {
1006 if (LayoutArray[DiskNumber])
1007 {
1008 /* Search for extended partitions */
1009 for (j = PARTITION_TBL_SIZE; j < LayoutArray[DiskNumber]->PartitionCount; j++)
1010 {
1011 if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) &&
1012 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
1013 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0)
1014 {
1015 swprintf(Buffer2,
1016 L"\\Device\\Harddisk%d\\Partition%d",
1017 DiskNumber,
1018 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
1019 RtlInitUnicodeString(&UnicodeString2,
1020 Buffer2);
1021
1022 /* Assign drive */
1023 DPRINT(" %wZ\n",
1024 &UnicodeString2);
1025 HalpAssignDrive(&UnicodeString2,
1026 AUTO_DRIVE,
1027 DOSDEVICE_DRIVE_FIXED,
1028 LayoutArray[DiskNumber]->Signature,
1029 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
1030 hKey);
1031 /* Mark the partition as assigned */
1032 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
1033 }
1034 }
1035 }
1036 }
1037
1038 /* Assign removable disk drives */
1039 DPRINT("Assigning removable disk drives:\n");
1040 for (i = 0; i < ConfigInfo->DiskCount; i++)
1041 {
1042 if (LayoutArray[i])
1043 {
1044 /* Search for virtual partitions */
1045 if (LayoutArray[i]->PartitionCount == 1 &&
1046 LayoutArray[i]->PartitionEntry[0].PartitionType == 0)
1047 {
1048 swprintf(Buffer2,
1049 L"\\Device\\Harddisk%d\\Partition1",
1050 i);
1051 RtlInitUnicodeString(&UnicodeString2,
1052 Buffer2);
1053
1054 /* Assign drive */
1055 DPRINT(" %wZ\n",
1056 &UnicodeString2);
1057 HalpAssignDrive(&UnicodeString2,
1058 AUTO_DRIVE,
1059 DOSDEVICE_DRIVE_REMOVABLE,
1060 0,
1061 (LARGE_INTEGER)0LL,
1062 hKey);
1063 }
1064 }
1065 }
1066
1067 /* Free layout array */
1068 for (i = 0; i < ConfigInfo->DiskCount; i++)
1069 {
1070 if (LayoutArray[i] != NULL)
1071 ExFreePool(LayoutArray[i]);
1072 }
1073 ExFreePool(LayoutArray);
1074
1075 /* Assign floppy drives */
1076 DPRINT("Floppy drives: %d\n", ConfigInfo->FloppyCount);
1077 for (i = 0; i < ConfigInfo->FloppyCount; i++)
1078 {
1079 swprintf(Buffer1,
1080 L"\\Device\\Floppy%d",
1081 i);
1082 RtlInitUnicodeString(&UnicodeString1,
1083 Buffer1);
1084
1085 /* Assign drive letters A: or B: or first free drive letter */
1086 DPRINT(" %wZ\n",
1087 &UnicodeString1);
1088 HalpAssignDrive(&UnicodeString1,
1089 (i < 2) ? i : AUTO_DRIVE,
1090 DOSDEVICE_DRIVE_REMOVABLE,
1091 0,
1092 (LARGE_INTEGER)0LL,
1093 hKey);
1094 }
1095
1096 /* Assign cdrom drives */
1097 DPRINT("CD-Rom drives: %d\n", ConfigInfo->CdRomCount);
1098 for (i = 0; i < ConfigInfo->CdRomCount; i++)
1099 {
1100 swprintf(Buffer1,
1101 L"\\Device\\CdRom%d",
1102 i);
1103 RtlInitUnicodeString(&UnicodeString1,
1104 Buffer1);
1105
1106 /* Assign first free drive letter */
1107 DPRINT(" %wZ\n", &UnicodeString1);
1108 HalpAssignDrive(&UnicodeString1,
1109 AUTO_DRIVE,
1110 DOSDEVICE_DRIVE_CDROM,
1111 0,
1112 (LARGE_INTEGER)0LL,
1113 hKey);
1114 }
1115
1116 /* Anything else to do? */
1117
1118 ExFreePool(PartialInformation);
1119 ExFreePool(Buffer2);
1120 ExFreePool(Buffer1);
1121 if (hKey)
1122 {
1123 ZwClose(hKey);
1124 }
1125 }
1126
1127
1128 NTSTATUS FASTCALL
1129 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
1130 ULONG SectorSize,
1131 BOOLEAN ReturnRecognizedPartitions,
1132 PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
1133 {
1134 LARGE_INTEGER RealPartitionOffset;
1135 ULONGLONG PartitionOffset;
1136 #if defined(__GNUC__)
1137 ULONGLONG nextPartitionOffset = 0LL;
1138 #else
1139 ULONGLONG nextPartitionOffset = 0;
1140 #endif
1141 ULONGLONG containerOffset;
1142 NTSTATUS Status;
1143 PPARTITION_SECTOR PartitionSector;
1144 PDRIVE_LAYOUT_INFORMATION LayoutBuffer;
1145 ULONG i;
1146 ULONG Count = 0;
1147 ULONG Number = 1;
1148 BOOLEAN ExtendedFound = FALSE;
1149 PVOID MbrBuffer;
1150 DISK_MANAGER DiskManager = NoDiskManager;
1151
1152 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
1153 DeviceObject,
1154 SectorSize,
1155 ReturnRecognizedPartitions,
1156 PartitionBuffer);
1157
1158 *PartitionBuffer = NULL;
1159
1160 /* Check sector size */
1161 if (SectorSize < 512)
1162 SectorSize = 512;
1163 if (SectorSize > 4096)
1164 SectorSize = 4096;
1165
1166 /* Check for 'Ontrack Disk Manager' */
1167 HalExamineMBR(DeviceObject,
1168 SectorSize,
1169 0x54,
1170 &MbrBuffer);
1171 if (MbrBuffer != NULL)
1172 {
1173 DPRINT("Found 'Ontrack Disk Manager'\n");
1174 DiskManager = OntrackDiskManager;
1175 ExFreePool(MbrBuffer);
1176 }
1177
1178 /* Check for 'EZ-Drive' */
1179 HalExamineMBR(DeviceObject,
1180 SectorSize,
1181 0x55,
1182 &MbrBuffer);
1183 if (MbrBuffer != NULL)
1184 {
1185 DPRINT("Found 'EZ-Drive'\n");
1186 DiskManager = EZ_Drive;
1187 ExFreePool(MbrBuffer);
1188 }
1189
1190 PartitionSector = (PPARTITION_SECTOR)ExAllocatePool(PagedPool,
1191 SectorSize);
1192 if (PartitionSector == NULL)
1193 {
1194 return(STATUS_INSUFFICIENT_RESOURCES);
1195 }
1196
1197 LayoutBuffer = (PDRIVE_LAYOUT_INFORMATION)ExAllocatePool(NonPagedPool,
1198 0x1000);
1199 if (LayoutBuffer == NULL)
1200 {
1201 ExFreePool(PartitionSector);
1202 return(STATUS_INSUFFICIENT_RESOURCES);
1203 }
1204
1205 RtlZeroMemory(LayoutBuffer,
1206 0x1000);
1207
1208 #if defined(__GNUC__)
1209 PartitionOffset = 0ULL;
1210 containerOffset = 0ULL;
1211 #else
1212 PartitionOffset = 0;
1213 containerOffset = 0;
1214 #endif
1215
1216 do
1217 {
1218 DPRINT("PartitionOffset: %I64u\n", PartitionOffset / SectorSize);
1219
1220 /* Handle disk managers */
1221 if (DiskManager == OntrackDiskManager)
1222 {
1223 /* Shift offset by 63 sectors */
1224 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
1225 }
1226 #if defined(__GNUC__)
1227 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
1228 #else
1229 else if (DiskManager == EZ_Drive && PartitionOffset == 0)
1230 #endif
1231 {
1232 /* Use sector 1 instead of sector 0 */
1233 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
1234 }
1235 else
1236 {
1237 RealPartitionOffset.QuadPart = PartitionOffset;
1238 }
1239
1240 DPRINT ("RealPartitionOffset: %I64u\n",
1241 RealPartitionOffset.QuadPart / SectorSize);
1242
1243 Status = xHalpReadSector (DeviceObject,
1244 SectorSize,
1245 &RealPartitionOffset,
1246 PartitionSector);
1247 if (!NT_SUCCESS(Status))
1248 {
1249 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
1250 Status);
1251 ExFreePool (PartitionSector);
1252 ExFreePool (LayoutBuffer);
1253 return Status;
1254 }
1255
1256 /* Check the boot sector id */
1257 DPRINT("Magic %x\n", PartitionSector->Magic);
1258 if (PartitionSector->Magic != PARTITION_MAGIC)
1259 {
1260 DPRINT ("Invalid partition sector magic\n");
1261 ExFreePool (PartitionSector);
1262 *PartitionBuffer = LayoutBuffer;
1263 return STATUS_SUCCESS;
1264 }
1265
1266 #ifndef NDEBUG
1267 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1268 {
1269 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
1270 i,
1271 PartitionSector->Partition[i].BootFlags,
1272 PartitionSector->Partition[i].PartitionType,
1273 PartitionSector->Partition[i].StartingHead,
1274 PartitionSector->Partition[i].StartingSector & 0x3f,
1275 (((PartitionSector->Partition[i].StartingSector) & 0xc0) << 2) +
1276 PartitionSector->Partition[i].StartingCylinder,
1277 PartitionSector->Partition[i].EndingHead,
1278 PartitionSector->Partition[i].EndingSector & 0x3f,
1279 (((PartitionSector->Partition[i].EndingSector) & 0xc0) << 2) +
1280 PartitionSector->Partition[i].EndingCylinder,
1281 PartitionSector->Partition[i].StartingBlock,
1282 PartitionSector->Partition[i].SectorCount);
1283 }
1284 #endif
1285
1286 #if defined(__GNUC__)
1287 if (PartitionOffset == 0ULL)
1288 #else
1289 if (PartitionOffset == 0)
1290 #endif
1291 {
1292 LayoutBuffer->Signature = PartitionSector->Signature;
1293 DPRINT("Disk signature: %lx\n", LayoutBuffer->Signature);
1294 }
1295
1296 ExtendedFound = FALSE;
1297
1298 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1299 {
1300 if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
1301 {
1302 ExtendedFound = TRUE;
1303 if ((ULONGLONG) containerOffset == (ULONGLONG) 0)
1304 {
1305 containerOffset = PartitionOffset;
1306 }
1307 nextPartitionOffset = (ULONGLONG) containerOffset +
1308 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
1309 (ULONGLONG) SectorSize;
1310 }
1311
1312 if ((ReturnRecognizedPartitions == FALSE) ||
1313 ((ReturnRecognizedPartitions == TRUE) &&
1314 !IsContainerPartition(PartitionSector->Partition[i].PartitionType) &&
1315 PartitionSector->Partition[i].PartitionType != PARTITION_ENTRY_UNUSED))
1316 {
1317 /* handle normal partition */
1318 DPRINT("Partition %u: Normal Partition\n", i);
1319 Count = LayoutBuffer->PartitionCount;
1320 DPRINT("Logical Partition %u\n", Count);
1321
1322 if (PartitionSector->Partition[i].StartingBlock == 0)
1323 {
1324 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart = 0;
1325 }
1326 else if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
1327 {
1328 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
1329 (ULONGLONG) containerOffset +
1330 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
1331 (ULONGLONG) SectorSize;
1332 }
1333 else
1334 {
1335 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
1336 (ULONGLONG)PartitionOffset +
1337 ((ULONGLONG)PartitionSector->Partition[i].StartingBlock * (ULONGLONG)SectorSize);
1338 }
1339 LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart =
1340 (ULONGLONG)PartitionSector->Partition[i].SectorCount * (ULONGLONG)SectorSize;
1341 LayoutBuffer->PartitionEntry[Count].HiddenSectors =
1342 PartitionSector->Partition[i].StartingBlock;
1343
1344 if (!IsContainerPartition(PartitionSector->Partition[i].PartitionType) &&
1345 PartitionSector->Partition[i].PartitionType != PARTITION_ENTRY_UNUSED)
1346 {
1347 LayoutBuffer->PartitionEntry[Count].RecognizedPartition = TRUE;
1348 /* WinXP returns garbage as PartitionNumber */
1349 LayoutBuffer->PartitionEntry[Count].PartitionNumber = Number;
1350 Number++;
1351 }
1352 else
1353 {
1354 LayoutBuffer->PartitionEntry[Count].RecognizedPartition = FALSE;
1355 LayoutBuffer->PartitionEntry[Count].PartitionNumber = 0;
1356 }
1357
1358 LayoutBuffer->PartitionEntry[Count].PartitionType =
1359 PartitionSector->Partition[i].PartitionType;
1360 LayoutBuffer->PartitionEntry[Count].BootIndicator =
1361 (PartitionSector->Partition[i].BootFlags & 0x80)?TRUE:FALSE;
1362 LayoutBuffer->PartitionEntry[Count].RewritePartition = FALSE;
1363
1364 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x rec: %d\n",
1365 Count,
1366 LayoutBuffer->PartitionEntry[Count].PartitionNumber,
1367 LayoutBuffer->PartitionEntry[Count].BootIndicator,
1368 LayoutBuffer->PartitionEntry[Count].PartitionType,
1369 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart,
1370 LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart,
1371 LayoutBuffer->PartitionEntry[Count].RecognizedPartition);
1372
1373 LayoutBuffer->PartitionCount++;
1374 }
1375 }
1376
1377 PartitionOffset = nextPartitionOffset;
1378 }
1379 while (ExtendedFound == TRUE);
1380
1381 *PartitionBuffer = LayoutBuffer;
1382 ExFreePool(PartitionSector);
1383
1384 return(STATUS_SUCCESS);
1385 }
1386
1387
1388 NTSTATUS FASTCALL
1389 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
1390 IN ULONG SectorSize,
1391 IN ULONG PartitionNumber,
1392 IN ULONG PartitionType)
1393 {
1394 PPARTITION_SECTOR PartitionSector;
1395 LARGE_INTEGER RealPartitionOffset;
1396 ULONGLONG PartitionOffset;
1397 #if defined(__GNUC__)
1398 ULONGLONG nextPartitionOffset = 0LL;
1399 #else
1400 ULONGLONG nextPartitionOffset = 0;
1401 #endif
1402 ULONGLONG containerOffset;
1403 NTSTATUS Status;
1404 ULONG i;
1405 ULONG Number = 1;
1406 BOOLEAN ExtendedFound = FALSE;
1407 DISK_MANAGER DiskManager = NoDiskManager;
1408
1409 DPRINT ("xHalIoSetPartitionInformation(%p %lu %lu %lu)\n",
1410 DeviceObject,
1411 SectorSize,
1412 PartitionNumber,
1413 PartitionType);
1414
1415 /* Check sector size */
1416 if (SectorSize < 512)
1417 SectorSize = 512;
1418 if (SectorSize > 4096)
1419 SectorSize = 4096;
1420
1421 /* Check for 'Ontrack Disk Manager' */
1422 HalExamineMBR (DeviceObject,
1423 SectorSize,
1424 0x54,
1425 (PVOID*)(PVOID)&PartitionSector);
1426 if (PartitionSector != NULL)
1427 {
1428 DPRINT ("Found 'Ontrack Disk Manager'\n");
1429 DiskManager = OntrackDiskManager;
1430 ExFreePool (PartitionSector);
1431 }
1432
1433 /* Check for 'EZ-Drive' */
1434 HalExamineMBR (DeviceObject,
1435 SectorSize,
1436 0x55,
1437 (PVOID*)(PVOID)&PartitionSector);
1438 if (PartitionSector != NULL)
1439 {
1440 DPRINT ("Found 'EZ-Drive'\n");
1441 DiskManager = EZ_Drive;
1442 ExFreePool (PartitionSector);
1443 }
1444
1445 /* Allocate partition sector */
1446 PartitionSector = (PPARTITION_SECTOR) ExAllocatePool (PagedPool,
1447 SectorSize);
1448 if (PartitionSector == NULL)
1449 {
1450 return STATUS_INSUFFICIENT_RESOURCES;
1451 }
1452
1453 #if defined(__GNUC__)
1454 PartitionOffset = 0ULL;
1455 containerOffset = 0ULL;
1456 #else
1457 PartitionOffset = 0;
1458 containerOffset = 0;
1459 #endif
1460
1461 do
1462 {
1463 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset / SectorSize);
1464
1465 /* Handle disk managers */
1466 if (DiskManager == OntrackDiskManager)
1467 {
1468 /* Shift offset by 63 sectors */
1469 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
1470 }
1471 #if defined(__GNUC__)
1472 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
1473 #else
1474 else if (DiskManager == EZ_Drive && PartitionOffset == 0)
1475 #endif
1476 {
1477 /* Use sector 1 instead of sector 0 */
1478 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
1479 }
1480 else
1481 {
1482 RealPartitionOffset.QuadPart = PartitionOffset;
1483 }
1484
1485 DPRINT ("RealPartitionOffset: %I64u\n",
1486 RealPartitionOffset.QuadPart / SectorSize);
1487
1488 Status = xHalpReadSector (DeviceObject,
1489 SectorSize,
1490 &RealPartitionOffset,
1491 PartitionSector);
1492 if (!NT_SUCCESS (Status))
1493 {
1494 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
1495 Status);
1496 ExFreePool (PartitionSector);
1497 return Status;
1498 }
1499
1500 /* Check the boot sector id */
1501 DPRINT("Magic %x\n", PartitionSector->Magic);
1502 if (PartitionSector->Magic != PARTITION_MAGIC)
1503 {
1504 DPRINT ("Invalid partition sector magic\n");
1505 ExFreePool (PartitionSector);
1506 return STATUS_UNSUCCESSFUL;
1507 }
1508
1509 #ifndef NDEBUG
1510 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1511 {
1512 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
1513 i,
1514 PartitionSector->Partition[i].BootFlags,
1515 PartitionSector->Partition[i].PartitionType,
1516 PartitionSector->Partition[i].StartingHead,
1517 PartitionSector->Partition[i].StartingSector & 0x3f,
1518 (((PartitionSector->Partition[i].StartingSector) & 0xc0) << 2) +
1519 PartitionSector->Partition[i].StartingCylinder,
1520 PartitionSector->Partition[i].EndingHead,
1521 PartitionSector->Partition[i].EndingSector & 0x3f,
1522 (((PartitionSector->Partition[i].EndingSector) & 0xc0) << 2) +
1523 PartitionSector->Partition[i].EndingCylinder,
1524 PartitionSector->Partition[i].StartingBlock,
1525 PartitionSector->Partition[i].SectorCount);
1526 }
1527 #endif
1528
1529 ExtendedFound = FALSE;
1530 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1531 {
1532 if (IsContainerPartition (PartitionSector->Partition[i].PartitionType))
1533 {
1534 ExtendedFound = TRUE;
1535 #if defined(__GNUC__)
1536 if (containerOffset == 0ULL)
1537 #else
1538 if (containerOffset == 0)
1539 #endif
1540 {
1541 containerOffset = PartitionOffset;
1542 }
1543 nextPartitionOffset = containerOffset +
1544 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
1545 (ULONGLONG) SectorSize;
1546 }
1547
1548 /* Handle recognized partition */
1549 if (IsRecognizedPartition (PartitionSector->Partition[i].PartitionType))
1550 {
1551 if (Number == PartitionNumber)
1552 {
1553 /* Set partition type */
1554 PartitionSector->Partition[i].PartitionType = PartitionType;
1555
1556 /* Write partition sector */
1557 Status = xHalpWriteSector (DeviceObject,
1558 SectorSize,
1559 &RealPartitionOffset,
1560 PartitionSector);
1561 if (!NT_SUCCESS(Status))
1562 {
1563 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
1564 }
1565
1566 ExFreePool (PartitionSector);
1567 return Status;
1568 }
1569 Number++;
1570 }
1571 }
1572
1573 PartitionOffset = nextPartitionOffset;
1574 }
1575 while (ExtendedFound == TRUE);
1576
1577 ExFreePool(PartitionSector);
1578
1579 return STATUS_UNSUCCESSFUL;
1580 }
1581
1582
1583 NTSTATUS FASTCALL
1584 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
1585 IN ULONG SectorSize,
1586 IN ULONG SectorsPerTrack,
1587 IN ULONG NumberOfHeads,
1588 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
1589 {
1590 PPARTITION_SECTOR PartitionSector;
1591 LARGE_INTEGER RealPartitionOffset;
1592 ULONGLONG PartitionOffset;
1593 #if defined(__GNUC__)
1594 ULONGLONG NextPartitionOffset = 0LL;
1595 #else
1596 ULONGLONG NextPartitionOffset = 0;
1597 #endif
1598 ULONGLONG ContainerOffset;
1599 BOOLEAN ContainerEntry;
1600 DISK_MANAGER DiskManager;
1601 ULONG i;
1602 ULONG j;
1603 ULONG StartBlock;
1604 ULONG SectorCount;
1605 ULONG StartCylinder;
1606 ULONG StartSector;
1607 ULONG StartHead;
1608 ULONG EndCylinder;
1609 ULONG EndSector;
1610 ULONG EndHead;
1611 ULONG lba;
1612 ULONG x;
1613 NTSTATUS Status;
1614
1615 DPRINT ("xHalIoWritePartitionTable(%p %lu %lu %lu %p)\n",
1616 DeviceObject,
1617 SectorSize,
1618 SectorsPerTrack,
1619 NumberOfHeads,
1620 PartitionBuffer);
1621
1622 ASSERT(DeviceObject);
1623 ASSERT(PartitionBuffer);
1624
1625 DiskManager = NoDiskManager;
1626
1627 /* Check sector size */
1628 if (SectorSize < 512)
1629 SectorSize = 512;
1630 if (SectorSize > 4096)
1631 SectorSize = 4096;
1632
1633 /* Check for 'Ontrack Disk Manager' */
1634 HalExamineMBR (DeviceObject,
1635 SectorSize,
1636 0x54,
1637 (PVOID*)(PVOID)&PartitionSector);
1638 if (PartitionSector != NULL)
1639 {
1640 DPRINT ("Found 'Ontrack Disk Manager'\n");
1641 DiskManager = OntrackDiskManager;
1642 ExFreePool (PartitionSector);
1643 }
1644
1645 /* Check for 'EZ-Drive' */
1646 HalExamineMBR (DeviceObject,
1647 SectorSize,
1648 0x55,
1649 (PVOID*)(PVOID)&PartitionSector);
1650 if (PartitionSector != NULL)
1651 {
1652 DPRINT ("Found 'EZ-Drive'\n");
1653 DiskManager = EZ_Drive;
1654 ExFreePool (PartitionSector);
1655 }
1656
1657 /* Allocate partition sector */
1658 PartitionSector = (PPARTITION_SECTOR)ExAllocatePool(PagedPool,
1659 SectorSize);
1660 if (PartitionSector == NULL)
1661 {
1662 return STATUS_INSUFFICIENT_RESOURCES;
1663 }
1664
1665 Status = STATUS_SUCCESS;
1666 #if defined(__GNUC__)
1667 PartitionOffset = 0ULL;
1668 ContainerOffset = 0ULL;
1669 #else
1670 PartitionOffset = 0;
1671 ContainerOffset = 0;
1672 #endif
1673 for (i = 0; i < PartitionBuffer->PartitionCount; i += 4)
1674 {
1675 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset);
1676 DPRINT ("ContainerOffset: %I64u\n", ContainerOffset);
1677
1678 /* Handle disk managers */
1679 if (DiskManager == OntrackDiskManager)
1680 {
1681 /* Shift offset by 63 sectors */
1682 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
1683 }
1684 #if defined(__GNUC__)
1685 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
1686 #else
1687 else if (DiskManager == EZ_Drive && PartitionOffset == 0)
1688 #endif
1689 {
1690 /* Use sector 1 instead of sector 0 */
1691 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
1692 }
1693 else
1694 {
1695 RealPartitionOffset.QuadPart = PartitionOffset;
1696 }
1697
1698 /* Write modified partition tables */
1699 if (PartitionBuffer->PartitionEntry[i].RewritePartition == TRUE ||
1700 PartitionBuffer->PartitionEntry[i + 1].RewritePartition == TRUE ||
1701 PartitionBuffer->PartitionEntry[i + 2].RewritePartition == TRUE ||
1702 PartitionBuffer->PartitionEntry[i + 3].RewritePartition == TRUE)
1703 {
1704 /* Read partition sector */
1705 Status = xHalpReadSector (DeviceObject,
1706 SectorSize,
1707 &RealPartitionOffset,
1708 PartitionSector);
1709 if (!NT_SUCCESS(Status))
1710 {
1711 DPRINT1 ("xHalpReadSector() failed (Status %lx)\n", Status);
1712 break;
1713 }
1714
1715 /* Initialize a new partition sector */
1716 if (PartitionSector->Magic != PARTITION_MAGIC)
1717 {
1718 /* Create empty partition sector */
1719 RtlZeroMemory (PartitionSector,
1720 SectorSize);
1721 PartitionSector->Magic = PARTITION_MAGIC;
1722 }
1723
1724 PartitionSector->Signature = PartitionBuffer->Signature;
1725 /* Update partition sector entries */
1726 for (j = 0; j < 4; j++)
1727 {
1728 if (PartitionBuffer->PartitionEntry[i + j].RewritePartition == TRUE)
1729 {
1730 /* Set partition boot flag */
1731 if (PartitionBuffer->PartitionEntry[i + j].BootIndicator)
1732 {
1733 PartitionSector->Partition[j].BootFlags |= 0x80;
1734 }
1735 else
1736 {
1737 PartitionSector->Partition[j].BootFlags &= ~0x80;
1738 }
1739
1740 /* Set partition type */
1741 PartitionSector->Partition[j].PartitionType =
1742 PartitionBuffer->PartitionEntry[i + j].PartitionType;
1743
1744 /* Set partition data */
1745 #if defined(__GNUC__)
1746 if (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart == 0ULL &&
1747 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart == 0ULL)
1748 #else
1749 if (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart == 0 &&
1750 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart == 0)
1751 #endif
1752 {
1753 PartitionSector->Partition[j].StartingBlock = 0;
1754 PartitionSector->Partition[j].SectorCount = 0;
1755 PartitionSector->Partition[j].StartingCylinder = 0;
1756 PartitionSector->Partition[j].StartingHead = 0;
1757 PartitionSector->Partition[j].StartingSector = 0;
1758 PartitionSector->Partition[j].EndingCylinder = 0;
1759 PartitionSector->Partition[j].EndingHead = 0;
1760 PartitionSector->Partition[j].EndingSector = 0;
1761 }
1762 else
1763 {
1764 /*
1765 * CHS formulas:
1766 * x = LBA DIV SectorsPerTrack
1767 * cylinder = (x DIV NumberOfHeads) % 1024
1768 * head = x MOD NumberOfHeads
1769 * sector = (LBA MOD SectorsPerTrack) + 1
1770 */
1771
1772 /* Compute starting CHS values */
1773 lba = (ULONG)((PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart) / SectorSize);
1774 x = lba / SectorsPerTrack;
1775 StartCylinder = (x / NumberOfHeads) %1024;
1776 StartHead = x % NumberOfHeads;
1777 StartSector = (lba % SectorsPerTrack) + 1;
1778 DPRINT ("StartingOffset (LBA:%d C:%d H:%d S:%d)\n",
1779 lba, StartCylinder, StartHead, StartSector);
1780
1781 /* Compute ending CHS values */
1782 lba = (ULONG)((PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart +
1783 (PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart - 1)) / SectorSize);
1784 x = lba / SectorsPerTrack;
1785 EndCylinder = (x / NumberOfHeads) % 1024;
1786 EndHead = x % NumberOfHeads;
1787 EndSector = (lba % SectorsPerTrack) + 1;
1788 DPRINT ("EndingOffset (LBA:%d C:%d H:%d S:%d)\n",
1789 lba, EndCylinder, EndHead, EndSector);
1790
1791 /* Set starting CHS values */
1792 PartitionSector->Partition[j].StartingCylinder = StartCylinder & 0xff;
1793 PartitionSector->Partition[j].StartingHead = StartHead;
1794 PartitionSector->Partition[j].StartingSector =
1795 ((StartCylinder & 0x0300) >> 2) + (StartSector & 0x3f);
1796
1797 /* Set ending CHS values */
1798 PartitionSector->Partition[j].EndingCylinder = EndCylinder & 0xff;
1799 PartitionSector->Partition[j].EndingHead = EndHead;
1800 PartitionSector->Partition[j].EndingSector =
1801 ((EndCylinder & 0x0300) >> 2) + (EndSector & 0x3f);
1802
1803 /* Calculate start sector and sector count */
1804 if (IsContainerPartition (PartitionBuffer->PartitionEntry[i + j].PartitionType))
1805 {
1806 StartBlock =
1807 (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart - ContainerOffset) / SectorSize;
1808 }
1809 else
1810 {
1811 StartBlock =
1812 (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart - NextPartitionOffset) / SectorSize;
1813 }
1814 SectorCount =
1815 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart / SectorSize;
1816 DPRINT ("LBA (StartBlock:%lu SectorCount:%lu)\n",
1817 StartBlock, SectorCount);
1818
1819 /* Set start sector and sector count */
1820 PartitionSector->Partition[j].StartingBlock = StartBlock;
1821 PartitionSector->Partition[j].SectorCount = SectorCount;
1822 }
1823 }
1824 }
1825
1826 /* Write partition sector */
1827 Status = xHalpWriteSector (DeviceObject,
1828 SectorSize,
1829 &RealPartitionOffset,
1830 PartitionSector);
1831 if (!NT_SUCCESS(Status))
1832 {
1833 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
1834 break;
1835 }
1836 }
1837
1838 ContainerEntry = FALSE;
1839 for (j = 0; j < 4; j++)
1840 {
1841 if (IsContainerPartition (PartitionBuffer->PartitionEntry[i + j].PartitionType))
1842 {
1843 ContainerEntry = TRUE;
1844 NextPartitionOffset =
1845 PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart;
1846
1847 #if defined(__GNUC__)
1848 if (ContainerOffset == 0ULL)
1849 #else
1850 if (ContainerOffset == 0)
1851 #endif
1852 {
1853 ContainerOffset = NextPartitionOffset;
1854 }
1855 }
1856 }
1857
1858 if (ContainerEntry == FALSE)
1859 {
1860 DPRINT ("No container entry in partition sector!\n");
1861 break;
1862 }
1863
1864 PartitionOffset = NextPartitionOffset;
1865 }
1866
1867 ExFreePool (PartitionSector);
1868
1869 return Status;
1870 }
1871
1872 /*
1873 * @unimplemented
1874 *
1875 STDCALL
1876 VOID
1877 IoAssignDriveLetters(
1878 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1879 IN PSTRING NtDeviceName,
1880 OUT PUCHAR NtSystemPath,
1881 OUT PSTRING NtSystemPathString
1882 )
1883 {
1884 UNIMPLEMENTED;
1885 */
1886
1887 /*
1888 * @unimplemented
1889 */
1890 NTSTATUS
1891 STDCALL
1892 IoCreateDisk(
1893 IN PDEVICE_OBJECT DeviceObject,
1894 IN struct _CREATE_DISK* Disk
1895 )
1896 {
1897 UNIMPLEMENTED;
1898 return STATUS_NOT_IMPLEMENTED;
1899 }
1900
1901 /*
1902 * @unimplemented
1903 */
1904 NTSTATUS
1905 STDCALL
1906 IoGetBootDiskInformation(
1907 IN OUT PBOOTDISK_INFORMATION BootDiskInformation,
1908 IN ULONG Size
1909 )
1910 {
1911 UNIMPLEMENTED;
1912 return STATUS_NOT_IMPLEMENTED;
1913 }
1914
1915
1916 /*
1917 * @unimplemented
1918 */
1919 NTSTATUS
1920 STDCALL
1921 IoReadDiskSignature(
1922 IN PDEVICE_OBJECT DeviceObject,
1923 IN ULONG BytesPerSector,
1924 OUT PDISK_SIGNATURE Signature
1925 )
1926 {
1927 UNIMPLEMENTED;
1928 return STATUS_NOT_IMPLEMENTED;
1929 }
1930
1931 /*
1932 * @unimplemented
1933 */
1934 NTSTATUS
1935 STDCALL
1936 IoReadPartitionTableEx(
1937 IN PDEVICE_OBJECT DeviceObject,
1938 IN struct _DRIVE_LAYOUT_INFORMATION_EX** DriveLayout
1939 )
1940 {
1941 UNIMPLEMENTED;
1942 return STATUS_NOT_IMPLEMENTED;
1943 }
1944
1945 /*
1946 * @unimplemented
1947 */
1948 NTSTATUS
1949 STDCALL
1950 IoSetPartitionInformationEx(
1951 IN PDEVICE_OBJECT DeviceObject,
1952 IN ULONG PartitionNumber,
1953 IN struct _SET_PARTITION_INFORMATION_EX* PartitionInfo
1954 )
1955 {
1956 UNIMPLEMENTED;
1957 return STATUS_NOT_IMPLEMENTED;
1958 }
1959
1960 /*
1961 * @unimplemented
1962 */
1963 NTSTATUS
1964 STDCALL
1965 IoSetSystemPartition(
1966 PUNICODE_STRING VolumeNameString
1967 )
1968 {
1969 UNIMPLEMENTED;
1970 return STATUS_NOT_IMPLEMENTED;
1971 }
1972
1973 /*
1974 * @unimplemented
1975 */
1976 NTSTATUS
1977 STDCALL
1978 IoVerifyPartitionTable(
1979 IN PDEVICE_OBJECT DeviceObject,
1980 IN BOOLEAN FixErrors
1981 )
1982 {
1983 UNIMPLEMENTED;
1984 return STATUS_NOT_IMPLEMENTED;
1985 }
1986
1987 /*
1988 * @unimplemented
1989 */
1990 NTSTATUS
1991 STDCALL
1992 IoVolumeDeviceToDosName(
1993 IN PVOID VolumeDeviceObject,
1994 OUT PUNICODE_STRING DosName
1995 )
1996 {
1997 UNIMPLEMENTED;
1998 return STATUS_NOT_IMPLEMENTED;
1999 }
2000
2001 /*
2002 * @unimplemented
2003 */
2004 NTSTATUS
2005 STDCALL
2006 IoWritePartitionTableEx(
2007 IN PDEVICE_OBJECT DeviceObject,
2008 IN struct _DRIVE_LAYOUT_INFORMATION_EX* DriveLayfout
2009 )
2010 {
2011 UNIMPLEMENTED;
2012 return STATUS_NOT_IMPLEMENTED;
2013 }
2014
2015 /*
2016 * @implemented
2017 */
2018 NTSTATUS FASTCALL
2019 IoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
2020 ULONG SectorSize,
2021 BOOLEAN ReturnRecognizedPartitions,
2022 PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
2023 {
2024 return(HalIoReadPartitionTable(DeviceObject,
2025 SectorSize,
2026 ReturnRecognizedPartitions,
2027 PartitionBuffer));
2028 }
2029
2030
2031 NTSTATUS FASTCALL
2032 IoSetPartitionInformation(PDEVICE_OBJECT DeviceObject,
2033 ULONG SectorSize,
2034 ULONG PartitionNumber,
2035 ULONG PartitionType)
2036 {
2037 return(HalIoSetPartitionInformation(DeviceObject,
2038 SectorSize,
2039 PartitionNumber,
2040 PartitionType));
2041 }
2042
2043
2044 NTSTATUS FASTCALL
2045 IoWritePartitionTable(PDEVICE_OBJECT DeviceObject,
2046 ULONG SectorSize,
2047 ULONG SectorsPerTrack,
2048 ULONG NumberOfHeads,
2049 PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
2050 {
2051 return(HalIoWritePartitionTable(DeviceObject,
2052 SectorSize,
2053 SectorsPerTrack,
2054 NumberOfHeads,
2055 PartitionBuffer));
2056 }
2057 /* EOF */