2 * PROJECT: ReactOS Setup Library
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Partition list functions
5 * COPYRIGHT: Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net)
17 //#define DUMP_PARTITION_TABLE
21 typedef struct _REG_DISK_MOUNT_INFO
24 LARGE_INTEGER StartingOffset
;
25 } REG_DISK_MOUNT_INFO
, *PREG_DISK_MOUNT_INFO
;
30 /* FUNCTIONS ****************************************************************/
32 #ifdef DUMP_PARTITION_TABLE
38 PPARTITION_INFORMATION PartitionInfo
;
42 DbgPrint("Index Start Length Hidden Nr Type Boot RW\n");
43 DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
45 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
47 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
48 DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n",
50 PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
,
51 PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
,
52 PartitionInfo
->HiddenSectors
,
53 PartitionInfo
->PartitionNumber
,
54 PartitionInfo
->PartitionType
,
55 PartitionInfo
->BootIndicator
? '*': ' ',
56 PartitionInfo
->RewritePartition
? 'Y': 'N');
71 Temp
= Value
/ Alignment
;
73 return Temp
* Alignment
;
81 ULONGLONG Temp
, Result
;
83 Temp
= Value
/ Alignment
;
85 Result
= Temp
* Alignment
;
86 if (Value
% Alignment
)
94 IN ULONGLONG Dividend
,
97 return (Dividend
+ Divisor
/ 2) / Divisor
;
104 IN PDISKENTRY DiskEntry
)
106 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
110 RtlInitUnicodeString(&DiskEntry
->DriverName
, NULL
);
112 RtlStringCchPrintfW(KeyName
, ARRAYSIZE(KeyName
),
113 L
"\\Scsi\\Scsi Port %hu",
116 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
118 QueryTable
[0].Name
= L
"Driver";
119 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
120 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
122 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
127 if (!NT_SUCCESS(Status
))
129 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
138 PDISKENTRY DiskEntry
;
139 PPARTENTRY PartEntry
;
146 /* Assign drive letters to primary partitions */
147 Entry1
= List
->DiskListHead
.Flink
;
148 while (Entry1
!= &List
->DiskListHead
)
150 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
152 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
153 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
155 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
157 PartEntry
->DriveLetter
= 0;
159 if (PartEntry
->IsPartitioned
&&
160 !IsContainerPartition(PartEntry
->PartitionType
))
162 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
163 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
164 PartEntry
->SectorCount
.QuadPart
!= 0LL))
168 PartEntry
->DriveLetter
= Letter
;
174 Entry2
= Entry2
->Flink
;
177 Entry1
= Entry1
->Flink
;
180 /* Assign drive letters to logical drives */
181 Entry1
= List
->DiskListHead
.Flink
;
182 while (Entry1
!= &List
->DiskListHead
)
184 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
186 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
187 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
189 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
191 PartEntry
->DriveLetter
= 0;
193 if (PartEntry
->IsPartitioned
)
195 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
196 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
197 PartEntry
->SectorCount
.QuadPart
!= 0LL))
201 PartEntry
->DriveLetter
= Letter
;
207 Entry2
= Entry2
->Flink
;
210 Entry1
= Entry1
->Flink
;
216 DiskIdentifierQueryRoutine(
224 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
225 UNICODE_STRING NameU
;
227 if (ValueType
== REG_SZ
&&
228 ValueLength
== 20 * sizeof(WCHAR
))
230 NameU
.Buffer
= (PWCHAR
)ValueData
;
231 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
232 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
234 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
235 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
237 return STATUS_SUCCESS
;
240 return STATUS_UNSUCCESSFUL
;
245 DiskConfigurationDataQueryRoutine(
253 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
254 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
255 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
258 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
259 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
260 return STATUS_UNSUCCESSFUL
;
262 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
264 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
266 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
267 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
268 return STATUS_UNSUCCESSFUL
;
271 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
273 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
274 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
277 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
278 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
280 return STATUS_SUCCESS
;
283 return STATUS_UNSUCCESSFUL
;
288 SystemConfigurationDataQueryRoutine(
296 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
297 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
300 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
301 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
302 return STATUS_UNSUCCESSFUL
;
304 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
306 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
308 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
309 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
310 return STATUS_UNSUCCESSFUL
;
313 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
315 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
316 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
319 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*)RtlAllocateHeap(ProcessHeap
, 0,
320 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
321 if (*Int13Drives
== NULL
)
322 return STATUS_NO_MEMORY
;
325 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
326 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
327 return STATUS_SUCCESS
;
330 return STATUS_UNSUCCESSFUL
;
334 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
337 EnumerateBiosDiskEntries(
338 IN PPARTLIST PartList
)
340 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
345 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
346 PBIOSDISKENTRY BiosDiskEntry
;
348 memset(QueryTable
, 0, sizeof(QueryTable
));
350 QueryTable
[1].Name
= L
"Configuration Data";
351 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
353 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
354 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
358 if (!NT_SUCCESS(Status
))
360 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
367 RtlStringCchPrintfW(Name
, ARRAYSIZE(Name
),
369 ROOT_NAME
, AdapterCount
);
370 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
375 if (!NT_SUCCESS(Status
))
380 RtlStringCchPrintfW(Name
, ARRAYSIZE(Name
),
381 L
"%s\\%lu\\DiskController",
382 ROOT_NAME
, AdapterCount
);
383 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
388 if (NT_SUCCESS(Status
))
392 RtlStringCchPrintfW(Name
, ARRAYSIZE(Name
),
393 L
"%s\\%lu\\DiskController\\0",
394 ROOT_NAME
, AdapterCount
);
395 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
400 if (!NT_SUCCESS(Status
))
402 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
406 RtlStringCchPrintfW(Name
, ARRAYSIZE(Name
),
407 L
"%s\\%lu\\DiskController\\0\\DiskPeripheral",
408 ROOT_NAME
, AdapterCount
);
409 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
414 if (NT_SUCCESS(Status
))
416 QueryTable
[0].Name
= L
"Identifier";
417 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
418 QueryTable
[1].Name
= L
"Configuration Data";
419 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
424 BiosDiskEntry
= (BIOSDISKENTRY
*)RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
425 if (BiosDiskEntry
== NULL
)
430 RtlStringCchPrintfW(Name
, ARRAYSIZE(Name
),
431 L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu",
432 ROOT_NAME
, AdapterCount
, DiskCount
);
433 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
436 (PVOID
)BiosDiskEntry
,
438 if (!NT_SUCCESS(Status
))
440 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
444 BiosDiskEntry
->DiskNumber
= DiskCount
;
445 BiosDiskEntry
->Recognized
= FALSE
;
447 if (DiskCount
< Int13Drives
[0].NumberDrives
)
449 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
453 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
456 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
458 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
459 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
460 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
461 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
462 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
463 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
464 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
465 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
466 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
467 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
468 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
474 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
482 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
489 IN PDISKENTRY DiskEntry
,
490 IN ULONG PartitionIndex
,
491 IN BOOLEAN LogicalPartition
)
493 PPARTITION_INFORMATION PartitionInfo
;
494 PPARTENTRY PartEntry
;
496 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[PartitionIndex
];
498 if (PartitionInfo
->PartitionType
== PARTITION_ENTRY_UNUSED
||
499 ((LogicalPartition
!= FALSE
) && IsContainerPartition(PartitionInfo
->PartitionType
)))
504 PartEntry
= RtlAllocateHeap(ProcessHeap
,
507 if (PartEntry
== NULL
)
510 PartEntry
->DiskEntry
= DiskEntry
;
512 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
513 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
515 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
516 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
517 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
519 PartEntry
->LogicalPartition
= LogicalPartition
;
520 PartEntry
->IsPartitioned
= TRUE
;
521 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
522 PartEntry
->PartitionIndex
= PartitionIndex
;
524 if (IsContainerPartition(PartEntry
->PartitionType
))
526 PartEntry
->FormatState
= Unformatted
;
527 PartEntry
->FileSystem
= NULL
;
529 if (LogicalPartition
== FALSE
&& DiskEntry
->ExtendedPartition
== NULL
)
530 DiskEntry
->ExtendedPartition
= PartEntry
;
532 else if (IsRecognizedPartition(PartEntry
->PartitionType
))
534 PartEntry
->FileSystem
= GetFileSystem(PartEntry
);
535 if (PartEntry
->FileSystem
)
536 PartEntry
->FormatState
= Preformatted
;
538 PartEntry
->FormatState
= Unformatted
;
539 // PartEntry->FormatState = UnknownFormat;
543 /* Unknown partition, hence unknown partition format (may or may not be actually formatted) */
544 PartEntry
->FormatState
= UnknownFormat
;
547 if (LogicalPartition
)
548 InsertTailList(&DiskEntry
->LogicalPartListHead
,
549 &PartEntry
->ListEntry
);
551 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
552 &PartEntry
->ListEntry
);
557 ScanForUnpartitionedDiskSpace(
558 IN PDISKENTRY DiskEntry
)
560 ULONGLONG LastStartSector
;
561 ULONGLONG LastSectorCount
;
562 ULONGLONG LastUnusedSectorCount
;
563 PPARTENTRY PartEntry
;
564 PPARTENTRY NewPartEntry
;
567 DPRINT("ScanForUnpartitionedDiskSpace()\n");
569 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
571 DPRINT1("No primary partition!\n");
573 /* Create a partition entry that represents the empty disk */
574 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
577 if (NewPartEntry
== NULL
)
580 NewPartEntry
->DiskEntry
= DiskEntry
;
582 NewPartEntry
->IsPartitioned
= FALSE
;
583 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorAlignment
;
584 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
585 NewPartEntry
->StartSector
.QuadPart
;
587 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
588 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
589 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
591 NewPartEntry
->FormatState
= Unformatted
;
592 NewPartEntry
->FileSystem
= NULL
;
594 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
595 &NewPartEntry
->ListEntry
);
600 /* Start partition at head 1, cylinder 0 */
601 LastStartSector
= DiskEntry
->SectorAlignment
;
602 LastSectorCount
= 0ULL;
603 LastUnusedSectorCount
= 0ULL;
605 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
606 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
608 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
610 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
611 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
613 LastUnusedSectorCount
=
614 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
616 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
617 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
619 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
621 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
624 if (NewPartEntry
== NULL
)
627 NewPartEntry
->DiskEntry
= DiskEntry
;
629 NewPartEntry
->IsPartitioned
= FALSE
;
630 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
631 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
632 NewPartEntry
->StartSector
.QuadPart
;
634 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
635 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
636 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
638 NewPartEntry
->FormatState
= Unformatted
;
639 NewPartEntry
->FileSystem
= NULL
;
641 /* Insert the table into the list */
642 InsertTailList(&PartEntry
->ListEntry
,
643 &NewPartEntry
->ListEntry
);
646 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
647 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
650 Entry
= Entry
->Flink
;
653 /* Check for trailing unpartitioned disk space */
654 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
656 LastUnusedSectorCount
= AlignDown(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
658 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
660 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
662 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
665 if (NewPartEntry
== NULL
)
668 NewPartEntry
->DiskEntry
= DiskEntry
;
670 NewPartEntry
->IsPartitioned
= FALSE
;
671 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
672 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
673 NewPartEntry
->StartSector
.QuadPart
;
675 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
676 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
677 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
679 NewPartEntry
->FormatState
= Unformatted
;
680 NewPartEntry
->FileSystem
= NULL
;
682 /* Append the table to the list */
683 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
684 &NewPartEntry
->ListEntry
);
688 if (DiskEntry
->ExtendedPartition
!= NULL
)
690 if (IsListEmpty(&DiskEntry
->LogicalPartListHead
))
692 DPRINT1("No logical partition!\n");
694 /* Create a partition entry that represents the empty extended partition */
695 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
698 if (NewPartEntry
== NULL
)
701 NewPartEntry
->DiskEntry
= DiskEntry
;
702 NewPartEntry
->LogicalPartition
= TRUE
;
704 NewPartEntry
->IsPartitioned
= FALSE
;
705 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
706 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
708 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
709 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
710 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
712 NewPartEntry
->FormatState
= Unformatted
;
713 NewPartEntry
->FileSystem
= NULL
;
715 InsertTailList(&DiskEntry
->LogicalPartListHead
,
716 &NewPartEntry
->ListEntry
);
721 /* Start partition at head 1, cylinder 0 */
722 LastStartSector
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
723 LastSectorCount
= 0ULL;
724 LastUnusedSectorCount
= 0ULL;
726 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
727 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
729 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
731 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
732 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
734 LastUnusedSectorCount
=
735 PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
- (LastStartSector
+ LastSectorCount
);
737 if ((PartEntry
->StartSector
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
) > (LastStartSector
+ LastSectorCount
) &&
738 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
740 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
742 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
745 if (NewPartEntry
== NULL
)
748 NewPartEntry
->DiskEntry
= DiskEntry
;
749 NewPartEntry
->LogicalPartition
= TRUE
;
751 NewPartEntry
->IsPartitioned
= FALSE
;
752 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
753 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
754 NewPartEntry
->StartSector
.QuadPart
;
756 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
757 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
758 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
760 NewPartEntry
->FormatState
= Unformatted
;
761 NewPartEntry
->FileSystem
= NULL
;
763 /* Insert the table into the list */
764 InsertTailList(&PartEntry
->ListEntry
,
765 &NewPartEntry
->ListEntry
);
768 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
769 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
772 Entry
= Entry
->Flink
;
775 /* Check for trailing unpartitioned disk space */
776 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
)
778 LastUnusedSectorCount
= AlignDown(DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
780 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
782 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
784 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
787 if (NewPartEntry
== NULL
)
790 NewPartEntry
->DiskEntry
= DiskEntry
;
791 NewPartEntry
->LogicalPartition
= TRUE
;
793 NewPartEntry
->IsPartitioned
= FALSE
;
794 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
795 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
796 NewPartEntry
->StartSector
.QuadPart
;
798 DPRINT("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
799 DPRINT("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
800 DPRINT("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
802 NewPartEntry
->FormatState
= Unformatted
;
803 NewPartEntry
->FileSystem
= NULL
;
805 /* Append the table to the list */
806 InsertTailList(&DiskEntry
->LogicalPartListHead
,
807 &NewPartEntry
->ListEntry
);
812 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
819 IN PDISKENTRY DiskEntry
)
821 LARGE_INTEGER SystemTime
;
822 TIME_FIELDS TimeFields
;
824 PDISKENTRY DiskEntry2
;
827 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
831 NtQuerySystemTime(&SystemTime
);
832 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
834 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
835 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
836 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
837 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
839 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
844 /* Check if the signature already exist */
846 * Check also signatures from disks, which are
847 * not visible (bootable) by the bios.
849 Entry2
= List
->DiskListHead
.Flink
;
850 while (Entry2
!= &List
->DiskListHead
)
852 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
854 if (DiskEntry
!= DiskEntry2
&&
855 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
858 Entry2
= Entry2
->Flink
;
861 if (Entry2
== &List
->DiskListHead
)
868 UpdateDiskSignatures(
872 PDISKENTRY DiskEntry
;
874 /* Print partition lines */
875 Entry
= List
->DiskListHead
.Flink
;
876 while (Entry
!= &List
->DiskListHead
)
878 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
880 if (DiskEntry
->LayoutBuffer
&&
881 DiskEntry
->LayoutBuffer
->Signature
== 0)
883 SetDiskSignature(List
, DiskEntry
);
884 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
887 Entry
= Entry
->Flink
;
894 IN HANDLE FileHandle
,
898 DISK_GEOMETRY DiskGeometry
;
899 SCSI_ADDRESS ScsiAddress
;
900 PDISKENTRY DiskEntry
;
901 IO_STATUS_BLOCK Iosb
;
903 PPARTITION_SECTOR Mbr
;
905 LARGE_INTEGER FileOffset
;
906 WCHAR Identifier
[20];
910 PLIST_ENTRY ListEntry
;
911 PBIOSDISKENTRY BiosDiskEntry
;
912 ULONG LayoutBufferSize
;
913 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
915 Status
= NtDeviceIoControlFile(FileHandle
,
920 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
924 sizeof(DISK_GEOMETRY
));
925 if (!NT_SUCCESS(Status
))
928 if (DiskGeometry
.MediaType
!= FixedMedia
&&
929 DiskGeometry
.MediaType
!= RemovableMedia
)
934 Status
= NtDeviceIoControlFile(FileHandle
,
939 IOCTL_SCSI_GET_ADDRESS
,
943 sizeof(SCSI_ADDRESS
));
944 if (!NT_SUCCESS(Status
))
948 * Check whether the disk is initialized, by looking at its MBR.
949 * NOTE that this must be generalized to GPT disks as well!
952 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
954 DiskGeometry
.BytesPerSector
);
958 FileOffset
.QuadPart
= 0;
959 Status
= NtReadFile(FileHandle
,
965 DiskGeometry
.BytesPerSector
,
968 if (!NT_SUCCESS(Status
))
970 RtlFreeHeap(ProcessHeap
, 0, Mbr
);
971 DPRINT1("NtReadFile failed, status=%x\n", Status
);
974 Signature
= Mbr
->Signature
;
976 /* Calculate the MBR checksum */
978 Buffer
= (PULONG
)Mbr
;
979 for (i
= 0; i
< 128; i
++)
981 Checksum
+= Buffer
[i
];
983 Checksum
= ~Checksum
+ 1;
985 RtlStringCchPrintfW(Identifier
, ARRAYSIZE(Identifier
),
986 L
"%08x-%08x-A", Checksum
, Signature
);
987 DPRINT("Identifier: %S\n", Identifier
);
989 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
992 if (DiskEntry
== NULL
)
997 // DiskEntry->Checksum = Checksum;
998 // DiskEntry->Signature = Signature;
999 DiskEntry
->BiosFound
= FALSE
;
1002 * Check if this disk has a valid MBR: verify its signature,
1003 * and whether its two first bytes are a valid instruction
1004 * (related to this, see IsThereAValidBootSector() in partlist.c).
1006 if (Mbr
->Magic
!= 0xaa55 || (*(PUSHORT
)Mbr
->BootCode
) == 0x0000)
1007 DiskEntry
->NoMbr
= TRUE
;
1009 DiskEntry
->NoMbr
= FALSE
;
1011 /* Free the MBR sector buffer */
1012 RtlFreeHeap(ProcessHeap
, 0, Mbr
);
1015 ListEntry
= List
->BiosDiskListHead
.Flink
;
1016 while (ListEntry
!= &List
->BiosDiskListHead
)
1018 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
1020 * Compare the size from bios and the reported size from driver.
1021 * If we have more than one disk with a zero or with the same signature
1022 * we must create new signatures and reboot. After the reboot,
1023 * it is possible to identify the disks.
1025 if (BiosDiskEntry
->Signature
== Signature
&&
1026 BiosDiskEntry
->Checksum
== Checksum
&&
1027 !BiosDiskEntry
->Recognized
)
1029 if (!DiskEntry
->BiosFound
)
1031 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
1032 DiskEntry
->BiosFound
= TRUE
;
1033 BiosDiskEntry
->Recognized
= TRUE
;
1039 ListEntry
= ListEntry
->Flink
;
1042 if (!DiskEntry
->BiosFound
)
1045 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1048 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
1052 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
1053 InitializeListHead(&DiskEntry
->LogicalPartListHead
);
1055 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
1056 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
1057 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
1058 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
1060 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
1061 DPRINT("TracksPerCylinder %lu\n", DiskEntry
->TracksPerCylinder
);
1062 DPRINT("SectorsPerTrack %lu\n", DiskEntry
->SectorsPerTrack
);
1063 DPRINT("BytesPerSector %lu\n", DiskEntry
->BytesPerSector
);
1065 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
1066 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1067 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1069 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1070 DiskEntry
->CylinderAlignment
= DiskGeometry
.TracksPerCylinder
*
1071 DiskGeometry
.SectorsPerTrack
;
1073 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
.QuadPart
);
1074 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1076 DiskEntry
->DiskNumber
= DiskNumber
;
1077 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1078 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1079 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1081 GetDriverName(DiskEntry
);
1083 * Actually it would be more correct somehow to use:
1085 * OBJECT_NAME_INFORMATION NameInfo; // ObjectNameInfo;
1086 * ULONG ReturnedLength;
1088 * Status = NtQueryObject(SomeHandleToTheDisk,
1089 * ObjectNameInformation,
1095 * See examples in https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/ntoskrnl/io/iomgr/error.c;hb=2f3a93ee9cec8322a86bf74b356f1ad83fc912dc#l267
1098 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1100 /* Allocate a layout buffer with 4 partition entries first */
1101 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1102 ((4 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1103 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1106 if (DiskEntry
->LayoutBuffer
== NULL
)
1108 DPRINT1("Failed to allocate the disk layout buffer!\n");
1114 DPRINT1("Buffer size: %lu\n", LayoutBufferSize
);
1115 Status
= NtDeviceIoControlFile(FileHandle
,
1120 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1123 DiskEntry
->LayoutBuffer
,
1125 if (NT_SUCCESS(Status
))
1128 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
1130 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status
);
1134 LayoutBufferSize
+= 4 * sizeof(PARTITION_INFORMATION
);
1135 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
1137 DiskEntry
->LayoutBuffer
,
1139 if (NewLayoutBuffer
== NULL
)
1141 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1145 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
1148 DPRINT1("PartitionCount: %lu\n", DiskEntry
->LayoutBuffer
->PartitionCount
);
1150 #ifdef DUMP_PARTITION_TABLE
1151 DumpPartitionTable(DiskEntry
);
1154 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
!= 0 &&
1155 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionLength
.QuadPart
!= 0 &&
1156 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1158 if ((DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
) % DiskEntry
->SectorsPerTrack
== 0)
1160 DPRINT("Use %lu Sector alignment!\n", DiskEntry
->SectorsPerTrack
);
1162 else if (DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
% (1024 * 1024) == 0)
1164 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1168 DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry
->LayoutBuffer
->PartitionEntry
[0].StartingOffset
.QuadPart
);
1173 DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry
->BytesPerSector
);
1177 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1179 DiskEntry
->NewDisk
= TRUE
;
1180 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1182 for (i
= 0; i
< 4; i
++)
1183 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1187 for (i
= 0; i
< 4; i
++)
1189 AddPartitionToDisk(DiskNumber
, DiskEntry
, i
, FALSE
);
1192 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
+= 4)
1194 AddPartitionToDisk(DiskNumber
, DiskEntry
, i
, TRUE
);
1198 ScanForUnpartitionedDiskSpace(DiskEntry
);
1202 CreatePartitionList(VOID
)
1205 OBJECT_ATTRIBUTES ObjectAttributes
;
1206 SYSTEM_DEVICE_INFORMATION Sdi
;
1207 IO_STATUS_BLOCK Iosb
;
1211 WCHAR Buffer
[MAX_PATH
];
1212 UNICODE_STRING Name
;
1215 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1221 List
->CurrentDisk
= NULL
;
1222 List
->CurrentPartition
= NULL
;
1224 List
->SystemPartition
= NULL
;
1225 List
->OriginalSystemPartition
= NULL
;
1227 InitializeListHead(&List
->DiskListHead
);
1228 InitializeListHead(&List
->BiosDiskListHead
);
1230 EnumerateBiosDiskEntries(List
);
1232 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1236 if (!NT_SUCCESS(Status
))
1238 DPRINT1("NtQuerySystemInformation() failed, Status 0x%08lx", Status
);
1239 RtlFreeHeap(ProcessHeap
, 0, List
);
1243 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1245 RtlStringCchPrintfW(Buffer
, ARRAYSIZE(Buffer
),
1246 L
"\\Device\\Harddisk%lu\\Partition0",
1248 RtlInitUnicodeString(&Name
, Buffer
);
1250 InitializeObjectAttributes(&ObjectAttributes
,
1256 Status
= NtOpenFile(&FileHandle
,
1257 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1261 FILE_SYNCHRONOUS_IO_NONALERT
);
1262 if (NT_SUCCESS(Status
))
1264 AddDiskToList(FileHandle
, DiskNumber
, List
);
1265 NtClose(FileHandle
);
1269 UpdateDiskSignatures(List
);
1271 AssignDriveLetters(List
);
1273 /* Search for first usable disk and partition */
1274 if (IsListEmpty(&List
->DiskListHead
))
1276 List
->CurrentDisk
= NULL
;
1277 List
->CurrentPartition
= NULL
;
1281 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1285 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1287 List
->CurrentPartition
= NULL
;
1291 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1301 DestroyPartitionList(
1304 PDISKENTRY DiskEntry
;
1305 PBIOSDISKENTRY BiosDiskEntry
;
1306 PPARTENTRY PartEntry
;
1309 /* Release disk and partition info */
1310 while (!IsListEmpty(&List
->DiskListHead
))
1312 Entry
= RemoveHeadList(&List
->DiskListHead
);
1313 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1315 /* Release driver name */
1316 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1318 /* Release primary partition list */
1319 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1321 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1322 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1324 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1327 /* Release logical partition list */
1328 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
1330 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
1331 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1333 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1336 /* Release layout buffer */
1337 if (DiskEntry
->LayoutBuffer
!= NULL
)
1338 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1340 /* Release disk entry */
1341 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1344 /* Release the bios disk info */
1345 while (!IsListEmpty(&List
->BiosDiskListHead
))
1347 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1348 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1350 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1353 /* Release list head */
1354 RtlFreeHeap(ProcessHeap
, 0, List
);
1358 GetDiskByBiosNumber(
1360 IN ULONG BiosDiskNumber
)
1362 PDISKENTRY DiskEntry
;
1365 /* Loop over the disks and find the correct one */
1366 Entry
= List
->DiskListHead
.Flink
;
1367 while (Entry
!= &List
->DiskListHead
)
1369 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1370 Entry
= Entry
->Flink
;
1372 if (DiskEntry
->BiosDiskNumber
== BiosDiskNumber
)
1379 /* Disk not found, stop there */
1386 IN ULONG DiskNumber
)
1388 PDISKENTRY DiskEntry
;
1391 /* Loop over the disks and find the correct one */
1392 Entry
= List
->DiskListHead
.Flink
;
1393 while (Entry
!= &List
->DiskListHead
)
1395 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1396 Entry
= Entry
->Flink
;
1398 if (DiskEntry
->DiskNumber
== DiskNumber
)
1405 /* Disk not found, stop there */
1416 PDISKENTRY DiskEntry
;
1419 /* Loop over the disks and find the correct one */
1420 Entry
= List
->DiskListHead
.Flink
;
1421 while (Entry
!= &List
->DiskListHead
)
1423 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1424 Entry
= Entry
->Flink
;
1426 if (DiskEntry
->Port
== Port
&&
1427 DiskEntry
->Bus
== Bus
&&
1428 DiskEntry
->Id
== Id
)
1435 /* Disk not found, stop there */
1444 PDISKENTRY DiskEntry
;
1447 /* Loop over the disks and find the correct one */
1448 Entry
= List
->DiskListHead
.Flink
;
1449 while (Entry
!= &List
->DiskListHead
)
1451 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1452 Entry
= Entry
->Flink
;
1454 if (DiskEntry
->LayoutBuffer
->Signature
== Signature
)
1461 /* Disk not found, stop there */
1467 // IN PPARTLIST List,
1468 IN PDISKENTRY DiskEntry
,
1469 IN ULONG PartitionNumber
)
1471 PPARTENTRY PartEntry
;
1474 /* Disk found, loop over the primary partitions first... */
1475 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1476 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
1478 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1479 Entry
= Entry
->Flink
;
1481 if (PartEntry
->PartitionNumber
== PartitionNumber
)
1483 /* Partition found */
1488 /* ... then over the logical partitions if needed */
1489 Entry
= DiskEntry
->LogicalPartListHead
.Flink
;
1490 while (Entry
!= &DiskEntry
->LogicalPartListHead
)
1492 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1493 Entry
= Entry
->Flink
;
1495 if (PartEntry
->PartitionNumber
== PartitionNumber
)
1497 /* Partition found */
1502 /* The partition was not found on the disk, stop there */
1509 IN ULONG DiskNumber
,
1510 IN ULONG PartitionNumber OPTIONAL
,
1511 OUT PDISKENTRY
* pDiskEntry
,
1512 OUT PPARTENTRY
* pPartEntry OPTIONAL
)
1514 PDISKENTRY DiskEntry
;
1515 PPARTENTRY PartEntry
= NULL
;
1518 DiskEntry
= GetDiskByNumber(List
, DiskNumber
);
1522 /* If we have a partition (PartitionNumber != 0), find it */
1523 if (PartitionNumber
!= 0)
1525 PartEntry
= GetPartition(/*List,*/ DiskEntry
, PartitionNumber
);
1528 ASSERT(PartEntry
->DiskEntry
== DiskEntry
);
1531 /* Return the disk (and optionally the partition) */
1532 *pDiskEntry
= DiskEntry
;
1533 if (pPartEntry
) *pPartEntry
= PartEntry
;
1538 // NOTE: Was introduced broken in r6258 by Casper
1543 IN ULONG DiskNumber
,
1544 IN ULONG PartitionNumber
)
1546 PDISKENTRY DiskEntry
;
1547 PPARTENTRY PartEntry
;
1549 DiskEntry
= GetDiskByNumber(List
, DiskNumber
);
1553 PartEntry
= GetPartition(/*List,*/ DiskEntry
, PartitionNumber
);
1557 ASSERT(PartEntry
->DiskEntry
== DiskEntry
);
1558 ASSERT(DiskEntry
->DiskNumber
== DiskNumber
);
1559 ASSERT(PartEntry
->PartitionNumber
== PartitionNumber
);
1561 List
->CurrentDisk
= DiskEntry
;
1562 List
->CurrentPartition
= PartEntry
;
1570 PLIST_ENTRY DiskListEntry
;
1571 PLIST_ENTRY PartListEntry
;
1572 PDISKENTRY DiskEntry
;
1573 PPARTENTRY PartEntry
;
1575 /* Fail if no disks are available */
1576 if (IsListEmpty(&List
->DiskListHead
))
1579 /* Check for next usable entry on current disk */
1580 if (List
->CurrentPartition
!= NULL
)
1582 if (List
->CurrentPartition
->LogicalPartition
)
1584 /* Logical partition */
1586 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
1587 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
1589 /* Next logical partition */
1590 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1592 List
->CurrentPartition
= PartEntry
;
1593 return List
->CurrentPartition
;
1597 PartListEntry
= List
->CurrentDisk
->ExtendedPartition
->ListEntry
.Flink
;
1598 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
1600 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1602 List
->CurrentPartition
= PartEntry
;
1603 return List
->CurrentPartition
;
1609 /* Primary or extended partition */
1611 if ((List
->CurrentPartition
->IsPartitioned
!= FALSE
) &&
1612 IsContainerPartition(List
->CurrentPartition
->PartitionType
))
1614 /* First logical partition */
1615 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Flink
;
1616 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
1618 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1620 List
->CurrentPartition
= PartEntry
;
1621 return List
->CurrentPartition
;
1626 /* Next primary partition */
1627 PartListEntry
= List
->CurrentPartition
->ListEntry
.Flink
;
1628 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
1630 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1632 List
->CurrentPartition
= PartEntry
;
1633 return List
->CurrentPartition
;
1639 /* Search for the first partition entry on the next disk */
1640 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Flink
;
1641 while (DiskListEntry
!= &List
->DiskListHead
)
1643 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
1645 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1646 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
1648 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1650 List
->CurrentDisk
= DiskEntry
;
1651 List
->CurrentPartition
= PartEntry
;
1652 return List
->CurrentPartition
;
1655 DiskListEntry
= DiskListEntry
->Flink
;
1665 PLIST_ENTRY DiskListEntry
;
1666 PLIST_ENTRY PartListEntry
;
1667 PDISKENTRY DiskEntry
;
1668 PPARTENTRY PartEntry
;
1670 /* Fail if no disks are available */
1671 if (IsListEmpty(&List
->DiskListHead
))
1674 /* Check for previous usable entry on current disk */
1675 if (List
->CurrentPartition
!= NULL
)
1677 if (List
->CurrentPartition
->LogicalPartition
)
1679 /* Logical partition */
1680 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
1681 if (PartListEntry
!= &List
->CurrentDisk
->LogicalPartListHead
)
1683 /* Previous logical partition */
1684 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1688 /* Extended partition */
1689 PartEntry
= List
->CurrentDisk
->ExtendedPartition
;
1692 List
->CurrentPartition
= PartEntry
;
1693 return List
->CurrentPartition
;
1697 /* Primary or extended partition */
1699 PartListEntry
= List
->CurrentPartition
->ListEntry
.Blink
;
1700 if (PartListEntry
!= &List
->CurrentDisk
->PrimaryPartListHead
)
1702 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1704 if ((PartEntry
->IsPartitioned
!= FALSE
) &&
1705 IsContainerPartition(PartEntry
->PartitionType
))
1707 PartListEntry
= List
->CurrentDisk
->LogicalPartListHead
.Blink
;
1708 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1711 List
->CurrentPartition
= PartEntry
;
1712 return List
->CurrentPartition
;
1717 /* Search for the last partition entry on the previous disk */
1718 DiskListEntry
= List
->CurrentDisk
->ListEntry
.Blink
;
1719 while (DiskListEntry
!= &List
->DiskListHead
)
1721 DiskEntry
= CONTAINING_RECORD(DiskListEntry
, DISKENTRY
, ListEntry
);
1723 PartListEntry
= DiskEntry
->PrimaryPartListHead
.Blink
;
1724 if (PartListEntry
!= &DiskEntry
->PrimaryPartListHead
)
1726 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1728 if ((PartEntry
->IsPartitioned
!= FALSE
) &&
1729 IsContainerPartition(PartEntry
->PartitionType
))
1731 PartListEntry
= DiskEntry
->LogicalPartListHead
.Blink
;
1732 if (PartListEntry
!= &DiskEntry
->LogicalPartListHead
)
1734 PartEntry
= CONTAINING_RECORD(PartListEntry
, PARTENTRY
, ListEntry
);
1736 List
->CurrentDisk
= DiskEntry
;
1737 List
->CurrentPartition
= PartEntry
;
1738 return List
->CurrentPartition
;
1743 List
->CurrentDisk
= DiskEntry
;
1744 List
->CurrentPartition
= PartEntry
;
1745 return List
->CurrentPartition
;
1749 DiskListEntry
= DiskListEntry
->Blink
;
1759 IN PPARTITION_INFORMATION PartitionInfo
)
1761 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
1762 PartitionInfo
->PartitionLength
.QuadPart
== 0)
1773 IsSamePrimaryLayoutEntry(
1774 IN PPARTITION_INFORMATION PartitionInfo
,
1775 IN PDISKENTRY DiskEntry
,
1776 IN PPARTENTRY PartEntry
)
1778 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
1779 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
1780 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
1781 // PartitionInfo->PartitionType == PartEntry->PartitionType
1791 GetPrimaryPartitionCount(
1792 IN PDISKENTRY DiskEntry
)
1795 PPARTENTRY PartEntry
;
1798 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1799 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
1801 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1802 if (PartEntry
->IsPartitioned
)
1805 Entry
= Entry
->Flink
;
1813 GetLogicalPartitionCount(
1814 IN PDISKENTRY DiskEntry
)
1816 PLIST_ENTRY ListEntry
;
1817 PPARTENTRY PartEntry
;
1820 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
1821 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
1823 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
1824 if (PartEntry
->IsPartitioned
)
1827 ListEntry
= ListEntry
->Flink
;
1835 ReAllocateLayoutBuffer(
1836 IN PDISKENTRY DiskEntry
)
1838 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer
;
1839 ULONG NewPartitionCount
;
1840 ULONG CurrentPartitionCount
= 0;
1841 ULONG LayoutBufferSize
;
1844 DPRINT1("ReAllocateLayoutBuffer()\n");
1846 NewPartitionCount
= 4 + GetLogicalPartitionCount(DiskEntry
) * 4;
1848 if (DiskEntry
->LayoutBuffer
)
1849 CurrentPartitionCount
= DiskEntry
->LayoutBuffer
->PartitionCount
;
1851 DPRINT1("CurrentPartitionCount: %lu NewPartitionCount: %lu\n",
1852 CurrentPartitionCount
, NewPartitionCount
);
1854 if (CurrentPartitionCount
== NewPartitionCount
)
1857 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1858 ((NewPartitionCount
- ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1859 NewLayoutBuffer
= RtlReAllocateHeap(ProcessHeap
,
1861 DiskEntry
->LayoutBuffer
,
1863 if (NewLayoutBuffer
== NULL
)
1865 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize
);
1869 /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
1870 if (NewPartitionCount
> CurrentPartitionCount
)
1872 for (i
= CurrentPartitionCount
; i
< NewPartitionCount
; i
++)
1873 NewLayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1876 DiskEntry
->LayoutBuffer
= NewLayoutBuffer
;
1877 DiskEntry
->LayoutBuffer
->PartitionCount
= NewPartitionCount
;
1885 IN PDISKENTRY DiskEntry
)
1887 PPARTITION_INFORMATION PartitionInfo
;
1888 PPARTITION_INFORMATION LinkInfo
= NULL
;
1889 PLIST_ENTRY ListEntry
;
1890 PPARTENTRY PartEntry
;
1891 LARGE_INTEGER HiddenSectors64
;
1893 ULONG PartitionNumber
= 1;
1895 DPRINT1("UpdateDiskLayout()\n");
1897 /* Resize the layout buffer if necessary */
1898 if (ReAllocateLayoutBuffer(DiskEntry
) == FALSE
)
1900 DPRINT("ReAllocateLayoutBuffer() failed.\n");
1904 /* Update the primary partition table */
1906 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1907 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
1909 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
1911 if (PartEntry
->IsPartitioned
!= FALSE
)
1913 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
1915 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
1917 DPRINT1("Updating primary partition entry %lu\n", Index
);
1919 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
1920 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1921 PartitionInfo
->HiddenSectors
= PartEntry
->StartSector
.LowPart
;
1922 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
1923 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
1924 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
1925 PartitionInfo
->RecognizedPartition
= FALSE
;
1926 PartitionInfo
->RewritePartition
= TRUE
;
1929 PartEntry
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
1930 PartEntry
->PartitionIndex
= Index
;
1932 if (!IsContainerPartition(PartEntry
->PartitionType
))
1938 ListEntry
= ListEntry
->Flink
;
1941 /* Update the logical partition table */
1943 ListEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
1944 while (ListEntry
!= &DiskEntry
->LogicalPartListHead
)
1946 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
1948 if (PartEntry
->IsPartitioned
)
1950 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
1952 DPRINT1("Updating logical partition entry %lu\n", Index
);
1954 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
1955 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1956 PartitionInfo
->HiddenSectors
= DiskEntry
->SectorAlignment
;
1957 PartitionInfo
->PartitionNumber
= PartitionNumber
;
1958 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
1959 PartitionInfo
->BootIndicator
= FALSE
;
1960 PartitionInfo
->RecognizedPartition
= FALSE
;
1961 PartitionInfo
->RewritePartition
= TRUE
;
1963 PartEntry
->PartitionNumber
= PartitionNumber
;
1964 PartEntry
->PartitionIndex
= Index
;
1966 /* Fill the link entry of the previous partition entry */
1967 if (LinkInfo
!= NULL
)
1969 LinkInfo
->StartingOffset
.QuadPart
= (PartEntry
->StartSector
.QuadPart
- DiskEntry
->SectorAlignment
) * DiskEntry
->BytesPerSector
;
1970 LinkInfo
->PartitionLength
.QuadPart
= (PartEntry
->StartSector
.QuadPart
+ DiskEntry
->SectorAlignment
) * DiskEntry
->BytesPerSector
;
1971 HiddenSectors64
.QuadPart
= PartEntry
->StartSector
.QuadPart
- DiskEntry
->SectorAlignment
- DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
;
1972 LinkInfo
->HiddenSectors
= HiddenSectors64
.LowPart
;
1973 LinkInfo
->PartitionNumber
= 0;
1974 LinkInfo
->PartitionType
= PARTITION_EXTENDED
;
1975 LinkInfo
->BootIndicator
= FALSE
;
1976 LinkInfo
->RecognizedPartition
= FALSE
;
1977 LinkInfo
->RewritePartition
= TRUE
;
1980 /* Save a pointer to the link entry of the current partition entry */
1981 LinkInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
+ 1];
1987 ListEntry
= ListEntry
->Flink
;
1990 /* Wipe unused primary partition entries */
1991 for (Index
= GetPrimaryPartitionCount(DiskEntry
); Index
< 4; Index
++)
1993 DPRINT1("Primary partition entry %lu\n", Index
);
1995 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
1997 if (!IsEmptyLayoutEntry(PartitionInfo
))
1999 DPRINT1("Wiping primary partition entry %lu\n", Index
);
2001 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2002 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2003 PartitionInfo
->HiddenSectors
= 0;
2004 PartitionInfo
->PartitionNumber
= 0;
2005 PartitionInfo
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2006 PartitionInfo
->BootIndicator
= FALSE
;
2007 PartitionInfo
->RecognizedPartition
= FALSE
;
2008 PartitionInfo
->RewritePartition
= TRUE
;
2012 /* Wipe unused logical partition entries */
2013 for (Index
= 4; Index
< DiskEntry
->LayoutBuffer
->PartitionCount
; Index
++)
2017 DPRINT1("Logical partition entry %lu\n", Index
);
2019 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2021 if (!IsEmptyLayoutEntry(PartitionInfo
))
2023 DPRINT1("Wiping partition entry %lu\n", Index
);
2025 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2026 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2027 PartitionInfo
->HiddenSectors
= 0;
2028 PartitionInfo
->PartitionNumber
= 0;
2029 PartitionInfo
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2030 PartitionInfo
->BootIndicator
= FALSE
;
2031 PartitionInfo
->RecognizedPartition
= FALSE
;
2032 PartitionInfo
->RewritePartition
= TRUE
;
2037 #ifdef DUMP_PARTITION_TABLE
2038 DumpPartitionTable(DiskEntry
);
2044 GetPrevUnpartitionedEntry(
2045 IN PDISKENTRY DiskEntry
,
2046 IN PPARTENTRY PartEntry
)
2048 PPARTENTRY PrevPartEntry
;
2049 PLIST_ENTRY ListHead
;
2051 if (PartEntry
->LogicalPartition
)
2052 ListHead
= &DiskEntry
->LogicalPartListHead
;
2054 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2056 if (PartEntry
->ListEntry
.Blink
!= ListHead
)
2058 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2061 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2062 return PrevPartEntry
;
2070 GetNextUnpartitionedEntry(
2071 IN PDISKENTRY DiskEntry
,
2072 IN PPARTENTRY PartEntry
)
2074 PPARTENTRY NextPartEntry
;
2075 PLIST_ENTRY ListHead
;
2077 if (PartEntry
->LogicalPartition
)
2078 ListHead
= &DiskEntry
->LogicalPartListHead
;
2080 ListHead
= &DiskEntry
->PrimaryPartListHead
;
2082 if (PartEntry
->ListEntry
.Flink
!= ListHead
)
2084 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2087 if (NextPartEntry
->IsPartitioned
== FALSE
)
2088 return NextPartEntry
;
2095 CreatePrimaryPartition(
2097 IN ULONGLONG SectorCount
,
2098 IN BOOLEAN AutoCreate
)
2100 PDISKENTRY DiskEntry
;
2101 PPARTENTRY PartEntry
;
2102 PPARTENTRY NewPartEntry
;
2104 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount
);
2107 List
->CurrentDisk
== NULL
||
2108 List
->CurrentPartition
== NULL
||
2109 List
->CurrentPartition
->IsPartitioned
!= FALSE
)
2114 DiskEntry
= List
->CurrentDisk
;
2115 PartEntry
= List
->CurrentPartition
;
2117 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2119 if ((AutoCreate
!= FALSE
) ||
2120 (AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
))
2122 DPRINT1("Convert existing partition entry\n");
2124 /* Convert current entry to 'new (unformatted)' */
2125 PartEntry
->IsPartitioned
= TRUE
;
2126 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2127 PartEntry
->FormatState
= Unformatted
;
2128 PartEntry
->FileSystem
= NULL
;
2129 PartEntry
->AutoCreate
= AutoCreate
;
2130 PartEntry
->New
= TRUE
;
2131 PartEntry
->BootIndicator
= FALSE
;
2133 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2134 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2135 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2139 DPRINT1("Add new partition entry\n");
2141 /* Insert and initialize a new partition entry */
2142 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2145 if (NewPartEntry
== NULL
)
2148 /* Insert the new entry into the list */
2149 InsertTailList(&PartEntry
->ListEntry
,
2150 &NewPartEntry
->ListEntry
);
2152 NewPartEntry
->DiskEntry
= DiskEntry
;
2154 NewPartEntry
->IsPartitioned
= TRUE
;
2155 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2156 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2157 NewPartEntry
->StartSector
.QuadPart
;
2158 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2160 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2161 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2162 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2164 NewPartEntry
->New
= TRUE
;
2165 NewPartEntry
->FormatState
= Unformatted
;
2166 NewPartEntry
->FileSystem
= NULL
;
2167 NewPartEntry
->BootIndicator
= FALSE
;
2169 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2170 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2173 UpdateDiskLayout(DiskEntry
);
2175 DiskEntry
->Dirty
= TRUE
;
2177 AssignDriveLetters(List
);
2182 AddLogicalDiskSpace(
2183 IN PDISKENTRY DiskEntry
)
2185 PPARTENTRY NewPartEntry
;
2187 DPRINT1("AddLogicalDiskSpace()\n");
2189 /* Create a partition entry that represents the empty space in the container partition */
2190 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2193 if (NewPartEntry
== NULL
)
2196 NewPartEntry
->DiskEntry
= DiskEntry
;
2197 NewPartEntry
->LogicalPartition
= TRUE
;
2199 NewPartEntry
->IsPartitioned
= FALSE
;
2200 NewPartEntry
->StartSector
.QuadPart
= DiskEntry
->ExtendedPartition
->StartSector
.QuadPart
+ (ULONGLONG
)DiskEntry
->SectorAlignment
;
2201 NewPartEntry
->SectorCount
.QuadPart
= DiskEntry
->ExtendedPartition
->SectorCount
.QuadPart
- (ULONGLONG
)DiskEntry
->SectorAlignment
;
2203 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2204 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2205 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2207 NewPartEntry
->FormatState
= Unformatted
;
2208 NewPartEntry
->FileSystem
= NULL
;
2210 InsertTailList(&DiskEntry
->LogicalPartListHead
,
2211 &NewPartEntry
->ListEntry
);
2215 CreateExtendedPartition(
2217 IN ULONGLONG SectorCount
)
2219 PDISKENTRY DiskEntry
;
2220 PPARTENTRY PartEntry
;
2221 PPARTENTRY NewPartEntry
;
2223 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount
);
2226 List
->CurrentDisk
== NULL
||
2227 List
->CurrentPartition
== NULL
||
2228 List
->CurrentPartition
->IsPartitioned
!= FALSE
)
2233 DiskEntry
= List
->CurrentDisk
;
2234 PartEntry
= List
->CurrentPartition
;
2236 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2238 if (AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2240 DPRINT1("Convert existing partition entry\n");
2242 /* Convert current entry to 'new (unformatted)' */
2243 PartEntry
->IsPartitioned
= TRUE
;
2244 PartEntry
->FormatState
= Formatted
; // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
2245 PartEntry
->FileSystem
= NULL
;
2246 PartEntry
->AutoCreate
= FALSE
;
2247 PartEntry
->New
= FALSE
;
2248 PartEntry
->BootIndicator
= FALSE
;
2250 if (PartEntry
->StartSector
.QuadPart
< 1450560)
2252 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2253 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
2257 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2258 PartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2261 DiskEntry
->ExtendedPartition
= PartEntry
;
2263 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2264 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2265 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2269 DPRINT1("Add new partition entry\n");
2271 /* Insert and initialize a new partition entry */
2272 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2275 if (NewPartEntry
== NULL
)
2278 /* Insert the new entry into the list */
2279 InsertTailList(&PartEntry
->ListEntry
,
2280 &NewPartEntry
->ListEntry
);
2282 NewPartEntry
->DiskEntry
= DiskEntry
;
2284 NewPartEntry
->IsPartitioned
= TRUE
;
2285 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2286 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2287 NewPartEntry
->StartSector
.QuadPart
;
2289 NewPartEntry
->New
= FALSE
;
2290 NewPartEntry
->FormatState
= Formatted
; // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
2291 NewPartEntry
->FileSystem
= NULL
;
2292 NewPartEntry
->BootIndicator
= FALSE
;
2294 if (NewPartEntry
->StartSector
.QuadPart
< 1450560)
2296 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2297 NewPartEntry
->PartitionType
= PARTITION_EXTENDED
;
2301 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2302 NewPartEntry
->PartitionType
= PARTITION_XINT13_EXTENDED
;
2305 DiskEntry
->ExtendedPartition
= NewPartEntry
;
2307 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2308 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2310 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2311 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2312 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2315 AddLogicalDiskSpace(DiskEntry
);
2317 UpdateDiskLayout(DiskEntry
);
2319 DiskEntry
->Dirty
= TRUE
;
2321 AssignDriveLetters(List
);
2325 CreateLogicalPartition(
2327 IN ULONGLONG SectorCount
,
2328 IN BOOLEAN AutoCreate
)
2330 PDISKENTRY DiskEntry
;
2331 PPARTENTRY PartEntry
;
2332 PPARTENTRY NewPartEntry
;
2334 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount
);
2337 List
->CurrentDisk
== NULL
||
2338 List
->CurrentPartition
== NULL
||
2339 List
->CurrentPartition
->IsPartitioned
!= FALSE
)
2344 DiskEntry
= List
->CurrentDisk
;
2345 PartEntry
= List
->CurrentPartition
;
2347 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2349 if ((AutoCreate
!= FALSE
) ||
2350 (AlignDown(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
))
2352 DPRINT1("Convert existing partition entry\n");
2354 /* Convert current entry to 'new (unformatted)' */
2355 PartEntry
->IsPartitioned
= TRUE
;
2356 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2357 PartEntry
->FormatState
= Unformatted
;
2358 PartEntry
->FileSystem
= NULL
;
2359 PartEntry
->AutoCreate
= FALSE
;
2360 PartEntry
->New
= TRUE
;
2361 PartEntry
->BootIndicator
= FALSE
;
2362 PartEntry
->LogicalPartition
= TRUE
;
2364 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2365 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2366 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2370 DPRINT1("Add new partition entry\n");
2372 /* Insert and initialize a new partition entry */
2373 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2376 if (NewPartEntry
== NULL
)
2379 /* Insert the new entry into the list */
2380 InsertTailList(&PartEntry
->ListEntry
,
2381 &NewPartEntry
->ListEntry
);
2383 NewPartEntry
->DiskEntry
= DiskEntry
;
2385 NewPartEntry
->IsPartitioned
= TRUE
;
2386 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2387 NewPartEntry
->SectorCount
.QuadPart
= AlignDown(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2388 NewPartEntry
->StartSector
.QuadPart
;
2389 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2391 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2392 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2393 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2395 NewPartEntry
->New
= TRUE
;
2396 NewPartEntry
->FormatState
= Unformatted
;
2397 NewPartEntry
->FileSystem
= NULL
;
2398 NewPartEntry
->BootIndicator
= FALSE
;
2399 NewPartEntry
->LogicalPartition
= TRUE
;
2401 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2402 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2405 UpdateDiskLayout(DiskEntry
);
2407 DiskEntry
->Dirty
= TRUE
;
2409 AssignDriveLetters(List
);
2413 DeleteCurrentPartition(
2416 PDISKENTRY DiskEntry
;
2417 PPARTENTRY PartEntry
;
2418 PPARTENTRY PrevPartEntry
;
2419 PPARTENTRY NextPartEntry
;
2420 PPARTENTRY LogicalPartEntry
;
2424 List
->CurrentDisk
== NULL
||
2425 List
->CurrentPartition
== NULL
||
2426 List
->CurrentPartition
->IsPartitioned
== FALSE
)
2431 /* Clear the system disk and partition pointers if the system partition is being deleted */
2432 if (List
->SystemPartition
== List
->CurrentPartition
)
2434 List
->SystemPartition
= NULL
;
2437 DiskEntry
= List
->CurrentDisk
;
2438 PartEntry
= List
->CurrentPartition
;
2440 /* Delete all logical partition entries if an extended partition will be deleted */
2441 if (DiskEntry
->ExtendedPartition
== PartEntry
)
2443 while (!IsListEmpty(&DiskEntry
->LogicalPartListHead
))
2445 Entry
= RemoveHeadList(&DiskEntry
->LogicalPartListHead
);
2446 LogicalPartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
2448 RtlFreeHeap(ProcessHeap
, 0, LogicalPartEntry
);
2451 DiskEntry
->ExtendedPartition
= NULL
;
2454 /* Adjust unpartitioned disk space entries */
2456 /* Get pointer to previous and next unpartitioned entries */
2457 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
, PartEntry
);
2458 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
, PartEntry
);
2460 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2462 /* Merge previous, current and next unpartitioned entry */
2464 /* Adjust the previous entries length */
2465 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
2467 /* Remove the current entry */
2468 RemoveEntryList(&PartEntry
->ListEntry
);
2469 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2471 /* Remove the next entry */
2472 RemoveEntryList(&NextPartEntry
->ListEntry
);
2473 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
2475 /* Update current partition */
2476 List
->CurrentPartition
= PrevPartEntry
;
2478 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2480 /* Merge current and previous unpartitioned entry */
2482 /* Adjust the previous entries length */
2483 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2485 /* Remove the current entry */
2486 RemoveEntryList(&PartEntry
->ListEntry
);
2487 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2489 /* Update current partition */
2490 List
->CurrentPartition
= PrevPartEntry
;
2492 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2494 /* Merge current and next unpartitioned entry */
2496 /* Adjust the next entries offset and length */
2497 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2498 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2500 /* Remove the current entry */
2501 RemoveEntryList(&PartEntry
->ListEntry
);
2502 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2504 /* Update current partition */
2505 List
->CurrentPartition
= NextPartEntry
;
2509 /* Nothing to merge but change current entry */
2510 PartEntry
->IsPartitioned
= FALSE
;
2511 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2512 PartEntry
->FormatState
= Unformatted
;
2513 PartEntry
->FileSystem
= NULL
;
2514 PartEntry
->DriveLetter
= 0;
2517 UpdateDiskLayout(DiskEntry
);
2519 DiskEntry
->Dirty
= TRUE
;
2521 AssignDriveLetters(List
);
2525 CheckActiveSystemPartition(
2528 PDISKENTRY DiskEntry
;
2529 PPARTENTRY PartEntry
;
2530 PLIST_ENTRY ListEntry
;
2532 PFILE_SYSTEM FileSystem
;
2534 /* Check for empty disk list */
2535 if (IsListEmpty(&List
->DiskListHead
))
2537 List
->SystemPartition
= NULL
;
2538 List
->OriginalSystemPartition
= NULL
;
2542 /* Choose the currently selected disk */
2543 DiskEntry
= List
->CurrentDisk
;
2545 /* Check for empty partition list */
2546 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
2548 List
->SystemPartition
= NULL
;
2549 List
->OriginalSystemPartition
= NULL
;
2553 if (List
->SystemPartition
!= NULL
)
2555 /* We already have an active system partition */
2556 DPRINT1("Use the current system partition %lu in disk %lu, drive letter %c\n",
2557 List
->SystemPartition
->PartitionNumber
,
2558 List
->SystemPartition
->DiskEntry
->DiskNumber
,
2559 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
2563 DPRINT1("We are here (1)!\n");
2565 List
->SystemPartition
= NULL
;
2566 List
->OriginalSystemPartition
= NULL
;
2568 /* Retrieve the first partition of the disk */
2569 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
2572 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
2573 List
->SystemPartition
= PartEntry
;
2576 // See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
2579 /* Check if the disk is new and if so, use its first partition as the active system partition */
2580 if (DiskEntry
->NewDisk
)
2582 if (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
|| PartEntry
->BootIndicator
== FALSE
)
2584 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
2585 List
->SystemPartition
= PartEntry
;
2587 List
->OriginalSystemPartition
= List
->SystemPartition
;
2589 DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %c\n",
2590 List
->SystemPartition
->PartitionNumber
,
2591 List
->SystemPartition
->DiskEntry
->DiskNumber
,
2592 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
2594 goto SetSystemPartition
;
2597 // FIXME: What to do??
2598 DPRINT1("NewDisk TRUE but first partition is used?\n");
2601 DPRINT1("We are here (2)!\n");
2604 * The disk is not new, check if any partition is initialized;
2605 * if not, the first one becomes the system partition.
2607 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2608 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2610 /* Retrieve the partition and go to the next one */
2611 PartEntry
= CONTAINING_RECORD(ListEntry
,
2615 /* Check if the partition is partitioned and is used */
2616 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
|| PartEntry
->BootIndicator
!= FALSE
)
2621 /* Go to the next one */
2622 ListEntry
= ListEntry
->Flink
;
2624 if (ListEntry
== &DiskEntry
->PrimaryPartListHead
)
2627 * OK we haven't encountered any used and active partition,
2628 * so use the first one as the system partition.
2630 ASSERT(DiskEntry
== List
->SystemPartition
->DiskEntry
);
2631 List
->OriginalSystemPartition
= List
->SystemPartition
; // First PartEntry
2633 DPRINT1("Use first active system partition %lu in disk %lu, drive letter %c\n",
2634 List
->SystemPartition
->PartitionNumber
,
2635 List
->SystemPartition
->DiskEntry
->DiskNumber
,
2636 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
2638 goto SetSystemPartition
;
2641 List
->SystemPartition
= NULL
;
2642 List
->OriginalSystemPartition
= NULL
;
2644 DPRINT1("We are here (3)!\n");
2646 /* The disk is not new, scan all partitions to find the (active) system partition */
2647 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2648 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2650 /* Retrieve the partition and go to the next one */
2651 PartEntry
= CONTAINING_RECORD(ListEntry
,
2654 ListEntry
= ListEntry
->Flink
;
2656 /* Check if the partition is partitioned and used */
2657 if (PartEntry
->IsPartitioned
&&
2658 PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
)
2660 /* Check if the partition is active */
2661 if (PartEntry
->BootIndicator
)
2663 /* Yes, we found it */
2664 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
2665 List
->SystemPartition
= PartEntry
;
2667 DPRINT1("Found active system partition %lu in disk %lu, drive letter %c\n",
2668 PartEntry
->PartitionNumber
,
2669 DiskEntry
->DiskNumber
,
2670 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
);
2676 /* Check if we have found the system partition */
2677 if (List
->SystemPartition
== NULL
)
2679 /* Nothing, use the alternative system partition */
2680 DPRINT1("No system partition found, use the alternative partition!\n");
2681 goto UseAlternativeSystemPartition
;
2685 List
->OriginalSystemPartition
= List
->SystemPartition
;
2688 * ADDITIONAL CHECKS / BIG HACK:
2690 * Retrieve its file system and check whether we have
2691 * write support for it. If that is the case we are fine
2692 * and we can use it directly. However if we don't have
2693 * write support we will need to change the active system
2696 * NOTE that this is completely useless on architectures
2697 * where a real system partition is required, as on these
2698 * architectures the partition uses the FAT FS, for which
2699 * we do have write support.
2700 * NOTE also that for those architectures looking for a
2701 * partition boot indicator is insufficient.
2703 FileSystem
= GetFileSystem(List
->OriginalSystemPartition
);
2704 if (FileSystem
== NULL
)
2706 DPRINT1("System partition %lu in disk %lu with no FS?!\n",
2707 List
->OriginalSystemPartition
->PartitionNumber
,
2708 List
->OriginalSystemPartition
->DiskEntry
->DiskNumber
);
2709 goto FindAndUseAlternativeSystemPartition
;
2711 // HACK: WARNING: We cannot write on this FS yet!
2712 // See fsutil.c:GetFileSystem()
2713 if (List
->OriginalSystemPartition
->PartitionType
== PARTITION_EXT2
||
2714 List
->OriginalSystemPartition
->PartitionType
== PARTITION_IFS
)
2716 DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
2717 FileSystem
->FileSystemName
);
2718 goto FindAndUseAlternativeSystemPartition
;
2721 DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %c\n",
2722 List
->SystemPartition
->PartitionNumber
,
2723 List
->SystemPartition
->DiskEntry
->DiskNumber
,
2724 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
2728 FindAndUseAlternativeSystemPartition
:
2730 * We are here because we have not found any (active) candidate
2731 * system partition that we know how to support. What we are going
2732 * to do is to change the existing system partition and use the
2733 * partition on which we install ReactOS as the new system partition,
2734 * and then we will need to add in FreeLdr's entry a boot entry to boot
2735 * from the original system partition.
2738 /* Unset the old system partition */
2739 List
->SystemPartition
->BootIndicator
= FALSE
;
2740 List
->SystemPartition
->DiskEntry
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].BootIndicator
= FALSE
;
2741 List
->SystemPartition
->DiskEntry
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].RewritePartition
= TRUE
;
2742 List
->SystemPartition
->DiskEntry
->Dirty
= TRUE
;
2744 UseAlternativeSystemPartition
:
2745 List
->SystemPartition
= List
->CurrentPartition
;
2747 DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %c\n",
2748 List
->SystemPartition
->PartitionNumber
,
2749 List
->SystemPartition
->DiskEntry
->DiskNumber
,
2750 (List
->SystemPartition
->DriveLetter
== 0) ? '-' : List
->SystemPartition
->DriveLetter
);
2753 /* Set the new active system partition */
2754 List
->SystemPartition
->BootIndicator
= TRUE
;
2755 List
->SystemPartition
->DiskEntry
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].BootIndicator
= TRUE
;
2756 List
->SystemPartition
->DiskEntry
->LayoutBuffer
->PartitionEntry
[List
->SystemPartition
->PartitionIndex
].RewritePartition
= TRUE
;
2757 List
->SystemPartition
->DiskEntry
->Dirty
= TRUE
;
2764 IN PDISKENTRY DiskEntry
)
2766 WCHAR DstPath
[MAX_PATH
];
2767 OBJECT_ATTRIBUTES ObjectAttributes
;
2768 IO_STATUS_BLOCK Iosb
;
2769 UNICODE_STRING Name
;
2771 HANDLE FileHandle
= NULL
;
2774 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
2776 RtlStringCchPrintfW(DstPath
, ARRAYSIZE(DstPath
),
2777 L
"\\Device\\Harddisk%lu\\Partition0",
2778 DiskEntry
->DiskNumber
);
2779 RtlInitUnicodeString(&Name
, DstPath
);
2780 InitializeObjectAttributes(&ObjectAttributes
,
2786 Status
= NtOpenFile(&FileHandle
,
2787 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
2791 FILE_SYNCHRONOUS_IO_NONALERT
);
2792 if (!NT_SUCCESS(Status
))
2794 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
2798 #ifdef DUMP_PARTITION_TABLE
2799 DumpPartitionTable(DiskEntry
);
2802 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2803 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
2804 Status
= NtDeviceIoControlFile(FileHandle
,
2809 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2810 DiskEntry
->LayoutBuffer
,
2814 if (!NT_SUCCESS(Status
))
2816 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
2819 if (FileHandle
!= NULL
)
2820 NtClose(FileHandle
);
2823 // NOTE: Originally (see r40437), we used to install here also a new MBR
2824 // for this disk (by calling InstallMbrBootCodeToDisk), only if:
2825 // DiskEntry->NewDisk == TRUE and DiskEntry->BiosDiskNumber == 0.
2826 // Then after that, both DiskEntry->NewDisk and DiskEntry->NoMbr were set
2827 // to FALSE. In the other place (in usetup.c) where InstallMbrBootCodeToDisk
2828 // was called too, the installation test was modified by checking whether
2829 // DiskEntry->NoMbr was TRUE (instead of NewDisk).
2836 WritePartitionsToDisk(
2840 PDISKENTRY DiskEntry
;
2845 Entry
= List
->DiskListHead
.Flink
;
2846 while (Entry
!= &List
->DiskListHead
)
2848 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
2850 if (DiskEntry
->Dirty
!= FALSE
)
2852 WritePartitions(List
, DiskEntry
);
2853 DiskEntry
->Dirty
= FALSE
;
2856 Entry
= Entry
->Flink
;
2863 SetMountedDeviceValue(
2866 IN LARGE_INTEGER StartingOffset
)
2868 OBJECT_ATTRIBUTES ObjectAttributes
;
2869 WCHAR ValueNameBuffer
[16];
2870 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\MountedDevices");
2871 UNICODE_STRING ValueName
;
2872 REG_DISK_MOUNT_INFO MountInfo
;
2876 RtlStringCchPrintfW(ValueNameBuffer
, ARRAYSIZE(ValueNameBuffer
),
2877 L
"\\DosDevices\\%C:", Letter
);
2878 RtlInitUnicodeString(&ValueName
, ValueNameBuffer
);
2880 InitializeObjectAttributes(&ObjectAttributes
,
2882 OBJ_CASE_INSENSITIVE
,
2885 Status
= NtOpenKey(&KeyHandle
,
2888 if (!NT_SUCCESS(Status
))
2890 Status
= NtCreateKey(&KeyHandle
,
2895 REG_OPTION_NON_VOLATILE
,
2899 if (!NT_SUCCESS(Status
))
2901 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status
);
2905 MountInfo
.Signature
= Signature
;
2906 MountInfo
.StartingOffset
= StartingOffset
;
2907 Status
= NtSetValueKey(KeyHandle
,
2914 if (!NT_SUCCESS(Status
))
2916 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
2924 SetMountedDeviceValues(
2927 PLIST_ENTRY Entry1
, Entry2
;
2928 PDISKENTRY DiskEntry
;
2929 PPARTENTRY PartEntry
;
2930 LARGE_INTEGER StartingOffset
;
2935 Entry1
= List
->DiskListHead
.Flink
;
2936 while (Entry1
!= &List
->DiskListHead
)
2938 DiskEntry
= CONTAINING_RECORD(Entry1
,
2942 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
2943 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
2945 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2946 if (PartEntry
->IsPartitioned
)
2948 /* Assign a "\DosDevices\#:" mount point to this partition */
2949 if (PartEntry
->DriveLetter
)
2951 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2952 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
2953 DiskEntry
->LayoutBuffer
->Signature
,
2961 Entry2
= Entry2
->Flink
;
2964 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
2965 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
2967 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2968 if (PartEntry
->IsPartitioned
)
2970 /* Assign a "\DosDevices\#:" mount point to this partition */
2971 if (PartEntry
->DriveLetter
)
2973 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2974 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
2975 DiskEntry
->LayoutBuffer
->Signature
,
2983 Entry2
= Entry2
->Flink
;
2986 Entry1
= Entry1
->Flink
;
2994 IN PPARTENTRY PartEntry
,
2995 IN UCHAR PartitionType
)
2997 PDISKENTRY DiskEntry
= PartEntry
->DiskEntry
;
2999 PartEntry
->PartitionType
= PartitionType
;
3001 DiskEntry
->Dirty
= TRUE
;
3002 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].PartitionType
= PartitionType
;
3003 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
3007 PrimaryPartitionCreationChecks(
3010 PDISKENTRY DiskEntry
;
3011 PPARTENTRY PartEntry
;
3013 DiskEntry
= List
->CurrentDisk
;
3014 PartEntry
= List
->CurrentPartition
;
3016 /* Fail if the partition is already in use */
3017 if (PartEntry
->IsPartitioned
!= FALSE
)
3018 return ERROR_NEW_PARTITION
;
3020 /* Fail if there are already 4 primary partitions in the list */
3021 if (GetPrimaryPartitionCount(DiskEntry
) >= 4)
3022 return ERROR_PARTITION_TABLE_FULL
;
3024 return ERROR_SUCCESS
;
3028 ExtendedPartitionCreationChecks(
3031 PDISKENTRY DiskEntry
;
3032 PPARTENTRY PartEntry
;
3034 DiskEntry
= List
->CurrentDisk
;
3035 PartEntry
= List
->CurrentPartition
;
3037 /* Fail if the partition is already in use */
3038 if (PartEntry
->IsPartitioned
!= FALSE
)
3039 return ERROR_NEW_PARTITION
;
3041 /* Fail if there are already 4 primary partitions in the list */
3042 if (GetPrimaryPartitionCount(DiskEntry
) >= 4)
3043 return ERROR_PARTITION_TABLE_FULL
;
3045 /* Fail if there is another extended partition in the list */
3046 if (DiskEntry
->ExtendedPartition
!= NULL
)
3047 return ERROR_ONLY_ONE_EXTENDED
;
3049 return ERROR_SUCCESS
;
3053 LogicalPartitionCreationChecks(
3056 // PDISKENTRY DiskEntry;
3057 PPARTENTRY PartEntry
;
3059 // DiskEntry = List->CurrentDisk;
3060 PartEntry
= List
->CurrentPartition
;
3062 /* Fail if the partition is already in use */
3063 if (PartEntry
->IsPartitioned
!= FALSE
)
3064 return ERROR_NEW_PARTITION
;
3066 return ERROR_SUCCESS
;
3070 GetNextUnformattedPartition(
3072 OUT PDISKENTRY
*pDiskEntry OPTIONAL
,
3073 OUT PPARTENTRY
*pPartEntry
)
3075 PLIST_ENTRY Entry1
, Entry2
;
3076 PDISKENTRY DiskEntry
;
3077 PPARTENTRY PartEntry
;
3079 Entry1
= List
->DiskListHead
.Flink
;
3080 while (Entry1
!= &List
->DiskListHead
)
3082 DiskEntry
= CONTAINING_RECORD(Entry1
,
3086 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3087 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3089 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3090 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3092 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
3093 if (pDiskEntry
) *pDiskEntry
= DiskEntry
;
3094 *pPartEntry
= PartEntry
;
3098 Entry2
= Entry2
->Flink
;
3101 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3102 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3104 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3105 if (PartEntry
->IsPartitioned
&& PartEntry
->New
)
3107 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
3108 if (pDiskEntry
) *pDiskEntry
= DiskEntry
;
3109 *pPartEntry
= PartEntry
;
3113 Entry2
= Entry2
->Flink
;
3116 Entry1
= Entry1
->Flink
;
3119 if (pDiskEntry
) *pDiskEntry
= NULL
;
3126 GetNextUncheckedPartition(
3128 OUT PDISKENTRY
*pDiskEntry OPTIONAL
,
3129 OUT PPARTENTRY
*pPartEntry
)
3131 PLIST_ENTRY Entry1
, Entry2
;
3132 PDISKENTRY DiskEntry
;
3133 PPARTENTRY PartEntry
;
3135 Entry1
= List
->DiskListHead
.Flink
;
3136 while (Entry1
!= &List
->DiskListHead
)
3138 DiskEntry
= CONTAINING_RECORD(Entry1
,
3142 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
3143 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
3145 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3146 if (PartEntry
->NeedsCheck
== TRUE
)
3148 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
3149 if (pDiskEntry
) *pDiskEntry
= DiskEntry
;
3150 *pPartEntry
= PartEntry
;
3154 Entry2
= Entry2
->Flink
;
3157 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
3158 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
3160 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
3161 if (PartEntry
->NeedsCheck
== TRUE
)
3163 ASSERT(DiskEntry
== PartEntry
->DiskEntry
);
3164 if (pDiskEntry
) *pDiskEntry
= DiskEntry
;
3165 *pPartEntry
= PartEntry
;
3169 Entry2
= Entry2
->Flink
;
3172 Entry1
= Entry1
->Flink
;
3175 if (pDiskEntry
) *pDiskEntry
= NULL
;