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
;
48 DbgPrint("Index Start Length Hidden Nr Type Boot RW\n");
49 DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
51 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
53 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
54 DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n",
56 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
57 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
58 PartitionInfo
->HiddenSectors
,
59 PartitionInfo
->PartitionNumber
,
60 PartitionInfo
->PartitionType
,
61 PartitionInfo
->BootIndicator
? '*': ' ',
62 PartitionInfo
->RewritePartition
? 'Y': 'N');
77 Temp
= Value
/ Alignment
;
79 return Temp
* Alignment
;
85 IN ULONGLONG Dividend
,
88 return (Dividend
+ Divisor
/ 2) / Divisor
;
97 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
101 RtlInitUnicodeString(&DiskEntry
->DriverName
,
105 L
"\\Scsi\\Scsi Port %lu",
108 RtlZeroMemory(&QueryTable
,
111 QueryTable
[0].Name
= L
"Driver";
112 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
113 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
115 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
120 if (!NT_SUCCESS(Status
))
122 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
132 PDISKENTRY DiskEntry
;
133 PPARTENTRY PartEntry
;
140 /* Assign drive letters to primary partitions */
141 Entry1
= List
->DiskListHead
.Flink
;
142 while (Entry1
!= &List
->DiskListHead
)
144 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
146 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
147 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
149 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
151 PartEntry
->DriveLetter
= 0;
153 if (PartEntry
->IsPartitioned
&&
154 !IsContainerPartition(PartEntry
->PartitionType
))
156 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
157 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
158 PartEntry
->SectorCount
.QuadPart
!= 0LL))
162 PartEntry
->DriveLetter
= Letter
;
168 Entry2
= Entry2
->Flink
;
171 Entry1
= Entry1
->Flink
;
174 /* Assign drive letters to logical drives */
175 Entry1
= List
->DiskListHead
.Flink
;
176 while (Entry1
!= &List
->DiskListHead
)
178 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
180 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
181 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
183 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
185 PartEntry
->DriveLetter
= 0;
187 if (PartEntry
->IsPartitioned
)
189 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
190 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
191 PartEntry
->SectorCount
.QuadPart
!= 0LL))
195 PartEntry
->DriveLetter
= Letter
;
201 Entry2
= Entry2
->Flink
;
204 Entry1
= Entry1
->Flink
;
211 DiskIdentifierQueryRoutine(
219 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
220 UNICODE_STRING NameU
;
222 if (ValueType
== REG_SZ
&&
223 ValueLength
== 20 * sizeof(WCHAR
))
225 NameU
.Buffer
= (PWCHAR
)ValueData
;
226 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
227 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
229 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
230 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
232 return STATUS_SUCCESS
;
235 return STATUS_UNSUCCESSFUL
;
241 DiskConfigurationDataQueryRoutine(
249 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
250 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
251 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
254 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
255 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
256 return STATUS_UNSUCCESSFUL
;
258 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
260 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
262 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
263 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
264 return STATUS_UNSUCCESSFUL
;
267 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
269 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
270 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
273 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
274 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
276 return STATUS_SUCCESS
;
279 return STATUS_UNSUCCESSFUL
;
285 SystemConfigurationDataQueryRoutine(
293 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
294 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
297 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
298 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
299 return STATUS_UNSUCCESSFUL
;
301 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
303 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
305 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
306 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
307 return STATUS_UNSUCCESSFUL
;
310 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
312 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
313 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
316 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
317 if (*Int13Drives
== NULL
)
318 return STATUS_NO_MEMORY
;
321 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
322 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
323 return STATUS_SUCCESS
;
326 return STATUS_UNSUCCESSFUL
;
330 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
333 EnumerateBiosDiskEntries(
336 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
341 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
342 PBIOSDISKENTRY BiosDiskEntry
;
344 memset(QueryTable
, 0, sizeof(QueryTable
));
346 QueryTable
[1].Name
= L
"Configuration Data";
347 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
349 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
350 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
354 if (!NT_SUCCESS(Status
))
356 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
363 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
364 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
369 if (!NT_SUCCESS(Status
))
374 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
375 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
380 if (NT_SUCCESS(Status
))
384 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
385 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
390 if (!NT_SUCCESS(Status
))
392 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
396 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
397 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
402 if (NT_SUCCESS(Status
))
404 QueryTable
[0].Name
= L
"Identifier";
405 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
406 QueryTable
[1].Name
= L
"Configuration Data";
407 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
412 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
413 if (BiosDiskEntry
== NULL
)
418 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
419 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
422 (PVOID
)BiosDiskEntry
,
424 if (!NT_SUCCESS(Status
))
426 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
430 BiosDiskEntry
->DiskNumber
= DiskCount
;
431 BiosDiskEntry
->Recognized
= FALSE
;
433 if (DiskCount
< Int13Drives
[0].NumberDrives
)
435 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
439 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
442 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
444 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
445 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
446 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
447 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
448 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
449 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
450 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
451 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
452 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
453 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
454 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
460 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
468 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
476 PDISKENTRY DiskEntry
,
477 ULONG PartitionIndex
,
478 BOOLEAN LogicalPartition
)
480 PPARTITION_INFORMATION PartitionInfo
;
481 PPARTENTRY PartEntry
;
483 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[PartitionIndex
];
484 if (PartitionInfo
->PartitionType
== 0 ||
485 (LogicalPartition
== TRUE
&& IsContainerPartition(PartitionInfo
->PartitionType
)))
488 PartEntry
= RtlAllocateHeap(ProcessHeap
,
491 if (PartEntry
== NULL
)
496 PartEntry
->DiskEntry
= DiskEntry
;
498 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
499 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
501 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
502 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
503 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
505 PartEntry
->LogicalPartition
= LogicalPartition
;
506 PartEntry
->IsPartitioned
= TRUE
;
507 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
508 PartEntry
->PartitionIndex
= PartitionIndex
;
510 if (IsContainerPartition(PartEntry
->PartitionType
))
512 PartEntry
->FormatState
= Unformatted
;
514 if (LogicalPartition
== FALSE
&& DiskEntry
->ExtendedPartition
== NULL
)
515 DiskEntry
->ExtendedPartition
= PartEntry
;
517 else if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
518 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
519 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
520 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
521 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
522 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
525 if (CheckFatFormat())
527 PartEntry
->FormatState
= Preformatted
;
531 PartEntry
->FormatState
= Unformatted
;
534 PartEntry
->FormatState
= Preformatted
;
536 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
539 if (CheckExt2Format())
541 PartEntry
->FormatState
= Preformatted
;
545 PartEntry
->FormatState
= Unformatted
;
548 PartEntry
->FormatState
= Preformatted
;
550 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
553 if (CheckNtfsFormat())
555 PartEntry
->FormatState
= Preformatted
;
557 else if (CheckHpfsFormat())
559 PartEntry
->FormatState
= Preformatted
;
563 PartEntry
->FormatState
= Unformatted
;
566 PartEntry
->FormatState
= Preformatted
;
570 PartEntry
->FormatState
= UnknownFormat
;
573 if (LogicalPartition
)
574 InsertTailList(&DiskEntry
->LogicalPartListHead
,
575 &PartEntry
->ListEntry
);
577 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
578 &PartEntry
->ListEntry
);
584 ScanForUnpartitionedDiskSpace(
585 PDISKENTRY DiskEntry
)
587 ULONGLONG LastStartSector
;
588 ULONGLONG LastSectorCount
;
589 ULONGLONG LastUnusedSectorCount
;
590 PPARTENTRY PartEntry
;
591 PPARTENTRY NewPartEntry
;
594 DPRINT("ScanForUnpartitionedDiskSpace()\n");
596 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
598 DPRINT1("No primary partition!\n");
600 /* Create a partition table that represents the empty disk */
601 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
604 if (NewPartEntry
== NULL
)
607 NewPartEntry
->DiskEntry
= DiskEntry
;
609 NewPartEntry
->IsPartitioned
= FALSE
;
610 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorAlignment
;
611 NewPartEntry
->SectorCount
.QuadPart
= Align(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
612 NewPartEntry
->StartSector
.QuadPart
;
614 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
615 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
616 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
618 NewPartEntry
->FormatState
= Unformatted
;
620 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
621 &NewPartEntry
->ListEntry
);
626 /* Start partition at head 1, cylinder 0 */
627 LastStartSector
= DiskEntry
->SectorAlignment
;
628 LastSectorCount
= 0ULL;
629 LastUnusedSectorCount
= 0ULL;
631 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
632 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
634 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
636 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
637 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
639 LastUnusedSectorCount
=
640 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
642 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
643 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
645 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
647 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
650 if (NewPartEntry
== NULL
)
653 NewPartEntry
->DiskEntry
= DiskEntry
;
655 NewPartEntry
->IsPartitioned
= FALSE
;
656 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
657 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
658 NewPartEntry
->StartSector
.QuadPart
;
660 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
661 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
662 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
664 NewPartEntry
->FormatState
= Unformatted
;
666 /* Insert the table into the list */
667 InsertTailList(&PartEntry
->ListEntry
,
668 &NewPartEntry
->ListEntry
);
671 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
672 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
675 Entry
= Entry
->Flink
;
678 /* Check for trailing unpartitioned disk space */
679 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
681 LastUnusedSectorCount
= Align(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
683 if (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 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
701 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
702 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
704 NewPartEntry
->FormatState
= Unformatted
;
706 /* Append the table to the list */
707 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
708 &NewPartEntry
->ListEntry
);
712 if (DiskEntry
->ExtendedPartition
!= NULL
)
714 if (IsListEmpty(&DiskEntry
->LogicalPartListHead
))
716 DPRINT1("No logical partition!\n");
718 /* Create a partition table entry that represents the empty extended partition */
719 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
722 if (NewPartEntry
== NULL
)
725 NewPartEntry
->DiskEntry
= DiskEntry
;
726 NewPartEntry
->LogicalPartition
= TRUE
;
728 NewPartEntry
->IsPartitioned
= FALSE
;
729 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
730 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
732 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
733 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
734 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
736 NewPartEntry
->FormatState
= Unformatted
;
738 InsertTailList(&DiskEntry
->LogicalPartListHead
,
739 &NewPartEntry
->ListEntry
);
744 /* Start partition at head 1, cylinder 0 */
745 LastStartSector
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
746 LastSectorCount
= 0ULL;
747 LastUnusedSectorCount
= 0ULL;
749 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
750 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
752 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
754 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
755 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
757 LastUnusedSectorCount
=
758 PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
- (LastStartSector
+ LastSectorCount
);
760 if ((PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
) > (LastStartSector
+ LastSectorCount
) &&
761 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
763 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
765 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
768 if (NewPartEntry
== NULL
)
771 NewPartEntry
->DiskEntry
= DiskEntry
;
772 NewPartEntry
->LogicalPartition
= TRUE
;
774 NewPartEntry
->IsPartitioned
= FALSE
;
775 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
776 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
777 NewPartEntry
->StartSector
.QuadPart
;
779 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
780 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
781 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
783 NewPartEntry
->FormatState
= Unformatted
;
785 /* Insert the table into the list */
786 InsertTailList(&PartEntry
->ListEntry
,
787 &NewPartEntry
->ListEntry
);
790 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
791 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
794 Entry
= Entry
->Flink
;
797 /* Check for trailing unpartitioned disk space */
798 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
)
800 LastUnusedSectorCount
= Align(DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
802 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
804 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
806 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
809 if (NewPartEntry
== NULL
)
812 NewPartEntry
->DiskEntry
= DiskEntry
;
813 NewPartEntry
->LogicalPartition
= TRUE
;
815 NewPartEntry
->IsPartitioned
= FALSE
;
816 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
817 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
818 NewPartEntry
->StartSector
.QuadPart
;
820 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
821 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
822 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
824 NewPartEntry
->FormatState
= Unformatted
;
826 /* Append the table to the list */
827 InsertTailList(&DiskEntry
->LogicalPartListHead
,
828 &NewPartEntry
->ListEntry
);
833 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
841 IN PDISKENTRY DiskEntry
)
843 LARGE_INTEGER SystemTime
;
844 TIME_FIELDS TimeFields
;
846 PDISKENTRY DiskEntry2
;
849 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
853 NtQuerySystemTime(&SystemTime
);
854 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
856 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
857 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
858 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
859 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
861 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
866 /* check if the signature already exist */
868 * Check also signatures from disks, which are
869 * not visible (bootable) by the bios.
871 Entry2
= List
->DiskListHead
.Flink
;
872 while (Entry2
!= &List
->DiskListHead
)
874 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
876 if (DiskEntry
!= DiskEntry2
&&
877 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
880 Entry2
= Entry2
->Flink
;
883 if (Entry2
== &List
->DiskListHead
)
891 UpdateDiskSignatures(
895 PDISKENTRY DiskEntry
;
897 /* Print partition lines*/
898 Entry
= List
->DiskListHead
.Flink
;
899 while (Entry
!= &List
->DiskListHead
)
901 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
903 if (DiskEntry
->LayoutBuffer
&&
904 DiskEntry
->LayoutBuffer
->Signature
== 0)
906 SetDiskSignature(List
, DiskEntry
);
907 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
910 Entry
= Entry
->Flink
;
922 DISK_GEOMETRY DiskGeometry
;
923 SCSI_ADDRESS ScsiAddress
;
924 PDISKENTRY DiskEntry
;
925 IO_STATUS_BLOCK Iosb
;
927 PPARTITION_SECTOR Mbr
;
929 LARGE_INTEGER FileOffset
;
930 WCHAR Identifier
[20];
934 PLIST_ENTRY ListEntry
;
935 PBIOSDISKENTRY BiosDiskEntry
;
936 ULONG LayoutBufferSize
;
937 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
939 Status
= NtDeviceIoControlFile(FileHandle
,
944 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
948 sizeof(DISK_GEOMETRY
));
949 if (!NT_SUCCESS(Status
))
954 if (DiskGeometry
.MediaType
!= FixedMedia
&&
955 DiskGeometry
.MediaType
!= RemovableMedia
)
960 Status
= NtDeviceIoControlFile(FileHandle
,
965 IOCTL_SCSI_GET_ADDRESS
,
969 sizeof(SCSI_ADDRESS
));
970 if (!NT_SUCCESS(Status
))
975 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
977 DiskGeometry
.BytesPerSector
);
983 FileOffset
.QuadPart
= 0;
984 Status
= NtReadFile(FileHandle
,
990 DiskGeometry
.BytesPerSector
,
993 if (!NT_SUCCESS(Status
))
995 RtlFreeHeap(ProcessHeap
,
998 DPRINT1("NtReadFile failed, status=%x\n", Status
);
1001 Signature
= Mbr
->Signature
;
1003 /* Calculate the MBR checksum */
1005 Buffer
= (PULONG
)Mbr
;
1006 for (i
= 0; i
< 128; i
++)
1008 Checksum
+= Buffer
[i
];
1010 Checksum
= ~Checksum
+ 1;
1012 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
1013 DPRINT("Identifier: %S\n", Identifier
);
1015 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
1018 if (DiskEntry
== NULL
)
1023 // DiskEntry->Checksum = Checksum;
1024 // DiskEntry->Signature = Signature;
1025 DiskEntry
->BiosFound
= FALSE
;
1027 /* Check if this disk has a valid MBR */
1028 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
1029 DiskEntry
->NoMbr
= TRUE
;
1031 DiskEntry
->NoMbr
= FALSE
;
1033 /* Free Mbr sector buffer */
1034 RtlFreeHeap(ProcessHeap
,
1038 ListEntry
= List
->BiosDiskListHead
.Flink
;
1039 while(ListEntry
!= &List
->BiosDiskListHead
)
1041 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
1043 * Compare the size from bios and the reported size from driver.
1044 * If we have more than one disk with a zero or with the same signatur
1045 * we must create new signatures and reboot. After the reboot,
1046 * it is possible to identify the disks.
1048 if (BiosDiskEntry
->Signature
== Signature
&&
1049 BiosDiskEntry
->Checksum
== Checksum
&&
1050 !BiosDiskEntry
->Recognized
)
1052 if (!DiskEntry
->BiosFound
)
1054 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
1055 DiskEntry
->BiosFound
= TRUE
;
1056 BiosDiskEntry
->Recognized
= TRUE
;
1062 ListEntry
= ListEntry
->Flink
;
1065 if (!DiskEntry
->BiosFound
)
1068 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1071 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
1075 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
1076 InitializeListHead(&DiskEntry
->LogicalPartListHead
);
1078 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
1079 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
1080 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
1081 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1083 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1084 DPRINT("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
1085 DPRINT("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
1086 DPRINT("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
1088 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1089 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1090 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1092 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1094 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
);
1095 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1097 DiskEntry
->DiskNumber
= DiskNumber
;
1098 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1099 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1100 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1102 GetDriverName(DiskEntry
);
1104 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1106 /* Allocate a layout buffer with 4 partition entries first */
1107 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1108 ((4 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1109 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1112 if (DiskEntry
->LayoutBuffer
== NULL
)
1114 DPRINT1("Failed to allocate the disk layout buffer!\n");
1120 DPRINT1("Buffer size: %lu\n", LayoutBufferSize
);
1121 Status
= NtDeviceIoControlFile(FileHandle
,
1126 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1129 DiskEntry
->LayoutBuffer
,
1131 if (NT_SUCCESS(Status
))
1134 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1136 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status
);
1140 LayoutBufferSize
+= 4 * sizeof(PARTITION_INFORMATION
);
1141 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
1143 DiskEntry
->LayoutBuffer
,
1145 if (NewLayoutBuffer
== NULL
)
1147 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1151 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
1154 DPRINT1("PartitionCount: %lu\n", DiskEntry
->LayoutBuffer
->PartitionCount
);
1156 #ifdef DUMP_PARTITION_TABLE
1157 DumpPartitionTable(DiskEntry
);
1160 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
!= 0 &&
1161 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionLength
.QuadPart
!= 0 &&
1162 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionType
!= 0)
1164 if ((DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
) % DiskEntry
->SectorsPerTrack
== 0)
1166 DPRINT("Use %lu Sector alignment!\n", DiskEntry
->SectorsPerTrack
);
1168 else if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
% (1024 * 1024) == 0)
1170 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1174 DPRINT1("No matching aligment found! Partiton 1 starts at %I64u\n", DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
);
1179 DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1183 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1185 DiskEntry
->NewDisk
= TRUE
;
1186 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1188 for (i
= 0; i
< 4; i
++)
1189 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1193 for (i
= 0; i
< 4; i
++)
1195 AddPartitionToDisk(DiskNumber
,
1201 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1203 AddPartitionToDisk(DiskNumber
,
1210 ScanForUnpartitionedDiskSpace(DiskEntry
);
1215 CreatePartitionList(
1222 OBJECT_ATTRIBUTES ObjectAttributes
;
1223 SYSTEM_DEVICE_INFORMATION Sdi
;
1224 IO_STATUS_BLOCK Iosb
;
1228 WCHAR Buffer
[MAX_PATH
];
1229 UNICODE_STRING Name
;
1232 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1240 List
->Right
= Right
;
1241 List
->Bottom
= Bottom
;
1246 List
->TopDisk
= (ULONG
)-1;
1247 List
->TopPartition
= (ULONG
)-1;
1249 List
->CurrentDisk
= NULL
;
1250 List
->CurrentPartition
= NULL
;
1252 List
->BootDisk
= NULL
;
1253 List
->BootPartition
= NULL
;
1255 List
->TempDisk
= NULL
;
1256 List
->TempPartition
= NULL
;
1257 List
->FormatState
= Start
;
1259 InitializeListHead(&List
->DiskListHead
);
1260 InitializeListHead(&List
->BiosDiskListHead
);
1262 EnumerateBiosDiskEntries(List
);
1264 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1266 sizeof(SYSTEM_DEVICE_INFORMATION
),
1268 if (!NT_SUCCESS(Status
))
1270 RtlFreeHeap(ProcessHeap
, 0, List
);
1274 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1277 L
"\\Device\\Harddisk%d\\Partition0",
1279 RtlInitUnicodeString(&Name
,
1282 InitializeObjectAttributes(&ObjectAttributes
,
1288 Status
= NtOpenFile(&FileHandle
,
1289 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1293 FILE_SYNCHRONOUS_IO_NONALERT
);
1294 if (NT_SUCCESS(Status
))
1296 AddDiskToList(FileHandle
,
1300 NtClose(FileHandle
);
1304 UpdateDiskSignatures(List
);
1306 AssignDriveLetters(List
);
1309 List
->TopPartition
= 0;
1311 /* Search for first usable disk and partition */
1312 if (IsListEmpty(&List
->DiskListHead
))
1314 List
->CurrentDisk
= NULL
;
1315 List
->CurrentPartition
= NULL
;
1319 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1323 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1325 List
->CurrentPartition
= 0;
1329 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1340 DestroyPartitionList(
1343 PDISKENTRY DiskEntry
;
1344 PBIOSDISKENTRY BiosDiskEntry
;
1345 PPARTENTRY PartEntry
;
1348 /* Release disk and partition info */
1349 while (!IsListEmpty(&List
->DiskListHead
))
1351 Entry
= RemoveHeadList(&List
->DiskListHead
);
1352 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1354 /* Release driver name */
1355 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1357 /* Release primary partition list */
1358 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1360 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1361 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1363 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1366 /* Release logical partition list */
1367 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
1369 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
1370 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1372 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1375 /* Release layout buffer */
1376 if (DiskEntry
->LayoutBuffer
!= NULL
)
1377 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1380 /* Release disk entry */
1381 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1384 /* release the bios disk info */
1385 while(!IsListEmpty(&List
->BiosDiskListHead
))
1387 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1388 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1390 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1393 /* Release list head */
1394 RtlFreeHeap(ProcessHeap
, 0, List
);
1408 Width
= List
->Right
- List
->Left
- 1;
1409 Height
= List
->Bottom
- List
->Top
- 2;
1411 coPos
.X
= List
->Left
+ 1;
1412 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1414 if (List
->Line
>= 0 && List
->Line
<= Height
)
1416 FillConsoleOutputAttribute(StdOutput
,
1417 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1422 FillConsoleOutputCharacterA(StdOutput
,
1437 PDISKENTRY DiskEntry
,
1438 PPARTENTRY PartEntry
)
1440 CHAR LineBuffer
[128];
1445 LARGE_INTEGER PartSize
;
1450 Width
= List
->Right
- List
->Left
- 1;
1451 Height
= List
->Bottom
- List
->Top
- 2;
1453 coPos
.X
= List
->Left
+ 1;
1454 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1456 if (PartEntry
->IsPartitioned
== FALSE
)
1458 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1460 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1462 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1463 Unit
= MUIGetString(STRING_GB
);
1467 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1469 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1470 Unit
= MUIGetString(STRING_MB
);
1474 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1475 Unit
= MUIGetString(STRING_KB
);
1479 MUIGetString(STRING_UNPSPACE
),
1480 PartEntry
->LogicalPartition
? " " : "",
1481 PartEntry
->LogicalPartition
? "" : " ",
1487 /* Determine partition type */
1489 if (PartEntry
->New
== TRUE
)
1491 PartType
= MUIGetString(STRING_UNFORMATTED
);
1493 else if (PartEntry
->IsPartitioned
== TRUE
)
1495 if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
1496 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
1497 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
1498 (PartEntry
->PartitionType
== PARTITION_XINT13
))
1502 else if ((PartEntry
->PartitionType
== PARTITION_FAT32
) ||
1503 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
1507 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
1511 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
1513 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1515 else if ((PartEntry
->PartitionType
== PARTITION_EXTENDED
) ||
1516 (PartEntry
->PartitionType
== PARTITION_XINT13_EXTENDED
))
1518 PartType
= MUIGetString(STRING_EXTENDED_PARTITION
);
1522 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1524 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1526 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1527 Unit
= MUIGetString(STRING_GB
);
1531 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1533 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1534 Unit
= MUIGetString(STRING_MB
);
1538 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1539 Unit
= MUIGetString(STRING_KB
);
1542 if (PartType
== NULL
)
1545 MUIGetString(STRING_HDDINFOUNK5
),
1546 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1547 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1548 PartEntry
->BootIndicator
? '*' : ' ',
1549 PartEntry
->LogicalPartition
? " " : "",
1550 PartEntry
->PartitionType
,
1551 PartEntry
->LogicalPartition
? "" : " ",
1558 "%c%c %c %s%-24s%s %6lu %s",
1559 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1560 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1561 PartEntry
->BootIndicator
? '*' : ' ',
1562 PartEntry
->LogicalPartition
? " " : "",
1564 PartEntry
->LogicalPartition
? "" : " ",
1570 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1571 List
->CurrentPartition
== PartEntry
) ?
1572 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1573 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1575 if (List
->Line
>= 0 && List
->Line
<= Height
)
1577 FillConsoleOutputCharacterA(StdOutput
,
1585 if (List
->Line
>= 0 && List
->Line
<= Height
)
1587 FillConsoleOutputAttribute(StdOutput
,
1595 if (List
->Line
>= 0 && List
->Line
<= Height
)
1597 WriteConsoleOutputCharacterA(StdOutput
,
1599 min(strlen(LineBuffer
), Width
),
1612 PDISKENTRY DiskEntry
)
1614 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
1615 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
1616 CHAR LineBuffer
[128];
1621 ULARGE_INTEGER DiskSize
;
1624 Width
= List
->Right
- List
->Left
- 1;
1625 Height
= List
->Bottom
- List
->Top
- 2;
1627 coPos
.X
= List
->Left
+ 1;
1628 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1630 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1631 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
1633 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
1634 Unit
= MUIGetString(STRING_GB
);
1638 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
1639 if (DiskSize
.QuadPart
== 0)
1640 DiskSize
.QuadPart
= 1;
1641 Unit
= MUIGetString(STRING_MB
);
1644 if (DiskEntry
->DriverName
.Length
> 0)
1647 MUIGetString(STRING_HDINFOPARTSELECT
),
1650 DiskEntry
->DiskNumber
,
1654 DiskEntry
->DriverName
.Buffer
);
1659 MUIGetString(STRING_HDDINFOUNK6
),
1662 DiskEntry
->DiskNumber
,
1668 if (List
->Line
>= 0 && List
->Line
<= Height
)
1670 FillConsoleOutputAttribute(StdOutput
,
1671 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1676 FillConsoleOutputCharacterA(StdOutput
,
1684 if (List
->Line
>= 0 && List
->Line
<= Height
)
1686 WriteConsoleOutputCharacterA(StdOutput
,
1688 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1695 /* Print separator line */
1696 PrintEmptyLine(List
);
1698 /* Print partition lines*/
1699 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1700 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
1702 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
1704 PrintPartitionData(List
,
1708 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
1710 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
1711 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
1713 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
1715 PrintPartitionData(List
,
1719 LogicalEntry
= LogicalEntry
->Flink
;
1723 PrimaryEntry
= PrimaryEntry
->Flink
;
1726 /* Print separator line */
1727 PrintEmptyLine(List
);
1735 PLIST_ENTRY Entry
, Entry2
;
1736 PDISKENTRY DiskEntry
;
1737 PPARTENTRY PartEntry
= NULL
;
1741 SHORT CurrentDiskLine
;
1742 SHORT CurrentPartLine
;
1744 BOOL CurrentPartLineFound
= FALSE
;
1745 BOOL CurrentDiskLineFound
= FALSE
;
1747 /* Calculate the line of the current disk and partition */
1748 CurrentDiskLine
= 0;
1749 CurrentPartLine
= 0;
1752 Entry
= List
->DiskListHead
.Flink
;
1753 while (Entry
!= &List
->DiskListHead
)
1755 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1758 if (CurrentPartLineFound
== FALSE
)
1760 CurrentPartLine
+= 2;
1763 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1764 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1766 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1767 if (PartEntry
== List
->CurrentPartition
)
1769 CurrentPartLineFound
= TRUE
;
1772 Entry2
= Entry2
->Flink
;
1773 if (CurrentPartLineFound
== FALSE
)
1781 if (DiskEntry
== List
->CurrentDisk
)
1783 CurrentDiskLineFound
= TRUE
;
1786 Entry
= Entry
->Flink
;
1787 if (Entry
!= &List
->DiskListHead
)
1789 if (CurrentDiskLineFound
== FALSE
)
1792 CurrentDiskLine
= CurrentPartLine
;
1803 /* If it possible, make the disk name visible */
1804 if (CurrentPartLine
< List
->Offset
)
1806 List
->Offset
= CurrentPartLine
;
1808 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1810 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1813 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1815 List
->Offset
= CurrentDiskLine
;
1818 /* draw upper left corner */
1819 coPos
.X
= List
->Left
;
1820 coPos
.Y
= List
->Top
;
1821 FillConsoleOutputCharacterA(StdOutput
,
1827 /* draw upper edge */
1828 coPos
.X
= List
->Left
+ 1;
1829 coPos
.Y
= List
->Top
;
1830 if (List
->Offset
== 0)
1832 FillConsoleOutputCharacterA(StdOutput
,
1834 List
->Right
- List
->Left
- 1,
1840 FillConsoleOutputCharacterA(StdOutput
,
1842 List
->Right
- List
->Left
- 5,
1845 coPos
.X
= List
->Right
- 5;
1846 WriteConsoleOutputCharacterA(StdOutput
,
1851 coPos
.X
= List
->Right
- 2;
1852 FillConsoleOutputCharacterA(StdOutput
,
1859 /* draw upper right corner */
1860 coPos
.X
= List
->Right
;
1861 coPos
.Y
= List
->Top
;
1862 FillConsoleOutputCharacterA(StdOutput
,
1868 /* draw left and right edge */
1869 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1871 coPos
.X
= List
->Left
;
1873 FillConsoleOutputCharacterA(StdOutput
,
1879 coPos
.X
= List
->Right
;
1880 FillConsoleOutputCharacterA(StdOutput
,
1887 /* draw lower left corner */
1888 coPos
.X
= List
->Left
;
1889 coPos
.Y
= List
->Bottom
;
1890 FillConsoleOutputCharacterA(StdOutput
,
1896 /* draw lower edge */
1897 coPos
.X
= List
->Left
+ 1;
1898 coPos
.Y
= List
->Bottom
;
1899 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1901 FillConsoleOutputCharacterA(StdOutput
,
1903 List
->Right
- List
->Left
- 1,
1909 FillConsoleOutputCharacterA(StdOutput
,
1911 List
->Right
- List
->Left
- 5,
1914 coPos
.X
= List
->Right
- 5;
1915 WriteConsoleOutputCharacterA(StdOutput
,
1916 "(\x19)", // "(down)"
1920 coPos
.X
= List
->Right
- 2;
1921 FillConsoleOutputCharacterA(StdOutput
,
1928 /* draw lower right corner */
1929 coPos
.X
= List
->Right
;
1930 coPos
.Y
= List
->Bottom
;
1931 FillConsoleOutputCharacterA(StdOutput
,
1937 /* print list entries */
1938 List
->Line
= - List
->Offset
;
1940 Entry
= List
->DiskListHead
.Flink
;
1941 while (Entry
!= &List
->DiskListHead
)
1943 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1945 /* Print disk entry */
1949 Entry
= Entry
->Flink
;
1958 ULONG PartitionNumber
)
1960 PDISKENTRY DiskEntry
;
1961 PPARTENTRY PartEntry
;
1965 /* Check for empty disks */
1966 if (IsListEmpty(&List
->DiskListHead
))
1969 /* Check for first usable entry on next disk */
1970 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1971 while (Entry1
!= &List
->DiskListHead
)
1973 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1975 if (DiskEntry
->DiskNumber
== DiskNumber
)
1977 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1978 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1980 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1982 if (PartEntry
->PartitionNumber
== PartitionNumber
)
1984 List
->CurrentDisk
= DiskEntry
;
1985 List
->CurrentPartition
= PartEntry
;
1986 DrawPartitionList(List
);
1990 Entry2
= Entry2
->Flink
;
1996 Entry1
= Entry1
->Flink
;
2004 ScrollDownPartitionList(
2007 PLIST_ENTRY DiskListEntry
;
2008 PLIST_ENTRY PartListEntry
;
2009 PDISKENTRY DiskEntry
;
2010 PPARTENTRY PartEntry
;
2012 /* Fail, if no disks are available */
2013 if (IsListEmpty(&List
->DiskListHead
))
2016 /* Check for next usable entry on current disk */
2017 if (List
->CurrentPartition
!= NULL
)
2019 if (List
->CurrentPartition
->LogicalPartition
)
2021 /* Logical partition */
2023 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2024 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2026 /* Next logical partition */
2027 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2029 List
->CurrentPartition
= PartEntry
;
2034 PartListEntry
= List
->CurrentDisk
->ExtendedPartition
->ListEntry
.Flink
;
2035 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2037 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2039 List
->CurrentPartition
= PartEntry
;
2046 /* Primary or extended partition */
2048 if (List
->CurrentPartition
->IsPartitioned
== TRUE
&&
2049 IsContainerPartition(List
->CurrentPartition
->PartitionType
))
2051 /* First logical partition */
2052 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Flink
;
2053 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2055 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2057 List
->CurrentPartition
= PartEntry
;
2063 /* Next primary partition */
2064 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2065 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2067 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2069 List
->CurrentPartition
= PartEntry
;
2076 /* Search for the first partition entry on the next disk */
2077 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Flink
;
2078 while (DiskListEntry
!= &List
->DiskListHead
)
2080 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2082 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2083 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2085 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2087 List
->CurrentDisk
= DiskEntry
;
2088 List
->CurrentPartition
= PartEntry
;
2092 DiskListEntry
= DiskListEntry
->Flink
;
2100 ScrollUpPartitionList(
2103 PLIST_ENTRY DiskListEntry
;
2104 PLIST_ENTRY PartListEntry
;
2105 PDISKENTRY DiskEntry
;
2106 PPARTENTRY PartEntry
;
2108 /* Fail, if no disks are available */
2109 if (IsListEmpty(&List
->DiskListHead
))
2112 /* Check for previous usable entry on current disk */
2113 if (List
->CurrentPartition
!= NULL
)
2115 if (List
->CurrentPartition
->LogicalPartition
)
2117 /* Logical partition */
2118 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2119 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2121 /* Previous logical partition */
2122 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2126 /* Extended partition*/
2127 PartEntry
= List
->CurrentDisk
->ExtendedPartition
;
2130 List
->CurrentPartition
= PartEntry
;
2135 /* Primary or extended partition */
2137 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2138 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2140 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2142 if (PartEntry
->IsPartitioned
== TRUE
&&
2143 IsContainerPartition(PartEntry
->PartitionType
))
2145 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Blink
;
2146 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2149 List
->CurrentPartition
= PartEntry
;
2156 /* Search for the last partition entry on the previous disk */
2157 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Blink
;
2158 while (DiskListEntry
!= &List
->DiskListHead
)
2160 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2162 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Blink
;
2163 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2165 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2167 if (PartEntry
->IsPartitioned
== TRUE
&&
2168 IsContainerPartition(PartEntry
->PartitionType
))
2170 PartListEntry
= DiskEntry
->LogicalPartListHead
.Blink
;
2171 if (PartListEntry
!= &DiskEntry
->LogicalPartListHead
)
2173 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2175 List
->CurrentDisk
= DiskEntry
;
2176 List
->CurrentPartition
= PartEntry
;
2182 List
->CurrentDisk
= DiskEntry
;
2183 List
->CurrentPartition
= PartEntry
;
2188 DiskListEntry
= DiskListEntry
->Blink
;
2199 PPARTITION_INFORMATION PartitionInfo
)
2201 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
2202 PartitionInfo
->PartitionLength
.QuadPart
== 0)
2203 // PartitionInfo->PartitionType == 0)
2213 IsSamePrimaryLayoutEntry(
2214 IN PPARTITION_INFORMATION PartitionInfo
,
2215 IN PDISKENTRY DiskEntry
,
2216 IN PPARTENTRY PartEntry
)
2218 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
2219 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
2220 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2221 // PartitionInfo->PartitionType == PartEntry->PartitionType
2230 GetPrimaryPartitionCount(
2231 IN PDISKENTRY DiskEntry
)
2234 PPARTENTRY PartEntry
;
2237 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2238 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
2240 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2241 if (PartEntry
->IsPartitioned
== TRUE
)
2244 Entry
= Entry
->Flink
;
2253 GetLogicalPartitionCount(
2254 PDISKENTRY DiskEntry
)
2256 PLIST_ENTRY ListEntry
;
2257 PPARTENTRY PartEntry
;
2260 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
2261 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
2263 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2264 if (PartEntry
->IsPartitioned
)
2267 ListEntry
= ListEntry
->Flink
;
2276 ReAllocateLayoutBuffer(
2277 PDISKENTRY DiskEntry
)
2279 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
2280 ULONG NewPartitionCount
;
2281 ULONG CurrentPartitionCount
= 0;
2282 ULONG LayoutBufferSize
;
2284 DPRINT1("ReAllocateLayoutBuffer()\n");
2286 NewPartitionCount
= 4 + GetLogicalPartitionCount(DiskEntry
) * 4;
2288 if (DiskEntry
->LayoutBuffer
)
2289 CurrentPartitionCount
= DiskEntry
->LayoutBuffer
->PartitionCount
;
2291 DPRINT1("CurrentPartitionCount: %lu NewPartitionCount: %lu\n",
2292 CurrentPartitionCount
, NewPartitionCount
);
2294 if (CurrentPartitionCount
== NewPartitionCount
)
2297 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2298 ((NewPartitionCount
- ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
2299 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
2301 DiskEntry
->LayoutBuffer
,
2303 if (NewLayoutBuffer
== NULL
)
2305 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize
);
2309 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
2310 DiskEntry
->LayoutBuffer
->PartitionCount
= NewPartitionCount
;
2319 IN PDISKENTRY DiskEntry
)
2321 PPARTITION_INFORMATION PartitionInfo
;
2322 PLIST_ENTRY ListEntry
;
2323 PPARTENTRY PartEntry
;
2325 ULONG PartitionNumber
= 1;
2327 DPRINT1("UpdateDiskLayout()\n");
2329 /* Resize the layout buffer if necessary */
2330 if (ReAllocateLayoutBuffer(DiskEntry
) == FALSE
)
2332 DPRINT("ReAllocateLayoutBuffer() failed.\n");
2336 /* Update the primary partition table */
2338 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2339 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2341 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2343 if (PartEntry
->IsPartitioned
== TRUE
)
2345 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2347 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2349 DPRINT1("Updating primary partition entry %lu\n", Index
);
2351 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2352 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2353 PartitionInfo
->HiddenSectors
= PartEntry
->StartSector
.LowPart
;
2354 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2355 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2356 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2357 PartitionInfo
->RecognizedPartition
= FALSE
;
2358 PartitionInfo
->RewritePartition
= TRUE
;
2361 PartEntry
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2362 PartEntry
->PartitionIndex
= Index
;
2364 if (!IsContainerPartition(PartEntry
->PartitionType
))
2370 ListEntry
= ListEntry
->Flink
;
2373 /* Update the logical partition tables */
2375 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
2376 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
2378 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2380 if (PartEntry
->IsPartitioned
)
2382 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2384 DPRINT1("Updating logical partition entry %lu\n", Index
);
2386 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2387 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2388 PartitionInfo
->HiddenSectors
= DiskEntry
->SectorAlignment
;
2389 PartitionInfo
->PartitionNumber
= PartitionNumber
;
2390 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2391 PartitionInfo
->BootIndicator
= FALSE
;
2392 PartitionInfo
->RecognizedPartition
= FALSE
;
2393 PartitionInfo
->RewritePartition
= TRUE
;
2395 PartEntry
->PartitionNumber
= PartitionNumber
;
2396 PartEntry
->PartitionIndex
= Index
;
2402 ListEntry
= ListEntry
->Flink
;
2406 for (;Index
< 4; Index
++)
2408 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2410 if (!IsEmptyLayoutEntry(PartitionInfo
))
2412 DPRINT1("Wiping partition entry %lu\n", Index
);
2414 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2415 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2416 PartitionInfo
->HiddenSectors
= 0;
2417 PartitionInfo
->PartitionNumber
= 0;
2418 PartitionInfo
->PartitionType
= 0;
2419 PartitionInfo
->BootIndicator
= FALSE
;
2420 PartitionInfo
->RecognizedPartition
= FALSE
;
2421 PartitionInfo
->RewritePartition
= TRUE
;
2426 #ifdef DUMP_PARTITION_TABLE
2427 DumpPartitionTable(DiskEntry
);
2434 GetPrevUnpartitionedEntry(
2435 PDISKENTRY DiskEntry
,
2436 PPARTENTRY PartEntry
)
2438 PPARTENTRY PrevPartEntry
;
2439 PLIST_ENTRY ListHead
;
2441 if (PartEntry
->LogicalPartition
)
2442 ListHead
= &DiskEntry
->LogicalPartListHead
;
2444 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2446 if (PartEntry
->ListEntry
.Blink
!= ListHead
)
2448 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2451 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2452 return PrevPartEntry
;
2461 GetNextUnpartitionedEntry(
2462 PDISKENTRY DiskEntry
,
2463 PPARTENTRY PartEntry
)
2465 PPARTENTRY NextPartEntry
;
2466 PLIST_ENTRY ListHead
;
2468 if (PartEntry
->LogicalPartition
)
2469 ListHead
= &DiskEntry
->LogicalPartListHead
;
2471 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2473 if (PartEntry
->ListEntry
.Flink
!= ListHead
)
2475 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2478 if (NextPartEntry
->IsPartitioned
== FALSE
)
2479 return NextPartEntry
;
2487 CreatePrimaryPartition(
2489 ULONGLONG SectorCount
,
2492 PDISKENTRY DiskEntry
;
2493 PPARTENTRY PartEntry
;
2494 PPARTENTRY NewPartEntry
;
2496 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2499 List
->CurrentDisk
== NULL
||
2500 List
->CurrentPartition
== NULL
||
2501 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2506 DiskEntry
= List
->CurrentDisk
;
2507 PartEntry
= List
->CurrentPartition
;
2509 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2511 if (AutoCreate
== TRUE
||
2512 Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2514 DPRINT1("Convert existing partition entry\n");
2516 /* Convert current entry to 'new (unformatted)' */
2517 PartEntry
->IsPartitioned
= TRUE
;
2518 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2519 PartEntry
->FormatState
= Unformatted
;
2520 PartEntry
->AutoCreate
= AutoCreate
;
2521 PartEntry
->New
= TRUE
;
2522 PartEntry
->BootIndicator
= FALSE
;
2524 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2525 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2526 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2530 DPRINT1("Add new partition entry\n");
2532 /* Insert and initialize a new partition entry */
2533 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2536 if (NewPartEntry
== NULL
)
2539 /* Insert the new entry into the list */
2540 InsertTailList(&PartEntry
->ListEntry
,
2541 &NewPartEntry
->ListEntry
);
2543 NewPartEntry
->DiskEntry
= DiskEntry
;
2545 NewPartEntry
->IsPartitioned
= TRUE
;
2546 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2547 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2548 NewPartEntry
->StartSector
.QuadPart
;
2549 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2551 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2552 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2553 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2555 NewPartEntry
->New
= TRUE
;
2556 NewPartEntry
->FormatState
= Unformatted
;
2557 NewPartEntry
->BootIndicator
= FALSE
;
2559 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2560 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2563 UpdateDiskLayout(DiskEntry
);
2565 DiskEntry
->Dirty
= TRUE
;
2567 AssignDriveLetters(List
);
2573 AddLogicalDiskSpace(
2574 PDISKENTRY DiskEntry
)
2576 PPARTENTRY NewPartEntry
;
2578 DPRINT1("AddLogicalDiskSpace()\n");
2580 /* Create a partition table entry that represents the empty space in the container partition */
2581 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2584 if (NewPartEntry
== NULL
)
2587 NewPartEntry
->DiskEntry
= DiskEntry
;
2588 NewPartEntry
->LogicalPartition
= TRUE
;
2590 NewPartEntry
->IsPartitioned
= FALSE
;
2591 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
2592 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
2594 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2595 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2596 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2598 NewPartEntry
->FormatState
= Unformatted
;
2600 InsertTailList(&DiskEntry
->LogicalPartListHead
,
2601 &NewPartEntry
->ListEntry
);
2606 CreateExtendedPartition(
2608 ULONGLONG SectorCount
)
2610 PDISKENTRY DiskEntry
;
2611 PPARTENTRY PartEntry
;
2612 PPARTENTRY NewPartEntry
;
2614 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount
);
2617 List
->CurrentDisk
== NULL
||
2618 List
->CurrentPartition
== NULL
||
2619 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2624 DiskEntry
= List
->CurrentDisk
;
2625 PartEntry
= List
->CurrentPartition
;
2627 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2629 if (Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2631 DPRINT1("Convert existing partition entry\n");
2633 /* Convert current entry to 'new (unformatted)' */
2634 PartEntry
->IsPartitioned
= TRUE
;
2635 PartEntry
->FormatState
= Formatted
;
2636 PartEntry
->AutoCreate
= FALSE
;
2637 PartEntry
->New
= FALSE
;
2638 PartEntry
->BootIndicator
= FALSE
;
2640 if (PartEntry
->StartSector
.QuadPart
< 1450560)
2642 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2643 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
2647 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2648 PartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2651 DiskEntry
->ExtendedPartition
= PartEntry
;
2653 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2654 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2655 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2659 DPRINT1("Add new partition entry\n");
2661 /* Insert and initialize a new partition entry */
2662 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2665 if (NewPartEntry
== NULL
)
2668 /* Insert the new entry into the list */
2669 InsertTailList(&PartEntry
->ListEntry
,
2670 &NewPartEntry
->ListEntry
);
2672 NewPartEntry
->DiskEntry
= DiskEntry
;
2674 NewPartEntry
->IsPartitioned
= TRUE
;
2675 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2676 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2677 NewPartEntry
->StartSector
.QuadPart
;
2679 NewPartEntry
->New
= FALSE
;
2680 NewPartEntry
->FormatState
= Formatted
;
2681 NewPartEntry
->BootIndicator
= FALSE
;
2683 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2685 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2686 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2690 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2691 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2694 DiskEntry
->ExtendedPartition
= NewPartEntry
;
2696 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2697 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2699 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2700 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2701 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2704 AddLogicalDiskSpace(DiskEntry
);
2706 UpdateDiskLayout(DiskEntry
);
2708 DiskEntry
->Dirty
= TRUE
;
2710 AssignDriveLetters(List
);
2715 CreateLogicalPartition(
2717 ULONGLONG SectorCount
)
2719 PDISKENTRY DiskEntry
;
2720 PPARTENTRY PartEntry
;
2721 PPARTENTRY NewPartEntry
;
2723 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount
);
2726 List
->CurrentDisk
== NULL
||
2727 List
->CurrentPartition
== NULL
||
2728 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2733 DiskEntry
= List
->CurrentDisk
;
2734 PartEntry
= List
->CurrentPartition
;
2736 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2738 if (Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2740 DPRINT1("Convert existing partition entry\n");
2742 /* Convert current entry to 'new (unformatted)' */
2743 PartEntry
->IsPartitioned
= TRUE
;
2744 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2745 PartEntry
->FormatState
= Unformatted
;
2746 PartEntry
->AutoCreate
= FALSE
;
2747 PartEntry
->New
= TRUE
;
2748 PartEntry
->BootIndicator
= FALSE
;
2749 PartEntry
->LogicalPartition
= TRUE
;
2751 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2752 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2753 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2757 DPRINT1("Add new partition entry\n");
2759 /* Insert and initialize a new partition entry */
2760 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2763 if (NewPartEntry
== NULL
)
2766 /* Insert the new entry into the list */
2767 InsertTailList(&PartEntry
->ListEntry
,
2768 &NewPartEntry
->ListEntry
);
2770 NewPartEntry
->DiskEntry
= DiskEntry
;
2772 NewPartEntry
->IsPartitioned
= TRUE
;
2773 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2774 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2775 NewPartEntry
->StartSector
.QuadPart
;
2776 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2778 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2779 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2780 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2782 NewPartEntry
->New
= TRUE
;
2783 NewPartEntry
->FormatState
= Unformatted
;
2784 NewPartEntry
->BootIndicator
= FALSE
;
2785 NewPartEntry
->LogicalPartition
= TRUE
;
2787 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2788 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2791 UpdateDiskLayout(DiskEntry
);
2793 DiskEntry
->Dirty
= TRUE
;
2795 AssignDriveLetters(List
);
2800 DeleteCurrentPartition(
2803 PDISKENTRY DiskEntry
;
2804 PPARTENTRY PartEntry
;
2805 PPARTENTRY PrevPartEntry
;
2806 PPARTENTRY NextPartEntry
;
2807 PPARTENTRY LogicalPartEntry
;
2811 List
->CurrentDisk
== NULL
||
2812 List
->CurrentPartition
== NULL
||
2813 List
->CurrentPartition
->IsPartitioned
== FALSE
)
2818 DiskEntry
= List
->CurrentDisk
;
2819 PartEntry
= List
->CurrentPartition
;
2821 /* Delete all logical partiton entries if an extended partition will be deleted */
2822 if (DiskEntry
->ExtendedPartition
== PartEntry
)
2824 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
2826 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
2827 LogicalPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2829 RtlFreeHeap(ProcessHeap
, 0, LogicalPartEntry
);
2832 DiskEntry
->ExtendedPartition
= NULL
;
2835 /* Adjust unpartitioned disk space entries */
2837 /* Get pointer to previous and next unpartitioned entries */
2838 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
,
2841 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
,
2844 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2846 /* Merge previous, current and next unpartitioned entry */
2848 /* Adjust the previous entries length */
2849 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
2851 /* Remove the current entry */
2852 RemoveEntryList(&PartEntry
->ListEntry
);
2853 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2855 /* Remove the next entry */
2856 RemoveEntryList (&NextPartEntry
->ListEntry
);
2857 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
2859 /* Update current partition */
2860 List
->CurrentPartition
= PrevPartEntry
;
2862 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2864 /* Merge current and previous unpartitioned entry */
2866 /* Adjust the previous entries length */
2867 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2869 /* Remove the current entry */
2870 RemoveEntryList(&PartEntry
->ListEntry
);
2871 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2873 /* Update current partition */
2874 List
->CurrentPartition
= PrevPartEntry
;
2876 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2878 /* Merge current and next unpartitioned entry */
2880 /* Adjust the next entries offset and length */
2881 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2882 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2884 /* Remove the current entry */
2885 RemoveEntryList(&PartEntry
->ListEntry
);
2886 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2888 /* Update current partition */
2889 List
->CurrentPartition
= NextPartEntry
;
2893 /* Nothing to merge but change current entry */
2894 PartEntry
->IsPartitioned
= FALSE
;
2895 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2896 PartEntry
->FormatState
= Unformatted
;
2897 PartEntry
->DriveLetter
= 0;
2900 UpdateDiskLayout(DiskEntry
);
2902 DiskEntry
->Dirty
= TRUE
;
2904 AssignDriveLetters(List
);
2909 CheckActiveBootPartition(
2912 PDISKENTRY DiskEntry
;
2913 PPARTENTRY PartEntry
;
2914 PLIST_ENTRY ListEntry
;
2916 /* Check for empty disk list */
2917 if (IsListEmpty (&List
->DiskListHead
))
2919 List
->BootDisk
= NULL
;
2920 List
->BootPartition
= NULL
;
2925 if (List
->BootDisk
!= NULL
&&
2926 List
->BootPartition
!= NULL
)
2928 /* We already have an active boot partition */
2933 /* Choose the currently selected disk */
2934 DiskEntry
= List
->CurrentDisk
;
2936 /* Check for empty partition list */
2937 if (IsListEmpty (&DiskEntry
->PrimaryPartListHead
))
2939 List
->BootDisk
= NULL
;
2940 List
->BootPartition
= NULL
;
2944 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
2948 /* Set active boot partition */
2949 if ((DiskEntry
->NewDisk
== TRUE
) ||
2950 (PartEntry
->BootIndicator
== FALSE
))
2952 PartEntry
->BootIndicator
= TRUE
;
2953 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].BootIndicator
= TRUE
;
2954 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
2955 DiskEntry
->Dirty
= TRUE
;
2957 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2958 List
->BootDisk
= DiskEntry
;
2959 List
->BootPartition
= PartEntry
;
2964 /* Disk is not new, scan all partitions to find a bootable one */
2965 List
->BootDisk
= NULL
;
2966 List
->BootPartition
= NULL
;
2968 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2969 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2971 PartEntry
= CONTAINING_RECORD(ListEntry
,
2975 /* Check if it is partitioned */
2976 if (PartEntry
->IsPartitioned
)
2978 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2979 PartEntry
->BootIndicator
)
2981 /* Yes, we found it */
2982 List
->BootDisk
= DiskEntry
;
2983 List
->BootPartition
= PartEntry
;
2985 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2986 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
);
2991 /* Go to the next one */
2992 ListEntry
= ListEntry
->Flink
;
3001 IN PDISKENTRY DiskEntry
)
3003 WCHAR DstPath
[MAX_PATH
];
3004 OBJECT_ATTRIBUTES ObjectAttributes
;
3005 IO_STATUS_BLOCK Iosb
;
3006 UNICODE_STRING Name
;
3008 HANDLE FileHandle
= NULL
;
3011 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
3014 L
"\\Device\\Harddisk%d\\Partition0",
3015 DiskEntry
->DiskNumber
);
3016 RtlInitUnicodeString(&Name
,
3018 InitializeObjectAttributes(&ObjectAttributes
,
3024 Status
= NtOpenFile(&FileHandle
,
3025 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
3029 FILE_SYNCHRONOUS_IO_NONALERT
);
3030 if (!NT_SUCCESS(Status
))
3032 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
3036 #ifdef DUMP_PARTITION_TABLE
3037 DumpPartitionTable(DiskEntry
);
3040 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
3041 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
3042 Status
= NtDeviceIoControlFile(FileHandle
,
3047 IOCTL_DISK_SET_DRIVE_LAYOUT
,
3048 DiskEntry
->LayoutBuffer
,
3052 if (!NT_SUCCESS(Status
))
3054 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
3057 if (FileHandle
!= NULL
)
3058 NtClose(FileHandle
);
3065 WritePartitionsToDisk(
3069 PDISKENTRY DiskEntry
;
3074 Entry
= List
->DiskListHead
.Flink
;
3075 while (Entry
!= &List
->DiskListHead
)
3077 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
3079 if (DiskEntry
->Dirty
== TRUE
)
3081 WritePartitions(List
, DiskEntry
);
3082 DiskEntry
->Dirty
= FALSE
;
3085 Entry
= Entry
->Flink
;
3093 SetMountedDeviceValues(
3096 PLIST_ENTRY Entry1
, Entry2
;
3097 PDISKENTRY DiskEntry
;
3098 PPARTENTRY PartEntry
;
3099 LARGE_INTEGER StartingOffset
;
3106 Entry1
= List
->DiskListHead
.Flink
;
3107 while (Entry1
!= &List
->DiskListHead
)
3109 DiskEntry
= CONTAINING_RECORD(Entry1
,
3113 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3114 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3116 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3117 if (PartEntry
->IsPartitioned
)
3119 if (PartEntry
->DriveLetter
)
3121 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
3122 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
3123 DiskEntry
->LayoutBuffer
->Signature
,
3131 Entry2
= Entry2
->Flink
;
3134 Entry1
= Entry1
->Flink
;
3142 PrimaryPartitionCreationChecks(
3145 PDISKENTRY DiskEntry
;
3146 PPARTENTRY PartEntry
;
3148 DiskEntry
= List
->CurrentDisk
;
3149 PartEntry
= List
->CurrentPartition
;
3151 /* Fail if partition is already in use */
3152 if (PartEntry
->IsPartitioned
== TRUE
)
3153 return ERROR_NEW_PARTITION
;
3155 /* Fail if there are more than 4 partitions in the list */
3156 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3157 return ERROR_PARTITION_TABLE_FULL
;
3159 return ERROR_SUCCESS
;
3164 ExtendedPartitionCreationChecks(
3167 PDISKENTRY DiskEntry
;
3168 PPARTENTRY PartEntry
;
3170 DiskEntry
= List
->CurrentDisk
;
3171 PartEntry
= List
->CurrentPartition
;
3173 /* Fail if partition is already in use */
3174 if (PartEntry
->IsPartitioned
== TRUE
)
3175 return ERROR_NEW_PARTITION
;
3177 /* Fail if there are more than 4 partitions in the list */
3178 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3179 return ERROR_PARTITION_TABLE_FULL
;
3181 /* Fail if there is another extended partition in the list */
3182 if (DiskEntry
->ExtendedPartition
!= NULL
)
3183 return ERROR_ONLY_ONE_EXTENDED
;
3185 return ERROR_SUCCESS
;
3190 LogicalPartitionCreationChecks(
3193 // PDISKENTRY DiskEntry;
3194 PPARTENTRY PartEntry
;
3196 // DiskEntry = List->CurrentDisk;
3197 PartEntry
= List
->CurrentPartition
;
3199 /* Fail if partition is already in use */
3200 if (PartEntry
->IsPartitioned
== TRUE
)
3201 return ERROR_NEW_PARTITION
;
3203 return ERROR_SUCCESS
;
3208 GetNextUnformattedPartition(
3210 OUT PDISKENTRY
*pDiskEntry
,
3211 OUT PPARTENTRY
*pPartEntry
)
3213 PLIST_ENTRY Entry1
, Entry2
;
3214 PDISKENTRY DiskEntry
;
3215 PPARTENTRY PartEntry
;
3217 Entry1
= List
->DiskListHead
.Flink
;
3218 while (Entry1
!= &List
->DiskListHead
)
3220 DiskEntry
= CONTAINING_RECORD(Entry1
,
3224 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3225 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3227 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3228 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3230 *pDiskEntry
= DiskEntry
;
3231 *pPartEntry
= PartEntry
;
3235 Entry2
= Entry2
->Flink
;
3238 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3239 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3241 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3242 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3244 *pDiskEntry
= DiskEntry
;
3245 *pPartEntry
= PartEntry
;
3249 Entry2
= Entry2
->Flink
;
3252 Entry1
= Entry1
->Flink
;
3263 GetNextUncheckedPartition(
3265 OUT PDISKENTRY
*pDiskEntry
,
3266 OUT PPARTENTRY
*pPartEntry
)
3268 PLIST_ENTRY Entry1
, Entry2
;
3269 PDISKENTRY DiskEntry
;
3270 PPARTENTRY PartEntry
;
3272 Entry1
= List
->DiskListHead
.Flink
;
3273 while (Entry1
!= &List
->DiskListHead
)
3275 DiskEntry
= CONTAINING_RECORD(Entry1
,
3279 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3280 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3282 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3283 if (PartEntry
->NeedsCheck
== TRUE
)
3285 *pDiskEntry
= DiskEntry
;
3286 *pPartEntry
= PartEntry
;
3290 Entry2
= Entry2
->Flink
;
3293 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3294 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3296 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3297 if (PartEntry
->NeedsCheck
== TRUE
)
3299 *pDiskEntry
= DiskEntry
;
3300 *pPartEntry
= PartEntry
;
3304 Entry2
= Entry2
->Flink
;
3307 Entry1
= Entry1
->Flink
;