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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/partlist.c
23 * PURPOSE: Partition list functions
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
34 /* FUNCTIONS ****************************************************************/
37 GetDriverName (PDISKENTRY DiskEntry
)
39 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
43 RtlInitUnicodeString (&DiskEntry
->DriverName
,
47 L
"\\Scsi\\Scsi Port %lu",
50 RtlZeroMemory (&QueryTable
,
53 QueryTable
[0].Name
= L
"Driver";
54 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
55 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
57 Status
= RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP
,
62 if (!NT_SUCCESS (Status
))
64 DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
70 AssignDriverLetters (PPARTLIST List
)
80 /* Assign drive letters to primary partitions */
81 Entry1
= List
->DiskListHead
.Flink
;
82 while (Entry1
!= &List
->DiskListHead
)
84 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
86 if (!IsListEmpty (&DiskEntry
->PartListHead
))
88 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
92 PartEntry
->DriveLetter
= 0;
94 if (PartEntry
->Unpartitioned
== FALSE
&&
95 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
97 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
98 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
99 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
103 PartEntry
->DriveLetter
= Letter
;
110 Entry1
= Entry1
->Flink
;
114 /* Assign drive letters to logical drives */
115 Entry1
= List
->DiskListHead
.Flink
;
116 while (Entry1
!= &List
->DiskListHead
)
118 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
120 Entry2
= DiskEntry
->PartListHead
.Flink
;
121 if (Entry2
!= &DiskEntry
->PartListHead
)
123 Entry2
= Entry2
->Flink
;
124 while (Entry2
!= &DiskEntry
->PartListHead
)
126 PartEntry
= CONTAINING_RECORD (Entry2
,
130 PartEntry
->DriveLetter
= 0;
132 if (PartEntry
->Unpartitioned
== FALSE
&&
133 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
135 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
136 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
137 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
141 PartEntry
->DriveLetter
= Letter
;
147 Entry2
= Entry2
->Flink
;
151 Entry1
= Entry1
->Flink
;
157 UpdatePartitionNumbers (PDISKENTRY DiskEntry
)
159 PPARTENTRY PartEntry
;
165 Entry
= DiskEntry
->PartListHead
.Flink
;
166 while (Entry
!= &DiskEntry
->PartListHead
)
168 PartEntry
= CONTAINING_RECORD (Entry
,
172 if (PartEntry
->Unpartitioned
== TRUE
)
174 for (i
= 0; i
< 4; i
++)
176 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
181 for (i
= 0; i
< 4; i
++)
183 if (IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
))
185 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
187 else if (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
188 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
== 0ULL)
190 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
194 PartEntry
->PartInfo
[i
].PartitionNumber
= PartNumber
;
200 Entry
= Entry
->Flink
;
206 AddPartitionToList (ULONG DiskNumber
,
207 PDISKENTRY DiskEntry
,
208 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
)
210 PPARTENTRY PartEntry
;
214 for (i
= 0; i
< LayoutBuffer
->PartitionCount
; i
+= 4)
216 for (j
= 0; j
< 4; j
++)
218 if (LayoutBuffer
->PartitionEntry
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
219 LayoutBuffer
->PartitionEntry
[j
].PartitionLength
.QuadPart
!= 0ULL)
229 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
232 if (PartEntry
== NULL
)
237 RtlZeroMemory (PartEntry
,
240 PartEntry
->Unpartitioned
= FALSE
;
242 for (j
= 0; j
< 4; j
++)
244 RtlCopyMemory (&PartEntry
->PartInfo
[j
],
245 &LayoutBuffer
->PartitionEntry
[i
+j
],
246 sizeof(PARTITION_INFORMATION
));
249 if (IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
251 PartEntry
->FormatState
= Unformatted
;
253 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
254 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
255 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
256 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
) ||
257 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
258 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
261 if (CheckFatFormat())
263 PartEntry
->FormatState
= Preformatted
;
267 PartEntry
->FormatState
= Unformatted
;
270 PartEntry
->FormatState
= Preformatted
;
272 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
275 if (CheckNtfsFormat())
277 PartEntry
->FormatState
= Preformatted
;
279 else if (CheckHpfsFormat())
281 PartEntry
->FormatState
= Preformatted
;
285 PartEntry
->FormatState
= Unformatted
;
288 PartEntry
->FormatState
= Preformatted
;
292 PartEntry
->FormatState
= Unknown
;
295 InsertTailList (&DiskEntry
->PartListHead
,
296 &PartEntry
->ListEntry
);
302 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry
)
304 ULONGLONG LastStartingOffset
;
305 ULONGLONG LastPartitionLength
;
306 ULONGLONG LastUnusedPartitionLength
;
307 PPARTENTRY PartEntry
;
308 PPARTENTRY NewPartEntry
;
313 if (IsListEmpty (&DiskEntry
->PartListHead
))
315 /* Create a partition table that represents the empty disk */
316 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
319 if (PartEntry
== NULL
)
322 RtlZeroMemory (PartEntry
,
325 PartEntry
->Unpartitioned
= TRUE
;
326 PartEntry
->UnpartitionedOffset
= 0ULL;
327 PartEntry
->UnpartitionedLength
= DiskEntry
->DiskSize
;
329 PartEntry
->FormatState
= Unformatted
;
331 InsertTailList (&DiskEntry
->PartListHead
,
332 &PartEntry
->ListEntry
);
336 /* Start partition at head 1, cylinder 0 */
337 LastStartingOffset
= DiskEntry
->TrackSize
;
338 LastPartitionLength
= 0ULL;
339 LastUnusedPartitionLength
= 0ULL;
342 Entry
= DiskEntry
->PartListHead
.Flink
;
343 while (Entry
!= &DiskEntry
->PartListHead
)
345 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
347 for (j
= 0; j
< 4; j
++)
349 if ((!IsContainerPartition (PartEntry
->PartInfo
[j
].PartitionType
)) &&
350 (PartEntry
->PartInfo
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
351 PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
!= 0LL))
353 LastUnusedPartitionLength
=
354 PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
-
355 (LastStartingOffset
+ LastPartitionLength
);
357 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
359 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
361 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
364 if (NewPartEntry
== NULL
)
367 RtlZeroMemory (NewPartEntry
,
370 NewPartEntry
->Unpartitioned
= TRUE
;
371 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
372 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
374 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
376 NewPartEntry
->FormatState
= Unformatted
;
378 /* Insert the table into the list */
379 InsertTailList (&PartEntry
->ListEntry
,
380 &NewPartEntry
->ListEntry
);
383 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
384 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
389 Entry
= Entry
->Flink
;
392 /* Check for trailing unpartitioned disk space */
393 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
395 /* Round-down to cylinder size */
396 LastUnusedPartitionLength
=
397 ROUND_DOWN (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
),
398 DiskEntry
->CylinderSize
);
400 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
402 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
404 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
407 if (NewPartEntry
== NULL
)
410 RtlZeroMemory (NewPartEntry
,
413 NewPartEntry
->Unpartitioned
= TRUE
;
414 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
415 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
417 /* Append the table to the list */
418 InsertTailList (&DiskEntry
->PartListHead
,
419 &NewPartEntry
->ListEntry
);
427 DiskIdentifierQueryRoutine(PWSTR ValueName
,
434 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
435 UNICODE_STRING NameU
;
437 if (ValueType
== REG_SZ
&&
438 ValueLength
== 20 * sizeof(WCHAR
))
440 NameU
.Buffer
= (PWCHAR
)ValueData
;
441 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
442 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
444 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
445 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
447 return STATUS_SUCCESS
;
449 return STATUS_UNSUCCESSFUL
;
454 DiskConfigurationDataQueryRoutine(PWSTR ValueName
,
461 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
462 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
463 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
465 if (ValueType
== REG_FULL_RESOURCE_DESCRIPTOR
&&
466 ValueLength
== sizeof(CM_FULL_RESOURCE_DESCRIPTOR
) + sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
468 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
470 * Is this 'paranoia' check correct ?
472 if (FullResourceDescriptor
->InterfaceType
!= InterfaceTypeUndefined
||
473 FullResourceDescriptor
->BusNumber
!= 0 ||
474 FullResourceDescriptor
->PartialResourceList
.Count
!= 1 ||
475 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[0].Type
!= CmResourceTypeDeviceSpecific
||
476 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[0].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
478 return STATUS_UNSUCCESSFUL
;
480 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)(FullResourceDescriptor
+ 1);
481 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
483 return STATUS_SUCCESS
;
485 return STATUS_UNSUCCESSFUL
;
490 SystemConfigurationDataQueryRoutine(PWSTR ValueName
,
497 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
498 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
500 if (ValueType
== REG_FULL_RESOURCE_DESCRIPTOR
&&
501 ValueLength
>= sizeof (CM_FULL_RESOURCE_DESCRIPTOR
) &&
502 (ValueLength
- sizeof(CM_FULL_RESOURCE_DESCRIPTOR
)) % sizeof(CM_INT13_DRIVE_PARAMETER
) == 0)
504 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
505 if (FullResourceDescriptor
->InterfaceType
!= InterfaceTypeUndefined
||
506 FullResourceDescriptor
->BusNumber
!= -1 ||
507 FullResourceDescriptor
->PartialResourceList
.Count
!= 1 ||
508 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[0].Type
!= CmResourceTypeDeviceSpecific
)
510 return STATUS_UNSUCCESSFUL
;
512 *Int13Drives
= RtlAllocateHeap(ProcessHeap
, 0, ValueLength
- sizeof (CM_FULL_RESOURCE_DESCRIPTOR
));
513 if (*Int13Drives
== NULL
)
515 return STATUS_NO_MEMORY
;
517 memcpy(*Int13Drives
, FullResourceDescriptor
+ 1, ValueLength
- sizeof (CM_FULL_RESOURCE_DESCRIPTOR
));
518 return STATUS_SUCCESS
;
520 return STATUS_UNSUCCESSFUL
;
523 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
526 EnumerateBiosDiskEntries(PPARTLIST PartList
)
528 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
533 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
534 PBIOSDISKENTRY BiosDiskEntry
;
536 memset(QueryTable
, 0, sizeof(QueryTable
));
538 QueryTable
[1].Name
= L
"Configuration Data";
539 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
541 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
542 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
546 if (!NT_SUCCESS(Status
))
548 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
555 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
556 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
561 if (!NT_SUCCESS(Status
))
566 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
567 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
572 if (NT_SUCCESS(Status
))
576 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
577 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
582 if (!NT_SUCCESS(Status
))
584 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
588 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
589 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
594 if (NT_SUCCESS(Status
))
596 QueryTable
[0].Name
= L
"Identifier";
597 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
598 QueryTable
[1].Name
= L
"Configuration Data";
599 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
603 BiosDiskEntry
= RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
604 if (BiosDiskEntry
== NULL
)
608 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
609 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
612 (PVOID
)BiosDiskEntry
,
614 if (!NT_SUCCESS(Status
))
616 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
619 BiosDiskEntry
->DiskNumber
= DiskCount
;
620 BiosDiskEntry
->Recognized
= FALSE
;
622 if (DiskCount
< Int13Drives
[0].NumberDrives
)
624 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
628 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
632 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
634 DPRINT("DiskNumber: %d\n", BiosDiskEntry
->DiskNumber
);
635 DPRINT("Signature: %08x\n", BiosDiskEntry
->Signature
);
636 DPRINT("Checksum: %08x\n", BiosDiskEntry
->Checksum
);
637 DPRINT("BytesPerSector: %d\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
638 DPRINT("NumberOfCylinders: %d\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
639 DPRINT("NumberOfHeads: %d\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
640 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
641 DPRINT("MaxCylinders: %d\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
642 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
643 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
644 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
649 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
655 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
659 AddDiskToList (HANDLE FileHandle
,
663 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
664 DISK_GEOMETRY DiskGeometry
;
665 SCSI_ADDRESS ScsiAddress
;
666 PDISKENTRY DiskEntry
;
667 IO_STATUS_BLOCK Iosb
;
669 PPARTITION_SECTOR Mbr
;
671 LARGE_INTEGER FileOffset
;
672 WCHAR Identifier
[20];
676 PLIST_ENTRY ListEntry
;
677 PBIOSDISKENTRY BiosDiskEntry
;
679 Status
= NtDeviceIoControlFile (FileHandle
,
684 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
688 sizeof(DISK_GEOMETRY
));
689 if (!NT_SUCCESS (Status
))
694 if (DiskGeometry
.MediaType
!= FixedMedia
)
699 Status
= NtDeviceIoControlFile (FileHandle
,
704 IOCTL_SCSI_GET_ADDRESS
,
708 sizeof(SCSI_ADDRESS
));
709 if (!NT_SUCCESS(Status
))
714 Mbr
= RtlAllocateHeap(ProcessHeap
,
716 DiskGeometry
.BytesPerSector
);
723 FileOffset
.QuadPart
= 0;
724 Status
= NtReadFile(FileHandle
,
730 DiskGeometry
.BytesPerSector
,
733 if (!NT_SUCCESS(Status
))
735 RtlFreeHeap(ProcessHeap
,
738 DPRINT1("NtReadFile failed, status=%x\n", Status
);
741 Signature
= Mbr
->Signature
;
743 /* Calculate the MBR checksum */
745 Buffer
= (PULONG
)Mbr
;
746 for (i
= 0; i
< 128; i
++)
748 Checksum
+= Buffer
[i
];
750 Checksum
= ~Checksum
+ 1;
752 RtlFreeHeap (ProcessHeap
,
756 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
757 DPRINT("Identifier: %S\n", Identifier
);
759 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
762 if (DiskEntry
== NULL
)
767 DiskEntry
->Checksum
= Checksum
;
768 DiskEntry
->Signature
= Signature
;
771 /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
772 DiskEntry
->Modified
= TRUE
;
774 DiskEntry
->BiosFound
= FALSE
;
776 ListEntry
= List
->BiosDiskListHead
.Flink
;
777 while(ListEntry
!= &List
->BiosDiskListHead
)
779 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
781 * Compare the size from bios and the reported size from driver.
782 * If we have more than one disk with a zero or with the same signatur
783 * we must create new signatures and reboot. After the reboot,
784 * it is possible to identify the disks.
786 if (BiosDiskEntry
->Signature
== Signature
&&
787 BiosDiskEntry
->Checksum
== Checksum
&&
788 !BiosDiskEntry
->Recognized
)
790 if (!DiskEntry
->BiosFound
)
792 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
793 DiskEntry
->BiosFound
= TRUE
;
794 BiosDiskEntry
->Recognized
= TRUE
;
800 ListEntry
= ListEntry
->Flink
;
803 if (!DiskEntry
->BiosFound
)
805 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
809 InitializeListHead (&DiskEntry
->PartListHead
);
811 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
812 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
813 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
814 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
816 DPRINT ("Cylinders %d\n", DiskEntry
->Cylinders
);
817 DPRINT ("TracksPerCylinder %d\n", DiskEntry
->TracksPerCylinder
);
818 DPRINT ("SectorsPerTrack %d\n", DiskEntry
->SectorsPerTrack
);
819 DPRINT ("BytesPerSector %d\n", DiskEntry
->BytesPerSector
);
821 DiskEntry
->DiskSize
=
822 DiskGeometry
.Cylinders
.QuadPart
*
823 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
824 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
825 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
826 DiskEntry
->CylinderSize
=
827 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
828 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
829 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
830 DiskEntry
->TrackSize
=
831 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
832 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
834 DiskEntry
->DiskNumber
= DiskNumber
;
835 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
836 DiskEntry
->Bus
= ScsiAddress
.PathId
;
837 DiskEntry
->Id
= ScsiAddress
.TargetId
;
839 GetDriverName (DiskEntry
);
841 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, BiosDiskNumber
);
843 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
846 if (LayoutBuffer
== NULL
)
851 Status
= NtDeviceIoControlFile (FileHandle
,
856 IOCTL_DISK_GET_DRIVE_LAYOUT
,
861 if (NT_SUCCESS (Status
))
863 if (LayoutBuffer
->PartitionCount
== 0)
865 DiskEntry
->NewDisk
= TRUE
;
868 AddPartitionToList (DiskNumber
,
872 ScanForUnpartitionedDiskSpace (DiskEntry
);
875 RtlFreeHeap (ProcessHeap
,
882 CreatePartitionList (SHORT Left
,
888 OBJECT_ATTRIBUTES ObjectAttributes
;
889 SYSTEM_DEVICE_INFORMATION Sdi
;
890 IO_STATUS_BLOCK Iosb
;
894 WCHAR Buffer
[MAX_PATH
];
898 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
907 List
->Bottom
= Bottom
;
911 List
->TopDisk
= (ULONG
)-1;
912 List
->TopPartition
= (ULONG
)-1;
914 List
->CurrentDisk
= NULL
;
915 List
->CurrentPartition
= NULL
;
917 InitializeListHead (&List
->DiskListHead
);
918 InitializeListHead (&List
->BiosDiskListHead
);
920 EnumerateBiosDiskEntries(List
);
922 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
924 sizeof(SYSTEM_DEVICE_INFORMATION
),
926 if (!NT_SUCCESS (Status
))
928 RtlFreeHeap (ProcessHeap
, 0, List
);
932 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
935 L
"\\Device\\Harddisk%d\\Partition0",
937 RtlInitUnicodeString (&Name
,
940 InitializeObjectAttributes (&ObjectAttributes
,
946 Status
= NtOpenFile (&FileHandle
,
951 FILE_SYNCHRONOUS_IO_NONALERT
);
952 if (NT_SUCCESS(Status
))
954 AddDiskToList (FileHandle
,
962 AssignDriverLetters (List
);
965 List
->TopPartition
= 0;
967 /* Search for first usable disk and partition */
968 if (IsListEmpty (&List
->DiskListHead
))
970 List
->CurrentDisk
= NULL
;
971 List
->CurrentPartition
= NULL
;
976 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
980 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
982 List
->CurrentPartition
= 0;
986 List
->CurrentPartition
=
987 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
998 DestroyPartitionList (PPARTLIST List
)
1000 PDISKENTRY DiskEntry
;
1001 PBIOSDISKENTRY BiosDiskEntry
;
1002 PPARTENTRY PartEntry
;
1005 /* Release disk and partition info */
1006 while (!IsListEmpty (&List
->DiskListHead
))
1008 Entry
= RemoveHeadList (&List
->DiskListHead
);
1009 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1011 /* Release driver name */
1012 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1014 /* Release partition array */
1015 while (!IsListEmpty (&DiskEntry
->PartListHead
))
1017 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
1018 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
1020 RtlFreeHeap (ProcessHeap
,
1025 /* Release disk entry */
1026 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
1029 /* release the bios disk info */
1030 while(!IsListEmpty(&List
->BiosDiskListHead
))
1032 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1033 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1035 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1038 /* Release list head */
1039 RtlFreeHeap (ProcessHeap
, 0, List
);
1044 PrintEmptyLine (PPARTLIST List
)
1051 Width
= List
->Right
- List
->Left
- 1;
1052 Height
= List
->Bottom
- List
->Top
- 2;
1055 coPos
.X
= List
->Left
+ 1;
1056 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1058 if (List
->Line
>= 0 && List
->Line
<= Height
)
1060 FillConsoleOutputAttribute (0x17,
1065 FillConsoleOutputCharacter (' ',
1075 PrintPartitionData (PPARTLIST List
,
1076 PDISKENTRY DiskEntry
,
1077 PPARTENTRY PartEntry
)
1079 CHAR LineBuffer
[128];
1090 Width
= List
->Right
- List
->Left
- 1;
1091 Height
= List
->Bottom
- List
->Top
- 2;
1094 coPos
.X
= List
->Left
+ 1;
1095 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1097 if (PartEntry
->Unpartitioned
== TRUE
)
1100 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1102 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1107 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1109 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1114 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1118 sprintf (LineBuffer
,
1119 " Unpartitioned space %6I64u %s",
1125 /* Determine partition type */
1127 if (PartEntry
->New
== TRUE
)
1129 PartType
= "New (Unformatted)";
1131 else if (PartEntry
->Unpartitioned
== FALSE
)
1133 if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
1134 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
1135 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
1136 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
))
1140 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
1141 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
1145 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
1147 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1152 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1154 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1159 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1161 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1166 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1170 if (PartType
== NULL
)
1172 sprintf (LineBuffer
,
1173 "%c%c Type %-3u %6I64u %s",
1174 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1175 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1176 PartEntry
->PartInfo
[0].PartitionType
,
1182 sprintf (LineBuffer
,
1183 "%c%c %-24s %6I64u %s",
1184 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1185 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1192 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1193 List
->CurrentPartition
== PartEntry
) ? 0x71 : 0x17;
1195 if (List
->Line
>= 0 && List
->Line
<= Height
)
1197 FillConsoleOutputCharacter (' ',
1204 if (List
->Line
>= 0 && List
->Line
<= Height
)
1206 FillConsoleOutputAttribute (Attribute
,
1213 if (List
->Line
>= 0 && List
->Line
<= Height
)
1215 WriteConsoleOutputCharacters (LineBuffer
,
1216 min (strlen (LineBuffer
), Width
),
1224 PrintDiskData (PPARTLIST List
,
1225 PDISKENTRY DiskEntry
)
1227 PPARTENTRY PartEntry
;
1228 CHAR LineBuffer
[128];
1236 Width
= List
->Right
- List
->Left
- 1;
1237 Height
= List
->Bottom
- List
->Top
- 2;
1240 coPos
.X
= List
->Left
+ 1;
1241 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1244 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1246 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1252 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1258 if (DiskEntry
->DriverName
.Length
> 0)
1260 sprintf (LineBuffer
,
1261 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ",
1264 DiskEntry
->DiskNumber
,
1268 &DiskEntry
->DriverName
);
1272 sprintf (LineBuffer
,
1273 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
1276 DiskEntry
->DiskNumber
,
1281 if (List
->Line
>= 0 && List
->Line
<= Height
)
1283 FillConsoleOutputAttribute (0x17,
1288 FillConsoleOutputCharacter (' ',
1295 if (List
->Line
>= 0 && List
->Line
<= Height
)
1297 WriteConsoleOutputCharacters (LineBuffer
,
1298 min (strlen (LineBuffer
), Width
- 2),
1303 /* Print separator line */
1304 PrintEmptyLine (List
);
1306 /* Print partition lines*/
1307 LIST_FOR_EACH(PartEntry
, &DiskEntry
->PartListHead
, PARTENTRY
, ListEntry
)
1309 /* Print disk entry */
1310 PrintPartitionData (List
,
1315 /* Print separator line */
1316 PrintEmptyLine (List
);
1321 DrawPartitionList (PPARTLIST List
)
1323 PLIST_ENTRY Entry
, Entry2
;
1324 PDISKENTRY DiskEntry
;
1325 PPARTENTRY PartEntry
= NULL
;
1329 SHORT CurrentDiskLine
;
1330 SHORT CurrentPartLine
;
1332 BOOL CurrentPartLineFound
= FALSE
;
1333 BOOL CurrentDiskLineFound
= FALSE
;
1335 /* Calculate the line of the current disk and partition */
1336 CurrentDiskLine
= 0;
1337 CurrentPartLine
= 0;
1339 Entry
= List
->DiskListHead
.Flink
;
1340 while (Entry
!= &List
->DiskListHead
)
1342 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1344 if (CurrentPartLineFound
== FALSE
)
1346 CurrentPartLine
+= 2;
1348 Entry2
= DiskEntry
->PartListHead
.Flink
;
1349 while (Entry2
!= &DiskEntry
->PartListHead
)
1351 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1352 if (PartEntry
== List
->CurrentPartition
)
1354 CurrentPartLineFound
= TRUE
;
1356 Entry2
= Entry2
->Flink
;
1357 if (CurrentPartLineFound
== FALSE
)
1363 if (DiskEntry
== List
->CurrentDisk
)
1365 CurrentDiskLineFound
= TRUE
;
1367 Entry
= Entry
->Flink
;
1368 if (Entry
!= &List
->DiskListHead
)
1370 if (CurrentDiskLineFound
== FALSE
)
1373 CurrentDiskLine
= CurrentPartLine
;
1383 /* If it possible, make the disk name visible */
1384 if (CurrentPartLine
< List
->Offset
)
1386 List
->Offset
= CurrentPartLine
;
1388 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1390 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1392 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1394 List
->Offset
= CurrentDiskLine
;
1398 /* draw upper left corner */
1399 coPos
.X
= List
->Left
;
1400 coPos
.Y
= List
->Top
;
1401 FillConsoleOutputCharacter (0xDA, // '+',
1406 /* draw upper edge */
1407 coPos
.X
= List
->Left
+ 1;
1408 coPos
.Y
= List
->Top
;
1409 if (List
->Offset
== 0)
1411 FillConsoleOutputCharacter (0xC4, // '-',
1412 List
->Right
- List
->Left
- 1,
1418 FillConsoleOutputCharacter (0xC4, // '-',
1419 List
->Right
- List
->Left
- 5,
1422 coPos
.X
= List
->Right
- 5;
1423 WriteConsoleOutputCharacters ("(\x18)", // "(up)"
1426 coPos
.X
= List
->Right
- 2;
1427 FillConsoleOutputCharacter (0xC4, // '-',
1433 /* draw upper right corner */
1434 coPos
.X
= List
->Right
;
1435 coPos
.Y
= List
->Top
;
1436 FillConsoleOutputCharacter (0xBF, // '+',
1441 /* draw left and right edge */
1442 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1444 coPos
.X
= List
->Left
;
1446 FillConsoleOutputCharacter (0xB3, // '|',
1451 coPos
.X
= List
->Right
;
1452 FillConsoleOutputCharacter (0xB3, //'|',
1458 /* draw lower left corner */
1459 coPos
.X
= List
->Left
;
1460 coPos
.Y
= List
->Bottom
;
1461 FillConsoleOutputCharacter (0xC0, // '+',
1466 /* draw lower edge */
1467 coPos
.X
= List
->Left
+ 1;
1468 coPos
.Y
= List
->Bottom
;
1469 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1471 FillConsoleOutputCharacter (0xC4, // '-',
1472 List
->Right
- List
->Left
- 1,
1478 FillConsoleOutputCharacter (0xC4, // '-',
1479 List
->Right
- List
->Left
- 5,
1482 coPos
.X
= List
->Right
- 5;
1483 WriteConsoleOutputCharacters ("(\x19)", // "(down)"
1486 coPos
.X
= List
->Right
- 2;
1487 FillConsoleOutputCharacter (0xC4, // '-',
1493 /* draw lower right corner */
1494 coPos
.X
= List
->Right
;
1495 coPos
.Y
= List
->Bottom
;
1496 FillConsoleOutputCharacter (0xD9, // '+',
1501 /* print list entries */
1502 List
->Line
= - List
->Offset
;
1504 LIST_FOR_EACH(DiskEntry
, &List
->DiskListHead
, DISKENTRY
, ListEntry
)
1506 /* Print disk entry */
1507 PrintDiskData (List
,
1514 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1516 PDISKENTRY DiskEntry
;
1517 PPARTENTRY PartEntry
;
1522 /* Check for empty disks */
1523 if (IsListEmpty (&List
->DiskListHead
))
1526 /* Check for first usable entry on next disk */
1527 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1528 while (Entry1
!= &List
->DiskListHead
)
1530 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1532 if (DiskEntry
->DiskNumber
== DiskNumber
)
1534 Entry2
= DiskEntry
->PartListHead
.Flink
;
1535 while (Entry2
!= &DiskEntry
->PartListHead
)
1537 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1539 for (i
= 0; i
< 4; i
++)
1541 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1543 List
->CurrentDisk
= DiskEntry
;
1544 List
->CurrentPartition
= PartEntry
;
1545 DrawPartitionList (List
);
1549 Entry2
= Entry2
->Flink
;
1553 Entry1
= Entry1
->Flink
;
1559 ScrollDownPartitionList (PPARTLIST List
)
1561 PDISKENTRY DiskEntry
;
1562 PPARTENTRY PartEntry
;
1566 /* Check for empty disks */
1567 if (IsListEmpty (&List
->DiskListHead
))
1570 /* Check for next usable entry on current disk */
1571 if (List
->CurrentPartition
!= NULL
)
1573 Entry2
= List
->CurrentPartition
->ListEntry
.Flink
;
1574 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1576 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1578 // if (PartEntry->HidePartEntry == FALSE)
1580 List
->CurrentPartition
= PartEntry
;
1581 DrawPartitionList (List
);
1584 Entry2
= Entry2
->Flink
;
1588 /* Check for first usable entry on next disk */
1589 if (List
->CurrentDisk
!= NULL
)
1591 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1592 while (Entry1
!= &List
->DiskListHead
)
1594 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1596 Entry2
= DiskEntry
->PartListHead
.Flink
;
1597 while (Entry2
!= &DiskEntry
->PartListHead
)
1599 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1601 // if (PartEntry->HidePartEntry == FALSE)
1603 List
->CurrentDisk
= DiskEntry
;
1604 List
->CurrentPartition
= PartEntry
;
1605 DrawPartitionList (List
);
1609 Entry2
= Entry2
->Flink
;
1612 Entry1
= Entry1
->Flink
;
1619 ScrollUpPartitionList (PPARTLIST List
)
1621 PDISKENTRY DiskEntry
;
1622 PPARTENTRY PartEntry
;
1626 /* Check for empty disks */
1627 if (IsListEmpty (&List
->DiskListHead
))
1630 /* check for previous usable entry on current disk */
1631 if (List
->CurrentPartition
!= NULL
)
1633 Entry2
= List
->CurrentPartition
->ListEntry
.Blink
;
1634 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1636 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1638 // if (PartEntry->HidePartEntry == FALSE)
1640 List
->CurrentPartition
= PartEntry
;
1641 DrawPartitionList (List
);
1644 Entry2
= Entry2
->Blink
;
1649 /* check for last usable entry on previous disk */
1650 if (List
->CurrentDisk
!= NULL
)
1652 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1653 while (Entry1
!= &List
->DiskListHead
)
1655 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1657 Entry2
= DiskEntry
->PartListHead
.Blink
;
1658 while (Entry2
!= &DiskEntry
->PartListHead
)
1660 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1662 // if (PartEntry->HidePartEntry == FALSE)
1664 List
->CurrentDisk
= DiskEntry
;
1665 List
->CurrentPartition
= PartEntry
;
1666 DrawPartitionList (List
);
1670 Entry2
= Entry2
->Blink
;
1673 Entry1
= Entry1
->Blink
;
1680 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1681 PPARTENTRY CurrentEntry
)
1683 PPARTENTRY PrevEntry
;
1686 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1689 Entry
= CurrentEntry
->ListEntry
.Blink
;
1690 while (Entry
!= &DiskEntry
->PartListHead
)
1692 PrevEntry
= CONTAINING_RECORD (Entry
,
1695 if (PrevEntry
->Unpartitioned
== FALSE
)
1698 Entry
= Entry
->Blink
;
1706 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1707 PPARTENTRY CurrentEntry
)
1709 PPARTENTRY NextEntry
;
1712 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1715 Entry
= CurrentEntry
->ListEntry
.Flink
;
1716 while (Entry
!= &DiskEntry
->PartListHead
)
1718 NextEntry
= CONTAINING_RECORD (Entry
,
1721 if (NextEntry
->Unpartitioned
== FALSE
)
1724 Entry
= Entry
->Flink
;
1732 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1733 PPARTENTRY PartEntry
)
1735 PPARTENTRY PrevPartEntry
;
1737 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1739 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1742 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1743 return PrevPartEntry
;
1751 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1752 PPARTENTRY PartEntry
)
1754 PPARTENTRY NextPartEntry
;
1756 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1758 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1761 if (NextPartEntry
->Unpartitioned
== TRUE
)
1762 return NextPartEntry
;
1770 CreateNewPartition (PPARTLIST List
,
1771 ULONGLONG PartitionSize
,
1774 PDISKENTRY DiskEntry
;
1775 PPARTENTRY PartEntry
;
1776 PPARTENTRY PrevPartEntry
;
1777 PPARTENTRY NextPartEntry
;
1778 PPARTENTRY NewPartEntry
;
1781 List
->CurrentDisk
== NULL
||
1782 List
->CurrentPartition
== NULL
||
1783 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1788 DiskEntry
= List
->CurrentDisk
;
1789 PartEntry
= List
->CurrentPartition
;
1791 if (AutoCreate
== TRUE
||
1792 PartitionSize
== PartEntry
->UnpartitionedLength
)
1794 /* Convert current entry to 'new (unformatted)' */
1795 PartEntry
->FormatState
= Unformatted
;
1796 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1797 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1798 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1799 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1800 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1801 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1802 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1803 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1804 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1805 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1807 /* Get previous and next partition entries */
1808 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1810 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1813 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1815 /* Current entry is in the middle of the list */
1817 /* Copy previous container partition data to current entry */
1818 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1819 &PrevPartEntry
->PartInfo
[1],
1820 sizeof(PARTITION_INFORMATION
));
1821 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1823 /* Update previous container partition data */
1825 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1826 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1828 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1830 /* Special case - previous partition is first partition */
1831 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1832 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1836 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1837 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1840 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1842 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1844 /* Current entry is the first entry */
1847 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1849 /* Current entry is the last entry */
1851 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1852 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1854 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1856 /* Special case - previous partition is first partition */
1857 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1858 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1862 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1863 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1866 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
1867 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
1868 (1024LL * 255LL * 63LL * 512LL))
1870 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
1874 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
1877 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1878 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1881 PartEntry
->AutoCreate
= AutoCreate
;
1882 PartEntry
->New
= TRUE
;
1883 PartEntry
->Unpartitioned
= FALSE
;
1884 PartEntry
->UnpartitionedOffset
= 0ULL;
1885 PartEntry
->UnpartitionedLength
= 0ULL;
1889 /* Insert an initialize a new partition entry */
1890 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
1893 if (NewPartEntry
== NULL
)
1896 RtlZeroMemory (NewPartEntry
,
1899 /* Insert the new entry into the list */
1900 InsertTailList (&PartEntry
->ListEntry
,
1901 &NewPartEntry
->ListEntry
);
1903 NewPartEntry
->New
= TRUE
;
1905 NewPartEntry
->FormatState
= Unformatted
;
1906 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1907 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1908 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1909 PartitionSize
- DiskEntry
->TrackSize
;
1910 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1911 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1912 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1913 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1914 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1915 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1917 /* Get previous and next partition entries */
1918 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1920 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1923 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1925 /* Current entry is in the middle of the list */
1927 /* Copy previous container partition data to current entry */
1928 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
1929 &PrevPartEntry
->PartInfo
[1],
1930 sizeof(PARTITION_INFORMATION
));
1931 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1933 /* Update previous container partition data */
1935 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1936 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1938 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1940 /* Special case - previous partition is first partition */
1941 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1942 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1946 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1947 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1950 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1952 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1954 /* Current entry is the first entry */
1957 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1959 /* Current entry is the last entry */
1961 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1962 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1964 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1966 /* Special case - previous partition is first partition */
1967 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1968 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1972 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1973 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1976 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
1977 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
1978 (1024LL * 255LL * 63LL * 512LL))
1980 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
1984 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
1987 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1988 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1991 /* Update offset and size of the remaining unpartitioned disk space */
1992 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
1993 PartEntry
->UnpartitionedLength
-= PartitionSize
;
1996 DiskEntry
->Modified
= TRUE
;
1998 UpdatePartitionNumbers (DiskEntry
);
2000 AssignDriverLetters (List
);
2005 DeleteCurrentPartition (PPARTLIST List
)
2007 PDISKENTRY DiskEntry
;
2008 PPARTENTRY PartEntry
;
2009 PPARTENTRY PrevPartEntry
;
2010 PPARTENTRY NextPartEntry
;
2013 List
->CurrentDisk
== NULL
||
2014 List
->CurrentPartition
== NULL
||
2015 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2020 DiskEntry
= List
->CurrentDisk
;
2021 PartEntry
= List
->CurrentPartition
;
2023 /* Adjust container partition entries */
2025 /* Get previous and next partition entries */
2026 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2028 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2031 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2033 /* Current entry is in the middle of the list */
2036 * The first extended partition can not be deleted
2037 * as long as other extended partitions are present.
2039 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2042 /* Copy previous container partition data to current entry */
2043 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
2044 &PartEntry
->PartInfo
[1],
2045 sizeof(PARTITION_INFORMATION
));
2046 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2048 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2051 * A primary partition can not be deleted as long as
2052 * extended partitions are present.
2056 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2058 /* Current entry is the last entry */
2059 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
2060 sizeof(PARTITION_INFORMATION
));
2061 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2065 /* Adjust unpartitioned disk space entries */
2067 /* Get pointer to previous and next unpartitioned entries */
2068 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
2071 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
2074 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2076 /* Merge previous, current and next unpartitioned entry */
2078 /* Adjust the previous entries length */
2079 PrevPartEntry
->UnpartitionedLength
+=
2080 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2081 NextPartEntry
->UnpartitionedLength
);
2083 /* Remove the current entry */
2084 RemoveEntryList (&PartEntry
->ListEntry
);
2085 RtlFreeHeap (ProcessHeap
,
2089 /* Remove the next entry */
2090 RemoveEntryList (&NextPartEntry
->ListEntry
);
2091 RtlFreeHeap (ProcessHeap
,
2095 /* Update current partition */
2096 List
->CurrentPartition
= PrevPartEntry
;
2098 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2100 /* Merge current and previous unpartitioned entry */
2102 /* Adjust the previous entries length */
2103 PrevPartEntry
->UnpartitionedLength
+=
2104 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2106 /* Remove the current entry */
2107 RemoveEntryList (&PartEntry
->ListEntry
);
2108 RtlFreeHeap (ProcessHeap
,
2112 /* Update current partition */
2113 List
->CurrentPartition
= PrevPartEntry
;
2115 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2117 /* Merge current and next unpartitioned entry */
2119 /* Adjust the next entries offset and length */
2120 NextPartEntry
->UnpartitionedOffset
=
2121 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2122 NextPartEntry
->UnpartitionedLength
+=
2123 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2125 /* Remove the current entry */
2126 RemoveEntryList (&PartEntry
->ListEntry
);
2127 RtlFreeHeap (ProcessHeap
,
2131 /* Update current partition */
2132 List
->CurrentPartition
= NextPartEntry
;
2136 /* Nothing to merge but change current entry */
2137 PartEntry
->New
= FALSE
;
2138 PartEntry
->Unpartitioned
= TRUE
;
2139 PartEntry
->UnpartitionedOffset
=
2140 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2141 PartEntry
->UnpartitionedLength
=
2142 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2144 /* Wipe the partition table */
2145 RtlZeroMemory (&PartEntry
->PartInfo
,
2146 sizeof(PartEntry
->PartInfo
));
2149 DiskEntry
->Modified
= TRUE
;
2151 UpdatePartitionNumbers (DiskEntry
);
2153 AssignDriverLetters (List
);
2158 CheckActiveBootPartition (PPARTLIST List
)
2160 PDISKENTRY DiskEntry
;
2161 PPARTENTRY PartEntry
;
2163 /* Check for empty disk list */
2164 if (IsListEmpty (&List
->DiskListHead
))
2166 List
->ActiveBootDisk
= NULL
;
2167 List
->ActiveBootPartition
= NULL
;
2172 if (List
->ActiveBootDisk
!= NULL
&&
2173 List
->ActiveBootPartition
!= NULL
)
2175 /* We already have an active boot partition */
2180 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
2184 /* Check for empty partition list */
2185 if (IsListEmpty (&DiskEntry
->PartListHead
))
2187 List
->ActiveBootDisk
= NULL
;
2188 List
->ActiveBootPartition
= NULL
;
2192 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
2196 /* Set active boot partition */
2197 if ((DiskEntry
->NewDisk
== TRUE
) ||
2198 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2199 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2200 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2201 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2203 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2204 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2205 DiskEntry
->Modified
= TRUE
;
2208 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2209 List
->ActiveBootDisk
= DiskEntry
;
2210 List
->ActiveBootPartition
= PartEntry
;
2215 CheckForLinuxFdiskPartitions (PPARTLIST List
)
2217 PDISKENTRY DiskEntry
;
2218 PPARTENTRY PartEntry
;
2221 ULONG PartitionCount
;
2224 Entry1
= List
->DiskListHead
.Flink
;
2225 while (Entry1
!= &List
->DiskListHead
)
2227 DiskEntry
= CONTAINING_RECORD (Entry1
,
2231 Entry2
= DiskEntry
->PartListHead
.Flink
;
2232 while (Entry2
!= &DiskEntry
->PartListHead
)
2234 PartEntry
= CONTAINING_RECORD (Entry2
,
2238 if (PartEntry
->Unpartitioned
== FALSE
)
2242 for (i
= 0; i
< 4; i
++)
2244 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
2245 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2251 if (PartitionCount
> 1)
2257 Entry2
= Entry2
->Flink
;
2260 Entry1
= Entry1
->Flink
;
2268 WritePartitionsToDisk (PPARTLIST List
)
2270 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2271 OBJECT_ATTRIBUTES ObjectAttributes
;
2272 IO_STATUS_BLOCK Iosb
;
2273 WCHAR SrcPath
[MAX_PATH
];
2274 WCHAR DstPath
[MAX_PATH
];
2275 UNICODE_STRING Name
;
2277 PDISKENTRY DiskEntry1
;
2278 PDISKENTRY DiskEntry2
;
2279 PPARTENTRY PartEntry
;
2282 ULONG PartitionCount
;
2283 ULONG DriveLayoutSize
;
2292 Entry1
= List
->DiskListHead
.Flink
;
2293 while (Entry1
!= &List
->DiskListHead
)
2295 DiskEntry1
= CONTAINING_RECORD (Entry1
,
2299 if (DiskEntry1
->Modified
== TRUE
)
2301 /* Count partitioned entries */
2303 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2304 while (Entry2
!= &DiskEntry1
->PartListHead
)
2306 PartEntry
= CONTAINING_RECORD (Entry2
,
2309 if (PartEntry
->Unpartitioned
== FALSE
)
2311 PartitionCount
+= 4;
2314 Entry2
= Entry2
->Flink
;
2316 if (PartitionCount
== 0)
2318 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2319 ((4 - 1) * sizeof (PARTITION_INFORMATION
));
2323 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2324 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2326 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
2329 if (DriveLayout
== NULL
)
2331 DPRINT1 ("RtlAllocateHeap() failed\n");
2335 RtlZeroMemory (DriveLayout
,
2338 if (PartitionCount
== 0)
2340 /* delete all partitions in the mbr */
2341 DriveLayout
->PartitionCount
= 4;
2342 for (Index
= 0; Index
< 4; Index
++)
2344 DriveLayout
->PartitionEntry
[Index
].RewritePartition
= TRUE
;
2349 DriveLayout
->PartitionCount
= PartitionCount
;
2352 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2353 while (Entry2
!= &DiskEntry1
->PartListHead
)
2355 PartEntry
= CONTAINING_RECORD (Entry2
,
2358 if (PartEntry
->Unpartitioned
== FALSE
)
2360 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2361 &PartEntry
->PartInfo
[0],
2362 4 * sizeof (PARTITION_INFORMATION
));
2366 Entry2
= Entry2
->Flink
;
2369 if (DiskEntry1
->Signature
== 0)
2371 LARGE_INTEGER SystemTime
;
2372 TIME_FIELDS TimeFields
;
2374 Buffer
= (PUCHAR
)&DiskEntry1
->Signature
;
2378 NtQuerySystemTime (&SystemTime
);
2379 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
2381 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
2382 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
2383 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
2384 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
2386 if (DiskEntry1
->Signature
== 0)
2391 /* check if the signature already exist */
2393 * Check also signatures from disks, which are
2394 * not visible (bootable) by the bios.
2396 Entry2
= List
->DiskListHead
.Flink
;
2397 while (Entry2
!= &List
->DiskListHead
)
2399 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
2400 if (DiskEntry1
!= DiskEntry2
&&
2401 DiskEntry1
->Signature
== DiskEntry2
->Signature
)
2405 Entry2
= Entry2
->Flink
;
2407 if (Entry2
== &List
->DiskListHead
)
2413 /* set one partition entry to dirty, this will update the signature */
2414 DriveLayout
->PartitionEntry
[0].RewritePartition
= TRUE
;
2418 DriveLayout
->Signature
= DiskEntry1
->Signature
;
2422 L
"\\Device\\Harddisk%d\\Partition0",
2423 DiskEntry1
->DiskNumber
);
2424 RtlInitUnicodeString (&Name
,
2426 InitializeObjectAttributes (&ObjectAttributes
,
2432 Status
= NtOpenFile (&FileHandle
,
2437 FILE_SYNCHRONOUS_IO_NONALERT
);
2439 if (!NT_SUCCESS (Status
))
2441 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2445 Status
= NtDeviceIoControlFile (FileHandle
,
2450 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2455 if (!NT_SUCCESS (Status
))
2457 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2458 NtClose (FileHandle
);
2462 RtlFreeHeap (ProcessHeap
,
2466 NtClose (FileHandle
);
2468 /* Install MBR code if the disk is new */
2469 if (DiskEntry1
->NewDisk
== TRUE
&&
2470 DiskEntry1
->BiosDiskNumber
== 0)
2472 wcscpy (SrcPath
, SourceRootPath
.Buffer
);
2473 wcscat (SrcPath
, L
"\\loader\\dosmbr.bin");
2475 DPRINT ("Install MBR bootcode: %S ==> %S\n",
2478 /* Install MBR bootcode */
2479 Status
= InstallMbrBootCodeToDisk (SrcPath
,
2481 if (!NT_SUCCESS (Status
))
2483 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
2488 DiskEntry1
->NewDisk
= FALSE
;
2492 Entry1
= Entry1
->Flink
;
2498 BOOL
SetMountedDeviceValues(PPARTLIST List
)
2500 PLIST_ENTRY Entry1
, Entry2
;
2501 PDISKENTRY DiskEntry
;
2502 PPARTENTRY PartEntry
;
2509 Entry1
= List
->DiskListHead
.Flink
;
2510 while (Entry1
!= &List
->DiskListHead
)
2512 DiskEntry
= CONTAINING_RECORD (Entry1
,
2516 Entry2
= DiskEntry
->PartListHead
.Flink
;
2517 while (Entry2
!= &DiskEntry
->PartListHead
)
2519 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2520 if (!PartEntry
->Unpartitioned
&& PartEntry
->DriveLetter
)
2522 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
, DiskEntry
->Signature
, PartEntry
->PartInfo
[0].StartingOffset
))
2527 Entry2
= Entry2
->Flink
;
2529 Entry1
= Entry1
->Flink
;