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.
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
)
78 /* Assign drive letters to primary partitions */
79 Entry1
= List
->DiskListHead
.Flink
;
80 while (Entry1
!= &List
->DiskListHead
)
82 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
84 if (!IsListEmpty (&DiskEntry
->PartListHead
))
86 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
90 PartEntry
->DriveLetter
= 0;
92 if (PartEntry
->Unpartitioned
== FALSE
&&
93 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
95 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
96 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
97 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
101 PartEntry
->DriveLetter
= Letter
;
108 Entry1
= Entry1
->Flink
;
112 /* Assign drive letters to logical drives */
113 Entry1
= List
->DiskListHead
.Flink
;
114 while (Entry1
!= &List
->DiskListHead
)
116 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
118 Entry2
= DiskEntry
->PartListHead
.Flink
;
119 if (Entry2
!= &DiskEntry
->PartListHead
)
121 Entry2
= Entry2
->Flink
;
122 while (Entry2
!= &DiskEntry
->PartListHead
)
124 PartEntry
= CONTAINING_RECORD (Entry2
,
128 PartEntry
->DriveLetter
= 0;
130 if (PartEntry
->Unpartitioned
== FALSE
&&
131 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
133 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
134 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
135 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
139 PartEntry
->DriveLetter
= Letter
;
145 Entry2
= Entry2
->Flink
;
149 Entry1
= Entry1
->Flink
;
155 UpdatePartitionNumbers (PDISKENTRY DiskEntry
)
157 PPARTENTRY PartEntry
;
163 Entry
= DiskEntry
->PartListHead
.Flink
;
164 while (Entry
!= &DiskEntry
->PartListHead
)
166 PartEntry
= CONTAINING_RECORD (Entry
,
170 if (PartEntry
->Unpartitioned
== TRUE
)
172 for (i
= 0; i
< 4; i
++)
174 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
179 for (i
= 0; i
< 4; i
++)
181 if (IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
))
183 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
185 else if (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
186 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
== 0ULL)
188 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
192 PartEntry
->PartInfo
[i
].PartitionNumber
= PartNumber
;
198 Entry
= Entry
->Flink
;
204 AddPartitionToList (ULONG DiskNumber
,
205 PDISKENTRY DiskEntry
,
206 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
)
208 PPARTENTRY PartEntry
;
212 for (i
= 0; i
< LayoutBuffer
->PartitionCount
; i
+= 4)
214 for (j
= 0; j
< 4; j
++)
216 if (LayoutBuffer
->PartitionEntry
[i
+j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
217 LayoutBuffer
->PartitionEntry
[i
+j
].PartitionLength
.QuadPart
!= 0ULL)
227 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
230 if (PartEntry
== NULL
)
235 RtlZeroMemory (PartEntry
,
238 PartEntry
->Unpartitioned
= FALSE
;
240 for (j
= 0; j
< 4; j
++)
242 RtlCopyMemory (&PartEntry
->PartInfo
[j
],
243 &LayoutBuffer
->PartitionEntry
[i
+j
],
244 sizeof(PARTITION_INFORMATION
));
247 if (IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
249 PartEntry
->FormatState
= Unformatted
;
251 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
252 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
253 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
254 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
) ||
255 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
256 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
259 if (CheckFatFormat())
261 PartEntry
->FormatState
= Preformatted
;
265 PartEntry
->FormatState
= Unformatted
;
268 PartEntry
->FormatState
= Preformatted
;
270 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_EXT2
)
273 if (CheckExt2Format())
275 PartEntry
->FormatState
= Preformatted
;
279 PartEntry
->FormatState
= Unformatted
;
282 PartEntry
->FormatState
= Preformatted
;
284 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
287 if (CheckNtfsFormat())
289 PartEntry
->FormatState
= Preformatted
;
291 else if (CheckHpfsFormat())
293 PartEntry
->FormatState
= Preformatted
;
297 PartEntry
->FormatState
= Unformatted
;
300 PartEntry
->FormatState
= Preformatted
;
304 PartEntry
->FormatState
= UnknownFormat
;
307 InsertTailList (&DiskEntry
->PartListHead
,
308 &PartEntry
->ListEntry
);
314 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry
)
316 ULONGLONG LastStartingOffset
;
317 ULONGLONG LastPartitionLength
;
318 ULONGLONG LastUnusedPartitionLength
;
319 PPARTENTRY PartEntry
;
320 PPARTENTRY NewPartEntry
;
325 if (IsListEmpty (&DiskEntry
->PartListHead
))
327 /* Create a partition table that represents the empty disk */
328 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
331 if (PartEntry
== NULL
)
334 RtlZeroMemory (PartEntry
,
337 PartEntry
->Unpartitioned
= TRUE
;
338 PartEntry
->UnpartitionedOffset
= 0ULL;
339 PartEntry
->UnpartitionedLength
= DiskEntry
->DiskSize
;
341 PartEntry
->FormatState
= Unformatted
;
343 InsertTailList (&DiskEntry
->PartListHead
,
344 &PartEntry
->ListEntry
);
348 /* Start partition at head 1, cylinder 0 */
349 LastStartingOffset
= DiskEntry
->TrackSize
;
350 LastPartitionLength
= 0ULL;
351 LastUnusedPartitionLength
= 0ULL;
354 Entry
= DiskEntry
->PartListHead
.Flink
;
355 while (Entry
!= &DiskEntry
->PartListHead
)
357 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
359 for (j
= 0; j
< 4; j
++)
361 if ((!IsContainerPartition (PartEntry
->PartInfo
[j
].PartitionType
)) &&
362 (PartEntry
->PartInfo
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
363 PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
!= 0LL))
365 LastUnusedPartitionLength
=
366 PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
-
367 (LastStartingOffset
+ LastPartitionLength
);
369 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
371 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
373 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
376 if (NewPartEntry
== NULL
)
379 RtlZeroMemory (NewPartEntry
,
382 NewPartEntry
->Unpartitioned
= TRUE
;
383 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
384 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
386 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
388 NewPartEntry
->FormatState
= Unformatted
;
390 /* Insert the table into the list */
391 InsertTailList (&PartEntry
->ListEntry
,
392 &NewPartEntry
->ListEntry
);
395 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
396 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
401 Entry
= Entry
->Flink
;
404 /* Check for trailing unpartitioned disk space */
405 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
407 /* Round-down to cylinder size */
408 LastUnusedPartitionLength
=
409 (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
))
410 & ~(DiskEntry
->CylinderSize
- 1);
412 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
414 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
416 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
419 if (NewPartEntry
== NULL
)
422 RtlZeroMemory (NewPartEntry
,
425 NewPartEntry
->Unpartitioned
= TRUE
;
426 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
427 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
429 /* Append the table to the list */
430 InsertTailList (&DiskEntry
->PartListHead
,
431 &NewPartEntry
->ListEntry
);
439 DiskIdentifierQueryRoutine(PWSTR ValueName
,
446 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
447 UNICODE_STRING NameU
;
449 if (ValueType
== REG_SZ
&&
450 ValueLength
== 20 * sizeof(WCHAR
))
452 NameU
.Buffer
= (PWCHAR
)ValueData
;
453 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
454 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
456 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
457 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
459 return STATUS_SUCCESS
;
461 return STATUS_UNSUCCESSFUL
;
466 DiskConfigurationDataQueryRoutine(PWSTR ValueName
,
473 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
474 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
475 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
478 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
479 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
480 return STATUS_UNSUCCESSFUL
;
482 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
483 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
484 /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
485 FullResourceDescriptor->PartialResourceList.Revision != 1)
486 return STATUS_UNSUCCESSFUL;*/
488 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
490 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
491 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
494 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
495 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
497 return STATUS_SUCCESS
;
499 return STATUS_UNSUCCESSFUL
;
504 SystemConfigurationDataQueryRoutine(PWSTR ValueName
,
511 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
512 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
515 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
516 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
517 return STATUS_UNSUCCESSFUL
;
519 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
520 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
521 /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
522 FullResourceDescriptor->PartialResourceList.Revision != 1)
523 return STATUS_UNSUCCESSFUL;*/
525 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
527 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
528 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
531 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
532 if (*Int13Drives
== NULL
)
533 return STATUS_NO_MEMORY
;
535 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
536 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
537 return STATUS_SUCCESS
;
539 return STATUS_UNSUCCESSFUL
;
541 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
544 EnumerateBiosDiskEntries(PPARTLIST PartList
)
546 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
551 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
552 PBIOSDISKENTRY BiosDiskEntry
;
554 memset(QueryTable
, 0, sizeof(QueryTable
));
556 QueryTable
[1].Name
= L
"Configuration Data";
557 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
559 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
560 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
564 if (!NT_SUCCESS(Status
))
566 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
573 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
574 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
579 if (!NT_SUCCESS(Status
))
584 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
585 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
590 if (NT_SUCCESS(Status
))
594 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
595 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
600 if (!NT_SUCCESS(Status
))
602 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
606 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
607 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
612 if (NT_SUCCESS(Status
))
614 QueryTable
[0].Name
= L
"Identifier";
615 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
616 QueryTable
[1].Name
= L
"Configuration Data";
617 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
621 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
622 if (BiosDiskEntry
== NULL
)
626 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
627 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
630 (PVOID
)BiosDiskEntry
,
632 if (!NT_SUCCESS(Status
))
634 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
637 BiosDiskEntry
->DiskNumber
= DiskCount
;
638 BiosDiskEntry
->Recognized
= FALSE
;
640 if (DiskCount
< Int13Drives
[0].NumberDrives
)
642 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
646 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
650 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
652 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
653 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
654 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
655 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
656 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
657 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
658 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
659 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
660 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
661 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
662 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
667 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
673 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
677 AddDiskToList (HANDLE FileHandle
,
681 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
682 DISK_GEOMETRY DiskGeometry
;
683 SCSI_ADDRESS ScsiAddress
;
684 PDISKENTRY DiskEntry
;
685 IO_STATUS_BLOCK Iosb
;
687 PPARTITION_SECTOR Mbr
;
689 LARGE_INTEGER FileOffset
;
690 WCHAR Identifier
[20];
694 PLIST_ENTRY ListEntry
;
695 PBIOSDISKENTRY BiosDiskEntry
;
697 Status
= NtDeviceIoControlFile (FileHandle
,
702 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
706 sizeof(DISK_GEOMETRY
));
707 if (!NT_SUCCESS (Status
))
712 if (DiskGeometry
.MediaType
!= FixedMedia
)
717 Status
= NtDeviceIoControlFile (FileHandle
,
722 IOCTL_SCSI_GET_ADDRESS
,
726 sizeof(SCSI_ADDRESS
));
727 if (!NT_SUCCESS(Status
))
732 Mbr
= (PARTITION_SECTOR
*) RtlAllocateHeap(ProcessHeap
,
734 DiskGeometry
.BytesPerSector
);
741 FileOffset
.QuadPart
= 0;
742 Status
= NtReadFile(FileHandle
,
748 DiskGeometry
.BytesPerSector
,
751 if (!NT_SUCCESS(Status
))
753 RtlFreeHeap(ProcessHeap
,
756 DPRINT1("NtReadFile failed, status=%x\n", Status
);
759 Signature
= Mbr
->Signature
;
761 /* Calculate the MBR checksum */
763 Buffer
= (PULONG
)Mbr
;
764 for (i
= 0; i
< 128; i
++)
766 Checksum
+= Buffer
[i
];
768 Checksum
= ~Checksum
+ 1;
770 RtlFreeHeap (ProcessHeap
,
774 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
775 DPRINT("Identifier: %S\n", Identifier
);
777 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
780 if (DiskEntry
== NULL
)
785 DiskEntry
->Checksum
= Checksum
;
786 DiskEntry
->Signature
= Signature
;
789 /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
790 DiskEntry
->Modified
= TRUE
;
792 DiskEntry
->BiosFound
= FALSE
;
794 ListEntry
= List
->BiosDiskListHead
.Flink
;
795 while(ListEntry
!= &List
->BiosDiskListHead
)
797 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
799 * Compare the size from bios and the reported size from driver.
800 * If we have more than one disk with a zero or with the same signatur
801 * we must create new signatures and reboot. After the reboot,
802 * it is possible to identify the disks.
804 if (BiosDiskEntry
->Signature
== Signature
&&
805 BiosDiskEntry
->Checksum
== Checksum
&&
806 !BiosDiskEntry
->Recognized
)
808 if (!DiskEntry
->BiosFound
)
810 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
811 DiskEntry
->BiosFound
= TRUE
;
812 BiosDiskEntry
->Recognized
= TRUE
;
818 ListEntry
= ListEntry
->Flink
;
821 if (!DiskEntry
->BiosFound
)
823 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
827 InitializeListHead (&DiskEntry
->PartListHead
);
829 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
830 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
831 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
832 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
834 DPRINT ("Cylinders %d\n", DiskEntry
->Cylinders
);
835 DPRINT ("TracksPerCylinder %d\n", DiskEntry
->TracksPerCylinder
);
836 DPRINT ("SectorsPerTrack %d\n", DiskEntry
->SectorsPerTrack
);
837 DPRINT ("BytesPerSector %d\n", DiskEntry
->BytesPerSector
);
839 DiskEntry
->TrackSize
=
840 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
841 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
842 DiskEntry
->CylinderSize
=
843 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
844 DiskEntry
->TrackSize
;
845 DiskEntry
->DiskSize
=
846 DiskGeometry
.Cylinders
.QuadPart
*
847 DiskEntry
->CylinderSize
;
849 DiskEntry
->DiskNumber
= DiskNumber
;
850 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
851 DiskEntry
->Bus
= ScsiAddress
.PathId
;
852 DiskEntry
->Id
= ScsiAddress
.TargetId
;
854 GetDriverName (DiskEntry
);
856 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, BiosDiskNumber
);
858 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
861 if (LayoutBuffer
== NULL
)
866 Status
= NtDeviceIoControlFile (FileHandle
,
871 IOCTL_DISK_GET_DRIVE_LAYOUT
,
876 if (NT_SUCCESS (Status
))
878 if (LayoutBuffer
->PartitionCount
== 0)
880 DiskEntry
->NewDisk
= TRUE
;
883 AddPartitionToList (DiskNumber
,
887 ScanForUnpartitionedDiskSpace (DiskEntry
);
890 RtlFreeHeap (ProcessHeap
,
897 CreatePartitionList (SHORT Left
,
903 OBJECT_ATTRIBUTES ObjectAttributes
;
904 SYSTEM_DEVICE_INFORMATION Sdi
;
905 IO_STATUS_BLOCK Iosb
;
909 WCHAR Buffer
[MAX_PATH
];
913 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
922 List
->Bottom
= Bottom
;
926 List
->TopDisk
= (ULONG
)-1;
927 List
->TopPartition
= (ULONG
)-1;
929 List
->CurrentDisk
= NULL
;
930 List
->CurrentPartition
= NULL
;
931 List
->CurrentPartitionNumber
= 0;
933 InitializeListHead (&List
->DiskListHead
);
934 InitializeListHead (&List
->BiosDiskListHead
);
936 EnumerateBiosDiskEntries(List
);
938 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
940 sizeof(SYSTEM_DEVICE_INFORMATION
),
942 if (!NT_SUCCESS (Status
))
944 RtlFreeHeap (ProcessHeap
, 0, List
);
948 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
951 L
"\\Device\\Harddisk%d\\Partition0",
953 RtlInitUnicodeString (&Name
,
956 InitializeObjectAttributes (&ObjectAttributes
,
962 Status
= NtOpenFile (&FileHandle
,
963 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
967 FILE_SYNCHRONOUS_IO_NONALERT
);
968 if (NT_SUCCESS(Status
))
970 AddDiskToList (FileHandle
,
978 AssignDriverLetters (List
);
981 List
->TopPartition
= 0;
983 /* Search for first usable disk and partition */
984 if (IsListEmpty (&List
->DiskListHead
))
986 List
->CurrentDisk
= NULL
;
987 List
->CurrentPartition
= NULL
;
988 List
->CurrentPartitionNumber
= 0;
993 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
997 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
999 List
->CurrentPartition
= 0;
1000 List
->CurrentPartitionNumber
= 0;
1004 List
->CurrentPartition
=
1005 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
1008 List
->CurrentPartitionNumber
= 0;
1017 DestroyPartitionList (PPARTLIST List
)
1019 PDISKENTRY DiskEntry
;
1020 PBIOSDISKENTRY BiosDiskEntry
;
1021 PPARTENTRY PartEntry
;
1024 /* Release disk and partition info */
1025 while (!IsListEmpty (&List
->DiskListHead
))
1027 Entry
= RemoveHeadList (&List
->DiskListHead
);
1028 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1030 /* Release driver name */
1031 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1033 /* Release partition array */
1034 while (!IsListEmpty (&DiskEntry
->PartListHead
))
1036 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
1037 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
1039 RtlFreeHeap (ProcessHeap
,
1044 /* Release disk entry */
1045 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
1048 /* release the bios disk info */
1049 while(!IsListEmpty(&List
->BiosDiskListHead
))
1051 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1052 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1054 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1057 /* Release list head */
1058 RtlFreeHeap (ProcessHeap
, 0, List
);
1063 PrintEmptyLine (PPARTLIST List
)
1070 Width
= List
->Right
- List
->Left
- 1;
1071 Height
= List
->Bottom
- List
->Top
- 2;
1074 coPos
.X
= List
->Left
+ 1;
1075 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1077 if (List
->Line
>= 0 && List
->Line
<= Height
)
1079 FillConsoleOutputAttribute (StdOutput
,
1080 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1085 FillConsoleOutputCharacterA (StdOutput
,
1096 PrintPartitionData (PPARTLIST List
,
1097 PDISKENTRY DiskEntry
,
1098 PPARTENTRY PartEntry
,
1101 CHAR LineBuffer
[128];
1107 LARGE_INTEGER PartSize
;
1112 Width
= List
->Right
- List
->Left
- 1;
1113 Height
= List
->Bottom
- List
->Top
- 2;
1116 coPos
.X
= List
->Left
+ 1;
1117 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1119 if (PartEntry
->Unpartitioned
== TRUE
)
1122 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1124 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1125 Unit
= MUIGetString(STRING_GB
);
1129 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1131 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1132 Unit
= MUIGetString(STRING_MB
);
1136 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1137 Unit
= MUIGetString(STRING_KB
);
1140 sprintf (LineBuffer
,
1141 MUIGetString(STRING_UNPSPACE
),
1147 /* Determine partition type */
1149 if (PartEntry
->New
== TRUE
)
1151 PartType
= MUIGetString(STRING_UNFORMATTED
);
1153 else if (PartEntry
->Unpartitioned
== FALSE
)
1155 if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_12
) ||
1156 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT_16
) ||
1157 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_HUGE
) ||
1158 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_XINT13
))
1162 else if ((PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32
) ||
1163 (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_FAT32_XINT13
))
1167 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_EXT2
)
1171 else if (PartEntry
->PartInfo
[PartNumber
].PartitionType
== PARTITION_IFS
)
1173 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1178 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1180 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1181 Unit
= MUIGetString(STRING_GB
);
1185 if (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1187 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1188 Unit
= MUIGetString(STRING_MB
);
1192 PartSize
.QuadPart
= (PartEntry
->PartInfo
[PartNumber
].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1193 Unit
= MUIGetString(STRING_KB
);
1196 if (PartType
== NULL
)
1198 sprintf (LineBuffer
,
1199 MUIGetString(STRING_HDDINFOUNK5
),
1200 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1201 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1202 PartEntry
->PartInfo
[PartNumber
].PartitionType
,
1208 sprintf (LineBuffer
,
1209 "%c%c %-24s %6lu %s",
1210 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1211 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1218 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1219 List
->CurrentPartition
== PartEntry
&&
1220 List
->CurrentPartitionNumber
== PartNumber
) ?
1221 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1222 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1224 if (List
->Line
>= 0 && List
->Line
<= Height
)
1226 FillConsoleOutputCharacterA (StdOutput
,
1234 if (List
->Line
>= 0 && List
->Line
<= Height
)
1236 FillConsoleOutputAttribute (StdOutput
,
1244 if (List
->Line
>= 0 && List
->Line
<= Height
)
1246 WriteConsoleOutputCharacterA (StdOutput
,
1248 min (strlen (LineBuffer
), Width
),
1257 PrintDiskData (PPARTLIST List
,
1258 PDISKENTRY DiskEntry
)
1260 PPARTENTRY PartEntry
;
1261 CHAR LineBuffer
[128];
1266 ULARGE_INTEGER DiskSize
;
1270 Width
= List
->Right
- List
->Left
- 1;
1271 Height
= List
->Bottom
- List
->Top
- 2;
1274 coPos
.X
= List
->Left
+ 1;
1275 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1278 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1280 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1281 Unit
= MUIGetString(STRING_GB
);
1286 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1287 if (DiskSize
.QuadPart
== 0)
1288 DiskSize
.QuadPart
= 1;
1289 Unit
= MUIGetString(STRING_MB
);
1292 if (DiskEntry
->DriverName
.Length
> 0)
1294 sprintf (LineBuffer
,
1295 MUIGetString(STRING_HDINFOPARTSELECT
),
1298 DiskEntry
->DiskNumber
,
1302 DiskEntry
->DriverName
.Buffer
);
1306 sprintf (LineBuffer
,
1307 MUIGetString(STRING_HDDINFOUNK6
),
1310 DiskEntry
->DiskNumber
,
1315 if (List
->Line
>= 0 && List
->Line
<= Height
)
1317 FillConsoleOutputAttribute (StdOutput
,
1318 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1323 FillConsoleOutputCharacterA (StdOutput
,
1331 if (List
->Line
>= 0 && List
->Line
<= Height
)
1333 WriteConsoleOutputCharacterA (StdOutput
,
1335 min ((USHORT
)strlen (LineBuffer
), Width
- 2),
1341 /* Print separator line */
1342 PrintEmptyLine (List
);
1344 /* Print partition lines*/
1345 LIST_FOR_EACH(PartEntry
, &DiskEntry
->PartListHead
, PARTENTRY
, ListEntry
)
1347 /* Print disk entry */
1350 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1352 PrintPartitionData (List
,
1360 /* Print separator line */
1361 PrintEmptyLine (List
);
1366 DrawPartitionList (PPARTLIST List
)
1368 PLIST_ENTRY Entry
, Entry2
;
1369 PDISKENTRY DiskEntry
;
1370 PPARTENTRY PartEntry
= NULL
;
1374 SHORT CurrentDiskLine
;
1375 SHORT CurrentPartLine
;
1377 BOOL CurrentPartLineFound
= FALSE
;
1378 BOOL CurrentDiskLineFound
= FALSE
;
1380 /* Calculate the line of the current disk and partition */
1381 CurrentDiskLine
= 0;
1382 CurrentPartLine
= 0;
1384 Entry
= List
->DiskListHead
.Flink
;
1385 while (Entry
!= &List
->DiskListHead
)
1387 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1389 if (CurrentPartLineFound
== FALSE
)
1391 CurrentPartLine
+= 2;
1393 Entry2
= DiskEntry
->PartListHead
.Flink
;
1394 while (Entry2
!= &DiskEntry
->PartListHead
)
1396 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1397 if (PartEntry
== List
->CurrentPartition
)
1399 CurrentPartLineFound
= TRUE
;
1401 Entry2
= Entry2
->Flink
;
1402 if (CurrentPartLineFound
== FALSE
)
1408 if (DiskEntry
== List
->CurrentDisk
)
1410 CurrentDiskLineFound
= TRUE
;
1412 Entry
= Entry
->Flink
;
1413 if (Entry
!= &List
->DiskListHead
)
1415 if (CurrentDiskLineFound
== FALSE
)
1418 CurrentDiskLine
= CurrentPartLine
;
1428 /* If it possible, make the disk name visible */
1429 if (CurrentPartLine
< List
->Offset
)
1431 List
->Offset
= CurrentPartLine
;
1433 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1435 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1437 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1439 List
->Offset
= CurrentDiskLine
;
1443 /* draw upper left corner */
1444 coPos
.X
= List
->Left
;
1445 coPos
.Y
= List
->Top
;
1446 FillConsoleOutputCharacterA (StdOutput
,
1452 /* draw upper edge */
1453 coPos
.X
= List
->Left
+ 1;
1454 coPos
.Y
= List
->Top
;
1455 if (List
->Offset
== 0)
1457 FillConsoleOutputCharacterA (StdOutput
,
1459 List
->Right
- List
->Left
- 1,
1465 FillConsoleOutputCharacterA (StdOutput
,
1467 List
->Right
- List
->Left
- 5,
1470 coPos
.X
= List
->Right
- 5;
1471 WriteConsoleOutputCharacterA (StdOutput
,
1476 coPos
.X
= List
->Right
- 2;
1477 FillConsoleOutputCharacterA (StdOutput
,
1484 /* draw upper right corner */
1485 coPos
.X
= List
->Right
;
1486 coPos
.Y
= List
->Top
;
1487 FillConsoleOutputCharacterA (StdOutput
,
1493 /* draw left and right edge */
1494 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1496 coPos
.X
= List
->Left
;
1498 FillConsoleOutputCharacterA (StdOutput
,
1504 coPos
.X
= List
->Right
;
1505 FillConsoleOutputCharacterA (StdOutput
,
1512 /* draw lower left corner */
1513 coPos
.X
= List
->Left
;
1514 coPos
.Y
= List
->Bottom
;
1515 FillConsoleOutputCharacterA (StdOutput
,
1521 /* draw lower edge */
1522 coPos
.X
= List
->Left
+ 1;
1523 coPos
.Y
= List
->Bottom
;
1524 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1526 FillConsoleOutputCharacterA (StdOutput
,
1528 List
->Right
- List
->Left
- 1,
1534 FillConsoleOutputCharacterA (StdOutput
,
1536 List
->Right
- List
->Left
- 5,
1539 coPos
.X
= List
->Right
- 5;
1540 WriteConsoleOutputCharacterA (StdOutput
,
1541 "(\x19)", // "(down)"
1545 coPos
.X
= List
->Right
- 2;
1546 FillConsoleOutputCharacterA (StdOutput
,
1553 /* draw lower right corner */
1554 coPos
.X
= List
->Right
;
1555 coPos
.Y
= List
->Bottom
;
1556 FillConsoleOutputCharacterA (StdOutput
,
1562 /* print list entries */
1563 List
->Line
= - List
->Offset
;
1565 LIST_FOR_EACH(DiskEntry
, &List
->DiskListHead
, DISKENTRY
, ListEntry
)
1567 /* Print disk entry */
1568 PrintDiskData (List
,
1575 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1577 PDISKENTRY DiskEntry
;
1578 PPARTENTRY PartEntry
;
1583 /* Check for empty disks */
1584 if (IsListEmpty (&List
->DiskListHead
))
1587 /* Check for first usable entry on next disk */
1588 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1589 while (Entry1
!= &List
->DiskListHead
)
1591 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1593 if (DiskEntry
->DiskNumber
== DiskNumber
)
1595 Entry2
= DiskEntry
->PartListHead
.Flink
;
1596 while (Entry2
!= &DiskEntry
->PartListHead
)
1598 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1600 for (i
= 0; i
< 4; i
++)
1602 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1604 List
->CurrentDisk
= DiskEntry
;
1605 List
->CurrentPartition
= PartEntry
;
1606 List
->CurrentPartitionNumber
= i
;
1607 DrawPartitionList (List
);
1611 Entry2
= Entry2
->Flink
;
1615 Entry1
= Entry1
->Flink
;
1622 ScrollDownPartitionList (PPARTLIST List
)
1624 PDISKENTRY DiskEntry
;
1625 PPARTENTRY PartEntry
;
1630 /* Check for empty disks */
1631 if (IsListEmpty (&List
->DiskListHead
))
1634 /* Check for next usable entry on current disk */
1635 if (List
->CurrentPartition
!= NULL
)
1637 Entry2
= &List
->CurrentPartition
->ListEntry
;
1638 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1640 /* Check if we can move inside primary partitions */
1641 for (i
= List
->CurrentPartitionNumber
+ 1; i
< 4; i
++)
1643 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1649 /* We're out of partitions in the current partition table.
1650 Try to move to the next one if possible. */
1651 Entry2
= Entry2
->Flink
;
1655 /* Just advance to the next partition */
1656 List
->CurrentPartitionNumber
= i
;
1657 DrawPartitionList (List
);
1661 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1663 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1665 // if (PartEntry->HidePartEntry == FALSE)
1667 List
->CurrentPartition
= PartEntry
;
1668 List
->CurrentPartitionNumber
= 0;
1669 DrawPartitionList (List
);
1672 Entry2
= Entry2
->Flink
;
1676 /* Check for first usable entry on next disk */
1677 if (List
->CurrentDisk
!= NULL
)
1679 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1680 while (Entry1
!= &List
->DiskListHead
)
1682 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1684 Entry2
= DiskEntry
->PartListHead
.Flink
;
1685 while (Entry2
!= &DiskEntry
->PartListHead
)
1687 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1689 // if (PartEntry->HidePartEntry == FALSE)
1691 List
->CurrentDisk
= DiskEntry
;
1692 List
->CurrentPartition
= PartEntry
;
1693 List
->CurrentPartitionNumber
= 0;
1694 DrawPartitionList (List
);
1698 Entry2
= Entry2
->Flink
;
1701 Entry1
= Entry1
->Flink
;
1708 ScrollUpPartitionList (PPARTLIST List
)
1710 PDISKENTRY DiskEntry
;
1711 PPARTENTRY PartEntry
;
1716 /* Check for empty disks */
1717 if (IsListEmpty (&List
->DiskListHead
))
1720 /* check for previous usable entry on current disk */
1721 if (List
->CurrentPartition
!= NULL
)
1723 Entry2
= &List
->CurrentPartition
->ListEntry
;
1724 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1726 /* Check if we can move inside primary partitions */
1727 if (List
->CurrentPartitionNumber
> 0)
1729 /* Find a previous partition */
1730 for (i
= List
->CurrentPartitionNumber
- 1; i
> 0; i
--)
1732 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1736 /* Move to it and return */
1737 List
->CurrentPartitionNumber
= i
;
1738 DrawPartitionList (List
);
1742 /* Move to the previous entry */
1743 Entry2
= Entry2
->Blink
;
1745 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1747 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1749 // if (PartEntry->HidePartEntry == FALSE)
1751 List
->CurrentPartition
= PartEntry
;
1753 /* Find last existing partition in the table */
1754 for (i
= 3; i
> 0; i
--)
1756 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1761 List
->CurrentPartitionNumber
= i
;
1763 /* Draw partition list and return */
1764 DrawPartitionList (List
);
1767 Entry2
= Entry2
->Blink
;
1772 /* check for last usable entry on previous disk */
1773 if (List
->CurrentDisk
!= NULL
)
1775 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1776 while (Entry1
!= &List
->DiskListHead
)
1778 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1780 Entry2
= DiskEntry
->PartListHead
.Blink
;
1781 while (Entry2
!= &DiskEntry
->PartListHead
)
1783 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1785 // if (PartEntry->HidePartEntry == FALSE)
1787 List
->CurrentDisk
= DiskEntry
;
1788 List
->CurrentPartition
= PartEntry
;
1790 /* Find last existing partition in the table */
1791 for (i
= 3; i
> 0; i
--)
1793 if (PartEntry
->PartInfo
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
1798 List
->CurrentPartitionNumber
= i
;
1800 /* Draw partition list and return */
1801 DrawPartitionList (List
);
1805 Entry2
= Entry2
->Blink
;
1808 Entry1
= Entry1
->Blink
;
1815 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1816 PPARTENTRY CurrentEntry
)
1818 PPARTENTRY PrevEntry
;
1821 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1824 Entry
= CurrentEntry
->ListEntry
.Blink
;
1825 while (Entry
!= &DiskEntry
->PartListHead
)
1827 PrevEntry
= CONTAINING_RECORD (Entry
,
1830 if (PrevEntry
->Unpartitioned
== FALSE
)
1833 Entry
= Entry
->Blink
;
1841 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1842 PPARTENTRY CurrentEntry
)
1844 PPARTENTRY NextEntry
;
1847 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1850 Entry
= CurrentEntry
->ListEntry
.Flink
;
1851 while (Entry
!= &DiskEntry
->PartListHead
)
1853 NextEntry
= CONTAINING_RECORD (Entry
,
1856 if (NextEntry
->Unpartitioned
== FALSE
)
1859 Entry
= Entry
->Flink
;
1867 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1868 PPARTENTRY PartEntry
)
1870 PPARTENTRY PrevPartEntry
;
1872 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1874 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1877 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1878 return PrevPartEntry
;
1886 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1887 PPARTENTRY PartEntry
)
1889 PPARTENTRY NextPartEntry
;
1891 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1893 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1896 if (NextPartEntry
->Unpartitioned
== TRUE
)
1897 return NextPartEntry
;
1905 CreateNewPartition (PPARTLIST List
,
1906 ULONGLONG PartitionSize
,
1909 PDISKENTRY DiskEntry
;
1910 PPARTENTRY PartEntry
;
1911 PPARTENTRY PrevPartEntry
;
1912 PPARTENTRY NextPartEntry
;
1913 PPARTENTRY NewPartEntry
;
1916 List
->CurrentDisk
== NULL
||
1917 List
->CurrentPartition
== NULL
||
1918 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1923 DiskEntry
= List
->CurrentDisk
;
1924 PartEntry
= List
->CurrentPartition
;
1926 if (AutoCreate
== TRUE
||
1927 PartitionSize
== PartEntry
->UnpartitionedLength
)
1929 /* Convert current entry to 'new (unformatted)' */
1930 PartEntry
->FormatState
= Unformatted
;
1931 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1932 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1933 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1934 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1935 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1936 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1937 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1938 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1939 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1940 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1942 /* Get previous and next partition entries */
1943 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1945 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1948 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1950 /* Current entry is in the middle of the list */
1952 /* Copy previous container partition data to current entry */
1953 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1954 &PrevPartEntry
->PartInfo
[1],
1955 sizeof(PARTITION_INFORMATION
));
1956 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1958 /* Update previous container partition data */
1960 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1961 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1963 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1965 /* Special case - previous partition is first partition */
1966 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1967 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1971 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1972 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1975 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1977 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1979 /* Current entry is the first entry */
1982 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1984 /* Current entry is the last entry */
1986 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1987 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1989 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1991 /* Special case - previous partition is first partition */
1992 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1993 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1997 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1998 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2001 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2002 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2003 (1024LL * 255LL * 63LL * 512LL))
2005 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2009 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2012 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2013 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2016 PartEntry
->AutoCreate
= AutoCreate
;
2017 PartEntry
->New
= TRUE
;
2018 PartEntry
->Unpartitioned
= FALSE
;
2019 PartEntry
->UnpartitionedOffset
= 0ULL;
2020 PartEntry
->UnpartitionedLength
= 0ULL;
2024 /* Insert an initialize a new partition entry */
2025 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
2028 if (NewPartEntry
== NULL
)
2031 RtlZeroMemory (NewPartEntry
,
2034 /* Insert the new entry into the list */
2035 InsertTailList (&PartEntry
->ListEntry
,
2036 &NewPartEntry
->ListEntry
);
2038 NewPartEntry
->New
= TRUE
;
2040 NewPartEntry
->FormatState
= Unformatted
;
2041 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
2042 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
2043 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
2044 PartitionSize
- DiskEntry
->TrackSize
;
2045 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
2046 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
2047 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2048 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2049 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
2050 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
2052 /* Get previous and next partition entries */
2053 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2055 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2058 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2060 /* Current entry is in the middle of the list */
2062 /* Copy previous container partition data to current entry */
2063 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
2064 &PrevPartEntry
->PartInfo
[1],
2065 sizeof(PARTITION_INFORMATION
));
2066 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2068 /* Update previous container partition data */
2070 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2071 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2073 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2075 /* Special case - previous partition is first partition */
2076 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2077 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2081 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2082 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2085 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2087 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2089 /* Current entry is the first entry */
2092 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2094 /* Current entry is the last entry */
2096 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2097 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2099 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2101 /* Special case - previous partition is first partition */
2102 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2103 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2107 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2108 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2111 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2112 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2113 (1024LL * 255LL * 63LL * 512LL))
2115 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2119 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2122 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2123 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2126 /* Update offset and size of the remaining unpartitioned disk space */
2127 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
2128 PartEntry
->UnpartitionedLength
-= PartitionSize
;
2131 DiskEntry
->Modified
= TRUE
;
2133 UpdatePartitionNumbers (DiskEntry
);
2135 AssignDriverLetters (List
);
2140 DeleteCurrentPartition (PPARTLIST List
)
2142 PDISKENTRY DiskEntry
;
2143 PPARTENTRY PartEntry
;
2144 PPARTENTRY PrevPartEntry
;
2145 PPARTENTRY NextPartEntry
;
2148 List
->CurrentDisk
== NULL
||
2149 List
->CurrentPartition
== NULL
||
2150 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2155 DiskEntry
= List
->CurrentDisk
;
2156 PartEntry
= List
->CurrentPartition
;
2158 /* Adjust container partition entries */
2160 /* Get previous and next partition entries */
2161 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2163 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2166 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2168 /* Current entry is in the middle of the list */
2171 * The first extended partition can not be deleted
2172 * as long as other extended partitions are present.
2174 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2177 /* Copy previous container partition data to current entry */
2178 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
2179 &PartEntry
->PartInfo
[1],
2180 sizeof(PARTITION_INFORMATION
));
2181 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2183 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2186 * A primary partition can not be deleted as long as
2187 * extended partitions are present.
2191 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2193 /* Current entry is the last entry */
2194 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
2195 sizeof(PARTITION_INFORMATION
));
2196 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2200 /* Adjust unpartitioned disk space entries */
2202 /* Get pointer to previous and next unpartitioned entries */
2203 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
2206 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
2209 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2211 /* Merge previous, current and next unpartitioned entry */
2213 /* Adjust the previous entries length */
2214 PrevPartEntry
->UnpartitionedLength
+=
2215 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2216 NextPartEntry
->UnpartitionedLength
);
2218 /* Remove the current entry */
2219 RemoveEntryList (&PartEntry
->ListEntry
);
2220 RtlFreeHeap (ProcessHeap
,
2224 /* Remove the next entry */
2225 RemoveEntryList (&NextPartEntry
->ListEntry
);
2226 RtlFreeHeap (ProcessHeap
,
2230 /* Update current partition */
2231 List
->CurrentPartition
= PrevPartEntry
;
2233 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2235 /* Merge current and previous unpartitioned entry */
2237 /* Adjust the previous entries length */
2238 PrevPartEntry
->UnpartitionedLength
+=
2239 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2241 /* Remove the current entry */
2242 RemoveEntryList (&PartEntry
->ListEntry
);
2243 RtlFreeHeap (ProcessHeap
,
2247 /* Update current partition */
2248 List
->CurrentPartition
= PrevPartEntry
;
2250 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2252 /* Merge current and next unpartitioned entry */
2254 /* Adjust the next entries offset and length */
2255 NextPartEntry
->UnpartitionedOffset
=
2256 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2257 NextPartEntry
->UnpartitionedLength
+=
2258 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2260 /* Remove the current entry */
2261 RemoveEntryList (&PartEntry
->ListEntry
);
2262 RtlFreeHeap (ProcessHeap
,
2266 /* Update current partition */
2267 List
->CurrentPartition
= NextPartEntry
;
2271 /* Nothing to merge but change current entry */
2272 PartEntry
->New
= FALSE
;
2273 PartEntry
->Unpartitioned
= TRUE
;
2274 PartEntry
->UnpartitionedOffset
=
2275 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2276 PartEntry
->UnpartitionedLength
=
2277 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2279 /* Wipe the partition table */
2280 RtlZeroMemory (&PartEntry
->PartInfo
,
2281 sizeof(PartEntry
->PartInfo
));
2284 DiskEntry
->Modified
= TRUE
;
2286 UpdatePartitionNumbers (DiskEntry
);
2288 AssignDriverLetters (List
);
2293 CheckActiveBootPartition (PPARTLIST List
)
2295 PDISKENTRY DiskEntry
;
2296 PPARTENTRY PartEntry
;
2298 /* Check for empty disk list */
2299 if (IsListEmpty (&List
->DiskListHead
))
2301 List
->ActiveBootDisk
= NULL
;
2302 List
->ActiveBootPartition
= NULL
;
2307 if (List
->ActiveBootDisk
!= NULL
&&
2308 List
->ActiveBootPartition
!= NULL
)
2310 /* We already have an active boot partition */
2315 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
2319 /* Check for empty partition list */
2320 if (IsListEmpty (&DiskEntry
->PartListHead
))
2322 List
->ActiveBootDisk
= NULL
;
2323 List
->ActiveBootPartition
= NULL
;
2327 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
2331 /* Set active boot partition */
2332 if ((DiskEntry
->NewDisk
== TRUE
) ||
2333 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2334 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2335 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2336 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2338 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2339 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2340 DiskEntry
->Modified
= TRUE
;
2343 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2344 List
->ActiveBootDisk
= DiskEntry
;
2345 List
->ActiveBootPartition
= PartEntry
;
2350 CheckForLinuxFdiskPartitions (PPARTLIST List
)
2352 PDISKENTRY DiskEntry
;
2353 PPARTENTRY PartEntry
;
2356 ULONG PartitionCount
;
2359 Entry1
= List
->DiskListHead
.Flink
;
2360 while (Entry1
!= &List
->DiskListHead
)
2362 DiskEntry
= CONTAINING_RECORD (Entry1
,
2366 Entry2
= DiskEntry
->PartListHead
.Flink
;
2367 while (Entry2
!= &DiskEntry
->PartListHead
)
2369 PartEntry
= CONTAINING_RECORD (Entry2
,
2373 if (PartEntry
->Unpartitioned
== FALSE
)
2377 for (i
= 0; i
< 4; i
++)
2379 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
2380 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2386 if (PartitionCount
> 1)
2392 Entry2
= Entry2
->Flink
;
2395 Entry1
= Entry1
->Flink
;
2403 WritePartitionsToDisk (PPARTLIST List
)
2405 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2406 OBJECT_ATTRIBUTES ObjectAttributes
;
2407 IO_STATUS_BLOCK Iosb
;
2408 WCHAR SrcPath
[MAX_PATH
];
2409 WCHAR DstPath
[MAX_PATH
];
2410 UNICODE_STRING Name
;
2412 PDISKENTRY DiskEntry1
;
2413 PDISKENTRY DiskEntry2
;
2414 PPARTENTRY PartEntry
;
2417 ULONG PartitionCount
;
2418 ULONG DriveLayoutSize
;
2427 Entry1
= List
->DiskListHead
.Flink
;
2428 while (Entry1
!= &List
->DiskListHead
)
2430 DiskEntry1
= CONTAINING_RECORD (Entry1
,
2434 if (DiskEntry1
->Modified
== TRUE
)
2436 /* Count partitioned entries */
2438 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2439 while (Entry2
!= &DiskEntry1
->PartListHead
)
2441 PartEntry
= CONTAINING_RECORD (Entry2
,
2444 if (PartEntry
->Unpartitioned
== FALSE
)
2446 PartitionCount
+= 4;
2449 Entry2
= Entry2
->Flink
;
2451 if (PartitionCount
== 0)
2453 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2454 ((4 - 1) * sizeof (PARTITION_INFORMATION
));
2458 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2459 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2461 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
2464 if (DriveLayout
== NULL
)
2466 DPRINT1 ("RtlAllocateHeap() failed\n");
2470 RtlZeroMemory (DriveLayout
,
2473 if (PartitionCount
== 0)
2475 /* delete all partitions in the mbr */
2476 DriveLayout
->PartitionCount
= 4;
2477 for (Index
= 0; Index
< 4; Index
++)
2479 DriveLayout
->PartitionEntry
[Index
].RewritePartition
= TRUE
;
2484 DriveLayout
->PartitionCount
= PartitionCount
;
2487 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2488 while (Entry2
!= &DiskEntry1
->PartListHead
)
2490 PartEntry
= CONTAINING_RECORD (Entry2
,
2493 if (PartEntry
->Unpartitioned
== FALSE
)
2495 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2496 &PartEntry
->PartInfo
[0],
2497 4 * sizeof (PARTITION_INFORMATION
));
2501 Entry2
= Entry2
->Flink
;
2504 if (DiskEntry1
->Signature
== 0)
2506 LARGE_INTEGER SystemTime
;
2507 TIME_FIELDS TimeFields
;
2509 Buffer
= (PUCHAR
)&DiskEntry1
->Signature
;
2513 NtQuerySystemTime (&SystemTime
);
2514 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
2516 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
2517 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
2518 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
2519 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
2521 if (DiskEntry1
->Signature
== 0)
2526 /* check if the signature already exist */
2528 * Check also signatures from disks, which are
2529 * not visible (bootable) by the bios.
2531 Entry2
= List
->DiskListHead
.Flink
;
2532 while (Entry2
!= &List
->DiskListHead
)
2534 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
2535 if (DiskEntry1
!= DiskEntry2
&&
2536 DiskEntry1
->Signature
== DiskEntry2
->Signature
)
2540 Entry2
= Entry2
->Flink
;
2542 if (Entry2
== &List
->DiskListHead
)
2548 /* set one partition entry to dirty, this will update the signature */
2549 DriveLayout
->PartitionEntry
[0].RewritePartition
= TRUE
;
2553 DriveLayout
->Signature
= DiskEntry1
->Signature
;
2557 L
"\\Device\\Harddisk%d\\Partition0",
2558 DiskEntry1
->DiskNumber
);
2559 RtlInitUnicodeString (&Name
,
2561 InitializeObjectAttributes (&ObjectAttributes
,
2567 Status
= NtOpenFile (&FileHandle
,
2572 FILE_SYNCHRONOUS_IO_NONALERT
);
2574 if (!NT_SUCCESS (Status
))
2576 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2580 Status
= NtDeviceIoControlFile (FileHandle
,
2585 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2590 if (!NT_SUCCESS (Status
))
2592 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2593 NtClose (FileHandle
);
2597 RtlFreeHeap (ProcessHeap
,
2601 NtClose (FileHandle
);
2603 /* Install MBR code if the disk is new */
2604 if (DiskEntry1
->NewDisk
== TRUE
&&
2605 DiskEntry1
->BiosDiskNumber
== 0)
2607 wcscpy (SrcPath
, SourceRootPath
.Buffer
);
2608 wcscat (SrcPath
, L
"\\loader\\dosmbr.bin");
2610 DPRINT ("Install MBR bootcode: %S ==> %S\n",
2613 /* Install MBR bootcode */
2614 Status
= InstallMbrBootCodeToDisk (SrcPath
,
2616 if (!NT_SUCCESS (Status
))
2618 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
2623 DiskEntry1
->NewDisk
= FALSE
;
2627 Entry1
= Entry1
->Flink
;
2633 BOOL
SetMountedDeviceValues(PPARTLIST List
)
2635 PLIST_ENTRY Entry1
, Entry2
;
2636 PDISKENTRY DiskEntry
;
2637 PPARTENTRY PartEntry
;
2644 Entry1
= List
->DiskListHead
.Flink
;
2645 while (Entry1
!= &List
->DiskListHead
)
2647 DiskEntry
= CONTAINING_RECORD (Entry1
,
2651 Entry2
= DiskEntry
->PartListHead
.Flink
;
2652 while (Entry2
!= &DiskEntry
->PartListHead
)
2654 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2655 if (!PartEntry
->Unpartitioned
&& PartEntry
->DriveLetter
)
2657 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
, DiskEntry
->Signature
, PartEntry
->PartInfo
[0].StartingOffset
))
2662 Entry2
= Entry2
->Flink
;
2664 Entry1
= Entry1
->Flink
;