3 * Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS text-mode setup
21 * FILE: subsys/system/usetup/partlist.c
22 * PURPOSE: Partition list functions
23 * PROGRAMMER: Eric Kohl
24 * Casper S. Hornstrup (chorns@users.sourceforge.net)
34 //#define DUMP_PARTITION_TABLE
36 /* FUNCTIONS ****************************************************************/
38 #ifdef DUMP_PARTITION_TABLE
44 PPARTITION_INFORMATION PartitionInfo
;
47 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
49 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
50 DPRINT1("\n%lu: %12I64u %12I64u %10lu %2lu %2x %c %c\n",
52 PartitionInfo
->StartingOffset
.QuadPart
,
53 PartitionInfo
->PartitionLength
.QuadPart
,
54 PartitionInfo
->HiddenSectors
,
55 PartitionInfo
->PartitionNumber
,
56 PartitionInfo
->PartitionType
,
57 PartitionInfo
->BootIndicator
? '*': ' ',
58 PartitionInfo
->RewritePartition
? 'Y': 'N');
71 Temp
= Value
/ Alignment
;
73 return Temp
* Alignment
;
79 IN ULONGLONG Dividend
,
82 return (Dividend
+ Divisor
/ 2) / Divisor
;
91 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
95 RtlInitUnicodeString(&DiskEntry
->DriverName
,
99 L
"\\Scsi\\Scsi Port %lu",
102 RtlZeroMemory(&QueryTable
,
105 QueryTable
[0].Name
= L
"Driver";
106 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
107 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
109 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
114 if (!NT_SUCCESS(Status
))
116 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
126 PDISKENTRY DiskEntry
;
127 PPARTENTRY PartEntry
;
134 /* Assign drive letters to primary partitions */
135 Entry1
= List
->DiskListHead
.Flink
;
136 while (Entry1
!= &List
->DiskListHead
)
138 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
140 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
141 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
143 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
145 PartEntry
->DriveLetter
= 0;
147 if (PartEntry
->IsPartitioned
&&
148 !IsContainerPartition(PartEntry
->PartitionType
))
150 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
151 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
152 PartEntry
->SectorCount
.QuadPart
!= 0LL))
156 PartEntry
->DriveLetter
= Letter
;
162 Entry2
= Entry2
->Flink
;
165 Entry1
= Entry1
->Flink
;
168 /* Assign drive letters to logical drives */
169 Entry1
= List
->DiskListHead
.Flink
;
170 while (Entry1
!= &List
->DiskListHead
)
172 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
174 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
175 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
177 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
179 PartEntry
->DriveLetter
= 0;
181 if (PartEntry
->IsPartitioned
)
183 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
184 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
185 PartEntry
->SectorCount
.QuadPart
!= 0LL))
189 PartEntry
->DriveLetter
= Letter
;
195 Entry2
= Entry2
->Flink
;
198 Entry1
= Entry1
->Flink
;
205 UpdatePartitionNumbers(
206 PDISKENTRY DiskEntry
)
208 PPARTENTRY PartEntry
;
210 // ULONG PartitionNumber = 1;
211 ULONG PartitionIndex
= 0;
213 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
214 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
216 PartEntry
= CONTAINING_RECORD(Entry
,
220 if (PartEntry
->IsPartitioned
== FALSE
)
222 // PartEntry->PartitionNumber = 0;
223 PartEntry
->PartitionIndex
= (ULONG
)-1;
227 if (IsContainerPartition(PartEntry
->PartitionType
))
229 // PartEntry->PartitionNumber = 0;
231 else if (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
232 PartEntry
->SectorCount
.QuadPart
== 0ULL)
234 // PartEntry->PartitionNumber = 0;
238 // PartEntry->PartitionNumber = PartitionNumber++;
241 PartEntry
->PartitionIndex
= PartitionIndex
++;
244 Entry
= Entry
->Flink
;
251 DiskIdentifierQueryRoutine(
259 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
260 UNICODE_STRING NameU
;
262 if (ValueType
== REG_SZ
&&
263 ValueLength
== 20 * sizeof(WCHAR
))
265 NameU
.Buffer
= (PWCHAR
)ValueData
;
266 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
267 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
269 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
270 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
272 return STATUS_SUCCESS
;
275 return STATUS_UNSUCCESSFUL
;
281 DiskConfigurationDataQueryRoutine(
289 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
290 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
291 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
294 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
295 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
296 return STATUS_UNSUCCESSFUL
;
298 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
300 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
302 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
303 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
304 return STATUS_UNSUCCESSFUL
;
307 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
309 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
310 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
313 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
314 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
316 return STATUS_SUCCESS
;
319 return STATUS_UNSUCCESSFUL
;
325 SystemConfigurationDataQueryRoutine(
333 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
334 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
337 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
338 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
339 return STATUS_UNSUCCESSFUL
;
341 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
343 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
345 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
346 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
347 return STATUS_UNSUCCESSFUL
;
350 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
352 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
353 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
356 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
357 if (*Int13Drives
== NULL
)
358 return STATUS_NO_MEMORY
;
361 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
362 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
363 return STATUS_SUCCESS
;
366 return STATUS_UNSUCCESSFUL
;
370 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
373 EnumerateBiosDiskEntries(
376 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
381 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
382 PBIOSDISKENTRY BiosDiskEntry
;
384 memset(QueryTable
, 0, sizeof(QueryTable
));
386 QueryTable
[1].Name
= L
"Configuration Data";
387 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
389 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
390 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
394 if (!NT_SUCCESS(Status
))
396 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
403 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
404 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
409 if (!NT_SUCCESS(Status
))
414 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
415 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
420 if (NT_SUCCESS(Status
))
424 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
425 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
430 if (!NT_SUCCESS(Status
))
432 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
436 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
437 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
442 if (NT_SUCCESS(Status
))
444 QueryTable
[0].Name
= L
"Identifier";
445 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
446 QueryTable
[1].Name
= L
"Configuration Data";
447 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
452 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
453 if (BiosDiskEntry
== NULL
)
458 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
459 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
462 (PVOID
)BiosDiskEntry
,
464 if (!NT_SUCCESS(Status
))
466 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
470 BiosDiskEntry
->DiskNumber
= DiskCount
;
471 BiosDiskEntry
->Recognized
= FALSE
;
473 if (DiskCount
< Int13Drives
[0].NumberDrives
)
475 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
479 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
482 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
484 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
485 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
486 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
487 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
488 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
489 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
490 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
491 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
492 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
493 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
494 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
500 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
508 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
516 PDISKENTRY DiskEntry
,
517 ULONG PartitionIndex
,
518 BOOLEAN LogicalPartition
)
520 PPARTITION_INFORMATION PartitionInfo
;
521 PPARTENTRY PartEntry
;
523 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[PartitionIndex
];
524 if (PartitionInfo
->PartitionType
== 0 ||
525 (LogicalPartition
== TRUE
&& IsContainerPartition(PartitionInfo
->PartitionType
)))
528 PartEntry
= RtlAllocateHeap(ProcessHeap
,
531 if (PartEntry
== NULL
)
536 PartEntry
->DiskEntry
= DiskEntry
;
538 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
539 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
541 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
542 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
543 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
545 PartEntry
->LogicalPartition
= LogicalPartition
;
546 PartEntry
->IsPartitioned
= TRUE
;
547 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
548 PartEntry
->PartitionIndex
= PartitionIndex
;
550 if (IsContainerPartition(PartEntry
->PartitionType
))
552 PartEntry
->FormatState
= Unformatted
;
554 if (LogicalPartition
== FALSE
&& DiskEntry
->ExtendedPartition
== NULL
)
555 DiskEntry
->ExtendedPartition
= PartEntry
;
557 else if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
558 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
559 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
560 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
561 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
562 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
565 if (CheckFatFormat())
567 PartEntry
->FormatState
= Preformatted
;
571 PartEntry
->FormatState
= Unformatted
;
574 PartEntry
->FormatState
= Preformatted
;
576 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
579 if (CheckExt2Format())
581 PartEntry
->FormatState
= Preformatted
;
585 PartEntry
->FormatState
= Unformatted
;
588 PartEntry
->FormatState
= Preformatted
;
590 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
593 if (CheckNtfsFormat())
595 PartEntry
->FormatState
= Preformatted
;
597 else if (CheckHpfsFormat())
599 PartEntry
->FormatState
= Preformatted
;
603 PartEntry
->FormatState
= Unformatted
;
606 PartEntry
->FormatState
= Preformatted
;
610 PartEntry
->FormatState
= UnknownFormat
;
613 if (LogicalPartition
)
614 InsertTailList(&DiskEntry
->LogicalPartListHead
,
615 &PartEntry
->ListEntry
);
617 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
618 &PartEntry
->ListEntry
);
624 ScanForUnpartitionedDiskSpace(
625 PDISKENTRY DiskEntry
)
627 ULONGLONG LastStartSector
;
628 ULONGLONG LastSectorCount
;
629 ULONGLONG LastUnusedSectorCount
;
630 PPARTENTRY PartEntry
;
631 PPARTENTRY NewPartEntry
;
634 DPRINT("ScanForUnpartitionedDiskSpace()\n");
636 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
638 DPRINT1("No primary partition!\n");
640 /* Create a partition table that represents the empty disk */
641 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
644 if (NewPartEntry
== NULL
)
647 NewPartEntry
->DiskEntry
= DiskEntry
;
649 NewPartEntry
->IsPartitioned
= FALSE
;
650 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorAlignment
;
651 NewPartEntry
->SectorCount
.QuadPart
= Align(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
652 NewPartEntry
->StartSector
.QuadPart
;
654 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
655 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
656 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
658 NewPartEntry
->FormatState
= Unformatted
;
660 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
661 &NewPartEntry
->ListEntry
);
666 /* Start partition at head 1, cylinder 0 */
667 LastStartSector
= DiskEntry
->SectorAlignment
;
668 LastSectorCount
= 0ULL;
669 LastUnusedSectorCount
= 0ULL;
671 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
672 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
674 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
676 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
677 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
679 LastUnusedSectorCount
=
680 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
682 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
683 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
685 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
687 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
690 if (NewPartEntry
== NULL
)
693 NewPartEntry
->DiskEntry
= DiskEntry
;
695 NewPartEntry
->IsPartitioned
= FALSE
;
696 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
697 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
698 NewPartEntry
->StartSector
.QuadPart
;
700 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
701 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
702 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
704 NewPartEntry
->FormatState
= Unformatted
;
706 /* Insert the table into the list */
707 InsertTailList(&PartEntry
->ListEntry
,
708 &NewPartEntry
->ListEntry
);
711 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
712 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
715 Entry
= Entry
->Flink
;
718 /* Check for trailing unpartitioned disk space */
719 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
721 LastUnusedSectorCount
= Align(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
723 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
725 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
727 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
730 if (NewPartEntry
== NULL
)
733 NewPartEntry
->DiskEntry
= DiskEntry
;
735 NewPartEntry
->IsPartitioned
= FALSE
;
736 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
737 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
738 NewPartEntry
->StartSector
.QuadPart
;
740 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
741 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
742 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
744 NewPartEntry
->FormatState
= Unformatted
;
746 /* Append the table to the list */
747 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
748 &NewPartEntry
->ListEntry
);
752 if (DiskEntry
->ExtendedPartition
!= NULL
)
754 if (IsListEmpty(&DiskEntry
->LogicalPartListHead
))
756 DPRINT1("No logical partition!\n");
758 /* Create a partition table entry that represents the empty extended partition */
759 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
762 if (NewPartEntry
== NULL
)
765 NewPartEntry
->DiskEntry
= DiskEntry
;
766 NewPartEntry
->LogicalPartition
= TRUE
;
768 NewPartEntry
->IsPartitioned
= FALSE
;
769 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
770 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
772 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
773 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
774 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
776 NewPartEntry
->FormatState
= Unformatted
;
778 InsertTailList(&DiskEntry
->LogicalPartListHead
,
779 &NewPartEntry
->ListEntry
);
784 /* Start partition at head 1, cylinder 0 */
785 LastStartSector
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
786 LastSectorCount
= 0ULL;
787 LastUnusedSectorCount
= 0ULL;
789 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
790 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
792 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
794 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
795 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
797 LastUnusedSectorCount
=
798 PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
- (LastStartSector
+ LastSectorCount
);
800 if ((PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
) > (LastStartSector
+ LastSectorCount
) &&
801 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
803 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
805 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
808 if (NewPartEntry
== NULL
)
811 NewPartEntry
->DiskEntry
= DiskEntry
;
812 NewPartEntry
->LogicalPartition
= TRUE
;
814 NewPartEntry
->IsPartitioned
= FALSE
;
815 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
816 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
817 NewPartEntry
->StartSector
.QuadPart
;
819 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
820 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
821 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
823 NewPartEntry
->FormatState
= Unformatted
;
825 /* Insert the table into the list */
826 InsertTailList(&PartEntry
->ListEntry
,
827 &NewPartEntry
->ListEntry
);
830 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
831 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
834 Entry
= Entry
->Flink
;
837 /* Check for trailing unpartitioned disk space */
838 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
)
840 LastUnusedSectorCount
= Align(DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
842 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
844 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
846 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
849 if (NewPartEntry
== NULL
)
852 NewPartEntry
->DiskEntry
= DiskEntry
;
853 NewPartEntry
->LogicalPartition
= TRUE
;
855 NewPartEntry
->IsPartitioned
= FALSE
;
856 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
857 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
858 NewPartEntry
->StartSector
.QuadPart
;
860 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
861 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
862 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
864 NewPartEntry
->FormatState
= Unformatted
;
866 /* Append the table to the list */
867 InsertTailList(&DiskEntry
->LogicalPartListHead
,
868 &NewPartEntry
->ListEntry
);
873 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
881 IN PDISKENTRY DiskEntry
)
883 LARGE_INTEGER SystemTime
;
884 TIME_FIELDS TimeFields
;
886 PDISKENTRY DiskEntry2
;
889 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
893 NtQuerySystemTime(&SystemTime
);
894 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
896 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
897 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
898 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
899 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
901 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
906 /* check if the signature already exist */
908 * Check also signatures from disks, which are
909 * not visible (bootable) by the bios.
911 Entry2
= List
->DiskListHead
.Flink
;
912 while (Entry2
!= &List
->DiskListHead
)
914 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
916 if (DiskEntry
!= DiskEntry2
&&
917 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
920 Entry2
= Entry2
->Flink
;
923 if (Entry2
== &List
->DiskListHead
)
931 UpdateDiskSignatures(
935 PDISKENTRY DiskEntry
;
937 /* Print partition lines*/
938 Entry
= List
->DiskListHead
.Flink
;
939 while (Entry
!= &List
->DiskListHead
)
941 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
943 if (DiskEntry
->LayoutBuffer
&&
944 DiskEntry
->LayoutBuffer
->Signature
== 0)
946 SetDiskSignature(List
, DiskEntry
);
947 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
950 Entry
= Entry
->Flink
;
962 DISK_GEOMETRY DiskGeometry
;
963 SCSI_ADDRESS ScsiAddress
;
964 PDISKENTRY DiskEntry
;
965 IO_STATUS_BLOCK Iosb
;
967 PPARTITION_SECTOR Mbr
;
969 LARGE_INTEGER FileOffset
;
970 WCHAR Identifier
[20];
974 PLIST_ENTRY ListEntry
;
975 PBIOSDISKENTRY BiosDiskEntry
;
976 ULONG LayoutBufferSize
;
978 Status
= NtDeviceIoControlFile(FileHandle
,
983 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
987 sizeof(DISK_GEOMETRY
));
988 if (!NT_SUCCESS(Status
))
993 if (DiskGeometry
.MediaType
!= FixedMedia
&&
994 DiskGeometry
.MediaType
!= RemovableMedia
)
999 Status
= NtDeviceIoControlFile(FileHandle
,
1004 IOCTL_SCSI_GET_ADDRESS
,
1008 sizeof(SCSI_ADDRESS
));
1009 if (!NT_SUCCESS(Status
))
1014 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
1016 DiskGeometry
.BytesPerSector
);
1022 FileOffset
.QuadPart
= 0;
1023 Status
= NtReadFile(FileHandle
,
1029 DiskGeometry
.BytesPerSector
,
1032 if (!NT_SUCCESS(Status
))
1034 RtlFreeHeap(ProcessHeap
,
1037 DPRINT1("NtReadFile failed, status=%x\n", Status
);
1040 Signature
= Mbr
->Signature
;
1042 /* Calculate the MBR checksum */
1044 Buffer
= (PULONG
)Mbr
;
1045 for (i
= 0; i
< 128; i
++)
1047 Checksum
+= Buffer
[i
];
1049 Checksum
= ~Checksum
+ 1;
1051 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
1052 DPRINT("Identifier: %S\n", Identifier
);
1054 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
1057 if (DiskEntry
== NULL
)
1062 // DiskEntry->Checksum = Checksum;
1063 // DiskEntry->Signature = Signature;
1064 DiskEntry
->BiosFound
= FALSE
;
1066 /* Check if this disk has a valid MBR */
1067 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
1068 DiskEntry
->NoMbr
= TRUE
;
1070 DiskEntry
->NoMbr
= FALSE
;
1072 /* Free Mbr sector buffer */
1073 RtlFreeHeap(ProcessHeap
,
1077 ListEntry
= List
->BiosDiskListHead
.Flink
;
1078 while(ListEntry
!= &List
->BiosDiskListHead
)
1080 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
1082 * Compare the size from bios and the reported size from driver.
1083 * If we have more than one disk with a zero or with the same signatur
1084 * we must create new signatures and reboot. After the reboot,
1085 * it is possible to identify the disks.
1087 if (BiosDiskEntry
->Signature
== Signature
&&
1088 BiosDiskEntry
->Checksum
== Checksum
&&
1089 !BiosDiskEntry
->Recognized
)
1091 if (!DiskEntry
->BiosFound
)
1093 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
1094 DiskEntry
->BiosFound
= TRUE
;
1095 BiosDiskEntry
->Recognized
= TRUE
;
1101 ListEntry
= ListEntry
->Flink
;
1104 if (!DiskEntry
->BiosFound
)
1107 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1110 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
1114 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
1115 InitializeListHead(&DiskEntry
->LogicalPartListHead
);
1117 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
1118 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
1119 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
1120 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1122 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1123 DPRINT("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
1124 DPRINT("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
1125 DPRINT("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
1127 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1128 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1129 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1131 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1133 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
);
1134 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1136 DiskEntry
->DiskNumber
= DiskNumber
;
1137 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1138 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1139 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1141 GetDriverName(DiskEntry
);
1143 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1145 /* Allocate a layout buffer with 4 partition entries first */
1146 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1147 ((4 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1148 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1151 if (DiskEntry
->LayoutBuffer
== NULL
)
1156 Status
= NtDeviceIoControlFile(FileHandle
,
1161 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1164 DiskEntry
->LayoutBuffer
,
1166 DPRINT("Status: 0x%08lx\n", Status
);
1167 DPRINT("PartitionCount: %lu\n", DiskEntry
->LayoutBuffer
->PartitionCount
);
1169 /* If we need more than 4 partition entries, reallocte the buffer and
1170 retrieve the disk layout again */
1171 if (!NT_SUCCESS(Status
) && DiskEntry
->LayoutBuffer
->PartitionCount
> 4)
1173 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1174 ((DiskEntry
->LayoutBuffer
->PartitionCount
- ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1175 DiskEntry
->LayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
1177 DiskEntry
->LayoutBuffer
,
1179 if (DiskEntry
->LayoutBuffer
== NULL
)
1184 Status
= NtDeviceIoControlFile(FileHandle
,
1189 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1192 DiskEntry
->LayoutBuffer
,
1196 if (NT_SUCCESS(Status
))
1198 #ifdef DUMP_PARTITION_TABLE
1199 DumpPartitionTable(DiskEntry
);
1202 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
!= 0 &&
1203 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionLength
.QuadPart
!= 0 &&
1204 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionType
!= 0)
1206 if ((DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
) % DiskEntry
->SectorsPerTrack
== 0)
1208 DPRINT("Use %lu Sector alignment!\n", DiskEntry
->SectorsPerTrack
);
1210 else if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
% (1024 * 1024) == 0)
1212 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1216 DPRINT1("No matching aligment found! Partiton 1 starts at %I64u\n", DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
);
1221 DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1225 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1227 DiskEntry
->NewDisk
= TRUE
;
1228 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1230 for (i
= 0; i
< 4; i
++)
1231 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1235 for (i
= 0; i
< 4; i
++)
1237 AddPartitionToDisk(DiskNumber
,
1243 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1245 AddPartitionToDisk(DiskNumber
,
1253 ScanForUnpartitionedDiskSpace(DiskEntry
);
1258 CreatePartitionList(
1265 OBJECT_ATTRIBUTES ObjectAttributes
;
1266 SYSTEM_DEVICE_INFORMATION Sdi
;
1267 IO_STATUS_BLOCK Iosb
;
1271 WCHAR Buffer
[MAX_PATH
];
1272 UNICODE_STRING Name
;
1275 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1283 List
->Right
= Right
;
1284 List
->Bottom
= Bottom
;
1289 List
->TopDisk
= (ULONG
)-1;
1290 List
->TopPartition
= (ULONG
)-1;
1292 List
->CurrentDisk
= NULL
;
1293 List
->CurrentPartition
= NULL
;
1295 List
->BootDisk
= NULL
;
1296 List
->BootPartition
= NULL
;
1298 List
->TempDisk
= NULL
;
1299 List
->TempPartition
= NULL
;
1300 List
->FormatState
= Start
;
1302 InitializeListHead(&List
->DiskListHead
);
1303 InitializeListHead(&List
->BiosDiskListHead
);
1305 EnumerateBiosDiskEntries(List
);
1307 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1309 sizeof(SYSTEM_DEVICE_INFORMATION
),
1311 if (!NT_SUCCESS(Status
))
1313 RtlFreeHeap(ProcessHeap
, 0, List
);
1317 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1320 L
"\\Device\\Harddisk%d\\Partition0",
1322 RtlInitUnicodeString(&Name
,
1325 InitializeObjectAttributes(&ObjectAttributes
,
1331 Status
= NtOpenFile(&FileHandle
,
1332 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1336 FILE_SYNCHRONOUS_IO_NONALERT
);
1337 if (NT_SUCCESS(Status
))
1339 AddDiskToList(FileHandle
,
1343 NtClose(FileHandle
);
1347 UpdateDiskSignatures(List
);
1349 AssignDriveLetters(List
);
1352 List
->TopPartition
= 0;
1354 /* Search for first usable disk and partition */
1355 if (IsListEmpty(&List
->DiskListHead
))
1357 List
->CurrentDisk
= NULL
;
1358 List
->CurrentPartition
= NULL
;
1362 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1366 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1368 List
->CurrentPartition
= 0;
1372 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1383 DestroyPartitionList(
1386 PDISKENTRY DiskEntry
;
1387 PBIOSDISKENTRY BiosDiskEntry
;
1388 PPARTENTRY PartEntry
;
1391 /* Release disk and partition info */
1392 while (!IsListEmpty(&List
->DiskListHead
))
1394 Entry
= RemoveHeadList(&List
->DiskListHead
);
1395 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1397 /* Release driver name */
1398 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1400 /* Release primary partition list */
1401 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1403 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1404 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1406 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1409 /* Release logical partition list */
1410 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
1412 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
1413 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1415 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1418 /* Release layout buffer */
1419 if (DiskEntry
->LayoutBuffer
!= NULL
)
1420 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1423 /* Release disk entry */
1424 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1427 /* release the bios disk info */
1428 while(!IsListEmpty(&List
->BiosDiskListHead
))
1430 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1431 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1433 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1436 /* Release list head */
1437 RtlFreeHeap(ProcessHeap
, 0, List
);
1451 Width
= List
->Right
- List
->Left
- 1;
1452 Height
= List
->Bottom
- List
->Top
- 2;
1454 coPos
.X
= List
->Left
+ 1;
1455 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1457 if (List
->Line
>= 0 && List
->Line
<= Height
)
1459 FillConsoleOutputAttribute(StdOutput
,
1460 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1465 FillConsoleOutputCharacterA(StdOutput
,
1480 PDISKENTRY DiskEntry
,
1481 PPARTENTRY PartEntry
)
1483 CHAR LineBuffer
[128];
1488 LARGE_INTEGER PartSize
;
1493 Width
= List
->Right
- List
->Left
- 1;
1494 Height
= List
->Bottom
- List
->Top
- 2;
1496 coPos
.X
= List
->Left
+ 1;
1497 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1499 if (PartEntry
->IsPartitioned
== FALSE
)
1501 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1503 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1505 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1506 Unit
= MUIGetString(STRING_GB
);
1510 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1512 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1513 Unit
= MUIGetString(STRING_MB
);
1517 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1518 Unit
= MUIGetString(STRING_KB
);
1522 MUIGetString(STRING_UNPSPACE
),
1523 PartEntry
->LogicalPartition
? " " : "",
1524 PartEntry
->LogicalPartition
? "" : " ",
1530 /* Determine partition type */
1532 if (PartEntry
->New
== TRUE
)
1534 PartType
= MUIGetString(STRING_UNFORMATTED
);
1536 else if (PartEntry
->IsPartitioned
== TRUE
)
1538 if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
1539 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
1540 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
1541 (PartEntry
->PartitionType
== PARTITION_XINT13
))
1545 else if ((PartEntry
->PartitionType
== PARTITION_FAT32
) ||
1546 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
1550 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
1554 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
1556 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1558 else if ((PartEntry
->PartitionType
== PARTITION_EXTENDED
) ||
1559 (PartEntry
->PartitionType
== PARTITION_XINT13_EXTENDED
))
1561 PartType
= MUIGetString(STRING_EXTENDED_PARTITION
);
1565 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1567 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1569 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1570 Unit
= MUIGetString(STRING_GB
);
1574 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1576 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1577 Unit
= MUIGetString(STRING_MB
);
1581 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1582 Unit
= MUIGetString(STRING_KB
);
1585 if (PartType
== NULL
)
1588 MUIGetString(STRING_HDDINFOUNK5
),
1589 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1590 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1591 PartEntry
->BootIndicator
? '*' : ' ',
1592 PartEntry
->LogicalPartition
? " " : "",
1593 PartEntry
->PartitionType
,
1594 PartEntry
->LogicalPartition
? "" : " ",
1601 "%c%c %c %s%-24s%s %6lu %s",
1602 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1603 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1604 PartEntry
->BootIndicator
? '*' : ' ',
1605 PartEntry
->LogicalPartition
? " " : "",
1607 PartEntry
->LogicalPartition
? "" : " ",
1613 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1614 List
->CurrentPartition
== PartEntry
) ?
1615 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1616 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1618 if (List
->Line
>= 0 && List
->Line
<= Height
)
1620 FillConsoleOutputCharacterA(StdOutput
,
1628 if (List
->Line
>= 0 && List
->Line
<= Height
)
1630 FillConsoleOutputAttribute(StdOutput
,
1638 if (List
->Line
>= 0 && List
->Line
<= Height
)
1640 WriteConsoleOutputCharacterA(StdOutput
,
1642 min(strlen(LineBuffer
), Width
),
1655 PDISKENTRY DiskEntry
)
1657 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
1658 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
1659 CHAR LineBuffer
[128];
1664 ULARGE_INTEGER DiskSize
;
1667 Width
= List
->Right
- List
->Left
- 1;
1668 Height
= List
->Bottom
- List
->Top
- 2;
1670 coPos
.X
= List
->Left
+ 1;
1671 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1673 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1674 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
1676 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
1677 Unit
= MUIGetString(STRING_GB
);
1681 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
1682 if (DiskSize
.QuadPart
== 0)
1683 DiskSize
.QuadPart
= 1;
1684 Unit
= MUIGetString(STRING_MB
);
1687 if (DiskEntry
->DriverName
.Length
> 0)
1690 MUIGetString(STRING_HDINFOPARTSELECT
),
1693 DiskEntry
->DiskNumber
,
1697 DiskEntry
->DriverName
.Buffer
);
1702 MUIGetString(STRING_HDDINFOUNK6
),
1705 DiskEntry
->DiskNumber
,
1711 if (List
->Line
>= 0 && List
->Line
<= Height
)
1713 FillConsoleOutputAttribute(StdOutput
,
1714 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1719 FillConsoleOutputCharacterA(StdOutput
,
1727 if (List
->Line
>= 0 && List
->Line
<= Height
)
1729 WriteConsoleOutputCharacterA(StdOutput
,
1731 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1738 /* Print separator line */
1739 PrintEmptyLine(List
);
1741 /* Print partition lines*/
1742 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1743 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
1745 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
1747 PrintPartitionData(List
,
1751 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
1753 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
1754 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
1756 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
1758 PrintPartitionData(List
,
1762 LogicalEntry
= LogicalEntry
->Flink
;
1766 PrimaryEntry
= PrimaryEntry
->Flink
;
1769 /* Print separator line */
1770 PrintEmptyLine(List
);
1778 PLIST_ENTRY Entry
, Entry2
;
1779 PDISKENTRY DiskEntry
;
1780 PPARTENTRY PartEntry
= NULL
;
1784 SHORT CurrentDiskLine
;
1785 SHORT CurrentPartLine
;
1787 BOOL CurrentPartLineFound
= FALSE
;
1788 BOOL CurrentDiskLineFound
= FALSE
;
1790 /* Calculate the line of the current disk and partition */
1791 CurrentDiskLine
= 0;
1792 CurrentPartLine
= 0;
1795 Entry
= List
->DiskListHead
.Flink
;
1796 while (Entry
!= &List
->DiskListHead
)
1798 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1801 if (CurrentPartLineFound
== FALSE
)
1803 CurrentPartLine
+= 2;
1806 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1807 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1809 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1810 if (PartEntry
== List
->CurrentPartition
)
1812 CurrentPartLineFound
= TRUE
;
1815 Entry2
= Entry2
->Flink
;
1816 if (CurrentPartLineFound
== FALSE
)
1824 if (DiskEntry
== List
->CurrentDisk
)
1826 CurrentDiskLineFound
= TRUE
;
1829 Entry
= Entry
->Flink
;
1830 if (Entry
!= &List
->DiskListHead
)
1832 if (CurrentDiskLineFound
== FALSE
)
1835 CurrentDiskLine
= CurrentPartLine
;
1846 /* If it possible, make the disk name visible */
1847 if (CurrentPartLine
< List
->Offset
)
1849 List
->Offset
= CurrentPartLine
;
1851 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1853 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1856 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1858 List
->Offset
= CurrentDiskLine
;
1861 /* draw upper left corner */
1862 coPos
.X
= List
->Left
;
1863 coPos
.Y
= List
->Top
;
1864 FillConsoleOutputCharacterA(StdOutput
,
1870 /* draw upper edge */
1871 coPos
.X
= List
->Left
+ 1;
1872 coPos
.Y
= List
->Top
;
1873 if (List
->Offset
== 0)
1875 FillConsoleOutputCharacterA(StdOutput
,
1877 List
->Right
- List
->Left
- 1,
1883 FillConsoleOutputCharacterA(StdOutput
,
1885 List
->Right
- List
->Left
- 5,
1888 coPos
.X
= List
->Right
- 5;
1889 WriteConsoleOutputCharacterA(StdOutput
,
1894 coPos
.X
= List
->Right
- 2;
1895 FillConsoleOutputCharacterA(StdOutput
,
1902 /* draw upper right corner */
1903 coPos
.X
= List
->Right
;
1904 coPos
.Y
= List
->Top
;
1905 FillConsoleOutputCharacterA(StdOutput
,
1911 /* draw left and right edge */
1912 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1914 coPos
.X
= List
->Left
;
1916 FillConsoleOutputCharacterA(StdOutput
,
1922 coPos
.X
= List
->Right
;
1923 FillConsoleOutputCharacterA(StdOutput
,
1930 /* draw lower left corner */
1931 coPos
.X
= List
->Left
;
1932 coPos
.Y
= List
->Bottom
;
1933 FillConsoleOutputCharacterA(StdOutput
,
1939 /* draw lower edge */
1940 coPos
.X
= List
->Left
+ 1;
1941 coPos
.Y
= List
->Bottom
;
1942 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1944 FillConsoleOutputCharacterA(StdOutput
,
1946 List
->Right
- List
->Left
- 1,
1952 FillConsoleOutputCharacterA(StdOutput
,
1954 List
->Right
- List
->Left
- 5,
1957 coPos
.X
= List
->Right
- 5;
1958 WriteConsoleOutputCharacterA(StdOutput
,
1959 "(\x19)", // "(down)"
1963 coPos
.X
= List
->Right
- 2;
1964 FillConsoleOutputCharacterA(StdOutput
,
1971 /* draw lower right corner */
1972 coPos
.X
= List
->Right
;
1973 coPos
.Y
= List
->Bottom
;
1974 FillConsoleOutputCharacterA(StdOutput
,
1980 /* print list entries */
1981 List
->Line
= - List
->Offset
;
1983 Entry
= List
->DiskListHead
.Flink
;
1984 while (Entry
!= &List
->DiskListHead
)
1986 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1988 /* Print disk entry */
1992 Entry
= Entry
->Flink
;
2001 ULONG PartitionNumber
)
2003 PDISKENTRY DiskEntry
;
2004 PPARTENTRY PartEntry
;
2008 /* Check for empty disks */
2009 if (IsListEmpty(&List
->DiskListHead
))
2012 /* Check for first usable entry on next disk */
2013 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
2014 while (Entry1
!= &List
->DiskListHead
)
2016 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
2018 if (DiskEntry
->DiskNumber
== DiskNumber
)
2020 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
2021 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
2023 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2025 if (PartEntry
->PartitionNumber
== PartitionNumber
)
2027 List
->CurrentDisk
= DiskEntry
;
2028 List
->CurrentPartition
= PartEntry
;
2029 DrawPartitionList(List
);
2033 Entry2
= Entry2
->Flink
;
2039 Entry1
= Entry1
->Flink
;
2047 ScrollDownPartitionList(
2050 PLIST_ENTRY DiskListEntry
;
2051 PLIST_ENTRY PartListEntry
;
2052 PDISKENTRY DiskEntry
;
2053 PPARTENTRY PartEntry
;
2055 /* Fail, if no disks are available */
2056 if (IsListEmpty(&List
->DiskListHead
))
2059 /* Check for next usable entry on current disk */
2060 if (List
->CurrentPartition
!= NULL
)
2062 if (List
->CurrentPartition
->LogicalPartition
)
2064 /* Logical partition */
2066 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2067 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2069 /* Next logical partition */
2070 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2072 List
->CurrentPartition
= PartEntry
;
2077 PartListEntry
= List
->CurrentDisk
->ExtendedPartition
->ListEntry
.Flink
;
2078 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2080 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2082 List
->CurrentPartition
= PartEntry
;
2089 /* Primary or extended partition */
2091 if (List
->CurrentPartition
->IsPartitioned
== TRUE
&&
2092 IsContainerPartition(List
->CurrentPartition
->PartitionType
))
2094 /* First logical partition */
2095 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Flink
;
2096 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2098 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2100 List
->CurrentPartition
= PartEntry
;
2106 /* Next primary partition */
2107 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2108 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2110 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2112 List
->CurrentPartition
= PartEntry
;
2119 /* Search for the first partition entry on the next disk */
2120 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Flink
;
2121 while (DiskListEntry
!= &List
->DiskListHead
)
2123 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2125 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2126 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2128 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2130 List
->CurrentDisk
= DiskEntry
;
2131 List
->CurrentPartition
= PartEntry
;
2135 DiskListEntry
= DiskListEntry
->Flink
;
2143 ScrollUpPartitionList(
2146 PLIST_ENTRY DiskListEntry
;
2147 PLIST_ENTRY PartListEntry
;
2148 PDISKENTRY DiskEntry
;
2149 PPARTENTRY PartEntry
;
2151 /* Fail, if no disks are available */
2152 if (IsListEmpty(&List
->DiskListHead
))
2155 /* Check for previous usable entry on current disk */
2156 if (List
->CurrentPartition
!= NULL
)
2158 if (List
->CurrentPartition
->LogicalPartition
)
2160 /* Logical partition */
2161 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2162 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2164 /* Previous logical partition */
2165 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2169 /* Extended partition*/
2170 PartEntry
= List
->CurrentDisk
->ExtendedPartition
;
2173 List
->CurrentPartition
= PartEntry
;
2178 /* Primary or extended partition */
2180 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2181 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2183 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2185 if (PartEntry
->IsPartitioned
== TRUE
&&
2186 IsContainerPartition(PartEntry
->PartitionType
))
2188 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Blink
;
2189 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2192 List
->CurrentPartition
= PartEntry
;
2199 /* Search for the last partition entry on the previous disk */
2200 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Blink
;
2201 while (DiskListEntry
!= &List
->DiskListHead
)
2203 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2205 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Blink
;
2206 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2208 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2210 if (PartEntry
->IsPartitioned
== TRUE
&&
2211 IsContainerPartition(PartEntry
->PartitionType
))
2213 PartListEntry
= DiskEntry
->LogicalPartListHead
.Blink
;
2214 if (PartListEntry
!= &DiskEntry
->LogicalPartListHead
)
2216 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2218 List
->CurrentDisk
= DiskEntry
;
2219 List
->CurrentPartition
= PartEntry
;
2225 List
->CurrentDisk
= DiskEntry
;
2226 List
->CurrentPartition
= PartEntry
;
2231 DiskListEntry
= DiskListEntry
->Blink
;
2241 PPARTITION_INFORMATION PartitionInfo
)
2243 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
2244 PartitionInfo
->PartitionLength
.QuadPart
== 0)
2245 // PartitionInfo->PartitionType == 0)
2254 IsSamePrimaryLayoutEntry(
2255 IN PPARTITION_INFORMATION PartitionInfo
,
2256 IN PDISKENTRY DiskEntry
,
2257 IN PPARTENTRY PartEntry
)
2259 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
2260 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
2261 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2262 // PartitionInfo->PartitionType == PartEntry->PartitionType
2272 IN PDISKENTRY DiskEntry
)
2274 PPARTITION_INFORMATION PartitionInfo
;
2275 PLIST_ENTRY ListEntry
;
2276 PPARTENTRY PartEntry
;
2278 ULONG PartitionNumber
= 1;
2280 DPRINT1("UpdateDiskLayout()\n");
2282 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2283 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2285 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2287 if (PartEntry
->IsPartitioned
== TRUE
)
2289 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2291 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2293 DPRINT1("Updating partition entry %lu\n", Index
);
2295 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2296 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2297 PartitionInfo
->HiddenSectors
= 0;
2298 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2299 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2300 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2301 PartitionInfo
->RecognizedPartition
= FALSE
;
2302 PartitionInfo
->RewritePartition
= TRUE
;
2304 PartEntry
->PartitionNumber
= PartitionNumber
;
2305 PartEntry
->PartitionIndex
= Index
;
2309 else if (!IsEmptyLayoutEntry(PartitionInfo
))
2317 ListEntry
= ListEntry
->Flink
;
2320 for (;Index
< 4; Index
++)
2322 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2324 if (!IsEmptyLayoutEntry(PartitionInfo
))
2326 DPRINT1("Wiping partition entry %lu\n", Index
);
2328 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2329 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2330 PartitionInfo
->HiddenSectors
= 0;
2331 PartitionInfo
->PartitionNumber
= 0;
2332 PartitionInfo
->PartitionType
= 0;
2333 PartitionInfo
->BootIndicator
= FALSE
;
2334 PartitionInfo
->RecognizedPartition
= FALSE
;
2335 PartitionInfo
->RewritePartition
= TRUE
;
2339 #ifdef DUMP_PARTITION_TABLE
2340 DumpPartitionTable(DiskEntry
);
2347 GetPrevUnpartitionedEntry(
2348 PDISKENTRY DiskEntry
,
2349 PPARTENTRY PartEntry
)
2351 PPARTENTRY PrevPartEntry
;
2352 PLIST_ENTRY ListHead
;
2354 if (PartEntry
->LogicalPartition
)
2355 ListHead
= &DiskEntry
->LogicalPartListHead
;
2357 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2359 if (PartEntry
->ListEntry
.Blink
!= ListHead
)
2361 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2364 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2365 return PrevPartEntry
;
2374 GetNextUnpartitionedEntry(
2375 PDISKENTRY DiskEntry
,
2376 PPARTENTRY PartEntry
)
2378 PPARTENTRY NextPartEntry
;
2379 PLIST_ENTRY ListHead
;
2381 if (PartEntry
->LogicalPartition
)
2382 ListHead
= &DiskEntry
->LogicalPartListHead
;
2384 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2386 if (PartEntry
->ListEntry
.Flink
!= ListHead
)
2388 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2391 if (NextPartEntry
->IsPartitioned
== FALSE
)
2392 return NextPartEntry
;
2400 CreatePrimaryPartition(
2402 ULONGLONG SectorCount
,
2405 PDISKENTRY DiskEntry
;
2406 PPARTENTRY PartEntry
;
2407 PPARTENTRY NewPartEntry
;
2409 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2412 List
->CurrentDisk
== NULL
||
2413 List
->CurrentPartition
== NULL
||
2414 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2419 DiskEntry
= List
->CurrentDisk
;
2420 PartEntry
= List
->CurrentPartition
;
2422 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2424 if (AutoCreate
== TRUE
||
2425 Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2427 DPRINT1("Convert existing partition entry\n");
2429 /* Convert current entry to 'new (unformatted)' */
2430 PartEntry
->IsPartitioned
= TRUE
;
2431 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2432 PartEntry
->FormatState
= Unformatted
;
2433 PartEntry
->AutoCreate
= AutoCreate
;
2434 PartEntry
->New
= TRUE
;
2435 PartEntry
->BootIndicator
= FALSE
;
2437 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2438 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2439 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2443 DPRINT1("Add new partition entry\n");
2445 /* Insert and initialize a new partition entry */
2446 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2449 if (NewPartEntry
== NULL
)
2452 /* Insert the new entry into the list */
2453 InsertTailList(&PartEntry
->ListEntry
,
2454 &NewPartEntry
->ListEntry
);
2456 NewPartEntry
->DiskEntry
= DiskEntry
;
2458 NewPartEntry
->IsPartitioned
= TRUE
;
2459 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2460 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2461 NewPartEntry
->StartSector
.QuadPart
;
2462 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2464 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2465 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2466 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2468 NewPartEntry
->New
= TRUE
;
2469 NewPartEntry
->FormatState
= Unformatted
;
2470 NewPartEntry
->BootIndicator
= FALSE
;
2472 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2473 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2476 UpdateDiskLayout(DiskEntry
);
2478 DiskEntry
->Dirty
= TRUE
;
2480 UpdatePartitionNumbers(DiskEntry
);
2482 AssignDriveLetters(List
);
2488 AddLogicalDiskSpace(
2489 PDISKENTRY DiskEntry
)
2491 PPARTENTRY NewPartEntry
;
2493 DPRINT1("AddLogicalDiskSpace()\n");
2495 /* Create a partition table entry that represents the empty space in the container partition */
2496 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2499 if (NewPartEntry
== NULL
)
2502 NewPartEntry
->DiskEntry
= DiskEntry
;
2503 NewPartEntry
->LogicalPartition
= TRUE
;
2505 NewPartEntry
->IsPartitioned
= FALSE
;
2506 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
2507 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
2509 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2510 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2511 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2513 NewPartEntry
->FormatState
= Unformatted
;
2515 InsertTailList(&DiskEntry
->LogicalPartListHead
,
2516 &NewPartEntry
->ListEntry
);
2521 CreateExtendedPartition(
2523 ULONGLONG SectorCount
)
2525 PDISKENTRY DiskEntry
;
2526 PPARTENTRY PartEntry
;
2527 PPARTENTRY NewPartEntry
;
2529 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount
);
2532 List
->CurrentDisk
== NULL
||
2533 List
->CurrentPartition
== NULL
||
2534 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2539 DiskEntry
= List
->CurrentDisk
;
2540 PartEntry
= List
->CurrentPartition
;
2542 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2544 if (Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2546 DPRINT1("Convert existing partition entry\n");
2548 /* Convert current entry to 'new (unformatted)' */
2549 PartEntry
->IsPartitioned
= TRUE
;
2550 PartEntry
->FormatState
= Formatted
;
2551 PartEntry
->AutoCreate
= FALSE
;
2552 PartEntry
->New
= FALSE
;
2553 PartEntry
->BootIndicator
= FALSE
;
2555 if (PartEntry
->StartSector
.QuadPart
< 1450560)
2557 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2558 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
2562 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2563 PartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2566 DiskEntry
->ExtendedPartition
= PartEntry
;
2568 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2569 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2570 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2574 DPRINT1("Add new partition entry\n");
2576 /* Insert and initialize a new partition entry */
2577 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2580 if (NewPartEntry
== NULL
)
2583 /* Insert the new entry into the list */
2584 InsertTailList(&PartEntry
->ListEntry
,
2585 &NewPartEntry
->ListEntry
);
2587 NewPartEntry
->DiskEntry
= DiskEntry
;
2589 NewPartEntry
->IsPartitioned
= TRUE
;
2590 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2591 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2592 NewPartEntry
->StartSector
.QuadPart
;
2594 NewPartEntry
->New
= FALSE
;
2595 NewPartEntry
->FormatState
= Formatted
;
2596 NewPartEntry
->BootIndicator
= FALSE
;
2598 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2600 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2601 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2605 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2606 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2609 DiskEntry
->ExtendedPartition
= NewPartEntry
;
2611 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2612 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2614 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2615 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2616 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2619 AddLogicalDiskSpace(DiskEntry
);
2621 UpdateDiskLayout(DiskEntry
);
2623 DiskEntry
->Dirty
= TRUE
;
2625 UpdatePartitionNumbers(DiskEntry
);
2627 AssignDriveLetters(List
);
2632 CreateLogicalPartition(
2634 ULONGLONG SectorCount
)
2636 PDISKENTRY DiskEntry
;
2637 PPARTENTRY PartEntry
;
2638 PPARTENTRY NewPartEntry
;
2640 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount
);
2643 List
->CurrentDisk
== NULL
||
2644 List
->CurrentPartition
== NULL
||
2645 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2650 DiskEntry
= List
->CurrentDisk
;
2651 PartEntry
= List
->CurrentPartition
;
2653 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2655 if (Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2657 DPRINT1("Convert existing partition entry\n");
2659 /* Convert current entry to 'new (unformatted)' */
2660 PartEntry
->IsPartitioned
= TRUE
;
2661 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2662 PartEntry
->FormatState
= Unformatted
;
2663 PartEntry
->AutoCreate
= FALSE
;
2664 PartEntry
->New
= TRUE
;
2665 PartEntry
->BootIndicator
= FALSE
;
2666 PartEntry
->LogicalPartition
= TRUE
;
2668 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2669 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2670 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2674 DPRINT1("Add new partition entry\n");
2676 /* Insert and initialize a new partition entry */
2677 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2680 if (NewPartEntry
== NULL
)
2683 /* Insert the new entry into the list */
2684 InsertTailList(&PartEntry
->ListEntry
,
2685 &NewPartEntry
->ListEntry
);
2687 NewPartEntry
->DiskEntry
= DiskEntry
;
2689 NewPartEntry
->IsPartitioned
= TRUE
;
2690 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2691 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2692 NewPartEntry
->StartSector
.QuadPart
;
2693 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2695 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2696 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2697 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2699 NewPartEntry
->New
= TRUE
;
2700 NewPartEntry
->FormatState
= Unformatted
;
2701 NewPartEntry
->BootIndicator
= FALSE
;
2702 NewPartEntry
->LogicalPartition
= TRUE
;
2704 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2705 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2708 UpdateDiskLayout(DiskEntry
);
2710 DiskEntry
->Dirty
= TRUE
;
2712 UpdatePartitionNumbers(DiskEntry
);
2714 AssignDriveLetters(List
);
2719 DeleteCurrentPartition(
2722 PDISKENTRY DiskEntry
;
2723 PPARTENTRY PartEntry
;
2724 PPARTENTRY PrevPartEntry
;
2725 PPARTENTRY NextPartEntry
;
2726 PPARTENTRY LogicalPartEntry
;
2730 List
->CurrentDisk
== NULL
||
2731 List
->CurrentPartition
== NULL
||
2732 List
->CurrentPartition
->IsPartitioned
== FALSE
)
2737 DiskEntry
= List
->CurrentDisk
;
2738 PartEntry
= List
->CurrentPartition
;
2740 /* Delete all logical partiton entries if an extended partition will be deleted */
2741 if (DiskEntry
->ExtendedPartition
== PartEntry
)
2743 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
2745 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
2746 LogicalPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2748 RtlFreeHeap(ProcessHeap
, 0, LogicalPartEntry
);
2751 DiskEntry
->ExtendedPartition
= NULL
;
2754 /* Adjust unpartitioned disk space entries */
2756 /* Get pointer to previous and next unpartitioned entries */
2757 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
,
2760 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
,
2763 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2765 /* Merge previous, current and next unpartitioned entry */
2767 /* Adjust the previous entries length */
2768 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
2770 /* Remove the current entry */
2771 RemoveEntryList(&PartEntry
->ListEntry
);
2772 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2774 /* Remove the next entry */
2775 RemoveEntryList (&NextPartEntry
->ListEntry
);
2776 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
2778 /* Update current partition */
2779 List
->CurrentPartition
= PrevPartEntry
;
2781 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2783 /* Merge current and previous unpartitioned entry */
2785 /* Adjust the previous entries length */
2786 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2788 /* Remove the current entry */
2789 RemoveEntryList(&PartEntry
->ListEntry
);
2790 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2792 /* Update current partition */
2793 List
->CurrentPartition
= PrevPartEntry
;
2795 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2797 /* Merge current and next unpartitioned entry */
2799 /* Adjust the next entries offset and length */
2800 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2801 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2803 /* Remove the current entry */
2804 RemoveEntryList(&PartEntry
->ListEntry
);
2805 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2807 /* Update current partition */
2808 List
->CurrentPartition
= NextPartEntry
;
2812 /* Nothing to merge but change current entry */
2813 PartEntry
->IsPartitioned
= FALSE
;
2814 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2815 PartEntry
->FormatState
= Unformatted
;
2816 PartEntry
->DriveLetter
= 0;
2819 UpdateDiskLayout(DiskEntry
);
2821 DiskEntry
->Dirty
= TRUE
;
2823 UpdatePartitionNumbers(DiskEntry
);
2825 AssignDriveLetters(List
);
2830 CheckActiveBootPartition(
2833 PDISKENTRY DiskEntry
;
2834 PPARTENTRY PartEntry
;
2835 PLIST_ENTRY ListEntry
;
2837 /* Check for empty disk list */
2838 if (IsListEmpty (&List
->DiskListHead
))
2840 List
->BootDisk
= NULL
;
2841 List
->BootPartition
= NULL
;
2846 if (List
->BootDisk
!= NULL
&&
2847 List
->BootPartition
!= NULL
)
2849 /* We already have an active boot partition */
2854 /* Choose the currently selected disk */
2855 DiskEntry
= List
->CurrentDisk
;
2857 /* Check for empty partition list */
2858 if (IsListEmpty (&DiskEntry
->PrimaryPartListHead
))
2860 List
->BootDisk
= NULL
;
2861 List
->BootPartition
= NULL
;
2865 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
2869 /* Set active boot partition */
2870 if ((DiskEntry
->NewDisk
== TRUE
) ||
2871 (PartEntry
->BootIndicator
== FALSE
))
2873 PartEntry
->BootIndicator
= TRUE
;
2874 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].BootIndicator
= TRUE
;
2875 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
2876 DiskEntry
->Dirty
= TRUE
;
2878 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2879 List
->BootDisk
= DiskEntry
;
2880 List
->BootPartition
= PartEntry
;
2885 /* Disk is not new, scan all partitions to find a bootable one */
2886 List
->BootDisk
= NULL
;
2887 List
->BootPartition
= NULL
;
2889 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2890 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2892 PartEntry
= CONTAINING_RECORD(ListEntry
,
2896 /* Check if it is partitioned */
2897 if (PartEntry
->IsPartitioned
)
2899 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2900 PartEntry
->BootIndicator
)
2902 /* Yes, we found it */
2903 List
->BootDisk
= DiskEntry
;
2904 List
->BootPartition
= PartEntry
;
2906 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2907 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
);
2912 /* Go to the next one */
2913 ListEntry
= ListEntry
->Flink
;
2922 IN PDISKENTRY DiskEntry
)
2924 WCHAR DstPath
[MAX_PATH
];
2925 OBJECT_ATTRIBUTES ObjectAttributes
;
2926 IO_STATUS_BLOCK Iosb
;
2927 UNICODE_STRING Name
;
2929 HANDLE FileHandle
= NULL
;
2932 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
2935 L
"\\Device\\Harddisk%d\\Partition0",
2936 DiskEntry
->DiskNumber
);
2937 RtlInitUnicodeString(&Name
,
2939 InitializeObjectAttributes(&ObjectAttributes
,
2945 Status
= NtOpenFile(&FileHandle
,
2946 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
2950 FILE_SYNCHRONOUS_IO_NONALERT
);
2951 if (!NT_SUCCESS(Status
))
2953 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
2957 #ifdef DUMP_PARTITION_TABLE
2958 DumpPartitionTable(DiskEntry
);
2961 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2962 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
2963 Status
= NtDeviceIoControlFile(FileHandle
,
2968 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2969 DiskEntry
->LayoutBuffer
,
2973 if (!NT_SUCCESS(Status
))
2975 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
2978 if (FileHandle
!= NULL
)
2979 NtClose(FileHandle
);
2986 WritePartitionsToDisk(
2990 PDISKENTRY DiskEntry
;
2995 Entry
= List
->DiskListHead
.Flink
;
2996 while (Entry
!= &List
->DiskListHead
)
2998 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
3000 if (DiskEntry
->Dirty
== TRUE
)
3002 WritePartitions(List
, DiskEntry
);
3003 DiskEntry
->Dirty
= FALSE
;
3006 Entry
= Entry
->Flink
;
3014 SetMountedDeviceValues(
3017 PLIST_ENTRY Entry1
, Entry2
;
3018 PDISKENTRY DiskEntry
;
3019 PPARTENTRY PartEntry
;
3020 LARGE_INTEGER StartingOffset
;
3027 Entry1
= List
->DiskListHead
.Flink
;
3028 while (Entry1
!= &List
->DiskListHead
)
3030 DiskEntry
= CONTAINING_RECORD(Entry1
,
3034 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3035 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3037 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3038 if (PartEntry
->IsPartitioned
)
3040 if (PartEntry
->DriveLetter
)
3042 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
3043 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
3044 DiskEntry
->LayoutBuffer
->Signature
,
3052 Entry2
= Entry2
->Flink
;
3055 Entry1
= Entry1
->Flink
;
3064 GetPrimaryPartitionCount(
3065 IN PDISKENTRY DiskEntry
)
3068 PPARTENTRY PartEntry
;
3071 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
3072 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
3074 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
3075 if (PartEntry
->IsPartitioned
== TRUE
)
3078 Entry
= Entry
->Flink
;
3086 PrimaryPartitionCreationChecks(
3089 PDISKENTRY DiskEntry
;
3090 PPARTENTRY PartEntry
;
3092 DiskEntry
= List
->CurrentDisk
;
3093 PartEntry
= List
->CurrentPartition
;
3095 /* Fail if partition is already in use */
3096 if (PartEntry
->IsPartitioned
== TRUE
)
3097 return ERROR_NEW_PARTITION
;
3099 /* Fail if there are more than 4 partitions in the list */
3100 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3101 return ERROR_PARTITION_TABLE_FULL
;
3103 return ERROR_SUCCESS
;
3108 ExtendedPartitionCreationChecks(
3111 PDISKENTRY DiskEntry
;
3112 PPARTENTRY PartEntry
;
3114 DiskEntry
= List
->CurrentDisk
;
3115 PartEntry
= List
->CurrentPartition
;
3117 /* Fail if partition is already in use */
3118 if (PartEntry
->IsPartitioned
== TRUE
)
3119 return ERROR_NEW_PARTITION
;
3121 /* Fail if there are more than 4 partitions in the list */
3122 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3123 return ERROR_PARTITION_TABLE_FULL
;
3125 /* Fail if there is another extended partition in the list */
3126 if (DiskEntry
->ExtendedPartition
!= NULL
)
3127 return ERROR_ONLY_ONE_EXTENDED
;
3129 return ERROR_SUCCESS
;
3134 LogicalPartitionCreationChecks(
3137 // PDISKENTRY DiskEntry;
3138 PPARTENTRY PartEntry
;
3140 // DiskEntry = List->CurrentDisk;
3141 PartEntry
= List
->CurrentPartition
;
3143 /* Fail if partition is already in use */
3144 if (PartEntry
->IsPartitioned
== TRUE
)
3145 return ERROR_NEW_PARTITION
;
3147 return ERROR_SUCCESS
;
3152 GetNextUnformattedPartition(
3154 OUT PDISKENTRY
*pDiskEntry
,
3155 OUT PPARTENTRY
*pPartEntry
)
3157 PLIST_ENTRY Entry1
, Entry2
;
3158 PDISKENTRY DiskEntry
;
3159 PPARTENTRY PartEntry
;
3161 Entry1
= List
->DiskListHead
.Flink
;
3162 while (Entry1
!= &List
->DiskListHead
)
3164 DiskEntry
= CONTAINING_RECORD(Entry1
,
3168 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3169 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3171 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3172 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3174 *pDiskEntry
= DiskEntry
;
3175 *pPartEntry
= PartEntry
;
3179 Entry2
= Entry2
->Flink
;
3182 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3183 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3185 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3186 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3188 *pDiskEntry
= DiskEntry
;
3189 *pPartEntry
= PartEntry
;
3193 Entry2
= Entry2
->Flink
;
3196 Entry1
= Entry1
->Flink
;
3207 GetNextUncheckedPartition(
3209 OUT PDISKENTRY
*pDiskEntry
,
3210 OUT PPARTENTRY
*pPartEntry
)
3212 PLIST_ENTRY Entry1
, Entry2
;
3213 PDISKENTRY DiskEntry
;
3214 PPARTENTRY PartEntry
;
3216 Entry1
= List
->DiskListHead
.Flink
;
3217 while (Entry1
!= &List
->DiskListHead
)
3219 DiskEntry
= CONTAINING_RECORD(Entry1
,
3223 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3224 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3226 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3227 if (PartEntry
->NeedsCheck
== TRUE
)
3229 *pDiskEntry
= DiskEntry
;
3230 *pPartEntry
= PartEntry
;
3234 Entry2
= Entry2
->Flink
;
3237 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3238 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3240 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3241 if (PartEntry
->NeedsCheck
== TRUE
)
3243 *pDiskEntry
= DiskEntry
;
3244 *pPartEntry
= PartEntry
;
3248 Entry2
= Entry2
->Flink
;
3251 Entry1
= Entry1
->Flink
;