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
;
88 ULONGLONG Temp
, Result
;
90 Temp
= Value
/ Alignment
;
92 Result
= Temp
* Alignment
;
93 if (Value
% Alignment
)
101 IN ULONGLONG Dividend
,
102 IN ULONGLONG Divisor
)
104 return (Dividend
+ Divisor
/ 2) / Divisor
;
111 PDISKENTRY DiskEntry
)
113 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
117 RtlInitUnicodeString(&DiskEntry
->DriverName
,
121 L
"\\Scsi\\Scsi Port %lu",
124 RtlZeroMemory(&QueryTable
,
127 QueryTable
[0].Name
= L
"Driver";
128 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
129 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
131 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
136 if (!NT_SUCCESS(Status
))
138 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
148 PDISKENTRY DiskEntry
;
149 PPARTENTRY PartEntry
;
156 /* Assign drive letters to primary partitions */
157 Entry1
= List
->DiskListHead
.Flink
;
158 while (Entry1
!= &List
->DiskListHead
)
160 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
162 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
163 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
165 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
167 PartEntry
->DriveLetter
= 0;
169 if (PartEntry
->IsPartitioned
&&
170 !IsContainerPartition(PartEntry
->PartitionType
))
172 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
173 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
174 PartEntry
->SectorCount
.QuadPart
!= 0LL))
178 PartEntry
->DriveLetter
= Letter
;
184 Entry2
= Entry2
->Flink
;
187 Entry1
= Entry1
->Flink
;
190 /* Assign drive letters to logical drives */
191 Entry1
= List
->DiskListHead
.Flink
;
192 while (Entry1
!= &List
->DiskListHead
)
194 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
196 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
197 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
199 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
201 PartEntry
->DriveLetter
= 0;
203 if (PartEntry
->IsPartitioned
)
205 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
206 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
207 PartEntry
->SectorCount
.QuadPart
!= 0LL))
211 PartEntry
->DriveLetter
= Letter
;
217 Entry2
= Entry2
->Flink
;
220 Entry1
= Entry1
->Flink
;
227 DiskIdentifierQueryRoutine(
235 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
236 UNICODE_STRING NameU
;
238 if (ValueType
== REG_SZ
&&
239 ValueLength
== 20 * sizeof(WCHAR
))
241 NameU
.Buffer
= (PWCHAR
)ValueData
;
242 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
243 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
245 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
246 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
248 return STATUS_SUCCESS
;
251 return STATUS_UNSUCCESSFUL
;
257 DiskConfigurationDataQueryRoutine(
265 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
266 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
267 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
270 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
271 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
272 return STATUS_UNSUCCESSFUL
;
274 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
276 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
278 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
279 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
280 return STATUS_UNSUCCESSFUL
;
283 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
285 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
286 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
289 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
290 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
292 return STATUS_SUCCESS
;
295 return STATUS_UNSUCCESSFUL
;
301 SystemConfigurationDataQueryRoutine(
309 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
310 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
313 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
314 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
315 return STATUS_UNSUCCESSFUL
;
317 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
319 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
321 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
322 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
323 return STATUS_UNSUCCESSFUL
;
326 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
328 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
329 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
332 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
333 if (*Int13Drives
== NULL
)
334 return STATUS_NO_MEMORY
;
337 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
338 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
339 return STATUS_SUCCESS
;
342 return STATUS_UNSUCCESSFUL
;
346 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
349 EnumerateBiosDiskEntries(
352 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
357 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
358 PBIOSDISKENTRY BiosDiskEntry
;
360 memset(QueryTable
, 0, sizeof(QueryTable
));
362 QueryTable
[1].Name
= L
"Configuration Data";
363 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
365 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
366 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
370 if (!NT_SUCCESS(Status
))
372 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
379 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
380 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
385 if (!NT_SUCCESS(Status
))
390 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
391 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
396 if (NT_SUCCESS(Status
))
400 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
401 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
406 if (!NT_SUCCESS(Status
))
408 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
412 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
413 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
418 if (NT_SUCCESS(Status
))
420 QueryTable
[0].Name
= L
"Identifier";
421 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
422 QueryTable
[1].Name
= L
"Configuration Data";
423 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
428 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
429 if (BiosDiskEntry
== NULL
)
434 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
435 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
438 (PVOID
)BiosDiskEntry
,
440 if (!NT_SUCCESS(Status
))
442 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
446 BiosDiskEntry
->DiskNumber
= DiskCount
;
447 BiosDiskEntry
->Recognized
= FALSE
;
449 if (DiskCount
< Int13Drives
[0].NumberDrives
)
451 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
455 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
458 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
460 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
461 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
462 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
463 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
464 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
465 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
466 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
467 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
468 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
469 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
470 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
476 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
484 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
492 PDISKENTRY DiskEntry
,
493 ULONG PartitionIndex
,
494 BOOLEAN LogicalPartition
)
496 PPARTITION_INFORMATION PartitionInfo
;
497 PPARTENTRY PartEntry
;
499 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[PartitionIndex
];
500 if (PartitionInfo
->PartitionType
== 0 ||
501 (LogicalPartition
== TRUE
&& IsContainerPartition(PartitionInfo
->PartitionType
)))
504 PartEntry
= RtlAllocateHeap(ProcessHeap
,
507 if (PartEntry
== NULL
)
512 PartEntry
->DiskEntry
= DiskEntry
;
514 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
515 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
517 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
518 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
519 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
521 PartEntry
->LogicalPartition
= LogicalPartition
;
522 PartEntry
->IsPartitioned
= TRUE
;
523 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
524 PartEntry
->PartitionIndex
= PartitionIndex
;
526 if (IsContainerPartition(PartEntry
->PartitionType
))
528 PartEntry
->FormatState
= Unformatted
;
530 if (LogicalPartition
== FALSE
&& DiskEntry
->ExtendedPartition
== NULL
)
531 DiskEntry
->ExtendedPartition
= PartEntry
;
533 else if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
534 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
535 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
536 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
537 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
538 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
541 if (CheckFatFormat())
543 PartEntry
->FormatState
= Preformatted
;
547 PartEntry
->FormatState
= Unformatted
;
550 PartEntry
->FormatState
= Preformatted
;
552 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
555 if (CheckExt2Format())
557 PartEntry
->FormatState
= Preformatted
;
561 PartEntry
->FormatState
= Unformatted
;
564 PartEntry
->FormatState
= Preformatted
;
566 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
569 if (CheckNtfsFormat())
571 PartEntry
->FormatState
= Preformatted
;
573 else if (CheckHpfsFormat())
575 PartEntry
->FormatState
= Preformatted
;
579 PartEntry
->FormatState
= Unformatted
;
582 PartEntry
->FormatState
= Preformatted
;
586 PartEntry
->FormatState
= UnknownFormat
;
589 if (LogicalPartition
)
590 InsertTailList(&DiskEntry
->LogicalPartListHead
,
591 &PartEntry
->ListEntry
);
593 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
594 &PartEntry
->ListEntry
);
600 ScanForUnpartitionedDiskSpace(
601 PDISKENTRY DiskEntry
)
603 ULONGLONG LastStartSector
;
604 ULONGLONG LastSectorCount
;
605 ULONGLONG LastUnusedSectorCount
;
606 PPARTENTRY PartEntry
;
607 PPARTENTRY NewPartEntry
;
610 DPRINT("ScanForUnpartitionedDiskSpace()\n");
612 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
614 DPRINT1("No primary partition!\n");
616 /* Create a partition table that represents the empty disk */
617 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
620 if (NewPartEntry
== NULL
)
623 NewPartEntry
->DiskEntry
= DiskEntry
;
625 NewPartEntry
->IsPartitioned
= FALSE
;
626 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorAlignment
;
627 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
628 NewPartEntry
->StartSector
.QuadPart
;
630 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
631 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
632 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
634 NewPartEntry
->FormatState
= Unformatted
;
636 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
637 &NewPartEntry
->ListEntry
);
642 /* Start partition at head 1, cylinder 0 */
643 LastStartSector
= DiskEntry
->SectorAlignment
;
644 LastSectorCount
= 0ULL;
645 LastUnusedSectorCount
= 0ULL;
647 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
648 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
650 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
652 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
653 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
655 LastUnusedSectorCount
=
656 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
658 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
659 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
661 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
663 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
666 if (NewPartEntry
== NULL
)
669 NewPartEntry
->DiskEntry
= DiskEntry
;
671 NewPartEntry
->IsPartitioned
= FALSE
;
672 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
673 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
674 NewPartEntry
->StartSector
.QuadPart
;
676 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
677 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
678 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
680 NewPartEntry
->FormatState
= Unformatted
;
682 /* Insert the table into the list */
683 InsertTailList(&PartEntry
->ListEntry
,
684 &NewPartEntry
->ListEntry
);
687 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
688 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
691 Entry
= Entry
->Flink
;
694 /* Check for trailing unpartitioned disk space */
695 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
697 LastUnusedSectorCount
= AlignDown(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
699 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
701 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
703 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
706 if (NewPartEntry
== NULL
)
709 NewPartEntry
->DiskEntry
= DiskEntry
;
711 NewPartEntry
->IsPartitioned
= FALSE
;
712 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
713 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
714 NewPartEntry
->StartSector
.QuadPart
;
716 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
717 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
718 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
720 NewPartEntry
->FormatState
= Unformatted
;
722 /* Append the table to the list */
723 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
724 &NewPartEntry
->ListEntry
);
728 if (DiskEntry
->ExtendedPartition
!= NULL
)
730 if (IsListEmpty(&DiskEntry
->LogicalPartListHead
))
732 DPRINT1("No logical partition!\n");
734 /* Create a partition table entry that represents the empty extended partition */
735 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
738 if (NewPartEntry
== NULL
)
741 NewPartEntry
->DiskEntry
= DiskEntry
;
742 NewPartEntry
->LogicalPartition
= TRUE
;
744 NewPartEntry
->IsPartitioned
= FALSE
;
745 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
746 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
748 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
749 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
750 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
752 NewPartEntry
->FormatState
= Unformatted
;
754 InsertTailList(&DiskEntry
->LogicalPartListHead
,
755 &NewPartEntry
->ListEntry
);
760 /* Start partition at head 1, cylinder 0 */
761 LastStartSector
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
762 LastSectorCount
= 0ULL;
763 LastUnusedSectorCount
= 0ULL;
765 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
766 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
768 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
770 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
771 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
773 LastUnusedSectorCount
=
774 PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
- (LastStartSector
+ LastSectorCount
);
776 if ((PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
) > (LastStartSector
+ LastSectorCount
) &&
777 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
779 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
781 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
784 if (NewPartEntry
== NULL
)
787 NewPartEntry
->DiskEntry
= DiskEntry
;
788 NewPartEntry
->LogicalPartition
= TRUE
;
790 NewPartEntry
->IsPartitioned
= FALSE
;
791 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
792 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
793 NewPartEntry
->StartSector
.QuadPart
;
795 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
796 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
797 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
799 NewPartEntry
->FormatState
= Unformatted
;
801 /* Insert the table into the list */
802 InsertTailList(&PartEntry
->ListEntry
,
803 &NewPartEntry
->ListEntry
);
806 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
807 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
810 Entry
= Entry
->Flink
;
813 /* Check for trailing unpartitioned disk space */
814 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
)
816 LastUnusedSectorCount
= AlignDown(DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
818 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
820 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
822 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
825 if (NewPartEntry
== NULL
)
828 NewPartEntry
->DiskEntry
= DiskEntry
;
829 NewPartEntry
->LogicalPartition
= TRUE
;
831 NewPartEntry
->IsPartitioned
= FALSE
;
832 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
833 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
834 NewPartEntry
->StartSector
.QuadPart
;
836 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
837 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
838 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
840 NewPartEntry
->FormatState
= Unformatted
;
842 /* Append the table to the list */
843 InsertTailList(&DiskEntry
->LogicalPartListHead
,
844 &NewPartEntry
->ListEntry
);
849 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
857 IN PDISKENTRY DiskEntry
)
859 LARGE_INTEGER SystemTime
;
860 TIME_FIELDS TimeFields
;
862 PDISKENTRY DiskEntry2
;
865 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
869 NtQuerySystemTime(&SystemTime
);
870 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
872 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
873 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
874 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
875 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
877 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
882 /* check if the signature already exist */
884 * Check also signatures from disks, which are
885 * not visible (bootable) by the bios.
887 Entry2
= List
->DiskListHead
.Flink
;
888 while (Entry2
!= &List
->DiskListHead
)
890 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
892 if (DiskEntry
!= DiskEntry2
&&
893 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
896 Entry2
= Entry2
->Flink
;
899 if (Entry2
== &List
->DiskListHead
)
907 UpdateDiskSignatures(
911 PDISKENTRY DiskEntry
;
913 /* Print partition lines*/
914 Entry
= List
->DiskListHead
.Flink
;
915 while (Entry
!= &List
->DiskListHead
)
917 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
919 if (DiskEntry
->LayoutBuffer
&&
920 DiskEntry
->LayoutBuffer
->Signature
== 0)
922 SetDiskSignature(List
, DiskEntry
);
923 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
926 Entry
= Entry
->Flink
;
938 DISK_GEOMETRY DiskGeometry
;
939 SCSI_ADDRESS ScsiAddress
;
940 PDISKENTRY DiskEntry
;
941 IO_STATUS_BLOCK Iosb
;
943 PPARTITION_SECTOR Mbr
;
945 LARGE_INTEGER FileOffset
;
946 WCHAR Identifier
[20];
950 PLIST_ENTRY ListEntry
;
951 PBIOSDISKENTRY BiosDiskEntry
;
952 ULONG LayoutBufferSize
;
953 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
955 Status
= NtDeviceIoControlFile(FileHandle
,
960 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
964 sizeof(DISK_GEOMETRY
));
965 if (!NT_SUCCESS(Status
))
970 if (DiskGeometry
.MediaType
!= FixedMedia
&&
971 DiskGeometry
.MediaType
!= RemovableMedia
)
976 Status
= NtDeviceIoControlFile(FileHandle
,
981 IOCTL_SCSI_GET_ADDRESS
,
985 sizeof(SCSI_ADDRESS
));
986 if (!NT_SUCCESS(Status
))
991 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
993 DiskGeometry
.BytesPerSector
);
999 FileOffset
.QuadPart
= 0;
1000 Status
= NtReadFile(FileHandle
,
1006 DiskGeometry
.BytesPerSector
,
1009 if (!NT_SUCCESS(Status
))
1011 RtlFreeHeap(ProcessHeap
,
1014 DPRINT1("NtReadFile failed, status=%x\n", Status
);
1017 Signature
= Mbr
->Signature
;
1019 /* Calculate the MBR checksum */
1021 Buffer
= (PULONG
)Mbr
;
1022 for (i
= 0; i
< 128; i
++)
1024 Checksum
+= Buffer
[i
];
1026 Checksum
= ~Checksum
+ 1;
1028 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
1029 DPRINT("Identifier: %S\n", Identifier
);
1031 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
1034 if (DiskEntry
== NULL
)
1039 // DiskEntry->Checksum = Checksum;
1040 // DiskEntry->Signature = Signature;
1041 DiskEntry
->BiosFound
= FALSE
;
1043 /* Check if this disk has a valid MBR */
1044 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
1045 DiskEntry
->NoMbr
= TRUE
;
1047 DiskEntry
->NoMbr
= FALSE
;
1049 /* Free Mbr sector buffer */
1050 RtlFreeHeap(ProcessHeap
,
1054 ListEntry
= List
->BiosDiskListHead
.Flink
;
1055 while(ListEntry
!= &List
->BiosDiskListHead
)
1057 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
1059 * Compare the size from bios and the reported size from driver.
1060 * If we have more than one disk with a zero or with the same signatur
1061 * we must create new signatures and reboot. After the reboot,
1062 * it is possible to identify the disks.
1064 if (BiosDiskEntry
->Signature
== Signature
&&
1065 BiosDiskEntry
->Checksum
== Checksum
&&
1066 !BiosDiskEntry
->Recognized
)
1068 if (!DiskEntry
->BiosFound
)
1070 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
1071 DiskEntry
->BiosFound
= TRUE
;
1072 BiosDiskEntry
->Recognized
= TRUE
;
1078 ListEntry
= ListEntry
->Flink
;
1081 if (!DiskEntry
->BiosFound
)
1084 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1087 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
1091 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
1092 InitializeListHead(&DiskEntry
->LogicalPartListHead
);
1094 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
1095 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
1096 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
1097 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1099 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1100 DPRINT("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
1101 DPRINT("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
1102 DPRINT("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
1104 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1105 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1106 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1108 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1109 DiskEntry
->CylinderAlignment
= DiskGeometry
.TracksPerCylinder
*
1110 DiskGeometry
.SectorsPerTrack
;
1112 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
);
1113 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1115 DiskEntry
->DiskNumber
= DiskNumber
;
1116 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1117 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1118 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1120 GetDriverName(DiskEntry
);
1122 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1124 /* Allocate a layout buffer with 4 partition entries first */
1125 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1126 ((4 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1127 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1130 if (DiskEntry
->LayoutBuffer
== NULL
)
1132 DPRINT1("Failed to allocate the disk layout buffer!\n");
1138 DPRINT1("Buffer size: %lu\n", LayoutBufferSize
);
1139 Status
= NtDeviceIoControlFile(FileHandle
,
1144 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1147 DiskEntry
->LayoutBuffer
,
1149 if (NT_SUCCESS(Status
))
1152 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1154 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status
);
1158 LayoutBufferSize
+= 4 * sizeof(PARTITION_INFORMATION
);
1159 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
1161 DiskEntry
->LayoutBuffer
,
1163 if (NewLayoutBuffer
== NULL
)
1165 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1169 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
1172 DPRINT1("PartitionCount: %lu\n", DiskEntry
->LayoutBuffer
->PartitionCount
);
1174 #ifdef DUMP_PARTITION_TABLE
1175 DumpPartitionTable(DiskEntry
);
1178 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
!= 0 &&
1179 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionLength
.QuadPart
!= 0 &&
1180 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionType
!= 0)
1182 if ((DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
) % DiskEntry
->SectorsPerTrack
== 0)
1184 DPRINT("Use %lu Sector alignment!\n", DiskEntry
->SectorsPerTrack
);
1186 else if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
% (1024 * 1024) == 0)
1188 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1192 DPRINT1("No matching aligment found! Partiton 1 starts at %I64u\n", DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
);
1197 DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1201 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1203 DiskEntry
->NewDisk
= TRUE
;
1204 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1206 for (i
= 0; i
< 4; i
++)
1207 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1211 for (i
= 0; i
< 4; i
++)
1213 AddPartitionToDisk(DiskNumber
,
1219 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1221 AddPartitionToDisk(DiskNumber
,
1228 ScanForUnpartitionedDiskSpace(DiskEntry
);
1233 CreatePartitionList(
1240 OBJECT_ATTRIBUTES ObjectAttributes
;
1241 SYSTEM_DEVICE_INFORMATION Sdi
;
1242 IO_STATUS_BLOCK Iosb
;
1246 WCHAR Buffer
[MAX_PATH
];
1247 UNICODE_STRING Name
;
1250 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1258 List
->Right
= Right
;
1259 List
->Bottom
= Bottom
;
1264 List
->TopDisk
= (ULONG
)-1;
1265 List
->TopPartition
= (ULONG
)-1;
1267 List
->CurrentDisk
= NULL
;
1268 List
->CurrentPartition
= NULL
;
1270 List
->BootDisk
= NULL
;
1271 List
->BootPartition
= NULL
;
1273 List
->TempDisk
= NULL
;
1274 List
->TempPartition
= NULL
;
1275 List
->FormatState
= Start
;
1277 InitializeListHead(&List
->DiskListHead
);
1278 InitializeListHead(&List
->BiosDiskListHead
);
1280 EnumerateBiosDiskEntries(List
);
1282 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1284 sizeof(SYSTEM_DEVICE_INFORMATION
),
1286 if (!NT_SUCCESS(Status
))
1288 RtlFreeHeap(ProcessHeap
, 0, List
);
1292 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1295 L
"\\Device\\Harddisk%d\\Partition0",
1297 RtlInitUnicodeString(&Name
,
1300 InitializeObjectAttributes(&ObjectAttributes
,
1306 Status
= NtOpenFile(&FileHandle
,
1307 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1311 FILE_SYNCHRONOUS_IO_NONALERT
);
1312 if (NT_SUCCESS(Status
))
1314 AddDiskToList(FileHandle
,
1318 NtClose(FileHandle
);
1322 UpdateDiskSignatures(List
);
1324 AssignDriveLetters(List
);
1327 List
->TopPartition
= 0;
1329 /* Search for first usable disk and partition */
1330 if (IsListEmpty(&List
->DiskListHead
))
1332 List
->CurrentDisk
= NULL
;
1333 List
->CurrentPartition
= NULL
;
1337 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1341 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1343 List
->CurrentPartition
= 0;
1347 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1358 DestroyPartitionList(
1361 PDISKENTRY DiskEntry
;
1362 PBIOSDISKENTRY BiosDiskEntry
;
1363 PPARTENTRY PartEntry
;
1366 /* Release disk and partition info */
1367 while (!IsListEmpty(&List
->DiskListHead
))
1369 Entry
= RemoveHeadList(&List
->DiskListHead
);
1370 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1372 /* Release driver name */
1373 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1375 /* Release primary partition list */
1376 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1378 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1379 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1381 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1384 /* Release logical partition list */
1385 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
1387 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
1388 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1390 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1393 /* Release layout buffer */
1394 if (DiskEntry
->LayoutBuffer
!= NULL
)
1395 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1398 /* Release disk entry */
1399 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1402 /* release the bios disk info */
1403 while(!IsListEmpty(&List
->BiosDiskListHead
))
1405 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1406 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1408 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1411 /* Release list head */
1412 RtlFreeHeap(ProcessHeap
, 0, List
);
1426 Width
= List
->Right
- List
->Left
- 1;
1427 Height
= List
->Bottom
- List
->Top
- 2;
1429 coPos
.X
= List
->Left
+ 1;
1430 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1432 if (List
->Line
>= 0 && List
->Line
<= Height
)
1434 FillConsoleOutputAttribute(StdOutput
,
1435 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1440 FillConsoleOutputCharacterA(StdOutput
,
1455 PDISKENTRY DiskEntry
,
1456 PPARTENTRY PartEntry
)
1458 CHAR LineBuffer
[128];
1463 LARGE_INTEGER PartSize
;
1468 Width
= List
->Right
- List
->Left
- 1;
1469 Height
= List
->Bottom
- List
->Top
- 2;
1471 coPos
.X
= List
->Left
+ 1;
1472 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1474 if (PartEntry
->IsPartitioned
== FALSE
)
1476 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1478 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1480 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1481 Unit
= MUIGetString(STRING_GB
);
1485 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1487 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1488 Unit
= MUIGetString(STRING_MB
);
1492 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1493 Unit
= MUIGetString(STRING_KB
);
1497 MUIGetString(STRING_UNPSPACE
),
1498 PartEntry
->LogicalPartition
? " " : "",
1499 PartEntry
->LogicalPartition
? "" : " ",
1505 /* Determine partition type */
1507 if (PartEntry
->New
== TRUE
)
1509 PartType
= MUIGetString(STRING_UNFORMATTED
);
1511 else if (PartEntry
->IsPartitioned
== TRUE
)
1513 if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
1514 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
1515 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
1516 (PartEntry
->PartitionType
== PARTITION_XINT13
))
1520 else if ((PartEntry
->PartitionType
== PARTITION_FAT32
) ||
1521 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
1525 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
1529 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
1531 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1533 else if ((PartEntry
->PartitionType
== PARTITION_EXTENDED
) ||
1534 (PartEntry
->PartitionType
== PARTITION_XINT13_EXTENDED
))
1536 PartType
= MUIGetString(STRING_EXTENDED_PARTITION
);
1540 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1542 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1544 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1545 Unit
= MUIGetString(STRING_GB
);
1549 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1551 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1552 Unit
= MUIGetString(STRING_MB
);
1556 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1557 Unit
= MUIGetString(STRING_KB
);
1560 if (PartType
== NULL
)
1563 MUIGetString(STRING_HDDINFOUNK5
),
1564 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1565 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1566 PartEntry
->BootIndicator
? '*' : ' ',
1567 PartEntry
->LogicalPartition
? " " : "",
1568 PartEntry
->PartitionType
,
1569 PartEntry
->LogicalPartition
? "" : " ",
1576 "%c%c %c %s%-24s%s %6lu %s",
1577 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1578 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1579 PartEntry
->BootIndicator
? '*' : ' ',
1580 PartEntry
->LogicalPartition
? " " : "",
1582 PartEntry
->LogicalPartition
? "" : " ",
1588 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1589 List
->CurrentPartition
== PartEntry
) ?
1590 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1591 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1593 if (List
->Line
>= 0 && List
->Line
<= Height
)
1595 FillConsoleOutputCharacterA(StdOutput
,
1603 if (List
->Line
>= 0 && List
->Line
<= Height
)
1605 FillConsoleOutputAttribute(StdOutput
,
1613 if (List
->Line
>= 0 && List
->Line
<= Height
)
1615 WriteConsoleOutputCharacterA(StdOutput
,
1617 min(strlen(LineBuffer
), Width
),
1630 PDISKENTRY DiskEntry
)
1632 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
1633 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
1634 CHAR LineBuffer
[128];
1639 ULARGE_INTEGER DiskSize
;
1642 Width
= List
->Right
- List
->Left
- 1;
1643 Height
= List
->Bottom
- List
->Top
- 2;
1645 coPos
.X
= List
->Left
+ 1;
1646 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1648 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1649 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
1651 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
1652 Unit
= MUIGetString(STRING_GB
);
1656 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
1657 if (DiskSize
.QuadPart
== 0)
1658 DiskSize
.QuadPart
= 1;
1659 Unit
= MUIGetString(STRING_MB
);
1662 if (DiskEntry
->DriverName
.Length
> 0)
1665 MUIGetString(STRING_HDINFOPARTSELECT
),
1668 DiskEntry
->DiskNumber
,
1672 DiskEntry
->DriverName
.Buffer
);
1677 MUIGetString(STRING_HDDINFOUNK6
),
1680 DiskEntry
->DiskNumber
,
1686 if (List
->Line
>= 0 && List
->Line
<= Height
)
1688 FillConsoleOutputAttribute(StdOutput
,
1689 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1694 FillConsoleOutputCharacterA(StdOutput
,
1702 if (List
->Line
>= 0 && List
->Line
<= Height
)
1704 WriteConsoleOutputCharacterA(StdOutput
,
1706 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1713 /* Print separator line */
1714 PrintEmptyLine(List
);
1716 /* Print partition lines*/
1717 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1718 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
1720 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
1722 PrintPartitionData(List
,
1726 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
1728 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
1729 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
1731 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
1733 PrintPartitionData(List
,
1737 LogicalEntry
= LogicalEntry
->Flink
;
1741 PrimaryEntry
= PrimaryEntry
->Flink
;
1744 /* Print separator line */
1745 PrintEmptyLine(List
);
1753 PLIST_ENTRY Entry
, Entry2
;
1754 PDISKENTRY DiskEntry
;
1755 PPARTENTRY PartEntry
= NULL
;
1759 SHORT CurrentDiskLine
;
1760 SHORT CurrentPartLine
;
1762 BOOL CurrentPartLineFound
= FALSE
;
1763 BOOL CurrentDiskLineFound
= FALSE
;
1765 /* Calculate the line of the current disk and partition */
1766 CurrentDiskLine
= 0;
1767 CurrentPartLine
= 0;
1770 Entry
= List
->DiskListHead
.Flink
;
1771 while (Entry
!= &List
->DiskListHead
)
1773 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1776 if (CurrentPartLineFound
== FALSE
)
1778 CurrentPartLine
+= 2;
1781 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1782 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1784 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1785 if (PartEntry
== List
->CurrentPartition
)
1787 CurrentPartLineFound
= TRUE
;
1790 Entry2
= Entry2
->Flink
;
1791 if (CurrentPartLineFound
== FALSE
)
1799 if (DiskEntry
== List
->CurrentDisk
)
1801 CurrentDiskLineFound
= TRUE
;
1804 Entry
= Entry
->Flink
;
1805 if (Entry
!= &List
->DiskListHead
)
1807 if (CurrentDiskLineFound
== FALSE
)
1810 CurrentDiskLine
= CurrentPartLine
;
1821 /* If it possible, make the disk name visible */
1822 if (CurrentPartLine
< List
->Offset
)
1824 List
->Offset
= CurrentPartLine
;
1826 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1828 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1831 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1833 List
->Offset
= CurrentDiskLine
;
1836 /* draw upper left corner */
1837 coPos
.X
= List
->Left
;
1838 coPos
.Y
= List
->Top
;
1839 FillConsoleOutputCharacterA(StdOutput
,
1845 /* draw upper edge */
1846 coPos
.X
= List
->Left
+ 1;
1847 coPos
.Y
= List
->Top
;
1848 if (List
->Offset
== 0)
1850 FillConsoleOutputCharacterA(StdOutput
,
1852 List
->Right
- List
->Left
- 1,
1858 FillConsoleOutputCharacterA(StdOutput
,
1860 List
->Right
- List
->Left
- 5,
1863 coPos
.X
= List
->Right
- 5;
1864 WriteConsoleOutputCharacterA(StdOutput
,
1869 coPos
.X
= List
->Right
- 2;
1870 FillConsoleOutputCharacterA(StdOutput
,
1877 /* draw upper right corner */
1878 coPos
.X
= List
->Right
;
1879 coPos
.Y
= List
->Top
;
1880 FillConsoleOutputCharacterA(StdOutput
,
1886 /* draw left and right edge */
1887 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1889 coPos
.X
= List
->Left
;
1891 FillConsoleOutputCharacterA(StdOutput
,
1897 coPos
.X
= List
->Right
;
1898 FillConsoleOutputCharacterA(StdOutput
,
1905 /* draw lower left corner */
1906 coPos
.X
= List
->Left
;
1907 coPos
.Y
= List
->Bottom
;
1908 FillConsoleOutputCharacterA(StdOutput
,
1914 /* draw lower edge */
1915 coPos
.X
= List
->Left
+ 1;
1916 coPos
.Y
= List
->Bottom
;
1917 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1919 FillConsoleOutputCharacterA(StdOutput
,
1921 List
->Right
- List
->Left
- 1,
1927 FillConsoleOutputCharacterA(StdOutput
,
1929 List
->Right
- List
->Left
- 5,
1932 coPos
.X
= List
->Right
- 5;
1933 WriteConsoleOutputCharacterA(StdOutput
,
1934 "(\x19)", // "(down)"
1938 coPos
.X
= List
->Right
- 2;
1939 FillConsoleOutputCharacterA(StdOutput
,
1946 /* draw lower right corner */
1947 coPos
.X
= List
->Right
;
1948 coPos
.Y
= List
->Bottom
;
1949 FillConsoleOutputCharacterA(StdOutput
,
1955 /* print list entries */
1956 List
->Line
= - List
->Offset
;
1958 Entry
= List
->DiskListHead
.Flink
;
1959 while (Entry
!= &List
->DiskListHead
)
1961 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1963 /* Print disk entry */
1967 Entry
= Entry
->Flink
;
1976 ULONG PartitionNumber
)
1978 PDISKENTRY DiskEntry
;
1979 PPARTENTRY PartEntry
;
1983 /* Check for empty disks */
1984 if (IsListEmpty(&List
->DiskListHead
))
1987 /* Check for first usable entry on next disk */
1988 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1989 while (Entry1
!= &List
->DiskListHead
)
1991 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1993 if (DiskEntry
->DiskNumber
== DiskNumber
)
1995 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1996 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1998 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2000 if (PartEntry
->PartitionNumber
== PartitionNumber
)
2002 List
->CurrentDisk
= DiskEntry
;
2003 List
->CurrentPartition
= PartEntry
;
2004 DrawPartitionList(List
);
2008 Entry2
= Entry2
->Flink
;
2014 Entry1
= Entry1
->Flink
;
2022 ScrollDownPartitionList(
2025 PLIST_ENTRY DiskListEntry
;
2026 PLIST_ENTRY PartListEntry
;
2027 PDISKENTRY DiskEntry
;
2028 PPARTENTRY PartEntry
;
2030 /* Fail, if no disks are available */
2031 if (IsListEmpty(&List
->DiskListHead
))
2034 /* Check for next usable entry on current disk */
2035 if (List
->CurrentPartition
!= NULL
)
2037 if (List
->CurrentPartition
->LogicalPartition
)
2039 /* Logical partition */
2041 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2042 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2044 /* Next logical partition */
2045 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2047 List
->CurrentPartition
= PartEntry
;
2052 PartListEntry
= List
->CurrentDisk
->ExtendedPartition
->ListEntry
.Flink
;
2053 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2055 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2057 List
->CurrentPartition
= PartEntry
;
2064 /* Primary or extended partition */
2066 if (List
->CurrentPartition
->IsPartitioned
== TRUE
&&
2067 IsContainerPartition(List
->CurrentPartition
->PartitionType
))
2069 /* First logical partition */
2070 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Flink
;
2071 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2073 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2075 List
->CurrentPartition
= PartEntry
;
2081 /* Next primary partition */
2082 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
2083 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2085 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2087 List
->CurrentPartition
= PartEntry
;
2094 /* Search for the first partition entry on the next disk */
2095 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Flink
;
2096 while (DiskListEntry
!= &List
->DiskListHead
)
2098 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2100 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2101 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2103 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2105 List
->CurrentDisk
= DiskEntry
;
2106 List
->CurrentPartition
= PartEntry
;
2110 DiskListEntry
= DiskListEntry
->Flink
;
2118 ScrollUpPartitionList(
2121 PLIST_ENTRY DiskListEntry
;
2122 PLIST_ENTRY PartListEntry
;
2123 PDISKENTRY DiskEntry
;
2124 PPARTENTRY PartEntry
;
2126 /* Fail, if no disks are available */
2127 if (IsListEmpty(&List
->DiskListHead
))
2130 /* Check for previous usable entry on current disk */
2131 if (List
->CurrentPartition
!= NULL
)
2133 if (List
->CurrentPartition
->LogicalPartition
)
2135 /* Logical partition */
2136 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2137 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
2139 /* Previous logical partition */
2140 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2144 /* Extended partition*/
2145 PartEntry
= List
->CurrentDisk
->ExtendedPartition
;
2148 List
->CurrentPartition
= PartEntry
;
2153 /* Primary or extended partition */
2155 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
2156 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
2158 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2160 if (PartEntry
->IsPartitioned
== TRUE
&&
2161 IsContainerPartition(PartEntry
->PartitionType
))
2163 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Blink
;
2164 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2167 List
->CurrentPartition
= PartEntry
;
2174 /* Search for the last partition entry on the previous disk */
2175 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Blink
;
2176 while (DiskListEntry
!= &List
->DiskListHead
)
2178 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
2180 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Blink
;
2181 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2183 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2185 if (PartEntry
->IsPartitioned
== TRUE
&&
2186 IsContainerPartition(PartEntry
->PartitionType
))
2188 PartListEntry
= DiskEntry
->LogicalPartListHead
.Blink
;
2189 if (PartListEntry
!= &DiskEntry
->LogicalPartListHead
)
2191 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
2193 List
->CurrentDisk
= DiskEntry
;
2194 List
->CurrentPartition
= PartEntry
;
2200 List
->CurrentDisk
= DiskEntry
;
2201 List
->CurrentPartition
= PartEntry
;
2206 DiskListEntry
= DiskListEntry
->Blink
;
2216 PPARTITION_INFORMATION PartitionInfo
)
2218 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
2219 PartitionInfo
->PartitionLength
.QuadPart
== 0)
2228 IsSamePrimaryLayoutEntry(
2229 IN PPARTITION_INFORMATION PartitionInfo
,
2230 IN PDISKENTRY DiskEntry
,
2231 IN PPARTENTRY PartEntry
)
2233 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
2234 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
2235 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2236 // PartitionInfo->PartitionType == PartEntry->PartitionType
2245 GetPrimaryPartitionCount(
2246 IN PDISKENTRY DiskEntry
)
2249 PPARTENTRY PartEntry
;
2252 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2253 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
2255 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2256 if (PartEntry
->IsPartitioned
== TRUE
)
2259 Entry
= Entry
->Flink
;
2268 GetLogicalPartitionCount(
2269 PDISKENTRY DiskEntry
)
2271 PLIST_ENTRY ListEntry
;
2272 PPARTENTRY PartEntry
;
2275 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
2276 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
2278 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2279 if (PartEntry
->IsPartitioned
)
2282 ListEntry
= ListEntry
->Flink
;
2291 ReAllocateLayoutBuffer(
2292 PDISKENTRY DiskEntry
)
2294 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
2295 ULONG NewPartitionCount
;
2296 ULONG CurrentPartitionCount
= 0;
2297 ULONG LayoutBufferSize
;
2300 DPRINT1("ReAllocateLayoutBuffer()\n");
2302 NewPartitionCount
= 4 + GetLogicalPartitionCount(DiskEntry
) * 4;
2304 if (DiskEntry
->LayoutBuffer
)
2305 CurrentPartitionCount
= DiskEntry
->LayoutBuffer
->PartitionCount
;
2307 DPRINT1("CurrentPartitionCount: %lu NewPartitionCount: %lu\n",
2308 CurrentPartitionCount
, NewPartitionCount
);
2310 if (CurrentPartitionCount
== NewPartitionCount
)
2313 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2314 ((NewPartitionCount
- ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
2315 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
2317 DiskEntry
->LayoutBuffer
,
2319 if (NewLayoutBuffer
== NULL
)
2321 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize
);
2325 /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
2326 if (NewPartitionCount
> CurrentPartitionCount
)
2328 for (i
= CurrentPartitionCount
; i
< NewPartitionCount
; i
++)
2329 NewLayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
2332 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
2333 DiskEntry
->LayoutBuffer
->PartitionCount
= NewPartitionCount
;
2342 IN PDISKENTRY DiskEntry
)
2344 PPARTITION_INFORMATION PartitionInfo
;
2345 PPARTITION_INFORMATION LinkInfo
= NULL
;
2346 PLIST_ENTRY ListEntry
;
2347 PPARTENTRY PartEntry
;
2348 LARGE_INTEGER HiddenSectors64
;
2350 ULONG PartitionNumber
= 1;
2352 DPRINT1("UpdateDiskLayout()\n");
2354 /* Resize the layout buffer if necessary */
2355 if (ReAllocateLayoutBuffer(DiskEntry
) == FALSE
)
2357 DPRINT("ReAllocateLayoutBuffer() failed.\n");
2361 /* Update the primary partition table */
2363 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2364 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2366 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2368 if (PartEntry
->IsPartitioned
== TRUE
)
2370 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2372 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2374 DPRINT1("Updating primary partition entry %lu\n", Index
);
2376 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2377 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2378 PartitionInfo
->HiddenSectors
= PartEntry
->StartSector
.LowPart
;
2379 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2380 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2381 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2382 PartitionInfo
->RecognizedPartition
= FALSE
;
2383 PartitionInfo
->RewritePartition
= TRUE
;
2386 PartEntry
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2387 PartEntry
->PartitionIndex
= Index
;
2389 if (!IsContainerPartition(PartEntry
->PartitionType
))
2395 ListEntry
= ListEntry
->Flink
;
2398 /* Update the logical partition tables */
2400 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
2401 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
2403 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
2405 if (PartEntry
->IsPartitioned
)
2407 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2409 DPRINT1("Updating logical partition entry %lu\n", Index
);
2411 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2412 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2413 PartitionInfo
->HiddenSectors
= DiskEntry
->SectorAlignment
;
2414 PartitionInfo
->PartitionNumber
= PartitionNumber
;
2415 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2416 PartitionInfo
->BootIndicator
= FALSE
;
2417 PartitionInfo
->RecognizedPartition
= FALSE
;
2418 PartitionInfo
->RewritePartition
= TRUE
;
2420 PartEntry
->PartitionNumber
= PartitionNumber
;
2421 PartEntry
->PartitionIndex
= Index
;
2423 /* Fill the link entry of the previous partition table */
2424 if (LinkInfo
!= NULL
)
2426 LinkInfo
->StartingOffset
.QuadPart
= (PartEntry
->StartSector
.QuadPart
- DiskEntry
->SectorAlignment
) * DiskEntry
->BytesPerSector
;
2427 LinkInfo
->PartitionLength
.QuadPart
= (PartEntry
->StartSector
.QuadPart
+ DiskEntry
->SectorAlignment
) * DiskEntry
->BytesPerSector
;
2428 HiddenSectors64
.QuadPart
= PartEntry
->StartSector
.QuadPart
- DiskEntry
->SectorAlignment
- DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
;
2429 LinkInfo
->HiddenSectors
= HiddenSectors64
.LowPart
;
2430 LinkInfo
->PartitionNumber
= 0;
2431 LinkInfo
->PartitionType
= PARTITION_EXTENDED
;
2432 LinkInfo
->BootIndicator
= FALSE
;
2433 LinkInfo
->RecognizedPartition
= FALSE
;
2434 LinkInfo
->RewritePartition
= TRUE
;
2437 /* Save a pointer to the link entry of the current partition table */
2438 LinkInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
+ 1];
2444 ListEntry
= ListEntry
->Flink
;
2447 /* Wipe unused primary partition table entries */
2448 for (Index
= GetPrimaryPartitionCount(DiskEntry
); Index
< 4; Index
++)
2450 DPRINT1("Primary partition entry %lu\n", Index
);
2452 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2454 if (!IsEmptyLayoutEntry(PartitionInfo
))
2456 DPRINT1("Wiping primary partition entry %lu\n", Index
);
2458 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2459 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2460 PartitionInfo
->HiddenSectors
= 0;
2461 PartitionInfo
->PartitionNumber
= 0;
2462 PartitionInfo
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2463 PartitionInfo
->BootIndicator
= FALSE
;
2464 PartitionInfo
->RecognizedPartition
= FALSE
;
2465 PartitionInfo
->RewritePartition
= TRUE
;
2469 /* Wipe unused logical partition table entries */
2470 for (Index
= 4; Index
< DiskEntry
->LayoutBuffer
->PartitionCount
; Index
++)
2474 DPRINT1("Logical partition entry %lu\n", Index
);
2476 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2478 if (!IsEmptyLayoutEntry(PartitionInfo
))
2480 DPRINT1("Wiping partition entry %lu\n", Index
);
2482 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2483 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2484 PartitionInfo
->HiddenSectors
= 0;
2485 PartitionInfo
->PartitionNumber
= 0;
2486 PartitionInfo
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2487 PartitionInfo
->BootIndicator
= FALSE
;
2488 PartitionInfo
->RecognizedPartition
= FALSE
;
2489 PartitionInfo
->RewritePartition
= TRUE
;
2494 #ifdef DUMP_PARTITION_TABLE
2495 DumpPartitionTable(DiskEntry
);
2502 GetPrevUnpartitionedEntry(
2503 PDISKENTRY DiskEntry
,
2504 PPARTENTRY PartEntry
)
2506 PPARTENTRY PrevPartEntry
;
2507 PLIST_ENTRY ListHead
;
2509 if (PartEntry
->LogicalPartition
)
2510 ListHead
= &DiskEntry
->LogicalPartListHead
;
2512 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2514 if (PartEntry
->ListEntry
.Blink
!= ListHead
)
2516 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2519 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2520 return PrevPartEntry
;
2529 GetNextUnpartitionedEntry(
2530 PDISKENTRY DiskEntry
,
2531 PPARTENTRY PartEntry
)
2533 PPARTENTRY NextPartEntry
;
2534 PLIST_ENTRY ListHead
;
2536 if (PartEntry
->LogicalPartition
)
2537 ListHead
= &DiskEntry
->LogicalPartListHead
;
2539 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2541 if (PartEntry
->ListEntry
.Flink
!= ListHead
)
2543 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2546 if (NextPartEntry
->IsPartitioned
== FALSE
)
2547 return NextPartEntry
;
2555 CreatePrimaryPartition(
2557 ULONGLONG SectorCount
,
2560 PDISKENTRY DiskEntry
;
2561 PPARTENTRY PartEntry
;
2562 PPARTENTRY NewPartEntry
;
2564 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2567 List
->CurrentDisk
== NULL
||
2568 List
->CurrentPartition
== NULL
||
2569 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2574 DiskEntry
= List
->CurrentDisk
;
2575 PartEntry
= List
->CurrentPartition
;
2577 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2579 if (AutoCreate
== TRUE
||
2580 AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2582 DPRINT1("Convert existing partition entry\n");
2584 /* Convert current entry to 'new (unformatted)' */
2585 PartEntry
->IsPartitioned
= TRUE
;
2586 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2587 PartEntry
->FormatState
= Unformatted
;
2588 PartEntry
->AutoCreate
= AutoCreate
;
2589 PartEntry
->New
= TRUE
;
2590 PartEntry
->BootIndicator
= FALSE
;
2592 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2593 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2594 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2598 DPRINT1("Add new partition entry\n");
2600 /* Insert and initialize a new partition entry */
2601 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2604 if (NewPartEntry
== NULL
)
2607 /* Insert the new entry into the list */
2608 InsertTailList(&PartEntry
->ListEntry
,
2609 &NewPartEntry
->ListEntry
);
2611 NewPartEntry
->DiskEntry
= DiskEntry
;
2613 NewPartEntry
->IsPartitioned
= TRUE
;
2614 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2615 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2616 NewPartEntry
->StartSector
.QuadPart
;
2617 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2619 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2620 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2621 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2623 NewPartEntry
->New
= TRUE
;
2624 NewPartEntry
->FormatState
= Unformatted
;
2625 NewPartEntry
->BootIndicator
= FALSE
;
2627 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2628 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2631 UpdateDiskLayout(DiskEntry
);
2633 DiskEntry
->Dirty
= TRUE
;
2635 AssignDriveLetters(List
);
2641 AddLogicalDiskSpace(
2642 PDISKENTRY DiskEntry
)
2644 PPARTENTRY NewPartEntry
;
2646 DPRINT1("AddLogicalDiskSpace()\n");
2648 /* Create a partition table entry that represents the empty space in the container partition */
2649 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2652 if (NewPartEntry
== NULL
)
2655 NewPartEntry
->DiskEntry
= DiskEntry
;
2656 NewPartEntry
->LogicalPartition
= TRUE
;
2658 NewPartEntry
->IsPartitioned
= FALSE
;
2659 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
2660 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
2662 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2663 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2664 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2666 NewPartEntry
->FormatState
= Unformatted
;
2668 InsertTailList(&DiskEntry
->LogicalPartListHead
,
2669 &NewPartEntry
->ListEntry
);
2674 CreateExtendedPartition(
2676 ULONGLONG SectorCount
)
2678 PDISKENTRY DiskEntry
;
2679 PPARTENTRY PartEntry
;
2680 PPARTENTRY NewPartEntry
;
2682 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount
);
2685 List
->CurrentDisk
== NULL
||
2686 List
->CurrentPartition
== NULL
||
2687 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2692 DiskEntry
= List
->CurrentDisk
;
2693 PartEntry
= List
->CurrentPartition
;
2695 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2697 if (AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2699 DPRINT1("Convert existing partition entry\n");
2701 /* Convert current entry to 'new (unformatted)' */
2702 PartEntry
->IsPartitioned
= TRUE
;
2703 PartEntry
->FormatState
= Formatted
;
2704 PartEntry
->AutoCreate
= FALSE
;
2705 PartEntry
->New
= FALSE
;
2706 PartEntry
->BootIndicator
= FALSE
;
2708 if (PartEntry
->StartSector
.QuadPart
< 1450560)
2710 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2711 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
2715 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2716 PartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2719 DiskEntry
->ExtendedPartition
= PartEntry
;
2721 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2722 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2723 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2727 DPRINT1("Add new partition entry\n");
2729 /* Insert and initialize a new partition entry */
2730 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2733 if (NewPartEntry
== NULL
)
2736 /* Insert the new entry into the list */
2737 InsertTailList(&PartEntry
->ListEntry
,
2738 &NewPartEntry
->ListEntry
);
2740 NewPartEntry
->DiskEntry
= DiskEntry
;
2742 NewPartEntry
->IsPartitioned
= TRUE
;
2743 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2744 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2745 NewPartEntry
->StartSector
.QuadPart
;
2747 NewPartEntry
->New
= FALSE
;
2748 NewPartEntry
->FormatState
= Formatted
;
2749 NewPartEntry
->BootIndicator
= FALSE
;
2751 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2753 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2754 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2758 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2759 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2762 DiskEntry
->ExtendedPartition
= NewPartEntry
;
2764 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2765 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2767 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2768 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2769 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2772 AddLogicalDiskSpace(DiskEntry
);
2774 UpdateDiskLayout(DiskEntry
);
2776 DiskEntry
->Dirty
= TRUE
;
2778 AssignDriveLetters(List
);
2783 CreateLogicalPartition(
2785 ULONGLONG SectorCount
,
2788 PDISKENTRY DiskEntry
;
2789 PPARTENTRY PartEntry
;
2790 PPARTENTRY NewPartEntry
;
2792 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount
);
2795 List
->CurrentDisk
== NULL
||
2796 List
->CurrentPartition
== NULL
||
2797 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2802 DiskEntry
= List
->CurrentDisk
;
2803 PartEntry
= List
->CurrentPartition
;
2805 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2807 if (AutoCreate
== TRUE
||
2808 AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2810 DPRINT1("Convert existing partition entry\n");
2812 /* Convert current entry to 'new (unformatted)' */
2813 PartEntry
->IsPartitioned
= TRUE
;
2814 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2815 PartEntry
->FormatState
= Unformatted
;
2816 PartEntry
->AutoCreate
= FALSE
;
2817 PartEntry
->New
= TRUE
;
2818 PartEntry
->BootIndicator
= FALSE
;
2819 PartEntry
->LogicalPartition
= TRUE
;
2821 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2822 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2823 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2827 DPRINT1("Add new partition entry\n");
2829 /* Insert and initialize a new partition entry */
2830 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2833 if (NewPartEntry
== NULL
)
2836 /* Insert the new entry into the list */
2837 InsertTailList(&PartEntry
->ListEntry
,
2838 &NewPartEntry
->ListEntry
);
2840 NewPartEntry
->DiskEntry
= DiskEntry
;
2842 NewPartEntry
->IsPartitioned
= TRUE
;
2843 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2844 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2845 NewPartEntry
->StartSector
.QuadPart
;
2846 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2848 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2849 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2850 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2852 NewPartEntry
->New
= TRUE
;
2853 NewPartEntry
->FormatState
= Unformatted
;
2854 NewPartEntry
->BootIndicator
= FALSE
;
2855 NewPartEntry
->LogicalPartition
= TRUE
;
2857 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2858 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2861 UpdateDiskLayout(DiskEntry
);
2863 DiskEntry
->Dirty
= TRUE
;
2865 AssignDriveLetters(List
);
2870 DeleteCurrentPartition(
2873 PDISKENTRY DiskEntry
;
2874 PPARTENTRY PartEntry
;
2875 PPARTENTRY PrevPartEntry
;
2876 PPARTENTRY NextPartEntry
;
2877 PPARTENTRY LogicalPartEntry
;
2881 List
->CurrentDisk
== NULL
||
2882 List
->CurrentPartition
== NULL
||
2883 List
->CurrentPartition
->IsPartitioned
== FALSE
)
2888 DiskEntry
= List
->CurrentDisk
;
2889 PartEntry
= List
->CurrentPartition
;
2891 /* Delete all logical partiton entries if an extended partition will be deleted */
2892 if (DiskEntry
->ExtendedPartition
== PartEntry
)
2894 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
2896 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
2897 LogicalPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2899 RtlFreeHeap(ProcessHeap
, 0, LogicalPartEntry
);
2902 DiskEntry
->ExtendedPartition
= NULL
;
2905 /* Adjust unpartitioned disk space entries */
2907 /* Get pointer to previous and next unpartitioned entries */
2908 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
,
2911 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
,
2914 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2916 /* Merge previous, current and next unpartitioned entry */
2918 /* Adjust the previous entries length */
2919 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
2921 /* Remove the current entry */
2922 RemoveEntryList(&PartEntry
->ListEntry
);
2923 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2925 /* Remove the next entry */
2926 RemoveEntryList (&NextPartEntry
->ListEntry
);
2927 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
2929 /* Update current partition */
2930 List
->CurrentPartition
= PrevPartEntry
;
2932 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2934 /* Merge current and previous unpartitioned entry */
2936 /* Adjust the previous entries length */
2937 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2939 /* Remove the current entry */
2940 RemoveEntryList(&PartEntry
->ListEntry
);
2941 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2943 /* Update current partition */
2944 List
->CurrentPartition
= PrevPartEntry
;
2946 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2948 /* Merge current and next unpartitioned entry */
2950 /* Adjust the next entries offset and length */
2951 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2952 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2954 /* Remove the current entry */
2955 RemoveEntryList(&PartEntry
->ListEntry
);
2956 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2958 /* Update current partition */
2959 List
->CurrentPartition
= NextPartEntry
;
2963 /* Nothing to merge but change current entry */
2964 PartEntry
->IsPartitioned
= FALSE
;
2965 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2966 PartEntry
->FormatState
= Unformatted
;
2967 PartEntry
->DriveLetter
= 0;
2970 UpdateDiskLayout(DiskEntry
);
2972 DiskEntry
->Dirty
= TRUE
;
2974 AssignDriveLetters(List
);
2979 CheckActiveBootPartition(
2982 PDISKENTRY DiskEntry
;
2983 PPARTENTRY PartEntry
;
2984 PLIST_ENTRY ListEntry
;
2986 /* Check for empty disk list */
2987 if (IsListEmpty (&List
->DiskListHead
))
2989 List
->BootDisk
= NULL
;
2990 List
->BootPartition
= NULL
;
2995 if (List
->BootDisk
!= NULL
&&
2996 List
->BootPartition
!= NULL
)
2998 /* We already have an active boot partition */
3003 /* Choose the currently selected disk */
3004 DiskEntry
= List
->CurrentDisk
;
3006 /* Check for empty partition list */
3007 if (IsListEmpty (&DiskEntry
->PrimaryPartListHead
))
3009 List
->BootDisk
= NULL
;
3010 List
->BootPartition
= NULL
;
3014 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
3018 /* Set active boot partition */
3019 if ((DiskEntry
->NewDisk
== TRUE
) ||
3020 (PartEntry
->BootIndicator
== FALSE
))
3022 PartEntry
->BootIndicator
= TRUE
;
3023 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].BootIndicator
= TRUE
;
3024 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
3025 DiskEntry
->Dirty
= TRUE
;
3027 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
3028 List
->BootDisk
= DiskEntry
;
3029 List
->BootPartition
= PartEntry
;
3034 /* Disk is not new, scan all partitions to find a bootable one */
3035 List
->BootDisk
= NULL
;
3036 List
->BootPartition
= NULL
;
3038 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
3039 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
3041 PartEntry
= CONTAINING_RECORD(ListEntry
,
3045 /* Check if it is partitioned */
3046 if (PartEntry
->IsPartitioned
)
3048 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
&&
3049 PartEntry
->BootIndicator
)
3051 /* Yes, we found it */
3052 List
->BootDisk
= DiskEntry
;
3053 List
->BootPartition
= PartEntry
;
3055 DPRINT("Found bootable partition disk %d, drive letter %c\n",
3056 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
);
3061 /* Go to the next one */
3062 ListEntry
= ListEntry
->Flink
;
3071 IN PDISKENTRY DiskEntry
)
3073 WCHAR DstPath
[MAX_PATH
];
3074 OBJECT_ATTRIBUTES ObjectAttributes
;
3075 IO_STATUS_BLOCK Iosb
;
3076 UNICODE_STRING Name
;
3078 HANDLE FileHandle
= NULL
;
3081 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
3084 L
"\\Device\\Harddisk%d\\Partition0",
3085 DiskEntry
->DiskNumber
);
3086 RtlInitUnicodeString(&Name
,
3088 InitializeObjectAttributes(&ObjectAttributes
,
3094 Status
= NtOpenFile(&FileHandle
,
3095 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
3099 FILE_SYNCHRONOUS_IO_NONALERT
);
3100 if (!NT_SUCCESS(Status
))
3102 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
3106 #ifdef DUMP_PARTITION_TABLE
3107 DumpPartitionTable(DiskEntry
);
3110 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
3111 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
3112 Status
= NtDeviceIoControlFile(FileHandle
,
3117 IOCTL_DISK_SET_DRIVE_LAYOUT
,
3118 DiskEntry
->LayoutBuffer
,
3122 if (!NT_SUCCESS(Status
))
3124 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
3127 if (FileHandle
!= NULL
)
3128 NtClose(FileHandle
);
3135 WritePartitionsToDisk(
3139 PDISKENTRY DiskEntry
;
3144 Entry
= List
->DiskListHead
.Flink
;
3145 while (Entry
!= &List
->DiskListHead
)
3147 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
3149 if (DiskEntry
->Dirty
== TRUE
)
3151 WritePartitions(List
, DiskEntry
);
3152 DiskEntry
->Dirty
= FALSE
;
3155 Entry
= Entry
->Flink
;
3163 SetMountedDeviceValues(
3166 PLIST_ENTRY Entry1
, Entry2
;
3167 PDISKENTRY DiskEntry
;
3168 PPARTENTRY PartEntry
;
3169 LARGE_INTEGER StartingOffset
;
3176 Entry1
= List
->DiskListHead
.Flink
;
3177 while (Entry1
!= &List
->DiskListHead
)
3179 DiskEntry
= CONTAINING_RECORD(Entry1
,
3183 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3184 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3186 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3187 if (PartEntry
->IsPartitioned
)
3189 if (PartEntry
->DriveLetter
)
3191 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
3192 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
3193 DiskEntry
->LayoutBuffer
->Signature
,
3201 Entry2
= Entry2
->Flink
;
3204 Entry1
= Entry1
->Flink
;
3212 PrimaryPartitionCreationChecks(
3215 PDISKENTRY DiskEntry
;
3216 PPARTENTRY PartEntry
;
3218 DiskEntry
= List
->CurrentDisk
;
3219 PartEntry
= List
->CurrentPartition
;
3221 /* Fail if partition is already in use */
3222 if (PartEntry
->IsPartitioned
== TRUE
)
3223 return ERROR_NEW_PARTITION
;
3225 /* Fail if there are more than 4 partitions in the list */
3226 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3227 return ERROR_PARTITION_TABLE_FULL
;
3229 return ERROR_SUCCESS
;
3234 ExtendedPartitionCreationChecks(
3237 PDISKENTRY DiskEntry
;
3238 PPARTENTRY PartEntry
;
3240 DiskEntry
= List
->CurrentDisk
;
3241 PartEntry
= List
->CurrentPartition
;
3243 /* Fail if partition is already in use */
3244 if (PartEntry
->IsPartitioned
== TRUE
)
3245 return ERROR_NEW_PARTITION
;
3247 /* Fail if there are more than 4 partitions in the list */
3248 if (GetPrimaryPartitionCount(DiskEntry
) > 4)
3249 return ERROR_PARTITION_TABLE_FULL
;
3251 /* Fail if there is another extended partition in the list */
3252 if (DiskEntry
->ExtendedPartition
!= NULL
)
3253 return ERROR_ONLY_ONE_EXTENDED
;
3255 return ERROR_SUCCESS
;
3260 LogicalPartitionCreationChecks(
3263 // PDISKENTRY DiskEntry;
3264 PPARTENTRY PartEntry
;
3266 // DiskEntry = List->CurrentDisk;
3267 PartEntry
= List
->CurrentPartition
;
3269 /* Fail if partition is already in use */
3270 if (PartEntry
->IsPartitioned
== TRUE
)
3271 return ERROR_NEW_PARTITION
;
3273 return ERROR_SUCCESS
;
3278 GetNextUnformattedPartition(
3280 OUT PDISKENTRY
*pDiskEntry
,
3281 OUT PPARTENTRY
*pPartEntry
)
3283 PLIST_ENTRY Entry1
, Entry2
;
3284 PDISKENTRY DiskEntry
;
3285 PPARTENTRY PartEntry
;
3287 Entry1
= List
->DiskListHead
.Flink
;
3288 while (Entry1
!= &List
->DiskListHead
)
3290 DiskEntry
= CONTAINING_RECORD(Entry1
,
3294 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3295 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3297 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3298 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3300 *pDiskEntry
= DiskEntry
;
3301 *pPartEntry
= PartEntry
;
3305 Entry2
= Entry2
->Flink
;
3308 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3309 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3311 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3312 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3314 *pDiskEntry
= DiskEntry
;
3315 *pPartEntry
= PartEntry
;
3319 Entry2
= Entry2
->Flink
;
3322 Entry1
= Entry1
->Flink
;
3333 GetNextUncheckedPartition(
3335 OUT PDISKENTRY
*pDiskEntry
,
3336 OUT PPARTENTRY
*pPartEntry
)
3338 PLIST_ENTRY Entry1
, Entry2
;
3339 PDISKENTRY DiskEntry
;
3340 PPARTENTRY PartEntry
;
3342 Entry1
= List
->DiskListHead
.Flink
;
3343 while (Entry1
!= &List
->DiskListHead
)
3345 DiskEntry
= CONTAINING_RECORD(Entry1
,
3349 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3350 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3352 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3353 if (PartEntry
->NeedsCheck
== TRUE
)
3355 *pDiskEntry
= DiskEntry
;
3356 *pPartEntry
= PartEntry
;
3360 Entry2
= Entry2
->Flink
;
3363 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3364 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3366 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3367 if (PartEntry
->NeedsCheck
== TRUE
)
3369 *pDiskEntry
= DiskEntry
;
3370 *pPartEntry
= PartEntry
;
3374 Entry2
= Entry2
->Flink
;
3377 Entry1
= Entry1
->Flink
;