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