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
;
1285 CHAR LineBuffer
[128];
1290 ULARGE_INTEGER DiskSize
;
1294 Width
= List
->Right
- List
->Left
- 1;
1295 Height
= List
->Bottom
- List
->Top
- 2;
1298 coPos
.X
= List
->Left
+ 1;
1299 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1302 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1304 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1305 Unit
= MUIGetString(STRING_GB
);
1310 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1311 if (DiskSize
.QuadPart
== 0)
1312 DiskSize
.QuadPart
= 1;
1313 Unit
= MUIGetString(STRING_MB
);
1316 if (DiskEntry
->DriverName
.Length
> 0)
1318 sprintf (LineBuffer
,
1319 MUIGetString(STRING_HDINFOPARTSELECT
),
1322 DiskEntry
->DiskNumber
,
1326 DiskEntry
->DriverName
.Buffer
);
1330 sprintf (LineBuffer
,
1331 MUIGetString(STRING_HDDINFOUNK6
),
1334 DiskEntry
->DiskNumber
,
1339 if (List
->Line
>= 0 && List
->Line
<= Height
)
1341 FillConsoleOutputAttribute (StdOutput
,
1342 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1347 FillConsoleOutputCharacterA (StdOutput
,
1355 if (List
->Line
>= 0 && List
->Line
<= Height
)
1357 WriteConsoleOutputCharacterA (StdOutput
,
1359 min ((USHORT
)strlen (LineBuffer
), Width
- 2),
1365 /* Print separator line */
1366 PrintEmptyLine (List
);
1368 /* Print partition lines*/
1369 Entry
= DiskEntry
->PartListHead
.Flink
;
1370 while (Entry
!= &DiskEntry
->PartListHead
)
1372 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1374 /* Print disk entry */
1377 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
1378 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
1380 PrintPartitionData (List
,
1387 /* Print unpartitioned entry */
1388 if (PartEntry
->Unpartitioned
)
1390 PrintPartitionData (List
,
1396 Entry
= Entry
->Flink
;
1399 /* Print separator line */
1400 PrintEmptyLine (List
);
1405 DrawPartitionList (PPARTLIST List
)
1407 PLIST_ENTRY Entry
, Entry2
;
1408 PDISKENTRY DiskEntry
;
1409 PPARTENTRY PartEntry
= NULL
;
1413 SHORT CurrentDiskLine
;
1414 SHORT CurrentPartLine
;
1416 BOOL CurrentPartLineFound
= FALSE
;
1417 BOOL CurrentDiskLineFound
= FALSE
;
1419 /* Calculate the line of the current disk and partition */
1420 CurrentDiskLine
= 0;
1421 CurrentPartLine
= 0;
1423 Entry
= List
->DiskListHead
.Flink
;
1424 while (Entry
!= &List
->DiskListHead
)
1426 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1428 if (CurrentPartLineFound
== FALSE
)
1430 CurrentPartLine
+= 2;
1432 Entry2
= DiskEntry
->PartListHead
.Flink
;
1433 while (Entry2
!= &DiskEntry
->PartListHead
)
1435 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1436 if (PartEntry
== List
->CurrentPartition
)
1438 CurrentPartLineFound
= TRUE
;
1440 Entry2
= Entry2
->Flink
;
1441 if (CurrentPartLineFound
== FALSE
)
1447 if (DiskEntry
== List
->CurrentDisk
)
1449 CurrentDiskLineFound
= TRUE
;
1451 Entry
= Entry
->Flink
;
1452 if (Entry
!= &List
->DiskListHead
)
1454 if (CurrentDiskLineFound
== FALSE
)
1457 CurrentDiskLine
= CurrentPartLine
;
1467 /* If it possible, make the disk name visible */
1468 if (CurrentPartLine
< List
->Offset
)
1470 List
->Offset
= CurrentPartLine
;
1472 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1474 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1476 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1478 List
->Offset
= CurrentDiskLine
;
1482 /* draw upper left corner */
1483 coPos
.X
= List
->Left
;
1484 coPos
.Y
= List
->Top
;
1485 FillConsoleOutputCharacterA (StdOutput
,
1491 /* draw upper edge */
1492 coPos
.X
= List
->Left
+ 1;
1493 coPos
.Y
= List
->Top
;
1494 if (List
->Offset
== 0)
1496 FillConsoleOutputCharacterA (StdOutput
,
1498 List
->Right
- List
->Left
- 1,
1504 FillConsoleOutputCharacterA (StdOutput
,
1506 List
->Right
- List
->Left
- 5,
1509 coPos
.X
= List
->Right
- 5;
1510 WriteConsoleOutputCharacterA (StdOutput
,
1515 coPos
.X
= List
->Right
- 2;
1516 FillConsoleOutputCharacterA (StdOutput
,
1523 /* draw upper right corner */
1524 coPos
.X
= List
->Right
;
1525 coPos
.Y
= List
->Top
;
1526 FillConsoleOutputCharacterA (StdOutput
,
1532 /* draw left and right edge */
1533 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1535 coPos
.X
= List
->Left
;
1537 FillConsoleOutputCharacterA (StdOutput
,
1543 coPos
.X
= List
->Right
;
1544 FillConsoleOutputCharacterA (StdOutput
,
1551 /* draw lower left corner */
1552 coPos
.X
= List
->Left
;
1553 coPos
.Y
= List
->Bottom
;
1554 FillConsoleOutputCharacterA (StdOutput
,
1560 /* draw lower edge */
1561 coPos
.X
= List
->Left
+ 1;
1562 coPos
.Y
= List
->Bottom
;
1563 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1565 FillConsoleOutputCharacterA (StdOutput
,
1567 List
->Right
- List
->Left
- 1,
1573 FillConsoleOutputCharacterA (StdOutput
,
1575 List
->Right
- List
->Left
- 5,
1578 coPos
.X
= List
->Right
- 5;
1579 WriteConsoleOutputCharacterA (StdOutput
,
1580 "(\x19)", // "(down)"
1584 coPos
.X
= List
->Right
- 2;
1585 FillConsoleOutputCharacterA (StdOutput
,
1592 /* draw lower right corner */
1593 coPos
.X
= List
->Right
;
1594 coPos
.Y
= List
->Bottom
;
1595 FillConsoleOutputCharacterA (StdOutput
,
1601 /* print list entries */
1602 List
->Line
= - List
->Offset
;
1604 Entry
= List
->DiskListHead
.Flink
;
1605 while (Entry
!= &List
->DiskListHead
)
1607 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1609 /* Print disk entry */
1610 PrintDiskData (List
,
1613 Entry
= Entry
->Flink
;
1619 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1621 PDISKENTRY DiskEntry
;
1622 PPARTENTRY PartEntry
;
1627 /* Check for empty disks */
1628 if (IsListEmpty (&List
->DiskListHead
))
1631 /* Check for first usable entry on next disk */
1632 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1633 while (Entry1
!= &List
->DiskListHead
)
1635 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1637 if (DiskEntry
->DiskNumber
== DiskNumber
)
1639 Entry2
= DiskEntry
->PartListHead
.Flink
;
1640 while (Entry2
!= &DiskEntry
->PartListHead
)
1642 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1644 for (i
= 0; i
< 4; i
++)
1646 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1648 List
->CurrentDisk
= DiskEntry
;
1649 List
->CurrentPartition
= PartEntry
;
1650 List
->CurrentPartitionNumber
= i
;
1651 DrawPartitionList (List
);
1655 Entry2
= Entry2
->Flink
;
1659 Entry1
= Entry1
->Flink
;
1666 ScrollDownPartitionList (PPARTLIST List
)
1668 PDISKENTRY DiskEntry
;
1669 PPARTENTRY PartEntry
;
1674 /* Check for empty disks */
1675 if (IsListEmpty (&List
->DiskListHead
))
1678 /* Check for next usable entry on current disk */
1679 if (List
->CurrentPartition
!= NULL
)
1681 Entry2
= &List
->CurrentPartition
->ListEntry
;
1682 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1684 /* Check if we can move inside primary partitions */
1685 for (i
= List
->CurrentPartitionNumber
+ 1; i
< 4; i
++)
1687 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1693 /* We're out of partitions in the current partition table.
1694 Try to move to the next one if possible. */
1695 Entry2
= Entry2
->Flink
;
1699 /* Just advance to the next partition */
1700 List
->CurrentPartitionNumber
= i
;
1701 DrawPartitionList (List
);
1705 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1707 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1709 // if (PartEntry->HidePartEntry == FALSE)
1711 List
->CurrentPartition
= PartEntry
;
1712 List
->CurrentPartitionNumber
= 0;
1713 DrawPartitionList (List
);
1716 Entry2
= Entry2
->Flink
;
1720 /* Check for first usable entry on next disk */
1721 if (List
->CurrentDisk
!= NULL
)
1723 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1724 while (Entry1
!= &List
->DiskListHead
)
1726 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1728 Entry2
= DiskEntry
->PartListHead
.Flink
;
1729 while (Entry2
!= &DiskEntry
->PartListHead
)
1731 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1733 // if (PartEntry->HidePartEntry == FALSE)
1735 List
->CurrentDisk
= DiskEntry
;
1736 List
->CurrentPartition
= PartEntry
;
1737 List
->CurrentPartitionNumber
= 0;
1738 DrawPartitionList (List
);
1742 Entry2
= Entry2
->Flink
;
1745 Entry1
= Entry1
->Flink
;
1752 ScrollUpPartitionList (PPARTLIST List
)
1754 PDISKENTRY DiskEntry
;
1755 PPARTENTRY PartEntry
;
1760 /* Check for empty disks */
1761 if (IsListEmpty (&List
->DiskListHead
))
1764 /* check for previous usable entry on current disk */
1765 if (List
->CurrentPartition
!= NULL
)
1767 Entry2
= &List
->CurrentPartition
->ListEntry
;
1768 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1770 /* Check if we can move inside primary partitions */
1771 if (List
->CurrentPartitionNumber
> 0)
1773 /* Find a previous partition */
1774 for (i
= List
->CurrentPartitionNumber
- 1; i
> 0; i
--)
1776 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1780 /* Move to it and return */
1781 List
->CurrentPartitionNumber
= i
;
1782 DrawPartitionList (List
);
1786 /* Move to the previous entry */
1787 Entry2
= Entry2
->Blink
;
1789 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1791 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1793 // if (PartEntry->HidePartEntry == FALSE)
1795 List
->CurrentPartition
= PartEntry
;
1797 /* Find last existing partition in the table */
1798 for (i
= 3; i
> 0; i
--)
1800 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1805 List
->CurrentPartitionNumber
= i
;
1807 /* Draw partition list and return */
1808 DrawPartitionList (List
);
1811 Entry2
= Entry2
->Blink
;
1816 /* check for last usable entry on previous disk */
1817 if (List
->CurrentDisk
!= NULL
)
1819 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1820 while (Entry1
!= &List
->DiskListHead
)
1822 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1824 Entry2
= DiskEntry
->PartListHead
.Blink
;
1825 while (Entry2
!= &DiskEntry
->PartListHead
)
1827 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1829 // if (PartEntry->HidePartEntry == FALSE)
1831 List
->CurrentDisk
= DiskEntry
;
1832 List
->CurrentPartition
= PartEntry
;
1834 /* Find last existing partition in the table */
1835 for (i
= 3; i
> 0; i
--)
1837 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1842 List
->CurrentPartitionNumber
= i
;
1844 /* Draw partition list and return */
1845 DrawPartitionList (List
);
1849 Entry2
= Entry2
->Blink
;
1852 Entry1
= Entry1
->Blink
;
1859 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1860 PPARTENTRY CurrentEntry
)
1862 PPARTENTRY PrevEntry
;
1865 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1868 Entry
= CurrentEntry
->ListEntry
.Blink
;
1869 while (Entry
!= &DiskEntry
->PartListHead
)
1871 PrevEntry
= CONTAINING_RECORD (Entry
,
1874 if (PrevEntry
->Unpartitioned
== FALSE
)
1877 Entry
= Entry
->Blink
;
1885 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1886 PPARTENTRY CurrentEntry
)
1888 PPARTENTRY NextEntry
;
1891 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1894 Entry
= CurrentEntry
->ListEntry
.Flink
;
1895 while (Entry
!= &DiskEntry
->PartListHead
)
1897 NextEntry
= CONTAINING_RECORD (Entry
,
1900 if (NextEntry
->Unpartitioned
== FALSE
)
1903 Entry
= Entry
->Flink
;
1911 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1912 PPARTENTRY PartEntry
)
1914 PPARTENTRY PrevPartEntry
;
1916 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1918 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1921 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1922 return PrevPartEntry
;
1930 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1931 PPARTENTRY PartEntry
)
1933 PPARTENTRY NextPartEntry
;
1935 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1937 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1940 if (NextPartEntry
->Unpartitioned
== TRUE
)
1941 return NextPartEntry
;
1949 CreateNewPartition (PPARTLIST List
,
1950 ULONGLONG PartitionSize
,
1953 PDISKENTRY DiskEntry
;
1954 PPARTENTRY PartEntry
;
1955 PPARTENTRY PrevPartEntry
;
1956 PPARTENTRY NextPartEntry
;
1957 PPARTENTRY NewPartEntry
;
1960 List
->CurrentDisk
== NULL
||
1961 List
->CurrentPartition
== NULL
||
1962 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1967 DiskEntry
= List
->CurrentDisk
;
1968 PartEntry
= List
->CurrentPartition
;
1970 if (AutoCreate
== TRUE
||
1971 PartitionSize
== PartEntry
->UnpartitionedLength
)
1973 /* Convert current entry to 'new (unformatted)' */
1974 PartEntry
->FormatState
= Unformatted
;
1975 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1976 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1977 PartEntry
->PartInfo
[0].HiddenSectors
=
1978 (ULONG
)(PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
1979 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1980 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1981 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1982 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1983 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1984 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1985 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1986 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1988 /* Get previous and next partition entries */
1989 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1991 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1994 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1996 /* Current entry is in the middle of the list */
1998 /* Copy previous container partition data to current entry */
1999 RtlCopyMemory (&PartEntry
->PartInfo
[1],
2000 &PrevPartEntry
->PartInfo
[1],
2001 sizeof(PARTITION_INFORMATION
));
2002 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2004 /* Update previous container partition data */
2006 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2007 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2008 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2009 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2011 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2013 /* Special case - previous partition is first partition */
2014 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2015 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2019 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2020 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2023 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2025 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2027 /* Current entry is the first entry */
2030 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2032 /* Current entry is the last entry */
2034 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2035 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2036 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2037 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2039 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2041 /* Special case - previous partition is first partition */
2042 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2043 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2047 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2048 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2051 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2052 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2053 (1024LL * 255LL * 63LL * 512LL))
2055 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2059 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2062 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2063 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2066 PartEntry
->AutoCreate
= AutoCreate
;
2067 PartEntry
->New
= TRUE
;
2068 PartEntry
->Unpartitioned
= FALSE
;
2069 PartEntry
->UnpartitionedOffset
= 0ULL;
2070 PartEntry
->UnpartitionedLength
= 0ULL;
2074 /* Insert an initialize a new partition entry */
2075 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
2078 if (NewPartEntry
== NULL
)
2081 RtlZeroMemory (NewPartEntry
,
2084 /* Insert the new entry into the list */
2085 InsertTailList (&PartEntry
->ListEntry
,
2086 &NewPartEntry
->ListEntry
);
2088 NewPartEntry
->New
= TRUE
;
2090 NewPartEntry
->FormatState
= Unformatted
;
2091 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
2092 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
2093 NewPartEntry
->PartInfo
[0].HiddenSectors
=
2094 (ULONG
)(NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2095 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
2096 PartitionSize
- DiskEntry
->TrackSize
;
2097 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
2098 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
2099 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2100 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2101 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
2102 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
2104 /* Get previous and next partition entries */
2105 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2107 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2110 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2112 /* Current entry is in the middle of the list */
2114 /* Copy previous container partition data to current entry */
2115 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
2116 &PrevPartEntry
->PartInfo
[1],
2117 sizeof(PARTITION_INFORMATION
));
2118 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2120 /* Update previous container partition data */
2122 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2123 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2124 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2125 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2127 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2129 /* Special case - previous partition is first partition */
2130 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2131 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2135 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2136 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2139 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2141 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2143 /* Current entry is the first entry */
2146 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2148 /* Current entry is the last entry */
2150 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2151 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2152 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2153 (ULONG
)(PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
);
2155 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2157 /* Special case - previous partition is first partition */
2158 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2159 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2163 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2164 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2167 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2168 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2169 (1024LL * 255LL * 63LL * 512LL))
2171 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2175 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2178 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2179 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2182 /* Update offset and size of the remaining unpartitioned disk space */
2183 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
2184 PartEntry
->UnpartitionedLength
-= PartitionSize
;
2187 DiskEntry
->Modified
= TRUE
;
2189 UpdatePartitionNumbers (DiskEntry
);
2191 AssignDriverLetters (List
);
2196 DeleteCurrentPartition (PPARTLIST List
)
2198 PDISKENTRY DiskEntry
;
2199 PPARTENTRY PartEntry
;
2200 PPARTENTRY PrevPartEntry
;
2201 PPARTENTRY NextPartEntry
;
2204 List
->CurrentDisk
== NULL
||
2205 List
->CurrentPartition
== NULL
||
2206 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2211 DiskEntry
= List
->CurrentDisk
;
2212 PartEntry
= List
->CurrentPartition
;
2214 /* Adjust container partition entries */
2216 /* Get previous and next partition entries */
2217 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2219 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2222 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2224 /* Current entry is in the middle of the list */
2227 * The first extended partition can not be deleted
2228 * as long as other extended partitions are present.
2230 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2233 /* Copy previous container partition data to current entry */
2234 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
2235 &PartEntry
->PartInfo
[1],
2236 sizeof(PARTITION_INFORMATION
));
2237 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2239 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2242 * A primary partition can not be deleted as long as
2243 * extended partitions are present.
2247 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2249 /* Current entry is the last entry */
2250 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
2251 sizeof(PARTITION_INFORMATION
));
2252 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2256 /* Adjust unpartitioned disk space entries */
2258 /* Get pointer to previous and next unpartitioned entries */
2259 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
2262 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
2265 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2267 /* Merge previous, current and next unpartitioned entry */
2269 /* Adjust the previous entries length */
2270 PrevPartEntry
->UnpartitionedLength
+=
2271 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2272 NextPartEntry
->UnpartitionedLength
);
2274 /* Remove the current entry */
2275 RemoveEntryList (&PartEntry
->ListEntry
);
2276 RtlFreeHeap (ProcessHeap
,
2280 /* Remove the next entry */
2281 RemoveEntryList (&NextPartEntry
->ListEntry
);
2282 RtlFreeHeap (ProcessHeap
,
2286 /* Update current partition */
2287 List
->CurrentPartition
= PrevPartEntry
;
2289 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2291 /* Merge current and previous unpartitioned entry */
2293 /* Adjust the previous entries length */
2294 PrevPartEntry
->UnpartitionedLength
+=
2295 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2297 /* Remove the current entry */
2298 RemoveEntryList (&PartEntry
->ListEntry
);
2299 RtlFreeHeap (ProcessHeap
,
2303 /* Update current partition */
2304 List
->CurrentPartition
= PrevPartEntry
;
2306 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2308 /* Merge current and next unpartitioned entry */
2310 /* Adjust the next entries offset and length */
2311 NextPartEntry
->UnpartitionedOffset
=
2312 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2313 NextPartEntry
->UnpartitionedLength
+=
2314 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2316 /* Remove the current entry */
2317 RemoveEntryList (&PartEntry
->ListEntry
);
2318 RtlFreeHeap (ProcessHeap
,
2322 /* Update current partition */
2323 List
->CurrentPartition
= NextPartEntry
;
2327 /* Nothing to merge but change current entry */
2328 PartEntry
->New
= FALSE
;
2329 PartEntry
->Unpartitioned
= TRUE
;
2330 PartEntry
->UnpartitionedOffset
=
2331 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2332 PartEntry
->UnpartitionedLength
=
2333 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2335 /* Wipe the partition table */
2336 RtlZeroMemory (&PartEntry
->PartInfo
,
2337 sizeof(PartEntry
->PartInfo
));
2340 DiskEntry
->Modified
= TRUE
;
2342 UpdatePartitionNumbers (DiskEntry
);
2344 AssignDriverLetters (List
);
2349 CheckActiveBootPartition (PPARTLIST List
)
2351 PDISKENTRY DiskEntry
;
2352 PPARTENTRY PartEntry
;
2353 PLIST_ENTRY ListEntry
;
2356 /* Check for empty disk list */
2357 if (IsListEmpty (&List
->DiskListHead
))
2359 List
->ActiveBootDisk
= NULL
;
2360 List
->ActiveBootPartition
= NULL
;
2361 List
->ActiveBootPartitionNumber
= 0;
2366 if (List
->ActiveBootDisk
!= NULL
&&
2367 List
->ActiveBootPartition
!= NULL
)
2369 /* We already have an active boot partition */
2374 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
2378 /* Check for empty partition list */
2379 if (IsListEmpty (&DiskEntry
->PartListHead
))
2381 List
->ActiveBootDisk
= NULL
;
2382 List
->ActiveBootPartition
= NULL
;
2383 List
->ActiveBootPartitionNumber
= 0;
2387 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
2391 /* Set active boot partition */
2392 if ((DiskEntry
->NewDisk
== TRUE
) ||
2393 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2394 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2395 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2396 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2398 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2399 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2400 DiskEntry
->Modified
= TRUE
;
2402 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2403 List
->ActiveBootDisk
= DiskEntry
;
2404 List
->ActiveBootPartition
= PartEntry
;
2405 List
->ActiveBootPartitionNumber
= 0;
2410 /* Disk is not new, scan all partitions to find a bootable one */
2411 List
->ActiveBootDisk
= NULL
;
2412 List
->ActiveBootPartition
= NULL
;
2413 List
->ActiveBootPartitionNumber
= 0;
2415 ListEntry
= DiskEntry
->PartListHead
.Flink
;
2416 while (ListEntry
!= &DiskEntry
->PartListHead
)
2418 PartEntry
= CONTAINING_RECORD(ListEntry
,
2422 /* Check if it's partitioned */
2423 if (!PartEntry
->Unpartitioned
)
2425 /* Go through all of its 4 partitions */
2428 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2429 PartEntry
->PartInfo
[i
].BootIndicator
)
2431 /* Yes, we found it */
2432 List
->ActiveBootDisk
= DiskEntry
;
2433 List
->ActiveBootPartition
= PartEntry
;
2434 List
->ActiveBootPartitionNumber
= i
;
2436 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2437 DiskEntry
->BiosDiskNumber
, PartEntry
->DriveLetter
[i
]);
2443 /* Go to the next one */
2444 ListEntry
= ListEntry
->Flink
;
2450 CheckForLinuxFdiskPartitions (PPARTLIST List
)
2452 PDISKENTRY DiskEntry
;
2453 PPARTENTRY PartEntry
;
2456 ULONG PartitionCount
;
2459 Entry1
= List
->DiskListHead
.Flink
;
2460 while (Entry1
!= &List
->DiskListHead
)
2462 DiskEntry
= CONTAINING_RECORD (Entry1
,
2466 Entry2
= DiskEntry
->PartListHead
.Flink
;
2467 while (Entry2
!= &DiskEntry
->PartListHead
)
2469 PartEntry
= CONTAINING_RECORD (Entry2
,
2473 if (PartEntry
->Unpartitioned
== FALSE
)
2477 for (i
= 0; i
< 4; i
++)
2479 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
2480 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2486 if (PartitionCount
> 1)
2492 Entry2
= Entry2
->Flink
;
2495 Entry1
= Entry1
->Flink
;
2503 WritePartitionsToDisk (PPARTLIST List
)
2505 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2506 OBJECT_ATTRIBUTES ObjectAttributes
;
2507 IO_STATUS_BLOCK Iosb
;
2508 WCHAR DstPath
[MAX_PATH
];
2509 UNICODE_STRING Name
;
2511 PDISKENTRY DiskEntry1
;
2512 PDISKENTRY DiskEntry2
;
2513 PPARTENTRY PartEntry
;
2516 ULONG PartitionCount
;
2517 ULONG DriveLayoutSize
;
2526 Entry1
= List
->DiskListHead
.Flink
;
2527 while (Entry1
!= &List
->DiskListHead
)
2529 DiskEntry1
= CONTAINING_RECORD (Entry1
,
2533 if (DiskEntry1
->Modified
== TRUE
)
2535 /* Count partitioned entries */
2537 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2538 while (Entry2
!= &DiskEntry1
->PartListHead
)
2540 PartEntry
= CONTAINING_RECORD (Entry2
,
2543 if (PartEntry
->Unpartitioned
== FALSE
)
2545 PartitionCount
+= 4;
2548 Entry2
= Entry2
->Flink
;
2550 if (PartitionCount
== 0)
2552 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2553 ((4 - 1) * sizeof (PARTITION_INFORMATION
));
2557 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2558 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2560 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
2563 if (DriveLayout
== NULL
)
2565 DPRINT1 ("RtlAllocateHeap() failed\n");
2569 RtlZeroMemory (DriveLayout
,
2572 if (PartitionCount
== 0)
2574 /* delete all partitions in the mbr */
2575 DriveLayout
->PartitionCount
= 4;
2576 for (Index
= 0; Index
< 4; Index
++)
2578 DriveLayout
->PartitionEntry
[Index
].RewritePartition
= TRUE
;
2583 DriveLayout
->PartitionCount
= PartitionCount
;
2586 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2587 while (Entry2
!= &DiskEntry1
->PartListHead
)
2589 PartEntry
= CONTAINING_RECORD (Entry2
,
2592 if (PartEntry
->Unpartitioned
== FALSE
)
2594 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2595 &PartEntry
->PartInfo
[0],
2596 4 * sizeof (PARTITION_INFORMATION
));
2600 Entry2
= Entry2
->Flink
;
2603 if (DiskEntry1
->Signature
== 0)
2605 LARGE_INTEGER SystemTime
;
2606 TIME_FIELDS TimeFields
;
2608 Buffer
= (PUCHAR
)&DiskEntry1
->Signature
;
2612 NtQuerySystemTime (&SystemTime
);
2613 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
2615 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
2616 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
2617 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
2618 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
2620 if (DiskEntry1
->Signature
== 0)
2625 /* check if the signature already exist */
2627 * Check also signatures from disks, which are
2628 * not visible (bootable) by the bios.
2630 Entry2
= List
->DiskListHead
.Flink
;
2631 while (Entry2
!= &List
->DiskListHead
)
2633 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
2634 if (DiskEntry1
!= DiskEntry2
&&
2635 DiskEntry1
->Signature
== DiskEntry2
->Signature
)
2639 Entry2
= Entry2
->Flink
;
2641 if (Entry2
== &List
->DiskListHead
)
2647 /* set one partition entry to dirty, this will update the signature */
2648 DriveLayout
->PartitionEntry
[0].RewritePartition
= TRUE
;
2652 DriveLayout
->Signature
= DiskEntry1
->Signature
;
2656 L
"\\Device\\Harddisk%d\\Partition0",
2657 DiskEntry1
->DiskNumber
);
2658 RtlInitUnicodeString (&Name
,
2660 InitializeObjectAttributes (&ObjectAttributes
,
2666 Status
= NtOpenFile (&FileHandle
,
2671 FILE_SYNCHRONOUS_IO_NONALERT
);
2673 if (!NT_SUCCESS (Status
))
2675 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2679 Status
= NtDeviceIoControlFile (FileHandle
,
2684 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2689 if (!NT_SUCCESS (Status
))
2691 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2692 NtClose (FileHandle
);
2696 RtlFreeHeap (ProcessHeap
,
2700 NtClose (FileHandle
);
2703 Entry1
= Entry1
->Flink
;
2709 BOOL
SetMountedDeviceValues(PPARTLIST List
)
2711 PLIST_ENTRY Entry1
, Entry2
;
2712 PDISKENTRY DiskEntry
;
2713 PPARTENTRY PartEntry
;
2721 Entry1
= List
->DiskListHead
.Flink
;
2722 while (Entry1
!= &List
->DiskListHead
)
2724 DiskEntry
= CONTAINING_RECORD (Entry1
,
2728 Entry2
= DiskEntry
->PartListHead
.Flink
;
2729 while (Entry2
!= &DiskEntry
->PartListHead
)
2731 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2732 if (!PartEntry
->Unpartitioned
)
2736 if (PartEntry
->DriveLetter
[i
])
2738 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
[i
], DiskEntry
->Signature
, PartEntry
->PartInfo
[i
].StartingOffset
))
2745 Entry2
= Entry2
->Flink
;
2747 Entry1
= Entry1
->Flink
;