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
->DiskSize
=
840 DiskGeometry
.Cylinders
.QuadPart
*
841 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
842 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
843 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
844 DiskEntry
->CylinderSize
=
845 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
846 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
847 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
848 DiskEntry
->TrackSize
=
849 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
850 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
852 DiskEntry
->DiskNumber
= DiskNumber
;
853 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
854 DiskEntry
->Bus
= ScsiAddress
.PathId
;
855 DiskEntry
->Id
= ScsiAddress
.TargetId
;
857 GetDriverName (DiskEntry
);
859 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, BiosDiskNumber
);
861 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
864 if (LayoutBuffer
== NULL
)
869 Status
= NtDeviceIoControlFile (FileHandle
,
874 IOCTL_DISK_GET_DRIVE_LAYOUT
,
879 if (NT_SUCCESS (Status
))
881 if (LayoutBuffer
->PartitionCount
== 0)
883 DiskEntry
->NewDisk
= TRUE
;
886 AddPartitionToList (DiskNumber
,
890 ScanForUnpartitionedDiskSpace (DiskEntry
);
893 RtlFreeHeap (ProcessHeap
,
900 CreatePartitionList (SHORT Left
,
906 OBJECT_ATTRIBUTES ObjectAttributes
;
907 SYSTEM_DEVICE_INFORMATION Sdi
;
908 IO_STATUS_BLOCK Iosb
;
912 WCHAR Buffer
[MAX_PATH
];
916 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
925 List
->Bottom
= Bottom
;
929 List
->TopDisk
= (ULONG
)-1;
930 List
->TopPartition
= (ULONG
)-1;
932 List
->CurrentDisk
= NULL
;
933 List
->CurrentPartition
= NULL
;
935 InitializeListHead (&List
->DiskListHead
);
936 InitializeListHead (&List
->BiosDiskListHead
);
938 EnumerateBiosDiskEntries(List
);
940 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
942 sizeof(SYSTEM_DEVICE_INFORMATION
),
944 if (!NT_SUCCESS (Status
))
946 RtlFreeHeap (ProcessHeap
, 0, List
);
950 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
953 L
"\\Device\\Harddisk%d\\Partition0",
955 RtlInitUnicodeString (&Name
,
958 InitializeObjectAttributes (&ObjectAttributes
,
964 Status
= NtOpenFile (&FileHandle
,
965 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
969 FILE_SYNCHRONOUS_IO_NONALERT
);
970 if (NT_SUCCESS(Status
))
972 AddDiskToList (FileHandle
,
980 AssignDriverLetters (List
);
983 List
->TopPartition
= 0;
985 /* Search for first usable disk and partition */
986 if (IsListEmpty (&List
->DiskListHead
))
988 List
->CurrentDisk
= NULL
;
989 List
->CurrentPartition
= NULL
;
994 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
998 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
1000 List
->CurrentPartition
= 0;
1004 List
->CurrentPartition
=
1005 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
1016 DestroyPartitionList (PPARTLIST List
)
1018 PDISKENTRY DiskEntry
;
1019 PBIOSDISKENTRY BiosDiskEntry
;
1020 PPARTENTRY PartEntry
;
1023 /* Release disk and partition info */
1024 while (!IsListEmpty (&List
->DiskListHead
))
1026 Entry
= RemoveHeadList (&List
->DiskListHead
);
1027 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1029 /* Release driver name */
1030 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1032 /* Release partition array */
1033 while (!IsListEmpty (&DiskEntry
->PartListHead
))
1035 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
1036 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
1038 RtlFreeHeap (ProcessHeap
,
1043 /* Release disk entry */
1044 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
1047 /* release the bios disk info */
1048 while(!IsListEmpty(&List
->BiosDiskListHead
))
1050 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1051 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1053 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1056 /* Release list head */
1057 RtlFreeHeap (ProcessHeap
, 0, List
);
1062 PrintEmptyLine (PPARTLIST List
)
1069 Width
= List
->Right
- List
->Left
- 1;
1070 Height
= List
->Bottom
- List
->Top
- 2;
1073 coPos
.X
= List
->Left
+ 1;
1074 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1076 if (List
->Line
>= 0 && List
->Line
<= Height
)
1078 FillConsoleOutputAttribute (StdOutput
,
1079 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1084 FillConsoleOutputCharacterA (StdOutput
,
1095 PrintPartitionData (PPARTLIST List
,
1096 PDISKENTRY DiskEntry
,
1097 PPARTENTRY PartEntry
)
1099 CHAR LineBuffer
[128];
1105 LARGE_INTEGER PartSize
;
1110 Width
= List
->Right
- List
->Left
- 1;
1111 Height
= List
->Bottom
- List
->Top
- 2;
1114 coPos
.X
= List
->Left
+ 1;
1115 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1117 if (PartEntry
->Unpartitioned
== TRUE
)
1120 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1122 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1123 Unit
= MUIGetString(STRING_GB
);
1127 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1129 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1130 Unit
= MUIGetString(STRING_MB
);
1134 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1135 Unit
= MUIGetString(STRING_KB
);
1138 sprintf (LineBuffer
,
1139 MUIGetString(STRING_UNPSPACE
),
1145 /* Determine partition type */
1147 if (PartEntry
->New
== TRUE
)
1149 PartType
= MUIGetString(STRING_UNFORMATTED
);
1151 else if (PartEntry
->Unpartitioned
== FALSE
)
1153 if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
1154 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
1155 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
1156 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
))
1160 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
1161 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
1165 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_EXT2
)
1169 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
1171 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1176 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1178 PartSize
.QuadPart
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1179 Unit
= MUIGetString(STRING_GB
);
1183 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1185 PartSize
.QuadPart
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1186 Unit
= MUIGetString(STRING_MB
);
1190 PartSize
.QuadPart
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1191 Unit
= MUIGetString(STRING_KB
);
1194 if (PartType
== NULL
)
1196 sprintf (LineBuffer
,
1197 MUIGetString(STRING_HDDINFOUNK5
),
1198 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1199 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1200 PartEntry
->PartInfo
[0].PartitionType
,
1206 sprintf (LineBuffer
,
1207 "%c%c %-24s %6lu %s",
1208 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1209 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1216 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1217 List
->CurrentPartition
== PartEntry
) ?
1218 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1219 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1221 if (List
->Line
>= 0 && List
->Line
<= Height
)
1223 FillConsoleOutputCharacterA (StdOutput
,
1231 if (List
->Line
>= 0 && List
->Line
<= Height
)
1233 FillConsoleOutputAttribute (StdOutput
,
1241 if (List
->Line
>= 0 && List
->Line
<= Height
)
1243 WriteConsoleOutputCharacterA (StdOutput
,
1245 min (strlen (LineBuffer
), Width
),
1254 PrintDiskData (PPARTLIST List
,
1255 PDISKENTRY DiskEntry
)
1257 PPARTENTRY PartEntry
;
1258 CHAR LineBuffer
[128];
1263 ULARGE_INTEGER DiskSize
;
1266 Width
= List
->Right
- List
->Left
- 1;
1267 Height
= List
->Bottom
- List
->Top
- 2;
1270 coPos
.X
= List
->Left
+ 1;
1271 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1274 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1276 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1277 Unit
= MUIGetString(STRING_GB
);
1282 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1283 if (DiskSize
.QuadPart
== 0)
1284 DiskSize
.QuadPart
= 1;
1285 Unit
= MUIGetString(STRING_MB
);
1288 if (DiskEntry
->DriverName
.Length
> 0)
1290 sprintf (LineBuffer
,
1291 MUIGetString(STRING_HDINFOPARTSELECT
),
1294 DiskEntry
->DiskNumber
,
1298 DiskEntry
->DriverName
.Buffer
);
1302 sprintf (LineBuffer
,
1303 MUIGetString(STRING_HDDINFOUNK6
),
1306 DiskEntry
->DiskNumber
,
1311 if (List
->Line
>= 0 && List
->Line
<= Height
)
1313 FillConsoleOutputAttribute (StdOutput
,
1314 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1319 FillConsoleOutputCharacterA (StdOutput
,
1327 if (List
->Line
>= 0 && List
->Line
<= Height
)
1329 WriteConsoleOutputCharacterA (StdOutput
,
1331 min ((USHORT
)strlen (LineBuffer
), Width
- 2),
1337 /* Print separator line */
1338 PrintEmptyLine (List
);
1340 /* Print partition lines*/
1341 LIST_FOR_EACH(PartEntry
, &DiskEntry
->PartListHead
, PARTENTRY
, ListEntry
)
1343 /* Print disk entry */
1344 PrintPartitionData (List
,
1349 /* Print separator line */
1350 PrintEmptyLine (List
);
1355 DrawPartitionList (PPARTLIST List
)
1357 PLIST_ENTRY Entry
, Entry2
;
1358 PDISKENTRY DiskEntry
;
1359 PPARTENTRY PartEntry
= NULL
;
1363 SHORT CurrentDiskLine
;
1364 SHORT CurrentPartLine
;
1366 BOOL CurrentPartLineFound
= FALSE
;
1367 BOOL CurrentDiskLineFound
= FALSE
;
1369 /* Calculate the line of the current disk and partition */
1370 CurrentDiskLine
= 0;
1371 CurrentPartLine
= 0;
1373 Entry
= List
->DiskListHead
.Flink
;
1374 while (Entry
!= &List
->DiskListHead
)
1376 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1378 if (CurrentPartLineFound
== FALSE
)
1380 CurrentPartLine
+= 2;
1382 Entry2
= DiskEntry
->PartListHead
.Flink
;
1383 while (Entry2
!= &DiskEntry
->PartListHead
)
1385 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1386 if (PartEntry
== List
->CurrentPartition
)
1388 CurrentPartLineFound
= TRUE
;
1390 Entry2
= Entry2
->Flink
;
1391 if (CurrentPartLineFound
== FALSE
)
1397 if (DiskEntry
== List
->CurrentDisk
)
1399 CurrentDiskLineFound
= TRUE
;
1401 Entry
= Entry
->Flink
;
1402 if (Entry
!= &List
->DiskListHead
)
1404 if (CurrentDiskLineFound
== FALSE
)
1407 CurrentDiskLine
= CurrentPartLine
;
1417 /* If it possible, make the disk name visible */
1418 if (CurrentPartLine
< List
->Offset
)
1420 List
->Offset
= CurrentPartLine
;
1422 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1424 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1426 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1428 List
->Offset
= CurrentDiskLine
;
1432 /* draw upper left corner */
1433 coPos
.X
= List
->Left
;
1434 coPos
.Y
= List
->Top
;
1435 FillConsoleOutputCharacterA (StdOutput
,
1441 /* draw upper edge */
1442 coPos
.X
= List
->Left
+ 1;
1443 coPos
.Y
= List
->Top
;
1444 if (List
->Offset
== 0)
1446 FillConsoleOutputCharacterA (StdOutput
,
1448 List
->Right
- List
->Left
- 1,
1454 FillConsoleOutputCharacterA (StdOutput
,
1456 List
->Right
- List
->Left
- 5,
1459 coPos
.X
= List
->Right
- 5;
1460 WriteConsoleOutputCharacterA (StdOutput
,
1465 coPos
.X
= List
->Right
- 2;
1466 FillConsoleOutputCharacterA (StdOutput
,
1473 /* draw upper right corner */
1474 coPos
.X
= List
->Right
;
1475 coPos
.Y
= List
->Top
;
1476 FillConsoleOutputCharacterA (StdOutput
,
1482 /* draw left and right edge */
1483 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1485 coPos
.X
= List
->Left
;
1487 FillConsoleOutputCharacterA (StdOutput
,
1493 coPos
.X
= List
->Right
;
1494 FillConsoleOutputCharacterA (StdOutput
,
1501 /* draw lower left corner */
1502 coPos
.X
= List
->Left
;
1503 coPos
.Y
= List
->Bottom
;
1504 FillConsoleOutputCharacterA (StdOutput
,
1510 /* draw lower edge */
1511 coPos
.X
= List
->Left
+ 1;
1512 coPos
.Y
= List
->Bottom
;
1513 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1515 FillConsoleOutputCharacterA (StdOutput
,
1517 List
->Right
- List
->Left
- 1,
1523 FillConsoleOutputCharacterA (StdOutput
,
1525 List
->Right
- List
->Left
- 5,
1528 coPos
.X
= List
->Right
- 5;
1529 WriteConsoleOutputCharacterA (StdOutput
,
1530 "(\x19)", // "(down)"
1534 coPos
.X
= List
->Right
- 2;
1535 FillConsoleOutputCharacterA (StdOutput
,
1542 /* draw lower right corner */
1543 coPos
.X
= List
->Right
;
1544 coPos
.Y
= List
->Bottom
;
1545 FillConsoleOutputCharacterA (StdOutput
,
1551 /* print list entries */
1552 List
->Line
= - List
->Offset
;
1554 LIST_FOR_EACH(DiskEntry
, &List
->DiskListHead
, DISKENTRY
, ListEntry
)
1556 /* Print disk entry */
1557 PrintDiskData (List
,
1564 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1566 PDISKENTRY DiskEntry
;
1567 PPARTENTRY PartEntry
;
1572 /* Check for empty disks */
1573 if (IsListEmpty (&List
->DiskListHead
))
1576 /* Check for first usable entry on next disk */
1577 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1578 while (Entry1
!= &List
->DiskListHead
)
1580 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1582 if (DiskEntry
->DiskNumber
== DiskNumber
)
1584 Entry2
= DiskEntry
->PartListHead
.Flink
;
1585 while (Entry2
!= &DiskEntry
->PartListHead
)
1587 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1589 for (i
= 0; i
< 4; i
++)
1591 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1593 List
->CurrentDisk
= DiskEntry
;
1594 List
->CurrentPartition
= PartEntry
;
1595 DrawPartitionList (List
);
1599 Entry2
= Entry2
->Flink
;
1603 Entry1
= Entry1
->Flink
;
1610 ScrollDownPartitionList (PPARTLIST List
)
1612 PDISKENTRY DiskEntry
;
1613 PPARTENTRY PartEntry
;
1617 /* Check for empty disks */
1618 if (IsListEmpty (&List
->DiskListHead
))
1621 /* Check for next usable entry on current disk */
1622 if (List
->CurrentPartition
!= NULL
)
1624 Entry2
= List
->CurrentPartition
->ListEntry
.Flink
;
1625 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1627 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1629 // if (PartEntry->HidePartEntry == FALSE)
1631 List
->CurrentPartition
= PartEntry
;
1632 DrawPartitionList (List
);
1635 Entry2
= Entry2
->Flink
;
1639 /* Check for first usable entry on next disk */
1640 if (List
->CurrentDisk
!= NULL
)
1642 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1643 while (Entry1
!= &List
->DiskListHead
)
1645 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1647 Entry2
= DiskEntry
->PartListHead
.Flink
;
1648 while (Entry2
!= &DiskEntry
->PartListHead
)
1650 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1652 // if (PartEntry->HidePartEntry == FALSE)
1654 List
->CurrentDisk
= DiskEntry
;
1655 List
->CurrentPartition
= PartEntry
;
1656 DrawPartitionList (List
);
1660 Entry2
= Entry2
->Flink
;
1663 Entry1
= Entry1
->Flink
;
1670 ScrollUpPartitionList (PPARTLIST List
)
1672 PDISKENTRY DiskEntry
;
1673 PPARTENTRY PartEntry
;
1677 /* Check for empty disks */
1678 if (IsListEmpty (&List
->DiskListHead
))
1681 /* check for previous usable entry on current disk */
1682 if (List
->CurrentPartition
!= NULL
)
1684 Entry2
= List
->CurrentPartition
->ListEntry
.Blink
;
1685 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1687 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1689 // if (PartEntry->HidePartEntry == FALSE)
1691 List
->CurrentPartition
= PartEntry
;
1692 DrawPartitionList (List
);
1695 Entry2
= Entry2
->Blink
;
1700 /* check for last usable entry on previous disk */
1701 if (List
->CurrentDisk
!= NULL
)
1703 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1704 while (Entry1
!= &List
->DiskListHead
)
1706 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1708 Entry2
= DiskEntry
->PartListHead
.Blink
;
1709 while (Entry2
!= &DiskEntry
->PartListHead
)
1711 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1713 // if (PartEntry->HidePartEntry == FALSE)
1715 List
->CurrentDisk
= DiskEntry
;
1716 List
->CurrentPartition
= PartEntry
;
1717 DrawPartitionList (List
);
1721 Entry2
= Entry2
->Blink
;
1724 Entry1
= Entry1
->Blink
;
1731 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1732 PPARTENTRY CurrentEntry
)
1734 PPARTENTRY PrevEntry
;
1737 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1740 Entry
= CurrentEntry
->ListEntry
.Blink
;
1741 while (Entry
!= &DiskEntry
->PartListHead
)
1743 PrevEntry
= CONTAINING_RECORD (Entry
,
1746 if (PrevEntry
->Unpartitioned
== FALSE
)
1749 Entry
= Entry
->Blink
;
1757 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1758 PPARTENTRY CurrentEntry
)
1760 PPARTENTRY NextEntry
;
1763 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1766 Entry
= CurrentEntry
->ListEntry
.Flink
;
1767 while (Entry
!= &DiskEntry
->PartListHead
)
1769 NextEntry
= CONTAINING_RECORD (Entry
,
1772 if (NextEntry
->Unpartitioned
== FALSE
)
1775 Entry
= Entry
->Flink
;
1783 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1784 PPARTENTRY PartEntry
)
1786 PPARTENTRY PrevPartEntry
;
1788 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1790 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1793 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1794 return PrevPartEntry
;
1802 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1803 PPARTENTRY PartEntry
)
1805 PPARTENTRY NextPartEntry
;
1807 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1809 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1812 if (NextPartEntry
->Unpartitioned
== TRUE
)
1813 return NextPartEntry
;
1821 CreateNewPartition (PPARTLIST List
,
1822 ULONGLONG PartitionSize
,
1825 PDISKENTRY DiskEntry
;
1826 PPARTENTRY PartEntry
;
1827 PPARTENTRY PrevPartEntry
;
1828 PPARTENTRY NextPartEntry
;
1829 PPARTENTRY NewPartEntry
;
1832 List
->CurrentDisk
== NULL
||
1833 List
->CurrentPartition
== NULL
||
1834 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1839 DiskEntry
= List
->CurrentDisk
;
1840 PartEntry
= List
->CurrentPartition
;
1842 if (AutoCreate
== TRUE
||
1843 PartitionSize
== PartEntry
->UnpartitionedLength
)
1845 /* Convert current entry to 'new (unformatted)' */
1846 PartEntry
->FormatState
= Unformatted
;
1847 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1848 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1849 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1850 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1851 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1852 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1853 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1854 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1855 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1856 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1858 /* Get previous and next partition entries */
1859 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1861 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1864 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1866 /* Current entry is in the middle of the list */
1868 /* Copy previous container partition data to current entry */
1869 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1870 &PrevPartEntry
->PartInfo
[1],
1871 sizeof(PARTITION_INFORMATION
));
1872 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1874 /* Update previous container partition data */
1876 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1877 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1879 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1881 /* Special case - previous partition is first partition */
1882 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1883 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1887 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1888 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1891 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1893 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1895 /* Current entry is the first entry */
1898 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1900 /* Current entry is the last entry */
1902 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1903 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1905 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1907 /* Special case - previous partition is first partition */
1908 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1909 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1913 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1914 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1917 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
1918 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
1919 (1024LL * 255LL * 63LL * 512LL))
1921 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
1925 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
1928 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1929 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1932 PartEntry
->AutoCreate
= AutoCreate
;
1933 PartEntry
->New
= TRUE
;
1934 PartEntry
->Unpartitioned
= FALSE
;
1935 PartEntry
->UnpartitionedOffset
= 0ULL;
1936 PartEntry
->UnpartitionedLength
= 0ULL;
1940 /* Insert an initialize a new partition entry */
1941 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
1944 if (NewPartEntry
== NULL
)
1947 RtlZeroMemory (NewPartEntry
,
1950 /* Insert the new entry into the list */
1951 InsertTailList (&PartEntry
->ListEntry
,
1952 &NewPartEntry
->ListEntry
);
1954 NewPartEntry
->New
= TRUE
;
1956 NewPartEntry
->FormatState
= Unformatted
;
1957 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1958 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1959 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1960 PartitionSize
- DiskEntry
->TrackSize
;
1961 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1962 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1963 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1964 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1965 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1966 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1968 /* Get previous and next partition entries */
1969 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1971 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1974 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1976 /* Current entry is in the middle of the list */
1978 /* Copy previous container partition data to current entry */
1979 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
1980 &PrevPartEntry
->PartInfo
[1],
1981 sizeof(PARTITION_INFORMATION
));
1982 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1984 /* Update previous container partition data */
1986 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1987 NewPartEntry
->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 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2001 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2003 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2005 /* Current entry is the first entry */
2008 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2010 /* Current entry is the last entry */
2012 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
2013 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2015 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
2017 /* Special case - previous partition is first partition */
2018 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2019 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2023 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2024 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2027 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2028 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2029 (1024LL * 255LL * 63LL * 512LL))
2031 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2035 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2038 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2039 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2042 /* Update offset and size of the remaining unpartitioned disk space */
2043 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
2044 PartEntry
->UnpartitionedLength
-= PartitionSize
;
2047 DiskEntry
->Modified
= TRUE
;
2049 UpdatePartitionNumbers (DiskEntry
);
2051 AssignDriverLetters (List
);
2056 DeleteCurrentPartition (PPARTLIST List
)
2058 PDISKENTRY DiskEntry
;
2059 PPARTENTRY PartEntry
;
2060 PPARTENTRY PrevPartEntry
;
2061 PPARTENTRY NextPartEntry
;
2064 List
->CurrentDisk
== NULL
||
2065 List
->CurrentPartition
== NULL
||
2066 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2071 DiskEntry
= List
->CurrentDisk
;
2072 PartEntry
= List
->CurrentPartition
;
2074 /* Adjust container partition entries */
2076 /* Get previous and next partition entries */
2077 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2079 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2082 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2084 /* Current entry is in the middle of the list */
2087 * The first extended partition can not be deleted
2088 * as long as other extended partitions are present.
2090 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2093 /* Copy previous container partition data to current entry */
2094 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
2095 &PartEntry
->PartInfo
[1],
2096 sizeof(PARTITION_INFORMATION
));
2097 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2099 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2102 * A primary partition can not be deleted as long as
2103 * extended partitions are present.
2107 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2109 /* Current entry is the last entry */
2110 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
2111 sizeof(PARTITION_INFORMATION
));
2112 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2116 /* Adjust unpartitioned disk space entries */
2118 /* Get pointer to previous and next unpartitioned entries */
2119 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
2122 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
2125 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2127 /* Merge previous, current and next unpartitioned entry */
2129 /* Adjust the previous entries length */
2130 PrevPartEntry
->UnpartitionedLength
+=
2131 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2132 NextPartEntry
->UnpartitionedLength
);
2134 /* Remove the current entry */
2135 RemoveEntryList (&PartEntry
->ListEntry
);
2136 RtlFreeHeap (ProcessHeap
,
2140 /* Remove the next entry */
2141 RemoveEntryList (&NextPartEntry
->ListEntry
);
2142 RtlFreeHeap (ProcessHeap
,
2146 /* Update current partition */
2147 List
->CurrentPartition
= PrevPartEntry
;
2149 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2151 /* Merge current and previous unpartitioned entry */
2153 /* Adjust the previous entries length */
2154 PrevPartEntry
->UnpartitionedLength
+=
2155 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2157 /* Remove the current entry */
2158 RemoveEntryList (&PartEntry
->ListEntry
);
2159 RtlFreeHeap (ProcessHeap
,
2163 /* Update current partition */
2164 List
->CurrentPartition
= PrevPartEntry
;
2166 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2168 /* Merge current and next unpartitioned entry */
2170 /* Adjust the next entries offset and length */
2171 NextPartEntry
->UnpartitionedOffset
=
2172 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2173 NextPartEntry
->UnpartitionedLength
+=
2174 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2176 /* Remove the current entry */
2177 RemoveEntryList (&PartEntry
->ListEntry
);
2178 RtlFreeHeap (ProcessHeap
,
2182 /* Update current partition */
2183 List
->CurrentPartition
= NextPartEntry
;
2187 /* Nothing to merge but change current entry */
2188 PartEntry
->New
= FALSE
;
2189 PartEntry
->Unpartitioned
= TRUE
;
2190 PartEntry
->UnpartitionedOffset
=
2191 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2192 PartEntry
->UnpartitionedLength
=
2193 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2195 /* Wipe the partition table */
2196 RtlZeroMemory (&PartEntry
->PartInfo
,
2197 sizeof(PartEntry
->PartInfo
));
2200 DiskEntry
->Modified
= TRUE
;
2202 UpdatePartitionNumbers (DiskEntry
);
2204 AssignDriverLetters (List
);
2209 CheckActiveBootPartition (PPARTLIST List
)
2211 PDISKENTRY DiskEntry
;
2212 PPARTENTRY PartEntry
;
2214 /* Check for empty disk list */
2215 if (IsListEmpty (&List
->DiskListHead
))
2217 List
->ActiveBootDisk
= NULL
;
2218 List
->ActiveBootPartition
= NULL
;
2223 if (List
->ActiveBootDisk
!= NULL
&&
2224 List
->ActiveBootPartition
!= NULL
)
2226 /* We already have an active boot partition */
2231 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
2235 /* Check for empty partition list */
2236 if (IsListEmpty (&DiskEntry
->PartListHead
))
2238 List
->ActiveBootDisk
= NULL
;
2239 List
->ActiveBootPartition
= NULL
;
2243 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
2247 /* Set active boot partition */
2248 if ((DiskEntry
->NewDisk
== TRUE
) ||
2249 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2250 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2251 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2252 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2254 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2255 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2256 DiskEntry
->Modified
= TRUE
;
2259 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2260 List
->ActiveBootDisk
= DiskEntry
;
2261 List
->ActiveBootPartition
= PartEntry
;
2266 CheckForLinuxFdiskPartitions (PPARTLIST List
)
2268 PDISKENTRY DiskEntry
;
2269 PPARTENTRY PartEntry
;
2272 ULONG PartitionCount
;
2275 Entry1
= List
->DiskListHead
.Flink
;
2276 while (Entry1
!= &List
->DiskListHead
)
2278 DiskEntry
= CONTAINING_RECORD (Entry1
,
2282 Entry2
= DiskEntry
->PartListHead
.Flink
;
2283 while (Entry2
!= &DiskEntry
->PartListHead
)
2285 PartEntry
= CONTAINING_RECORD (Entry2
,
2289 if (PartEntry
->Unpartitioned
== FALSE
)
2293 for (i
= 0; i
< 4; i
++)
2295 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
2296 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2302 if (PartitionCount
> 1)
2308 Entry2
= Entry2
->Flink
;
2311 Entry1
= Entry1
->Flink
;
2319 WritePartitionsToDisk (PPARTLIST List
)
2321 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2322 OBJECT_ATTRIBUTES ObjectAttributes
;
2323 IO_STATUS_BLOCK Iosb
;
2324 WCHAR SrcPath
[MAX_PATH
];
2325 WCHAR DstPath
[MAX_PATH
];
2326 UNICODE_STRING Name
;
2328 PDISKENTRY DiskEntry1
;
2329 PDISKENTRY DiskEntry2
;
2330 PPARTENTRY PartEntry
;
2333 ULONG PartitionCount
;
2334 ULONG DriveLayoutSize
;
2343 Entry1
= List
->DiskListHead
.Flink
;
2344 while (Entry1
!= &List
->DiskListHead
)
2346 DiskEntry1
= CONTAINING_RECORD (Entry1
,
2350 if (DiskEntry1
->Modified
== TRUE
)
2352 /* Count partitioned entries */
2354 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2355 while (Entry2
!= &DiskEntry1
->PartListHead
)
2357 PartEntry
= CONTAINING_RECORD (Entry2
,
2360 if (PartEntry
->Unpartitioned
== FALSE
)
2362 PartitionCount
+= 4;
2365 Entry2
= Entry2
->Flink
;
2367 if (PartitionCount
== 0)
2369 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2370 ((4 - 1) * sizeof (PARTITION_INFORMATION
));
2374 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2375 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2377 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
2380 if (DriveLayout
== NULL
)
2382 DPRINT1 ("RtlAllocateHeap() failed\n");
2386 RtlZeroMemory (DriveLayout
,
2389 if (PartitionCount
== 0)
2391 /* delete all partitions in the mbr */
2392 DriveLayout
->PartitionCount
= 4;
2393 for (Index
= 0; Index
< 4; Index
++)
2395 DriveLayout
->PartitionEntry
[Index
].RewritePartition
= TRUE
;
2400 DriveLayout
->PartitionCount
= PartitionCount
;
2403 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2404 while (Entry2
!= &DiskEntry1
->PartListHead
)
2406 PartEntry
= CONTAINING_RECORD (Entry2
,
2409 if (PartEntry
->Unpartitioned
== FALSE
)
2411 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2412 &PartEntry
->PartInfo
[0],
2413 4 * sizeof (PARTITION_INFORMATION
));
2417 Entry2
= Entry2
->Flink
;
2420 if (DiskEntry1
->Signature
== 0)
2422 LARGE_INTEGER SystemTime
;
2423 TIME_FIELDS TimeFields
;
2425 Buffer
= (PUCHAR
)&DiskEntry1
->Signature
;
2429 NtQuerySystemTime (&SystemTime
);
2430 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
2432 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
2433 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
2434 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
2435 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
2437 if (DiskEntry1
->Signature
== 0)
2442 /* check if the signature already exist */
2444 * Check also signatures from disks, which are
2445 * not visible (bootable) by the bios.
2447 Entry2
= List
->DiskListHead
.Flink
;
2448 while (Entry2
!= &List
->DiskListHead
)
2450 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
2451 if (DiskEntry1
!= DiskEntry2
&&
2452 DiskEntry1
->Signature
== DiskEntry2
->Signature
)
2456 Entry2
= Entry2
->Flink
;
2458 if (Entry2
== &List
->DiskListHead
)
2464 /* set one partition entry to dirty, this will update the signature */
2465 DriveLayout
->PartitionEntry
[0].RewritePartition
= TRUE
;
2469 DriveLayout
->Signature
= DiskEntry1
->Signature
;
2473 L
"\\Device\\Harddisk%d\\Partition0",
2474 DiskEntry1
->DiskNumber
);
2475 RtlInitUnicodeString (&Name
,
2477 InitializeObjectAttributes (&ObjectAttributes
,
2483 Status
= NtOpenFile (&FileHandle
,
2488 FILE_SYNCHRONOUS_IO_NONALERT
);
2490 if (!NT_SUCCESS (Status
))
2492 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2496 Status
= NtDeviceIoControlFile (FileHandle
,
2501 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2506 if (!NT_SUCCESS (Status
))
2508 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2509 NtClose (FileHandle
);
2513 RtlFreeHeap (ProcessHeap
,
2517 NtClose (FileHandle
);
2519 /* Install MBR code if the disk is new */
2520 if (DiskEntry1
->NewDisk
== TRUE
&&
2521 DiskEntry1
->BiosDiskNumber
== 0)
2523 wcscpy (SrcPath
, SourceRootPath
.Buffer
);
2524 wcscat (SrcPath
, L
"\\loader\\dosmbr.bin");
2526 DPRINT ("Install MBR bootcode: %S ==> %S\n",
2529 /* Install MBR bootcode */
2530 Status
= InstallMbrBootCodeToDisk (SrcPath
,
2532 if (!NT_SUCCESS (Status
))
2534 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
2539 DiskEntry1
->NewDisk
= FALSE
;
2543 Entry1
= Entry1
->Flink
;
2549 BOOL
SetMountedDeviceValues(PPARTLIST List
)
2551 PLIST_ENTRY Entry1
, Entry2
;
2552 PDISKENTRY DiskEntry
;
2553 PPARTENTRY PartEntry
;
2560 Entry1
= List
->DiskListHead
.Flink
;
2561 while (Entry1
!= &List
->DiskListHead
)
2563 DiskEntry
= CONTAINING_RECORD (Entry1
,
2567 Entry2
= DiskEntry
->PartListHead
.Flink
;
2568 while (Entry2
!= &DiskEntry
->PartListHead
)
2570 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2571 if (!PartEntry
->Unpartitioned
&& PartEntry
->DriveLetter
)
2573 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
, DiskEntry
->Signature
, PartEntry
->PartInfo
[0].StartingOffset
))
2578 Entry2
= Entry2
->Flink
;
2580 Entry1
= Entry1
->Flink
;