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 (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
379 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
381 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
384 if (NewPartEntry
== NULL
)
387 RtlZeroMemory (NewPartEntry
,
390 NewPartEntry
->Unpartitioned
= TRUE
;
391 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
392 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
394 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
396 NewPartEntry
->FormatState
= Unformatted
;
398 /* Insert the table into the list */
399 InsertTailList (&PartEntry
->ListEntry
,
400 &NewPartEntry
->ListEntry
);
403 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
404 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
409 Entry
= Entry
->Flink
;
412 /* Check for trailing unpartitioned disk space */
413 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
415 /* Round-down to cylinder size */
416 LastUnusedPartitionLength
=
417 (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
))
418 & ~(DiskEntry
->CylinderSize
- 1);
420 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
422 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
424 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
427 if (NewPartEntry
== NULL
)
430 RtlZeroMemory (NewPartEntry
,
433 NewPartEntry
->Unpartitioned
= TRUE
;
434 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
435 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
437 /* Append the table to the list */
438 InsertTailList (&DiskEntry
->PartListHead
,
439 &NewPartEntry
->ListEntry
);
447 DiskIdentifierQueryRoutine(PWSTR ValueName
,
454 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
455 UNICODE_STRING NameU
;
457 if (ValueType
== REG_SZ
&&
458 ValueLength
== 20 * sizeof(WCHAR
))
460 NameU
.Buffer
= (PWCHAR
)ValueData
;
461 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
462 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
464 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
465 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
467 return STATUS_SUCCESS
;
469 return STATUS_UNSUCCESSFUL
;
474 DiskConfigurationDataQueryRoutine(PWSTR ValueName
,
481 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
482 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
483 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
486 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
487 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
488 return STATUS_UNSUCCESSFUL
;
490 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
491 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
492 /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
493 FullResourceDescriptor->PartialResourceList.Revision != 1)
494 return STATUS_UNSUCCESSFUL;*/
496 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
498 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
499 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
502 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
503 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
505 return STATUS_SUCCESS
;
507 return STATUS_UNSUCCESSFUL
;
512 SystemConfigurationDataQueryRoutine(PWSTR ValueName
,
519 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
520 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
523 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
524 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
525 return STATUS_UNSUCCESSFUL
;
527 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
528 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
529 /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
530 FullResourceDescriptor->PartialResourceList.Revision != 1)
531 return STATUS_UNSUCCESSFUL;*/
533 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
535 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
536 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
539 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
540 if (*Int13Drives
== NULL
)
541 return STATUS_NO_MEMORY
;
543 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
544 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
545 return STATUS_SUCCESS
;
547 return STATUS_UNSUCCESSFUL
;
549 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
552 EnumerateBiosDiskEntries(PPARTLIST PartList
)
554 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
559 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
560 PBIOSDISKENTRY BiosDiskEntry
;
562 memset(QueryTable
, 0, sizeof(QueryTable
));
564 QueryTable
[1].Name
= L
"Configuration Data";
565 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
567 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
568 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
572 if (!NT_SUCCESS(Status
))
574 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
581 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
582 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
587 if (!NT_SUCCESS(Status
))
592 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
593 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
598 if (NT_SUCCESS(Status
))
602 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
603 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
608 if (!NT_SUCCESS(Status
))
610 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
614 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
615 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
620 if (NT_SUCCESS(Status
))
622 QueryTable
[0].Name
= L
"Identifier";
623 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
624 QueryTable
[1].Name
= L
"Configuration Data";
625 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
629 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
630 if (BiosDiskEntry
== NULL
)
634 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
635 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
638 (PVOID
)BiosDiskEntry
,
640 if (!NT_SUCCESS(Status
))
642 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
645 BiosDiskEntry
->DiskNumber
= DiskCount
;
646 BiosDiskEntry
->Recognized
= FALSE
;
648 if (DiskCount
< Int13Drives
[0].NumberDrives
)
650 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
654 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
658 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
660 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
661 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
662 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
663 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
664 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
665 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
666 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
667 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
668 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
669 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
670 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
675 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
681 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
685 AddDiskToList (HANDLE FileHandle
,
689 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
690 DISK_GEOMETRY DiskGeometry
;
691 SCSI_ADDRESS ScsiAddress
;
692 PDISKENTRY DiskEntry
;
693 IO_STATUS_BLOCK Iosb
;
695 PPARTITION_SECTOR Mbr
;
697 LARGE_INTEGER FileOffset
;
698 WCHAR Identifier
[20];
702 PLIST_ENTRY ListEntry
;
703 PBIOSDISKENTRY BiosDiskEntry
;
705 Status
= NtDeviceIoControlFile (FileHandle
,
710 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
714 sizeof(DISK_GEOMETRY
));
715 if (!NT_SUCCESS (Status
))
720 if (DiskGeometry
.MediaType
!= FixedMedia
)
725 Status
= NtDeviceIoControlFile (FileHandle
,
730 IOCTL_SCSI_GET_ADDRESS
,
734 sizeof(SCSI_ADDRESS
));
735 if (!NT_SUCCESS(Status
))
740 Mbr
= (PARTITION_SECTOR
*) RtlAllocateHeap(ProcessHeap
,
742 DiskGeometry
.BytesPerSector
);
749 FileOffset
.QuadPart
= 0;
750 Status
= NtReadFile(FileHandle
,
756 DiskGeometry
.BytesPerSector
,
759 if (!NT_SUCCESS(Status
))
761 RtlFreeHeap(ProcessHeap
,
764 DPRINT1("NtReadFile failed, status=%x\n", Status
);
767 Signature
= Mbr
->Signature
;
769 /* Calculate the MBR checksum */
771 Buffer
= (PULONG
)Mbr
;
772 for (i
= 0; i
< 128; i
++)
774 Checksum
+= Buffer
[i
];
776 Checksum
= ~Checksum
+ 1;
778 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
779 DPRINT("Identifier: %S\n", Identifier
);
781 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
784 if (DiskEntry
== NULL
)
789 DiskEntry
->Checksum
= Checksum
;
790 DiskEntry
->Signature
= Signature
;
793 /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
794 DiskEntry
->Modified
= TRUE
;
796 DiskEntry
->BiosFound
= FALSE
;
798 /* Check if this disk has a valid MBR */
799 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
800 DiskEntry
->NoMbr
= TRUE
;
802 DiskEntry
->NoMbr
= FALSE
;
804 /* Free Mbr sector buffer */
805 RtlFreeHeap (ProcessHeap
,
809 ListEntry
= List
->BiosDiskListHead
.Flink
;
810 while(ListEntry
!= &List
->BiosDiskListHead
)
812 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
814 * Compare the size from bios and the reported size from driver.
815 * If we have more than one disk with a zero or with the same signatur
816 * we must create new signatures and reboot. After the reboot,
817 * it is possible to identify the disks.
819 if (BiosDiskEntry
->Signature
== Signature
&&
820 BiosDiskEntry
->Checksum
== Checksum
&&
821 !BiosDiskEntry
->Recognized
)
823 if (!DiskEntry
->BiosFound
)
825 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
826 DiskEntry
->BiosFound
= TRUE
;
827 BiosDiskEntry
->Recognized
= TRUE
;
833 ListEntry
= ListEntry
->Flink
;
836 if (!DiskEntry
->BiosFound
)
838 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
842 InitializeListHead (&DiskEntry
->PartListHead
);
844 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
845 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
846 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
847 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
849 DPRINT ("Cylinders %d\n", DiskEntry
->Cylinders
);
850 DPRINT ("TracksPerCylinder %d\n", DiskEntry
->TracksPerCylinder
);
851 DPRINT ("SectorsPerTrack %d\n", DiskEntry
->SectorsPerTrack
);
852 DPRINT ("BytesPerSector %d\n", DiskEntry
->BytesPerSector
);
854 DiskEntry
->TrackSize
=
855 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
856 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
857 DiskEntry
->CylinderSize
=
858 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
859 DiskEntry
->TrackSize
;
860 DiskEntry
->DiskSize
=
861 DiskGeometry
.Cylinders
.QuadPart
*
862 DiskEntry
->CylinderSize
;
864 DiskEntry
->DiskNumber
= DiskNumber
;
865 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
866 DiskEntry
->Bus
= ScsiAddress
.PathId
;
867 DiskEntry
->Id
= ScsiAddress
.TargetId
;
869 GetDriverName (DiskEntry
);
871 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, BiosDiskNumber
);
873 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
876 if (LayoutBuffer
== NULL
)
881 Status
= NtDeviceIoControlFile (FileHandle
,
886 IOCTL_DISK_GET_DRIVE_LAYOUT
,
891 if (NT_SUCCESS (Status
))
893 if (LayoutBuffer
->PartitionCount
== 0)
895 DiskEntry
->NewDisk
= TRUE
;
898 AddPartitionToList (DiskNumber
,
902 ScanForUnpartitionedDiskSpace (DiskEntry
);
905 RtlFreeHeap (ProcessHeap
,
912 CreatePartitionList (SHORT Left
,
918 OBJECT_ATTRIBUTES ObjectAttributes
;
919 SYSTEM_DEVICE_INFORMATION Sdi
;
920 IO_STATUS_BLOCK Iosb
;
924 WCHAR Buffer
[MAX_PATH
];
928 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
937 List
->Bottom
= Bottom
;
941 List
->TopDisk
= (ULONG
)-1;
942 List
->TopPartition
= (ULONG
)-1;
944 List
->CurrentDisk
= NULL
;
945 List
->CurrentPartition
= NULL
;
946 List
->CurrentPartitionNumber
= 0;
948 InitializeListHead (&List
->DiskListHead
);
949 InitializeListHead (&List
->BiosDiskListHead
);
951 EnumerateBiosDiskEntries(List
);
953 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
955 sizeof(SYSTEM_DEVICE_INFORMATION
),
957 if (!NT_SUCCESS (Status
))
959 RtlFreeHeap (ProcessHeap
, 0, List
);
963 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
966 L
"\\Device\\Harddisk%d\\Partition0",
968 RtlInitUnicodeString (&Name
,
971 InitializeObjectAttributes (&ObjectAttributes
,
977 Status
= NtOpenFile (&FileHandle
,
978 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
982 FILE_SYNCHRONOUS_IO_NONALERT
);
983 if (NT_SUCCESS(Status
))
985 AddDiskToList (FileHandle
,
993 AssignDriverLetters (List
);
996 List
->TopPartition
= 0;
998 /* Search for first usable disk and partition */
999 if (IsListEmpty (&List
->DiskListHead
))
1001 List
->CurrentDisk
= NULL
;
1002 List
->CurrentPartition
= NULL
;
1003 List
->CurrentPartitionNumber
= 0;
1008 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
1012 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
1014 List
->CurrentPartition
= 0;
1015 List
->CurrentPartitionNumber
= 0;
1019 List
->CurrentPartition
=
1020 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
1023 List
->CurrentPartitionNumber
= 0;
1032 DestroyPartitionList (PPARTLIST List
)
1034 PDISKENTRY DiskEntry
;
1035 PBIOSDISKENTRY BiosDiskEntry
;
1036 PPARTENTRY PartEntry
;
1039 /* Release disk and partition info */
1040 while (!IsListEmpty (&List
->DiskListHead
))
1042 Entry
= RemoveHeadList (&List
->DiskListHead
);
1043 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1045 /* Release driver name */
1046 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1048 /* Release partition array */
1049 while (!IsListEmpty (&DiskEntry
->PartListHead
))
1051 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
1052 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
1054 RtlFreeHeap (ProcessHeap
,
1059 /* Release disk entry */
1060 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
1063 /* release the bios disk info */
1064 while(!IsListEmpty(&List
->BiosDiskListHead
))
1066 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1067 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1069 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1072 /* Release list head */
1073 RtlFreeHeap (ProcessHeap
, 0, List
);
1078 PrintEmptyLine (PPARTLIST List
)
1085 Width
= List
->Right
- List
->Left
- 1;
1086 Height
= List
->Bottom
- List
->Top
- 2;
1089 coPos
.X
= List
->Left
+ 1;
1090 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1092 if (List
->Line
>= 0 && List
->Line
<= Height
)
1094 FillConsoleOutputAttribute (StdOutput
,
1095 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1100 FillConsoleOutputCharacterA (StdOutput
,
1111 PrintPartitionData (PPARTLIST List
,
1112 PDISKENTRY DiskEntry
,
1113 PPARTENTRY PartEntry
,
1116 CHAR LineBuffer
[128];
1122 LARGE_INTEGER PartSize
;
1127 Width
= List
->Right
- List
->Left
- 1;
1128 Height
= List
->Bottom
- List
->Top
- 2;
1131 coPos
.X
= List
->Left
+ 1;
1132 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1134 if (PartEntry
->Unpartitioned
== TRUE
)
1137 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1139 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1140 Unit
= MUIGetString(STRING_GB
);
1144 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1146 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1147 Unit
= MUIGetString(STRING_MB
);
1151 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1152 Unit
= MUIGetString(STRING_KB
);
1155 sprintf (LineBuffer
,
1156 MUIGetString(STRING_UNPSPACE
),
1162 /* Determine partition type */
1164 if (PartEntry
->New
== TRUE
)
1166 PartType
= MUIGetString(STRING_UNFORMATTED
);
1168 else if (PartEntry
->Unpartitioned
== FALSE
)
1170 if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_12
) ||
1171 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_16
) ||
1172 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_HUGE
) ||
1173 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_XINT13
))
1177 else if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32
) ||
1178 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32_XINT13
))
1182 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_EXT2
)
1186 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_IFS
)
1188 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1193 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1195 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1196 Unit
= MUIGetString(STRING_GB
);
1200 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1202 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1203 Unit
= MUIGetString(STRING_MB
);
1207 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1208 Unit
= MUIGetString(STRING_KB
);
1211 if (PartType
== NULL
)
1213 sprintf (LineBuffer
,
1214 MUIGetString(STRING_HDDINFOUNK5
),
1215 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1216 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1217 PartEntry
->PartInfo
[PartNumber
].PartitionType
,
1223 sprintf (LineBuffer
,
1224 "%c%c %-24s %6lu %s",
1225 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1226 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1233 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1234 List
->CurrentPartition
== PartEntry
&&
1235 List
->CurrentPartitionNumber
== PartNumber
) ?
1236 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1237 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1239 if (List
->Line
>= 0 && List
->Line
<= Height
)
1241 FillConsoleOutputCharacterA (StdOutput
,
1249 if (List
->Line
>= 0 && List
->Line
<= Height
)
1251 FillConsoleOutputAttribute (StdOutput
,
1259 if (List
->Line
>= 0 && List
->Line
<= Height
)
1261 WriteConsoleOutputCharacterA (StdOutput
,
1263 min (strlen (LineBuffer
), Width
),
1272 PrintDiskData (PPARTLIST List
,
1273 PDISKENTRY DiskEntry
)
1275 PPARTENTRY PartEntry
;
1276 CHAR LineBuffer
[128];
1281 ULARGE_INTEGER DiskSize
;
1285 Width
= List
->Right
- List
->Left
- 1;
1286 Height
= List
->Bottom
- List
->Top
- 2;
1289 coPos
.X
= List
->Left
+ 1;
1290 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1293 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1295 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1296 Unit
= MUIGetString(STRING_GB
);
1301 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1302 if (DiskSize
.QuadPart
== 0)
1303 DiskSize
.QuadPart
= 1;
1304 Unit
= MUIGetString(STRING_MB
);
1307 if (DiskEntry
->DriverName
.Length
> 0)
1309 sprintf (LineBuffer
,
1310 MUIGetString(STRING_HDINFOPARTSELECT
),
1313 DiskEntry
->DiskNumber
,
1317 DiskEntry
->DriverName
.Buffer
);
1321 sprintf (LineBuffer
,
1322 MUIGetString(STRING_HDDINFOUNK6
),
1325 DiskEntry
->DiskNumber
,
1330 if (List
->Line
>= 0 && List
->Line
<= Height
)
1332 FillConsoleOutputAttribute (StdOutput
,
1333 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1338 FillConsoleOutputCharacterA (StdOutput
,
1346 if (List
->Line
>= 0 && List
->Line
<= Height
)
1348 WriteConsoleOutputCharacterA (StdOutput
,
1350 min ((USHORT
)strlen (LineBuffer
), Width
- 2),
1356 /* Print separator line */
1357 PrintEmptyLine (List
);
1359 /* Print partition lines*/
1360 LIST_FOR_EACH(PartEntry
, &DiskEntry
->PartListHead
, PARTENTRY
, ListEntry
)
1362 /* Print disk entry */
1365 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
1366 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
1368 PrintPartitionData (List
,
1375 /* Print unpartitioned entry */
1376 if (PartEntry
->Unpartitioned
)
1378 PrintPartitionData (List
,
1386 /* Print separator line */
1387 PrintEmptyLine (List
);
1392 DrawPartitionList (PPARTLIST List
)
1394 PLIST_ENTRY Entry
, Entry2
;
1395 PDISKENTRY DiskEntry
;
1396 PPARTENTRY PartEntry
= NULL
;
1400 SHORT CurrentDiskLine
;
1401 SHORT CurrentPartLine
;
1403 BOOL CurrentPartLineFound
= FALSE
;
1404 BOOL CurrentDiskLineFound
= FALSE
;
1406 /* Calculate the line of the current disk and partition */
1407 CurrentDiskLine
= 0;
1408 CurrentPartLine
= 0;
1410 Entry
= List
->DiskListHead
.Flink
;
1411 while (Entry
!= &List
->DiskListHead
)
1413 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1415 if (CurrentPartLineFound
== FALSE
)
1417 CurrentPartLine
+= 2;
1419 Entry2
= DiskEntry
->PartListHead
.Flink
;
1420 while (Entry2
!= &DiskEntry
->PartListHead
)
1422 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1423 if (PartEntry
== List
->CurrentPartition
)
1425 CurrentPartLineFound
= TRUE
;
1427 Entry2
= Entry2
->Flink
;
1428 if (CurrentPartLineFound
== FALSE
)
1434 if (DiskEntry
== List
->CurrentDisk
)
1436 CurrentDiskLineFound
= TRUE
;
1438 Entry
= Entry
->Flink
;
1439 if (Entry
!= &List
->DiskListHead
)
1441 if (CurrentDiskLineFound
== FALSE
)
1444 CurrentDiskLine
= CurrentPartLine
;
1454 /* If it possible, make the disk name visible */
1455 if (CurrentPartLine
< List
->Offset
)
1457 List
->Offset
= CurrentPartLine
;
1459 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1461 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1463 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1465 List
->Offset
= CurrentDiskLine
;
1469 /* draw upper left corner */
1470 coPos
.X
= List
->Left
;
1471 coPos
.Y
= List
->Top
;
1472 FillConsoleOutputCharacterA (StdOutput
,
1478 /* draw upper edge */
1479 coPos
.X
= List
->Left
+ 1;
1480 coPos
.Y
= List
->Top
;
1481 if (List
->Offset
== 0)
1483 FillConsoleOutputCharacterA (StdOutput
,
1485 List
->Right
- List
->Left
- 1,
1491 FillConsoleOutputCharacterA (StdOutput
,
1493 List
->Right
- List
->Left
- 5,
1496 coPos
.X
= List
->Right
- 5;
1497 WriteConsoleOutputCharacterA (StdOutput
,
1502 coPos
.X
= List
->Right
- 2;
1503 FillConsoleOutputCharacterA (StdOutput
,
1510 /* draw upper right corner */
1511 coPos
.X
= List
->Right
;
1512 coPos
.Y
= List
->Top
;
1513 FillConsoleOutputCharacterA (StdOutput
,
1519 /* draw left and right edge */
1520 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1522 coPos
.X
= List
->Left
;
1524 FillConsoleOutputCharacterA (StdOutput
,
1530 coPos
.X
= List
->Right
;
1531 FillConsoleOutputCharacterA (StdOutput
,
1538 /* draw lower left corner */
1539 coPos
.X
= List
->Left
;
1540 coPos
.Y
= List
->Bottom
;
1541 FillConsoleOutputCharacterA (StdOutput
,
1547 /* draw lower edge */
1548 coPos
.X
= List
->Left
+ 1;
1549 coPos
.Y
= List
->Bottom
;
1550 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1552 FillConsoleOutputCharacterA (StdOutput
,
1554 List
->Right
- List
->Left
- 1,
1560 FillConsoleOutputCharacterA (StdOutput
,
1562 List
->Right
- List
->Left
- 5,
1565 coPos
.X
= List
->Right
- 5;
1566 WriteConsoleOutputCharacterA (StdOutput
,
1567 "(\x19)", // "(down)"
1571 coPos
.X
= List
->Right
- 2;
1572 FillConsoleOutputCharacterA (StdOutput
,
1579 /* draw lower right corner */
1580 coPos
.X
= List
->Right
;
1581 coPos
.Y
= List
->Bottom
;
1582 FillConsoleOutputCharacterA (StdOutput
,
1588 /* print list entries */
1589 List
->Line
= - List
->Offset
;
1591 LIST_FOR_EACH(DiskEntry
, &List
->DiskListHead
, DISKENTRY
, ListEntry
)
1593 /* Print disk entry */
1594 PrintDiskData (List
,
1601 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1603 PDISKENTRY DiskEntry
;
1604 PPARTENTRY PartEntry
;
1609 /* Check for empty disks */
1610 if (IsListEmpty (&List
->DiskListHead
))
1613 /* Check for first usable entry on next disk */
1614 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1615 while (Entry1
!= &List
->DiskListHead
)
1617 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1619 if (DiskEntry
->DiskNumber
== DiskNumber
)
1621 Entry2
= DiskEntry
->PartListHead
.Flink
;
1622 while (Entry2
!= &DiskEntry
->PartListHead
)
1624 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1626 for (i
= 0; i
< 4; i
++)
1628 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1630 List
->CurrentDisk
= DiskEntry
;
1631 List
->CurrentPartition
= PartEntry
;
1632 List
->CurrentPartitionNumber
= i
;
1633 DrawPartitionList (List
);
1637 Entry2
= Entry2
->Flink
;
1641 Entry1
= Entry1
->Flink
;
1648 ScrollDownPartitionList (PPARTLIST List
)
1650 PDISKENTRY DiskEntry
;
1651 PPARTENTRY PartEntry
;
1656 /* Check for empty disks */
1657 if (IsListEmpty (&List
->DiskListHead
))
1660 /* Check for next usable entry on current disk */
1661 if (List
->CurrentPartition
!= NULL
)
1663 Entry2
= &List
->CurrentPartition
->ListEntry
;
1664 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1666 /* Check if we can move inside primary partitions */
1667 for (i
= List
->CurrentPartitionNumber
+ 1; i
< 4; i
++)
1669 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1675 /* We're out of partitions in the current partition table.
1676 Try to move to the next one if possible. */
1677 Entry2
= Entry2
->Flink
;
1681 /* Just advance to the next partition */
1682 List
->CurrentPartitionNumber
= i
;
1683 DrawPartitionList (List
);
1687 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1689 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1691 // if (PartEntry->HidePartEntry == FALSE)
1693 List
->CurrentPartition
= PartEntry
;
1694 List
->CurrentPartitionNumber
= 0;
1695 DrawPartitionList (List
);
1698 Entry2
= Entry2
->Flink
;
1702 /* Check for first usable entry on next disk */
1703 if (List
->CurrentDisk
!= NULL
)
1705 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1706 while (Entry1
!= &List
->DiskListHead
)
1708 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1710 Entry2
= DiskEntry
->PartListHead
.Flink
;
1711 while (Entry2
!= &DiskEntry
->PartListHead
)
1713 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1715 // if (PartEntry->HidePartEntry == FALSE)
1717 List
->CurrentDisk
= DiskEntry
;
1718 List
->CurrentPartition
= PartEntry
;
1719 List
->CurrentPartitionNumber
= 0;
1720 DrawPartitionList (List
);
1724 Entry2
= Entry2
->Flink
;
1727 Entry1
= Entry1
->Flink
;
1734 ScrollUpPartitionList (PPARTLIST List
)
1736 PDISKENTRY DiskEntry
;
1737 PPARTENTRY PartEntry
;
1742 /* Check for empty disks */
1743 if (IsListEmpty (&List
->DiskListHead
))
1746 /* check for previous 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 if (List
->CurrentPartitionNumber
> 0)
1755 /* Find a previous partition */
1756 for (i
= List
->CurrentPartitionNumber
- 1; i
> 0; i
--)
1758 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1762 /* Move to it and return */
1763 List
->CurrentPartitionNumber
= i
;
1764 DrawPartitionList (List
);
1768 /* Move to the previous entry */
1769 Entry2
= Entry2
->Blink
;
1771 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1773 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1775 // if (PartEntry->HidePartEntry == FALSE)
1777 List
->CurrentPartition
= PartEntry
;
1779 /* Find last existing partition in the table */
1780 for (i
= 3; i
> 0; i
--)
1782 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1787 List
->CurrentPartitionNumber
= i
;
1789 /* Draw partition list and return */
1790 DrawPartitionList (List
);
1793 Entry2
= Entry2
->Blink
;
1798 /* check for last usable entry on previous disk */
1799 if (List
->CurrentDisk
!= NULL
)
1801 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1802 while (Entry1
!= &List
->DiskListHead
)
1804 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1806 Entry2
= DiskEntry
->PartListHead
.Blink
;
1807 while (Entry2
!= &DiskEntry
->PartListHead
)
1809 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1811 // if (PartEntry->HidePartEntry == FALSE)
1813 List
->CurrentDisk
= DiskEntry
;
1814 List
->CurrentPartition
= PartEntry
;
1816 /* Find last existing partition in the table */
1817 for (i
= 3; i
> 0; i
--)
1819 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1824 List
->CurrentPartitionNumber
= i
;
1826 /* Draw partition list and return */
1827 DrawPartitionList (List
);
1831 Entry2
= Entry2
->Blink
;
1834 Entry1
= Entry1
->Blink
;
1841 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1842 PPARTENTRY CurrentEntry
)
1844 PPARTENTRY PrevEntry
;
1847 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1850 Entry
= CurrentEntry
->ListEntry
.Blink
;
1851 while (Entry
!= &DiskEntry
->PartListHead
)
1853 PrevEntry
= CONTAINING_RECORD (Entry
,
1856 if (PrevEntry
->Unpartitioned
== FALSE
)
1859 Entry
= Entry
->Blink
;
1867 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1868 PPARTENTRY CurrentEntry
)
1870 PPARTENTRY NextEntry
;
1873 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1876 Entry
= CurrentEntry
->ListEntry
.Flink
;
1877 while (Entry
!= &DiskEntry
->PartListHead
)
1879 NextEntry
= CONTAINING_RECORD (Entry
,
1882 if (NextEntry
->Unpartitioned
== FALSE
)
1885 Entry
= Entry
->Flink
;
1893 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1894 PPARTENTRY PartEntry
)
1896 PPARTENTRY PrevPartEntry
;
1898 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1900 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1903 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1904 return PrevPartEntry
;
1912 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1913 PPARTENTRY PartEntry
)
1915 PPARTENTRY NextPartEntry
;
1917 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1919 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1922 if (NextPartEntry
->Unpartitioned
== TRUE
)
1923 return NextPartEntry
;
1931 CreateNewPartition (PPARTLIST List
,
1932 ULONGLONG PartitionSize
,
1935 PDISKENTRY DiskEntry
;
1936 PPARTENTRY PartEntry
;
1937 PPARTENTRY PrevPartEntry
;
1938 PPARTENTRY NextPartEntry
;
1939 PPARTENTRY NewPartEntry
;
1942 List
->CurrentDisk
== NULL
||
1943 List
->CurrentPartition
== NULL
||
1944 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1949 DiskEntry
= List
->CurrentDisk
;
1950 PartEntry
= List
->CurrentPartition
;
1952 if (AutoCreate
== TRUE
||
1953 PartitionSize
== PartEntry
->UnpartitionedLength
)
1955 /* Convert current entry to 'new (unformatted)' */
1956 PartEntry
->FormatState
= Unformatted
;
1957 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1958 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1959 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1960 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1961 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1962 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1963 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1964 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1965 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1966 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1968 /* Get previous and next partition entries */
1969 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1971 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1974 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1976 /* Current entry is in the middle of the list */
1978 /* Copy previous container partition data to current entry */
1979 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1980 &PrevPartEntry
->PartInfo
[1],
1981 sizeof(PARTITION_INFORMATION
));
1982 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1984 /* Update previous container partition data */
1986 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1987 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1989 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1991 /* Special case - previous partition is first partition */
1992 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1993 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1997 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1998 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2001 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2003 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2005 /* Current entry is the first entry */
2008 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2010 /* Current entry is the last entry */
2012 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2013 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2015 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2017 /* Special case - previous partition is first partition */
2018 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2019 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2023 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2024 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2027 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2028 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2029 (1024LL * 255LL * 63LL * 512LL))
2031 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2035 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2038 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2039 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2042 PartEntry
->AutoCreate
= AutoCreate
;
2043 PartEntry
->New
= TRUE
;
2044 PartEntry
->Unpartitioned
= FALSE
;
2045 PartEntry
->UnpartitionedOffset
= 0ULL;
2046 PartEntry
->UnpartitionedLength
= 0ULL;
2050 /* Insert an initialize a new partition entry */
2051 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
2054 if (NewPartEntry
== NULL
)
2057 RtlZeroMemory (NewPartEntry
,
2060 /* Insert the new entry into the list */
2061 InsertTailList (&PartEntry
->ListEntry
,
2062 &NewPartEntry
->ListEntry
);
2064 NewPartEntry
->New
= TRUE
;
2066 NewPartEntry
->FormatState
= Unformatted
;
2067 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
2068 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
2069 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
2070 PartitionSize
- DiskEntry
->TrackSize
;
2071 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
2072 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
2073 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2074 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2075 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
2076 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
2078 /* Get previous and next partition entries */
2079 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2081 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2084 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2086 /* Current entry is in the middle of the list */
2088 /* Copy previous container partition data to current entry */
2089 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
2090 &PrevPartEntry
->PartInfo
[1],
2091 sizeof(PARTITION_INFORMATION
));
2092 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2094 /* Update previous container partition data */
2096 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2097 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2099 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2101 /* Special case - previous partition is first partition */
2102 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2103 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2107 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2108 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2111 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2113 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2115 /* Current entry is the first entry */
2118 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2120 /* Current entry is the last entry */
2122 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2123 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2125 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2127 /* Special case - previous partition is first partition */
2128 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2129 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2133 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2134 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2137 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2138 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2139 (1024LL * 255LL * 63LL * 512LL))
2141 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2145 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2148 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2149 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2152 /* Update offset and size of the remaining unpartitioned disk space */
2153 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
2154 PartEntry
->UnpartitionedLength
-= PartitionSize
;
2157 DiskEntry
->Modified
= TRUE
;
2159 UpdatePartitionNumbers (DiskEntry
);
2161 AssignDriverLetters (List
);
2166 DeleteCurrentPartition (PPARTLIST List
)
2168 PDISKENTRY DiskEntry
;
2169 PPARTENTRY PartEntry
;
2170 PPARTENTRY PrevPartEntry
;
2171 PPARTENTRY NextPartEntry
;
2174 List
->CurrentDisk
== NULL
||
2175 List
->CurrentPartition
== NULL
||
2176 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2181 DiskEntry
= List
->CurrentDisk
;
2182 PartEntry
= List
->CurrentPartition
;
2184 /* Adjust container partition entries */
2186 /* Get previous and next partition entries */
2187 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2189 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2192 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2194 /* Current entry is in the middle of the list */
2197 * The first extended partition can not be deleted
2198 * as long as other extended partitions are present.
2200 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2203 /* Copy previous container partition data to current entry */
2204 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
2205 &PartEntry
->PartInfo
[1],
2206 sizeof(PARTITION_INFORMATION
));
2207 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2209 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2212 * A primary partition can not be deleted as long as
2213 * extended partitions are present.
2217 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2219 /* Current entry is the last entry */
2220 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
2221 sizeof(PARTITION_INFORMATION
));
2222 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2226 /* Adjust unpartitioned disk space entries */
2228 /* Get pointer to previous and next unpartitioned entries */
2229 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
2232 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
2235 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2237 /* Merge previous, current and next unpartitioned entry */
2239 /* Adjust the previous entries length */
2240 PrevPartEntry
->UnpartitionedLength
+=
2241 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2242 NextPartEntry
->UnpartitionedLength
);
2244 /* Remove the current entry */
2245 RemoveEntryList (&PartEntry
->ListEntry
);
2246 RtlFreeHeap (ProcessHeap
,
2250 /* Remove the next entry */
2251 RemoveEntryList (&NextPartEntry
->ListEntry
);
2252 RtlFreeHeap (ProcessHeap
,
2256 /* Update current partition */
2257 List
->CurrentPartition
= PrevPartEntry
;
2259 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2261 /* Merge current and previous unpartitioned entry */
2263 /* Adjust the previous entries length */
2264 PrevPartEntry
->UnpartitionedLength
+=
2265 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2267 /* Remove the current entry */
2268 RemoveEntryList (&PartEntry
->ListEntry
);
2269 RtlFreeHeap (ProcessHeap
,
2273 /* Update current partition */
2274 List
->CurrentPartition
= PrevPartEntry
;
2276 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2278 /* Merge current and next unpartitioned entry */
2280 /* Adjust the next entries offset and length */
2281 NextPartEntry
->UnpartitionedOffset
=
2282 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2283 NextPartEntry
->UnpartitionedLength
+=
2284 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2286 /* Remove the current entry */
2287 RemoveEntryList (&PartEntry
->ListEntry
);
2288 RtlFreeHeap (ProcessHeap
,
2292 /* Update current partition */
2293 List
->CurrentPartition
= NextPartEntry
;
2297 /* Nothing to merge but change current entry */
2298 PartEntry
->New
= FALSE
;
2299 PartEntry
->Unpartitioned
= TRUE
;
2300 PartEntry
->UnpartitionedOffset
=
2301 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2302 PartEntry
->UnpartitionedLength
=
2303 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2305 /* Wipe the partition table */
2306 RtlZeroMemory (&PartEntry
->PartInfo
,
2307 sizeof(PartEntry
->PartInfo
));
2310 DiskEntry
->Modified
= TRUE
;
2312 UpdatePartitionNumbers (DiskEntry
);
2314 AssignDriverLetters (List
);
2319 CheckActiveBootPartition (PPARTLIST List
)
2321 PDISKENTRY DiskEntry
;
2322 PPARTENTRY PartEntry
;
2323 PLIST_ENTRY ListEntry
;
2326 /* Check for empty disk list */
2327 if (IsListEmpty (&List
->DiskListHead
))
2329 List
->ActiveBootDisk
= NULL
;
2330 List
->ActiveBootPartition
= NULL
;
2331 List
->ActiveBootPartitionNumber
= 0;
2336 if (List
->ActiveBootDisk
!= NULL
&&
2337 List
->ActiveBootPartition
!= NULL
)
2339 /* We already have an active boot partition */
2344 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
2348 /* Check for empty partition list */
2349 if (IsListEmpty (&DiskEntry
->PartListHead
))
2351 List
->ActiveBootDisk
= NULL
;
2352 List
->ActiveBootPartition
= NULL
;
2353 List
->ActiveBootPartitionNumber
= 0;
2357 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
2361 /* Set active boot partition */
2362 if ((DiskEntry
->NewDisk
== TRUE
) ||
2363 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2364 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2365 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2366 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2368 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2369 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2370 DiskEntry
->Modified
= TRUE
;
2372 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2373 List
->ActiveBootDisk
= DiskEntry
;
2374 List
->ActiveBootPartition
= PartEntry
;
2375 List
->ActiveBootPartitionNumber
= 0;
2380 /* Disk is not new, scan all partitions to find a bootable one */
2381 List
->ActiveBootDisk
= NULL
;
2382 List
->ActiveBootPartition
= NULL
;
2383 List
->ActiveBootPartitionNumber
= 0;
2385 ListEntry
= DiskEntry
->PartListHead
.Flink
;
2386 while (ListEntry
!= &DiskEntry
->PartListHead
)
2388 PartEntry
= CONTAINING_RECORD(ListEntry
,
2392 /* Check if it's partitioned */
2393 if (!PartEntry
->Unpartitioned
)
2395 /* Go through all of its 4 partitions */
2398 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2399 PartEntry
->PartInfo
[i
].BootIndicator
)
2401 /* Yes, we found it */
2402 List
->ActiveBootDisk
= DiskEntry
;
2403 List
->ActiveBootPartition
= PartEntry
;
2404 List
->ActiveBootPartitionNumber
= i
;
2406 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2407 DiskEntry
->BiosDiskNumber
, PartEntry
->DriveLetter
[i
]);
2413 /* Go to the next one */
2414 ListEntry
= ListEntry
->Flink
;
2420 CheckForLinuxFdiskPartitions (PPARTLIST List
)
2422 PDISKENTRY DiskEntry
;
2423 PPARTENTRY PartEntry
;
2426 ULONG PartitionCount
;
2429 Entry1
= List
->DiskListHead
.Flink
;
2430 while (Entry1
!= &List
->DiskListHead
)
2432 DiskEntry
= CONTAINING_RECORD (Entry1
,
2436 Entry2
= DiskEntry
->PartListHead
.Flink
;
2437 while (Entry2
!= &DiskEntry
->PartListHead
)
2439 PartEntry
= CONTAINING_RECORD (Entry2
,
2443 if (PartEntry
->Unpartitioned
== FALSE
)
2447 for (i
= 0; i
< 4; i
++)
2449 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
2450 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2456 if (PartitionCount
> 1)
2462 Entry2
= Entry2
->Flink
;
2465 Entry1
= Entry1
->Flink
;
2473 WritePartitionsToDisk (PPARTLIST List
)
2475 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2476 OBJECT_ATTRIBUTES ObjectAttributes
;
2477 IO_STATUS_BLOCK Iosb
;
2478 WCHAR SrcPath
[MAX_PATH
];
2479 WCHAR DstPath
[MAX_PATH
];
2480 UNICODE_STRING Name
;
2482 PDISKENTRY DiskEntry1
;
2483 PDISKENTRY DiskEntry2
;
2484 PPARTENTRY PartEntry
;
2487 ULONG PartitionCount
;
2488 ULONG DriveLayoutSize
;
2497 Entry1
= List
->DiskListHead
.Flink
;
2498 while (Entry1
!= &List
->DiskListHead
)
2500 DiskEntry1
= CONTAINING_RECORD (Entry1
,
2504 if (DiskEntry1
->Modified
== TRUE
)
2506 /* Count partitioned entries */
2508 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2509 while (Entry2
!= &DiskEntry1
->PartListHead
)
2511 PartEntry
= CONTAINING_RECORD (Entry2
,
2514 if (PartEntry
->Unpartitioned
== FALSE
)
2516 PartitionCount
+= 4;
2519 Entry2
= Entry2
->Flink
;
2521 if (PartitionCount
== 0)
2523 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2524 ((4 - 1) * sizeof (PARTITION_INFORMATION
));
2528 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2529 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2531 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
2534 if (DriveLayout
== NULL
)
2536 DPRINT1 ("RtlAllocateHeap() failed\n");
2540 RtlZeroMemory (DriveLayout
,
2543 if (PartitionCount
== 0)
2545 /* delete all partitions in the mbr */
2546 DriveLayout
->PartitionCount
= 4;
2547 for (Index
= 0; Index
< 4; Index
++)
2549 DriveLayout
->PartitionEntry
[Index
].RewritePartition
= TRUE
;
2554 DriveLayout
->PartitionCount
= PartitionCount
;
2557 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2558 while (Entry2
!= &DiskEntry1
->PartListHead
)
2560 PartEntry
= CONTAINING_RECORD (Entry2
,
2563 if (PartEntry
->Unpartitioned
== FALSE
)
2565 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2566 &PartEntry
->PartInfo
[0],
2567 4 * sizeof (PARTITION_INFORMATION
));
2571 Entry2
= Entry2
->Flink
;
2574 if (DiskEntry1
->Signature
== 0)
2576 LARGE_INTEGER SystemTime
;
2577 TIME_FIELDS TimeFields
;
2579 Buffer
= (PUCHAR
)&DiskEntry1
->Signature
;
2583 NtQuerySystemTime (&SystemTime
);
2584 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
2586 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
2587 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
2588 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
2589 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
2591 if (DiskEntry1
->Signature
== 0)
2596 /* check if the signature already exist */
2598 * Check also signatures from disks, which are
2599 * not visible (bootable) by the bios.
2601 Entry2
= List
->DiskListHead
.Flink
;
2602 while (Entry2
!= &List
->DiskListHead
)
2604 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
2605 if (DiskEntry1
!= DiskEntry2
&&
2606 DiskEntry1
->Signature
== DiskEntry2
->Signature
)
2610 Entry2
= Entry2
->Flink
;
2612 if (Entry2
== &List
->DiskListHead
)
2618 /* set one partition entry to dirty, this will update the signature */
2619 DriveLayout
->PartitionEntry
[0].RewritePartition
= TRUE
;
2623 DriveLayout
->Signature
= DiskEntry1
->Signature
;
2627 L
"\\Device\\Harddisk%d\\Partition0",
2628 DiskEntry1
->DiskNumber
);
2629 RtlInitUnicodeString (&Name
,
2631 InitializeObjectAttributes (&ObjectAttributes
,
2637 Status
= NtOpenFile (&FileHandle
,
2642 FILE_SYNCHRONOUS_IO_NONALERT
);
2644 if (!NT_SUCCESS (Status
))
2646 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2650 Status
= NtDeviceIoControlFile (FileHandle
,
2655 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2660 if (!NT_SUCCESS (Status
))
2662 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2663 NtClose (FileHandle
);
2667 RtlFreeHeap (ProcessHeap
,
2671 NtClose (FileHandle
);
2673 /* Install MBR code if the disk is new */
2674 if (DiskEntry1
->NewDisk
== TRUE
&&
2675 DiskEntry1
->BiosDiskNumber
== 0)
2677 wcscpy (SrcPath
, SourceRootPath
.Buffer
);
2678 wcscat (SrcPath
, L
"\\loader\\dosmbr.bin");
2680 DPRINT ("Install MBR bootcode: %S ==> %S\n",
2683 /* Install MBR bootcode */
2684 Status
= InstallMbrBootCodeToDisk (SrcPath
,
2686 if (!NT_SUCCESS (Status
))
2688 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
2693 DiskEntry1
->NewDisk
= FALSE
;
2694 DiskEntry1
->NoMbr
= FALSE
;
2698 Entry1
= Entry1
->Flink
;
2704 BOOL
SetMountedDeviceValues(PPARTLIST List
)
2706 PLIST_ENTRY Entry1
, Entry2
;
2707 PDISKENTRY DiskEntry
;
2708 PPARTENTRY PartEntry
;
2716 Entry1
= List
->DiskListHead
.Flink
;
2717 while (Entry1
!= &List
->DiskListHead
)
2719 DiskEntry
= CONTAINING_RECORD (Entry1
,
2723 Entry2
= DiskEntry
->PartListHead
.Flink
;
2724 while (Entry2
!= &DiskEntry
->PartListHead
)
2726 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2727 if (!PartEntry
->Unpartitioned
)
2731 if (PartEntry
->DriveLetter
[i
])
2733 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
[i
], DiskEntry
->Signature
, PartEntry
->PartInfo
[i
].StartingOffset
))
2740 Entry2
= Entry2
->Flink
;
2742 Entry1
= Entry1
->Flink
;