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