20a90697f60b44b0ac9197c6cfc953ca56b231df
[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 BOOLEAN
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 FALSE;
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 FALSE;
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 (hKey &&
448 DriveType == DOSDEVICE_DRIVE_FIXED &&
449 Signature)
450 {
451 DiskMountInfo.Signature = Signature;
452 DiskMountInfo.StartingOffset = StartingOffset;
453 swprintf(DriveNameBuffer, DiskMountString, L'A' + DriveNumber);
454 RtlInitUnicodeString(&DriveName, DriveNameBuffer);
455
456 Status = ZwSetValueKey(hKey,
457 &DriveName,
458 0,
459 REG_BINARY,
460 &DiskMountInfo,
461 sizeof(DiskMountInfo));
462 if (!NT_SUCCESS(Status))
463 {
464 DPRINT1("ZwCreateValueKey failed for %wZ, status=%x\n", &DriveName, Status);
465 }
466 }
467 return TRUE;
468 }
469
470 ULONG
471 xHalpGetRDiskCount(VOID)
472 {
473 NTSTATUS Status;
474 UNICODE_STRING ArcName;
475 PWCHAR ArcNameBuffer;
476 OBJECT_ATTRIBUTES ObjectAttributes;
477 HANDLE DirectoryHandle;
478 POBJECT_DIRECTORY_INFORMATION DirectoryInfo;
479 ULONG Skip;
480 ULONG ResultLength;
481 ULONG CurrentRDisk;
482 ULONG RDiskCount;
483 BOOLEAN First = TRUE;
484 ULONG Count;
485
486 DirectoryInfo = ExAllocatePool(PagedPool, 2 * PAGE_SIZE);
487 if (DirectoryInfo == NULL)
488 {
489 return 0;
490 }
491
492 RtlInitUnicodeString(&ArcName, L"\\ArcName");
493 InitializeObjectAttributes(&ObjectAttributes,
494 &ArcName,
495 0,
496 NULL,
497 NULL);
498
499 Status = ZwOpenDirectoryObject (&DirectoryHandle,
500 SYMBOLIC_LINK_ALL_ACCESS,
501 &ObjectAttributes);
502 if (!NT_SUCCESS(Status))
503 {
504 DPRINT1("ZwOpenDirectoryObject for %wZ failed, status=%lx\n", &ArcName, Status);
505 ExFreePool(DirectoryInfo);
506 return 0;
507 }
508
509 RDiskCount = 0;
510 Skip = 0;
511 while (NT_SUCCESS(Status))
512 {
513 Status = NtQueryDirectoryObject (DirectoryHandle,
514 DirectoryInfo,
515 2 * PAGE_SIZE,
516 FALSE,
517 First,
518 &Skip,
519 &ResultLength);
520 First = FALSE;
521 if (NT_SUCCESS(Status))
522 {
523 Count = 0;
524 while (DirectoryInfo[Count].ObjectName.Buffer)
525 {
526 DPRINT("Count %x\n", Count);
527 DirectoryInfo[Count].ObjectName.Buffer[DirectoryInfo[Count].ObjectName.Length / sizeof(WCHAR)] = 0;
528 ArcNameBuffer = DirectoryInfo[Count].ObjectName.Buffer;
529 if (DirectoryInfo[Count].ObjectName.Length >= sizeof(L"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR) &&
530 !_wcsnicmp(ArcNameBuffer, L"multi(0)disk(0)rdisk(", (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR)))
531 {
532 DPRINT("%S\n", ArcNameBuffer);
533 ArcNameBuffer += (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR);
534 CurrentRDisk = 0;
535 while (iswdigit(*ArcNameBuffer))
536 {
537 CurrentRDisk = CurrentRDisk * 10 + *ArcNameBuffer - L'0';
538 ArcNameBuffer++;
539 }
540 if (!_wcsicmp(ArcNameBuffer, L")") &&
541 CurrentRDisk >= RDiskCount)
542 {
543 RDiskCount = CurrentRDisk + 1;
544 }
545 }
546 Count++;
547 }
548 }
549 }
550 ExFreePool(DirectoryInfo);
551 return RDiskCount;
552 }
553
554 NTSTATUS
555 xHalpGetDiskNumberFromRDisk(ULONG RDisk, PULONG DiskNumber)
556 {
557 WCHAR NameBuffer[80];
558 UNICODE_STRING ArcName;
559 UNICODE_STRING LinkName;
560 OBJECT_ATTRIBUTES ObjectAttributes;
561 HANDLE LinkHandle;
562 NTSTATUS Status;
563
564 swprintf(NameBuffer,
565 L"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
566 RDisk);
567
568 RtlInitUnicodeString(&ArcName, NameBuffer);
569 InitializeObjectAttributes(&ObjectAttributes,
570 &ArcName,
571 0,
572 NULL,
573 NULL);
574 Status = ZwOpenSymbolicLinkObject(&LinkHandle,
575 SYMBOLIC_LINK_ALL_ACCESS,
576 &ObjectAttributes);
577 if (!NT_SUCCESS(Status))
578 {
579 DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName, Status);
580 return Status;
581 }
582
583 LinkName.Buffer = NameBuffer;
584 LinkName.Length = 0;
585 LinkName.MaximumLength = sizeof(NameBuffer);
586 Status = ZwQuerySymbolicLinkObject(LinkHandle,
587 &LinkName,
588 NULL);
589 ZwClose(LinkHandle);
590 if (!NT_SUCCESS(Status))
591 {
592 DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status);
593 return Status;
594 }
595 if (LinkName.Length < sizeof(L"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR) ||
596 LinkName.Length >= sizeof(NameBuffer))
597 {
598 return STATUS_UNSUCCESSFUL;
599 }
600
601 NameBuffer[LinkName.Length / sizeof(WCHAR)] = 0;
602 if (_wcsnicmp(NameBuffer, L"\\Device\\Harddisk", (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR)))
603 {
604 return STATUS_UNSUCCESSFUL;
605 }
606 LinkName.Buffer += (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR);
607
608 if (!iswdigit(*LinkName.Buffer))
609 {
610 return STATUS_UNSUCCESSFUL;
611 }
612 *DiskNumber = 0;
613 while (iswdigit(*LinkName.Buffer))
614 {
615 *DiskNumber = *DiskNumber * 10 + *LinkName.Buffer - L'0';
616 LinkName.Buffer++;
617 }
618 if (_wcsicmp(LinkName.Buffer, L"\\Partition0"))
619 {
620 return STATUS_UNSUCCESSFUL;
621 }
622 return STATUS_SUCCESS;
623 }
624
625
626 VOID FASTCALL
627 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
628 IN PSTRING NtDeviceName,
629 OUT PUCHAR NtSystemPath,
630 OUT PSTRING NtSystemPathString)
631 {
632 PDRIVE_LAYOUT_INFORMATION *LayoutArray;
633 PCONFIGURATION_INFORMATION ConfigInfo;
634 OBJECT_ATTRIBUTES ObjectAttributes;
635 IO_STATUS_BLOCK StatusBlock;
636 UNICODE_STRING UnicodeString1;
637 UNICODE_STRING UnicodeString2;
638 HANDLE FileHandle;
639 PWSTR Buffer1;
640 PWSTR Buffer2;
641 ULONG i, j, k;
642 ULONG DiskNumber;
643 ULONG RDisk;
644 NTSTATUS Status;
645 HANDLE hKey;
646 ULONG Length;
647 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
648 PREG_DISK_MOUNT_INFO DiskMountInfo;
649 ULONG RDiskCount;
650
651 DPRINT("xHalIoAssignDriveLetters()\n");
652
653 ConfigInfo = IoGetConfigurationInformation();
654
655 RDiskCount = xHalpGetRDiskCount();
656
657 DPRINT1("RDiskCount %d\n", RDiskCount);
658
659 Buffer1 = (PWSTR)ExAllocatePool(PagedPool,
660 64 * sizeof(WCHAR));
661 Buffer2 = (PWSTR)ExAllocatePool(PagedPool,
662 32 * sizeof(WCHAR));
663
664 PartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(PagedPool,
665 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO));
666
667 DiskMountInfo = (PREG_DISK_MOUNT_INFO) PartialInformation->Data;
668
669 /* Open or Create the 'MountedDevices' key */
670 RtlInitUnicodeString(&UnicodeString1, L"\\Registry\\Machine\\SYSTEM\\MountedDevices");
671 InitializeObjectAttributes(&ObjectAttributes,
672 &UnicodeString1,
673 OBJ_CASE_INSENSITIVE,
674 NULL,
675 NULL);
676 Status = ZwOpenKey(&hKey,
677 KEY_ALL_ACCESS,
678 &ObjectAttributes);
679 if (!NT_SUCCESS(Status))
680 {
681 Status = ZwCreateKey(&hKey,
682 KEY_ALL_ACCESS,
683 &ObjectAttributes,
684 0,
685 NULL,
686 REG_OPTION_NON_VOLATILE,
687 NULL);
688 }
689 if (!NT_SUCCESS(Status))
690 {
691 hKey = NULL;
692 DPRINT1("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1, Status);
693 }
694
695 /* Create PhysicalDrive links */
696 DPRINT("Physical disk drives: %d\n", ConfigInfo->DiskCount);
697 for (i = 0; i < ConfigInfo->DiskCount; i++)
698 {
699 swprintf(Buffer1,
700 L"\\Device\\Harddisk%d\\Partition0",
701 i);
702 RtlInitUnicodeString(&UnicodeString1,
703 Buffer1);
704
705 InitializeObjectAttributes(&ObjectAttributes,
706 &UnicodeString1,
707 0,
708 NULL,
709 NULL);
710
711 Status = ZwOpenFile(&FileHandle,
712 0x10001,
713 &ObjectAttributes,
714 &StatusBlock,
715 1,
716 FILE_SYNCHRONOUS_IO_NONALERT);
717 if (NT_SUCCESS(Status))
718 {
719 ZwClose(FileHandle);
720
721 swprintf(Buffer2,
722 L"\\??\\PhysicalDrive%d",
723 i);
724 RtlInitUnicodeString(&UnicodeString2,
725 Buffer2);
726
727 DPRINT("Creating link: %S ==> %S\n",
728 Buffer2,
729 Buffer1);
730
731 IoCreateSymbolicLink(&UnicodeString2,
732 &UnicodeString1);
733 }
734 }
735
736 /* Initialize layout array */
737 LayoutArray = ExAllocatePool(NonPagedPool,
738 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
739 RtlZeroMemory(LayoutArray,
740 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
741 for (i = 0; i < ConfigInfo->DiskCount; i++)
742 {
743 swprintf(Buffer1,
744 L"\\Device\\Harddisk%d\\Partition0",
745 i);
746 RtlInitUnicodeString(&UnicodeString1,
747 Buffer1);
748
749 Status = xHalQueryDriveLayout(&UnicodeString1,
750 &LayoutArray[i]);
751 if (!NT_SUCCESS(Status))
752 {
753 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
754 Status);
755 LayoutArray[i] = NULL;
756 continue;
757 }
758 /* We don't use the RewritePartition value while mounting the disks.
759 * We use this value for marking pre-assigned (registry) partitions.
760 */
761 for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
762 {
763 LayoutArray[i]->PartitionEntry[j].RewritePartition = FALSE;
764 }
765 }
766
767 #ifndef NDEBUG
768 /* Dump layout array */
769 for (i = 0; i < ConfigInfo->DiskCount; i++)
770 {
771 DPRINT("Harddisk %d:\n",
772 i);
773
774 if (LayoutArray[i] == NULL)
775 continue;
776
777 DPRINT("Logical partitions: %d\n",
778 LayoutArray[i]->PartitionCount);
779
780 for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
781 {
782 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
783 j,
784 LayoutArray[i]->PartitionEntry[j].PartitionNumber,
785 LayoutArray[i]->PartitionEntry[j].BootIndicator,
786 LayoutArray[i]->PartitionEntry[j].PartitionType,
787 LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart,
788 LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart);
789 }
790 }
791 #endif
792
793 /* Assign pre-assigned (registry) partitions */
794 if (hKey)
795 {
796 for (k = 2; k < 26; k++)
797 {
798 swprintf(Buffer1, DiskMountString, L'A' + k);
799 RtlInitUnicodeString(&UnicodeString1, Buffer1);
800 Status = ZwQueryValueKey(hKey,
801 &UnicodeString1,
802 KeyValuePartialInformation,
803 PartialInformation,
804 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO),
805 &Length);
806 if (NT_SUCCESS(Status) &&
807 PartialInformation->Type == REG_BINARY &&
808 PartialInformation->DataLength == sizeof(REG_DISK_MOUNT_INFO))
809 {
810 DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1, DiskMountInfo->Signature,
811 DiskMountInfo->StartingOffset.u.HighPart, DiskMountInfo->StartingOffset.u.LowPart);
812 {
813 BOOLEAN Found = FALSE;
814 for (i = 0; i < ConfigInfo->DiskCount; i++)
815 {
816 DPRINT("%x\n", LayoutArray[i]->Signature);
817 if (LayoutArray[i] &&
818 LayoutArray[i]->Signature &&
819 LayoutArray[i]->Signature == DiskMountInfo->Signature)
820 {
821 for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
822 {
823 if (LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart == DiskMountInfo->StartingOffset.QuadPart)
824 {
825 if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType) &&
826 LayoutArray[i]->PartitionEntry[j].RewritePartition == FALSE)
827 {
828 swprintf(Buffer2,
829 L"\\Device\\Harddisk%d\\Partition%d",
830 i,
831 LayoutArray[i]->PartitionEntry[j].PartitionNumber);
832 RtlInitUnicodeString(&UnicodeString2,
833 Buffer2);
834
835 /* Assign drive */
836 DPRINT(" %wZ\n", &UnicodeString2);
837 Found = HalpAssignDrive(&UnicodeString2,
838 k,
839 DOSDEVICE_DRIVE_FIXED,
840 DiskMountInfo->Signature,
841 DiskMountInfo->StartingOffset,
842 NULL);
843 /* Mark the partition as assigned */
844 LayoutArray[i]->PartitionEntry[j].RewritePartition = TRUE;
845 }
846 break;
847 }
848 }
849 }
850 }
851 if (Found == FALSE)
852 {
853 /* We didn't find a partition for this entry, remove them. */
854 Status = ZwDeleteValueKey(hKey, &UnicodeString1);
855 }
856 }
857 }
858 }
859 }
860
861 /* Assign bootable partition on first harddisk */
862 DPRINT("Assigning bootable primary partition on first harddisk:\n");
863 if (RDiskCount > 0)
864 {
865 Status = xHalpGetDiskNumberFromRDisk(0, &DiskNumber);
866 if (NT_SUCCESS(Status) &&
867 DiskNumber < ConfigInfo->DiskCount &&
868 LayoutArray[DiskNumber])
869 {
870 /* Search for bootable partition */
871 for (j = 0; j < PARTITION_TBL_SIZE && j < LayoutArray[DiskNumber]->PartitionCount; j++)
872 {
873 if ((LayoutArray[DiskNumber]->PartitionEntry[j].BootIndicator == TRUE) &&
874 IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
875 {
876 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE)
877 {
878 swprintf(Buffer2,
879 L"\\Device\\Harddisk%lu\\Partition%d",
880 DiskNumber,
881 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
882 RtlInitUnicodeString(&UnicodeString2,
883 Buffer2);
884
885 /* Assign drive */
886 DPRINT(" %wZ\n", &UnicodeString2);
887 HalpAssignDrive(&UnicodeString2,
888 AUTO_DRIVE,
889 DOSDEVICE_DRIVE_FIXED,
890 LayoutArray[DiskNumber]->Signature,
891 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
892 hKey);
893 /* Mark the partition as assigned */
894 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
895 }
896 break;
897 }
898 }
899 }
900 }
901
902 /* Assign remaining primary partitions */
903 DPRINT("Assigning remaining primary partitions:\n");
904 for (RDisk = 0; RDisk < RDiskCount; RDisk++)
905 {
906 Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber);
907 if (NT_SUCCESS(Status) &&
908 DiskNumber < ConfigInfo->DiskCount &&
909 LayoutArray[DiskNumber])
910 {
911 /* Search for primary partitions */
912 for (j = 0; (j < PARTITION_TBL_SIZE) && (j < LayoutArray[DiskNumber]->PartitionCount); j++)
913 {
914 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
915 IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
916 {
917 swprintf(Buffer2,
918 L"\\Device\\Harddisk%d\\Partition%d",
919 DiskNumber,
920 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
921 RtlInitUnicodeString(&UnicodeString2,
922 Buffer2);
923
924 /* Assign drive */
925 DPRINT(" %wZ\n",
926 &UnicodeString2);
927 HalpAssignDrive(&UnicodeString2,
928 AUTO_DRIVE,
929 DOSDEVICE_DRIVE_FIXED,
930 LayoutArray[DiskNumber]->Signature,
931 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
932 hKey);
933 /* Mark the partition as assigned */
934 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
935 }
936 }
937 }
938 }
939
940 /* Assign extended (logical) partitions */
941 DPRINT("Assigning extended (logical) partitions:\n");
942 for (RDisk = 0; RDisk < RDiskCount; RDisk++)
943 {
944 Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber);
945 if (NT_SUCCESS(Status) &&
946 DiskNumber < ConfigInfo->DiskCount &&
947 LayoutArray[DiskNumber])
948 {
949 /* Search for extended partitions */
950 for (j = PARTITION_TBL_SIZE; j < LayoutArray[DiskNumber]->PartitionCount; j++)
951 {
952 if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) &&
953 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
954 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0)
955 {
956 swprintf(Buffer2,
957 L"\\Device\\Harddisk%d\\Partition%d",
958 DiskNumber,
959 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
960 RtlInitUnicodeString(&UnicodeString2,
961 Buffer2);
962
963 /* Assign drive */
964 DPRINT(" %wZ\n",
965 &UnicodeString2);
966 HalpAssignDrive(&UnicodeString2,
967 AUTO_DRIVE,
968 DOSDEVICE_DRIVE_FIXED,
969 LayoutArray[DiskNumber]->Signature,
970 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
971 hKey);
972 /* Mark the partition as assigned */
973 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
974 }
975 }
976 }
977 }
978
979 /* Assign remaining primary partitions without an arc-name */
980 DPRINT("Assigning remaining primary partitions:\n");
981 for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++)
982 {
983 if (LayoutArray[DiskNumber])
984 {
985 /* Search for primary partitions */
986 for (j = 0; (j < PARTITION_TBL_SIZE) && (j < LayoutArray[DiskNumber]->PartitionCount); j++)
987 {
988 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
989 IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
990 {
991 swprintf(Buffer2,
992 L"\\Device\\Harddisk%d\\Partition%d",
993 DiskNumber,
994 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
995 RtlInitUnicodeString(&UnicodeString2,
996 Buffer2);
997
998 /* Assign drive */
999 DPRINT(" %wZ\n",
1000 &UnicodeString2);
1001 HalpAssignDrive(&UnicodeString2,
1002 AUTO_DRIVE,
1003 DOSDEVICE_DRIVE_FIXED,
1004 LayoutArray[DiskNumber]->Signature,
1005 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
1006 hKey);
1007 /* Mark the partition as assigned */
1008 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
1009 }
1010 }
1011 }
1012 }
1013
1014 /* Assign extended (logical) partitions without an arc-name */
1015 DPRINT("Assigning extended (logical) partitions:\n");
1016 for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++)
1017 {
1018 if (LayoutArray[DiskNumber])
1019 {
1020 /* Search for extended partitions */
1021 for (j = PARTITION_TBL_SIZE; j < LayoutArray[DiskNumber]->PartitionCount; j++)
1022 {
1023 if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) &&
1024 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
1025 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0)
1026 {
1027 swprintf(Buffer2,
1028 L"\\Device\\Harddisk%d\\Partition%d",
1029 DiskNumber,
1030 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
1031 RtlInitUnicodeString(&UnicodeString2,
1032 Buffer2);
1033
1034 /* Assign drive */
1035 DPRINT(" %wZ\n",
1036 &UnicodeString2);
1037 HalpAssignDrive(&UnicodeString2,
1038 AUTO_DRIVE,
1039 DOSDEVICE_DRIVE_FIXED,
1040 LayoutArray[DiskNumber]->Signature,
1041 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
1042 hKey);
1043 /* Mark the partition as assigned */
1044 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
1045 }
1046 }
1047 }
1048 }
1049
1050 /* Assign removable disk drives */
1051 DPRINT("Assigning removable disk drives:\n");
1052 for (i = 0; i < ConfigInfo->DiskCount; i++)
1053 {
1054 if (LayoutArray[i])
1055 {
1056 /* Search for virtual partitions */
1057 if (LayoutArray[i]->PartitionCount == 1 &&
1058 LayoutArray[i]->PartitionEntry[0].PartitionType == 0)
1059 {
1060 swprintf(Buffer2,
1061 L"\\Device\\Harddisk%d\\Partition1",
1062 i);
1063 RtlInitUnicodeString(&UnicodeString2,
1064 Buffer2);
1065
1066 /* Assign drive */
1067 DPRINT(" %wZ\n",
1068 &UnicodeString2);
1069 HalpAssignDrive(&UnicodeString2,
1070 AUTO_DRIVE,
1071 DOSDEVICE_DRIVE_REMOVABLE,
1072 0,
1073 (LARGE_INTEGER)0LL,
1074 hKey);
1075 }
1076 }
1077 }
1078
1079 /* Free layout array */
1080 for (i = 0; i < ConfigInfo->DiskCount; i++)
1081 {
1082 if (LayoutArray[i] != NULL)
1083 ExFreePool(LayoutArray[i]);
1084 }
1085 ExFreePool(LayoutArray);
1086
1087 /* Assign floppy drives */
1088 DPRINT("Floppy drives: %d\n", ConfigInfo->FloppyCount);
1089 for (i = 0; i < ConfigInfo->FloppyCount; i++)
1090 {
1091 swprintf(Buffer1,
1092 L"\\Device\\Floppy%d",
1093 i);
1094 RtlInitUnicodeString(&UnicodeString1,
1095 Buffer1);
1096
1097 /* Assign drive letters A: or B: or first free drive letter */
1098 DPRINT(" %wZ\n",
1099 &UnicodeString1);
1100 HalpAssignDrive(&UnicodeString1,
1101 (i < 2) ? i : AUTO_DRIVE,
1102 DOSDEVICE_DRIVE_REMOVABLE,
1103 0,
1104 (LARGE_INTEGER)0LL,
1105 hKey);
1106 }
1107
1108 /* Assign cdrom drives */
1109 DPRINT("CD-Rom drives: %d\n", ConfigInfo->CdRomCount);
1110 for (i = 0; i < ConfigInfo->CdRomCount; i++)
1111 {
1112 swprintf(Buffer1,
1113 L"\\Device\\CdRom%d",
1114 i);
1115 RtlInitUnicodeString(&UnicodeString1,
1116 Buffer1);
1117
1118 /* Assign first free drive letter */
1119 DPRINT(" %wZ\n", &UnicodeString1);
1120 HalpAssignDrive(&UnicodeString1,
1121 AUTO_DRIVE,
1122 DOSDEVICE_DRIVE_CDROM,
1123 0,
1124 (LARGE_INTEGER)0LL,
1125 hKey);
1126 }
1127
1128 /* Anything else to do? */
1129
1130 ExFreePool(PartialInformation);
1131 ExFreePool(Buffer2);
1132 ExFreePool(Buffer1);
1133 if (hKey)
1134 {
1135 ZwClose(hKey);
1136 }
1137 }
1138
1139
1140 NTSTATUS FASTCALL
1141 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
1142 ULONG SectorSize,
1143 BOOLEAN ReturnRecognizedPartitions,
1144 PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
1145 {
1146 LARGE_INTEGER RealPartitionOffset;
1147 ULONGLONG PartitionOffset;
1148 #if defined(__GNUC__)
1149 ULONGLONG nextPartitionOffset = 0LL;
1150 #else
1151 ULONGLONG nextPartitionOffset = 0;
1152 #endif
1153 ULONGLONG containerOffset;
1154 NTSTATUS Status;
1155 PPARTITION_SECTOR PartitionSector;
1156 PDRIVE_LAYOUT_INFORMATION LayoutBuffer;
1157 ULONG i;
1158 ULONG Count = 0;
1159 ULONG Number = 1;
1160 BOOLEAN ExtendedFound = FALSE;
1161 PVOID MbrBuffer;
1162 DISK_MANAGER DiskManager = NoDiskManager;
1163
1164 DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
1165 DeviceObject,
1166 SectorSize,
1167 ReturnRecognizedPartitions,
1168 PartitionBuffer);
1169
1170 *PartitionBuffer = NULL;
1171
1172 /* Check sector size */
1173 if (SectorSize < 512)
1174 SectorSize = 512;
1175 if (SectorSize > 4096)
1176 SectorSize = 4096;
1177
1178 /* Check for 'Ontrack Disk Manager' */
1179 HalExamineMBR(DeviceObject,
1180 SectorSize,
1181 0x54,
1182 &MbrBuffer);
1183 if (MbrBuffer != NULL)
1184 {
1185 DPRINT("Found 'Ontrack Disk Manager'\n");
1186 DiskManager = OntrackDiskManager;
1187 ExFreePool(MbrBuffer);
1188 }
1189
1190 /* Check for 'EZ-Drive' */
1191 HalExamineMBR(DeviceObject,
1192 SectorSize,
1193 0x55,
1194 &MbrBuffer);
1195 if (MbrBuffer != NULL)
1196 {
1197 DPRINT("Found 'EZ-Drive'\n");
1198 DiskManager = EZ_Drive;
1199 ExFreePool(MbrBuffer);
1200 }
1201
1202 PartitionSector = (PPARTITION_SECTOR)ExAllocatePool(PagedPool,
1203 SectorSize);
1204 if (PartitionSector == NULL)
1205 {
1206 return(STATUS_INSUFFICIENT_RESOURCES);
1207 }
1208
1209 LayoutBuffer = (PDRIVE_LAYOUT_INFORMATION)ExAllocatePool(NonPagedPool,
1210 0x1000);
1211 if (LayoutBuffer == NULL)
1212 {
1213 ExFreePool(PartitionSector);
1214 return(STATUS_INSUFFICIENT_RESOURCES);
1215 }
1216
1217 RtlZeroMemory(LayoutBuffer,
1218 0x1000);
1219
1220 #if defined(__GNUC__)
1221 PartitionOffset = 0ULL;
1222 containerOffset = 0ULL;
1223 #else
1224 PartitionOffset = 0;
1225 containerOffset = 0;
1226 #endif
1227
1228 do
1229 {
1230 DPRINT("PartitionOffset: %I64u\n", PartitionOffset / SectorSize);
1231
1232 /* Handle disk managers */
1233 if (DiskManager == OntrackDiskManager)
1234 {
1235 /* Shift offset by 63 sectors */
1236 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
1237 }
1238 #if defined(__GNUC__)
1239 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
1240 #else
1241 else if (DiskManager == EZ_Drive && PartitionOffset == 0)
1242 #endif
1243 {
1244 /* Use sector 1 instead of sector 0 */
1245 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
1246 }
1247 else
1248 {
1249 RealPartitionOffset.QuadPart = PartitionOffset;
1250 }
1251
1252 DPRINT ("RealPartitionOffset: %I64u\n",
1253 RealPartitionOffset.QuadPart / SectorSize);
1254
1255 Status = xHalpReadSector (DeviceObject,
1256 SectorSize,
1257 &RealPartitionOffset,
1258 PartitionSector);
1259 if (!NT_SUCCESS(Status))
1260 {
1261 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
1262 Status);
1263 ExFreePool (PartitionSector);
1264 ExFreePool (LayoutBuffer);
1265 return Status;
1266 }
1267
1268 /* Check the boot sector id */
1269 DPRINT("Magic %x\n", PartitionSector->Magic);
1270 if (PartitionSector->Magic != PARTITION_MAGIC)
1271 {
1272 DPRINT ("Invalid partition sector magic\n");
1273 ExFreePool (PartitionSector);
1274 *PartitionBuffer = LayoutBuffer;
1275 return STATUS_SUCCESS;
1276 }
1277
1278 #ifndef NDEBUG
1279 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1280 {
1281 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
1282 i,
1283 PartitionSector->Partition[i].BootFlags,
1284 PartitionSector->Partition[i].PartitionType,
1285 PartitionSector->Partition[i].StartingHead,
1286 PartitionSector->Partition[i].StartingSector & 0x3f,
1287 (((PartitionSector->Partition[i].StartingSector) & 0xc0) << 2) +
1288 PartitionSector->Partition[i].StartingCylinder,
1289 PartitionSector->Partition[i].EndingHead,
1290 PartitionSector->Partition[i].EndingSector & 0x3f,
1291 (((PartitionSector->Partition[i].EndingSector) & 0xc0) << 2) +
1292 PartitionSector->Partition[i].EndingCylinder,
1293 PartitionSector->Partition[i].StartingBlock,
1294 PartitionSector->Partition[i].SectorCount);
1295 }
1296 #endif
1297
1298 #if defined(__GNUC__)
1299 if (PartitionOffset == 0ULL)
1300 #else
1301 if (PartitionOffset == 0)
1302 #endif
1303 {
1304 LayoutBuffer->Signature = PartitionSector->Signature;
1305 DPRINT("Disk signature: %lx\n", LayoutBuffer->Signature);
1306 }
1307
1308 ExtendedFound = FALSE;
1309
1310 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1311 {
1312 if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
1313 {
1314 ExtendedFound = TRUE;
1315 if ((ULONGLONG) containerOffset == (ULONGLONG) 0)
1316 {
1317 containerOffset = PartitionOffset;
1318 }
1319 nextPartitionOffset = (ULONGLONG) containerOffset +
1320 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
1321 (ULONGLONG) SectorSize;
1322 }
1323
1324 if ((ReturnRecognizedPartitions == FALSE) ||
1325 ((ReturnRecognizedPartitions == TRUE) &&
1326 !IsContainerPartition(PartitionSector->Partition[i].PartitionType) &&
1327 PartitionSector->Partition[i].PartitionType != PARTITION_ENTRY_UNUSED))
1328 {
1329 /* handle normal partition */
1330 DPRINT("Partition %u: Normal Partition\n", i);
1331 Count = LayoutBuffer->PartitionCount;
1332 DPRINT("Logical Partition %u\n", Count);
1333
1334 if (PartitionSector->Partition[i].StartingBlock == 0)
1335 {
1336 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart = 0;
1337 }
1338 else if (IsContainerPartition(PartitionSector->Partition[i].PartitionType))
1339 {
1340 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
1341 (ULONGLONG) containerOffset +
1342 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
1343 (ULONGLONG) SectorSize;
1344 }
1345 else
1346 {
1347 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
1348 (ULONGLONG)PartitionOffset +
1349 ((ULONGLONG)PartitionSector->Partition[i].StartingBlock * (ULONGLONG)SectorSize);
1350 }
1351 LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart =
1352 (ULONGLONG)PartitionSector->Partition[i].SectorCount * (ULONGLONG)SectorSize;
1353 LayoutBuffer->PartitionEntry[Count].HiddenSectors =
1354 PartitionSector->Partition[i].StartingBlock;
1355
1356 if (!IsContainerPartition(PartitionSector->Partition[i].PartitionType) &&
1357 PartitionSector->Partition[i].PartitionType != PARTITION_ENTRY_UNUSED)
1358 {
1359 LayoutBuffer->PartitionEntry[Count].RecognizedPartition = TRUE;
1360 /* WinXP returns garbage as PartitionNumber */
1361 LayoutBuffer->PartitionEntry[Count].PartitionNumber = Number;
1362 Number++;
1363 }
1364 else
1365 {
1366 LayoutBuffer->PartitionEntry[Count].RecognizedPartition = FALSE;
1367 LayoutBuffer->PartitionEntry[Count].PartitionNumber = 0;
1368 }
1369
1370 LayoutBuffer->PartitionEntry[Count].PartitionType =
1371 PartitionSector->Partition[i].PartitionType;
1372 LayoutBuffer->PartitionEntry[Count].BootIndicator =
1373 (PartitionSector->Partition[i].BootFlags & 0x80)?TRUE:FALSE;
1374 LayoutBuffer->PartitionEntry[Count].RewritePartition = FALSE;
1375
1376 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x rec: %d\n",
1377 Count,
1378 LayoutBuffer->PartitionEntry[Count].PartitionNumber,
1379 LayoutBuffer->PartitionEntry[Count].BootIndicator,
1380 LayoutBuffer->PartitionEntry[Count].PartitionType,
1381 LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart,
1382 LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart,
1383 LayoutBuffer->PartitionEntry[Count].RecognizedPartition);
1384
1385 LayoutBuffer->PartitionCount++;
1386 }
1387 }
1388
1389 PartitionOffset = nextPartitionOffset;
1390 }
1391 while (ExtendedFound == TRUE);
1392
1393 *PartitionBuffer = LayoutBuffer;
1394 ExFreePool(PartitionSector);
1395
1396 return(STATUS_SUCCESS);
1397 }
1398
1399
1400 NTSTATUS FASTCALL
1401 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
1402 IN ULONG SectorSize,
1403 IN ULONG PartitionNumber,
1404 IN ULONG PartitionType)
1405 {
1406 PPARTITION_SECTOR PartitionSector;
1407 LARGE_INTEGER RealPartitionOffset;
1408 ULONGLONG PartitionOffset;
1409 #if defined(__GNUC__)
1410 ULONGLONG nextPartitionOffset = 0LL;
1411 #else
1412 ULONGLONG nextPartitionOffset = 0;
1413 #endif
1414 ULONGLONG containerOffset;
1415 NTSTATUS Status;
1416 ULONG i;
1417 ULONG Number = 1;
1418 BOOLEAN ExtendedFound = FALSE;
1419 DISK_MANAGER DiskManager = NoDiskManager;
1420
1421 DPRINT ("xHalIoSetPartitionInformation(%p %lu %lu %lu)\n",
1422 DeviceObject,
1423 SectorSize,
1424 PartitionNumber,
1425 PartitionType);
1426
1427 /* Check sector size */
1428 if (SectorSize < 512)
1429 SectorSize = 512;
1430 if (SectorSize > 4096)
1431 SectorSize = 4096;
1432
1433 /* Check for 'Ontrack Disk Manager' */
1434 HalExamineMBR (DeviceObject,
1435 SectorSize,
1436 0x54,
1437 (PVOID*)(PVOID)&PartitionSector);
1438 if (PartitionSector != NULL)
1439 {
1440 DPRINT ("Found 'Ontrack Disk Manager'\n");
1441 DiskManager = OntrackDiskManager;
1442 ExFreePool (PartitionSector);
1443 }
1444
1445 /* Check for 'EZ-Drive' */
1446 HalExamineMBR (DeviceObject,
1447 SectorSize,
1448 0x55,
1449 (PVOID*)(PVOID)&PartitionSector);
1450 if (PartitionSector != NULL)
1451 {
1452 DPRINT ("Found 'EZ-Drive'\n");
1453 DiskManager = EZ_Drive;
1454 ExFreePool (PartitionSector);
1455 }
1456
1457 /* Allocate partition sector */
1458 PartitionSector = (PPARTITION_SECTOR) ExAllocatePool (PagedPool,
1459 SectorSize);
1460 if (PartitionSector == NULL)
1461 {
1462 return STATUS_INSUFFICIENT_RESOURCES;
1463 }
1464
1465 #if defined(__GNUC__)
1466 PartitionOffset = 0ULL;
1467 containerOffset = 0ULL;
1468 #else
1469 PartitionOffset = 0;
1470 containerOffset = 0;
1471 #endif
1472
1473 do
1474 {
1475 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset / SectorSize);
1476
1477 /* Handle disk managers */
1478 if (DiskManager == OntrackDiskManager)
1479 {
1480 /* Shift offset by 63 sectors */
1481 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
1482 }
1483 #if defined(__GNUC__)
1484 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
1485 #else
1486 else if (DiskManager == EZ_Drive && PartitionOffset == 0)
1487 #endif
1488 {
1489 /* Use sector 1 instead of sector 0 */
1490 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
1491 }
1492 else
1493 {
1494 RealPartitionOffset.QuadPart = PartitionOffset;
1495 }
1496
1497 DPRINT ("RealPartitionOffset: %I64u\n",
1498 RealPartitionOffset.QuadPart / SectorSize);
1499
1500 Status = xHalpReadSector (DeviceObject,
1501 SectorSize,
1502 &RealPartitionOffset,
1503 PartitionSector);
1504 if (!NT_SUCCESS (Status))
1505 {
1506 DPRINT ("Failed to read partition table sector (Status = 0x%08lx)\n",
1507 Status);
1508 ExFreePool (PartitionSector);
1509 return Status;
1510 }
1511
1512 /* Check the boot sector id */
1513 DPRINT("Magic %x\n", PartitionSector->Magic);
1514 if (PartitionSector->Magic != PARTITION_MAGIC)
1515 {
1516 DPRINT ("Invalid partition sector magic\n");
1517 ExFreePool (PartitionSector);
1518 return STATUS_UNSUCCESSFUL;
1519 }
1520
1521 #ifndef NDEBUG
1522 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1523 {
1524 DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
1525 i,
1526 PartitionSector->Partition[i].BootFlags,
1527 PartitionSector->Partition[i].PartitionType,
1528 PartitionSector->Partition[i].StartingHead,
1529 PartitionSector->Partition[i].StartingSector & 0x3f,
1530 (((PartitionSector->Partition[i].StartingSector) & 0xc0) << 2) +
1531 PartitionSector->Partition[i].StartingCylinder,
1532 PartitionSector->Partition[i].EndingHead,
1533 PartitionSector->Partition[i].EndingSector & 0x3f,
1534 (((PartitionSector->Partition[i].EndingSector) & 0xc0) << 2) +
1535 PartitionSector->Partition[i].EndingCylinder,
1536 PartitionSector->Partition[i].StartingBlock,
1537 PartitionSector->Partition[i].SectorCount);
1538 }
1539 #endif
1540
1541 ExtendedFound = FALSE;
1542 for (i = 0; i < PARTITION_TBL_SIZE; i++)
1543 {
1544 if (IsContainerPartition (PartitionSector->Partition[i].PartitionType))
1545 {
1546 ExtendedFound = TRUE;
1547 #if defined(__GNUC__)
1548 if (containerOffset == 0ULL)
1549 #else
1550 if (containerOffset == 0)
1551 #endif
1552 {
1553 containerOffset = PartitionOffset;
1554 }
1555 nextPartitionOffset = containerOffset +
1556 (ULONGLONG) PartitionSector->Partition[i].StartingBlock *
1557 (ULONGLONG) SectorSize;
1558 }
1559
1560 /* Handle recognized partition */
1561 if (IsRecognizedPartition (PartitionSector->Partition[i].PartitionType))
1562 {
1563 if (Number == PartitionNumber)
1564 {
1565 /* Set partition type */
1566 PartitionSector->Partition[i].PartitionType = PartitionType;
1567
1568 /* Write partition sector */
1569 Status = xHalpWriteSector (DeviceObject,
1570 SectorSize,
1571 &RealPartitionOffset,
1572 PartitionSector);
1573 if (!NT_SUCCESS(Status))
1574 {
1575 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
1576 }
1577
1578 ExFreePool (PartitionSector);
1579 return Status;
1580 }
1581 Number++;
1582 }
1583 }
1584
1585 PartitionOffset = nextPartitionOffset;
1586 }
1587 while (ExtendedFound == TRUE);
1588
1589 ExFreePool(PartitionSector);
1590
1591 return STATUS_UNSUCCESSFUL;
1592 }
1593
1594
1595 NTSTATUS FASTCALL
1596 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
1597 IN ULONG SectorSize,
1598 IN ULONG SectorsPerTrack,
1599 IN ULONG NumberOfHeads,
1600 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
1601 {
1602 PPARTITION_SECTOR PartitionSector;
1603 LARGE_INTEGER RealPartitionOffset;
1604 ULONGLONG PartitionOffset;
1605 #if defined(__GNUC__)
1606 ULONGLONG NextPartitionOffset = 0LL;
1607 #else
1608 ULONGLONG NextPartitionOffset = 0;
1609 #endif
1610 ULONGLONG ContainerOffset;
1611 BOOLEAN ContainerEntry;
1612 DISK_MANAGER DiskManager;
1613 ULONG i;
1614 ULONG j;
1615 ULONG StartBlock;
1616 ULONG SectorCount;
1617 ULONG StartCylinder;
1618 ULONG StartSector;
1619 ULONG StartHead;
1620 ULONG EndCylinder;
1621 ULONG EndSector;
1622 ULONG EndHead;
1623 ULONG lba;
1624 ULONG x;
1625 NTSTATUS Status;
1626
1627 DPRINT ("xHalIoWritePartitionTable(%p %lu %lu %lu %p)\n",
1628 DeviceObject,
1629 SectorSize,
1630 SectorsPerTrack,
1631 NumberOfHeads,
1632 PartitionBuffer);
1633
1634 ASSERT(DeviceObject);
1635 ASSERT(PartitionBuffer);
1636
1637 DiskManager = NoDiskManager;
1638
1639 /* Check sector size */
1640 if (SectorSize < 512)
1641 SectorSize = 512;
1642 if (SectorSize > 4096)
1643 SectorSize = 4096;
1644
1645 /* Check for 'Ontrack Disk Manager' */
1646 HalExamineMBR (DeviceObject,
1647 SectorSize,
1648 0x54,
1649 (PVOID*)(PVOID)&PartitionSector);
1650 if (PartitionSector != NULL)
1651 {
1652 DPRINT ("Found 'Ontrack Disk Manager'\n");
1653 DiskManager = OntrackDiskManager;
1654 ExFreePool (PartitionSector);
1655 }
1656
1657 /* Check for 'EZ-Drive' */
1658 HalExamineMBR (DeviceObject,
1659 SectorSize,
1660 0x55,
1661 (PVOID*)(PVOID)&PartitionSector);
1662 if (PartitionSector != NULL)
1663 {
1664 DPRINT ("Found 'EZ-Drive'\n");
1665 DiskManager = EZ_Drive;
1666 ExFreePool (PartitionSector);
1667 }
1668
1669 /* Allocate partition sector */
1670 PartitionSector = (PPARTITION_SECTOR)ExAllocatePool(PagedPool,
1671 SectorSize);
1672 if (PartitionSector == NULL)
1673 {
1674 return STATUS_INSUFFICIENT_RESOURCES;
1675 }
1676
1677 Status = STATUS_SUCCESS;
1678 #if defined(__GNUC__)
1679 PartitionOffset = 0ULL;
1680 ContainerOffset = 0ULL;
1681 #else
1682 PartitionOffset = 0;
1683 ContainerOffset = 0;
1684 #endif
1685 for (i = 0; i < PartitionBuffer->PartitionCount; i += 4)
1686 {
1687 DPRINT ("PartitionOffset: %I64u\n", PartitionOffset);
1688 DPRINT ("ContainerOffset: %I64u\n", ContainerOffset);
1689
1690 /* Handle disk managers */
1691 if (DiskManager == OntrackDiskManager)
1692 {
1693 /* Shift offset by 63 sectors */
1694 RealPartitionOffset.QuadPart = PartitionOffset + (ULONGLONG)(63 * SectorSize);
1695 }
1696 #if defined(__GNUC__)
1697 else if (DiskManager == EZ_Drive && PartitionOffset == 0ULL)
1698 #else
1699 else if (DiskManager == EZ_Drive && PartitionOffset == 0)
1700 #endif
1701 {
1702 /* Use sector 1 instead of sector 0 */
1703 RealPartitionOffset.QuadPart = (ULONGLONG)SectorSize;
1704 }
1705 else
1706 {
1707 RealPartitionOffset.QuadPart = PartitionOffset;
1708 }
1709
1710 /* Write modified partition tables */
1711 if (PartitionBuffer->PartitionEntry[i].RewritePartition == TRUE ||
1712 PartitionBuffer->PartitionEntry[i + 1].RewritePartition == TRUE ||
1713 PartitionBuffer->PartitionEntry[i + 2].RewritePartition == TRUE ||
1714 PartitionBuffer->PartitionEntry[i + 3].RewritePartition == TRUE)
1715 {
1716 /* Read partition sector */
1717 Status = xHalpReadSector (DeviceObject,
1718 SectorSize,
1719 &RealPartitionOffset,
1720 PartitionSector);
1721 if (!NT_SUCCESS(Status))
1722 {
1723 DPRINT1 ("xHalpReadSector() failed (Status %lx)\n", Status);
1724 break;
1725 }
1726
1727 /* Initialize a new partition sector */
1728 if (PartitionSector->Magic != PARTITION_MAGIC)
1729 {
1730 /* Create empty partition sector */
1731 RtlZeroMemory (PartitionSector,
1732 SectorSize);
1733 PartitionSector->Magic = PARTITION_MAGIC;
1734 }
1735
1736 PartitionSector->Signature = PartitionBuffer->Signature;
1737 /* Update partition sector entries */
1738 for (j = 0; j < 4; j++)
1739 {
1740 if (PartitionBuffer->PartitionEntry[i + j].RewritePartition == TRUE)
1741 {
1742 /* Set partition boot flag */
1743 if (PartitionBuffer->PartitionEntry[i + j].BootIndicator)
1744 {
1745 PartitionSector->Partition[j].BootFlags |= 0x80;
1746 }
1747 else
1748 {
1749 PartitionSector->Partition[j].BootFlags &= ~0x80;
1750 }
1751
1752 /* Set partition type */
1753 PartitionSector->Partition[j].PartitionType =
1754 PartitionBuffer->PartitionEntry[i + j].PartitionType;
1755
1756 /* Set partition data */
1757 #if defined(__GNUC__)
1758 if (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart == 0ULL &&
1759 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart == 0ULL)
1760 #else
1761 if (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart == 0 &&
1762 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart == 0)
1763 #endif
1764 {
1765 PartitionSector->Partition[j].StartingBlock = 0;
1766 PartitionSector->Partition[j].SectorCount = 0;
1767 PartitionSector->Partition[j].StartingCylinder = 0;
1768 PartitionSector->Partition[j].StartingHead = 0;
1769 PartitionSector->Partition[j].StartingSector = 0;
1770 PartitionSector->Partition[j].EndingCylinder = 0;
1771 PartitionSector->Partition[j].EndingHead = 0;
1772 PartitionSector->Partition[j].EndingSector = 0;
1773 }
1774 else
1775 {
1776 /*
1777 * CHS formulas:
1778 * x = LBA DIV SectorsPerTrack
1779 * cylinder = (x DIV NumberOfHeads) % 1024
1780 * head = x MOD NumberOfHeads
1781 * sector = (LBA MOD SectorsPerTrack) + 1
1782 */
1783
1784 /* Compute starting CHS values */
1785 lba = (ULONG)((PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart) / SectorSize);
1786 x = lba / SectorsPerTrack;
1787 StartCylinder = (x / NumberOfHeads) %1024;
1788 StartHead = x % NumberOfHeads;
1789 StartSector = (lba % SectorsPerTrack) + 1;
1790 DPRINT ("StartingOffset (LBA:%d C:%d H:%d S:%d)\n",
1791 lba, StartCylinder, StartHead, StartSector);
1792
1793 /* Compute ending CHS values */
1794 lba = (ULONG)((PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart +
1795 (PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart - 1)) / SectorSize);
1796 x = lba / SectorsPerTrack;
1797 EndCylinder = (x / NumberOfHeads) % 1024;
1798 EndHead = x % NumberOfHeads;
1799 EndSector = (lba % SectorsPerTrack) + 1;
1800 DPRINT ("EndingOffset (LBA:%d C:%d H:%d S:%d)\n",
1801 lba, EndCylinder, EndHead, EndSector);
1802
1803 /* Set starting CHS values */
1804 PartitionSector->Partition[j].StartingCylinder = StartCylinder & 0xff;
1805 PartitionSector->Partition[j].StartingHead = StartHead;
1806 PartitionSector->Partition[j].StartingSector =
1807 ((StartCylinder & 0x0300) >> 2) + (StartSector & 0x3f);
1808
1809 /* Set ending CHS values */
1810 PartitionSector->Partition[j].EndingCylinder = EndCylinder & 0xff;
1811 PartitionSector->Partition[j].EndingHead = EndHead;
1812 PartitionSector->Partition[j].EndingSector =
1813 ((EndCylinder & 0x0300) >> 2) + (EndSector & 0x3f);
1814
1815 /* Calculate start sector and sector count */
1816 if (IsContainerPartition (PartitionBuffer->PartitionEntry[i + j].PartitionType))
1817 {
1818 StartBlock =
1819 (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart - ContainerOffset) / SectorSize;
1820 }
1821 else
1822 {
1823 StartBlock =
1824 (PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart - NextPartitionOffset) / SectorSize;
1825 }
1826 SectorCount =
1827 PartitionBuffer->PartitionEntry[i + j].PartitionLength.QuadPart / SectorSize;
1828 DPRINT ("LBA (StartBlock:%lu SectorCount:%lu)\n",
1829 StartBlock, SectorCount);
1830
1831 /* Set start sector and sector count */
1832 PartitionSector->Partition[j].StartingBlock = StartBlock;
1833 PartitionSector->Partition[j].SectorCount = SectorCount;
1834 }
1835 }
1836 }
1837
1838 /* Write partition sector */
1839 Status = xHalpWriteSector (DeviceObject,
1840 SectorSize,
1841 &RealPartitionOffset,
1842 PartitionSector);
1843 if (!NT_SUCCESS(Status))
1844 {
1845 DPRINT1("xHalpWriteSector() failed (Status %lx)\n", Status);
1846 break;
1847 }
1848 }
1849
1850 ContainerEntry = FALSE;
1851 for (j = 0; j < 4; j++)
1852 {
1853 if (IsContainerPartition (PartitionBuffer->PartitionEntry[i + j].PartitionType))
1854 {
1855 ContainerEntry = TRUE;
1856 NextPartitionOffset =
1857 PartitionBuffer->PartitionEntry[i + j].StartingOffset.QuadPart;
1858
1859 #if defined(__GNUC__)
1860 if (ContainerOffset == 0ULL)
1861 #else
1862 if (ContainerOffset == 0)
1863 #endif
1864 {
1865 ContainerOffset = NextPartitionOffset;
1866 }
1867 }
1868 }
1869
1870 if (ContainerEntry == FALSE)
1871 {
1872 DPRINT ("No container entry in partition sector!\n");
1873 break;
1874 }
1875
1876 PartitionOffset = NextPartitionOffset;
1877 }
1878
1879 ExFreePool (PartitionSector);
1880
1881 return Status;
1882 }
1883
1884 /*
1885 * @unimplemented
1886 *
1887 STDCALL
1888 VOID
1889 IoAssignDriveLetters(
1890 IN PLOADER_PARAMETER_BLOCK LoaderBlock,
1891 IN PSTRING NtDeviceName,
1892 OUT PUCHAR NtSystemPath,
1893 OUT PSTRING NtSystemPathString
1894 )
1895 {
1896 UNIMPLEMENTED;
1897 */
1898
1899 /*
1900 * @unimplemented
1901 */
1902 NTSTATUS
1903 STDCALL
1904 IoCreateDisk(
1905 IN PDEVICE_OBJECT DeviceObject,
1906 IN struct _CREATE_DISK* Disk
1907 )
1908 {
1909 UNIMPLEMENTED;
1910 return STATUS_NOT_IMPLEMENTED;
1911 }
1912
1913 /*
1914 * @unimplemented
1915 */
1916 NTSTATUS
1917 STDCALL
1918 IoGetBootDiskInformation(
1919 IN OUT PBOOTDISK_INFORMATION BootDiskInformation,
1920 IN ULONG Size
1921 )
1922 {
1923 UNIMPLEMENTED;
1924 return STATUS_NOT_IMPLEMENTED;
1925 }
1926
1927
1928 /*
1929 * @unimplemented
1930 */
1931 NTSTATUS
1932 STDCALL
1933 IoReadDiskSignature(
1934 IN PDEVICE_OBJECT DeviceObject,
1935 IN ULONG BytesPerSector,
1936 OUT PDISK_SIGNATURE Signature
1937 )
1938 {
1939 UNIMPLEMENTED;
1940 return STATUS_NOT_IMPLEMENTED;
1941 }
1942
1943 /*
1944 * @unimplemented
1945 */
1946 NTSTATUS
1947 STDCALL
1948 IoReadPartitionTableEx(
1949 IN PDEVICE_OBJECT DeviceObject,
1950 IN struct _DRIVE_LAYOUT_INFORMATION_EX** DriveLayout
1951 )
1952 {
1953 UNIMPLEMENTED;
1954 return STATUS_NOT_IMPLEMENTED;
1955 }
1956
1957 /*
1958 * @unimplemented
1959 */
1960 NTSTATUS
1961 STDCALL
1962 IoSetPartitionInformationEx(
1963 IN PDEVICE_OBJECT DeviceObject,
1964 IN ULONG PartitionNumber,
1965 IN struct _SET_PARTITION_INFORMATION_EX* PartitionInfo
1966 )
1967 {
1968 UNIMPLEMENTED;
1969 return STATUS_NOT_IMPLEMENTED;
1970 }
1971
1972 /*
1973 * @unimplemented
1974 */
1975 NTSTATUS
1976 STDCALL
1977 IoSetSystemPartition(
1978 PUNICODE_STRING VolumeNameString
1979 )
1980 {
1981 UNIMPLEMENTED;
1982 return STATUS_NOT_IMPLEMENTED;
1983 }
1984
1985 /*
1986 * @unimplemented
1987 */
1988 NTSTATUS
1989 STDCALL
1990 IoVerifyPartitionTable(
1991 IN PDEVICE_OBJECT DeviceObject,
1992 IN BOOLEAN FixErrors
1993 )
1994 {
1995 UNIMPLEMENTED;
1996 return STATUS_NOT_IMPLEMENTED;
1997 }
1998
1999 /*
2000 * @unimplemented
2001 */
2002 NTSTATUS
2003 STDCALL
2004 IoVolumeDeviceToDosName(
2005 IN PVOID VolumeDeviceObject,
2006 OUT PUNICODE_STRING DosName
2007 )
2008 {
2009 UNIMPLEMENTED;
2010 return STATUS_NOT_IMPLEMENTED;
2011 }
2012
2013 /*
2014 * @unimplemented
2015 */
2016 NTSTATUS
2017 STDCALL
2018 IoWritePartitionTableEx(
2019 IN PDEVICE_OBJECT DeviceObject,
2020 IN struct _DRIVE_LAYOUT_INFORMATION_EX* DriveLayfout
2021 )
2022 {
2023 UNIMPLEMENTED;
2024 return STATUS_NOT_IMPLEMENTED;
2025 }
2026
2027 /*
2028 * @implemented
2029 */
2030 NTSTATUS FASTCALL
2031 IoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
2032 ULONG SectorSize,
2033 BOOLEAN ReturnRecognizedPartitions,
2034 PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
2035 {
2036 return(HalIoReadPartitionTable(DeviceObject,
2037 SectorSize,
2038 ReturnRecognizedPartitions,
2039 PartitionBuffer));
2040 }
2041
2042
2043 NTSTATUS FASTCALL
2044 IoSetPartitionInformation(PDEVICE_OBJECT DeviceObject,
2045 ULONG SectorSize,
2046 ULONG PartitionNumber,
2047 ULONG PartitionType)
2048 {
2049 return(HalIoSetPartitionInformation(DeviceObject,
2050 SectorSize,
2051 PartitionNumber,
2052 PartitionType));
2053 }
2054
2055
2056 NTSTATUS FASTCALL
2057 IoWritePartitionTable(PDEVICE_OBJECT DeviceObject,
2058 ULONG SectorSize,
2059 ULONG SectorsPerTrack,
2060 ULONG NumberOfHeads,
2061 PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
2062 {
2063 return(HalIoWritePartitionTable(DeviceObject,
2064 SectorSize,
2065 SectorsPerTrack,
2066 NumberOfHeads,
2067 PartitionBuffer));
2068 }
2069 /* EOF */