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 ****************************************************************/
37 GetDriverName (PDISKENTRY DiskEntry
)
39 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
43 RtlInitUnicodeString (&DiskEntry
->DriverName
,
47 L
"\\Scsi\\Scsi Port %lu",
50 RtlZeroMemory (&QueryTable
,
53 QueryTable
[0].Name
= L
"Driver";
54 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
55 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
57 Status
= RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP
,
62 if (!NT_SUCCESS (Status
))
64 DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
70 AssignDriverLetters (PPARTLIST List
)
81 /* Assign drive letters to primary partitions */
82 Entry1
= List
->DiskListHead
.Flink
;
83 while (Entry1
!= &List
->DiskListHead
)
85 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
87 if (!IsListEmpty (&DiskEntry
->PartListHead
))
89 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
94 PartEntry
->DriveLetter
[i
] = 0;
96 if (PartEntry
->Unpartitioned
== FALSE
)
100 if (IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
))
103 if (IsRecognizedPartition (PartEntry
->PartInfo
[i
].PartitionType
) ||
104 (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
105 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0LL))
109 PartEntry
->DriveLetter
[i
] = Letter
;
117 Entry1
= Entry1
->Flink
;
120 /* Assign drive letters to logical drives */
122 Entry1
= List
->DiskListHead
.Flink
;
123 while (Entry1
!= &List
->DiskListHead
)
125 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
127 Entry2
= DiskEntry
->PartListHead
.Flink
;
128 if (Entry2
!= &DiskEntry
->PartListHead
)
130 Entry2
= Entry2
->Flink
;
131 while (Entry2
!= &DiskEntry
->PartListHead
)
133 PartEntry
= CONTAINING_RECORD (Entry2
,
137 PartEntry
->DriveLetter
= 0;
139 if (PartEntry
->Unpartitioned
== FALSE
&&
140 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
142 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
143 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
144 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
148 PartEntry
->DriveLetter
= Letter
;
154 Entry2
= Entry2
->Flink
;
158 Entry1
= Entry1
->Flink
;
165 UpdatePartitionNumbers (PDISKENTRY DiskEntry
)
167 PPARTENTRY PartEntry
;
173 Entry
= DiskEntry
->PartListHead
.Flink
;
174 while (Entry
!= &DiskEntry
->PartListHead
)
176 PartEntry
= CONTAINING_RECORD (Entry
,
180 if (PartEntry
->Unpartitioned
== TRUE
)
182 for (i
= 0; i
< 4; i
++)
184 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
189 for (i
= 0; i
< 4; i
++)
191 if (IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
))
193 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
195 else if (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
196 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
== 0ULL)
198 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
202 PartEntry
->PartInfo
[i
].PartitionNumber
= PartNumber
;
208 Entry
= Entry
->Flink
;
214 AddPartitionToList (ULONG DiskNumber
,
215 PDISKENTRY DiskEntry
,
216 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
)
218 PPARTENTRY PartEntry
;
222 for (i
= 0; i
< LayoutBuffer
->PartitionCount
; i
+= 4)
224 for (j
= 0; j
< 4; j
++)
226 if (LayoutBuffer
->PartitionEntry
[i
+j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
227 LayoutBuffer
->PartitionEntry
[i
+j
].PartitionLength
.QuadPart
!= 0ULL)
237 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
240 if (PartEntry
== NULL
)
245 RtlZeroMemory (PartEntry
,
248 PartEntry
->Unpartitioned
= FALSE
;
250 for (j
= 0; j
< 4; j
++)
252 RtlCopyMemory (&PartEntry
->PartInfo
[j
],
253 &LayoutBuffer
->PartitionEntry
[i
+j
],
254 sizeof(PARTITION_INFORMATION
));
257 if (IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
259 PartEntry
->FormatState
= Unformatted
;
261 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
262 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
263 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
264 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
) ||
265 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
266 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
269 if (CheckFatFormat())
271 PartEntry
->FormatState
= Preformatted
;
275 PartEntry
->FormatState
= Unformatted
;
278 PartEntry
->FormatState
= Preformatted
;
280 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_EXT2
)
283 if (CheckExt2Format())
285 PartEntry
->FormatState
= Preformatted
;
289 PartEntry
->FormatState
= Unformatted
;
292 PartEntry
->FormatState
= Preformatted
;
294 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
297 if (CheckNtfsFormat())
299 PartEntry
->FormatState
= Preformatted
;
301 else if (CheckHpfsFormat())
303 PartEntry
->FormatState
= Preformatted
;
307 PartEntry
->FormatState
= Unformatted
;
310 PartEntry
->FormatState
= Preformatted
;
314 PartEntry
->FormatState
= UnknownFormat
;
317 InsertTailList (&DiskEntry
->PartListHead
,
318 &PartEntry
->ListEntry
);
324 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry
)
326 ULONGLONG LastStartingOffset
;
327 ULONGLONG LastPartitionLength
;
328 ULONGLONG LastUnusedPartitionLength
;
329 PPARTENTRY PartEntry
;
330 PPARTENTRY NewPartEntry
;
335 if (IsListEmpty (&DiskEntry
->PartListHead
))
337 /* Create a partition table that represents the empty disk */
338 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
341 if (PartEntry
== NULL
)
344 RtlZeroMemory (PartEntry
,
347 PartEntry
->Unpartitioned
= TRUE
;
348 PartEntry
->UnpartitionedOffset
= 0ULL;
349 PartEntry
->UnpartitionedLength
= DiskEntry
->DiskSize
;
351 PartEntry
->FormatState
= Unformatted
;
353 InsertTailList (&DiskEntry
->PartListHead
,
354 &PartEntry
->ListEntry
);
358 /* Start partition at head 1, cylinder 0 */
359 LastStartingOffset
= DiskEntry
->TrackSize
;
360 LastPartitionLength
= 0ULL;
361 LastUnusedPartitionLength
= 0ULL;
364 Entry
= DiskEntry
->PartListHead
.Flink
;
365 while (Entry
!= &DiskEntry
->PartListHead
)
367 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
369 for (j
= 0; j
< 4; j
++)
371 if ((!IsContainerPartition (PartEntry
->PartInfo
[j
].PartitionType
)) &&
372 (PartEntry
->PartInfo
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
373 PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
!= 0LL))
375 LastUnusedPartitionLength
=
376 PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
-
377 (LastStartingOffset
+ LastPartitionLength
);
379 if (PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
> (LastStartingOffset
+ LastPartitionLength
) &&
380 LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
382 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
384 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
387 if (NewPartEntry
== NULL
)
390 RtlZeroMemory (NewPartEntry
,
393 NewPartEntry
->Unpartitioned
= TRUE
;
394 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
395 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
397 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
399 NewPartEntry
->FormatState
= Unformatted
;
401 /* Insert the table into the list */
402 InsertTailList (&PartEntry
->ListEntry
,
403 &NewPartEntry
->ListEntry
);
406 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
407 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
412 Entry
= Entry
->Flink
;
415 /* Check for trailing unpartitioned disk space */
416 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
418 /* Round-down to cylinder size */
419 LastUnusedPartitionLength
=
420 (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
))
421 & ~(DiskEntry
->CylinderSize
- 1);
423 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
425 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
427 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
430 if (NewPartEntry
== NULL
)
433 RtlZeroMemory (NewPartEntry
,
436 NewPartEntry
->Unpartitioned
= TRUE
;
437 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
438 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
440 /* Append the table to the list */
441 InsertTailList (&DiskEntry
->PartListHead
,
442 &NewPartEntry
->ListEntry
);
450 DiskIdentifierQueryRoutine(PWSTR ValueName
,
457 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
458 UNICODE_STRING NameU
;
460 if (ValueType
== REG_SZ
&&
461 ValueLength
== 20 * sizeof(WCHAR
))
463 NameU
.Buffer
= (PWCHAR
)ValueData
;
464 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
465 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
467 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
468 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
470 return STATUS_SUCCESS
;
472 return STATUS_UNSUCCESSFUL
;
477 DiskConfigurationDataQueryRoutine(PWSTR ValueName
,
484 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
485 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
486 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
489 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
490 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
491 return STATUS_UNSUCCESSFUL
;
493 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
494 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
495 /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
496 FullResourceDescriptor->PartialResourceList.Revision != 1)
497 return STATUS_UNSUCCESSFUL;*/
499 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
501 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
502 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
505 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
506 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
508 return STATUS_SUCCESS
;
510 return STATUS_UNSUCCESSFUL
;
515 SystemConfigurationDataQueryRoutine(PWSTR ValueName
,
522 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
523 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
526 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
527 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
528 return STATUS_UNSUCCESSFUL
;
530 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
531 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
532 /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
533 FullResourceDescriptor->PartialResourceList.Revision != 1)
534 return STATUS_UNSUCCESSFUL;*/
536 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
538 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
539 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
542 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
543 if (*Int13Drives
== NULL
)
544 return STATUS_NO_MEMORY
;
546 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
547 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
548 return STATUS_SUCCESS
;
550 return STATUS_UNSUCCESSFUL
;
552 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
555 EnumerateBiosDiskEntries(PPARTLIST PartList
)
557 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
562 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
563 PBIOSDISKENTRY BiosDiskEntry
;
565 memset(QueryTable
, 0, sizeof(QueryTable
));
567 QueryTable
[1].Name
= L
"Configuration Data";
568 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
570 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
571 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
575 if (!NT_SUCCESS(Status
))
577 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
584 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
585 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
590 if (!NT_SUCCESS(Status
))
595 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
596 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
601 if (NT_SUCCESS(Status
))
605 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
606 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
611 if (!NT_SUCCESS(Status
))
613 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
617 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
618 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
623 if (NT_SUCCESS(Status
))
625 QueryTable
[0].Name
= L
"Identifier";
626 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
627 QueryTable
[1].Name
= L
"Configuration Data";
628 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
632 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
633 if (BiosDiskEntry
== NULL
)
637 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
638 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
641 (PVOID
)BiosDiskEntry
,
643 if (!NT_SUCCESS(Status
))
645 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
648 BiosDiskEntry
->DiskNumber
= DiskCount
;
649 BiosDiskEntry
->Recognized
= FALSE
;
651 if (DiskCount
< Int13Drives
[0].NumberDrives
)
653 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
657 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
661 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
663 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
664 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
665 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
666 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
667 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
668 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
669 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
670 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
671 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
672 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
673 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
678 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
684 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
688 AddDiskToList (HANDLE FileHandle
,
692 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
693 DISK_GEOMETRY DiskGeometry
;
694 SCSI_ADDRESS ScsiAddress
;
695 PDISKENTRY DiskEntry
;
696 IO_STATUS_BLOCK Iosb
;
698 PPARTITION_SECTOR Mbr
;
700 LARGE_INTEGER FileOffset
;
701 WCHAR Identifier
[20];
705 PLIST_ENTRY ListEntry
;
706 PBIOSDISKENTRY BiosDiskEntry
;
707 ULONG LayoutBufferSize
;
709 Status
= NtDeviceIoControlFile (FileHandle
,
714 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
718 sizeof(DISK_GEOMETRY
));
719 if (!NT_SUCCESS (Status
))
724 if (DiskGeometry
.MediaType
!= FixedMedia
&&
725 DiskGeometry
.MediaType
!= RemovableMedia
)
730 Status
= NtDeviceIoControlFile (FileHandle
,
735 IOCTL_SCSI_GET_ADDRESS
,
739 sizeof(SCSI_ADDRESS
));
740 if (!NT_SUCCESS(Status
))
745 Mbr
= (PARTITION_SECTOR
*) RtlAllocateHeap(ProcessHeap
,
747 DiskGeometry
.BytesPerSector
);
754 FileOffset
.QuadPart
= 0;
755 Status
= NtReadFile(FileHandle
,
761 DiskGeometry
.BytesPerSector
,
764 if (!NT_SUCCESS(Status
))
766 RtlFreeHeap(ProcessHeap
,
769 DPRINT1("NtReadFile failed, status=%x\n", Status
);
772 Signature
= Mbr
->Signature
;
774 /* Calculate the MBR checksum */
776 Buffer
= (PULONG
)Mbr
;
777 for (i
= 0; i
< 128; i
++)
779 Checksum
+= Buffer
[i
];
781 Checksum
= ~Checksum
+ 1;
783 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
784 DPRINT("Identifier: %S\n", Identifier
);
786 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
789 if (DiskEntry
== NULL
)
794 DiskEntry
->Checksum
= Checksum
;
795 DiskEntry
->Signature
= Signature
;
798 /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
799 DiskEntry
->Modified
= TRUE
;
801 DiskEntry
->BiosFound
= FALSE
;
803 /* Check if this disk has a valid MBR */
804 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
805 DiskEntry
->NoMbr
= TRUE
;
807 DiskEntry
->NoMbr
= FALSE
;
809 /* Free Mbr sector buffer */
810 RtlFreeHeap (ProcessHeap
,
814 ListEntry
= List
->BiosDiskListHead
.Flink
;
815 while(ListEntry
!= &List
->BiosDiskListHead
)
817 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
819 * Compare the size from bios and the reported size from driver.
820 * If we have more than one disk with a zero or with the same signatur
821 * we must create new signatures and reboot. After the reboot,
822 * it is possible to identify the disks.
824 if (BiosDiskEntry
->Signature
== Signature
&&
825 BiosDiskEntry
->Checksum
== Checksum
&&
826 !BiosDiskEntry
->Recognized
)
828 if (!DiskEntry
->BiosFound
)
830 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
831 DiskEntry
->BiosFound
= TRUE
;
832 BiosDiskEntry
->Recognized
= TRUE
;
838 ListEntry
= ListEntry
->Flink
;
841 if (!DiskEntry
->BiosFound
)
844 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
847 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
851 InitializeListHead (&DiskEntry
->PartListHead
);
853 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
854 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
855 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
856 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
858 DPRINT ("Cylinders %I64u\n", DiskEntry
->Cylinders
);
859 DPRINT ("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
860 DPRINT ("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
861 DPRINT ("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
863 DiskEntry
->TrackSize
=
864 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
865 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
866 DiskEntry
->CylinderSize
=
867 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
868 DiskEntry
->TrackSize
;
869 DiskEntry
->DiskSize
=
870 DiskGeometry
.Cylinders
.QuadPart
*
871 DiskEntry
->CylinderSize
;
873 DiskEntry
->DiskNumber
= DiskNumber
;
874 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
875 DiskEntry
->Bus
= ScsiAddress
.PathId
;
876 DiskEntry
->Id
= ScsiAddress
.TargetId
;
878 GetDriverName (DiskEntry
);
880 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
883 * Allocate a buffer for 26 logical drives (2 entries each == 52)
884 * plus the main partiton table (4 entries). Total 56 entries.
886 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
887 ((56 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
888 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
891 if (LayoutBuffer
== NULL
)
896 Status
= NtDeviceIoControlFile (FileHandle
,
901 IOCTL_DISK_GET_DRIVE_LAYOUT
,
906 if (NT_SUCCESS (Status
))
908 if (LayoutBuffer
->PartitionCount
== 0)
910 DiskEntry
->NewDisk
= TRUE
;
913 AddPartitionToList (DiskNumber
,
917 ScanForUnpartitionedDiskSpace (DiskEntry
);
920 RtlFreeHeap (ProcessHeap
,
927 CreatePartitionList (SHORT Left
,
933 OBJECT_ATTRIBUTES ObjectAttributes
;
934 SYSTEM_DEVICE_INFORMATION Sdi
;
935 IO_STATUS_BLOCK Iosb
;
939 WCHAR Buffer
[MAX_PATH
];
943 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
952 List
->Bottom
= Bottom
;
957 List
->TopDisk
= (ULONG
)-1;
958 List
->TopPartition
= (ULONG
)-1;
960 List
->CurrentDisk
= NULL
;
961 List
->CurrentPartition
= NULL
;
962 List
->CurrentPartitionNumber
= 0;
964 InitializeListHead (&List
->DiskListHead
);
965 InitializeListHead (&List
->BiosDiskListHead
);
967 EnumerateBiosDiskEntries(List
);
969 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
971 sizeof(SYSTEM_DEVICE_INFORMATION
),
973 if (!NT_SUCCESS (Status
))
975 RtlFreeHeap (ProcessHeap
, 0, List
);
979 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
982 L
"\\Device\\Harddisk%d\\Partition0",
984 RtlInitUnicodeString (&Name
,
987 InitializeObjectAttributes (&ObjectAttributes
,
993 Status
= NtOpenFile (&FileHandle
,
994 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
998 FILE_SYNCHRONOUS_IO_NONALERT
);
999 if (NT_SUCCESS(Status
))
1001 AddDiskToList (FileHandle
,
1005 NtClose(FileHandle
);
1009 AssignDriverLetters (List
);
1012 List
->TopPartition
= 0;
1014 /* Search for first usable disk and partition */
1015 if (IsListEmpty (&List
->DiskListHead
))
1017 List
->CurrentDisk
= NULL
;
1018 List
->CurrentPartition
= NULL
;
1019 List
->CurrentPartitionNumber
= 0;
1024 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
1028 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
1030 List
->CurrentPartition
= 0;
1031 List
->CurrentPartitionNumber
= 0;
1035 List
->CurrentPartition
=
1036 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
1039 List
->CurrentPartitionNumber
= 0;
1048 DestroyPartitionList (PPARTLIST List
)
1050 PDISKENTRY DiskEntry
;
1051 PBIOSDISKENTRY BiosDiskEntry
;
1052 PPARTENTRY PartEntry
;
1055 /* Release disk and partition info */
1056 while (!IsListEmpty (&List
->DiskListHead
))
1058 Entry
= RemoveHeadList (&List
->DiskListHead
);
1059 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1061 /* Release driver name */
1062 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1064 /* Release partition array */
1065 while (!IsListEmpty (&DiskEntry
->PartListHead
))
1067 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
1068 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
1070 RtlFreeHeap (ProcessHeap
,
1075 /* Release disk entry */
1076 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
1079 /* release the bios disk info */
1080 while(!IsListEmpty(&List
->BiosDiskListHead
))
1082 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1083 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1085 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1088 /* Release list head */
1089 RtlFreeHeap (ProcessHeap
, 0, List
);
1094 PrintEmptyLine (PPARTLIST List
)
1101 Width
= List
->Right
- List
->Left
- 1;
1102 Height
= List
->Bottom
- List
->Top
- 2;
1105 coPos
.X
= List
->Left
+ 1;
1106 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1108 if (List
->Line
>= 0 && List
->Line
<= Height
)
1110 FillConsoleOutputAttribute (StdOutput
,
1111 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1116 FillConsoleOutputCharacterA (StdOutput
,
1127 PrintPartitionData (PPARTLIST List
,
1128 PDISKENTRY DiskEntry
,
1129 PPARTENTRY PartEntry
,
1132 CHAR LineBuffer
[128];
1138 LARGE_INTEGER PartSize
;
1143 Width
= List
->Right
- List
->Left
- 1;
1144 Height
= List
->Bottom
- List
->Top
- 2;
1147 coPos
.X
= List
->Left
+ 1;
1148 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1150 if (PartEntry
->Unpartitioned
== TRUE
)
1153 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1155 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1156 Unit
= MUIGetString(STRING_GB
);
1160 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1162 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1163 Unit
= MUIGetString(STRING_MB
);
1167 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1168 Unit
= MUIGetString(STRING_KB
);
1171 sprintf (LineBuffer
,
1172 MUIGetString(STRING_UNPSPACE
),
1178 /* Determine partition type */
1180 if (PartEntry
->New
== TRUE
)
1182 PartType
= MUIGetString(STRING_UNFORMATTED
);
1184 else if (PartEntry
->Unpartitioned
== FALSE
)
1186 if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_12
) ||
1187 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_16
) ||
1188 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_HUGE
) ||
1189 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_XINT13
))
1193 else if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32
) ||
1194 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32_XINT13
))
1198 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_EXT2
)
1202 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_IFS
)
1204 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1209 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1211 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1212 Unit
= MUIGetString(STRING_GB
);
1216 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1218 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1219 Unit
= MUIGetString(STRING_MB
);
1223 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1224 Unit
= MUIGetString(STRING_KB
);
1227 if (PartType
== NULL
)
1229 sprintf (LineBuffer
,
1230 MUIGetString(STRING_HDDINFOUNK5
),
1231 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1232 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1233 PartEntry
->PartInfo
[PartNumber
].PartitionType
,
1239 sprintf (LineBuffer
,
1240 "%c%c %-24s %6lu %s",
1241 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1242 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1249 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1250 List
->CurrentPartition
== PartEntry
&&
1251 List
->CurrentPartitionNumber
== PartNumber
) ?
1252 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1253 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1255 if (List
->Line
>= 0 && List
->Line
<= Height
)
1257 FillConsoleOutputCharacterA (StdOutput
,
1265 if (List
->Line
>= 0 && List
->Line
<= Height
)
1267 FillConsoleOutputAttribute (StdOutput
,
1275 if (List
->Line
>= 0 && List
->Line
<= Height
)
1277 WriteConsoleOutputCharacterA (StdOutput
,
1279 min (strlen (LineBuffer
), Width
),
1288 PrintDiskData (PPARTLIST List
,
1289 PDISKENTRY DiskEntry
)
1291 PPARTENTRY PartEntry
;
1293 CHAR LineBuffer
[128];
1298 ULARGE_INTEGER DiskSize
;
1302 Width
= List
->Right
- List
->Left
- 1;
1303 Height
= List
->Bottom
- List
->Top
- 2;
1306 coPos
.X
= List
->Left
+ 1;
1307 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1310 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1312 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1313 Unit
= MUIGetString(STRING_GB
);
1318 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1319 if (DiskSize
.QuadPart
== 0)
1320 DiskSize
.QuadPart
= 1;
1321 Unit
= MUIGetString(STRING_MB
);
1324 if (DiskEntry
->DriverName
.Length
> 0)
1326 sprintf (LineBuffer
,
1327 MUIGetString(STRING_HDINFOPARTSELECT
),
1330 DiskEntry
->DiskNumber
,
1334 DiskEntry
->DriverName
.Buffer
);
1338 sprintf (LineBuffer
,
1339 MUIGetString(STRING_HDDINFOUNK6
),
1342 DiskEntry
->DiskNumber
,
1347 if (List
->Line
>= 0 && List
->Line
<= Height
)
1349 FillConsoleOutputAttribute (StdOutput
,
1350 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1355 FillConsoleOutputCharacterA (StdOutput
,
1363 if (List
->Line
>= 0 && List
->Line
<= Height
)
1365 WriteConsoleOutputCharacterA (StdOutput
,
1367 min ((USHORT
)strlen (LineBuffer
), Width
- 2),
1373 /* Print separator line */
1374 PrintEmptyLine (List
);
1376 /* Print partition lines*/
1377 Entry
= DiskEntry
->PartListHead
.Flink
;
1378 while (Entry
!= &DiskEntry
->PartListHead
)
1380 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1382 /* Print disk entry */
1385 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
1386 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
1388 PrintPartitionData (List
,
1395 /* Print unpartitioned entry */
1396 if (PartEntry
->Unpartitioned
)
1398 PrintPartitionData (List
,
1404 Entry
= Entry
->Flink
;
1407 /* Print separator line */
1408 PrintEmptyLine (List
);
1413 DrawPartitionList (PPARTLIST List
)
1415 PLIST_ENTRY Entry
, Entry2
;
1416 PDISKENTRY DiskEntry
;
1417 PPARTENTRY PartEntry
= NULL
;
1421 SHORT CurrentDiskLine
;
1422 SHORT CurrentPartLine
;
1424 BOOL CurrentPartLineFound
= FALSE
;
1425 BOOL CurrentDiskLineFound
= FALSE
;
1427 /* Calculate the line of the current disk and partition */
1428 CurrentDiskLine
= 0;
1429 CurrentPartLine
= 0;
1431 Entry
= List
->DiskListHead
.Flink
;
1432 while (Entry
!= &List
->DiskListHead
)
1434 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1436 if (CurrentPartLineFound
== FALSE
)
1438 CurrentPartLine
+= 2;
1440 Entry2
= DiskEntry
->PartListHead
.Flink
;
1441 while (Entry2
!= &DiskEntry
->PartListHead
)
1443 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1444 if (PartEntry
== List
->CurrentPartition
)
1446 CurrentPartLineFound
= TRUE
;
1448 Entry2
= Entry2
->Flink
;
1449 if (CurrentPartLineFound
== FALSE
)
1455 if (DiskEntry
== List
->CurrentDisk
)
1457 CurrentDiskLineFound
= TRUE
;
1459 Entry
= Entry
->Flink
;
1460 if (Entry
!= &List
->DiskListHead
)
1462 if (CurrentDiskLineFound
== FALSE
)
1465 CurrentDiskLine
= CurrentPartLine
;
1475 /* If it possible, make the disk name visible */
1476 if (CurrentPartLine
< List
->Offset
)
1478 List
->Offset
= CurrentPartLine
;
1480 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1482 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1484 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1486 List
->Offset
= CurrentDiskLine
;
1490 /* draw upper left corner */
1491 coPos
.X
= List
->Left
;
1492 coPos
.Y
= List
->Top
;
1493 FillConsoleOutputCharacterA (StdOutput
,
1499 /* draw upper edge */
1500 coPos
.X
= List
->Left
+ 1;
1501 coPos
.Y
= List
->Top
;
1502 if (List
->Offset
== 0)
1504 FillConsoleOutputCharacterA (StdOutput
,
1506 List
->Right
- List
->Left
- 1,
1512 FillConsoleOutputCharacterA (StdOutput
,
1514 List
->Right
- List
->Left
- 5,
1517 coPos
.X
= List
->Right
- 5;
1518 WriteConsoleOutputCharacterA (StdOutput
,
1523 coPos
.X
= List
->Right
- 2;
1524 FillConsoleOutputCharacterA (StdOutput
,
1531 /* draw upper right corner */
1532 coPos
.X
= List
->Right
;
1533 coPos
.Y
= List
->Top
;
1534 FillConsoleOutputCharacterA (StdOutput
,
1540 /* draw left and right edge */
1541 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1543 coPos
.X
= List
->Left
;
1545 FillConsoleOutputCharacterA (StdOutput
,
1551 coPos
.X
= List
->Right
;
1552 FillConsoleOutputCharacterA (StdOutput
,
1559 /* draw lower left corner */
1560 coPos
.X
= List
->Left
;
1561 coPos
.Y
= List
->Bottom
;
1562 FillConsoleOutputCharacterA (StdOutput
,
1568 /* draw lower edge */
1569 coPos
.X
= List
->Left
+ 1;
1570 coPos
.Y
= List
->Bottom
;
1571 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1573 FillConsoleOutputCharacterA (StdOutput
,
1575 List
->Right
- List
->Left
- 1,
1581 FillConsoleOutputCharacterA (StdOutput
,
1583 List
->Right
- List
->Left
- 5,
1586 coPos
.X
= List
->Right
- 5;
1587 WriteConsoleOutputCharacterA (StdOutput
,
1588 "(\x19)", // "(down)"
1592 coPos
.X
= List
->Right
- 2;
1593 FillConsoleOutputCharacterA (StdOutput
,
1600 /* draw lower right corner */
1601 coPos
.X
= List
->Right
;
1602 coPos
.Y
= List
->Bottom
;
1603 FillConsoleOutputCharacterA (StdOutput
,
1609 /* print list entries */
1610 List
->Line
= - List
->Offset
;
1612 Entry
= List
->DiskListHead
.Flink
;
1613 while (Entry
!= &List
->DiskListHead
)
1615 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1617 /* Print disk entry */
1618 PrintDiskData (List
,
1621 Entry
= Entry
->Flink
;
1627 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1629 PDISKENTRY DiskEntry
;
1630 PPARTENTRY PartEntry
;
1635 /* Check for empty disks */
1636 if (IsListEmpty (&List
->DiskListHead
))
1639 /* Check for first usable entry on next disk */
1640 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1641 while (Entry1
!= &List
->DiskListHead
)
1643 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1645 if (DiskEntry
->DiskNumber
== DiskNumber
)
1647 Entry2
= DiskEntry
->PartListHead
.Flink
;
1648 while (Entry2
!= &DiskEntry
->PartListHead
)
1650 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1652 for (i
= 0; i
< 4; i
++)
1654 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1656 List
->CurrentDisk
= DiskEntry
;
1657 List
->CurrentPartition
= PartEntry
;
1658 List
->CurrentPartitionNumber
= i
;
1659 DrawPartitionList (List
);
1663 Entry2
= Entry2
->Flink
;
1667 Entry1
= Entry1
->Flink
;
1674 ScrollDownPartitionList (PPARTLIST List
)
1676 PDISKENTRY DiskEntry
;
1677 PPARTENTRY PartEntry
;
1682 /* Check for empty disks */
1683 if (IsListEmpty (&List
->DiskListHead
))
1686 /* Check for next usable entry on current disk */
1687 if (List
->CurrentPartition
!= NULL
)
1689 Entry2
= &List
->CurrentPartition
->ListEntry
;
1690 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1692 /* Check if we can move inside primary partitions */
1693 for (i
= List
->CurrentPartitionNumber
+ 1; i
< 4; i
++)
1695 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1701 /* We're out of partitions in the current partition table.
1702 Try to move to the next one if possible. */
1703 Entry2
= Entry2
->Flink
;
1707 /* Just advance to the next partition */
1708 List
->CurrentPartitionNumber
= i
;
1709 DrawPartitionList (List
);
1713 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1715 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1717 // if (PartEntry->HidePartEntry == FALSE)
1719 List
->CurrentPartition
= PartEntry
;
1720 List
->CurrentPartitionNumber
= 0;
1721 DrawPartitionList (List
);
1724 Entry2
= Entry2
->Flink
;
1728 /* Check for first usable entry on next disk */
1729 if (List
->CurrentDisk
!= NULL
)
1731 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1732 while (Entry1
!= &List
->DiskListHead
)
1734 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1736 Entry2
= DiskEntry
->PartListHead
.Flink
;
1737 while (Entry2
!= &DiskEntry
->PartListHead
)
1739 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1741 // if (PartEntry->HidePartEntry == FALSE)
1743 List
->CurrentDisk
= DiskEntry
;
1744 List
->CurrentPartition
= PartEntry
;
1745 List
->CurrentPartitionNumber
= 0;
1746 DrawPartitionList (List
);
1750 Entry2
= Entry2
->Flink
;
1753 Entry1
= Entry1
->Flink
;
1760 ScrollUpPartitionList (PPARTLIST List
)
1762 PDISKENTRY DiskEntry
;
1763 PPARTENTRY PartEntry
;
1768 /* Check for empty disks */
1769 if (IsListEmpty (&List
->DiskListHead
))
1772 /* check for previous usable entry on current disk */
1773 if (List
->CurrentPartition
!= NULL
)
1775 Entry2
= &List
->CurrentPartition
->ListEntry
;
1776 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1778 /* Check if we can move inside primary partitions */
1779 if (List
->CurrentPartitionNumber
> 0)
1781 /* Find a previous partition */
1782 for (i
= List
->CurrentPartitionNumber
- 1; i
> 0; i
--)
1784 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1788 /* Move to it and return */
1789 List
->CurrentPartitionNumber
= i
;
1790 DrawPartitionList (List
);
1794 /* Move to the previous entry */
1795 Entry2
= Entry2
->Blink
;
1797 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1799 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1801 // if (PartEntry->HidePartEntry == FALSE)
1803 List
->CurrentPartition
= PartEntry
;
1805 /* Find last existing partition in the table */
1806 for (i
= 3; i
> 0; i
--)
1808 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1813 List
->CurrentPartitionNumber
= i
;
1815 /* Draw partition list and return */
1816 DrawPartitionList (List
);
1819 Entry2
= Entry2
->Blink
;
1824 /* check for last usable entry on previous disk */
1825 if (List
->CurrentDisk
!= NULL
)
1827 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1828 while (Entry1
!= &List
->DiskListHead
)
1830 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1832 Entry2
= DiskEntry
->PartListHead
.Blink
;
1833 while (Entry2
!= &DiskEntry
->PartListHead
)
1835 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1837 // if (PartEntry->HidePartEntry == FALSE)
1839 List
->CurrentDisk
= DiskEntry
;
1840 List
->CurrentPartition
= PartEntry
;
1842 /* Find last existing partition in the table */
1843 for (i
= 3; i
> 0; i
--)
1845 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1850 List
->CurrentPartitionNumber
= i
;
1852 /* Draw partition list and return */
1853 DrawPartitionList (List
);
1857 Entry2
= Entry2
->Blink
;
1860 Entry1
= Entry1
->Blink
;
1867 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1868 PPARTENTRY CurrentEntry
)
1870 PPARTENTRY PrevEntry
;
1873 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1876 Entry
= CurrentEntry
->ListEntry
.Blink
;
1877 while (Entry
!= &DiskEntry
->PartListHead
)
1879 PrevEntry
= CONTAINING_RECORD (Entry
,
1882 if (PrevEntry
->Unpartitioned
== FALSE
)
1885 Entry
= Entry
->Blink
;
1893 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1894 PPARTENTRY CurrentEntry
)
1896 PPARTENTRY NextEntry
;
1899 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1902 Entry
= CurrentEntry
->ListEntry
.Flink
;
1903 while (Entry
!= &DiskEntry
->PartListHead
)
1905 NextEntry
= CONTAINING_RECORD (Entry
,
1908 if (NextEntry
->Unpartitioned
== FALSE
)
1911 Entry
= Entry
->Flink
;
1919 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1920 PPARTENTRY PartEntry
)
1922 PPARTENTRY PrevPartEntry
;
1924 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1926 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1929 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1930 return PrevPartEntry
;
1938 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1939 PPARTENTRY PartEntry
)
1941 PPARTENTRY NextPartEntry
;
1943 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1945 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1948 if (NextPartEntry
->Unpartitioned
== TRUE
)
1949 return NextPartEntry
;
1957 CreateNewPartition (PPARTLIST List
,
1958 ULONGLONG PartitionSize
,
1961 PDISKENTRY DiskEntry
;
1962 PPARTENTRY PartEntry
;
1963 PPARTENTRY PrevPartEntry
;
1964 PPARTENTRY NextPartEntry
;
1965 PPARTENTRY NewPartEntry
;
1968 List
->CurrentDisk
== NULL
||
1969 List
->CurrentPartition
== NULL
||
1970 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1975 DiskEntry
= List
->CurrentDisk
;
1976 PartEntry
= List
->CurrentPartition
;
1978 if (AutoCreate
== TRUE
||
1979 PartitionSize
== PartEntry
->UnpartitionedLength
)
1981 /* Convert current entry to 'new (unformatted)' */
1982 PartEntry
->FormatState
= Unformatted
;
1983 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1984 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1985 PartEntry
->PartInfo
[0].HiddenSectors
=
1986 (ULONG
)(PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
1987 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1988 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1989 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1990 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1991 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1992 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1993 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1994 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1996 /* Get previous and next partition entries */
1997 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1999 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2002 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2004 /* Current entry is in the middle of the list */
2006 /* Copy previous container partition data to current entry */
2007 RtlCopyMemory (&PartEntry
->PartInfo
[1],
2008 &PrevPartEntry
->PartInfo
[1],
2009 sizeof(PARTITION_INFORMATION
));
2010 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2012 /* Update previous container partition data */
2014 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2015 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2016 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2017 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2019 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2021 /* Special case - previous partition is first partition */
2022 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2023 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2027 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2028 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2031 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2033 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2035 /* Current entry is the first entry */
2038 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2040 /* Current entry is the last entry */
2042 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2043 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2044 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2045 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2047 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2049 /* Special case - previous partition is first partition */
2050 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2051 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2055 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2056 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2059 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2060 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2061 (1024LL * 255LL * 63LL * 512LL))
2063 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2067 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2070 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2071 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2074 PartEntry
->AutoCreate
= AutoCreate
;
2075 PartEntry
->New
= TRUE
;
2076 PartEntry
->Unpartitioned
= FALSE
;
2077 PartEntry
->UnpartitionedOffset
= 0ULL;
2078 PartEntry
->UnpartitionedLength
= 0ULL;
2082 /* Insert an initialize a new partition entry */
2083 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
2086 if (NewPartEntry
== NULL
)
2089 RtlZeroMemory (NewPartEntry
,
2092 /* Insert the new entry into the list */
2093 InsertTailList (&PartEntry
->ListEntry
,
2094 &NewPartEntry
->ListEntry
);
2096 NewPartEntry
->New
= TRUE
;
2098 NewPartEntry
->FormatState
= Unformatted
;
2099 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
2100 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
2101 NewPartEntry
->PartInfo
[0].HiddenSectors
=
2102 (ULONG
)(NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2103 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
2104 PartitionSize
- DiskEntry
->TrackSize
;
2105 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
2106 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
2107 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2108 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2109 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
2110 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
2112 /* Get previous and next partition entries */
2113 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2115 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2118 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2120 /* Current entry is in the middle of the list */
2122 /* Copy previous container partition data to current entry */
2123 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
2124 &PrevPartEntry
->PartInfo
[1],
2125 sizeof(PARTITION_INFORMATION
));
2126 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2128 /* Update previous container partition data */
2130 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2131 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2132 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2133 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2135 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2137 /* Special case - previous partition is first partition */
2138 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2139 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2143 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2144 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2147 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2149 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2151 /* Current entry is the first entry */
2154 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2156 /* Current entry is the last entry */
2158 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2159 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2160 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2161 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2163 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2165 /* Special case - previous partition is first partition */
2166 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2167 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2171 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2172 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2175 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2176 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2177 (1024LL * 255LL * 63LL * 512LL))
2179 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2183 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2186 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2187 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2190 /* Update offset and size of the remaining unpartitioned disk space */
2191 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
2192 PartEntry
->UnpartitionedLength
-= PartitionSize
;
2195 DiskEntry
->Modified
= TRUE
;
2197 UpdatePartitionNumbers (DiskEntry
);
2199 AssignDriverLetters (List
);
2204 DeleteCurrentPartition (PPARTLIST List
)
2206 PDISKENTRY DiskEntry
;
2207 PPARTENTRY PartEntry
;
2208 PPARTENTRY PrevPartEntry
;
2209 PPARTENTRY NextPartEntry
;
2212 List
->CurrentDisk
== NULL
||
2213 List
->CurrentPartition
== NULL
||
2214 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2219 DiskEntry
= List
->CurrentDisk
;
2220 PartEntry
= List
->CurrentPartition
;
2222 /* Adjust container partition entries */
2224 /* Get previous and next partition entries */
2225 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2227 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2230 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2232 /* Current entry is in the middle of the list */
2235 * The first extended partition can not be deleted
2236 * as long as other extended partitions are present.
2238 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2241 /* Copy previous container partition data to current entry */
2242 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
2243 &PartEntry
->PartInfo
[1],
2244 sizeof(PARTITION_INFORMATION
));
2245 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2247 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2250 * A primary partition can not be deleted as long as
2251 * extended partitions are present.
2255 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2257 /* Current entry is the last entry */
2258 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
2259 sizeof(PARTITION_INFORMATION
));
2260 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2264 /* Adjust unpartitioned disk space entries */
2266 /* Get pointer to previous and next unpartitioned entries */
2267 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
2270 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
2273 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2275 /* Merge previous, current and next unpartitioned entry */
2277 /* Adjust the previous entries length */
2278 PrevPartEntry
->UnpartitionedLength
+=
2279 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2280 NextPartEntry
->UnpartitionedLength
);
2282 /* Remove the current entry */
2283 RemoveEntryList (&PartEntry
->ListEntry
);
2284 RtlFreeHeap (ProcessHeap
,
2288 /* Remove the next entry */
2289 RemoveEntryList (&NextPartEntry
->ListEntry
);
2290 RtlFreeHeap (ProcessHeap
,
2294 /* Update current partition */
2295 List
->CurrentPartition
= PrevPartEntry
;
2297 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2299 /* Merge current and previous unpartitioned entry */
2301 /* Adjust the previous entries length */
2302 PrevPartEntry
->UnpartitionedLength
+=
2303 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2305 /* Remove the current entry */
2306 RemoveEntryList (&PartEntry
->ListEntry
);
2307 RtlFreeHeap (ProcessHeap
,
2311 /* Update current partition */
2312 List
->CurrentPartition
= PrevPartEntry
;
2314 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2316 /* Merge current and next unpartitioned entry */
2318 /* Adjust the next entries offset and length */
2319 NextPartEntry
->UnpartitionedOffset
=
2320 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2321 NextPartEntry
->UnpartitionedLength
+=
2322 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2324 /* Remove the current entry */
2325 RemoveEntryList (&PartEntry
->ListEntry
);
2326 RtlFreeHeap (ProcessHeap
,
2330 /* Update current partition */
2331 List
->CurrentPartition
= NextPartEntry
;
2335 /* Nothing to merge but change current entry */
2336 PartEntry
->New
= FALSE
;
2337 PartEntry
->Unpartitioned
= TRUE
;
2338 PartEntry
->UnpartitionedOffset
=
2339 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2340 PartEntry
->UnpartitionedLength
=
2341 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2343 /* Wipe the partition table */
2344 RtlZeroMemory (&PartEntry
->PartInfo
,
2345 sizeof(PartEntry
->PartInfo
));
2348 DiskEntry
->Modified
= TRUE
;
2350 UpdatePartitionNumbers (DiskEntry
);
2352 AssignDriverLetters (List
);
2357 CheckActiveBootPartition (PPARTLIST List
)
2359 PDISKENTRY DiskEntry
;
2360 PPARTENTRY PartEntry
;
2361 PLIST_ENTRY ListEntry
;
2364 /* Check for empty disk list */
2365 if (IsListEmpty (&List
->DiskListHead
))
2367 List
->ActiveBootDisk
= NULL
;
2368 List
->ActiveBootPartition
= NULL
;
2369 List
->ActiveBootPartitionNumber
= 0;
2374 if (List
->ActiveBootDisk
!= NULL
&&
2375 List
->ActiveBootPartition
!= NULL
)
2377 /* We already have an active boot partition */
2382 /* Choose the currently selected disk */
2383 DiskEntry
= List
->CurrentDisk
;
2385 /* Check for empty partition list */
2386 if (IsListEmpty (&DiskEntry
->PartListHead
))
2388 List
->ActiveBootDisk
= NULL
;
2389 List
->ActiveBootPartition
= NULL
;
2390 List
->ActiveBootPartitionNumber
= 0;
2394 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
2398 /* Set active boot partition */
2399 if ((DiskEntry
->NewDisk
== TRUE
) ||
2400 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2401 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2402 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2403 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2405 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2406 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2407 DiskEntry
->Modified
= TRUE
;
2409 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2410 List
->ActiveBootDisk
= DiskEntry
;
2411 List
->ActiveBootPartition
= PartEntry
;
2412 List
->ActiveBootPartitionNumber
= 0;
2417 /* Disk is not new, scan all partitions to find a bootable one */
2418 List
->ActiveBootDisk
= NULL
;
2419 List
->ActiveBootPartition
= NULL
;
2420 List
->ActiveBootPartitionNumber
= 0;
2422 ListEntry
= DiskEntry
->PartListHead
.Flink
;
2423 while (ListEntry
!= &DiskEntry
->PartListHead
)
2425 PartEntry
= CONTAINING_RECORD(ListEntry
,
2429 /* Check if it's partitioned */
2430 if (!PartEntry
->Unpartitioned
)
2432 /* Go through all of its 4 partitions */
2435 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2436 PartEntry
->PartInfo
[i
].BootIndicator
)
2438 /* Yes, we found it */
2439 List
->ActiveBootDisk
= DiskEntry
;
2440 List
->ActiveBootPartition
= PartEntry
;
2441 List
->ActiveBootPartitionNumber
= i
;
2443 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2444 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
[i
]);
2450 /* Go to the next one */
2451 ListEntry
= ListEntry
->Flink
;
2457 CheckForLinuxFdiskPartitions (PPARTLIST List
)
2459 PDISKENTRY DiskEntry
;
2460 PPARTENTRY PartEntry
;
2463 ULONG PartitionCount
;
2466 Entry1
= List
->DiskListHead
.Flink
;
2467 while (Entry1
!= &List
->DiskListHead
)
2469 DiskEntry
= CONTAINING_RECORD (Entry1
,
2473 Entry2
= DiskEntry
->PartListHead
.Flink
;
2474 while (Entry2
!= &DiskEntry
->PartListHead
)
2476 PartEntry
= CONTAINING_RECORD (Entry2
,
2480 if (PartEntry
->Unpartitioned
== FALSE
)
2484 for (i
= 0; i
< 4; i
++)
2486 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
2487 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2493 if (PartitionCount
> 1)
2499 Entry2
= Entry2
->Flink
;
2502 Entry1
= Entry1
->Flink
;
2510 WritePartitionsToDisk (PPARTLIST List
)
2512 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2513 OBJECT_ATTRIBUTES ObjectAttributes
;
2514 IO_STATUS_BLOCK Iosb
;
2515 WCHAR DstPath
[MAX_PATH
];
2516 UNICODE_STRING Name
;
2518 PDISKENTRY DiskEntry1
;
2519 PDISKENTRY DiskEntry2
;
2520 PPARTENTRY PartEntry
;
2523 ULONG PartitionCount
;
2524 ULONG DriveLayoutSize
;
2533 Entry1
= List
->DiskListHead
.Flink
;
2534 while (Entry1
!= &List
->DiskListHead
)
2536 DiskEntry1
= CONTAINING_RECORD (Entry1
,
2540 if (DiskEntry1
->Modified
== TRUE
)
2542 /* Count partitioned entries */
2544 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2545 while (Entry2
!= &DiskEntry1
->PartListHead
)
2547 PartEntry
= CONTAINING_RECORD (Entry2
,
2550 if (PartEntry
->Unpartitioned
== FALSE
)
2552 PartitionCount
+= 4;
2555 Entry2
= Entry2
->Flink
;
2557 if (PartitionCount
== 0)
2559 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2560 ((4 - 1) * sizeof (PARTITION_INFORMATION
));
2564 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2565 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2567 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
2570 if (DriveLayout
== NULL
)
2572 DPRINT1 ("RtlAllocateHeap() failed\n");
2576 RtlZeroMemory (DriveLayout
,
2579 if (PartitionCount
== 0)
2581 /* delete all partitions in the mbr */
2582 DriveLayout
->PartitionCount
= 4;
2583 for (Index
= 0; Index
< 4; Index
++)
2585 DriveLayout
->PartitionEntry
[Index
].RewritePartition
= TRUE
;
2590 DriveLayout
->PartitionCount
= PartitionCount
;
2593 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2594 while (Entry2
!= &DiskEntry1
->PartListHead
)
2596 PartEntry
= CONTAINING_RECORD (Entry2
,
2599 if (PartEntry
->Unpartitioned
== FALSE
)
2601 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2602 &PartEntry
->PartInfo
[0],
2603 4 * sizeof (PARTITION_INFORMATION
));
2607 Entry2
= Entry2
->Flink
;
2610 if (DiskEntry1
->Signature
== 0)
2612 LARGE_INTEGER SystemTime
;
2613 TIME_FIELDS TimeFields
;
2615 Buffer
= (PUCHAR
)&DiskEntry1
->Signature
;
2619 NtQuerySystemTime (&SystemTime
);
2620 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
2622 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
2623 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
2624 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
2625 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
2627 if (DiskEntry1
->Signature
== 0)
2632 /* check if the signature already exist */
2634 * Check also signatures from disks, which are
2635 * not visible (bootable) by the bios.
2637 Entry2
= List
->DiskListHead
.Flink
;
2638 while (Entry2
!= &List
->DiskListHead
)
2640 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
2641 if (DiskEntry1
!= DiskEntry2
&&
2642 DiskEntry1
->Signature
== DiskEntry2
->Signature
)
2646 Entry2
= Entry2
->Flink
;
2648 if (Entry2
== &List
->DiskListHead
)
2654 /* set one partition entry to dirty, this will update the signature */
2655 DriveLayout
->PartitionEntry
[0].RewritePartition
= TRUE
;
2659 DriveLayout
->Signature
= DiskEntry1
->Signature
;
2663 L
"\\Device\\Harddisk%d\\Partition0",
2664 DiskEntry1
->DiskNumber
);
2665 RtlInitUnicodeString (&Name
,
2667 InitializeObjectAttributes (&ObjectAttributes
,
2673 Status
= NtOpenFile (&FileHandle
,
2678 FILE_SYNCHRONOUS_IO_NONALERT
);
2680 if (!NT_SUCCESS (Status
))
2682 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2686 Status
= NtDeviceIoControlFile (FileHandle
,
2691 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2696 if (!NT_SUCCESS (Status
))
2698 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2699 NtClose (FileHandle
);
2703 RtlFreeHeap (ProcessHeap
,
2707 NtClose (FileHandle
);
2710 Entry1
= Entry1
->Flink
;
2716 BOOL
SetMountedDeviceValues(PPARTLIST List
)
2718 PLIST_ENTRY Entry1
, Entry2
;
2719 PDISKENTRY DiskEntry
;
2720 PPARTENTRY PartEntry
;
2728 Entry1
= List
->DiskListHead
.Flink
;
2729 while (Entry1
!= &List
->DiskListHead
)
2731 DiskEntry
= CONTAINING_RECORD (Entry1
,
2735 Entry2
= DiskEntry
->PartListHead
.Flink
;
2736 while (Entry2
!= &DiskEntry
->PartListHead
)
2738 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2739 if (!PartEntry
->Unpartitioned
)
2743 if (PartEntry
->DriveLetter
[i
])
2745 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
[i
], DiskEntry
->Signature
, PartEntry
->PartInfo
[i
].StartingOffset
))
2752 Entry2
= Entry2
->Flink
;
2754 Entry1
= Entry1
->Flink
;