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
;
704 ULONG LayoutBufferSize
;
706 Status
= NtDeviceIoControlFile (FileHandle
,
711 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
715 sizeof(DISK_GEOMETRY
));
716 if (!NT_SUCCESS (Status
))
721 if (DiskGeometry
.MediaType
!= FixedMedia
)
726 Status
= NtDeviceIoControlFile (FileHandle
,
731 IOCTL_SCSI_GET_ADDRESS
,
735 sizeof(SCSI_ADDRESS
));
736 if (!NT_SUCCESS(Status
))
741 Mbr
= (PARTITION_SECTOR
*) RtlAllocateHeap(ProcessHeap
,
743 DiskGeometry
.BytesPerSector
);
750 FileOffset
.QuadPart
= 0;
751 Status
= NtReadFile(FileHandle
,
757 DiskGeometry
.BytesPerSector
,
760 if (!NT_SUCCESS(Status
))
762 RtlFreeHeap(ProcessHeap
,
765 DPRINT1("NtReadFile failed, status=%x\n", Status
);
768 Signature
= Mbr
->Signature
;
770 /* Calculate the MBR checksum */
772 Buffer
= (PULONG
)Mbr
;
773 for (i
= 0; i
< 128; i
++)
775 Checksum
+= Buffer
[i
];
777 Checksum
= ~Checksum
+ 1;
779 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
780 DPRINT("Identifier: %S\n", Identifier
);
782 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
785 if (DiskEntry
== NULL
)
790 DiskEntry
->Checksum
= Checksum
;
791 DiskEntry
->Signature
= Signature
;
794 /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
795 DiskEntry
->Modified
= TRUE
;
797 DiskEntry
->BiosFound
= FALSE
;
799 /* Check if this disk has a valid MBR */
800 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
801 DiskEntry
->NoMbr
= TRUE
;
803 DiskEntry
->NoMbr
= FALSE
;
805 /* Free Mbr sector buffer */
806 RtlFreeHeap (ProcessHeap
,
810 ListEntry
= List
->BiosDiskListHead
.Flink
;
811 while(ListEntry
!= &List
->BiosDiskListHead
)
813 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
815 * Compare the size from bios and the reported size from driver.
816 * If we have more than one disk with a zero or with the same signatur
817 * we must create new signatures and reboot. After the reboot,
818 * it is possible to identify the disks.
820 if (BiosDiskEntry
->Signature
== Signature
&&
821 BiosDiskEntry
->Checksum
== Checksum
&&
822 !BiosDiskEntry
->Recognized
)
824 if (!DiskEntry
->BiosFound
)
826 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
827 DiskEntry
->BiosFound
= TRUE
;
828 BiosDiskEntry
->Recognized
= TRUE
;
834 ListEntry
= ListEntry
->Flink
;
837 if (!DiskEntry
->BiosFound
)
839 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
843 InitializeListHead (&DiskEntry
->PartListHead
);
845 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
846 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
847 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
848 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
850 DPRINT ("Cylinders %I64u\n", DiskEntry
->Cylinders
);
851 DPRINT ("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
852 DPRINT ("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
853 DPRINT ("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
855 DiskEntry
->TrackSize
=
856 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
857 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
858 DiskEntry
->CylinderSize
=
859 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
860 DiskEntry
->TrackSize
;
861 DiskEntry
->DiskSize
=
862 DiskGeometry
.Cylinders
.QuadPart
*
863 DiskEntry
->CylinderSize
;
865 DiskEntry
->DiskNumber
= DiskNumber
;
866 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
867 DiskEntry
->Bus
= ScsiAddress
.PathId
;
868 DiskEntry
->Id
= ScsiAddress
.TargetId
;
870 GetDriverName (DiskEntry
);
872 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, BiosDiskNumber
);
875 * Allocate a buffer for 26 logical drives (2 entries each == 52)
876 * plus the main partiton table (4 entries). Total 56 entries.
878 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
879 ((56 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
880 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
883 if (LayoutBuffer
== NULL
)
888 Status
= NtDeviceIoControlFile (FileHandle
,
893 IOCTL_DISK_GET_DRIVE_LAYOUT
,
898 if (NT_SUCCESS (Status
))
900 if (LayoutBuffer
->PartitionCount
== 0)
902 DiskEntry
->NewDisk
= TRUE
;
905 AddPartitionToList (DiskNumber
,
909 ScanForUnpartitionedDiskSpace (DiskEntry
);
912 RtlFreeHeap (ProcessHeap
,
919 CreatePartitionList (SHORT Left
,
925 OBJECT_ATTRIBUTES ObjectAttributes
;
926 SYSTEM_DEVICE_INFORMATION Sdi
;
927 IO_STATUS_BLOCK Iosb
;
931 WCHAR Buffer
[MAX_PATH
];
935 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
944 List
->Bottom
= Bottom
;
949 List
->TopDisk
= (ULONG
)-1;
950 List
->TopPartition
= (ULONG
)-1;
952 List
->CurrentDisk
= NULL
;
953 List
->CurrentPartition
= NULL
;
954 List
->CurrentPartitionNumber
= 0;
956 InitializeListHead (&List
->DiskListHead
);
957 InitializeListHead (&List
->BiosDiskListHead
);
959 EnumerateBiosDiskEntries(List
);
961 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
963 sizeof(SYSTEM_DEVICE_INFORMATION
),
965 if (!NT_SUCCESS (Status
))
967 RtlFreeHeap (ProcessHeap
, 0, List
);
971 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
974 L
"\\Device\\Harddisk%d\\Partition0",
976 RtlInitUnicodeString (&Name
,
979 InitializeObjectAttributes (&ObjectAttributes
,
985 Status
= NtOpenFile (&FileHandle
,
986 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
990 FILE_SYNCHRONOUS_IO_NONALERT
);
991 if (NT_SUCCESS(Status
))
993 AddDiskToList (FileHandle
,
1001 AssignDriverLetters (List
);
1004 List
->TopPartition
= 0;
1006 /* Search for first usable disk and partition */
1007 if (IsListEmpty (&List
->DiskListHead
))
1009 List
->CurrentDisk
= NULL
;
1010 List
->CurrentPartition
= NULL
;
1011 List
->CurrentPartitionNumber
= 0;
1016 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
1020 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
1022 List
->CurrentPartition
= 0;
1023 List
->CurrentPartitionNumber
= 0;
1027 List
->CurrentPartition
=
1028 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
1031 List
->CurrentPartitionNumber
= 0;
1040 DestroyPartitionList (PPARTLIST List
)
1042 PDISKENTRY DiskEntry
;
1043 PBIOSDISKENTRY BiosDiskEntry
;
1044 PPARTENTRY PartEntry
;
1047 /* Release disk and partition info */
1048 while (!IsListEmpty (&List
->DiskListHead
))
1050 Entry
= RemoveHeadList (&List
->DiskListHead
);
1051 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1053 /* Release driver name */
1054 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1056 /* Release partition array */
1057 while (!IsListEmpty (&DiskEntry
->PartListHead
))
1059 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
1060 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
1062 RtlFreeHeap (ProcessHeap
,
1067 /* Release disk entry */
1068 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
1071 /* release the bios disk info */
1072 while(!IsListEmpty(&List
->BiosDiskListHead
))
1074 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1075 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1077 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1080 /* Release list head */
1081 RtlFreeHeap (ProcessHeap
, 0, List
);
1086 PrintEmptyLine (PPARTLIST List
)
1093 Width
= List
->Right
- List
->Left
- 1;
1094 Height
= List
->Bottom
- List
->Top
- 2;
1097 coPos
.X
= List
->Left
+ 1;
1098 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1100 if (List
->Line
>= 0 && List
->Line
<= Height
)
1102 FillConsoleOutputAttribute (StdOutput
,
1103 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1108 FillConsoleOutputCharacterA (StdOutput
,
1119 PrintPartitionData (PPARTLIST List
,
1120 PDISKENTRY DiskEntry
,
1121 PPARTENTRY PartEntry
,
1124 CHAR LineBuffer
[128];
1130 LARGE_INTEGER PartSize
;
1135 Width
= List
->Right
- List
->Left
- 1;
1136 Height
= List
->Bottom
- List
->Top
- 2;
1139 coPos
.X
= List
->Left
+ 1;
1140 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1142 if (PartEntry
->Unpartitioned
== TRUE
)
1145 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1147 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1148 Unit
= MUIGetString(STRING_GB
);
1152 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1154 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1155 Unit
= MUIGetString(STRING_MB
);
1159 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1160 Unit
= MUIGetString(STRING_KB
);
1163 sprintf (LineBuffer
,
1164 MUIGetString(STRING_UNPSPACE
),
1170 /* Determine partition type */
1172 if (PartEntry
->New
== TRUE
)
1174 PartType
= MUIGetString(STRING_UNFORMATTED
);
1176 else if (PartEntry
->Unpartitioned
== FALSE
)
1178 if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_12
) ||
1179 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_16
) ||
1180 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_HUGE
) ||
1181 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_XINT13
))
1185 else if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32
) ||
1186 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32_XINT13
))
1190 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_EXT2
)
1194 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_IFS
)
1196 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1201 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1203 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1204 Unit
= MUIGetString(STRING_GB
);
1208 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1210 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1211 Unit
= MUIGetString(STRING_MB
);
1215 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1216 Unit
= MUIGetString(STRING_KB
);
1219 if (PartType
== NULL
)
1221 sprintf (LineBuffer
,
1222 MUIGetString(STRING_HDDINFOUNK5
),
1223 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1224 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1225 PartEntry
->PartInfo
[PartNumber
].PartitionType
,
1231 sprintf (LineBuffer
,
1232 "%c%c %-24s %6lu %s",
1233 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1234 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1241 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1242 List
->CurrentPartition
== PartEntry
&&
1243 List
->CurrentPartitionNumber
== PartNumber
) ?
1244 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1245 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1247 if (List
->Line
>= 0 && List
->Line
<= Height
)
1249 FillConsoleOutputCharacterA (StdOutput
,
1257 if (List
->Line
>= 0 && List
->Line
<= Height
)
1259 FillConsoleOutputAttribute (StdOutput
,
1267 if (List
->Line
>= 0 && List
->Line
<= Height
)
1269 WriteConsoleOutputCharacterA (StdOutput
,
1271 min (strlen (LineBuffer
), Width
),
1280 PrintDiskData (PPARTLIST List
,
1281 PDISKENTRY DiskEntry
)
1283 PPARTENTRY PartEntry
;
1284 CHAR LineBuffer
[128];
1289 ULARGE_INTEGER DiskSize
;
1293 Width
= List
->Right
- List
->Left
- 1;
1294 Height
= List
->Bottom
- List
->Top
- 2;
1297 coPos
.X
= List
->Left
+ 1;
1298 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1301 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1303 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1304 Unit
= MUIGetString(STRING_GB
);
1309 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1310 if (DiskSize
.QuadPart
== 0)
1311 DiskSize
.QuadPart
= 1;
1312 Unit
= MUIGetString(STRING_MB
);
1315 if (DiskEntry
->DriverName
.Length
> 0)
1317 sprintf (LineBuffer
,
1318 MUIGetString(STRING_HDINFOPARTSELECT
),
1321 DiskEntry
->DiskNumber
,
1325 DiskEntry
->DriverName
.Buffer
);
1329 sprintf (LineBuffer
,
1330 MUIGetString(STRING_HDDINFOUNK6
),
1333 DiskEntry
->DiskNumber
,
1338 if (List
->Line
>= 0 && List
->Line
<= Height
)
1340 FillConsoleOutputAttribute (StdOutput
,
1341 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1346 FillConsoleOutputCharacterA (StdOutput
,
1354 if (List
->Line
>= 0 && List
->Line
<= Height
)
1356 WriteConsoleOutputCharacterA (StdOutput
,
1358 min ((USHORT
)strlen (LineBuffer
), Width
- 2),
1364 /* Print separator line */
1365 PrintEmptyLine (List
);
1367 /* Print partition lines*/
1368 LIST_FOR_EACH(PartEntry
, &DiskEntry
->PartListHead
, PARTENTRY
, ListEntry
)
1370 /* Print disk entry */
1373 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
1374 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
1376 PrintPartitionData (List
,
1383 /* Print unpartitioned entry */
1384 if (PartEntry
->Unpartitioned
)
1386 PrintPartitionData (List
,
1394 /* Print separator line */
1395 PrintEmptyLine (List
);
1400 DrawPartitionList (PPARTLIST List
)
1402 PLIST_ENTRY Entry
, Entry2
;
1403 PDISKENTRY DiskEntry
;
1404 PPARTENTRY PartEntry
= NULL
;
1408 SHORT CurrentDiskLine
;
1409 SHORT CurrentPartLine
;
1411 BOOL CurrentPartLineFound
= FALSE
;
1412 BOOL CurrentDiskLineFound
= FALSE
;
1414 /* Calculate the line of the current disk and partition */
1415 CurrentDiskLine
= 0;
1416 CurrentPartLine
= 0;
1418 Entry
= List
->DiskListHead
.Flink
;
1419 while (Entry
!= &List
->DiskListHead
)
1421 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1423 if (CurrentPartLineFound
== FALSE
)
1425 CurrentPartLine
+= 2;
1427 Entry2
= DiskEntry
->PartListHead
.Flink
;
1428 while (Entry2
!= &DiskEntry
->PartListHead
)
1430 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1431 if (PartEntry
== List
->CurrentPartition
)
1433 CurrentPartLineFound
= TRUE
;
1435 Entry2
= Entry2
->Flink
;
1436 if (CurrentPartLineFound
== FALSE
)
1442 if (DiskEntry
== List
->CurrentDisk
)
1444 CurrentDiskLineFound
= TRUE
;
1446 Entry
= Entry
->Flink
;
1447 if (Entry
!= &List
->DiskListHead
)
1449 if (CurrentDiskLineFound
== FALSE
)
1452 CurrentDiskLine
= CurrentPartLine
;
1462 /* If it possible, make the disk name visible */
1463 if (CurrentPartLine
< List
->Offset
)
1465 List
->Offset
= CurrentPartLine
;
1467 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1469 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1471 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1473 List
->Offset
= CurrentDiskLine
;
1477 /* draw upper left corner */
1478 coPos
.X
= List
->Left
;
1479 coPos
.Y
= List
->Top
;
1480 FillConsoleOutputCharacterA (StdOutput
,
1486 /* draw upper edge */
1487 coPos
.X
= List
->Left
+ 1;
1488 coPos
.Y
= List
->Top
;
1489 if (List
->Offset
== 0)
1491 FillConsoleOutputCharacterA (StdOutput
,
1493 List
->Right
- List
->Left
- 1,
1499 FillConsoleOutputCharacterA (StdOutput
,
1501 List
->Right
- List
->Left
- 5,
1504 coPos
.X
= List
->Right
- 5;
1505 WriteConsoleOutputCharacterA (StdOutput
,
1510 coPos
.X
= List
->Right
- 2;
1511 FillConsoleOutputCharacterA (StdOutput
,
1518 /* draw upper right corner */
1519 coPos
.X
= List
->Right
;
1520 coPos
.Y
= List
->Top
;
1521 FillConsoleOutputCharacterA (StdOutput
,
1527 /* draw left and right edge */
1528 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1530 coPos
.X
= List
->Left
;
1532 FillConsoleOutputCharacterA (StdOutput
,
1538 coPos
.X
= List
->Right
;
1539 FillConsoleOutputCharacterA (StdOutput
,
1546 /* draw lower left corner */
1547 coPos
.X
= List
->Left
;
1548 coPos
.Y
= List
->Bottom
;
1549 FillConsoleOutputCharacterA (StdOutput
,
1555 /* draw lower edge */
1556 coPos
.X
= List
->Left
+ 1;
1557 coPos
.Y
= List
->Bottom
;
1558 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1560 FillConsoleOutputCharacterA (StdOutput
,
1562 List
->Right
- List
->Left
- 1,
1568 FillConsoleOutputCharacterA (StdOutput
,
1570 List
->Right
- List
->Left
- 5,
1573 coPos
.X
= List
->Right
- 5;
1574 WriteConsoleOutputCharacterA (StdOutput
,
1575 "(\x19)", // "(down)"
1579 coPos
.X
= List
->Right
- 2;
1580 FillConsoleOutputCharacterA (StdOutput
,
1587 /* draw lower right corner */
1588 coPos
.X
= List
->Right
;
1589 coPos
.Y
= List
->Bottom
;
1590 FillConsoleOutputCharacterA (StdOutput
,
1596 /* print list entries */
1597 List
->Line
= - List
->Offset
;
1599 LIST_FOR_EACH(DiskEntry
, &List
->DiskListHead
, DISKENTRY
, ListEntry
)
1601 /* Print disk entry */
1602 PrintDiskData (List
,
1609 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1611 PDISKENTRY DiskEntry
;
1612 PPARTENTRY PartEntry
;
1617 /* Check for empty disks */
1618 if (IsListEmpty (&List
->DiskListHead
))
1621 /* Check for first usable entry on next disk */
1622 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1623 while (Entry1
!= &List
->DiskListHead
)
1625 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1627 if (DiskEntry
->DiskNumber
== DiskNumber
)
1629 Entry2
= DiskEntry
->PartListHead
.Flink
;
1630 while (Entry2
!= &DiskEntry
->PartListHead
)
1632 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1634 for (i
= 0; i
< 4; i
++)
1636 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1638 List
->CurrentDisk
= DiskEntry
;
1639 List
->CurrentPartition
= PartEntry
;
1640 List
->CurrentPartitionNumber
= i
;
1641 DrawPartitionList (List
);
1645 Entry2
= Entry2
->Flink
;
1649 Entry1
= Entry1
->Flink
;
1656 ScrollDownPartitionList (PPARTLIST List
)
1658 PDISKENTRY DiskEntry
;
1659 PPARTENTRY PartEntry
;
1664 /* Check for empty disks */
1665 if (IsListEmpty (&List
->DiskListHead
))
1668 /* Check for next usable entry on current disk */
1669 if (List
->CurrentPartition
!= NULL
)
1671 Entry2
= &List
->CurrentPartition
->ListEntry
;
1672 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1674 /* Check if we can move inside primary partitions */
1675 for (i
= List
->CurrentPartitionNumber
+ 1; i
< 4; i
++)
1677 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1683 /* We're out of partitions in the current partition table.
1684 Try to move to the next one if possible. */
1685 Entry2
= Entry2
->Flink
;
1689 /* Just advance to the next partition */
1690 List
->CurrentPartitionNumber
= i
;
1691 DrawPartitionList (List
);
1695 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1697 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1699 // if (PartEntry->HidePartEntry == FALSE)
1701 List
->CurrentPartition
= PartEntry
;
1702 List
->CurrentPartitionNumber
= 0;
1703 DrawPartitionList (List
);
1706 Entry2
= Entry2
->Flink
;
1710 /* Check for first usable entry on next disk */
1711 if (List
->CurrentDisk
!= NULL
)
1713 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1714 while (Entry1
!= &List
->DiskListHead
)
1716 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1718 Entry2
= DiskEntry
->PartListHead
.Flink
;
1719 while (Entry2
!= &DiskEntry
->PartListHead
)
1721 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1723 // if (PartEntry->HidePartEntry == FALSE)
1725 List
->CurrentDisk
= DiskEntry
;
1726 List
->CurrentPartition
= PartEntry
;
1727 List
->CurrentPartitionNumber
= 0;
1728 DrawPartitionList (List
);
1732 Entry2
= Entry2
->Flink
;
1735 Entry1
= Entry1
->Flink
;
1742 ScrollUpPartitionList (PPARTLIST List
)
1744 PDISKENTRY DiskEntry
;
1745 PPARTENTRY PartEntry
;
1750 /* Check for empty disks */
1751 if (IsListEmpty (&List
->DiskListHead
))
1754 /* check for previous usable entry on current disk */
1755 if (List
->CurrentPartition
!= NULL
)
1757 Entry2
= &List
->CurrentPartition
->ListEntry
;
1758 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1760 /* Check if we can move inside primary partitions */
1761 if (List
->CurrentPartitionNumber
> 0)
1763 /* Find a previous partition */
1764 for (i
= List
->CurrentPartitionNumber
- 1; i
> 0; i
--)
1766 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1770 /* Move to it and return */
1771 List
->CurrentPartitionNumber
= i
;
1772 DrawPartitionList (List
);
1776 /* Move to the previous entry */
1777 Entry2
= Entry2
->Blink
;
1779 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1781 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1783 // if (PartEntry->HidePartEntry == FALSE)
1785 List
->CurrentPartition
= PartEntry
;
1787 /* Find last existing partition in the table */
1788 for (i
= 3; i
> 0; i
--)
1790 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1795 List
->CurrentPartitionNumber
= i
;
1797 /* Draw partition list and return */
1798 DrawPartitionList (List
);
1801 Entry2
= Entry2
->Blink
;
1806 /* check for last usable entry on previous disk */
1807 if (List
->CurrentDisk
!= NULL
)
1809 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1810 while (Entry1
!= &List
->DiskListHead
)
1812 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1814 Entry2
= DiskEntry
->PartListHead
.Blink
;
1815 while (Entry2
!= &DiskEntry
->PartListHead
)
1817 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1819 // if (PartEntry->HidePartEntry == FALSE)
1821 List
->CurrentDisk
= DiskEntry
;
1822 List
->CurrentPartition
= PartEntry
;
1824 /* Find last existing partition in the table */
1825 for (i
= 3; i
> 0; i
--)
1827 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1832 List
->CurrentPartitionNumber
= i
;
1834 /* Draw partition list and return */
1835 DrawPartitionList (List
);
1839 Entry2
= Entry2
->Blink
;
1842 Entry1
= Entry1
->Blink
;
1849 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1850 PPARTENTRY CurrentEntry
)
1852 PPARTENTRY PrevEntry
;
1855 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1858 Entry
= CurrentEntry
->ListEntry
.Blink
;
1859 while (Entry
!= &DiskEntry
->PartListHead
)
1861 PrevEntry
= CONTAINING_RECORD (Entry
,
1864 if (PrevEntry
->Unpartitioned
== FALSE
)
1867 Entry
= Entry
->Blink
;
1875 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1876 PPARTENTRY CurrentEntry
)
1878 PPARTENTRY NextEntry
;
1881 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1884 Entry
= CurrentEntry
->ListEntry
.Flink
;
1885 while (Entry
!= &DiskEntry
->PartListHead
)
1887 NextEntry
= CONTAINING_RECORD (Entry
,
1890 if (NextEntry
->Unpartitioned
== FALSE
)
1893 Entry
= Entry
->Flink
;
1901 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1902 PPARTENTRY PartEntry
)
1904 PPARTENTRY PrevPartEntry
;
1906 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1908 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1911 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1912 return PrevPartEntry
;
1920 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1921 PPARTENTRY PartEntry
)
1923 PPARTENTRY NextPartEntry
;
1925 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1927 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1930 if (NextPartEntry
->Unpartitioned
== TRUE
)
1931 return NextPartEntry
;
1939 CreateNewPartition (PPARTLIST List
,
1940 ULONGLONG PartitionSize
,
1943 PDISKENTRY DiskEntry
;
1944 PPARTENTRY PartEntry
;
1945 PPARTENTRY PrevPartEntry
;
1946 PPARTENTRY NextPartEntry
;
1947 PPARTENTRY NewPartEntry
;
1950 List
->CurrentDisk
== NULL
||
1951 List
->CurrentPartition
== NULL
||
1952 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1957 DiskEntry
= List
->CurrentDisk
;
1958 PartEntry
= List
->CurrentPartition
;
1960 if (AutoCreate
== TRUE
||
1961 PartitionSize
== PartEntry
->UnpartitionedLength
)
1963 /* Convert current entry to 'new (unformatted)' */
1964 PartEntry
->FormatState
= Unformatted
;
1965 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1966 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1967 PartEntry
->PartInfo
[0].HiddenSectors
=
1968 (ULONG
)(PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
1969 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1970 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1971 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1972 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1973 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1974 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1975 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1976 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1978 /* Get previous and next partition entries */
1979 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1981 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1984 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1986 /* Current entry is in the middle of the list */
1988 /* Copy previous container partition data to current entry */
1989 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1990 &PrevPartEntry
->PartInfo
[1],
1991 sizeof(PARTITION_INFORMATION
));
1992 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1994 /* Update previous container partition data */
1996 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1997 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1998 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
1999 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2001 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2003 /* Special case - previous partition is first partition */
2004 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2005 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2009 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2010 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2013 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2015 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2017 /* Current entry is the first entry */
2020 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2022 /* Current entry is the last entry */
2024 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2025 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2026 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2027 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2029 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2031 /* Special case - previous partition is first partition */
2032 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2033 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2037 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2038 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2041 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2042 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2043 (1024LL * 255LL * 63LL * 512LL))
2045 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2049 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2052 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2053 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2056 PartEntry
->AutoCreate
= AutoCreate
;
2057 PartEntry
->New
= TRUE
;
2058 PartEntry
->Unpartitioned
= FALSE
;
2059 PartEntry
->UnpartitionedOffset
= 0ULL;
2060 PartEntry
->UnpartitionedLength
= 0ULL;
2064 /* Insert an initialize a new partition entry */
2065 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
2068 if (NewPartEntry
== NULL
)
2071 RtlZeroMemory (NewPartEntry
,
2074 /* Insert the new entry into the list */
2075 InsertTailList (&PartEntry
->ListEntry
,
2076 &NewPartEntry
->ListEntry
);
2078 NewPartEntry
->New
= TRUE
;
2080 NewPartEntry
->FormatState
= Unformatted
;
2081 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
2082 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
2083 NewPartEntry
->PartInfo
[0].HiddenSectors
=
2084 (ULONG
)(NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2085 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
2086 PartitionSize
- DiskEntry
->TrackSize
;
2087 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
2088 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
2089 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2090 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2091 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
2092 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
2094 /* Get previous and next partition entries */
2095 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2097 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2100 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2102 /* Current entry is in the middle of the list */
2104 /* Copy previous container partition data to current entry */
2105 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
2106 &PrevPartEntry
->PartInfo
[1],
2107 sizeof(PARTITION_INFORMATION
));
2108 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2110 /* Update previous container partition data */
2112 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2113 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2114 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2115 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2117 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2119 /* Special case - previous partition is first partition */
2120 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2121 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2125 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2126 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2129 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2131 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2133 /* Current entry is the first entry */
2136 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2138 /* Current entry is the last entry */
2140 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2141 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2142 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2143 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2145 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2147 /* Special case - previous partition is first partition */
2148 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2149 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2153 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2154 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2157 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2158 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2159 (1024LL * 255LL * 63LL * 512LL))
2161 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2165 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2168 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2169 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2172 /* Update offset and size of the remaining unpartitioned disk space */
2173 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
2174 PartEntry
->UnpartitionedLength
-= PartitionSize
;
2177 DiskEntry
->Modified
= TRUE
;
2179 UpdatePartitionNumbers (DiskEntry
);
2181 AssignDriverLetters (List
);
2186 DeleteCurrentPartition (PPARTLIST List
)
2188 PDISKENTRY DiskEntry
;
2189 PPARTENTRY PartEntry
;
2190 PPARTENTRY PrevPartEntry
;
2191 PPARTENTRY NextPartEntry
;
2194 List
->CurrentDisk
== NULL
||
2195 List
->CurrentPartition
== NULL
||
2196 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2201 DiskEntry
= List
->CurrentDisk
;
2202 PartEntry
= List
->CurrentPartition
;
2204 /* Adjust container partition entries */
2206 /* Get previous and next partition entries */
2207 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2209 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2212 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2214 /* Current entry is in the middle of the list */
2217 * The first extended partition can not be deleted
2218 * as long as other extended partitions are present.
2220 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2223 /* Copy previous container partition data to current entry */
2224 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
2225 &PartEntry
->PartInfo
[1],
2226 sizeof(PARTITION_INFORMATION
));
2227 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2229 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2232 * A primary partition can not be deleted as long as
2233 * extended partitions are present.
2237 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2239 /* Current entry is the last entry */
2240 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
2241 sizeof(PARTITION_INFORMATION
));
2242 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2246 /* Adjust unpartitioned disk space entries */
2248 /* Get pointer to previous and next unpartitioned entries */
2249 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
2252 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
2255 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2257 /* Merge previous, current and next unpartitioned entry */
2259 /* Adjust the previous entries length */
2260 PrevPartEntry
->UnpartitionedLength
+=
2261 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2262 NextPartEntry
->UnpartitionedLength
);
2264 /* Remove the current entry */
2265 RemoveEntryList (&PartEntry
->ListEntry
);
2266 RtlFreeHeap (ProcessHeap
,
2270 /* Remove the next entry */
2271 RemoveEntryList (&NextPartEntry
->ListEntry
);
2272 RtlFreeHeap (ProcessHeap
,
2276 /* Update current partition */
2277 List
->CurrentPartition
= PrevPartEntry
;
2279 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2281 /* Merge current and previous unpartitioned entry */
2283 /* Adjust the previous entries length */
2284 PrevPartEntry
->UnpartitionedLength
+=
2285 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2287 /* Remove the current entry */
2288 RemoveEntryList (&PartEntry
->ListEntry
);
2289 RtlFreeHeap (ProcessHeap
,
2293 /* Update current partition */
2294 List
->CurrentPartition
= PrevPartEntry
;
2296 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2298 /* Merge current and next unpartitioned entry */
2300 /* Adjust the next entries offset and length */
2301 NextPartEntry
->UnpartitionedOffset
=
2302 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2303 NextPartEntry
->UnpartitionedLength
+=
2304 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2306 /* Remove the current entry */
2307 RemoveEntryList (&PartEntry
->ListEntry
);
2308 RtlFreeHeap (ProcessHeap
,
2312 /* Update current partition */
2313 List
->CurrentPartition
= NextPartEntry
;
2317 /* Nothing to merge but change current entry */
2318 PartEntry
->New
= FALSE
;
2319 PartEntry
->Unpartitioned
= TRUE
;
2320 PartEntry
->UnpartitionedOffset
=
2321 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2322 PartEntry
->UnpartitionedLength
=
2323 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2325 /* Wipe the partition table */
2326 RtlZeroMemory (&PartEntry
->PartInfo
,
2327 sizeof(PartEntry
->PartInfo
));
2330 DiskEntry
->Modified
= TRUE
;
2332 UpdatePartitionNumbers (DiskEntry
);
2334 AssignDriverLetters (List
);
2339 CheckActiveBootPartition (PPARTLIST List
)
2341 PDISKENTRY DiskEntry
;
2342 PPARTENTRY PartEntry
;
2343 PLIST_ENTRY ListEntry
;
2346 /* Check for empty disk list */
2347 if (IsListEmpty (&List
->DiskListHead
))
2349 List
->ActiveBootDisk
= NULL
;
2350 List
->ActiveBootPartition
= NULL
;
2351 List
->ActiveBootPartitionNumber
= 0;
2356 if (List
->ActiveBootDisk
!= NULL
&&
2357 List
->ActiveBootPartition
!= NULL
)
2359 /* We already have an active boot partition */
2364 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
2368 /* Check for empty partition list */
2369 if (IsListEmpty (&DiskEntry
->PartListHead
))
2371 List
->ActiveBootDisk
= NULL
;
2372 List
->ActiveBootPartition
= NULL
;
2373 List
->ActiveBootPartitionNumber
= 0;
2377 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
2381 /* Set active boot partition */
2382 if ((DiskEntry
->NewDisk
== TRUE
) ||
2383 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2384 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2385 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2386 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2388 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2389 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2390 DiskEntry
->Modified
= TRUE
;
2392 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2393 List
->ActiveBootDisk
= DiskEntry
;
2394 List
->ActiveBootPartition
= PartEntry
;
2395 List
->ActiveBootPartitionNumber
= 0;
2400 /* Disk is not new, scan all partitions to find a bootable one */
2401 List
->ActiveBootDisk
= NULL
;
2402 List
->ActiveBootPartition
= NULL
;
2403 List
->ActiveBootPartitionNumber
= 0;
2405 ListEntry
= DiskEntry
->PartListHead
.Flink
;
2406 while (ListEntry
!= &DiskEntry
->PartListHead
)
2408 PartEntry
= CONTAINING_RECORD(ListEntry
,
2412 /* Check if it's partitioned */
2413 if (!PartEntry
->Unpartitioned
)
2415 /* Go through all of its 4 partitions */
2418 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2419 PartEntry
->PartInfo
[i
].BootIndicator
)
2421 /* Yes, we found it */
2422 List
->ActiveBootDisk
= DiskEntry
;
2423 List
->ActiveBootPartition
= PartEntry
;
2424 List
->ActiveBootPartitionNumber
= i
;
2426 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2427 DiskEntry
->BiosDiskNumber
, PartEntry
->DriveLetter
[i
]);
2433 /* Go to the next one */
2434 ListEntry
= ListEntry
->Flink
;
2440 CheckForLinuxFdiskPartitions (PPARTLIST List
)
2442 PDISKENTRY DiskEntry
;
2443 PPARTENTRY PartEntry
;
2446 ULONG PartitionCount
;
2449 Entry1
= List
->DiskListHead
.Flink
;
2450 while (Entry1
!= &List
->DiskListHead
)
2452 DiskEntry
= CONTAINING_RECORD (Entry1
,
2456 Entry2
= DiskEntry
->PartListHead
.Flink
;
2457 while (Entry2
!= &DiskEntry
->PartListHead
)
2459 PartEntry
= CONTAINING_RECORD (Entry2
,
2463 if (PartEntry
->Unpartitioned
== FALSE
)
2467 for (i
= 0; i
< 4; i
++)
2469 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
2470 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2476 if (PartitionCount
> 1)
2482 Entry2
= Entry2
->Flink
;
2485 Entry1
= Entry1
->Flink
;
2493 WritePartitionsToDisk (PPARTLIST List
)
2495 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2496 OBJECT_ATTRIBUTES ObjectAttributes
;
2497 IO_STATUS_BLOCK Iosb
;
2498 WCHAR DstPath
[MAX_PATH
];
2499 UNICODE_STRING Name
;
2501 PDISKENTRY DiskEntry1
;
2502 PDISKENTRY DiskEntry2
;
2503 PPARTENTRY PartEntry
;
2506 ULONG PartitionCount
;
2507 ULONG DriveLayoutSize
;
2516 Entry1
= List
->DiskListHead
.Flink
;
2517 while (Entry1
!= &List
->DiskListHead
)
2519 DiskEntry1
= CONTAINING_RECORD (Entry1
,
2523 if (DiskEntry1
->Modified
== TRUE
)
2525 /* Count partitioned entries */
2527 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2528 while (Entry2
!= &DiskEntry1
->PartListHead
)
2530 PartEntry
= CONTAINING_RECORD (Entry2
,
2533 if (PartEntry
->Unpartitioned
== FALSE
)
2535 PartitionCount
+= 4;
2538 Entry2
= Entry2
->Flink
;
2540 if (PartitionCount
== 0)
2542 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2543 ((4 - 1) * sizeof (PARTITION_INFORMATION
));
2547 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2548 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2550 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
2553 if (DriveLayout
== NULL
)
2555 DPRINT1 ("RtlAllocateHeap() failed\n");
2559 RtlZeroMemory (DriveLayout
,
2562 if (PartitionCount
== 0)
2564 /* delete all partitions in the mbr */
2565 DriveLayout
->PartitionCount
= 4;
2566 for (Index
= 0; Index
< 4; Index
++)
2568 DriveLayout
->PartitionEntry
[Index
].RewritePartition
= TRUE
;
2573 DriveLayout
->PartitionCount
= PartitionCount
;
2576 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2577 while (Entry2
!= &DiskEntry1
->PartListHead
)
2579 PartEntry
= CONTAINING_RECORD (Entry2
,
2582 if (PartEntry
->Unpartitioned
== FALSE
)
2584 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2585 &PartEntry
->PartInfo
[0],
2586 4 * sizeof (PARTITION_INFORMATION
));
2590 Entry2
= Entry2
->Flink
;
2593 if (DiskEntry1
->Signature
== 0)
2595 LARGE_INTEGER SystemTime
;
2596 TIME_FIELDS TimeFields
;
2598 Buffer
= (PUCHAR
)&DiskEntry1
->Signature
;
2602 NtQuerySystemTime (&SystemTime
);
2603 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
2605 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
2606 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
2607 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
2608 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
2610 if (DiskEntry1
->Signature
== 0)
2615 /* check if the signature already exist */
2617 * Check also signatures from disks, which are
2618 * not visible (bootable) by the bios.
2620 Entry2
= List
->DiskListHead
.Flink
;
2621 while (Entry2
!= &List
->DiskListHead
)
2623 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
2624 if (DiskEntry1
!= DiskEntry2
&&
2625 DiskEntry1
->Signature
== DiskEntry2
->Signature
)
2629 Entry2
= Entry2
->Flink
;
2631 if (Entry2
== &List
->DiskListHead
)
2637 /* set one partition entry to dirty, this will update the signature */
2638 DriveLayout
->PartitionEntry
[0].RewritePartition
= TRUE
;
2642 DriveLayout
->Signature
= DiskEntry1
->Signature
;
2646 L
"\\Device\\Harddisk%d\\Partition0",
2647 DiskEntry1
->DiskNumber
);
2648 RtlInitUnicodeString (&Name
,
2650 InitializeObjectAttributes (&ObjectAttributes
,
2656 Status
= NtOpenFile (&FileHandle
,
2661 FILE_SYNCHRONOUS_IO_NONALERT
);
2663 if (!NT_SUCCESS (Status
))
2665 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2669 Status
= NtDeviceIoControlFile (FileHandle
,
2674 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2679 if (!NT_SUCCESS (Status
))
2681 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2682 NtClose (FileHandle
);
2686 RtlFreeHeap (ProcessHeap
,
2690 NtClose (FileHandle
);
2693 Entry1
= Entry1
->Flink
;
2699 BOOL
SetMountedDeviceValues(PPARTLIST List
)
2701 PLIST_ENTRY Entry1
, Entry2
;
2702 PDISKENTRY DiskEntry
;
2703 PPARTENTRY PartEntry
;
2711 Entry1
= List
->DiskListHead
.Flink
;
2712 while (Entry1
!= &List
->DiskListHead
)
2714 DiskEntry
= CONTAINING_RECORD (Entry1
,
2718 Entry2
= DiskEntry
->PartListHead
.Flink
;
2719 while (Entry2
!= &DiskEntry
->PartListHead
)
2721 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2722 if (!PartEntry
->Unpartitioned
)
2726 if (PartEntry
->DriveLetter
[i
])
2728 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
[i
], DiskEntry
->Signature
, PartEntry
->PartInfo
[i
].StartingOffset
))
2735 Entry2
= Entry2
->Flink
;
2737 Entry1
= Entry1
->Flink
;