Fixed prototypes: CcMapData()
[reactos.git] / ntoskrnl / io / xhaldrv.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            ntoskrnl/io/xhaldrv.c
6  * PURPOSE:         Hal drive routines
7  * PROGRAMMER:      Eric Kohl (ekohl@rz-online.de)
8  * UPDATE HISTORY:
9  *                  Created 19/06/2000
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/xhal.h>
16
17 #define NDEBUG
18 #include <internal/debug.h>
19
20 /* LOCAL MACROS and TYPES ***************************************************/
21
22 #define  AUTO_DRIVE         ((ULONG)-1)
23
24 #define  PARTITION_MAGIC    0xaa55
25 #define  PART_MAGIC_OFFSET  0x01fe
26 #define  PARTITION_OFFSET   0x01be
27 #define  SIGNATURE_OFFSET   0x01b8
28 #define  PARTITION_TBL_SIZE 4
29
30
31 typedef struct _PARTITION
32 {
33   unsigned char   BootFlags;
34   unsigned char   StartingHead;
35   unsigned char   StartingSector;
36   unsigned char   StartingCylinder;
37   unsigned char   PartitionType;
38   unsigned char   EndingHead;
39   unsigned char   EndingSector;
40   unsigned char   EndingCylinder;
41   unsigned int  StartingBlock;
42   unsigned int  SectorCount;
43 } PARTITION, *PPARTITION;
44
45 typedef struct _PARTITION_TABLE
46 {
47   PARTITION Partition[PARTITION_TBL_SIZE];
48   unsigned short Magic;
49 } PARTITION_TABLE, *PPARTITION_TABLE;
50
51 /* FUNCTIONS *****************************************************************/
52
53 NTSTATUS
54 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName,
55                      OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
56 {
57   IO_STATUS_BLOCK StatusBlock;
58   DISK_GEOMETRY DiskGeometry;
59   PDEVICE_OBJECT DeviceObject = NULL;
60   PFILE_OBJECT FileObject;
61   KEVENT Event;
62   PIRP Irp;
63   NTSTATUS Status;
64
65   DPRINT("xHalpQueryDriveLayout %wZ %p\n",
66          DeviceName,
67          LayoutInfo);
68
69   /* Get the drives sector size */
70   Status = IoGetDeviceObjectPointer(DeviceName,
71                                     FILE_READ_DATA,
72                                     &FileObject,
73                                     &DeviceObject);
74   if (!NT_SUCCESS(Status))
75     {
76       DPRINT("Status %x\n",Status);
77       return(Status);
78     }
79
80   KeInitializeEvent(&Event,
81                     NotificationEvent,
82                     FALSE);
83
84   Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
85                                       DeviceObject,
86                                       NULL,
87                                       0,
88                                       &DiskGeometry,
89                                       sizeof(DISK_GEOMETRY),
90                                       FALSE,
91                                       &Event,
92                                       &StatusBlock);
93   if (Irp == NULL)
94     {
95       ObDereferenceObject(FileObject);
96       return(STATUS_INSUFFICIENT_RESOURCES);
97     }
98
99   Status = IoCallDriver(DeviceObject,
100                         Irp);
101   if (Status == STATUS_PENDING)
102     {
103       KeWaitForSingleObject(&Event,
104                             Executive,
105                             KernelMode,
106                             FALSE,
107                             NULL);
108       Status = StatusBlock.Status;
109     }
110   if (!NT_SUCCESS(Status))
111     {
112       if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
113         {
114           DiskGeometry.BytesPerSector = 512;
115         }
116       else
117         {
118           ObDereferenceObject(FileObject);
119           return(Status);
120         }
121     }
122
123   DPRINT("DiskGeometry.BytesPerSector: %d\n",
124          DiskGeometry.BytesPerSector);
125
126   /* read the partition table */
127   Status = IoReadPartitionTable(DeviceObject,
128                                 DiskGeometry.BytesPerSector,
129                                 FALSE,
130                                 LayoutInfo);
131
132   if ((!NT_SUCCESS(Status) || (*LayoutInfo)->PartitionCount == 0) &&
133       DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
134     {
135       PDRIVE_LAYOUT_INFORMATION Buffer;
136
137       if (NT_SUCCESS(Status))
138         {
139           ExFreePool(*LayoutInfo);
140         }
141
142       /* Allocate a partition list for a single entry. */
143       Buffer = ExAllocatePool(NonPagedPool,
144                               sizeof(DRIVE_LAYOUT_INFORMATION));
145       if (Buffer != NULL)
146         {
147           RtlZeroMemory(Buffer,
148                         sizeof(DRIVE_LAYOUT_INFORMATION));
149           Buffer->PartitionCount = 1;
150           *LayoutInfo = Buffer;
151
152           Status = STATUS_SUCCESS;
153         }
154     }
155
156   ObDereferenceObject(FileObject);
157
158   return(Status);
159 }
160
161
162 VOID FASTCALL
163 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
164                IN ULONG SectorSize,
165                IN ULONG MBRTypeIdentifier,
166                OUT PVOID *Buffer)
167 {
168   KEVENT Event;
169   IO_STATUS_BLOCK StatusBlock;
170   LARGE_INTEGER Offset;
171   PUCHAR LocalBuffer;
172   PIRP Irp;
173   NTSTATUS Status;
174
175   DPRINT("xHalExamineMBR()\n");
176   *Buffer = NULL;
177
178   if (SectorSize < 512)
179     SectorSize = 512;
180   if (SectorSize > 4096)
181     SectorSize = 4096;
182
183   LocalBuffer = (PUCHAR)ExAllocatePool(PagedPool,
184                                        SectorSize);
185   if (LocalBuffer == NULL)
186     return;
187
188   KeInitializeEvent(&Event,
189                     NotificationEvent,
190                     FALSE);
191
192   Offset.QuadPart = 0;
193
194   Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
195                                      DeviceObject,
196                                      LocalBuffer,
197                                      SectorSize,
198                                      &Offset,
199                                      &Event,
200                                      &StatusBlock);
201
202   Status = IoCallDriver(DeviceObject,
203                         Irp);
204   if (Status == STATUS_PENDING)
205     {
206       KeWaitForSingleObject(&Event,
207                             Executive,
208                             KernelMode,
209                             FALSE,
210                             NULL);
211       Status = StatusBlock.Status;
212     }
213
214   if (!NT_SUCCESS(Status))
215     {
216       DPRINT("xHalExamineMBR failed (Status = 0x%08lx)\n",
217              Status);
218       ExFreePool(LocalBuffer);
219       return;
220     }
221
222   if (LocalBuffer[0x1FE] != 0x55 || LocalBuffer[0x1FF] != 0xAA)
223     {
224       DPRINT("xHalExamineMBR: invalid MBR signature\n");
225       ExFreePool(LocalBuffer);
226       return;
227     }
228
229   if (LocalBuffer[0x1C2] != MBRTypeIdentifier)
230     {
231       DPRINT("xHalExamineMBR: invalid MBRTypeIdentifier\n");
232       ExFreePool(LocalBuffer);
233       return;
234     }
235
236   *Buffer = (PVOID)LocalBuffer;
237 }
238
239
240 static VOID
241 HalpAssignDrive(IN PUNICODE_STRING PartitionName,
242                 IN ULONG DriveNumber,
243                 IN UCHAR DriveType)
244 {
245   WCHAR DriveNameBuffer[8];
246   UNICODE_STRING DriveName;
247   ULONG i;
248
249   DPRINT("HalpAssignDrive()\n");
250
251   if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 24))
252     {
253       /* Force assignment */
254       if ((SharedUserData->DosDeviceMap & (1 << DriveNumber)) != 0)
255         {
256           DbgPrint("Drive letter already used!\n");
257           return;
258         }
259     }
260   else
261     {
262       /* Automatic assignment */
263       DriveNumber = AUTO_DRIVE;
264
265       for (i = 2; i < 24; i++)
266         {
267           if ((SharedUserData->DosDeviceMap & (1 << i)) == 0)
268             {
269               DriveNumber = i;
270               break;
271             }
272         }
273
274       if (DriveNumber == AUTO_DRIVE)
275         {
276           DbgPrint("No drive letter available!\n");
277           return;
278         }
279     }
280
281   DPRINT("DriveNumber %d\n", DriveNumber);
282
283   /* Update the shared user page */
284   SharedUserData->DosDeviceMap |= (1 << DriveNumber);
285   SharedUserData->DosDeviceDriveType[DriveNumber] = DriveType;
286
287   /* Build drive name */
288   swprintf(DriveNameBuffer,
289            L"\\??\\%C:",
290            'A' + DriveNumber);
291   RtlInitUnicodeString(&DriveName,
292                        DriveNameBuffer);
293
294   DPRINT("  %wZ ==> %wZ\n",
295          &DriveName,
296          PartitionName);
297
298   /* Create symbolic link */
299   IoCreateSymbolicLink(&DriveName,
300                        PartitionName);
301 }
302
303
304 VOID FASTCALL
305 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
306                          IN PSTRING NtDeviceName,
307                          OUT PUCHAR NtSystemPath,
308                          OUT PSTRING NtSystemPathString)
309 {
310   PDRIVE_LAYOUT_INFORMATION *LayoutArray;
311   PCONFIGURATION_INFORMATION ConfigInfo;
312   OBJECT_ATTRIBUTES ObjectAttributes;
313   IO_STATUS_BLOCK StatusBlock;
314   UNICODE_STRING UnicodeString1;
315   UNICODE_STRING UnicodeString2;
316   HANDLE FileHandle;
317   PWSTR Buffer1;
318   PWSTR Buffer2;
319   ULONG i;
320   NTSTATUS Status;
321   ULONG j;
322
323   DPRINT("xHalIoAssignDriveLetters()\n");
324
325   ConfigInfo = IoGetConfigurationInformation();
326
327   Buffer1 = (PWSTR)ExAllocatePool(PagedPool,
328                                   64 * sizeof(WCHAR));
329   Buffer2 = (PWSTR)ExAllocatePool(PagedPool,
330                                   32 * sizeof(WCHAR));
331
332   /* Create PhysicalDrive links */
333   DPRINT("Physical disk drives: %d\n", ConfigInfo->DiskCount);
334   for (i = 0; i < ConfigInfo->DiskCount; i++)
335     {
336       swprintf(Buffer1,
337                L"\\Device\\Harddisk%d\\Partition0",
338                 i);
339       RtlInitUnicodeString(&UnicodeString1,
340                            Buffer1);
341
342       InitializeObjectAttributes(&ObjectAttributes,
343                                  &UnicodeString1,
344                                  0,
345                                  NULL,
346                                  NULL);
347
348       Status = NtOpenFile(&FileHandle,
349                           0x10001,
350                           &ObjectAttributes,
351                           &StatusBlock,
352                           1,
353                           FILE_SYNCHRONOUS_IO_NONALERT);
354       if (NT_SUCCESS(Status))
355         {
356           NtClose(FileHandle);
357
358           swprintf(Buffer2,
359                    L"\\??\\PhysicalDrive%d",
360                    i);
361           RtlInitUnicodeString(&UnicodeString2,
362                                Buffer2);
363
364           DPRINT("Creating link: %S ==> %S\n",
365                  Buffer2,
366                  Buffer1);
367
368           IoCreateSymbolicLink(&UnicodeString2,
369                                &UnicodeString1);
370         }
371     }
372
373   /* Initialize layout array */
374   LayoutArray = ExAllocatePool(NonPagedPool,
375                                ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
376   RtlZeroMemory(LayoutArray,
377                 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
378   for (i = 0; i < ConfigInfo->DiskCount; i++)
379     {
380       swprintf(Buffer1,
381                L"\\Device\\Harddisk%d\\Partition0",
382                i);
383       RtlInitUnicodeString(&UnicodeString1,
384                            Buffer1);
385
386       Status = xHalQueryDriveLayout(&UnicodeString1,
387                                     &LayoutArray[i]);
388       if (!NT_SUCCESS(Status))
389         {
390           DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
391                    Status);
392           LayoutArray[i] = NULL;
393           continue;
394         }
395     }
396
397 #ifndef NDEBUG
398   /* Dump layout array */
399   for (i = 0; i < ConfigInfo->DiskCount; i++)
400     {
401       DPRINT("Harddisk %d:\n",
402              i);
403
404       if (LayoutArray[i] == NULL)
405         continue;
406
407       DPRINT("Logical partitions: %d\n",
408              LayoutArray[i]->PartitionCount);
409
410       for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
411         {
412           DPRINT("  %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
413                  j,
414                  LayoutArray[i]->PartitionEntry[j].PartitionNumber,
415                  LayoutArray[i]->PartitionEntry[j].BootIndicator,
416                  LayoutArray[i]->PartitionEntry[j].PartitionType,
417                  LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart,
418                  LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart);
419         }
420     }
421 #endif
422
423   /* Assign pre-assigned (registry) partitions */
424
425
426   /* Assign bootable partition on first harddisk */
427   DPRINT("Assigning bootable primary partition on first harddisk:\n");
428   if (ConfigInfo->DiskCount > 0)
429     {
430       /* Search for bootable partition */
431       for (j = 0; j < LayoutArray[0]->PartitionCount; j++)
432         {
433           if ((LayoutArray[0]->PartitionEntry[j].BootIndicator == TRUE) &&
434               IsRecognizedPartition(LayoutArray[0]->PartitionEntry[j].PartitionType))
435             {
436               swprintf(Buffer2,
437                        L"\\Device\\Harddisk0\\Partition%d",
438                        LayoutArray[0]->PartitionEntry[j].PartitionNumber);
439               RtlInitUnicodeString(&UnicodeString2,
440                                    Buffer2);
441
442               /* Assign drive */
443               DPRINT("  %wZ\n", &UnicodeString2);
444               HalpAssignDrive(&UnicodeString2,
445                               AUTO_DRIVE,
446                               DOSDEVICE_DRIVE_FIXED);
447             }
448         }
449     }
450
451   /* Assign remaining  primary partitions */
452   DPRINT("Assigning remaining primary partitions:\n");
453   for (i = 0; i < ConfigInfo->DiskCount; i++)
454     {
455       /* Search for primary partitions */
456       for (j = 0; (j < PARTITION_TBL_SIZE) && (j < LayoutArray[i]->PartitionCount); j++)
457         {
458           if ((i == 0) && (LayoutArray[i]->PartitionEntry[j].BootIndicator == TRUE))
459             continue;
460
461           if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType))
462             {
463               swprintf(Buffer2,
464                        L"\\Device\\Harddisk%d\\Partition%d",
465                        i,
466                        LayoutArray[i]->PartitionEntry[j].PartitionNumber);
467               RtlInitUnicodeString(&UnicodeString2,
468                                    Buffer2);
469
470               /* Assign drive */
471               DPRINT("  %wZ\n",
472                      &UnicodeString2);
473               HalpAssignDrive(&UnicodeString2,
474                               AUTO_DRIVE,
475                               DOSDEVICE_DRIVE_FIXED);
476             }
477         }
478     }
479
480   /* Assign extended (logical) partitions */
481   DPRINT("Assigning extended (logical) partitions:\n");
482   for (i = 0; i < ConfigInfo->DiskCount; i++)
483     {
484       if (LayoutArray[i])
485         {
486           /* Search for extended partitions */
487           for (j = PARTITION_TBL_SIZE; j < LayoutArray[i]->PartitionCount; j++)
488             {
489               if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType) &&
490                   (LayoutArray[i]->PartitionEntry[j].PartitionNumber != 0))
491                 {
492                   swprintf(Buffer2,
493                            L"\\Device\\Harddisk%d\\Partition%d",
494                            i,
495                            LayoutArray[i]->PartitionEntry[j].PartitionNumber);
496                   RtlInitUnicodeString(&UnicodeString2,
497                                        Buffer2);
498
499                   /* Assign drive */
500                   DPRINT("  %wZ\n",
501                          &UnicodeString2);
502                   HalpAssignDrive(&UnicodeString2,
503                                   AUTO_DRIVE,
504                                   DOSDEVICE_DRIVE_FIXED);
505                 }
506             }
507         }
508     }
509
510   /* Assign removable disk drives */
511   DPRINT("Assigning removable disk drives:\n");
512   for (i = 0; i < ConfigInfo->DiskCount; i++)
513     {
514       /* Search for virtual partitions */
515       if (LayoutArray[i]->PartitionCount == 1 &&
516           LayoutArray[i]->PartitionEntry[0].PartitionType == 0)
517         {
518           swprintf(Buffer2,
519                    L"\\Device\\Harddisk%d\\Partition1",
520                    i);
521           RtlInitUnicodeString(&UnicodeString2,
522                                Buffer2);
523
524           /* Assign drive */
525           DPRINT("  %wZ\n",
526                  &UnicodeString2);
527           HalpAssignDrive(&UnicodeString2,
528                           AUTO_DRIVE,
529                           DOSDEVICE_DRIVE_REMOVABLE);
530         }
531     }
532
533   /* Free layout array */
534   for (i = 0; i < ConfigInfo->DiskCount; i++)
535     {
536       if (LayoutArray[i] != NULL)
537         ExFreePool(LayoutArray[i]);
538     }
539   ExFreePool(LayoutArray);
540
541   /* Assign floppy drives */
542   DPRINT("Floppy drives: %d\n", ConfigInfo->FloppyCount);
543   for (i = 0; i < ConfigInfo->FloppyCount; i++)
544     {
545       swprintf(Buffer1,
546                L"\\Device\\Floppy%d",
547                i);
548       RtlInitUnicodeString(&UnicodeString1,
549                            Buffer1);
550
551       /* Assign drive letters A: or B: or first free drive letter */
552       DPRINT("  %wZ\n",
553              &UnicodeString1);
554       HalpAssignDrive(&UnicodeString1,
555                       (i < 2) ? i : AUTO_DRIVE,
556                       DOSDEVICE_DRIVE_REMOVABLE);
557     }
558
559   /* Assign cdrom drives */
560   DPRINT("CD-Rom drives: %d\n", ConfigInfo->CDRomCount);
561   for (i = 0; i < ConfigInfo->CDRomCount; i++)
562     {
563       swprintf(Buffer1,
564                L"\\Device\\CdRom%d",
565                i);
566       RtlInitUnicodeString(&UnicodeString1,
567                            Buffer1);
568
569       /* Assign first free drive letter */
570       DPRINT("  %wZ\n", &UnicodeString1);
571       HalpAssignDrive(&UnicodeString1,
572                       AUTO_DRIVE,
573                       DOSDEVICE_DRIVE_CDROM);
574     }
575
576   /* Anything else ?? */
577
578   ExFreePool(Buffer2);
579   ExFreePool(Buffer1);
580 }
581
582
583 NTSTATUS FASTCALL
584 xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
585                          ULONG SectorSize,
586                          BOOLEAN ReturnRecognizedPartitions,
587                          PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
588 {
589   KEVENT Event;
590   IO_STATUS_BLOCK StatusBlock;
591   ULARGE_INTEGER PartitionOffset;
592   ULARGE_INTEGER  nextPartitionOffset;
593   ULARGE_INTEGER  containerOffset;
594   PUCHAR SectorBuffer;
595   PIRP Irp;
596   NTSTATUS Status;
597   PPARTITION_TABLE PartitionTable;
598   PDRIVE_LAYOUT_INFORMATION LayoutBuffer;
599   ULONG i;
600   ULONG Count = 0;
601   ULONG Number = 1;
602   BOOLEAN ExtendedFound = FALSE;
603
604   DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n",
605          DeviceObject,
606          SectorSize,
607          ReturnRecognizedPartitions,
608          PartitionBuffer);
609
610   *PartitionBuffer = NULL;
611
612   SectorBuffer = (PUCHAR)ExAllocatePool(PagedPool,
613                                         SectorSize);
614   if (SectorBuffer == NULL)
615     {
616       return(STATUS_INSUFFICIENT_RESOURCES);
617     }
618
619   LayoutBuffer = (PDRIVE_LAYOUT_INFORMATION)ExAllocatePool(NonPagedPool,
620                                                            0x1000);
621   if (LayoutBuffer == NULL)
622     {
623       ExFreePool(SectorBuffer);
624       return(STATUS_INSUFFICIENT_RESOURCES);
625     }
626
627   RtlZeroMemory(LayoutBuffer,
628                 0x1000);
629
630   PartitionOffset.QuadPart = 0;
631   containerOffset.QuadPart = 0;
632
633   do
634     {
635       KeInitializeEvent(&Event,
636                         NotificationEvent,
637                         FALSE);
638
639       DPRINT("PartitionOffset: %I64u\n", PartitionOffset.QuadPart / SectorSize);
640
641       Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
642                                          DeviceObject,
643                                          SectorBuffer,
644                                          SectorSize,
645                                          (PLARGE_INTEGER)&PartitionOffset,
646                                          &Event,
647                                          &StatusBlock);
648       Status = IoCallDriver(DeviceObject,
649                             Irp);
650       if (Status == STATUS_PENDING)
651         {
652           KeWaitForSingleObject(&Event,
653                                 Executive,
654                                 KernelMode,
655                                 FALSE,
656                                 NULL);
657           Status = StatusBlock.Status;
658         }
659
660       if (!NT_SUCCESS(Status))
661         {
662           DPRINT("Failed to read partition table sector (Status = 0x%08lx)\n",
663                  Status);
664           ExFreePool(SectorBuffer);
665           ExFreePool(LayoutBuffer);
666           return(Status);
667         }
668
669       PartitionTable = (PPARTITION_TABLE)(SectorBuffer + PARTITION_OFFSET);
670
671       /* check the boot sector id */
672       DPRINT("Magic %x\n", PartitionTable->Magic);
673       if (PartitionTable->Magic != PARTITION_MAGIC)
674         {
675           DbgPrint("Invalid partition table magic\n");
676           ExFreePool(SectorBuffer);
677           *PartitionBuffer = LayoutBuffer;
678           return(STATUS_SUCCESS);
679         }
680
681 #ifndef NDEBUG
682       for (i = 0; i < PARTITION_TBL_SIZE; i++)
683         {
684           DPRINT1("  %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
685                   i,
686                   PartitionTable->Partition[i].BootFlags,
687                   PartitionTable->Partition[i].PartitionType,
688                   PartitionTable->Partition[i].StartingHead,
689                   PartitionTable->Partition[i].StartingSector & 0x3f,
690                   (((PartitionTable->Partition[i].StartingSector) & 0xc0) << 2) +
691                      PartitionTable->Partition[i].StartingCylinder,
692                   PartitionTable->Partition[i].EndingHead,
693                   PartitionTable->Partition[i].EndingSector,
694                   PartitionTable->Partition[i].EndingCylinder,
695                   PartitionTable->Partition[i].StartingBlock,
696                   PartitionTable->Partition[i].SectorCount);
697         }
698 #endif
699
700       if (ExtendedFound == FALSE);
701         {
702           LayoutBuffer->Signature = *((PULONG)(SectorBuffer + SIGNATURE_OFFSET));
703         }
704
705       ExtendedFound = FALSE;
706
707       for (i = 0; i < PARTITION_TBL_SIZE; i++)
708         {
709           if ((ReturnRecognizedPartitions == FALSE) ||
710                ((ReturnRecognizedPartitions == TRUE) &&
711                 IsRecognizedPartition(PartitionTable->Partition[i].PartitionType)))
712             {
713               /* handle normal partition */
714               DPRINT("Partition %u: Normal Partition\n", i);
715               Count = LayoutBuffer->PartitionCount;
716               DPRINT("Logical Partition %u\n", Count);
717               if (PartitionTable->Partition[i].StartingBlock == 0)
718                 {
719                   LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart = 0;
720                 }
721               else if (IsContainerPartition(PartitionTable->Partition[i].PartitionType))
722                 {
723                   LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
724                     (ULONGLONG)PartitionOffset.QuadPart;
725                 }
726               else
727                 {
728                   LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart =
729                     (ULONGLONG)PartitionOffset.QuadPart +
730                     ((ULONGLONG)PartitionTable->Partition[i].StartingBlock * (ULONGLONG)SectorSize);
731                 }
732               LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart =
733                 (ULONGLONG)PartitionTable->Partition[i].SectorCount * (ULONGLONG)SectorSize;
734               LayoutBuffer->PartitionEntry[Count].HiddenSectors = 0;
735
736               if (IsRecognizedPartition(PartitionTable->Partition[i].PartitionType))
737                 {
738                   LayoutBuffer->PartitionEntry[Count].PartitionNumber = Number;
739                   Number++;
740                 }
741               else
742                 {
743                   LayoutBuffer->PartitionEntry[Count].PartitionNumber = 0;
744                 }
745
746               LayoutBuffer->PartitionEntry[Count].PartitionType =
747                 PartitionTable->Partition[i].PartitionType;
748               LayoutBuffer->PartitionEntry[Count].BootIndicator =
749                 (PartitionTable->Partition[i].BootFlags & 0x80)?TRUE:FALSE;
750               LayoutBuffer->PartitionEntry[Count].RecognizedPartition =
751                 IsRecognizedPartition (PartitionTable->Partition[i].PartitionType);
752               LayoutBuffer->PartitionEntry[Count].RewritePartition = FALSE;
753
754               DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n",
755                      Count,
756                      LayoutBuffer->PartitionEntry[Count].PartitionNumber,
757                      LayoutBuffer->PartitionEntry[Count].BootIndicator,
758                      LayoutBuffer->PartitionEntry[Count].PartitionType,
759                      LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart,
760                      LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart);
761
762               LayoutBuffer->PartitionCount++;
763             }
764
765           if (IsContainerPartition(PartitionTable->Partition[i].PartitionType))
766             {
767               ExtendedFound = TRUE;
768               if ((ULONGLONG) containerOffset.QuadPart == (ULONGLONG) 0)
769                 {
770                   containerOffset = PartitionOffset;
771                 }
772               nextPartitionOffset.QuadPart = (ULONGLONG) containerOffset.QuadPart +
773                 (ULONGLONG) PartitionTable->Partition[i].StartingBlock *
774                 (ULONGLONG) SectorSize;
775             }
776         }
777       PartitionOffset = nextPartitionOffset;
778     }
779   while (ExtendedFound == TRUE);
780
781   *PartitionBuffer = LayoutBuffer;
782   ExFreePool(SectorBuffer);
783
784   return(STATUS_SUCCESS);
785 }
786
787
788 NTSTATUS FASTCALL
789 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
790                               IN ULONG SectorSize,
791                               IN ULONG PartitionNumber,
792                               IN ULONG PartitionType)
793 {
794   return(STATUS_NOT_IMPLEMENTED);
795 }
796
797
798 NTSTATUS FASTCALL
799 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
800                           IN ULONG SectorSize,
801                           IN ULONG SectorsPerTrack,
802                           IN ULONG NumberOfHeads,
803                           IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
804 {
805   return(STATUS_NOT_IMPLEMENTED);
806 }
807
808 /* EOF */