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
;
948 List
->TopDisk
= (ULONG
)-1;
949 List
->TopPartition
= (ULONG
)-1;
951 List
->CurrentDisk
= NULL
;
952 List
->CurrentPartition
= NULL
;
953 List
->CurrentPartitionNumber
= 0;
955 InitializeListHead (&List
->DiskListHead
);
956 InitializeListHead (&List
->BiosDiskListHead
);
958 EnumerateBiosDiskEntries(List
);
960 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
962 sizeof(SYSTEM_DEVICE_INFORMATION
),
964 if (!NT_SUCCESS (Status
))
966 RtlFreeHeap (ProcessHeap
, 0, List
);
970 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
973 L
"\\Device\\Harddisk%d\\Partition0",
975 RtlInitUnicodeString (&Name
,
978 InitializeObjectAttributes (&ObjectAttributes
,
984 Status
= NtOpenFile (&FileHandle
,
985 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
989 FILE_SYNCHRONOUS_IO_NONALERT
);
990 if (NT_SUCCESS(Status
))
992 AddDiskToList (FileHandle
,
1000 AssignDriverLetters (List
);
1003 List
->TopPartition
= 0;
1005 /* Search for first usable disk and partition */
1006 if (IsListEmpty (&List
->DiskListHead
))
1008 List
->CurrentDisk
= NULL
;
1009 List
->CurrentPartition
= NULL
;
1010 List
->CurrentPartitionNumber
= 0;
1015 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
1019 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
1021 List
->CurrentPartition
= 0;
1022 List
->CurrentPartitionNumber
= 0;
1026 List
->CurrentPartition
=
1027 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
1030 List
->CurrentPartitionNumber
= 0;
1039 DestroyPartitionList (PPARTLIST List
)
1041 PDISKENTRY DiskEntry
;
1042 PBIOSDISKENTRY BiosDiskEntry
;
1043 PPARTENTRY PartEntry
;
1046 /* Release disk and partition info */
1047 while (!IsListEmpty (&List
->DiskListHead
))
1049 Entry
= RemoveHeadList (&List
->DiskListHead
);
1050 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1052 /* Release driver name */
1053 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1055 /* Release partition array */
1056 while (!IsListEmpty (&DiskEntry
->PartListHead
))
1058 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
1059 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
1061 RtlFreeHeap (ProcessHeap
,
1066 /* Release disk entry */
1067 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
1070 /* release the bios disk info */
1071 while(!IsListEmpty(&List
->BiosDiskListHead
))
1073 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1074 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1076 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1079 /* Release list head */
1080 RtlFreeHeap (ProcessHeap
, 0, List
);
1085 PrintEmptyLine (PPARTLIST List
)
1092 Width
= List
->Right
- List
->Left
- 1;
1093 Height
= List
->Bottom
- List
->Top
- 2;
1096 coPos
.X
= List
->Left
+ 1;
1097 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1099 if (List
->Line
>= 0 && List
->Line
<= Height
)
1101 FillConsoleOutputAttribute (StdOutput
,
1102 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1107 FillConsoleOutputCharacterA (StdOutput
,
1118 PrintPartitionData (PPARTLIST List
,
1119 PDISKENTRY DiskEntry
,
1120 PPARTENTRY PartEntry
,
1123 CHAR LineBuffer
[128];
1129 LARGE_INTEGER PartSize
;
1134 Width
= List
->Right
- List
->Left
- 1;
1135 Height
= List
->Bottom
- List
->Top
- 2;
1138 coPos
.X
= List
->Left
+ 1;
1139 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1141 if (PartEntry
->Unpartitioned
== TRUE
)
1144 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1146 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1147 Unit
= MUIGetString(STRING_GB
);
1151 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1153 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1154 Unit
= MUIGetString(STRING_MB
);
1158 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1159 Unit
= MUIGetString(STRING_KB
);
1162 sprintf (LineBuffer
,
1163 MUIGetString(STRING_UNPSPACE
),
1169 /* Determine partition type */
1171 if (PartEntry
->New
== TRUE
)
1173 PartType
= MUIGetString(STRING_UNFORMATTED
);
1175 else if (PartEntry
->Unpartitioned
== FALSE
)
1177 if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_12
) ||
1178 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_16
) ||
1179 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_HUGE
) ||
1180 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_XINT13
))
1184 else if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32
) ||
1185 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32_XINT13
))
1189 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_EXT2
)
1193 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_IFS
)
1195 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1200 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1202 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1203 Unit
= MUIGetString(STRING_GB
);
1207 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1209 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1210 Unit
= MUIGetString(STRING_MB
);
1214 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1215 Unit
= MUIGetString(STRING_KB
);
1218 if (PartType
== NULL
)
1220 sprintf (LineBuffer
,
1221 MUIGetString(STRING_HDDINFOUNK5
),
1222 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1223 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1224 PartEntry
->PartInfo
[PartNumber
].PartitionType
,
1230 sprintf (LineBuffer
,
1231 "%c%c %-24s %6lu %s",
1232 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : PartEntry
->DriveLetter
[PartNumber
],
1233 (PartEntry
->DriveLetter
[PartNumber
] == 0) ? '-' : ':',
1240 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1241 List
->CurrentPartition
== PartEntry
&&
1242 List
->CurrentPartitionNumber
== PartNumber
) ?
1243 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1244 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1246 if (List
->Line
>= 0 && List
->Line
<= Height
)
1248 FillConsoleOutputCharacterA (StdOutput
,
1256 if (List
->Line
>= 0 && List
->Line
<= Height
)
1258 FillConsoleOutputAttribute (StdOutput
,
1266 if (List
->Line
>= 0 && List
->Line
<= Height
)
1268 WriteConsoleOutputCharacterA (StdOutput
,
1270 min (strlen (LineBuffer
), Width
),
1279 PrintDiskData (PPARTLIST List
,
1280 PDISKENTRY DiskEntry
)
1282 PPARTENTRY PartEntry
;
1283 CHAR LineBuffer
[128];
1288 ULARGE_INTEGER DiskSize
;
1292 Width
= List
->Right
- List
->Left
- 1;
1293 Height
= List
->Bottom
- List
->Top
- 2;
1296 coPos
.X
= List
->Left
+ 1;
1297 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1300 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1302 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1303 Unit
= MUIGetString(STRING_GB
);
1308 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1309 if (DiskSize
.QuadPart
== 0)
1310 DiskSize
.QuadPart
= 1;
1311 Unit
= MUIGetString(STRING_MB
);
1314 if (DiskEntry
->DriverName
.Length
> 0)
1316 sprintf (LineBuffer
,
1317 MUIGetString(STRING_HDINFOPARTSELECT
),
1320 DiskEntry
->DiskNumber
,
1324 DiskEntry
->DriverName
.Buffer
);
1328 sprintf (LineBuffer
,
1329 MUIGetString(STRING_HDDINFOUNK6
),
1332 DiskEntry
->DiskNumber
,
1337 if (List
->Line
>= 0 && List
->Line
<= Height
)
1339 FillConsoleOutputAttribute (StdOutput
,
1340 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1345 FillConsoleOutputCharacterA (StdOutput
,
1353 if (List
->Line
>= 0 && List
->Line
<= Height
)
1355 WriteConsoleOutputCharacterA (StdOutput
,
1357 min ((USHORT
)strlen (LineBuffer
), Width
- 2),
1363 /* Print separator line */
1364 PrintEmptyLine (List
);
1366 /* Print partition lines*/
1367 LIST_FOR_EACH(PartEntry
, &DiskEntry
->PartListHead
, PARTENTRY
, ListEntry
)
1369 /* Print disk entry */
1372 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
1373 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
1375 PrintPartitionData (List
,
1382 /* Print unpartitioned entry */
1383 if (PartEntry
->Unpartitioned
)
1385 PrintPartitionData (List
,
1393 /* Print separator line */
1394 PrintEmptyLine (List
);
1399 DrawPartitionList (PPARTLIST List
)
1401 PLIST_ENTRY Entry
, Entry2
;
1402 PDISKENTRY DiskEntry
;
1403 PPARTENTRY PartEntry
= NULL
;
1407 SHORT CurrentDiskLine
;
1408 SHORT CurrentPartLine
;
1410 BOOL CurrentPartLineFound
= FALSE
;
1411 BOOL CurrentDiskLineFound
= FALSE
;
1413 /* Calculate the line of the current disk and partition */
1414 CurrentDiskLine
= 0;
1415 CurrentPartLine
= 0;
1417 Entry
= List
->DiskListHead
.Flink
;
1418 while (Entry
!= &List
->DiskListHead
)
1420 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1422 if (CurrentPartLineFound
== FALSE
)
1424 CurrentPartLine
+= 2;
1426 Entry2
= DiskEntry
->PartListHead
.Flink
;
1427 while (Entry2
!= &DiskEntry
->PartListHead
)
1429 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1430 if (PartEntry
== List
->CurrentPartition
)
1432 CurrentPartLineFound
= TRUE
;
1434 Entry2
= Entry2
->Flink
;
1435 if (CurrentPartLineFound
== FALSE
)
1441 if (DiskEntry
== List
->CurrentDisk
)
1443 CurrentDiskLineFound
= TRUE
;
1445 Entry
= Entry
->Flink
;
1446 if (Entry
!= &List
->DiskListHead
)
1448 if (CurrentDiskLineFound
== FALSE
)
1451 CurrentDiskLine
= CurrentPartLine
;
1461 /* If it possible, make the disk name visible */
1462 if (CurrentPartLine
< List
->Offset
)
1464 List
->Offset
= CurrentPartLine
;
1466 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1468 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1470 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1472 List
->Offset
= CurrentDiskLine
;
1476 /* draw upper left corner */
1477 coPos
.X
= List
->Left
;
1478 coPos
.Y
= List
->Top
;
1479 FillConsoleOutputCharacterA (StdOutput
,
1485 /* draw upper edge */
1486 coPos
.X
= List
->Left
+ 1;
1487 coPos
.Y
= List
->Top
;
1488 if (List
->Offset
== 0)
1490 FillConsoleOutputCharacterA (StdOutput
,
1492 List
->Right
- List
->Left
- 1,
1498 FillConsoleOutputCharacterA (StdOutput
,
1500 List
->Right
- List
->Left
- 5,
1503 coPos
.X
= List
->Right
- 5;
1504 WriteConsoleOutputCharacterA (StdOutput
,
1509 coPos
.X
= List
->Right
- 2;
1510 FillConsoleOutputCharacterA (StdOutput
,
1517 /* draw upper right corner */
1518 coPos
.X
= List
->Right
;
1519 coPos
.Y
= List
->Top
;
1520 FillConsoleOutputCharacterA (StdOutput
,
1526 /* draw left and right edge */
1527 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1529 coPos
.X
= List
->Left
;
1531 FillConsoleOutputCharacterA (StdOutput
,
1537 coPos
.X
= List
->Right
;
1538 FillConsoleOutputCharacterA (StdOutput
,
1545 /* draw lower left corner */
1546 coPos
.X
= List
->Left
;
1547 coPos
.Y
= List
->Bottom
;
1548 FillConsoleOutputCharacterA (StdOutput
,
1554 /* draw lower edge */
1555 coPos
.X
= List
->Left
+ 1;
1556 coPos
.Y
= List
->Bottom
;
1557 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1559 FillConsoleOutputCharacterA (StdOutput
,
1561 List
->Right
- List
->Left
- 1,
1567 FillConsoleOutputCharacterA (StdOutput
,
1569 List
->Right
- List
->Left
- 5,
1572 coPos
.X
= List
->Right
- 5;
1573 WriteConsoleOutputCharacterA (StdOutput
,
1574 "(\x19)", // "(down)"
1578 coPos
.X
= List
->Right
- 2;
1579 FillConsoleOutputCharacterA (StdOutput
,
1586 /* draw lower right corner */
1587 coPos
.X
= List
->Right
;
1588 coPos
.Y
= List
->Bottom
;
1589 FillConsoleOutputCharacterA (StdOutput
,
1595 /* print list entries */
1596 List
->Line
= - List
->Offset
;
1598 LIST_FOR_EACH(DiskEntry
, &List
->DiskListHead
, DISKENTRY
, ListEntry
)
1600 /* Print disk entry */
1601 PrintDiskData (List
,
1608 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1610 PDISKENTRY DiskEntry
;
1611 PPARTENTRY PartEntry
;
1616 /* Check for empty disks */
1617 if (IsListEmpty (&List
->DiskListHead
))
1620 /* Check for first usable entry on next disk */
1621 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1622 while (Entry1
!= &List
->DiskListHead
)
1624 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1626 if (DiskEntry
->DiskNumber
== DiskNumber
)
1628 Entry2
= DiskEntry
->PartListHead
.Flink
;
1629 while (Entry2
!= &DiskEntry
->PartListHead
)
1631 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1633 for (i
= 0; i
< 4; i
++)
1635 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1637 List
->CurrentDisk
= DiskEntry
;
1638 List
->CurrentPartition
= PartEntry
;
1639 List
->CurrentPartitionNumber
= i
;
1640 DrawPartitionList (List
);
1644 Entry2
= Entry2
->Flink
;
1648 Entry1
= Entry1
->Flink
;
1655 ScrollDownPartitionList (PPARTLIST List
)
1657 PDISKENTRY DiskEntry
;
1658 PPARTENTRY PartEntry
;
1663 /* Check for empty disks */
1664 if (IsListEmpty (&List
->DiskListHead
))
1667 /* Check for next usable entry on current disk */
1668 if (List
->CurrentPartition
!= NULL
)
1670 Entry2
= &List
->CurrentPartition
->ListEntry
;
1671 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1673 /* Check if we can move inside primary partitions */
1674 for (i
= List
->CurrentPartitionNumber
+ 1; i
< 4; i
++)
1676 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1682 /* We're out of partitions in the current partition table.
1683 Try to move to the next one if possible. */
1684 Entry2
= Entry2
->Flink
;
1688 /* Just advance to the next partition */
1689 List
->CurrentPartitionNumber
= i
;
1690 DrawPartitionList (List
);
1694 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1696 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1698 // if (PartEntry->HidePartEntry == FALSE)
1700 List
->CurrentPartition
= PartEntry
;
1701 List
->CurrentPartitionNumber
= 0;
1702 DrawPartitionList (List
);
1705 Entry2
= Entry2
->Flink
;
1709 /* Check for first usable entry on next disk */
1710 if (List
->CurrentDisk
!= NULL
)
1712 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1713 while (Entry1
!= &List
->DiskListHead
)
1715 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1717 Entry2
= DiskEntry
->PartListHead
.Flink
;
1718 while (Entry2
!= &DiskEntry
->PartListHead
)
1720 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1722 // if (PartEntry->HidePartEntry == FALSE)
1724 List
->CurrentDisk
= DiskEntry
;
1725 List
->CurrentPartition
= PartEntry
;
1726 List
->CurrentPartitionNumber
= 0;
1727 DrawPartitionList (List
);
1731 Entry2
= Entry2
->Flink
;
1734 Entry1
= Entry1
->Flink
;
1741 ScrollUpPartitionList (PPARTLIST List
)
1743 PDISKENTRY DiskEntry
;
1744 PPARTENTRY PartEntry
;
1749 /* Check for empty disks */
1750 if (IsListEmpty (&List
->DiskListHead
))
1753 /* check for previous usable entry on current disk */
1754 if (List
->CurrentPartition
!= NULL
)
1756 Entry2
= &List
->CurrentPartition
->ListEntry
;
1757 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1759 /* Check if we can move inside primary partitions */
1760 if (List
->CurrentPartitionNumber
> 0)
1762 /* Find a previous partition */
1763 for (i
= List
->CurrentPartitionNumber
- 1; i
> 0; i
--)
1765 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1769 /* Move to it and return */
1770 List
->CurrentPartitionNumber
= i
;
1771 DrawPartitionList (List
);
1775 /* Move to the previous entry */
1776 Entry2
= Entry2
->Blink
;
1778 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1780 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1782 // if (PartEntry->HidePartEntry == FALSE)
1784 List
->CurrentPartition
= PartEntry
;
1786 /* Find last existing partition in the table */
1787 for (i
= 3; i
> 0; i
--)
1789 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1794 List
->CurrentPartitionNumber
= i
;
1796 /* Draw partition list and return */
1797 DrawPartitionList (List
);
1800 Entry2
= Entry2
->Blink
;
1805 /* check for last usable entry on previous disk */
1806 if (List
->CurrentDisk
!= NULL
)
1808 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1809 while (Entry1
!= &List
->DiskListHead
)
1811 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1813 Entry2
= DiskEntry
->PartListHead
.Blink
;
1814 while (Entry2
!= &DiskEntry
->PartListHead
)
1816 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1818 // if (PartEntry->HidePartEntry == FALSE)
1820 List
->CurrentDisk
= DiskEntry
;
1821 List
->CurrentPartition
= PartEntry
;
1823 /* Find last existing partition in the table */
1824 for (i
= 3; i
> 0; i
--)
1826 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1831 List
->CurrentPartitionNumber
= i
;
1833 /* Draw partition list and return */
1834 DrawPartitionList (List
);
1838 Entry2
= Entry2
->Blink
;
1841 Entry1
= Entry1
->Blink
;
1848 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1849 PPARTENTRY CurrentEntry
)
1851 PPARTENTRY PrevEntry
;
1854 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1857 Entry
= CurrentEntry
->ListEntry
.Blink
;
1858 while (Entry
!= &DiskEntry
->PartListHead
)
1860 PrevEntry
= CONTAINING_RECORD (Entry
,
1863 if (PrevEntry
->Unpartitioned
== FALSE
)
1866 Entry
= Entry
->Blink
;
1874 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1875 PPARTENTRY CurrentEntry
)
1877 PPARTENTRY NextEntry
;
1880 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1883 Entry
= CurrentEntry
->ListEntry
.Flink
;
1884 while (Entry
!= &DiskEntry
->PartListHead
)
1886 NextEntry
= CONTAINING_RECORD (Entry
,
1889 if (NextEntry
->Unpartitioned
== FALSE
)
1892 Entry
= Entry
->Flink
;
1900 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1901 PPARTENTRY PartEntry
)
1903 PPARTENTRY PrevPartEntry
;
1905 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1907 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1910 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1911 return PrevPartEntry
;
1919 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1920 PPARTENTRY PartEntry
)
1922 PPARTENTRY NextPartEntry
;
1924 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1926 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1929 if (NextPartEntry
->Unpartitioned
== TRUE
)
1930 return NextPartEntry
;
1938 CreateNewPartition (PPARTLIST List
,
1939 ULONGLONG PartitionSize
,
1942 PDISKENTRY DiskEntry
;
1943 PPARTENTRY PartEntry
;
1944 PPARTENTRY PrevPartEntry
;
1945 PPARTENTRY NextPartEntry
;
1946 PPARTENTRY NewPartEntry
;
1949 List
->CurrentDisk
== NULL
||
1950 List
->CurrentPartition
== NULL
||
1951 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1956 DiskEntry
= List
->CurrentDisk
;
1957 PartEntry
= List
->CurrentPartition
;
1959 if (AutoCreate
== TRUE
||
1960 PartitionSize
== PartEntry
->UnpartitionedLength
)
1962 /* Convert current entry to 'new (unformatted)' */
1963 PartEntry
->FormatState
= Unformatted
;
1964 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1965 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1966 PartEntry
->PartInfo
[0].HiddenSectors
=
1967 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
1968 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1969 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1970 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1971 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1972 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1973 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1974 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1975 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1977 /* Get previous and next partition entries */
1978 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1980 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1983 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1985 /* Current entry is in the middle of the list */
1987 /* Copy previous container partition data to current entry */
1988 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1989 &PrevPartEntry
->PartInfo
[1],
1990 sizeof(PARTITION_INFORMATION
));
1991 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1993 /* Update previous container partition data */
1995 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1996 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1997 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
1998 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
2000 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2002 /* Special case - previous partition is first partition */
2003 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2004 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2008 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2009 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2012 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2014 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2016 /* Current entry is the first entry */
2019 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2021 /* Current entry is the last entry */
2023 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2024 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2025 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2026 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
2028 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2030 /* Special case - previous partition is first partition */
2031 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2032 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2036 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2037 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2040 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2041 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2042 (1024LL * 255LL * 63LL * 512LL))
2044 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2048 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2051 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2052 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2055 PartEntry
->AutoCreate
= AutoCreate
;
2056 PartEntry
->New
= TRUE
;
2057 PartEntry
->Unpartitioned
= FALSE
;
2058 PartEntry
->UnpartitionedOffset
= 0ULL;
2059 PartEntry
->UnpartitionedLength
= 0ULL;
2063 /* Insert an initialize a new partition entry */
2064 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
2067 if (NewPartEntry
== NULL
)
2070 RtlZeroMemory (NewPartEntry
,
2073 /* Insert the new entry into the list */
2074 InsertTailList (&PartEntry
->ListEntry
,
2075 &NewPartEntry
->ListEntry
);
2077 NewPartEntry
->New
= TRUE
;
2079 NewPartEntry
->FormatState
= Unformatted
;
2080 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
2081 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
2082 NewPartEntry
->PartInfo
[0].HiddenSectors
=
2083 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
2084 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
2085 PartitionSize
- DiskEntry
->TrackSize
;
2086 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
2087 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
2088 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2089 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2090 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
2091 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
2093 /* Get previous and next partition entries */
2094 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2096 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2099 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2101 /* Current entry is in the middle of the list */
2103 /* Copy previous container partition data to current entry */
2104 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
2105 &PrevPartEntry
->PartInfo
[1],
2106 sizeof(PARTITION_INFORMATION
));
2107 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2109 /* Update previous container partition data */
2111 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2112 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2113 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2114 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
2116 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2118 /* Special case - previous partition is first partition */
2119 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2120 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2124 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2125 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2128 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2130 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2132 /* Current entry is the first entry */
2135 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2137 /* Current entry is the last entry */
2139 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2140 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2141 PrevPartEntry
->PartInfo
[1].HiddenSectors
=
2142 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
2144 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2146 /* Special case - previous partition is first partition */
2147 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2148 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2152 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2153 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2156 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2157 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2158 (1024LL * 255LL * 63LL * 512LL))
2160 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2164 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2167 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2168 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2171 /* Update offset and size of the remaining unpartitioned disk space */
2172 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
2173 PartEntry
->UnpartitionedLength
-= PartitionSize
;
2176 DiskEntry
->Modified
= TRUE
;
2178 UpdatePartitionNumbers (DiskEntry
);
2180 AssignDriverLetters (List
);
2185 DeleteCurrentPartition (PPARTLIST List
)
2187 PDISKENTRY DiskEntry
;
2188 PPARTENTRY PartEntry
;
2189 PPARTENTRY PrevPartEntry
;
2190 PPARTENTRY NextPartEntry
;
2193 List
->CurrentDisk
== NULL
||
2194 List
->CurrentPartition
== NULL
||
2195 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2200 DiskEntry
= List
->CurrentDisk
;
2201 PartEntry
= List
->CurrentPartition
;
2203 /* Adjust container partition entries */
2205 /* Get previous and next partition entries */
2206 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2208 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2211 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2213 /* Current entry is in the middle of the list */
2216 * The first extended partition can not be deleted
2217 * as long as other extended partitions are present.
2219 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2222 /* Copy previous container partition data to current entry */
2223 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
2224 &PartEntry
->PartInfo
[1],
2225 sizeof(PARTITION_INFORMATION
));
2226 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2228 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2231 * A primary partition can not be deleted as long as
2232 * extended partitions are present.
2236 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2238 /* Current entry is the last entry */
2239 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
2240 sizeof(PARTITION_INFORMATION
));
2241 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2245 /* Adjust unpartitioned disk space entries */
2247 /* Get pointer to previous and next unpartitioned entries */
2248 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
2251 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
2254 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2256 /* Merge previous, current and next unpartitioned entry */
2258 /* Adjust the previous entries length */
2259 PrevPartEntry
->UnpartitionedLength
+=
2260 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2261 NextPartEntry
->UnpartitionedLength
);
2263 /* Remove the current entry */
2264 RemoveEntryList (&PartEntry
->ListEntry
);
2265 RtlFreeHeap (ProcessHeap
,
2269 /* Remove the next entry */
2270 RemoveEntryList (&NextPartEntry
->ListEntry
);
2271 RtlFreeHeap (ProcessHeap
,
2275 /* Update current partition */
2276 List
->CurrentPartition
= PrevPartEntry
;
2278 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2280 /* Merge current and previous unpartitioned entry */
2282 /* Adjust the previous entries length */
2283 PrevPartEntry
->UnpartitionedLength
+=
2284 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2286 /* Remove the current entry */
2287 RemoveEntryList (&PartEntry
->ListEntry
);
2288 RtlFreeHeap (ProcessHeap
,
2292 /* Update current partition */
2293 List
->CurrentPartition
= PrevPartEntry
;
2295 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2297 /* Merge current and next unpartitioned entry */
2299 /* Adjust the next entries offset and length */
2300 NextPartEntry
->UnpartitionedOffset
=
2301 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2302 NextPartEntry
->UnpartitionedLength
+=
2303 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2305 /* Remove the current entry */
2306 RemoveEntryList (&PartEntry
->ListEntry
);
2307 RtlFreeHeap (ProcessHeap
,
2311 /* Update current partition */
2312 List
->CurrentPartition
= NextPartEntry
;
2316 /* Nothing to merge but change current entry */
2317 PartEntry
->New
= FALSE
;
2318 PartEntry
->Unpartitioned
= TRUE
;
2319 PartEntry
->UnpartitionedOffset
=
2320 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2321 PartEntry
->UnpartitionedLength
=
2322 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2324 /* Wipe the partition table */
2325 RtlZeroMemory (&PartEntry
->PartInfo
,
2326 sizeof(PartEntry
->PartInfo
));
2329 DiskEntry
->Modified
= TRUE
;
2331 UpdatePartitionNumbers (DiskEntry
);
2333 AssignDriverLetters (List
);
2338 CheckActiveBootPartition (PPARTLIST List
)
2340 PDISKENTRY DiskEntry
;
2341 PPARTENTRY PartEntry
;
2342 PLIST_ENTRY ListEntry
;
2345 /* Check for empty disk list */
2346 if (IsListEmpty (&List
->DiskListHead
))
2348 List
->ActiveBootDisk
= NULL
;
2349 List
->ActiveBootPartition
= NULL
;
2350 List
->ActiveBootPartitionNumber
= 0;
2355 if (List
->ActiveBootDisk
!= NULL
&&
2356 List
->ActiveBootPartition
!= NULL
)
2358 /* We already have an active boot partition */
2363 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
2367 /* Check for empty partition list */
2368 if (IsListEmpty (&DiskEntry
->PartListHead
))
2370 List
->ActiveBootDisk
= NULL
;
2371 List
->ActiveBootPartition
= NULL
;
2372 List
->ActiveBootPartitionNumber
= 0;
2376 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
2380 /* Set active boot partition */
2381 if ((DiskEntry
->NewDisk
== TRUE
) ||
2382 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2383 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2384 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2385 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2387 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2388 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2389 DiskEntry
->Modified
= TRUE
;
2391 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2392 List
->ActiveBootDisk
= DiskEntry
;
2393 List
->ActiveBootPartition
= PartEntry
;
2394 List
->ActiveBootPartitionNumber
= 0;
2399 /* Disk is not new, scan all partitions to find a bootable one */
2400 List
->ActiveBootDisk
= NULL
;
2401 List
->ActiveBootPartition
= NULL
;
2402 List
->ActiveBootPartitionNumber
= 0;
2404 ListEntry
= DiskEntry
->PartListHead
.Flink
;
2405 while (ListEntry
!= &DiskEntry
->PartListHead
)
2407 PartEntry
= CONTAINING_RECORD(ListEntry
,
2411 /* Check if it's partitioned */
2412 if (!PartEntry
->Unpartitioned
)
2414 /* Go through all of its 4 partitions */
2417 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2418 PartEntry
->PartInfo
[i
].BootIndicator
)
2420 /* Yes, we found it */
2421 List
->ActiveBootDisk
= DiskEntry
;
2422 List
->ActiveBootPartition
= PartEntry
;
2423 List
->ActiveBootPartitionNumber
= i
;
2425 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2426 DiskEntry
->BiosDiskNumber
, PartEntry
->DriveLetter
[i
]);
2432 /* Go to the next one */
2433 ListEntry
= ListEntry
->Flink
;
2439 CheckForLinuxFdiskPartitions (PPARTLIST List
)
2441 PDISKENTRY DiskEntry
;
2442 PPARTENTRY PartEntry
;
2445 ULONG PartitionCount
;
2448 Entry1
= List
->DiskListHead
.Flink
;
2449 while (Entry1
!= &List
->DiskListHead
)
2451 DiskEntry
= CONTAINING_RECORD (Entry1
,
2455 Entry2
= DiskEntry
->PartListHead
.Flink
;
2456 while (Entry2
!= &DiskEntry
->PartListHead
)
2458 PartEntry
= CONTAINING_RECORD (Entry2
,
2462 if (PartEntry
->Unpartitioned
== FALSE
)
2466 for (i
= 0; i
< 4; i
++)
2468 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
2469 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2475 if (PartitionCount
> 1)
2481 Entry2
= Entry2
->Flink
;
2484 Entry1
= Entry1
->Flink
;
2492 WritePartitionsToDisk (PPARTLIST List
)
2494 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2495 OBJECT_ATTRIBUTES ObjectAttributes
;
2496 IO_STATUS_BLOCK Iosb
;
2497 WCHAR SrcPath
[MAX_PATH
];
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
);
2692 /* Install MBR code if the disk is new */
2693 if (DiskEntry1
->NewDisk
== TRUE
&&
2694 DiskEntry1
->BiosDiskNumber
== 0)
2696 wcscpy (SrcPath
, SourceRootPath
.Buffer
);
2697 wcscat (SrcPath
, L
"\\loader\\dosmbr.bin");
2699 DPRINT ("Install MBR bootcode: %S ==> %S\n",
2702 /* Install MBR bootcode */
2703 Status
= InstallMbrBootCodeToDisk (SrcPath
,
2705 if (!NT_SUCCESS (Status
))
2707 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
2712 DiskEntry1
->NewDisk
= FALSE
;
2713 DiskEntry1
->NoMbr
= FALSE
;
2717 Entry1
= Entry1
->Flink
;
2723 BOOL
SetMountedDeviceValues(PPARTLIST List
)
2725 PLIST_ENTRY Entry1
, Entry2
;
2726 PDISKENTRY DiskEntry
;
2727 PPARTENTRY PartEntry
;
2735 Entry1
= List
->DiskListHead
.Flink
;
2736 while (Entry1
!= &List
->DiskListHead
)
2738 DiskEntry
= CONTAINING_RECORD (Entry1
,
2742 Entry2
= DiskEntry
->PartListHead
.Flink
;
2743 while (Entry2
!= &DiskEntry
->PartListHead
)
2745 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2746 if (!PartEntry
->Unpartitioned
)
2750 if (PartEntry
->DriveLetter
[i
])
2752 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
[i
], DiskEntry
->Signature
, PartEntry
->PartInfo
[i
].StartingOffset
))
2759 Entry2
= Entry2
->Flink
;
2761 Entry1
= Entry1
->Flink
;