3 * Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS text-mode setup
21 * FILE: subsys/system/usetup/partlist.c
22 * PURPOSE: Partition list functions
23 * PROGRAMMER: Eric Kohl
24 * Casper S. Hornstrup (chorns@users.sourceforge.net)
34 /* FUNCTIONS ****************************************************************/
41 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
45 RtlInitUnicodeString(&DiskEntry
->DriverName
,
49 L
"\\Scsi\\Scsi Port %lu",
52 RtlZeroMemory(&QueryTable
,
55 QueryTable
[0].Name
= L
"Driver";
56 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
57 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
59 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
64 if (!NT_SUCCESS(Status
))
66 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
85 /* Assign drive letters to primary partitions */
86 Entry1
= List
->DiskListHead
.Flink
;
87 while (Entry1
!= &List
->DiskListHead
)
89 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
91 if (!IsListEmpty(&DiskEntry
->PartListHead
))
93 PartEntry
= CONTAINING_RECORD(DiskEntry
->PartListHead
.Flink
,
97 for (i
= 0; i
< 4; i
++)
98 PartEntry
->DriveLetter
[i
] = 0;
100 if (PartEntry
->Unpartitioned
== FALSE
)
102 for (i
= 0; i
< 4; i
++)
104 if (IsContainerPartition(PartEntry
->PartInfo
[i
].PartitionType
))
107 if (IsRecognizedPartition(PartEntry
->PartInfo
[i
].PartitionType
) ||
108 (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
109 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0LL))
113 PartEntry
->DriveLetter
[i
] = Letter
;
121 Entry1
= Entry1
->Flink
;
124 /* Assign drive letters to logical drives */
126 Entry1
= List
->DiskListHead
.Flink
;
127 while (Entry1
!= &List
->DiskListHead
)
129 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
131 Entry2
= DiskEntry
->PartListHead
.Flink
;
132 if (Entry2
!= &DiskEntry
->PartListHead
)
134 Entry2
= Entry2
->Flink
;
135 while (Entry2
!= &DiskEntry
->PartListHead
)
137 PartEntry
= CONTAINING_RECORD(Entry2
,
141 PartEntry
->DriveLetter
= 0;
143 if (PartEntry
->Unpartitioned
== FALSE
&&
144 !IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
146 if (IsRecognizedPartition(PartEntry
->PartInfo
[0].PartitionType
) ||
147 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
148 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
152 PartEntry
->DriveLetter
= Letter
;
158 Entry2
= Entry2
->Flink
;
162 Entry1
= Entry1
->Flink
;
170 UpdatePartitionNumbers(
171 PDISKENTRY DiskEntry
)
173 PPARTENTRY PartEntry
;
179 Entry
= DiskEntry
->PartListHead
.Flink
;
180 while (Entry
!= &DiskEntry
->PartListHead
)
182 PartEntry
= CONTAINING_RECORD(Entry
,
186 if (PartEntry
->Unpartitioned
== TRUE
)
188 for (i
= 0; i
< 4; i
++)
190 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
195 for (i
= 0; i
< 4; i
++)
197 if (IsContainerPartition(PartEntry
->PartInfo
[i
].PartitionType
))
199 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
201 else if (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
202 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
== 0ULL)
204 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
208 PartEntry
->PartInfo
[i
].PartitionNumber
= PartNumber
;
214 Entry
= Entry
->Flink
;
223 PDISKENTRY DiskEntry
,
224 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
)
226 PPARTENTRY PartEntry
;
230 for (i
= 0; i
< LayoutBuffer
->PartitionCount
; i
+= 4)
232 for (j
= 0; j
< 4; j
++)
234 if (LayoutBuffer
->PartitionEntry
[i
+j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
235 LayoutBuffer
->PartitionEntry
[i
+j
].PartitionLength
.QuadPart
!= 0ULL)
246 PartEntry
= (PPARTENTRY
)RtlAllocateHeap(ProcessHeap
,
249 if (PartEntry
== NULL
)
254 RtlZeroMemory(PartEntry
,
257 PartEntry
->Unpartitioned
= FALSE
;
259 for (j
= 0; j
< 4; j
++)
261 RtlCopyMemory(&PartEntry
->PartInfo
[j
],
262 &LayoutBuffer
->PartitionEntry
[i
+j
],
263 sizeof(PARTITION_INFORMATION
));
266 if (IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
268 PartEntry
->FormatState
= Unformatted
;
270 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
271 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
272 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
273 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
) ||
274 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
275 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
278 if (CheckFatFormat())
280 PartEntry
->FormatState
= Preformatted
;
284 PartEntry
->FormatState
= Unformatted
;
287 PartEntry
->FormatState
= Preformatted
;
289 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_EXT2
)
292 if (CheckExt2Format())
294 PartEntry
->FormatState
= Preformatted
;
298 PartEntry
->FormatState
= Unformatted
;
301 PartEntry
->FormatState
= Preformatted
;
303 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
306 if (CheckNtfsFormat())
308 PartEntry
->FormatState
= Preformatted
;
310 else if (CheckHpfsFormat())
312 PartEntry
->FormatState
= Preformatted
;
316 PartEntry
->FormatState
= Unformatted
;
319 PartEntry
->FormatState
= Preformatted
;
323 PartEntry
->FormatState
= UnknownFormat
;
326 InsertTailList(&DiskEntry
->PartListHead
,
327 &PartEntry
->ListEntry
);
334 ScanForUnpartitionedDiskSpace(
335 PDISKENTRY DiskEntry
)
337 ULONGLONG LastStartingOffset
;
338 ULONGLONG LastPartitionLength
;
339 ULONGLONG LastUnusedPartitionLength
;
340 PPARTENTRY PartEntry
;
341 PPARTENTRY NewPartEntry
;
346 if (IsListEmpty (&DiskEntry
->PartListHead
))
348 /* Create a partition table that represents the empty disk */
349 PartEntry
= (PPARTENTRY
)RtlAllocateHeap(ProcessHeap
,
352 if (PartEntry
== NULL
)
355 RtlZeroMemory(PartEntry
,
358 PartEntry
->Unpartitioned
= TRUE
;
359 PartEntry
->UnpartitionedOffset
= 0ULL;
360 PartEntry
->UnpartitionedLength
= DiskEntry
->DiskSize
;
362 PartEntry
->FormatState
= Unformatted
;
364 InsertTailList(&DiskEntry
->PartListHead
,
365 &PartEntry
->ListEntry
);
369 /* Start partition at head 1, cylinder 0 */
370 LastStartingOffset
= DiskEntry
->TrackSize
;
371 LastPartitionLength
= 0ULL;
372 LastUnusedPartitionLength
= 0ULL;
375 Entry
= DiskEntry
->PartListHead
.Flink
;
376 while (Entry
!= &DiskEntry
->PartListHead
)
378 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
380 for (j
= 0; j
< 4; j
++)
382 if ((!IsContainerPartition (PartEntry
->PartInfo
[j
].PartitionType
)) &&
383 (PartEntry
->PartInfo
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
384 PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
!= 0LL))
386 LastUnusedPartitionLength
=
387 PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
-
388 (LastStartingOffset
+ LastPartitionLength
);
390 if (PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
> (LastStartingOffset
+ LastPartitionLength
) &&
391 LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
393 DPRINT("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
395 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap(ProcessHeap
,
398 if (NewPartEntry
== NULL
)
401 RtlZeroMemory(NewPartEntry
,
404 NewPartEntry
->Unpartitioned
= TRUE
;
405 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
406 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
408 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
410 NewPartEntry
->FormatState
= Unformatted
;
412 /* Insert the table into the list */
413 InsertTailList(&PartEntry
->ListEntry
,
414 &NewPartEntry
->ListEntry
);
417 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
418 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
423 Entry
= Entry
->Flink
;
426 /* Check for trailing unpartitioned disk space */
427 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
429 /* Round-down to cylinder size */
430 LastUnusedPartitionLength
=
431 (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
))
432 & ~(DiskEntry
->CylinderSize
- 1);
434 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
436 DPRINT("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
438 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap(ProcessHeap
,
441 if (NewPartEntry
== NULL
)
444 RtlZeroMemory(NewPartEntry
,
447 NewPartEntry
->Unpartitioned
= TRUE
;
448 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
449 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
451 /* Append the table to the list */
452 InsertTailList(&DiskEntry
->PartListHead
,
453 &NewPartEntry
->ListEntry
);
462 DiskIdentifierQueryRoutine(
470 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
471 UNICODE_STRING NameU
;
473 if (ValueType
== REG_SZ
&&
474 ValueLength
== 20 * sizeof(WCHAR
))
476 NameU
.Buffer
= (PWCHAR
)ValueData
;
477 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
478 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
480 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
481 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
483 return STATUS_SUCCESS
;
486 return STATUS_UNSUCCESSFUL
;
492 DiskConfigurationDataQueryRoutine(
500 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
501 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
502 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
505 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
506 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
507 return STATUS_UNSUCCESSFUL
;
509 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
511 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
513 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
514 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
515 return STATUS_UNSUCCESSFUL
;
518 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
520 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
521 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
524 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
525 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
527 return STATUS_SUCCESS
;
530 return STATUS_UNSUCCESSFUL
;
536 SystemConfigurationDataQueryRoutine(
544 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
545 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
548 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
549 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
550 return STATUS_UNSUCCESSFUL
;
552 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
554 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
556 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
557 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
558 return STATUS_UNSUCCESSFUL
;
561 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
563 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
564 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
567 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
568 if (*Int13Drives
== NULL
)
569 return STATUS_NO_MEMORY
;
572 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
573 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
574 return STATUS_SUCCESS
;
577 return STATUS_UNSUCCESSFUL
;
581 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
584 EnumerateBiosDiskEntries(
587 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
592 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
593 PBIOSDISKENTRY BiosDiskEntry
;
595 memset(QueryTable
, 0, sizeof(QueryTable
));
597 QueryTable
[1].Name
= L
"Configuration Data";
598 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
600 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
601 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
605 if (!NT_SUCCESS(Status
))
607 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
614 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
615 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
620 if (!NT_SUCCESS(Status
))
625 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
626 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
631 if (NT_SUCCESS(Status
))
635 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
636 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
641 if (!NT_SUCCESS(Status
))
643 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
647 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
648 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
653 if (NT_SUCCESS(Status
))
655 QueryTable
[0].Name
= L
"Identifier";
656 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
657 QueryTable
[1].Name
= L
"Configuration Data";
658 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
663 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
664 if (BiosDiskEntry
== NULL
)
669 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
670 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
673 (PVOID
)BiosDiskEntry
,
675 if (!NT_SUCCESS(Status
))
677 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
681 BiosDiskEntry
->DiskNumber
= DiskCount
;
682 BiosDiskEntry
->Recognized
= FALSE
;
684 if (DiskCount
< Int13Drives
[0].NumberDrives
)
686 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
690 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
693 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
695 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
696 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
697 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
698 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
699 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
700 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
701 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
702 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
703 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
704 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
705 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
711 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
719 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
730 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
731 DISK_GEOMETRY DiskGeometry
;
732 SCSI_ADDRESS ScsiAddress
;
733 PDISKENTRY DiskEntry
;
734 IO_STATUS_BLOCK Iosb
;
736 PPARTITION_SECTOR Mbr
;
738 LARGE_INTEGER FileOffset
;
739 WCHAR Identifier
[20];
743 PLIST_ENTRY ListEntry
;
744 PBIOSDISKENTRY BiosDiskEntry
;
745 ULONG LayoutBufferSize
;
747 Status
= NtDeviceIoControlFile(FileHandle
,
752 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
756 sizeof(DISK_GEOMETRY
));
757 if (!NT_SUCCESS(Status
))
762 if (DiskGeometry
.MediaType
!= FixedMedia
&&
763 DiskGeometry
.MediaType
!= RemovableMedia
)
768 Status
= NtDeviceIoControlFile(FileHandle
,
773 IOCTL_SCSI_GET_ADDRESS
,
777 sizeof(SCSI_ADDRESS
));
778 if (!NT_SUCCESS(Status
))
783 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
785 DiskGeometry
.BytesPerSector
);
791 FileOffset
.QuadPart
= 0;
792 Status
= NtReadFile(FileHandle
,
798 DiskGeometry
.BytesPerSector
,
801 if (!NT_SUCCESS(Status
))
803 RtlFreeHeap(ProcessHeap
,
806 DPRINT1("NtReadFile failed, status=%x\n", Status
);
809 Signature
= Mbr
->Signature
;
811 /* Calculate the MBR checksum */
813 Buffer
= (PULONG
)Mbr
;
814 for (i
= 0; i
< 128; i
++)
816 Checksum
+= Buffer
[i
];
818 Checksum
= ~Checksum
+ 1;
820 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
821 DPRINT("Identifier: %S\n", Identifier
);
823 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap(ProcessHeap
,
826 if (DiskEntry
== NULL
)
831 DiskEntry
->Checksum
= Checksum
;
832 DiskEntry
->Signature
= Signature
;
835 /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
836 DiskEntry
->Modified
= TRUE
;
838 DiskEntry
->BiosFound
= FALSE
;
840 /* Check if this disk has a valid MBR */
841 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
842 DiskEntry
->NoMbr
= TRUE
;
844 DiskEntry
->NoMbr
= FALSE
;
846 /* Free Mbr sector buffer */
847 RtlFreeHeap(ProcessHeap
,
851 ListEntry
= List
->BiosDiskListHead
.Flink
;
852 while(ListEntry
!= &List
->BiosDiskListHead
)
854 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
856 * Compare the size from bios and the reported size from driver.
857 * If we have more than one disk with a zero or with the same signatur
858 * we must create new signatures and reboot. After the reboot,
859 * it is possible to identify the disks.
861 if (BiosDiskEntry
->Signature
== Signature
&&
862 BiosDiskEntry
->Checksum
== Checksum
&&
863 !BiosDiskEntry
->Recognized
)
865 if (!DiskEntry
->BiosFound
)
867 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
868 DiskEntry
->BiosFound
= TRUE
;
869 BiosDiskEntry
->Recognized
= TRUE
;
875 ListEntry
= ListEntry
->Flink
;
878 if (!DiskEntry
->BiosFound
)
881 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
884 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
888 InitializeListHead(&DiskEntry
->PartListHead
);
890 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
891 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
892 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
893 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
895 DPRINT ("Cylinders %I64u\n", DiskEntry
->Cylinders
);
896 DPRINT ("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
897 DPRINT ("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
898 DPRINT ("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
900 DiskEntry
->TrackSize
=
901 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
902 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
903 DiskEntry
->CylinderSize
=
904 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
905 DiskEntry
->TrackSize
;
906 DiskEntry
->DiskSize
=
907 DiskGeometry
.Cylinders
.QuadPart
*
908 DiskEntry
->CylinderSize
;
910 DiskEntry
->DiskNumber
= DiskNumber
;
911 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
912 DiskEntry
->Bus
= ScsiAddress
.PathId
;
913 DiskEntry
->Id
= ScsiAddress
.TargetId
;
915 GetDriverName(DiskEntry
);
917 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
920 * Allocate a buffer for 26 logical drives (2 entries each == 52)
921 * plus the main partiton table (4 entries). Total 56 entries.
923 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
924 ((56 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
925 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap(ProcessHeap
,
928 if (LayoutBuffer
== NULL
)
933 Status
= NtDeviceIoControlFile(FileHandle
,
938 IOCTL_DISK_GET_DRIVE_LAYOUT
,
943 if (NT_SUCCESS(Status
))
945 if (LayoutBuffer
->PartitionCount
== 0)
947 DiskEntry
->NewDisk
= TRUE
;
950 AddPartitionToList(DiskNumber
,
954 ScanForUnpartitionedDiskSpace(DiskEntry
);
957 RtlFreeHeap(ProcessHeap
,
971 OBJECT_ATTRIBUTES ObjectAttributes
;
972 SYSTEM_DEVICE_INFORMATION Sdi
;
973 IO_STATUS_BLOCK Iosb
;
977 WCHAR Buffer
[MAX_PATH
];
981 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
990 List
->Bottom
= Bottom
;
995 List
->TopDisk
= (ULONG
)-1;
996 List
->TopPartition
= (ULONG
)-1;
998 List
->CurrentDisk
= NULL
;
999 List
->CurrentPartition
= NULL
;
1000 List
->CurrentPartitionNumber
= 0;
1002 InitializeListHead(&List
->DiskListHead
);
1003 InitializeListHead(&List
->BiosDiskListHead
);
1005 EnumerateBiosDiskEntries(List
);
1007 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1009 sizeof(SYSTEM_DEVICE_INFORMATION
),
1011 if (!NT_SUCCESS(Status
))
1013 RtlFreeHeap(ProcessHeap
, 0, List
);
1017 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1020 L
"\\Device\\Harddisk%d\\Partition0",
1022 RtlInitUnicodeString(&Name
,
1025 InitializeObjectAttributes(&ObjectAttributes
,
1031 Status
= NtOpenFile(&FileHandle
,
1032 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1036 FILE_SYNCHRONOUS_IO_NONALERT
);
1037 if (NT_SUCCESS(Status
))
1039 AddDiskToList(FileHandle
,
1043 NtClose(FileHandle
);
1047 AssignDriverLetters(List
);
1050 List
->TopPartition
= 0;
1052 /* Search for first usable disk and partition */
1053 if (IsListEmpty(&List
->DiskListHead
))
1055 List
->CurrentDisk
= NULL
;
1056 List
->CurrentPartition
= NULL
;
1057 List
->CurrentPartitionNumber
= 0;
1061 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1065 if (IsListEmpty(&List
->CurrentDisk
->PartListHead
))
1067 List
->CurrentPartition
= 0;
1068 List
->CurrentPartitionNumber
= 0;
1072 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PartListHead
.Flink
,
1075 List
->CurrentPartitionNumber
= 0;
1084 DestroyPartitionList(
1087 PDISKENTRY DiskEntry
;
1088 PBIOSDISKENTRY BiosDiskEntry
;
1089 PPARTENTRY PartEntry
;
1092 /* Release disk and partition info */
1093 while (!IsListEmpty(&List
->DiskListHead
))
1095 Entry
= RemoveHeadList(&List
->DiskListHead
);
1096 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1098 /* Release driver name */
1099 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1101 /* Release partition array */
1102 while (!IsListEmpty(&DiskEntry
->PartListHead
))
1104 Entry
= RemoveHeadList(&DiskEntry
->PartListHead
);
1105 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1107 RtlFreeHeap(ProcessHeap
,
1112 /* Release disk entry */
1113 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1116 /* release the bios disk info */
1117 while(!IsListEmpty(&List
->BiosDiskListHead
))
1119 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1120 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1122 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1125 /* Release list head */
1126 RtlFreeHeap(ProcessHeap
, 0, List
);
1140 Width
= List
->Right
- List
->Left
- 1;
1141 Height
= List
->Bottom
- List
->Top
- 2;
1143 coPos
.X
= List
->Left
+ 1;
1144 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1146 if (List
->Line
>= 0 && List
->Line
<= Height
)
1148 FillConsoleOutputAttribute(StdOutput
,
1149 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1154 FillConsoleOutputCharacterA(StdOutput
,
1169 PDISKENTRY DiskEntry
,
1170 PPARTENTRY PartEntry
,
1173 CHAR LineBuffer
[128];
1178 LARGE_INTEGER PartSize
;
1183 Width
= List
->Right
- List
->Left
- 1;
1184 Height
= List
->Bottom
- List
->Top
- 2;
1186 coPos
.X
= List
->Left
+ 1;
1187 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1189 if (PartEntry
->Unpartitioned
== TRUE
)
1192 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1194 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1195 Unit
= MUIGetString(STRING_GB
);
1199 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1201 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1202 Unit
= MUIGetString(STRING_MB
);
1206 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1207 Unit
= MUIGetString(STRING_KB
);
1211 MUIGetString(STRING_UNPSPACE
),
1217 /* Determine partition type */
1219 if (PartEntry
->New
== TRUE
)
1221 PartType
= MUIGetString(STRING_UNFORMATTED
);
1223 else if (PartEntry
->Unpartitioned
== FALSE
)
1225 if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_12
) ||
1226 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_16
) ||
1227 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_HUGE
) ||
1228 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_XINT13
))
1232 else if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32
) ||
1233 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32_XINT13
))
1237 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_EXT2
)
1241 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_IFS
)
1243 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1248 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1250 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1251 Unit
= MUIGetString(STRING_GB
);
1255 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1257 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1258 Unit
= MUIGetString(STRING_MB
);
1262 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1263 Unit
= MUIGetString(STRING_KB
);
1266 if (PartType
== NULL
)
1269 MUIGetString(STRING_HDDINFOUNK5
),
1270 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1271 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1272 PartEntry
->PartInfo
[PartNumber
].PartitionType
,
1279 "%c%c %-24s %6lu %s",
1280 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1281 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1288 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1289 List
->CurrentPartition
== PartEntry
&&
1290 List
->CurrentPartitionNumber
== PartNumber
) ?
1291 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1292 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1294 if (List
->Line
>= 0 && List
->Line
<= Height
)
1296 FillConsoleOutputCharacterA(StdOutput
,
1304 if (List
->Line
>= 0 && List
->Line
<= Height
)
1306 FillConsoleOutputAttribute(StdOutput
,
1314 if (List
->Line
>= 0 && List
->Line
<= Height
)
1316 WriteConsoleOutputCharacterA(StdOutput
,
1318 min(strlen(LineBuffer
), Width
),
1331 PDISKENTRY DiskEntry
)
1333 PPARTENTRY PartEntry
;
1335 CHAR LineBuffer
[128];
1340 ULARGE_INTEGER DiskSize
;
1344 Width
= List
->Right
- List
->Left
- 1;
1345 Height
= List
->Bottom
- List
->Top
- 2;
1347 coPos
.X
= List
->Left
+ 1;
1348 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1351 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1353 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1354 Unit
= MUIGetString(STRING_GB
);
1359 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1360 if (DiskSize
.QuadPart
== 0)
1361 DiskSize
.QuadPart
= 1;
1362 Unit
= MUIGetString(STRING_MB
);
1365 if (DiskEntry
->DriverName
.Length
> 0)
1368 MUIGetString(STRING_HDINFOPARTSELECT
),
1371 DiskEntry
->DiskNumber
,
1375 DiskEntry
->DriverName
.Buffer
);
1380 MUIGetString(STRING_HDDINFOUNK6
),
1383 DiskEntry
->DiskNumber
,
1389 if (List
->Line
>= 0 && List
->Line
<= Height
)
1391 FillConsoleOutputAttribute(StdOutput
,
1392 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1397 FillConsoleOutputCharacterA(StdOutput
,
1405 if (List
->Line
>= 0 && List
->Line
<= Height
)
1407 WriteConsoleOutputCharacterA(StdOutput
,
1409 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1416 /* Print separator line */
1417 PrintEmptyLine(List
);
1419 /* Print partition lines*/
1420 Entry
= DiskEntry
->PartListHead
.Flink
;
1421 while (Entry
!= &DiskEntry
->PartListHead
)
1423 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1425 /* Print disk entry */
1426 for (i
= 0; i
< 4; i
++)
1428 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
1429 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
1431 PrintPartitionData(List
,
1438 /* Print unpartitioned entry */
1439 if (PartEntry
->Unpartitioned
)
1441 PrintPartitionData(List
,
1447 Entry
= Entry
->Flink
;
1450 /* Print separator line */
1451 PrintEmptyLine(List
);
1459 PLIST_ENTRY Entry
, Entry2
;
1460 PDISKENTRY DiskEntry
;
1461 PPARTENTRY PartEntry
= NULL
;
1465 SHORT CurrentDiskLine
;
1466 SHORT CurrentPartLine
;
1468 BOOL CurrentPartLineFound
= FALSE
;
1469 BOOL CurrentDiskLineFound
= FALSE
;
1471 /* Calculate the line of the current disk and partition */
1472 CurrentDiskLine
= 0;
1473 CurrentPartLine
= 0;
1476 Entry
= List
->DiskListHead
.Flink
;
1477 while (Entry
!= &List
->DiskListHead
)
1479 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1482 if (CurrentPartLineFound
== FALSE
)
1484 CurrentPartLine
+= 2;
1487 Entry2
= DiskEntry
->PartListHead
.Flink
;
1488 while (Entry2
!= &DiskEntry
->PartListHead
)
1490 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1491 if (PartEntry
== List
->CurrentPartition
)
1493 CurrentPartLineFound
= TRUE
;
1496 Entry2
= Entry2
->Flink
;
1497 if (CurrentPartLineFound
== FALSE
)
1505 if (DiskEntry
== List
->CurrentDisk
)
1507 CurrentDiskLineFound
= TRUE
;
1510 Entry
= Entry
->Flink
;
1511 if (Entry
!= &List
->DiskListHead
)
1513 if (CurrentDiskLineFound
== FALSE
)
1516 CurrentDiskLine
= CurrentPartLine
;
1527 /* If it possible, make the disk name visible */
1528 if (CurrentPartLine
< List
->Offset
)
1530 List
->Offset
= CurrentPartLine
;
1532 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1534 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1537 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1539 List
->Offset
= CurrentDiskLine
;
1542 /* draw upper left corner */
1543 coPos
.X
= List
->Left
;
1544 coPos
.Y
= List
->Top
;
1545 FillConsoleOutputCharacterA(StdOutput
,
1551 /* draw upper edge */
1552 coPos
.X
= List
->Left
+ 1;
1553 coPos
.Y
= List
->Top
;
1554 if (List
->Offset
== 0)
1556 FillConsoleOutputCharacterA(StdOutput
,
1558 List
->Right
- List
->Left
- 1,
1564 FillConsoleOutputCharacterA(StdOutput
,
1566 List
->Right
- List
->Left
- 5,
1569 coPos
.X
= List
->Right
- 5;
1570 WriteConsoleOutputCharacterA(StdOutput
,
1575 coPos
.X
= List
->Right
- 2;
1576 FillConsoleOutputCharacterA(StdOutput
,
1583 /* draw upper right corner */
1584 coPos
.X
= List
->Right
;
1585 coPos
.Y
= List
->Top
;
1586 FillConsoleOutputCharacterA(StdOutput
,
1592 /* draw left and right edge */
1593 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1595 coPos
.X
= List
->Left
;
1597 FillConsoleOutputCharacterA(StdOutput
,
1603 coPos
.X
= List
->Right
;
1604 FillConsoleOutputCharacterA(StdOutput
,
1611 /* draw lower left corner */
1612 coPos
.X
= List
->Left
;
1613 coPos
.Y
= List
->Bottom
;
1614 FillConsoleOutputCharacterA(StdOutput
,
1620 /* draw lower edge */
1621 coPos
.X
= List
->Left
+ 1;
1622 coPos
.Y
= List
->Bottom
;
1623 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1625 FillConsoleOutputCharacterA(StdOutput
,
1627 List
->Right
- List
->Left
- 1,
1633 FillConsoleOutputCharacterA(StdOutput
,
1635 List
->Right
- List
->Left
- 5,
1638 coPos
.X
= List
->Right
- 5;
1639 WriteConsoleOutputCharacterA(StdOutput
,
1640 "(\x19)", // "(down)"
1644 coPos
.X
= List
->Right
- 2;
1645 FillConsoleOutputCharacterA(StdOutput
,
1652 /* draw lower right corner */
1653 coPos
.X
= List
->Right
;
1654 coPos
.Y
= List
->Bottom
;
1655 FillConsoleOutputCharacterA(StdOutput
,
1661 /* print list entries */
1662 List
->Line
= - List
->Offset
;
1664 Entry
= List
->DiskListHead
.Flink
;
1665 while (Entry
!= &List
->DiskListHead
)
1667 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1669 /* Print disk entry */
1673 Entry
= Entry
->Flink
;
1682 ULONG PartitionNumber
)
1684 PDISKENTRY DiskEntry
;
1685 PPARTENTRY PartEntry
;
1690 /* Check for empty disks */
1691 if (IsListEmpty(&List
->DiskListHead
))
1694 /* Check for first usable entry on next disk */
1695 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1696 while (Entry1
!= &List
->DiskListHead
)
1698 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1700 if (DiskEntry
->DiskNumber
== DiskNumber
)
1702 Entry2
= DiskEntry
->PartListHead
.Flink
;
1703 while (Entry2
!= &DiskEntry
->PartListHead
)
1705 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1707 for (i
= 0; i
< 4; i
++)
1709 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1711 List
->CurrentDisk
= DiskEntry
;
1712 List
->CurrentPartition
= PartEntry
;
1713 List
->CurrentPartitionNumber
= i
;
1714 DrawPartitionList(List
);
1719 Entry2
= Entry2
->Flink
;
1725 Entry1
= Entry1
->Flink
;
1733 ScrollDownPartitionList(
1736 PDISKENTRY DiskEntry
;
1737 PPARTENTRY PartEntry
;
1742 /* Check for empty disks */
1743 if (IsListEmpty(&List
->DiskListHead
))
1746 /* Check for next usable entry on current disk */
1747 if (List
->CurrentPartition
!= NULL
)
1749 Entry2
= &List
->CurrentPartition
->ListEntry
;
1750 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1752 /* Check if we can move inside primary partitions */
1753 for (i
= List
->CurrentPartitionNumber
+ 1; i
< 4; i
++)
1755 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1761 /* We're out of partitions in the current partition table.
1762 Try to move to the next one if possible. */
1763 Entry2
= Entry2
->Flink
;
1767 /* Just advance to the next partition */
1768 List
->CurrentPartitionNumber
= i
;
1769 DrawPartitionList(List
);
1773 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1775 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1777 // if (PartEntry->HidePartEntry == FALSE)
1779 List
->CurrentPartition
= PartEntry
;
1780 List
->CurrentPartitionNumber
= 0;
1781 DrawPartitionList(List
);
1785 Entry2
= Entry2
->Flink
;
1789 /* Check for first usable entry on next disk */
1790 if (List
->CurrentDisk
!= NULL
)
1792 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1793 while (Entry1
!= &List
->DiskListHead
)
1795 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1797 Entry2
= DiskEntry
->PartListHead
.Flink
;
1798 while (Entry2
!= &DiskEntry
->PartListHead
)
1800 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1802 // if (PartEntry->HidePartEntry == FALSE)
1804 List
->CurrentDisk
= DiskEntry
;
1805 List
->CurrentPartition
= PartEntry
;
1806 List
->CurrentPartitionNumber
= 0;
1807 DrawPartitionList(List
);
1811 Entry2
= Entry2
->Flink
;
1814 Entry1
= Entry1
->Flink
;
1821 ScrollUpPartitionList(
1824 PDISKENTRY DiskEntry
;
1825 PPARTENTRY PartEntry
;
1830 /* Check for empty disks */
1831 if (IsListEmpty(&List
->DiskListHead
))
1834 /* check for previous usable entry on current disk */
1835 if (List
->CurrentPartition
!= NULL
)
1837 Entry2
= &List
->CurrentPartition
->ListEntry
;
1838 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1840 /* Check if we can move inside primary partitions */
1841 if (List
->CurrentPartitionNumber
> 0)
1843 /* Find a previous partition */
1844 for (i
= List
->CurrentPartitionNumber
- 1; i
> 0; i
--)
1846 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1850 /* Move to it and return */
1851 List
->CurrentPartitionNumber
= i
;
1852 DrawPartitionList(List
);
1856 /* Move to the previous entry */
1857 Entry2
= Entry2
->Blink
;
1859 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1861 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1863 // if (PartEntry->HidePartEntry == FALSE)
1865 List
->CurrentPartition
= PartEntry
;
1867 /* Find last existing partition in the table */
1868 for (i
= 3; i
> 0; i
--)
1870 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1875 List
->CurrentPartitionNumber
= i
;
1877 /* Draw partition list and return */
1878 DrawPartitionList(List
);
1882 Entry2
= Entry2
->Blink
;
1887 /* check for last usable entry on previous disk */
1888 if (List
->CurrentDisk
!= NULL
)
1890 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1891 while (Entry1
!= &List
->DiskListHead
)
1893 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1895 Entry2
= DiskEntry
->PartListHead
.Blink
;
1896 while (Entry2
!= &DiskEntry
->PartListHead
)
1898 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1900 // if (PartEntry->HidePartEntry == FALSE)
1902 List
->CurrentDisk
= DiskEntry
;
1903 List
->CurrentPartition
= PartEntry
;
1905 /* Find last existing partition in the table */
1906 for (i
= 3; i
> 0; i
--)
1908 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1913 List
->CurrentPartitionNumber
= i
;
1915 /* Draw partition list and return */
1916 DrawPartitionList(List
);
1920 Entry2
= Entry2
->Blink
;
1923 Entry1
= Entry1
->Blink
;
1931 GetPrevPartitionedEntry(
1932 PDISKENTRY DiskEntry
,
1933 PPARTENTRY CurrentEntry
)
1935 PPARTENTRY PrevEntry
;
1938 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1941 Entry
= CurrentEntry
->ListEntry
.Blink
;
1942 while (Entry
!= &DiskEntry
->PartListHead
)
1944 PrevEntry
= CONTAINING_RECORD(Entry
,
1947 if (PrevEntry
->Unpartitioned
== FALSE
)
1950 Entry
= Entry
->Blink
;
1959 GetNextPartitionedEntry(
1960 PDISKENTRY DiskEntry
,
1961 PPARTENTRY CurrentEntry
)
1963 PPARTENTRY NextEntry
;
1966 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1969 Entry
= CurrentEntry
->ListEntry
.Flink
;
1970 while (Entry
!= &DiskEntry
->PartListHead
)
1972 NextEntry
= CONTAINING_RECORD(Entry
,
1975 if (NextEntry
->Unpartitioned
== FALSE
)
1978 Entry
= Entry
->Flink
;
1987 GetPrevUnpartitionedEntry(
1988 PDISKENTRY DiskEntry
,
1989 PPARTENTRY PartEntry
)
1991 PPARTENTRY PrevPartEntry
;
1993 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1995 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
1998 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1999 return PrevPartEntry
;
2008 GetNextUnpartitionedEntry(
2009 PDISKENTRY DiskEntry
,
2010 PPARTENTRY PartEntry
)
2012 PPARTENTRY NextPartEntry
;
2014 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
2016 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2019 if (NextPartEntry
->Unpartitioned
== TRUE
)
2020 return NextPartEntry
;
2030 ULONGLONG PartitionSize
,
2033 PDISKENTRY DiskEntry
;
2034 PPARTENTRY PartEntry
;
2035 PPARTENTRY PrevPartEntry
;
2036 PPARTENTRY NextPartEntry
;
2037 PPARTENTRY NewPartEntry
;
2040 List
->CurrentDisk
== NULL
||
2041 List
->CurrentPartition
== NULL
||
2042 List
->CurrentPartition
->Unpartitioned
== FALSE
)
2047 DiskEntry
= List
->CurrentDisk
;
2048 PartEntry
= List
->CurrentPartition
;
2050 if (AutoCreate
== TRUE
||
2051 PartitionSize
== PartEntry
->UnpartitionedLength
)
2053 /* Convert current entry to 'new (unformatted)' */
2054 PartEntry
->FormatState
= Unformatted
;
2055 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
2056 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
2057 PartEntry
->PartInfo
[0].HiddenSectors
=
2058 (ULONG
)(PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2059 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
2060 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
2061 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
2062 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
2063 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2064 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2065 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
2066 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
2068 /* Get previous and next partition entries */
2069 PrevPartEntry
= GetPrevPartitionedEntry(DiskEntry
,
2071 NextPartEntry
= GetNextPartitionedEntry(DiskEntry
,
2074 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2076 /* Current entry is in the middle of the list */
2078 /* Copy previous container partition data to current entry */
2079 RtlCopyMemory(&PartEntry
->PartInfo
[1],
2080 &PrevPartEntry
->PartInfo
[1],
2081 sizeof(PARTITION_INFORMATION
));
2082 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2084 /* Update previous container partition data */
2086 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2087 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2088 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2089 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2091 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2093 /* Special case - previous partition is first partition */
2094 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2095 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2099 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2100 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2103 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2105 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2107 /* Current entry is the first entry */
2110 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2112 /* Current entry is the last entry */
2114 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2115 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2116 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2117 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2119 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2121 /* Special case - previous partition is first partition */
2122 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2123 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2127 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2128 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2131 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2132 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2133 (1024LL * 255LL * 63LL * 512LL))
2135 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2139 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2142 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2143 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2146 PartEntry
->AutoCreate
= AutoCreate
;
2147 PartEntry
->New
= TRUE
;
2148 PartEntry
->Unpartitioned
= FALSE
;
2149 PartEntry
->UnpartitionedOffset
= 0ULL;
2150 PartEntry
->UnpartitionedLength
= 0ULL;
2154 /* Insert an initialize a new partition entry */
2155 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap(ProcessHeap
,
2158 if (NewPartEntry
== NULL
)
2161 RtlZeroMemory(NewPartEntry
,
2164 /* Insert the new entry into the list */
2165 InsertTailList(&PartEntry
->ListEntry
,
2166 &NewPartEntry
->ListEntry
);
2168 NewPartEntry
->New
= TRUE
;
2170 NewPartEntry
->FormatState
= Unformatted
;
2171 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
2172 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
2173 NewPartEntry
->PartInfo
[0].HiddenSectors
=
2174 (ULONG
)(NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2175 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
2176 PartitionSize
- DiskEntry
->TrackSize
;
2177 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
2178 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
2179 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2180 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2181 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
2182 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
2184 /* Get previous and next partition entries */
2185 PrevPartEntry
= GetPrevPartitionedEntry(DiskEntry
,
2187 NextPartEntry
= GetNextPartitionedEntry(DiskEntry
,
2190 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2192 /* Current entry is in the middle of the list */
2194 /* Copy previous container partition data to current entry */
2195 RtlCopyMemory(&NewPartEntry
->PartInfo
[1],
2196 &PrevPartEntry
->PartInfo
[1],
2197 sizeof(PARTITION_INFORMATION
));
2198 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2200 /* Update previous container partition data */
2201 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2202 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2203 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2204 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2206 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2208 /* Special case - previous partition is first partition */
2209 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2210 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2214 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2215 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2218 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2220 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2222 /* Current entry is the first entry */
2225 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2227 /* Current entry is the last entry */
2229 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2230 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2231 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2232 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2234 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2236 /* Special case - previous partition is first partition */
2237 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2238 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2242 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2243 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2246 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2247 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2248 (1024LL * 255LL * 63LL * 512LL))
2250 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2254 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2257 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2258 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2261 /* Update offset and size of the remaining unpartitioned disk space */
2262 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
2263 PartEntry
->UnpartitionedLength
-= PartitionSize
;
2266 DiskEntry
->Modified
= TRUE
;
2268 UpdatePartitionNumbers(DiskEntry
);
2270 AssignDriverLetters(List
);
2275 DeleteCurrentPartition(
2278 PDISKENTRY DiskEntry
;
2279 PPARTENTRY PartEntry
;
2280 PPARTENTRY PrevPartEntry
;
2281 PPARTENTRY NextPartEntry
;
2284 List
->CurrentDisk
== NULL
||
2285 List
->CurrentPartition
== NULL
||
2286 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2291 DiskEntry
= List
->CurrentDisk
;
2292 PartEntry
= List
->CurrentPartition
;
2294 /* Adjust container partition entries */
2296 /* Get previous and next partition entries */
2297 PrevPartEntry
= GetPrevPartitionedEntry(DiskEntry
,
2299 NextPartEntry
= GetNextPartitionedEntry(DiskEntry
,
2302 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2304 /* Current entry is in the middle of the list */
2307 * The first extended partition can not be deleted
2308 * as long as other extended partitions are present.
2310 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2313 /* Copy previous container partition data to current entry */
2314 RtlCopyMemory(&PrevPartEntry
->PartInfo
[1],
2315 &PartEntry
->PartInfo
[1],
2316 sizeof(PARTITION_INFORMATION
));
2317 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2319 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2322 * A primary partition can not be deleted as long as
2323 * extended partitions are present.
2327 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2329 /* Current entry is the last entry */
2330 RtlZeroMemory(&PrevPartEntry
->PartInfo
[1],
2331 sizeof(PARTITION_INFORMATION
));
2332 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2336 /* Adjust unpartitioned disk space entries */
2338 /* Get pointer to previous and next unpartitioned entries */
2339 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
,
2342 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
,
2345 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2347 /* Merge previous, current and next unpartitioned entry */
2349 /* Adjust the previous entries length */
2350 PrevPartEntry
->UnpartitionedLength
+=
2351 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2352 NextPartEntry
->UnpartitionedLength
);
2354 /* Remove the current entry */
2355 RemoveEntryList(&PartEntry
->ListEntry
);
2356 RtlFreeHeap(ProcessHeap
,
2360 /* Remove the next entry */
2361 RemoveEntryList (&NextPartEntry
->ListEntry
);
2362 RtlFreeHeap(ProcessHeap
,
2366 /* Update current partition */
2367 List
->CurrentPartition
= PrevPartEntry
;
2369 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2371 /* Merge current and previous unpartitioned entry */
2373 /* Adjust the previous entries length */
2374 PrevPartEntry
->UnpartitionedLength
+=
2375 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2377 /* Remove the current entry */
2378 RemoveEntryList(&PartEntry
->ListEntry
);
2379 RtlFreeHeap(ProcessHeap
,
2383 /* Update current partition */
2384 List
->CurrentPartition
= PrevPartEntry
;
2386 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2388 /* Merge current and next unpartitioned entry */
2390 /* Adjust the next entries offset and length */
2391 NextPartEntry
->UnpartitionedOffset
=
2392 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2393 NextPartEntry
->UnpartitionedLength
+=
2394 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2396 /* Remove the current entry */
2397 RemoveEntryList(&PartEntry
->ListEntry
);
2398 RtlFreeHeap(ProcessHeap
,
2402 /* Update current partition */
2403 List
->CurrentPartition
= NextPartEntry
;
2407 /* Nothing to merge but change current entry */
2408 PartEntry
->New
= FALSE
;
2409 PartEntry
->Unpartitioned
= TRUE
;
2410 PartEntry
->UnpartitionedOffset
=
2411 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2412 PartEntry
->UnpartitionedLength
=
2413 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2415 /* Wipe the partition table */
2416 RtlZeroMemory(&PartEntry
->PartInfo
,
2417 sizeof(PartEntry
->PartInfo
));
2420 DiskEntry
->Modified
= TRUE
;
2422 UpdatePartitionNumbers(DiskEntry
);
2424 AssignDriverLetters(List
);
2429 CheckActiveBootPartition(
2432 PDISKENTRY DiskEntry
;
2433 PPARTENTRY PartEntry
;
2434 PLIST_ENTRY ListEntry
;
2437 /* Check for empty disk list */
2438 if (IsListEmpty (&List
->DiskListHead
))
2440 List
->ActiveBootDisk
= NULL
;
2441 List
->ActiveBootPartition
= NULL
;
2442 List
->ActiveBootPartitionNumber
= 0;
2447 if (List
->ActiveBootDisk
!= NULL
&&
2448 List
->ActiveBootPartition
!= NULL
)
2450 /* We already have an active boot partition */
2455 /* Choose the currently selected disk */
2456 DiskEntry
= List
->CurrentDisk
;
2458 /* Check for empty partition list */
2459 if (IsListEmpty (&DiskEntry
->PartListHead
))
2461 List
->ActiveBootDisk
= NULL
;
2462 List
->ActiveBootPartition
= NULL
;
2463 List
->ActiveBootPartitionNumber
= 0;
2467 PartEntry
= CONTAINING_RECORD(DiskEntry
->PartListHead
.Flink
,
2471 /* Set active boot partition */
2472 if ((DiskEntry
->NewDisk
== TRUE
) ||
2473 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2474 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2475 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2476 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2478 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2479 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2480 DiskEntry
->Modified
= TRUE
;
2482 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2483 List
->ActiveBootDisk
= DiskEntry
;
2484 List
->ActiveBootPartition
= PartEntry
;
2485 List
->ActiveBootPartitionNumber
= 0;
2490 /* Disk is not new, scan all partitions to find a bootable one */
2491 List
->ActiveBootDisk
= NULL
;
2492 List
->ActiveBootPartition
= NULL
;
2493 List
->ActiveBootPartitionNumber
= 0;
2495 ListEntry
= DiskEntry
->PartListHead
.Flink
;
2496 while (ListEntry
!= &DiskEntry
->PartListHead
)
2498 PartEntry
= CONTAINING_RECORD(ListEntry
,
2502 /* Check if it's partitioned */
2503 if (!PartEntry
->Unpartitioned
)
2505 /* Go through all of its 4 partitions */
2506 for (i
= 0; i
< 4; i
++)
2508 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2509 PartEntry
->PartInfo
[i
].BootIndicator
)
2511 /* Yes, we found it */
2512 List
->ActiveBootDisk
= DiskEntry
;
2513 List
->ActiveBootPartition
= PartEntry
;
2514 List
->ActiveBootPartitionNumber
= i
;
2516 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2517 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
[i
]);
2524 /* Go to the next one */
2525 ListEntry
= ListEntry
->Flink
;
2531 CheckForLinuxFdiskPartitions(
2534 PDISKENTRY DiskEntry
;
2535 PPARTENTRY PartEntry
;
2538 ULONG PartitionCount
;
2541 Entry1
= List
->DiskListHead
.Flink
;
2542 while (Entry1
!= &List
->DiskListHead
)
2544 DiskEntry
= CONTAINING_RECORD(Entry1
,
2548 Entry2
= DiskEntry
->PartListHead
.Flink
;
2549 while (Entry2
!= &DiskEntry
->PartListHead
)
2551 PartEntry
= CONTAINING_RECORD(Entry2
,
2555 if (PartEntry
->Unpartitioned
== FALSE
)
2559 for (i
= 0; i
< 4; i
++)
2561 if (!IsContainerPartition(PartEntry
->PartInfo
[i
].PartitionType
) &&
2562 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2568 if (PartitionCount
> 1)
2574 Entry2
= Entry2
->Flink
;
2577 Entry1
= Entry1
->Flink
;
2585 WritePartitionsToDisk(
2588 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2589 OBJECT_ATTRIBUTES ObjectAttributes
;
2590 IO_STATUS_BLOCK Iosb
;
2591 WCHAR DstPath
[MAX_PATH
];
2592 UNICODE_STRING Name
;
2594 PDISKENTRY DiskEntry1
;
2595 PDISKENTRY DiskEntry2
;
2596 PPARTENTRY PartEntry
;
2599 ULONG PartitionCount
;
2600 ULONG DriveLayoutSize
;
2609 Entry1
= List
->DiskListHead
.Flink
;
2610 while (Entry1
!= &List
->DiskListHead
)
2612 DiskEntry1
= CONTAINING_RECORD(Entry1
,
2616 if (DiskEntry1
->Modified
== TRUE
)
2618 /* Count partitioned entries */
2621 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2622 while (Entry2
!= &DiskEntry1
->PartListHead
)
2624 PartEntry
= CONTAINING_RECORD(Entry2
,
2627 if (PartEntry
->Unpartitioned
== FALSE
)
2629 PartitionCount
+= 4;
2632 Entry2
= Entry2
->Flink
;
2635 if (PartitionCount
== 0)
2637 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2638 ((4 - 1) * sizeof (PARTITION_INFORMATION
));
2642 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2643 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2646 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap(ProcessHeap
,
2649 if (DriveLayout
== NULL
)
2651 DPRINT1("RtlAllocateHeap() failed\n");
2655 RtlZeroMemory(DriveLayout
,
2658 if (PartitionCount
== 0)
2660 /* delete all partitions in the mbr */
2661 DriveLayout
->PartitionCount
= 4;
2662 for (Index
= 0; Index
< 4; Index
++)
2664 DriveLayout
->PartitionEntry
[Index
].RewritePartition
= TRUE
;
2669 DriveLayout
->PartitionCount
= PartitionCount
;
2672 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2673 while (Entry2
!= &DiskEntry1
->PartListHead
)
2675 PartEntry
= CONTAINING_RECORD(Entry2
,
2678 if (PartEntry
->Unpartitioned
== FALSE
)
2680 RtlCopyMemory(&DriveLayout
->PartitionEntry
[Index
],
2681 &PartEntry
->PartInfo
[0],
2682 4 * sizeof (PARTITION_INFORMATION
));
2686 Entry2
= Entry2
->Flink
;
2690 if (DiskEntry1
->Signature
== 0)
2692 LARGE_INTEGER SystemTime
;
2693 TIME_FIELDS TimeFields
;
2695 Buffer
= (PUCHAR
)&DiskEntry1
->Signature
;
2699 NtQuerySystemTime(&SystemTime
);
2700 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
2702 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
2703 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
2704 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
2705 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
2707 if (DiskEntry1
->Signature
== 0)
2712 /* check if the signature already exist */
2714 * Check also signatures from disks, which are
2715 * not visible (bootable) by the bios.
2717 Entry2
= List
->DiskListHead
.Flink
;
2718 while (Entry2
!= &List
->DiskListHead
)
2720 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
2721 if (DiskEntry1
!= DiskEntry2
&&
2722 DiskEntry1
->Signature
== DiskEntry2
->Signature
)
2727 Entry2
= Entry2
->Flink
;
2730 if (Entry2
== &List
->DiskListHead
)
2736 /* set one partition entry to dirty, this will update the signature */
2737 DriveLayout
->PartitionEntry
[0].RewritePartition
= TRUE
;
2740 DriveLayout
->Signature
= DiskEntry1
->Signature
;
2743 L
"\\Device\\Harddisk%d\\Partition0",
2744 DiskEntry1
->DiskNumber
);
2745 RtlInitUnicodeString(&Name
,
2747 InitializeObjectAttributes(&ObjectAttributes
,
2753 Status
= NtOpenFile(&FileHandle
,
2758 FILE_SYNCHRONOUS_IO_NONALERT
);
2759 if (!NT_SUCCESS(Status
))
2761 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
2765 Status
= NtDeviceIoControlFile(FileHandle
,
2770 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2775 if (!NT_SUCCESS(Status
))
2777 DPRINT1("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2778 NtClose(FileHandle
);
2782 RtlFreeHeap(ProcessHeap
,
2786 NtClose(FileHandle
);
2789 Entry1
= Entry1
->Flink
;
2797 SetMountedDeviceValues(
2800 PLIST_ENTRY Entry1
, Entry2
;
2801 PDISKENTRY DiskEntry
;
2802 PPARTENTRY PartEntry
;
2810 Entry1
= List
->DiskListHead
.Flink
;
2811 while (Entry1
!= &List
->DiskListHead
)
2813 DiskEntry
= CONTAINING_RECORD(Entry1
,
2817 Entry2
= DiskEntry
->PartListHead
.Flink
;
2818 while (Entry2
!= &DiskEntry
->PartListHead
)
2820 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2821 if (!PartEntry
->Unpartitioned
)
2823 for (i
= 0; i
< 4; i
++)
2825 if (PartEntry
->DriveLetter
[i
])
2827 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
[i
],
2828 DiskEntry
->Signature
,
2829 PartEntry
->PartInfo
[i
].StartingOffset
))
2837 Entry2
= Entry2
->Flink
;
2840 Entry1
= Entry1
->Flink
;