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