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)
32 /* FUNCTIONS ****************************************************************/
35 GetDriverName (PDISKENTRY DiskEntry
)
37 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
41 RtlInitUnicodeString (&DiskEntry
->DriverName
,
45 L
"\\Scsi\\Scsi Port %lu",
48 RtlZeroMemory (&QueryTable
,
51 QueryTable
[0].Name
= L
"Driver";
52 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
53 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
55 Status
= RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP
,
60 if (!NT_SUCCESS (Status
))
62 DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
68 AssignDriverLetters (PPARTLIST List
)
79 /* Assign drive letters to primary partitions */
80 Entry1
= List
->DiskListHead
.Flink
;
81 while (Entry1
!= &List
->DiskListHead
)
83 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
85 if (!IsListEmpty (&DiskEntry
->PartListHead
))
87 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
92 PartEntry
->DriveLetter
[i
] = 0;
94 if (PartEntry
->Unpartitioned
== FALSE
)
98 if (IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
))
101 if (IsRecognizedPartition (PartEntry
->PartInfo
[i
].PartitionType
) ||
102 (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
103 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0LL))
107 PartEntry
->DriveLetter
[i
] = Letter
;
115 Entry1
= Entry1
->Flink
;
118 /* Assign drive letters to logical drives */
120 Entry1
= List
->DiskListHead
.Flink
;
121 while (Entry1
!= &List
->DiskListHead
)
123 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
125 Entry2
= DiskEntry
->PartListHead
.Flink
;
126 if (Entry2
!= &DiskEntry
->PartListHead
)
128 Entry2
= Entry2
->Flink
;
129 while (Entry2
!= &DiskEntry
->PartListHead
)
131 PartEntry
= CONTAINING_RECORD (Entry2
,
135 PartEntry
->DriveLetter
= 0;
137 if (PartEntry
->Unpartitioned
== FALSE
&&
138 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
140 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
141 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
142 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
146 PartEntry
->DriveLetter
= Letter
;
152 Entry2
= Entry2
->Flink
;
156 Entry1
= Entry1
->Flink
;
163 UpdatePartitionNumbers (PDISKENTRY DiskEntry
)
165 PPARTENTRY PartEntry
;
171 Entry
= DiskEntry
->PartListHead
.Flink
;
172 while (Entry
!= &DiskEntry
->PartListHead
)
174 PartEntry
= CONTAINING_RECORD (Entry
,
178 if (PartEntry
->Unpartitioned
== TRUE
)
180 for (i
= 0; i
< 4; i
++)
182 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
187 for (i
= 0; i
< 4; i
++)
189 if (IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
))
191 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
193 else if (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
194 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
== 0ULL)
196 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
200 PartEntry
->PartInfo
[i
].PartitionNumber
= PartNumber
;
206 Entry
= Entry
->Flink
;
212 AddPartitionToList (ULONG DiskNumber
,
213 PDISKENTRY DiskEntry
,
214 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
)
216 PPARTENTRY PartEntry
;
220 for (i
= 0; i
< LayoutBuffer
->PartitionCount
; i
+= 4)
222 for (j
= 0; j
< 4; j
++)
224 if (LayoutBuffer
->PartitionEntry
[i
+j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
225 LayoutBuffer
->PartitionEntry
[i
+j
].PartitionLength
.QuadPart
!= 0ULL)
235 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
238 if (PartEntry
== NULL
)
243 RtlZeroMemory (PartEntry
,
246 PartEntry
->Unpartitioned
= FALSE
;
248 for (j
= 0; j
< 4; j
++)
250 RtlCopyMemory (&PartEntry
->PartInfo
[j
],
251 &LayoutBuffer
->PartitionEntry
[i
+j
],
252 sizeof(PARTITION_INFORMATION
));
255 if (IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
257 PartEntry
->FormatState
= Unformatted
;
259 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
260 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
261 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
262 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
) ||
263 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
264 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
267 if (CheckFatFormat())
269 PartEntry
->FormatState
= Preformatted
;
273 PartEntry
->FormatState
= Unformatted
;
276 PartEntry
->FormatState
= Preformatted
;
278 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_EXT2
)
281 if (CheckExt2Format())
283 PartEntry
->FormatState
= Preformatted
;
287 PartEntry
->FormatState
= Unformatted
;
290 PartEntry
->FormatState
= Preformatted
;
292 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
295 if (CheckNtfsFormat())
297 PartEntry
->FormatState
= Preformatted
;
299 else if (CheckHpfsFormat())
301 PartEntry
->FormatState
= Preformatted
;
305 PartEntry
->FormatState
= Unformatted
;
308 PartEntry
->FormatState
= Preformatted
;
312 PartEntry
->FormatState
= UnknownFormat
;
315 InsertTailList (&DiskEntry
->PartListHead
,
316 &PartEntry
->ListEntry
);
322 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry
)
324 ULONGLONG LastStartingOffset
;
325 ULONGLONG LastPartitionLength
;
326 ULONGLONG LastUnusedPartitionLength
;
327 PPARTENTRY PartEntry
;
328 PPARTENTRY NewPartEntry
;
333 if (IsListEmpty (&DiskEntry
->PartListHead
))
335 /* Create a partition table that represents the empty disk */
336 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
339 if (PartEntry
== NULL
)
342 RtlZeroMemory (PartEntry
,
345 PartEntry
->Unpartitioned
= TRUE
;
346 PartEntry
->UnpartitionedOffset
= 0ULL;
347 PartEntry
->UnpartitionedLength
= DiskEntry
->DiskSize
;
349 PartEntry
->FormatState
= Unformatted
;
351 InsertTailList (&DiskEntry
->PartListHead
,
352 &PartEntry
->ListEntry
);
356 /* Start partition at head 1, cylinder 0 */
357 LastStartingOffset
= DiskEntry
->TrackSize
;
358 LastPartitionLength
= 0ULL;
359 LastUnusedPartitionLength
= 0ULL;
362 Entry
= DiskEntry
->PartListHead
.Flink
;
363 while (Entry
!= &DiskEntry
->PartListHead
)
365 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
367 for (j
= 0; j
< 4; j
++)
369 if ((!IsContainerPartition (PartEntry
->PartInfo
[j
].PartitionType
)) &&
370 (PartEntry
->PartInfo
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
371 PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
!= 0LL))
373 LastUnusedPartitionLength
=
374 PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
-
375 (LastStartingOffset
+ LastPartitionLength
);
377 if (PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
> (LastStartingOffset
+ LastPartitionLength
) &&
378 LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
380 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
382 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
385 if (NewPartEntry
== NULL
)
388 RtlZeroMemory (NewPartEntry
,
391 NewPartEntry
->Unpartitioned
= TRUE
;
392 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
393 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
395 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
397 NewPartEntry
->FormatState
= Unformatted
;
399 /* Insert the table into the list */
400 InsertTailList (&PartEntry
->ListEntry
,
401 &NewPartEntry
->ListEntry
);
404 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
405 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
410 Entry
= Entry
->Flink
;
413 /* Check for trailing unpartitioned disk space */
414 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
416 /* Round-down to cylinder size */
417 LastUnusedPartitionLength
=
418 (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
))
419 & ~(DiskEntry
->CylinderSize
- 1);
421 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
423 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
425 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
428 if (NewPartEntry
== NULL
)
431 RtlZeroMemory (NewPartEntry
,
434 NewPartEntry
->Unpartitioned
= TRUE
;
435 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
436 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
438 /* Append the table to the list */
439 InsertTailList (&DiskEntry
->PartListHead
,
440 &NewPartEntry
->ListEntry
);
448 DiskIdentifierQueryRoutine(PWSTR ValueName
,
455 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
456 UNICODE_STRING NameU
;
458 if (ValueType
== REG_SZ
&&
459 ValueLength
== 20 * sizeof(WCHAR
))
461 NameU
.Buffer
= (PWCHAR
)ValueData
;
462 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
463 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
465 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
466 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
468 return STATUS_SUCCESS
;
470 return STATUS_UNSUCCESSFUL
;
475 DiskConfigurationDataQueryRoutine(PWSTR ValueName
,
482 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
483 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
484 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
487 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
488 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
489 return STATUS_UNSUCCESSFUL
;
491 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
492 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
493 /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
494 FullResourceDescriptor->PartialResourceList.Revision != 1)
495 return STATUS_UNSUCCESSFUL;*/
497 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
499 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
500 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
503 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
504 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
506 return STATUS_SUCCESS
;
508 return STATUS_UNSUCCESSFUL
;
513 SystemConfigurationDataQueryRoutine(PWSTR ValueName
,
520 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
521 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
524 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
525 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
526 return STATUS_UNSUCCESSFUL
;
528 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
529 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
530 /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
531 FullResourceDescriptor->PartialResourceList.Revision != 1)
532 return STATUS_UNSUCCESSFUL;*/
534 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
536 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
537 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
540 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
541 if (*Int13Drives
== NULL
)
542 return STATUS_NO_MEMORY
;
544 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
545 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
546 return STATUS_SUCCESS
;
548 return STATUS_UNSUCCESSFUL
;
550 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
553 EnumerateBiosDiskEntries(PPARTLIST PartList
)
555 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
560 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
561 PBIOSDISKENTRY BiosDiskEntry
;
563 memset(QueryTable
, 0, sizeof(QueryTable
));
565 QueryTable
[1].Name
= L
"Configuration Data";
566 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
568 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
569 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
573 if (!NT_SUCCESS(Status
))
575 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
582 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
583 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
588 if (!NT_SUCCESS(Status
))
593 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
594 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
599 if (NT_SUCCESS(Status
))
603 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
604 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
609 if (!NT_SUCCESS(Status
))
611 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
615 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
616 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
621 if (NT_SUCCESS(Status
))
623 QueryTable
[0].Name
= L
"Identifier";
624 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
625 QueryTable
[1].Name
= L
"Configuration Data";
626 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
630 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
631 if (BiosDiskEntry
== NULL
)
635 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
636 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
639 (PVOID
)BiosDiskEntry
,
641 if (!NT_SUCCESS(Status
))
643 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
646 BiosDiskEntry
->DiskNumber
= DiskCount
;
647 BiosDiskEntry
->Recognized
= FALSE
;
649 if (DiskCount
< Int13Drives
[0].NumberDrives
)
651 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
655 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
659 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
661 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
662 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
663 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
664 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
665 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
666 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
667 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
668 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
669 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
670 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
671 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
676 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
682 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
686 AddDiskToList (HANDLE FileHandle
,
690 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
691 DISK_GEOMETRY DiskGeometry
;
692 SCSI_ADDRESS ScsiAddress
;
693 PDISKENTRY DiskEntry
;
694 IO_STATUS_BLOCK Iosb
;
696 PPARTITION_SECTOR Mbr
;
698 LARGE_INTEGER FileOffset
;
699 WCHAR Identifier
[20];
703 PLIST_ENTRY ListEntry
;
704 PBIOSDISKENTRY BiosDiskEntry
;
705 ULONG LayoutBufferSize
;
707 Status
= NtDeviceIoControlFile (FileHandle
,
712 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
716 sizeof(DISK_GEOMETRY
));
717 if (!NT_SUCCESS (Status
))
722 if (DiskGeometry
.MediaType
!= FixedMedia
&&
723 DiskGeometry
.MediaType
!= RemovableMedia
)
728 Status
= NtDeviceIoControlFile (FileHandle
,
733 IOCTL_SCSI_GET_ADDRESS
,
737 sizeof(SCSI_ADDRESS
));
738 if (!NT_SUCCESS(Status
))
743 Mbr
= (PARTITION_SECTOR
*) RtlAllocateHeap(ProcessHeap
,
745 DiskGeometry
.BytesPerSector
);
752 FileOffset
.QuadPart
= 0;
753 Status
= NtReadFile(FileHandle
,
759 DiskGeometry
.BytesPerSector
,
762 if (!NT_SUCCESS(Status
))
764 RtlFreeHeap(ProcessHeap
,
767 DPRINT1("NtReadFile failed, status=%x\n", Status
);
770 Signature
= Mbr
->Signature
;
772 /* Calculate the MBR checksum */
774 Buffer
= (PULONG
)Mbr
;
775 for (i
= 0; i
< 128; i
++)
777 Checksum
+= Buffer
[i
];
779 Checksum
= ~Checksum
+ 1;
781 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
782 DPRINT("Identifier: %S\n", Identifier
);
784 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
787 if (DiskEntry
== NULL
)
792 DiskEntry
->Checksum
= Checksum
;
793 DiskEntry
->Signature
= Signature
;
796 /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
797 DiskEntry
->Modified
= TRUE
;
799 DiskEntry
->BiosFound
= FALSE
;
801 /* Check if this disk has a valid MBR */
802 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
803 DiskEntry
->NoMbr
= TRUE
;
805 DiskEntry
->NoMbr
= FALSE
;
807 /* Free Mbr sector buffer */
808 RtlFreeHeap (ProcessHeap
,
812 ListEntry
= List
->BiosDiskListHead
.Flink
;
813 while(ListEntry
!= &List
->BiosDiskListHead
)
815 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
817 * Compare the size from bios and the reported size from driver.
818 * If we have more than one disk with a zero or with the same signatur
819 * we must create new signatures and reboot. After the reboot,
820 * it is possible to identify the disks.
822 if (BiosDiskEntry
->Signature
== Signature
&&
823 BiosDiskEntry
->Checksum
== Checksum
&&
824 !BiosDiskEntry
->Recognized
)
826 if (!DiskEntry
->BiosFound
)
828 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
829 DiskEntry
->BiosFound
= TRUE
;
830 BiosDiskEntry
->Recognized
= TRUE
;
836 ListEntry
= ListEntry
->Flink
;
839 if (!DiskEntry
->BiosFound
)
842 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
845 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
849 InitializeListHead (&DiskEntry
->PartListHead
);
851 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
852 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
853 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
854 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
856 DPRINT ("Cylinders %I64u\n", DiskEntry
->Cylinders
);
857 DPRINT ("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
858 DPRINT ("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
859 DPRINT ("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
861 DiskEntry
->TrackSize
=
862 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
863 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
864 DiskEntry
->CylinderSize
=
865 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
866 DiskEntry
->TrackSize
;
867 DiskEntry
->DiskSize
=
868 DiskGeometry
.Cylinders
.QuadPart
*
869 DiskEntry
->CylinderSize
;
871 DiskEntry
->DiskNumber
= DiskNumber
;
872 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
873 DiskEntry
->Bus
= ScsiAddress
.PathId
;
874 DiskEntry
->Id
= ScsiAddress
.TargetId
;
876 GetDriverName (DiskEntry
);
878 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
881 * Allocate a buffer for 26 logical drives (2 entries each == 52)
882 * plus the main partiton table (4 entries). Total 56 entries.
884 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
885 ((56 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
886 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
889 if (LayoutBuffer
== NULL
)
894 Status
= NtDeviceIoControlFile (FileHandle
,
899 IOCTL_DISK_GET_DRIVE_LAYOUT
,
904 if (NT_SUCCESS (Status
))
906 if (LayoutBuffer
->PartitionCount
== 0)
908 DiskEntry
->NewDisk
= TRUE
;
911 AddPartitionToList (DiskNumber
,
915 ScanForUnpartitionedDiskSpace (DiskEntry
);
918 RtlFreeHeap (ProcessHeap
,
925 CreatePartitionList (SHORT Left
,
931 OBJECT_ATTRIBUTES ObjectAttributes
;
932 SYSTEM_DEVICE_INFORMATION Sdi
;
933 IO_STATUS_BLOCK Iosb
;
937 WCHAR Buffer
[MAX_PATH
];
941 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
950 List
->Bottom
= Bottom
;
955 List
->TopDisk
= (ULONG
)-1;
956 List
->TopPartition
= (ULONG
)-1;
958 List
->CurrentDisk
= NULL
;
959 List
->CurrentPartition
= NULL
;
960 List
->CurrentPartitionNumber
= 0;
962 InitializeListHead (&List
->DiskListHead
);
963 InitializeListHead (&List
->BiosDiskListHead
);
965 EnumerateBiosDiskEntries(List
);
967 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
969 sizeof(SYSTEM_DEVICE_INFORMATION
),
971 if (!NT_SUCCESS (Status
))
973 RtlFreeHeap (ProcessHeap
, 0, List
);
977 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
980 L
"\\Device\\Harddisk%d\\Partition0",
982 RtlInitUnicodeString (&Name
,
985 InitializeObjectAttributes (&ObjectAttributes
,
991 Status
= NtOpenFile (&FileHandle
,
992 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
996 FILE_SYNCHRONOUS_IO_NONALERT
);
997 if (NT_SUCCESS(Status
))
999 AddDiskToList (FileHandle
,
1003 NtClose(FileHandle
);
1007 AssignDriverLetters (List
);
1010 List
->TopPartition
= 0;
1012 /* Search for first usable disk and partition */
1013 if (IsListEmpty (&List
->DiskListHead
))
1015 List
->CurrentDisk
= NULL
;
1016 List
->CurrentPartition
= NULL
;
1017 List
->CurrentPartitionNumber
= 0;
1022 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
1026 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
1028 List
->CurrentPartition
= 0;
1029 List
->CurrentPartitionNumber
= 0;
1033 List
->CurrentPartition
=
1034 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
1037 List
->CurrentPartitionNumber
= 0;
1046 DestroyPartitionList (PPARTLIST List
)
1048 PDISKENTRY DiskEntry
;
1049 PBIOSDISKENTRY BiosDiskEntry
;
1050 PPARTENTRY PartEntry
;
1053 /* Release disk and partition info */
1054 while (!IsListEmpty (&List
->DiskListHead
))
1056 Entry
= RemoveHeadList (&List
->DiskListHead
);
1057 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1059 /* Release driver name */
1060 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1062 /* Release partition array */
1063 while (!IsListEmpty (&DiskEntry
->PartListHead
))
1065 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
1066 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
1068 RtlFreeHeap (ProcessHeap
,
1073 /* Release disk entry */
1074 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
1077 /* release the bios disk info */
1078 while(!IsListEmpty(&List
->BiosDiskListHead
))
1080 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1081 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1083 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1086 /* Release list head */
1087 RtlFreeHeap (ProcessHeap
, 0, List
);
1092 PrintEmptyLine (PPARTLIST List
)
1099 Width
= List
->Right
- List
->Left
- 1;
1100 Height
= List
->Bottom
- List
->Top
- 2;
1103 coPos
.X
= List
->Left
+ 1;
1104 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1106 if (List
->Line
>= 0 && List
->Line
<= Height
)
1108 FillConsoleOutputAttribute (StdOutput
,
1109 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1114 FillConsoleOutputCharacterA (StdOutput
,
1125 PrintPartitionData (PPARTLIST List
,
1126 PDISKENTRY DiskEntry
,
1127 PPARTENTRY PartEntry
,
1130 CHAR LineBuffer
[128];
1136 LARGE_INTEGER PartSize
;
1141 Width
= List
->Right
- List
->Left
- 1;
1142 Height
= List
->Bottom
- List
->Top
- 2;
1145 coPos
.X
= List
->Left
+ 1;
1146 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1148 if (PartEntry
->Unpartitioned
== TRUE
)
1151 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1153 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1154 Unit
= MUIGetString(STRING_GB
);
1158 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1160 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1161 Unit
= MUIGetString(STRING_MB
);
1165 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1166 Unit
= MUIGetString(STRING_KB
);
1169 sprintf (LineBuffer
,
1170 MUIGetString(STRING_UNPSPACE
),
1176 /* Determine partition type */
1178 if (PartEntry
->New
== TRUE
)
1180 PartType
= MUIGetString(STRING_UNFORMATTED
);
1182 else if (PartEntry
->Unpartitioned
== FALSE
)
1184 if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_12
) ||
1185 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_16
) ||
1186 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_HUGE
) ||
1187 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_XINT13
))
1191 else if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32
) ||
1192 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32_XINT13
))
1196 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_EXT2
)
1200 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_IFS
)
1202 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1207 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1209 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1210 Unit
= MUIGetString(STRING_GB
);
1214 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1216 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1217 Unit
= MUIGetString(STRING_MB
);
1221 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1222 Unit
= MUIGetString(STRING_KB
);
1225 if (PartType
== NULL
)
1227 sprintf (LineBuffer
,
1228 MUIGetString(STRING_HDDINFOUNK5
),
1229 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1230 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1231 PartEntry
->PartInfo
[PartNumber
].PartitionType
,
1237 sprintf (LineBuffer
,
1238 "%c%c %-24s %6lu %s",
1239 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1240 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1247 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1248 List
->CurrentPartition
== PartEntry
&&
1249 List
->CurrentPartitionNumber
== PartNumber
) ?
1250 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1251 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1253 if (List
->Line
>= 0 && List
->Line
<= Height
)
1255 FillConsoleOutputCharacterA (StdOutput
,
1263 if (List
->Line
>= 0 && List
->Line
<= Height
)
1265 FillConsoleOutputAttribute (StdOutput
,
1273 if (List
->Line
>= 0 && List
->Line
<= Height
)
1275 WriteConsoleOutputCharacterA (StdOutput
,
1277 min (strlen (LineBuffer
), Width
),
1286 PrintDiskData (PPARTLIST List
,
1287 PDISKENTRY DiskEntry
)
1289 PPARTENTRY PartEntry
;
1291 CHAR LineBuffer
[128];
1296 ULARGE_INTEGER DiskSize
;
1300 Width
= List
->Right
- List
->Left
- 1;
1301 Height
= List
->Bottom
- List
->Top
- 2;
1304 coPos
.X
= List
->Left
+ 1;
1305 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1308 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1310 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1311 Unit
= MUIGetString(STRING_GB
);
1316 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1317 if (DiskSize
.QuadPart
== 0)
1318 DiskSize
.QuadPart
= 1;
1319 Unit
= MUIGetString(STRING_MB
);
1322 if (DiskEntry
->DriverName
.Length
> 0)
1324 sprintf (LineBuffer
,
1325 MUIGetString(STRING_HDINFOPARTSELECT
),
1328 DiskEntry
->DiskNumber
,
1332 DiskEntry
->DriverName
.Buffer
);
1336 sprintf (LineBuffer
,
1337 MUIGetString(STRING_HDDINFOUNK6
),
1340 DiskEntry
->DiskNumber
,
1345 if (List
->Line
>= 0 && List
->Line
<= Height
)
1347 FillConsoleOutputAttribute (StdOutput
,
1348 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1353 FillConsoleOutputCharacterA (StdOutput
,
1361 if (List
->Line
>= 0 && List
->Line
<= Height
)
1363 WriteConsoleOutputCharacterA (StdOutput
,
1365 min ((USHORT
)strlen (LineBuffer
), Width
- 2),
1371 /* Print separator line */
1372 PrintEmptyLine (List
);
1374 /* Print partition lines*/
1375 Entry
= DiskEntry
->PartListHead
.Flink
;
1376 while (Entry
!= &DiskEntry
->PartListHead
)
1378 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1380 /* Print disk entry */
1383 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
1384 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
1386 PrintPartitionData (List
,
1393 /* Print unpartitioned entry */
1394 if (PartEntry
->Unpartitioned
)
1396 PrintPartitionData (List
,
1402 Entry
= Entry
->Flink
;
1405 /* Print separator line */
1406 PrintEmptyLine (List
);
1411 DrawPartitionList (PPARTLIST List
)
1413 PLIST_ENTRY Entry
, Entry2
;
1414 PDISKENTRY DiskEntry
;
1415 PPARTENTRY PartEntry
= NULL
;
1419 SHORT CurrentDiskLine
;
1420 SHORT CurrentPartLine
;
1422 BOOL CurrentPartLineFound
= FALSE
;
1423 BOOL CurrentDiskLineFound
= FALSE
;
1425 /* Calculate the line of the current disk and partition */
1426 CurrentDiskLine
= 0;
1427 CurrentPartLine
= 0;
1429 Entry
= List
->DiskListHead
.Flink
;
1430 while (Entry
!= &List
->DiskListHead
)
1432 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1434 if (CurrentPartLineFound
== FALSE
)
1436 CurrentPartLine
+= 2;
1438 Entry2
= DiskEntry
->PartListHead
.Flink
;
1439 while (Entry2
!= &DiskEntry
->PartListHead
)
1441 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1442 if (PartEntry
== List
->CurrentPartition
)
1444 CurrentPartLineFound
= TRUE
;
1446 Entry2
= Entry2
->Flink
;
1447 if (CurrentPartLineFound
== FALSE
)
1453 if (DiskEntry
== List
->CurrentDisk
)
1455 CurrentDiskLineFound
= TRUE
;
1457 Entry
= Entry
->Flink
;
1458 if (Entry
!= &List
->DiskListHead
)
1460 if (CurrentDiskLineFound
== FALSE
)
1463 CurrentDiskLine
= CurrentPartLine
;
1473 /* If it possible, make the disk name visible */
1474 if (CurrentPartLine
< List
->Offset
)
1476 List
->Offset
= CurrentPartLine
;
1478 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1480 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1482 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1484 List
->Offset
= CurrentDiskLine
;
1488 /* draw upper left corner */
1489 coPos
.X
= List
->Left
;
1490 coPos
.Y
= List
->Top
;
1491 FillConsoleOutputCharacterA (StdOutput
,
1497 /* draw upper edge */
1498 coPos
.X
= List
->Left
+ 1;
1499 coPos
.Y
= List
->Top
;
1500 if (List
->Offset
== 0)
1502 FillConsoleOutputCharacterA (StdOutput
,
1504 List
->Right
- List
->Left
- 1,
1510 FillConsoleOutputCharacterA (StdOutput
,
1512 List
->Right
- List
->Left
- 5,
1515 coPos
.X
= List
->Right
- 5;
1516 WriteConsoleOutputCharacterA (StdOutput
,
1521 coPos
.X
= List
->Right
- 2;
1522 FillConsoleOutputCharacterA (StdOutput
,
1529 /* draw upper right corner */
1530 coPos
.X
= List
->Right
;
1531 coPos
.Y
= List
->Top
;
1532 FillConsoleOutputCharacterA (StdOutput
,
1538 /* draw left and right edge */
1539 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1541 coPos
.X
= List
->Left
;
1543 FillConsoleOutputCharacterA (StdOutput
,
1549 coPos
.X
= List
->Right
;
1550 FillConsoleOutputCharacterA (StdOutput
,
1557 /* draw lower left corner */
1558 coPos
.X
= List
->Left
;
1559 coPos
.Y
= List
->Bottom
;
1560 FillConsoleOutputCharacterA (StdOutput
,
1566 /* draw lower edge */
1567 coPos
.X
= List
->Left
+ 1;
1568 coPos
.Y
= List
->Bottom
;
1569 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1571 FillConsoleOutputCharacterA (StdOutput
,
1573 List
->Right
- List
->Left
- 1,
1579 FillConsoleOutputCharacterA (StdOutput
,
1581 List
->Right
- List
->Left
- 5,
1584 coPos
.X
= List
->Right
- 5;
1585 WriteConsoleOutputCharacterA (StdOutput
,
1586 "(\x19)", // "(down)"
1590 coPos
.X
= List
->Right
- 2;
1591 FillConsoleOutputCharacterA (StdOutput
,
1598 /* draw lower right corner */
1599 coPos
.X
= List
->Right
;
1600 coPos
.Y
= List
->Bottom
;
1601 FillConsoleOutputCharacterA (StdOutput
,
1607 /* print list entries */
1608 List
->Line
= - List
->Offset
;
1610 Entry
= List
->DiskListHead
.Flink
;
1611 while (Entry
!= &List
->DiskListHead
)
1613 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1615 /* Print disk entry */
1616 PrintDiskData (List
,
1619 Entry
= Entry
->Flink
;
1625 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1627 PDISKENTRY DiskEntry
;
1628 PPARTENTRY PartEntry
;
1633 /* Check for empty disks */
1634 if (IsListEmpty (&List
->DiskListHead
))
1637 /* Check for first usable entry on next disk */
1638 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1639 while (Entry1
!= &List
->DiskListHead
)
1641 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1643 if (DiskEntry
->DiskNumber
== DiskNumber
)
1645 Entry2
= DiskEntry
->PartListHead
.Flink
;
1646 while (Entry2
!= &DiskEntry
->PartListHead
)
1648 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1650 for (i
= 0; i
< 4; i
++)
1652 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1654 List
->CurrentDisk
= DiskEntry
;
1655 List
->CurrentPartition
= PartEntry
;
1656 List
->CurrentPartitionNumber
= i
;
1657 DrawPartitionList (List
);
1661 Entry2
= Entry2
->Flink
;
1665 Entry1
= Entry1
->Flink
;
1672 ScrollDownPartitionList (PPARTLIST List
)
1674 PDISKENTRY DiskEntry
;
1675 PPARTENTRY PartEntry
;
1680 /* Check for empty disks */
1681 if (IsListEmpty (&List
->DiskListHead
))
1684 /* Check for next usable entry on current disk */
1685 if (List
->CurrentPartition
!= NULL
)
1687 Entry2
= &List
->CurrentPartition
->ListEntry
;
1688 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1690 /* Check if we can move inside primary partitions */
1691 for (i
= List
->CurrentPartitionNumber
+ 1; i
< 4; i
++)
1693 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1699 /* We're out of partitions in the current partition table.
1700 Try to move to the next one if possible. */
1701 Entry2
= Entry2
->Flink
;
1705 /* Just advance to the next partition */
1706 List
->CurrentPartitionNumber
= i
;
1707 DrawPartitionList (List
);
1711 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1713 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1715 // if (PartEntry->HidePartEntry == FALSE)
1717 List
->CurrentPartition
= PartEntry
;
1718 List
->CurrentPartitionNumber
= 0;
1719 DrawPartitionList (List
);
1722 Entry2
= Entry2
->Flink
;
1726 /* Check for first usable entry on next disk */
1727 if (List
->CurrentDisk
!= NULL
)
1729 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1730 while (Entry1
!= &List
->DiskListHead
)
1732 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1734 Entry2
= DiskEntry
->PartListHead
.Flink
;
1735 while (Entry2
!= &DiskEntry
->PartListHead
)
1737 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1739 // if (PartEntry->HidePartEntry == FALSE)
1741 List
->CurrentDisk
= DiskEntry
;
1742 List
->CurrentPartition
= PartEntry
;
1743 List
->CurrentPartitionNumber
= 0;
1744 DrawPartitionList (List
);
1748 Entry2
= Entry2
->Flink
;
1751 Entry1
= Entry1
->Flink
;
1758 ScrollUpPartitionList (PPARTLIST List
)
1760 PDISKENTRY DiskEntry
;
1761 PPARTENTRY PartEntry
;
1766 /* Check for empty disks */
1767 if (IsListEmpty (&List
->DiskListHead
))
1770 /* check for previous usable entry on current disk */
1771 if (List
->CurrentPartition
!= NULL
)
1773 Entry2
= &List
->CurrentPartition
->ListEntry
;
1774 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1776 /* Check if we can move inside primary partitions */
1777 if (List
->CurrentPartitionNumber
> 0)
1779 /* Find a previous partition */
1780 for (i
= List
->CurrentPartitionNumber
- 1; i
> 0; i
--)
1782 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1786 /* Move to it and return */
1787 List
->CurrentPartitionNumber
= i
;
1788 DrawPartitionList (List
);
1792 /* Move to the previous entry */
1793 Entry2
= Entry2
->Blink
;
1795 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1797 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1799 // if (PartEntry->HidePartEntry == FALSE)
1801 List
->CurrentPartition
= PartEntry
;
1803 /* Find last existing partition in the table */
1804 for (i
= 3; i
> 0; i
--)
1806 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1811 List
->CurrentPartitionNumber
= i
;
1813 /* Draw partition list and return */
1814 DrawPartitionList (List
);
1817 Entry2
= Entry2
->Blink
;
1822 /* check for last usable entry on previous disk */
1823 if (List
->CurrentDisk
!= NULL
)
1825 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1826 while (Entry1
!= &List
->DiskListHead
)
1828 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1830 Entry2
= DiskEntry
->PartListHead
.Blink
;
1831 while (Entry2
!= &DiskEntry
->PartListHead
)
1833 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1835 // if (PartEntry->HidePartEntry == FALSE)
1837 List
->CurrentDisk
= DiskEntry
;
1838 List
->CurrentPartition
= PartEntry
;
1840 /* Find last existing partition in the table */
1841 for (i
= 3; i
> 0; i
--)
1843 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1848 List
->CurrentPartitionNumber
= i
;
1850 /* Draw partition list and return */
1851 DrawPartitionList (List
);
1855 Entry2
= Entry2
->Blink
;
1858 Entry1
= Entry1
->Blink
;
1865 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1866 PPARTENTRY CurrentEntry
)
1868 PPARTENTRY PrevEntry
;
1871 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1874 Entry
= CurrentEntry
->ListEntry
.Blink
;
1875 while (Entry
!= &DiskEntry
->PartListHead
)
1877 PrevEntry
= CONTAINING_RECORD (Entry
,
1880 if (PrevEntry
->Unpartitioned
== FALSE
)
1883 Entry
= Entry
->Blink
;
1891 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1892 PPARTENTRY CurrentEntry
)
1894 PPARTENTRY NextEntry
;
1897 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1900 Entry
= CurrentEntry
->ListEntry
.Flink
;
1901 while (Entry
!= &DiskEntry
->PartListHead
)
1903 NextEntry
= CONTAINING_RECORD (Entry
,
1906 if (NextEntry
->Unpartitioned
== FALSE
)
1909 Entry
= Entry
->Flink
;
1917 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1918 PPARTENTRY PartEntry
)
1920 PPARTENTRY PrevPartEntry
;
1922 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1924 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1927 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1928 return PrevPartEntry
;
1936 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1937 PPARTENTRY PartEntry
)
1939 PPARTENTRY NextPartEntry
;
1941 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1943 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1946 if (NextPartEntry
->Unpartitioned
== TRUE
)
1947 return NextPartEntry
;
1955 CreateNewPartition (PPARTLIST List
,
1956 ULONGLONG PartitionSize
,
1959 PDISKENTRY DiskEntry
;
1960 PPARTENTRY PartEntry
;
1961 PPARTENTRY PrevPartEntry
;
1962 PPARTENTRY NextPartEntry
;
1963 PPARTENTRY NewPartEntry
;
1966 List
->CurrentDisk
== NULL
||
1967 List
->CurrentPartition
== NULL
||
1968 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1973 DiskEntry
= List
->CurrentDisk
;
1974 PartEntry
= List
->CurrentPartition
;
1976 if (AutoCreate
== TRUE
||
1977 PartitionSize
== PartEntry
->UnpartitionedLength
)
1979 /* Convert current entry to 'new (unformatted)' */
1980 PartEntry
->FormatState
= Unformatted
;
1981 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1982 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1983 PartEntry
->PartInfo
[0].HiddenSectors
=
1984 (ULONG
)(PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
1985 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1986 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1987 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1988 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1989 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1990 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1991 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1992 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1994 /* Get previous and next partition entries */
1995 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1997 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2000 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2002 /* Current entry is in the middle of the list */
2004 /* Copy previous container partition data to current entry */
2005 RtlCopyMemory (&PartEntry
->PartInfo
[1],
2006 &PrevPartEntry
->PartInfo
[1],
2007 sizeof(PARTITION_INFORMATION
));
2008 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2010 /* Update previous container partition data */
2012 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2013 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2014 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2015 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2017 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2019 /* Special case - previous partition is first partition */
2020 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2021 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2025 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2026 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2029 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2031 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2033 /* Current entry is the first entry */
2036 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2038 /* Current entry is the last entry */
2040 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2041 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2042 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2043 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2045 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2047 /* Special case - previous partition is first partition */
2048 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2049 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2053 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2054 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2057 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2058 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2059 (1024LL * 255LL * 63LL * 512LL))
2061 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2065 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2068 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2069 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2072 PartEntry
->AutoCreate
= AutoCreate
;
2073 PartEntry
->New
= TRUE
;
2074 PartEntry
->Unpartitioned
= FALSE
;
2075 PartEntry
->UnpartitionedOffset
= 0ULL;
2076 PartEntry
->UnpartitionedLength
= 0ULL;
2080 /* Insert an initialize a new partition entry */
2081 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
2084 if (NewPartEntry
== NULL
)
2087 RtlZeroMemory (NewPartEntry
,
2090 /* Insert the new entry into the list */
2091 InsertTailList (&PartEntry
->ListEntry
,
2092 &NewPartEntry
->ListEntry
);
2094 NewPartEntry
->New
= TRUE
;
2096 NewPartEntry
->FormatState
= Unformatted
;
2097 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
2098 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
2099 NewPartEntry
->PartInfo
[0].HiddenSectors
=
2100 (ULONG
)(NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2101 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
2102 PartitionSize
- DiskEntry
->TrackSize
;
2103 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
2104 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
2105 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2106 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2107 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
2108 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
2110 /* Get previous and next partition entries */
2111 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2113 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2116 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2118 /* Current entry is in the middle of the list */
2120 /* Copy previous container partition data to current entry */
2121 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
2122 &PrevPartEntry
->PartInfo
[1],
2123 sizeof(PARTITION_INFORMATION
));
2124 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2126 /* Update previous container partition data */
2128 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2129 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2130 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2131 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2133 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2135 /* Special case - previous partition is first partition */
2136 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2137 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2141 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2142 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2145 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2147 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2149 /* Current entry is the first entry */
2152 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2154 /* Current entry is the last entry */
2156 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2157 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2158 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2159 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2161 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2163 /* Special case - previous partition is first partition */
2164 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2165 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2169 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2170 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2173 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2174 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2175 (1024LL * 255LL * 63LL * 512LL))
2177 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2181 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2184 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2185 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2188 /* Update offset and size of the remaining unpartitioned disk space */
2189 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
2190 PartEntry
->UnpartitionedLength
-= PartitionSize
;
2193 DiskEntry
->Modified
= TRUE
;
2195 UpdatePartitionNumbers (DiskEntry
);
2197 AssignDriverLetters (List
);
2202 DeleteCurrentPartition (PPARTLIST List
)
2204 PDISKENTRY DiskEntry
;
2205 PPARTENTRY PartEntry
;
2206 PPARTENTRY PrevPartEntry
;
2207 PPARTENTRY NextPartEntry
;
2210 List
->CurrentDisk
== NULL
||
2211 List
->CurrentPartition
== NULL
||
2212 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2217 DiskEntry
= List
->CurrentDisk
;
2218 PartEntry
= List
->CurrentPartition
;
2220 /* Adjust container partition entries */
2222 /* Get previous and next partition entries */
2223 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2225 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2228 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2230 /* Current entry is in the middle of the list */
2233 * The first extended partition can not be deleted
2234 * as long as other extended partitions are present.
2236 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2239 /* Copy previous container partition data to current entry */
2240 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
2241 &PartEntry
->PartInfo
[1],
2242 sizeof(PARTITION_INFORMATION
));
2243 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2245 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2248 * A primary partition can not be deleted as long as
2249 * extended partitions are present.
2253 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2255 /* Current entry is the last entry */
2256 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
2257 sizeof(PARTITION_INFORMATION
));
2258 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2262 /* Adjust unpartitioned disk space entries */
2264 /* Get pointer to previous and next unpartitioned entries */
2265 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
2268 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
2271 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2273 /* Merge previous, current and next unpartitioned entry */
2275 /* Adjust the previous entries length */
2276 PrevPartEntry
->UnpartitionedLength
+=
2277 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2278 NextPartEntry
->UnpartitionedLength
);
2280 /* Remove the current entry */
2281 RemoveEntryList (&PartEntry
->ListEntry
);
2282 RtlFreeHeap (ProcessHeap
,
2286 /* Remove the next entry */
2287 RemoveEntryList (&NextPartEntry
->ListEntry
);
2288 RtlFreeHeap (ProcessHeap
,
2292 /* Update current partition */
2293 List
->CurrentPartition
= PrevPartEntry
;
2295 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2297 /* Merge current and previous unpartitioned entry */
2299 /* Adjust the previous entries length */
2300 PrevPartEntry
->UnpartitionedLength
+=
2301 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2303 /* Remove the current entry */
2304 RemoveEntryList (&PartEntry
->ListEntry
);
2305 RtlFreeHeap (ProcessHeap
,
2309 /* Update current partition */
2310 List
->CurrentPartition
= PrevPartEntry
;
2312 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2314 /* Merge current and next unpartitioned entry */
2316 /* Adjust the next entries offset and length */
2317 NextPartEntry
->UnpartitionedOffset
=
2318 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2319 NextPartEntry
->UnpartitionedLength
+=
2320 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2322 /* Remove the current entry */
2323 RemoveEntryList (&PartEntry
->ListEntry
);
2324 RtlFreeHeap (ProcessHeap
,
2328 /* Update current partition */
2329 List
->CurrentPartition
= NextPartEntry
;
2333 /* Nothing to merge but change current entry */
2334 PartEntry
->New
= FALSE
;
2335 PartEntry
->Unpartitioned
= TRUE
;
2336 PartEntry
->UnpartitionedOffset
=
2337 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2338 PartEntry
->UnpartitionedLength
=
2339 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2341 /* Wipe the partition table */
2342 RtlZeroMemory (&PartEntry
->PartInfo
,
2343 sizeof(PartEntry
->PartInfo
));
2346 DiskEntry
->Modified
= TRUE
;
2348 UpdatePartitionNumbers (DiskEntry
);
2350 AssignDriverLetters (List
);
2355 CheckActiveBootPartition (PPARTLIST List
)
2357 PDISKENTRY DiskEntry
;
2358 PPARTENTRY PartEntry
;
2359 PLIST_ENTRY ListEntry
;
2362 /* Check for empty disk list */
2363 if (IsListEmpty (&List
->DiskListHead
))
2365 List
->ActiveBootDisk
= NULL
;
2366 List
->ActiveBootPartition
= NULL
;
2367 List
->ActiveBootPartitionNumber
= 0;
2372 if (List
->ActiveBootDisk
!= NULL
&&
2373 List
->ActiveBootPartition
!= NULL
)
2375 /* We already have an active boot partition */
2380 /* Choose the currently selected disk */
2381 DiskEntry
= List
->CurrentDisk
;
2383 /* Check for empty partition list */
2384 if (IsListEmpty (&DiskEntry
->PartListHead
))
2386 List
->ActiveBootDisk
= NULL
;
2387 List
->ActiveBootPartition
= NULL
;
2388 List
->ActiveBootPartitionNumber
= 0;
2392 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
2396 /* Set active boot partition */
2397 if ((DiskEntry
->NewDisk
== TRUE
) ||
2398 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2399 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2400 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2401 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2403 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2404 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2405 DiskEntry
->Modified
= TRUE
;
2407 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2408 List
->ActiveBootDisk
= DiskEntry
;
2409 List
->ActiveBootPartition
= PartEntry
;
2410 List
->ActiveBootPartitionNumber
= 0;
2415 /* Disk is not new, scan all partitions to find a bootable one */
2416 List
->ActiveBootDisk
= NULL
;
2417 List
->ActiveBootPartition
= NULL
;
2418 List
->ActiveBootPartitionNumber
= 0;
2420 ListEntry
= DiskEntry
->PartListHead
.Flink
;
2421 while (ListEntry
!= &DiskEntry
->PartListHead
)
2423 PartEntry
= CONTAINING_RECORD(ListEntry
,
2427 /* Check if it's partitioned */
2428 if (!PartEntry
->Unpartitioned
)
2430 /* Go through all of its 4 partitions */
2433 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2434 PartEntry
->PartInfo
[i
].BootIndicator
)
2436 /* Yes, we found it */
2437 List
->ActiveBootDisk
= DiskEntry
;
2438 List
->ActiveBootPartition
= PartEntry
;
2439 List
->ActiveBootPartitionNumber
= i
;
2441 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2442 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
[i
]);
2448 /* Go to the next one */
2449 ListEntry
= ListEntry
->Flink
;
2455 CheckForLinuxFdiskPartitions (PPARTLIST List
)
2457 PDISKENTRY DiskEntry
;
2458 PPARTENTRY PartEntry
;
2461 ULONG PartitionCount
;
2464 Entry1
= List
->DiskListHead
.Flink
;
2465 while (Entry1
!= &List
->DiskListHead
)
2467 DiskEntry
= CONTAINING_RECORD (Entry1
,
2471 Entry2
= DiskEntry
->PartListHead
.Flink
;
2472 while (Entry2
!= &DiskEntry
->PartListHead
)
2474 PartEntry
= CONTAINING_RECORD (Entry2
,
2478 if (PartEntry
->Unpartitioned
== FALSE
)
2482 for (i
= 0; i
< 4; i
++)
2484 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
2485 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2491 if (PartitionCount
> 1)
2497 Entry2
= Entry2
->Flink
;
2500 Entry1
= Entry1
->Flink
;
2508 WritePartitionsToDisk (PPARTLIST List
)
2510 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2511 OBJECT_ATTRIBUTES ObjectAttributes
;
2512 IO_STATUS_BLOCK Iosb
;
2513 WCHAR DstPath
[MAX_PATH
];
2514 UNICODE_STRING Name
;
2516 PDISKENTRY DiskEntry1
;
2517 PDISKENTRY DiskEntry2
;
2518 PPARTENTRY PartEntry
;
2521 ULONG PartitionCount
;
2522 ULONG DriveLayoutSize
;
2531 Entry1
= List
->DiskListHead
.Flink
;
2532 while (Entry1
!= &List
->DiskListHead
)
2534 DiskEntry1
= CONTAINING_RECORD (Entry1
,
2538 if (DiskEntry1
->Modified
== TRUE
)
2540 /* Count partitioned entries */
2542 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2543 while (Entry2
!= &DiskEntry1
->PartListHead
)
2545 PartEntry
= CONTAINING_RECORD (Entry2
,
2548 if (PartEntry
->Unpartitioned
== FALSE
)
2550 PartitionCount
+= 4;
2553 Entry2
= Entry2
->Flink
;
2555 if (PartitionCount
== 0)
2557 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2558 ((4 - 1) * sizeof (PARTITION_INFORMATION
));
2562 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2563 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2565 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
2568 if (DriveLayout
== NULL
)
2570 DPRINT1 ("RtlAllocateHeap() failed\n");
2574 RtlZeroMemory (DriveLayout
,
2577 if (PartitionCount
== 0)
2579 /* delete all partitions in the mbr */
2580 DriveLayout
->PartitionCount
= 4;
2581 for (Index
= 0; Index
< 4; Index
++)
2583 DriveLayout
->PartitionEntry
[Index
].RewritePartition
= TRUE
;
2588 DriveLayout
->PartitionCount
= PartitionCount
;
2591 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2592 while (Entry2
!= &DiskEntry1
->PartListHead
)
2594 PartEntry
= CONTAINING_RECORD (Entry2
,
2597 if (PartEntry
->Unpartitioned
== FALSE
)
2599 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2600 &PartEntry
->PartInfo
[0],
2601 4 * sizeof (PARTITION_INFORMATION
));
2605 Entry2
= Entry2
->Flink
;
2608 if (DiskEntry1
->Signature
== 0)
2610 LARGE_INTEGER SystemTime
;
2611 TIME_FIELDS TimeFields
;
2613 Buffer
= (PUCHAR
)&DiskEntry1
->Signature
;
2617 NtQuerySystemTime (&SystemTime
);
2618 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
2620 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
2621 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
2622 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
2623 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
2625 if (DiskEntry1
->Signature
== 0)
2630 /* check if the signature already exist */
2632 * Check also signatures from disks, which are
2633 * not visible (bootable) by the bios.
2635 Entry2
= List
->DiskListHead
.Flink
;
2636 while (Entry2
!= &List
->DiskListHead
)
2638 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
2639 if (DiskEntry1
!= DiskEntry2
&&
2640 DiskEntry1
->Signature
== DiskEntry2
->Signature
)
2644 Entry2
= Entry2
->Flink
;
2646 if (Entry2
== &List
->DiskListHead
)
2652 /* set one partition entry to dirty, this will update the signature */
2653 DriveLayout
->PartitionEntry
[0].RewritePartition
= TRUE
;
2657 DriveLayout
->Signature
= DiskEntry1
->Signature
;
2661 L
"\\Device\\Harddisk%d\\Partition0",
2662 DiskEntry1
->DiskNumber
);
2663 RtlInitUnicodeString (&Name
,
2665 InitializeObjectAttributes (&ObjectAttributes
,
2671 Status
= NtOpenFile (&FileHandle
,
2676 FILE_SYNCHRONOUS_IO_NONALERT
);
2678 if (!NT_SUCCESS (Status
))
2680 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2684 Status
= NtDeviceIoControlFile (FileHandle
,
2689 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2694 if (!NT_SUCCESS (Status
))
2696 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2697 NtClose (FileHandle
);
2701 RtlFreeHeap (ProcessHeap
,
2705 NtClose (FileHandle
);
2708 Entry1
= Entry1
->Flink
;
2714 BOOL
SetMountedDeviceValues(PPARTLIST List
)
2716 PLIST_ENTRY Entry1
, Entry2
;
2717 PDISKENTRY DiskEntry
;
2718 PPARTENTRY PartEntry
;
2726 Entry1
= List
->DiskListHead
.Flink
;
2727 while (Entry1
!= &List
->DiskListHead
)
2729 DiskEntry
= CONTAINING_RECORD (Entry1
,
2733 Entry2
= DiskEntry
->PartListHead
.Flink
;
2734 while (Entry2
!= &DiskEntry
->PartListHead
)
2736 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2737 if (!PartEntry
->Unpartitioned
)
2741 if (PartEntry
->DriveLetter
[i
])
2743 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
[i
], DiskEntry
->Signature
, PartEntry
->PartInfo
[i
].StartingOffset
))
2750 Entry2
= Entry2
->Flink
;
2752 Entry1
= Entry1
->Flink
;