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 DbgPrint("%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 */
170 Entry1
= List
->DiskListHead
.Flink
;
171 while (Entry1
!= &List
->DiskListHead
)
173 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
175 Entry2
= DiskEntry
->PartListHead
.Flink
;
176 if (Entry2
!= &DiskEntry
->PartListHead
)
178 Entry2
= Entry2
->Flink
;
179 while (Entry2
!= &DiskEntry
->PartListHead
)
181 PartEntry
= CONTAINING_RECORD(Entry2
,
185 PartEntry
->DriveLetter
= 0;
187 if (PartEntry
->Unpartitioned
== FALSE
&&
188 !IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
190 if (IsRecognizedPartition(PartEntry
->PartInfo
[0].PartitionType
) ||
191 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
192 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
196 PartEntry
->DriveLetter
= Letter
;
202 Entry2
= Entry2
->Flink
;
206 Entry1
= Entry1
->Flink
;
214 UpdatePartitionNumbers(
215 PDISKENTRY DiskEntry
)
217 PPARTENTRY PartEntry
;
219 // ULONG PartitionNumber = 1;
220 ULONG PartitionIndex
= 0;
222 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
223 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
225 PartEntry
= CONTAINING_RECORD(Entry
,
229 if (PartEntry
->IsPartitioned
== FALSE
)
231 // PartEntry->PartitionNumber = 0;
232 PartEntry
->PartitionIndex
= (ULONG
)-1;
236 if (IsContainerPartition(PartEntry
->PartitionType
))
238 // PartEntry->PartitionNumber = 0;
240 else if (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
241 PartEntry
->SectorCount
.QuadPart
== 0ULL)
243 // PartEntry->PartitionNumber = 0;
247 // PartEntry->PartitionNumber = PartitionNumber++;
250 PartEntry
->PartitionIndex
= PartitionIndex
++;
253 Entry
= Entry
->Flink
;
260 DiskIdentifierQueryRoutine(
268 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
269 UNICODE_STRING NameU
;
271 if (ValueType
== REG_SZ
&&
272 ValueLength
== 20 * sizeof(WCHAR
))
274 NameU
.Buffer
= (PWCHAR
)ValueData
;
275 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
276 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
278 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
279 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
281 return STATUS_SUCCESS
;
284 return STATUS_UNSUCCESSFUL
;
290 DiskConfigurationDataQueryRoutine(
298 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
299 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
300 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
303 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
304 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
305 return STATUS_UNSUCCESSFUL
;
307 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
309 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
311 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
312 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
313 return STATUS_UNSUCCESSFUL
;
316 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
318 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
319 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
322 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
323 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
325 return STATUS_SUCCESS
;
328 return STATUS_UNSUCCESSFUL
;
334 SystemConfigurationDataQueryRoutine(
342 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
343 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
346 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
347 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
348 return STATUS_UNSUCCESSFUL
;
350 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
352 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
354 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
355 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
356 return STATUS_UNSUCCESSFUL
;
359 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
361 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
362 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
365 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
366 if (*Int13Drives
== NULL
)
367 return STATUS_NO_MEMORY
;
370 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
371 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
372 return STATUS_SUCCESS
;
375 return STATUS_UNSUCCESSFUL
;
379 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
382 EnumerateBiosDiskEntries(
385 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
390 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
391 PBIOSDISKENTRY BiosDiskEntry
;
393 memset(QueryTable
, 0, sizeof(QueryTable
));
395 QueryTable
[1].Name
= L
"Configuration Data";
396 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
398 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
399 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
403 if (!NT_SUCCESS(Status
))
405 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
412 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
413 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
418 if (!NT_SUCCESS(Status
))
423 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
424 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
429 if (NT_SUCCESS(Status
))
433 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
434 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
439 if (!NT_SUCCESS(Status
))
441 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
445 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
446 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
451 if (NT_SUCCESS(Status
))
453 QueryTable
[0].Name
= L
"Identifier";
454 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
455 QueryTable
[1].Name
= L
"Configuration Data";
456 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
461 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
462 if (BiosDiskEntry
== NULL
)
467 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
468 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
471 (PVOID
)BiosDiskEntry
,
473 if (!NT_SUCCESS(Status
))
475 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
479 BiosDiskEntry
->DiskNumber
= DiskCount
;
480 BiosDiskEntry
->Recognized
= FALSE
;
482 if (DiskCount
< Int13Drives
[0].NumberDrives
)
484 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
488 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
491 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
493 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
494 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
495 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
496 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
497 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
498 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
499 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
500 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
501 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
502 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
503 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
509 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
517 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
525 PDISKENTRY DiskEntry
,
526 ULONG PartitionIndex
,
527 BOOLEAN ExtendedPartition
)
529 PPARTITION_INFORMATION PartitionInfo
;
530 PPARTENTRY PartEntry
;
532 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[PartitionIndex
];
533 if (PartitionInfo
->PartitionType
== 0)
536 PartEntry
= RtlAllocateHeap(ProcessHeap
,
539 if (PartEntry
== NULL
)
544 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
545 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
547 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
548 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
549 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
551 PartEntry
->ExtendedPartition
= ExtendedPartition
;
552 PartEntry
->IsPartitioned
= TRUE
;
553 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
554 PartEntry
->PartitionIndex
= PartitionIndex
;
556 if (IsContainerPartition(PartEntry
->PartitionType
))
558 PartEntry
->FormatState
= Unformatted
;
560 else if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
561 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
562 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
563 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
564 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
565 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
568 if (CheckFatFormat())
570 PartEntry
->FormatState
= Preformatted
;
574 PartEntry
->FormatState
= Unformatted
;
577 PartEntry
->FormatState
= Preformatted
;
579 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
582 if (CheckExt2Format())
584 PartEntry
->FormatState
= Preformatted
;
588 PartEntry
->FormatState
= Unformatted
;
591 PartEntry
->FormatState
= Preformatted
;
593 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
596 if (CheckNtfsFormat())
598 PartEntry
->FormatState
= Preformatted
;
600 else if (CheckHpfsFormat())
602 PartEntry
->FormatState
= Preformatted
;
606 PartEntry
->FormatState
= Unformatted
;
609 PartEntry
->FormatState
= Preformatted
;
613 PartEntry
->FormatState
= UnknownFormat
;
616 if (ExtendedPartition
)
617 InsertTailList(&DiskEntry
->ExtendedPartListHead
,
618 &PartEntry
->ListEntry
);
620 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
621 &PartEntry
->ListEntry
);
627 ScanForUnpartitionedDiskSpace(
628 PDISKENTRY DiskEntry
)
630 ULONGLONG LastStartSector
;
631 ULONGLONG LastSectorCount
;
632 ULONGLONG LastUnusedSectorCount
;
633 PPARTENTRY PartEntry
;
634 PPARTENTRY NewPartEntry
;
637 DPRINT1("ScanForUnpartitionedDiskSpace()\n");
639 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
641 DPRINT1("No primary partition!\n");
643 /* Create a partition table that represents the empty disk */
644 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
647 if (NewPartEntry
== NULL
)
650 NewPartEntry
->DiskEntry
= DiskEntry
;
652 NewPartEntry
->IsPartitioned
= FALSE
;
653 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
654 NewPartEntry
->SectorCount
.QuadPart
= Align(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
655 DiskEntry
->SectorsPerTrack
;
656 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
657 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
658 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
660 NewPartEntry
->FormatState
= Unformatted
;
662 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
663 &NewPartEntry
->ListEntry
);
668 /* Start partition at head 1, cylinder 0 */
669 LastStartSector
= DiskEntry
->SectorsPerTrack
;
670 LastSectorCount
= 0ULL;
671 LastUnusedSectorCount
= 0ULL;
673 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
674 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
676 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
678 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
679 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
681 LastUnusedSectorCount
=
682 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
684 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
685 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
687 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
689 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
692 if (NewPartEntry
== NULL
)
695 NewPartEntry
->DiskEntry
= DiskEntry
;
697 NewPartEntry
->IsPartitioned
= FALSE
;
698 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
699 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
700 NewPartEntry
->StartSector
.QuadPart
;
701 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
702 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
703 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
705 NewPartEntry
->FormatState
= Unformatted
;
707 /* Insert the table into the list */
708 InsertTailList(&PartEntry
->ListEntry
,
709 &NewPartEntry
->ListEntry
);
712 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
713 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
716 Entry
= Entry
->Flink
;
719 /* Check for trailing unpartitioned disk space */
720 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
722 LastUnusedSectorCount
= Align(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
724 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
726 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
728 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
731 if (NewPartEntry
== NULL
)
734 NewPartEntry
->DiskEntry
= DiskEntry
;
736 NewPartEntry
->IsPartitioned
= FALSE
;
737 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
738 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
739 NewPartEntry
->StartSector
.QuadPart
;
740 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
741 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
742 DPRINT1("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 DPRINT1("ScanForUnpartitionedDiskSpace() done\n");
760 IN PDISKENTRY DiskEntry
)
762 LARGE_INTEGER SystemTime
;
763 TIME_FIELDS TimeFields
;
765 PDISKENTRY DiskEntry2
;
768 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
772 NtQuerySystemTime(&SystemTime
);
773 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
775 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
776 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
777 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
778 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
780 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
785 /* check if the signature already exist */
787 * Check also signatures from disks, which are
788 * not visible (bootable) by the bios.
790 Entry2
= List
->DiskListHead
.Flink
;
791 while (Entry2
!= &List
->DiskListHead
)
793 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
795 if (DiskEntry
!= DiskEntry2
&&
796 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
799 Entry2
= Entry2
->Flink
;
802 if (Entry2
== &List
->DiskListHead
)
810 UpdateDiskSignatures(
814 PDISKENTRY DiskEntry
;
816 /* Print partition lines*/
817 Entry
= List
->DiskListHead
.Flink
;
818 while (Entry
!= &List
->DiskListHead
)
820 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
822 if (DiskEntry
->LayoutBuffer
&&
823 DiskEntry
->LayoutBuffer
->Signature
== 0)
825 SetDiskSignature(List
, DiskEntry
);
826 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
829 Entry
= Entry
->Flink
;
841 DISK_GEOMETRY DiskGeometry
;
842 SCSI_ADDRESS ScsiAddress
;
843 PDISKENTRY DiskEntry
;
844 IO_STATUS_BLOCK Iosb
;
846 PPARTITION_SECTOR Mbr
;
848 LARGE_INTEGER FileOffset
;
849 WCHAR Identifier
[20];
853 PLIST_ENTRY ListEntry
;
854 PBIOSDISKENTRY BiosDiskEntry
;
855 ULONG LayoutBufferSize
;
857 Status
= NtDeviceIoControlFile(FileHandle
,
862 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
866 sizeof(DISK_GEOMETRY
));
867 if (!NT_SUCCESS(Status
))
872 if (DiskGeometry
.MediaType
!= FixedMedia
&&
873 DiskGeometry
.MediaType
!= RemovableMedia
)
878 Status
= NtDeviceIoControlFile(FileHandle
,
883 IOCTL_SCSI_GET_ADDRESS
,
887 sizeof(SCSI_ADDRESS
));
888 if (!NT_SUCCESS(Status
))
893 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
895 DiskGeometry
.BytesPerSector
);
901 FileOffset
.QuadPart
= 0;
902 Status
= NtReadFile(FileHandle
,
908 DiskGeometry
.BytesPerSector
,
911 if (!NT_SUCCESS(Status
))
913 RtlFreeHeap(ProcessHeap
,
916 DPRINT1("NtReadFile failed, status=%x\n", Status
);
919 Signature
= Mbr
->Signature
;
921 /* Calculate the MBR checksum */
923 Buffer
= (PULONG
)Mbr
;
924 for (i
= 0; i
< 128; i
++)
926 Checksum
+= Buffer
[i
];
928 Checksum
= ~Checksum
+ 1;
930 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
931 DPRINT("Identifier: %S\n", Identifier
);
933 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
936 if (DiskEntry
== NULL
)
941 // DiskEntry->Checksum = Checksum;
942 // DiskEntry->Signature = Signature;
943 DiskEntry
->BiosFound
= FALSE
;
945 /* Check if this disk has a valid MBR */
946 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
947 DiskEntry
->NoMbr
= TRUE
;
949 DiskEntry
->NoMbr
= FALSE
;
951 /* Free Mbr sector buffer */
952 RtlFreeHeap(ProcessHeap
,
956 ListEntry
= List
->BiosDiskListHead
.Flink
;
957 while(ListEntry
!= &List
->BiosDiskListHead
)
959 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
961 * Compare the size from bios and the reported size from driver.
962 * If we have more than one disk with a zero or with the same signatur
963 * we must create new signatures and reboot. After the reboot,
964 * it is possible to identify the disks.
966 if (BiosDiskEntry
->Signature
== Signature
&&
967 BiosDiskEntry
->Checksum
== Checksum
&&
968 !BiosDiskEntry
->Recognized
)
970 if (!DiskEntry
->BiosFound
)
972 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
973 DiskEntry
->BiosFound
= TRUE
;
974 BiosDiskEntry
->Recognized
= TRUE
;
980 ListEntry
= ListEntry
->Flink
;
983 if (!DiskEntry
->BiosFound
)
986 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
989 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
993 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
994 InitializeListHead(&DiskEntry
->ExtendedPartListHead
);
996 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
997 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
998 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
999 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1001 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1002 DPRINT("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
1003 DPRINT("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
1004 DPRINT("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
1006 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1007 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1008 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1010 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1012 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
);
1013 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1015 DiskEntry
->DiskNumber
= DiskNumber
;
1016 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1017 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1018 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1020 GetDriverName(DiskEntry
);
1022 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1025 * Allocate a buffer for 26 logical drives (2 entries each == 52)
1026 * plus the main partiton table (4 entries). Total 56 entries.
1028 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1029 ((56 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1030 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1033 if (DiskEntry
->LayoutBuffer
== NULL
)
1038 Status
= NtDeviceIoControlFile(FileHandle
,
1043 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1046 DiskEntry
->LayoutBuffer
,
1048 if (NT_SUCCESS(Status
))
1050 #ifdef DUMP_PARTITION_TABLE
1051 DumpPartitionTable(DiskEntry
);
1054 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1056 DiskEntry
->NewDisk
= TRUE
;
1057 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1059 for (i
= 0; i
< 4; i
++)
1060 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1064 for (i
= 0; i
< 4; i
++)
1066 AddPartitionToDisk(DiskNumber
,
1072 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1074 AddPartitionToDisk(DiskNumber
,
1082 ScanForUnpartitionedDiskSpace(DiskEntry
);
1087 CreatePartitionList(
1094 OBJECT_ATTRIBUTES ObjectAttributes
;
1095 SYSTEM_DEVICE_INFORMATION Sdi
;
1096 IO_STATUS_BLOCK Iosb
;
1100 WCHAR Buffer
[MAX_PATH
];
1101 UNICODE_STRING Name
;
1104 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1112 List
->Right
= Right
;
1113 List
->Bottom
= Bottom
;
1118 List
->TopDisk
= (ULONG
)-1;
1119 List
->TopPartition
= (ULONG
)-1;
1121 List
->CurrentDisk
= NULL
;
1122 List
->CurrentPartition
= NULL
;
1124 InitializeListHead(&List
->DiskListHead
);
1125 InitializeListHead(&List
->BiosDiskListHead
);
1127 EnumerateBiosDiskEntries(List
);
1129 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1131 sizeof(SYSTEM_DEVICE_INFORMATION
),
1133 if (!NT_SUCCESS(Status
))
1135 RtlFreeHeap(ProcessHeap
, 0, List
);
1139 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1142 L
"\\Device\\Harddisk%d\\Partition0",
1144 RtlInitUnicodeString(&Name
,
1147 InitializeObjectAttributes(&ObjectAttributes
,
1153 Status
= NtOpenFile(&FileHandle
,
1154 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1158 FILE_SYNCHRONOUS_IO_NONALERT
);
1159 if (NT_SUCCESS(Status
))
1161 AddDiskToList(FileHandle
,
1165 NtClose(FileHandle
);
1169 UpdateDiskSignatures(List
);
1171 AssignDriveLetters(List
);
1174 List
->TopPartition
= 0;
1176 /* Search for first usable disk and partition */
1177 if (IsListEmpty(&List
->DiskListHead
))
1179 List
->CurrentDisk
= NULL
;
1180 List
->CurrentPartition
= NULL
;
1184 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1188 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1190 List
->CurrentPartition
= 0;
1194 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1205 DestroyPartitionList(
1208 PDISKENTRY DiskEntry
;
1209 PBIOSDISKENTRY BiosDiskEntry
;
1210 PPARTENTRY PartEntry
;
1213 /* Release disk and partition info */
1214 while (!IsListEmpty(&List
->DiskListHead
))
1216 Entry
= RemoveHeadList(&List
->DiskListHead
);
1217 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1219 /* Release driver name */
1220 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1222 /* Release primary partition list */
1223 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1225 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1226 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1228 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1231 /* Release extended partition list */
1232 while (!IsListEmpty(&DiskEntry
->ExtendedPartListHead
))
1234 Entry
= RemoveHeadList(&DiskEntry
->ExtendedPartListHead
);
1235 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1237 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1240 /* Release layout buffer */
1241 if (DiskEntry
->LayoutBuffer
!= NULL
)
1242 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1245 /* Release disk entry */
1246 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1249 /* release the bios disk info */
1250 while(!IsListEmpty(&List
->BiosDiskListHead
))
1252 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1253 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1255 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1258 /* Release list head */
1259 RtlFreeHeap(ProcessHeap
, 0, List
);
1273 Width
= List
->Right
- List
->Left
- 1;
1274 Height
= List
->Bottom
- List
->Top
- 2;
1276 coPos
.X
= List
->Left
+ 1;
1277 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1279 if (List
->Line
>= 0 && List
->Line
<= Height
)
1281 FillConsoleOutputAttribute(StdOutput
,
1282 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1287 FillConsoleOutputCharacterA(StdOutput
,
1302 PDISKENTRY DiskEntry
,
1303 PPARTENTRY PartEntry
)
1305 CHAR LineBuffer
[128];
1310 LARGE_INTEGER PartSize
;
1315 Width
= List
->Right
- List
->Left
- 1;
1316 Height
= List
->Bottom
- List
->Top
- 2;
1318 coPos
.X
= List
->Left
+ 1;
1319 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1321 if (PartEntry
->IsPartitioned
== FALSE
)
1323 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1325 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1327 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1328 Unit
= MUIGetString(STRING_GB
);
1332 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1334 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1335 Unit
= MUIGetString(STRING_MB
);
1339 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1340 Unit
= MUIGetString(STRING_KB
);
1344 MUIGetString(STRING_UNPSPACE
),
1345 PartEntry
->ExtendedPartition
? " " : "",
1346 PartEntry
->ExtendedPartition
? "" : " ",
1352 /* Determine partition type */
1354 if (PartEntry
->New
== TRUE
)
1356 PartType
= MUIGetString(STRING_UNFORMATTED
);
1358 else if (PartEntry
->IsPartitioned
== TRUE
)
1360 if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
1361 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
1362 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
1363 (PartEntry
->PartitionType
== PARTITION_XINT13
))
1367 else if ((PartEntry
->PartitionType
== PARTITION_FAT32
) ||
1368 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
1372 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
1376 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
1378 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1380 else if ((PartEntry
->PartitionType
== PARTITION_EXTENDED
) ||
1381 (PartEntry
->PartitionType
== PARTITION_XINT13_EXTENDED
))
1383 PartType
= MUIGetString(STRING_EXTENDED_PARTITION
);
1387 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1389 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1391 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1392 Unit
= MUIGetString(STRING_GB
);
1396 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1398 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1399 Unit
= MUIGetString(STRING_MB
);
1403 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1404 Unit
= MUIGetString(STRING_KB
);
1407 if (PartType
== NULL
)
1410 MUIGetString(STRING_HDDINFOUNK5
),
1411 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1412 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1413 PartEntry
->ExtendedPartition
? " " : "",
1414 PartEntry
->PartitionType
,
1415 PartEntry
->ExtendedPartition
? "" : " ",
1422 "%c%c %s%-24s%s %6lu %s",
1423 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1424 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1425 PartEntry
->ExtendedPartition
? " " : "",
1427 PartEntry
->ExtendedPartition
? "" : " ",
1433 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1434 List
->CurrentPartition
== PartEntry
) ?
1435 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1436 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1438 if (List
->Line
>= 0 && List
->Line
<= Height
)
1440 FillConsoleOutputCharacterA(StdOutput
,
1448 if (List
->Line
>= 0 && List
->Line
<= Height
)
1450 FillConsoleOutputAttribute(StdOutput
,
1458 if (List
->Line
>= 0 && List
->Line
<= Height
)
1460 WriteConsoleOutputCharacterA(StdOutput
,
1462 min(strlen(LineBuffer
), Width
),
1475 PDISKENTRY DiskEntry
)
1477 PPARTENTRY PrimaryPartEntry
, ExtendedPartEntry
;
1478 PLIST_ENTRY PrimaryEntry
, ExtendedEntry
;
1479 CHAR LineBuffer
[128];
1484 ULARGE_INTEGER DiskSize
;
1487 Width
= List
->Right
- List
->Left
- 1;
1488 Height
= List
->Bottom
- List
->Top
- 2;
1490 coPos
.X
= List
->Left
+ 1;
1491 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1493 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1494 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
1496 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
1497 Unit
= MUIGetString(STRING_GB
);
1501 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
1502 if (DiskSize
.QuadPart
== 0)
1503 DiskSize
.QuadPart
= 1;
1504 Unit
= MUIGetString(STRING_MB
);
1507 if (DiskEntry
->DriverName
.Length
> 0)
1510 MUIGetString(STRING_HDINFOPARTSELECT
),
1513 DiskEntry
->DiskNumber
,
1517 DiskEntry
->DriverName
.Buffer
);
1522 MUIGetString(STRING_HDDINFOUNK6
),
1525 DiskEntry
->DiskNumber
,
1531 if (List
->Line
>= 0 && List
->Line
<= Height
)
1533 FillConsoleOutputAttribute(StdOutput
,
1534 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1539 FillConsoleOutputCharacterA(StdOutput
,
1547 if (List
->Line
>= 0 && List
->Line
<= Height
)
1549 WriteConsoleOutputCharacterA(StdOutput
,
1551 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1558 /* Print separator line */
1559 PrintEmptyLine(List
);
1561 /* Print partition lines*/
1562 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1563 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
1565 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
1567 PrintPartitionData(List
,
1571 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
1573 ExtendedEntry
= DiskEntry
->ExtendedPartListHead
.Flink
;
1574 while (ExtendedEntry
!= &DiskEntry
->ExtendedPartListHead
)
1576 ExtendedPartEntry
= CONTAINING_RECORD(ExtendedEntry
, PARTENTRY
, ListEntry
);
1578 PrintPartitionData(List
,
1582 ExtendedEntry
= ExtendedEntry
->Flink
;
1586 PrimaryEntry
= PrimaryEntry
->Flink
;
1589 /* Print separator line */
1590 PrintEmptyLine(List
);
1598 PLIST_ENTRY Entry
, Entry2
;
1599 PDISKENTRY DiskEntry
;
1600 PPARTENTRY PartEntry
= NULL
;
1604 SHORT CurrentDiskLine
;
1605 SHORT CurrentPartLine
;
1607 BOOL CurrentPartLineFound
= FALSE
;
1608 BOOL CurrentDiskLineFound
= FALSE
;
1610 /* Calculate the line of the current disk and partition */
1611 CurrentDiskLine
= 0;
1612 CurrentPartLine
= 0;
1615 Entry
= List
->DiskListHead
.Flink
;
1616 while (Entry
!= &List
->DiskListHead
)
1618 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1621 if (CurrentPartLineFound
== FALSE
)
1623 CurrentPartLine
+= 2;
1626 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1627 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1629 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1630 if (PartEntry
== List
->CurrentPartition
)
1632 CurrentPartLineFound
= TRUE
;
1635 Entry2
= Entry2
->Flink
;
1636 if (CurrentPartLineFound
== FALSE
)
1644 if (DiskEntry
== List
->CurrentDisk
)
1646 CurrentDiskLineFound
= TRUE
;
1649 Entry
= Entry
->Flink
;
1650 if (Entry
!= &List
->DiskListHead
)
1652 if (CurrentDiskLineFound
== FALSE
)
1655 CurrentDiskLine
= CurrentPartLine
;
1666 /* If it possible, make the disk name visible */
1667 if (CurrentPartLine
< List
->Offset
)
1669 List
->Offset
= CurrentPartLine
;
1671 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1673 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1676 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1678 List
->Offset
= CurrentDiskLine
;
1681 /* draw upper left corner */
1682 coPos
.X
= List
->Left
;
1683 coPos
.Y
= List
->Top
;
1684 FillConsoleOutputCharacterA(StdOutput
,
1690 /* draw upper edge */
1691 coPos
.X
= List
->Left
+ 1;
1692 coPos
.Y
= List
->Top
;
1693 if (List
->Offset
== 0)
1695 FillConsoleOutputCharacterA(StdOutput
,
1697 List
->Right
- List
->Left
- 1,
1703 FillConsoleOutputCharacterA(StdOutput
,
1705 List
->Right
- List
->Left
- 5,
1708 coPos
.X
= List
->Right
- 5;
1709 WriteConsoleOutputCharacterA(StdOutput
,
1714 coPos
.X
= List
->Right
- 2;
1715 FillConsoleOutputCharacterA(StdOutput
,
1722 /* draw upper right corner */
1723 coPos
.X
= List
->Right
;
1724 coPos
.Y
= List
->Top
;
1725 FillConsoleOutputCharacterA(StdOutput
,
1731 /* draw left and right edge */
1732 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1734 coPos
.X
= List
->Left
;
1736 FillConsoleOutputCharacterA(StdOutput
,
1742 coPos
.X
= List
->Right
;
1743 FillConsoleOutputCharacterA(StdOutput
,
1750 /* draw lower left corner */
1751 coPos
.X
= List
->Left
;
1752 coPos
.Y
= List
->Bottom
;
1753 FillConsoleOutputCharacterA(StdOutput
,
1759 /* draw lower edge */
1760 coPos
.X
= List
->Left
+ 1;
1761 coPos
.Y
= List
->Bottom
;
1762 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1764 FillConsoleOutputCharacterA(StdOutput
,
1766 List
->Right
- List
->Left
- 1,
1772 FillConsoleOutputCharacterA(StdOutput
,
1774 List
->Right
- List
->Left
- 5,
1777 coPos
.X
= List
->Right
- 5;
1778 WriteConsoleOutputCharacterA(StdOutput
,
1779 "(\x19)", // "(down)"
1783 coPos
.X
= List
->Right
- 2;
1784 FillConsoleOutputCharacterA(StdOutput
,
1791 /* draw lower right corner */
1792 coPos
.X
= List
->Right
;
1793 coPos
.Y
= List
->Bottom
;
1794 FillConsoleOutputCharacterA(StdOutput
,
1800 /* print list entries */
1801 List
->Line
= - List
->Offset
;
1803 Entry
= List
->DiskListHead
.Flink
;
1804 while (Entry
!= &List
->DiskListHead
)
1806 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1808 /* Print disk entry */
1812 Entry
= Entry
->Flink
;
1821 ULONG PartitionNumber
)
1823 PDISKENTRY DiskEntry
;
1824 PPARTENTRY PartEntry
;
1828 /* Check for empty disks */
1829 if (IsListEmpty(&List
->DiskListHead
))
1832 /* Check for first usable entry on next disk */
1833 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1834 while (Entry1
!= &List
->DiskListHead
)
1836 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1838 if (DiskEntry
->DiskNumber
== DiskNumber
)
1840 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1841 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1843 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1845 if (PartEntry
->PartitionNumber
== PartitionNumber
)
1847 List
->CurrentDisk
= DiskEntry
;
1848 List
->CurrentPartition
= PartEntry
;
1849 DrawPartitionList(List
);
1853 Entry2
= Entry2
->Flink
;
1859 Entry1
= Entry1
->Flink
;
1867 ScrollDownPartitionList(
1870 // PDISKENTRY DiskEntry;
1871 PPARTENTRY PartEntry
;
1872 // PLIST_ENTRY Entry1;
1875 /* Check for empty disks */
1876 if (IsListEmpty(&List
->DiskListHead
))
1879 /* Check for next usable entry on current disk */
1880 if (List
->CurrentPartition
!= NULL
)
1882 Entry2
= List
->CurrentPartition
->ListEntry
.Flink
;
1883 if (Entry2
!= &List
->CurrentDisk
->PrimaryPartListHead
)
1885 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1887 List
->CurrentPartition
= PartEntry
;
1888 DrawPartitionList(List
);
1894 /* Check for first usable entry on next disk */
1895 if (List
->CurrentDisk
!= NULL
)
1897 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1898 while (Entry1
!= &List
->DiskListHead
)
1900 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1902 Entry2
= DiskEntry
->PartListHead
.Flink
;
1903 if (Entry2
!= &DiskEntry
->PartListHead
)
1905 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1907 List
->CurrentDisk
= DiskEntry
;
1908 List
->CurrentPartition
= PartEntry
;
1909 DrawPartitionList(List
);
1913 Entry1
= Entry1
->Flink
;
1921 ScrollUpPartitionList(
1924 // PDISKENTRY DiskEntry;
1925 PPARTENTRY PartEntry
;
1926 // PLIST_ENTRY Entry1;
1929 /* Check for empty disks */
1930 if (IsListEmpty(&List
->DiskListHead
))
1933 /* check for previous usable entry on current disk */
1934 if (List
->CurrentPartition
!= NULL
)
1936 Entry2
= List
->CurrentPartition
->ListEntry
.Blink
;
1937 if (Entry2
!= &List
->CurrentDisk
->PrimaryPartListHead
)
1939 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1941 List
->CurrentPartition
= PartEntry
;
1943 /* Draw partition list and return */
1944 DrawPartitionList(List
);
1950 /* check for last usable entry on previous disk */
1951 if (List
->CurrentDisk
!= NULL
)
1953 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1954 while (Entry1
!= &List
->DiskListHead
)
1956 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1958 Entry2
= DiskEntry
->PrimaryPartListHead
.Blink
;
1959 if (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1961 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1963 List
->CurrentDisk
= DiskEntry
;
1964 List
->CurrentPartition
= PartEntry
;
1966 /* Draw partition list and return */
1967 DrawPartitionList(List
);
1971 Entry1
= Entry1
->Blink
;
1981 PPARTITION_INFORMATION PartitionInfo
)
1983 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
1984 PartitionInfo
->PartitionLength
.QuadPart
== 0)
1985 // PartitionInfo->PartitionType == 0)
1994 IsSamePrimaryLayoutEntry(
1995 IN PPARTITION_INFORMATION PartitionInfo
,
1996 IN PDISKENTRY DiskEntry
,
1997 IN PPARTENTRY PartEntry
)
1999 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
2000 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
2001 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2002 // PartitionInfo->PartitionType == PartEntry->PartitionType
2012 IN PDISKENTRY DiskEntry
)
2014 PPARTITION_INFORMATION PartitionInfo
;
2015 PLIST_ENTRY ListEntry
;
2016 PPARTENTRY PartEntry
;
2018 ULONG PartitionNumber
= 1;
2020 DPRINT1("UpdateDiskLayout()\n");
2022 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2023 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2025 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2027 if (PartEntry
->IsPartitioned
== TRUE
)
2029 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2031 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2033 DPRINT1("Updating partition entry %lu\n", Index
);
2034 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2035 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2036 PartitionInfo
->HiddenSectors
= 0;
2037 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2038 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2039 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2040 PartitionInfo
->RecognizedPartition
= FALSE
;
2041 PartitionInfo
->RewritePartition
= TRUE
;
2043 PartEntry
->PartitionNumber
= PartitionNumber
;
2044 PartEntry
->PartitionIndex
= Index
;
2048 else if (!IsEmptyLayoutEntry(PartitionInfo
))
2056 ListEntry
= ListEntry
->Flink
;
2059 for (;Index
< 4; Index
++)
2061 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2063 if (!IsEmptyLayoutEntry(PartitionInfo
))
2065 DPRINT1("Wiping partition entry %lu\n", Index
);
2066 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2067 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2068 PartitionInfo
->HiddenSectors
= 0;
2069 PartitionInfo
->PartitionNumber
= 0;
2070 PartitionInfo
->PartitionType
= 0;
2071 PartitionInfo
->BootIndicator
= FALSE
;
2072 PartitionInfo
->RecognizedPartition
= FALSE
;
2073 PartitionInfo
->RewritePartition
= TRUE
;
2077 #ifdef DUMP_PARTITION_TABLE
2078 DumpPartitionTable(DiskEntry
);
2085 GetPrevUnpartitionedEntry(
2086 PDISKENTRY DiskEntry
,
2087 PPARTENTRY PartEntry
)
2089 PPARTENTRY PrevPartEntry
;
2091 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PrimaryPartListHead
)
2093 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2096 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2097 return PrevPartEntry
;
2106 GetNextUnpartitionedEntry(
2107 PDISKENTRY DiskEntry
,
2108 PPARTENTRY PartEntry
)
2110 PPARTENTRY NextPartEntry
;
2112 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PrimaryPartListHead
)
2114 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2117 if (NextPartEntry
->IsPartitioned
== FALSE
)
2118 return NextPartEntry
;
2126 CreatePrimaryPartition(
2128 ULONGLONG SectorCount
,
2131 PDISKENTRY DiskEntry
;
2132 PPARTENTRY PartEntry
;
2133 PPARTENTRY NewPartEntry
;
2135 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2138 List
->CurrentDisk
== NULL
||
2139 List
->CurrentPartition
== NULL
||
2140 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2145 DiskEntry
= List
->CurrentDisk
;
2146 PartEntry
= List
->CurrentPartition
;
2148 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2150 if (AutoCreate
== TRUE
||
2151 Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2153 DPRINT1("Convert existing partition entry\n");
2154 /* Convert current entry to 'new (unformatted)' */
2155 PartEntry
->IsPartitioned
= TRUE
;
2156 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2157 PartEntry
->FormatState
= Unformatted
;
2158 PartEntry
->AutoCreate
= AutoCreate
;
2159 PartEntry
->New
= TRUE
;
2160 PartEntry
->BootIndicator
= FALSE
; /* FIXME */
2162 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2163 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2164 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2168 DPRINT1("Add new partition entry\n");
2170 /* Insert and initialize a new partition entry */
2171 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2174 if (NewPartEntry
== NULL
)
2177 /* Insert the new entry into the list */
2178 InsertTailList(&PartEntry
->ListEntry
,
2179 &NewPartEntry
->ListEntry
);
2181 NewPartEntry
->DiskEntry
= DiskEntry
;
2183 NewPartEntry
->IsPartitioned
= TRUE
;
2184 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2185 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2186 NewPartEntry
->StartSector
.QuadPart
;
2187 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2189 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2190 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2191 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2193 NewPartEntry
->New
= TRUE
;
2194 NewPartEntry
->FormatState
= Unformatted
;
2195 NewPartEntry
->BootIndicator
= FALSE
; /* FIXME */
2197 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2198 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2201 UpdateDiskLayout(DiskEntry
);
2203 DiskEntry
->Dirty
= TRUE
;
2205 UpdatePartitionNumbers(DiskEntry
);
2207 AssignDriveLetters(List
);
2212 CreateExtendedPartition(
2214 ULONGLONG SectorCount
)
2216 PDISKENTRY DiskEntry
;
2217 PPARTENTRY PartEntry
;
2218 PPARTENTRY NewPartEntry
;
2220 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2223 List
->CurrentDisk
== NULL
||
2224 List
->CurrentPartition
== NULL
||
2225 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2230 DiskEntry
= List
->CurrentDisk
;
2231 PartEntry
= List
->CurrentPartition
;
2233 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2235 if (Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2237 DPRINT1("Convert existing partition entry\n");
2238 /* Convert current entry to 'new (unformatted)' */
2239 PartEntry
->IsPartitioned
= TRUE
;
2240 // PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
2241 PartEntry
->FormatState
= Formatted
;
2242 PartEntry
->AutoCreate
= FALSE
;
2243 PartEntry
->New
= FALSE
;
2244 PartEntry
->BootIndicator
= FALSE
; /* FIXME */
2246 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2247 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2248 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2252 DPRINT1("Add new partition entry\n");
2254 /* Insert and initialize a new partition entry */
2255 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2258 if (NewPartEntry
== NULL
)
2261 /* Insert the new entry into the list */
2262 InsertTailList(&PartEntry
->ListEntry
,
2263 &NewPartEntry
->ListEntry
);
2265 NewPartEntry
->DiskEntry
= DiskEntry
;
2267 NewPartEntry
->IsPartitioned
= TRUE
;
2268 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2269 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2270 NewPartEntry
->StartSector
.QuadPart
;
2272 // NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
2274 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2275 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2276 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2278 NewPartEntry
->New
= FALSE
;
2279 NewPartEntry
->FormatState
= Formatted
;
2280 NewPartEntry
->BootIndicator
= FALSE
; /* FIXME */
2282 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2283 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2286 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2288 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2289 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2293 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2294 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2297 UpdateDiskLayout(DiskEntry
);
2299 DiskEntry
->Dirty
= TRUE
;
2301 UpdatePartitionNumbers(DiskEntry
);
2303 AssignDriveLetters(List
);
2308 DeleteCurrentPartition(
2311 PDISKENTRY DiskEntry
;
2312 PPARTENTRY PartEntry
;
2313 PPARTENTRY PrevPartEntry
;
2314 PPARTENTRY NextPartEntry
;
2317 List
->CurrentDisk
== NULL
||
2318 List
->CurrentPartition
== NULL
||
2319 List
->CurrentPartition
->IsPartitioned
== FALSE
)
2324 DiskEntry
= List
->CurrentDisk
;
2325 PartEntry
= List
->CurrentPartition
;
2327 /* Adjust unpartitioned disk space entries */
2329 /* Get pointer to previous and next unpartitioned entries */
2330 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
,
2333 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
,
2336 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2338 /* Merge previous, current and next unpartitioned entry */
2340 /* Adjust the previous entries length */
2341 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
2343 /* Remove the current entry */
2344 RemoveEntryList(&PartEntry
->ListEntry
);
2345 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2347 /* Remove the next entry */
2348 RemoveEntryList (&NextPartEntry
->ListEntry
);
2349 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
2351 /* Update current partition */
2352 List
->CurrentPartition
= PrevPartEntry
;
2354 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2356 /* Merge current and previous unpartitioned entry */
2358 /* Adjust the previous entries length */
2359 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2361 /* Remove the current entry */
2362 RemoveEntryList(&PartEntry
->ListEntry
);
2363 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2365 /* Update current partition */
2366 List
->CurrentPartition
= PrevPartEntry
;
2368 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2370 /* Merge current and next unpartitioned entry */
2372 /* Adjust the next entries offset and length */
2373 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2374 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2376 /* Remove the current entry */
2377 RemoveEntryList(&PartEntry
->ListEntry
);
2378 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2380 /* Update current partition */
2381 List
->CurrentPartition
= NextPartEntry
;
2385 /* Nothing to merge but change current entry */
2386 PartEntry
->IsPartitioned
= FALSE
;
2387 PartEntry
->FormatState
= Unformatted
;
2388 PartEntry
->DriveLetter
= 0;
2391 UpdateDiskLayout(DiskEntry
);
2393 DiskEntry
->Dirty
= TRUE
;
2395 UpdatePartitionNumbers(DiskEntry
);
2397 AssignDriveLetters(List
);
2402 CheckActiveBootPartition(
2405 PDISKENTRY DiskEntry
;
2406 PPARTENTRY PartEntry
;
2407 PLIST_ENTRY ListEntry
;
2409 /* Check for empty disk list */
2410 if (IsListEmpty (&List
->DiskListHead
))
2412 List
->ActiveBootDisk
= NULL
;
2413 List
->ActiveBootPartition
= NULL
;
2418 if (List
->ActiveBootDisk
!= NULL
&&
2419 List
->ActiveBootPartition
!= NULL
)
2421 /* We already have an active boot partition */
2426 /* Choose the currently selected disk */
2427 DiskEntry
= List
->CurrentDisk
;
2429 /* Check for empty partition list */
2430 if (IsListEmpty (&DiskEntry
->PrimaryPartListHead
))
2432 List
->ActiveBootDisk
= NULL
;
2433 List
->ActiveBootPartition
= NULL
;
2437 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
2441 /* Set active boot partition */
2442 if ((DiskEntry
->NewDisk
== TRUE
) ||
2443 (PartEntry
->BootIndicator
== FALSE
))
2445 PartEntry
->BootIndicator
= TRUE
;
2446 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].BootIndicator
= TRUE
;
2447 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
2448 DiskEntry
->Dirty
= TRUE
;
2450 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2451 List
->ActiveBootDisk
= DiskEntry
;
2452 List
->ActiveBootPartition
= PartEntry
;
2457 /* Disk is not new, scan all partitions to find a bootable one */
2458 List
->ActiveBootDisk
= NULL
;
2459 List
->ActiveBootPartition
= NULL
;
2461 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2462 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2464 PartEntry
= CONTAINING_RECORD(ListEntry
,
2468 /* Check if it is partitioned */
2469 if (PartEntry
->IsPartitioned
)
2471 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2472 PartEntry
->BootIndicator
)
2474 /* Yes, we found it */
2475 List
->ActiveBootDisk
= DiskEntry
;
2476 List
->ActiveBootPartition
= PartEntry
;
2478 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2479 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
);
2484 /* Go to the next one */
2485 ListEntry
= ListEntry
->Flink
;
2491 CheckForLinuxFdiskPartitions(
2495 PDISKENTRY DiskEntry
;
2496 PPARTENTRY PartEntry
;
2499 ULONG PartitionCount
;
2502 Entry1
= List
->DiskListHead
.Flink
;
2503 while (Entry1
!= &List
->DiskListHead
)
2505 DiskEntry
= CONTAINING_RECORD(Entry1
,
2509 Entry2
= DiskEntry
->PartListHead
.Flink
;
2510 while (Entry2
!= &DiskEntry
->PartListHead
)
2512 PartEntry
= CONTAINING_RECORD(Entry2
,
2516 if (PartEntry
->Unpartitioned
== FALSE
)
2520 for (i
= 0; i
< 4; i
++)
2522 if (!IsContainerPartition(PartEntry
->PartInfo
[i
].PartitionType
) &&
2523 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2529 if (PartitionCount
> 1)
2535 Entry2
= Entry2
->Flink
;
2538 Entry1
= Entry1
->Flink
;
2550 IN PDISKENTRY DiskEntry
)
2552 WCHAR DstPath
[MAX_PATH
];
2553 OBJECT_ATTRIBUTES ObjectAttributes
;
2554 IO_STATUS_BLOCK Iosb
;
2555 UNICODE_STRING Name
;
2557 HANDLE FileHandle
= NULL
;
2560 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
2563 L
"\\Device\\Harddisk%d\\Partition0",
2564 DiskEntry
->DiskNumber
);
2565 RtlInitUnicodeString(&Name
,
2567 InitializeObjectAttributes(&ObjectAttributes
,
2573 Status
= NtOpenFile(&FileHandle
,
2574 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
2578 FILE_SYNCHRONOUS_IO_NONALERT
);
2579 if (!NT_SUCCESS(Status
))
2581 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
2585 #ifdef DUMP_PARTITION_TABLE
2586 DumpPartitionTable(DiskEntry
);
2589 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2590 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
2591 Status
= NtDeviceIoControlFile(FileHandle
,
2596 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2597 DiskEntry
->LayoutBuffer
,
2601 if (!NT_SUCCESS(Status
))
2603 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
2606 if (FileHandle
!= NULL
)
2607 NtClose(FileHandle
);
2614 WritePartitionsToDisk(
2618 PDISKENTRY DiskEntry
;
2623 Entry
= List
->DiskListHead
.Flink
;
2624 while (Entry
!= &List
->DiskListHead
)
2626 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
2628 if (DiskEntry
->Dirty
== TRUE
)
2630 WritePartitons(List
, DiskEntry
);
2633 Entry
= Entry
->Flink
;
2641 SetMountedDeviceValues(
2644 PLIST_ENTRY Entry1
, Entry2
;
2645 PDISKENTRY DiskEntry
;
2646 PPARTENTRY PartEntry
;
2647 LARGE_INTEGER StartingOffset
;
2654 Entry1
= List
->DiskListHead
.Flink
;
2655 while (Entry1
!= &List
->DiskListHead
)
2657 DiskEntry
= CONTAINING_RECORD(Entry1
,
2661 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
2662 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
2664 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2665 if (PartEntry
->IsPartitioned
)
2667 if (PartEntry
->DriveLetter
)
2669 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2670 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
2671 DiskEntry
->LayoutBuffer
->Signature
,
2679 Entry2
= Entry2
->Flink
;
2682 Entry1
= Entry1
->Flink
;
2691 IsLastPrimaryPartiton(
2692 IN PPARTENTRY PartEntry
)
2694 return (PartEntry
->ListEntry
.Flink
== &PartEntry
->DiskEntry
->PrimaryPartListHead
);
2700 IsPreviousPartitionExtended(
2701 IN PPARTENTRY PartEntry
,
2702 IN PDISKENTRY DiskEntry
)
2704 PPARTENTRY PrevPartEntry
;
2707 Entry
= PartEntry
->ListEntry
.Blink
;
2709 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
2711 PrevPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2713 if (IsContainerPartition(PrevPartEntry
->PartitionType
))
2716 Entry
= Entry
->Blink
;
2726 GetPrimaryPartitionCount(
2727 IN PDISKENTRY DiskEntry
)
2730 PPARTENTRY PartEntry
;
2733 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2734 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
2736 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2737 if (PartEntry
->IsPartitioned
== TRUE
)
2740 Entry
= Entry
->Flink
;
2749 GetExtendedPartitionCount(
2750 IN PDISKENTRY DiskEntry
)
2753 PPARTENTRY PartEntry
;
2756 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2757 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
2759 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2760 if (PartEntry
->IsPartitioned
== TRUE
&&
2761 IsContainerPartition(PartEntry
->PartitionType
))
2764 Entry
= Entry
->Flink
;
2772 PrimaryPartitionCreationChecks(
2775 PDISKENTRY DiskEntry
;
2776 PPARTENTRY PartEntry
;
2778 DiskEntry
= List
->CurrentDisk
;
2779 PartEntry
= List
->CurrentPartition
;
2781 /* Fail if partition is already in use */
2782 if (PartEntry
->IsPartitioned
== TRUE
)
2783 return ERROR_NEW_PARTITION
;
2785 /* Fail if there are more than 4 partitions in the list */
2786 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
2787 return ERROR_PARTITION_TABLE_FULL
;
2789 /* FIXME: Fail if this partiton is located behind an extended partition */
2790 if (IsPreviousPartitionExtended(PartEntry
, DiskEntry
))
2791 return ERROR_NOT_BEHIND_EXTENDED
;
2793 return ERROR_SUCCESS
;
2798 ExtendedPartitionCreationChecks(
2801 PDISKENTRY DiskEntry
;
2802 PPARTENTRY PartEntry
;
2804 DiskEntry
= List
->CurrentDisk
;
2805 PartEntry
= List
->CurrentPartition
;
2807 /* Fail if partition is already in use */
2808 if (PartEntry
->IsPartitioned
== TRUE
)
2809 return ERROR_NEW_PARTITION
;
2811 /* Fail if there are more than 4 partitions in the list */
2812 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
2813 return ERROR_PARTITION_TABLE_FULL
;
2815 /* Fail if there is another extended partition in the list */
2816 if (GetExtendedPartitionCount(DiskEntry
) != 0)
2817 return ERROR_ONLY_ONE_EXTENDED
;
2819 /* Fail if the partition is not the last list entry */
2820 if (!IsLastPrimaryPartiton(PartEntry
))
2821 return ERROR_EXTENDED_NOT_LAST
;
2823 return ERROR_SUCCESS
;