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_IFS
)
273 if (CheckNtfsFormat())
275 PartEntry
->FormatState
= Preformatted
;
277 else if (CheckHpfsFormat())
279 PartEntry
->FormatState
= Preformatted
;
283 PartEntry
->FormatState
= Unformatted
;
286 PartEntry
->FormatState
= Preformatted
;
290 PartEntry
->FormatState
= UnknownFormat
;
293 InsertTailList (&DiskEntry
->PartListHead
,
294 &PartEntry
->ListEntry
);
300 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry
)
302 ULONGLONG LastStartingOffset
;
303 ULONGLONG LastPartitionLength
;
304 ULONGLONG LastUnusedPartitionLength
;
305 PPARTENTRY PartEntry
;
306 PPARTENTRY NewPartEntry
;
311 if (IsListEmpty (&DiskEntry
->PartListHead
))
313 /* Create a partition table that represents the empty disk */
314 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
317 if (PartEntry
== NULL
)
320 RtlZeroMemory (PartEntry
,
323 PartEntry
->Unpartitioned
= TRUE
;
324 PartEntry
->UnpartitionedOffset
= 0ULL;
325 PartEntry
->UnpartitionedLength
= DiskEntry
->DiskSize
;
327 PartEntry
->FormatState
= Unformatted
;
329 InsertTailList (&DiskEntry
->PartListHead
,
330 &PartEntry
->ListEntry
);
334 /* Start partition at head 1, cylinder 0 */
335 LastStartingOffset
= DiskEntry
->TrackSize
;
336 LastPartitionLength
= 0ULL;
337 LastUnusedPartitionLength
= 0ULL;
340 Entry
= DiskEntry
->PartListHead
.Flink
;
341 while (Entry
!= &DiskEntry
->PartListHead
)
343 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
345 for (j
= 0; j
< 4; j
++)
347 if ((!IsContainerPartition (PartEntry
->PartInfo
[j
].PartitionType
)) &&
348 (PartEntry
->PartInfo
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
349 PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
!= 0LL))
351 LastUnusedPartitionLength
=
352 PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
-
353 (LastStartingOffset
+ LastPartitionLength
);
355 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
357 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
359 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
362 if (NewPartEntry
== NULL
)
365 RtlZeroMemory (NewPartEntry
,
368 NewPartEntry
->Unpartitioned
= TRUE
;
369 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
370 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
372 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
374 NewPartEntry
->FormatState
= Unformatted
;
376 /* Insert the table into the list */
377 InsertTailList (&PartEntry
->ListEntry
,
378 &NewPartEntry
->ListEntry
);
381 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
382 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
387 Entry
= Entry
->Flink
;
390 /* Check for trailing unpartitioned disk space */
391 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
393 /* Round-down to cylinder size */
394 LastUnusedPartitionLength
=
395 ROUND_DOWN (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
),
396 DiskEntry
->CylinderSize
);
398 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
400 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
402 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
405 if (NewPartEntry
== NULL
)
408 RtlZeroMemory (NewPartEntry
,
411 NewPartEntry
->Unpartitioned
= TRUE
;
412 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
413 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
415 /* Append the table to the list */
416 InsertTailList (&DiskEntry
->PartListHead
,
417 &NewPartEntry
->ListEntry
);
425 DiskIdentifierQueryRoutine(PWSTR ValueName
,
432 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
433 UNICODE_STRING NameU
;
435 if (ValueType
== REG_SZ
&&
436 ValueLength
== 20 * sizeof(WCHAR
))
438 NameU
.Buffer
= (PWCHAR
)ValueData
;
439 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
440 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
442 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
443 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
445 return STATUS_SUCCESS
;
447 return STATUS_UNSUCCESSFUL
;
452 DiskConfigurationDataQueryRoutine(PWSTR ValueName
,
459 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
460 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
461 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
464 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
465 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
466 return STATUS_UNSUCCESSFUL
;
468 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
469 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
470 /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
471 FullResourceDescriptor->PartialResourceList.Revision != 1)
472 return STATUS_UNSUCCESSFUL;*/
474 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
476 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
477 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
480 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
481 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
483 return STATUS_SUCCESS
;
485 return STATUS_UNSUCCESSFUL
;
490 SystemConfigurationDataQueryRoutine(PWSTR ValueName
,
497 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
498 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
501 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
502 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
503 return STATUS_UNSUCCESSFUL
;
505 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
506 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
507 /*if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
508 FullResourceDescriptor->PartialResourceList.Revision != 1)
509 return STATUS_UNSUCCESSFUL;*/
511 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
513 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
514 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
517 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
518 if (*Int13Drives
== NULL
)
519 return STATUS_NO_MEMORY
;
522 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
523 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
524 return STATUS_SUCCESS
;
526 return STATUS_UNSUCCESSFUL
;
528 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
531 EnumerateBiosDiskEntries(PPARTLIST PartList
)
533 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
538 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
539 PBIOSDISKENTRY BiosDiskEntry
;
541 memset(QueryTable
, 0, sizeof(QueryTable
));
543 QueryTable
[1].Name
= L
"Configuration Data";
544 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
546 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
547 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
551 if (!NT_SUCCESS(Status
))
553 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
560 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
561 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
566 if (!NT_SUCCESS(Status
))
571 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
572 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
577 if (NT_SUCCESS(Status
))
581 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
582 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
587 if (!NT_SUCCESS(Status
))
589 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
593 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
594 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
599 if (NT_SUCCESS(Status
))
601 QueryTable
[0].Name
= L
"Identifier";
602 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
603 QueryTable
[1].Name
= L
"Configuration Data";
604 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
608 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
609 if (BiosDiskEntry
== NULL
)
613 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
614 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
617 (PVOID
)BiosDiskEntry
,
619 if (!NT_SUCCESS(Status
))
621 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
624 BiosDiskEntry
->DiskNumber
= DiskCount
;
625 BiosDiskEntry
->Recognized
= FALSE
;
627 if (DiskCount
< Int13Drives
[0].NumberDrives
)
629 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
633 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
637 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
639 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
640 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
641 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
642 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
643 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
644 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
645 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
646 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
647 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
648 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
649 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
654 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
660 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
664 AddDiskToList (HANDLE FileHandle
,
668 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
669 DISK_GEOMETRY DiskGeometry
;
670 SCSI_ADDRESS ScsiAddress
;
671 PDISKENTRY DiskEntry
;
672 IO_STATUS_BLOCK Iosb
;
674 PPARTITION_SECTOR Mbr
;
676 LARGE_INTEGER FileOffset
;
677 WCHAR Identifier
[20];
681 PLIST_ENTRY ListEntry
;
682 PBIOSDISKENTRY BiosDiskEntry
;
684 Status
= NtDeviceIoControlFile (FileHandle
,
689 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
693 sizeof(DISK_GEOMETRY
));
694 if (!NT_SUCCESS (Status
))
699 if (DiskGeometry
.MediaType
!= FixedMedia
)
704 Status
= NtDeviceIoControlFile (FileHandle
,
709 IOCTL_SCSI_GET_ADDRESS
,
713 sizeof(SCSI_ADDRESS
));
714 if (!NT_SUCCESS(Status
))
719 Mbr
= (PARTITION_SECTOR
*) RtlAllocateHeap(ProcessHeap
,
721 DiskGeometry
.BytesPerSector
);
728 FileOffset
.QuadPart
= 0;
729 Status
= NtReadFile(FileHandle
,
735 DiskGeometry
.BytesPerSector
,
738 if (!NT_SUCCESS(Status
))
740 RtlFreeHeap(ProcessHeap
,
743 DPRINT1("NtReadFile failed, status=%x\n", Status
);
746 Signature
= Mbr
->Signature
;
748 /* Calculate the MBR checksum */
750 Buffer
= (PULONG
)Mbr
;
751 for (i
= 0; i
< 128; i
++)
753 Checksum
+= Buffer
[i
];
755 Checksum
= ~Checksum
+ 1;
757 RtlFreeHeap (ProcessHeap
,
761 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
762 DPRINT("Identifier: %S\n", Identifier
);
764 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
767 if (DiskEntry
== NULL
)
772 DiskEntry
->Checksum
= Checksum
;
773 DiskEntry
->Signature
= Signature
;
776 /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
777 DiskEntry
->Modified
= TRUE
;
779 DiskEntry
->BiosFound
= FALSE
;
781 ListEntry
= List
->BiosDiskListHead
.Flink
;
782 while(ListEntry
!= &List
->BiosDiskListHead
)
784 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
786 * Compare the size from bios and the reported size from driver.
787 * If we have more than one disk with a zero or with the same signatur
788 * we must create new signatures and reboot. After the reboot,
789 * it is possible to identify the disks.
791 if (BiosDiskEntry
->Signature
== Signature
&&
792 BiosDiskEntry
->Checksum
== Checksum
&&
793 !BiosDiskEntry
->Recognized
)
795 if (!DiskEntry
->BiosFound
)
797 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
798 DiskEntry
->BiosFound
= TRUE
;
799 BiosDiskEntry
->Recognized
= TRUE
;
805 ListEntry
= ListEntry
->Flink
;
808 if (!DiskEntry
->BiosFound
)
810 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
814 InitializeListHead (&DiskEntry
->PartListHead
);
816 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
817 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
818 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
819 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
821 DPRINT ("Cylinders %d\n", DiskEntry
->Cylinders
);
822 DPRINT ("TracksPerCylinder %d\n", DiskEntry
->TracksPerCylinder
);
823 DPRINT ("SectorsPerTrack %d\n", DiskEntry
->SectorsPerTrack
);
824 DPRINT ("BytesPerSector %d\n", DiskEntry
->BytesPerSector
);
826 DiskEntry
->DiskSize
=
827 DiskGeometry
.Cylinders
.QuadPart
*
828 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
829 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
830 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
831 DiskEntry
->CylinderSize
=
832 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
833 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
834 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
835 DiskEntry
->TrackSize
=
836 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
837 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
839 DiskEntry
->DiskNumber
= DiskNumber
;
840 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
841 DiskEntry
->Bus
= ScsiAddress
.PathId
;
842 DiskEntry
->Id
= ScsiAddress
.TargetId
;
844 GetDriverName (DiskEntry
);
846 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, BiosDiskNumber
);
848 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
851 if (LayoutBuffer
== NULL
)
856 Status
= NtDeviceIoControlFile (FileHandle
,
861 IOCTL_DISK_GET_DRIVE_LAYOUT
,
866 if (NT_SUCCESS (Status
))
868 if (LayoutBuffer
->PartitionCount
== 0)
870 DiskEntry
->NewDisk
= TRUE
;
873 AddPartitionToList (DiskNumber
,
877 ScanForUnpartitionedDiskSpace (DiskEntry
);
880 RtlFreeHeap (ProcessHeap
,
887 CreatePartitionList (SHORT Left
,
893 OBJECT_ATTRIBUTES ObjectAttributes
;
894 SYSTEM_DEVICE_INFORMATION Sdi
;
895 IO_STATUS_BLOCK Iosb
;
899 WCHAR Buffer
[MAX_PATH
];
903 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
912 List
->Bottom
= Bottom
;
916 List
->TopDisk
= (ULONG
)-1;
917 List
->TopPartition
= (ULONG
)-1;
919 List
->CurrentDisk
= NULL
;
920 List
->CurrentPartition
= NULL
;
922 InitializeListHead (&List
->DiskListHead
);
923 InitializeListHead (&List
->BiosDiskListHead
);
925 EnumerateBiosDiskEntries(List
);
927 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
929 sizeof(SYSTEM_DEVICE_INFORMATION
),
931 if (!NT_SUCCESS (Status
))
933 RtlFreeHeap (ProcessHeap
, 0, List
);
937 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
940 L
"\\Device\\Harddisk%d\\Partition0",
942 RtlInitUnicodeString (&Name
,
945 InitializeObjectAttributes (&ObjectAttributes
,
951 Status
= NtOpenFile (&FileHandle
,
956 FILE_SYNCHRONOUS_IO_NONALERT
);
957 if (NT_SUCCESS(Status
))
959 AddDiskToList (FileHandle
,
967 AssignDriverLetters (List
);
970 List
->TopPartition
= 0;
972 /* Search for first usable disk and partition */
973 if (IsListEmpty (&List
->DiskListHead
))
975 List
->CurrentDisk
= NULL
;
976 List
->CurrentPartition
= NULL
;
981 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
985 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
987 List
->CurrentPartition
= 0;
991 List
->CurrentPartition
=
992 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
1003 DestroyPartitionList (PPARTLIST List
)
1005 PDISKENTRY DiskEntry
;
1006 PBIOSDISKENTRY BiosDiskEntry
;
1007 PPARTENTRY PartEntry
;
1010 /* Release disk and partition info */
1011 while (!IsListEmpty (&List
->DiskListHead
))
1013 Entry
= RemoveHeadList (&List
->DiskListHead
);
1014 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1016 /* Release driver name */
1017 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1019 /* Release partition array */
1020 while (!IsListEmpty (&DiskEntry
->PartListHead
))
1022 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
1023 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
1025 RtlFreeHeap (ProcessHeap
,
1030 /* Release disk entry */
1031 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
1034 /* release the bios disk info */
1035 while(!IsListEmpty(&List
->BiosDiskListHead
))
1037 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1038 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1040 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1043 /* Release list head */
1044 RtlFreeHeap (ProcessHeap
, 0, List
);
1049 PrintEmptyLine (PPARTLIST List
)
1056 Width
= List
->Right
- List
->Left
- 1;
1057 Height
= List
->Bottom
- List
->Top
- 2;
1060 coPos
.X
= List
->Left
+ 1;
1061 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1063 if (List
->Line
>= 0 && List
->Line
<= Height
)
1065 FillConsoleOutputAttribute (StdOutput
,
1066 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1071 FillConsoleOutputCharacterA (StdOutput
,
1082 PrintPartitionData (PPARTLIST List
,
1083 PDISKENTRY DiskEntry
,
1084 PPARTENTRY PartEntry
)
1086 CHAR LineBuffer
[128];
1092 LARGE_INTEGER PartSize
;
1097 Width
= List
->Right
- List
->Left
- 1;
1098 Height
= List
->Bottom
- List
->Top
- 2;
1101 coPos
.X
= List
->Left
+ 1;
1102 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1104 if (PartEntry
->Unpartitioned
== TRUE
)
1107 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1109 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1114 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1116 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1121 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1125 sprintf (LineBuffer
,
1126 " Unpartitioned space %6lu %s",
1132 /* Determine partition type */
1134 if (PartEntry
->New
== TRUE
)
1136 PartType
= "New (Unformatted)";
1138 else if (PartEntry
->Unpartitioned
== FALSE
)
1140 if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
1141 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
1142 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
1143 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
))
1147 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
1148 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
1152 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
1154 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1159 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1161 PartSize
.QuadPart
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1166 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1168 PartSize
.QuadPart
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1173 PartSize
.QuadPart
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1177 if (PartType
== NULL
)
1179 sprintf (LineBuffer
,
1180 "%c%c Type %-3u %6lu %s",
1181 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1182 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1183 PartEntry
->PartInfo
[0].PartitionType
,
1189 sprintf (LineBuffer
,
1190 "%c%c %-24s %6lu %s",
1191 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1192 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1199 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1200 List
->CurrentPartition
== PartEntry
) ?
1201 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1202 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1204 if (List
->Line
>= 0 && List
->Line
<= Height
)
1206 FillConsoleOutputCharacterA (StdOutput
,
1214 if (List
->Line
>= 0 && List
->Line
<= Height
)
1216 FillConsoleOutputAttribute (StdOutput
,
1224 if (List
->Line
>= 0 && List
->Line
<= Height
)
1226 WriteConsoleOutputCharacterA (StdOutput
,
1228 min (strlen (LineBuffer
), Width
),
1237 PrintDiskData (PPARTLIST List
,
1238 PDISKENTRY DiskEntry
)
1240 PPARTENTRY PartEntry
;
1241 CHAR LineBuffer
[128];
1246 ULARGE_INTEGER DiskSize
;
1249 Width
= List
->Right
- List
->Left
- 1;
1250 Height
= List
->Bottom
- List
->Top
- 2;
1253 coPos
.X
= List
->Left
+ 1;
1254 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1257 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1259 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1265 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1266 if (DiskSize
.QuadPart
== 0)
1267 DiskSize
.QuadPart
= 1;
1271 if (DiskEntry
->DriverName
.Length
> 0)
1273 sprintf (LineBuffer
,
1274 "%6lu %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %S",
1277 DiskEntry
->DiskNumber
,
1281 DiskEntry
->DriverName
.Buffer
);
1285 sprintf (LineBuffer
,
1286 "%6lu %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
1289 DiskEntry
->DiskNumber
,
1294 if (List
->Line
>= 0 && List
->Line
<= Height
)
1296 FillConsoleOutputAttribute (StdOutput
,
1297 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1302 FillConsoleOutputCharacterA (StdOutput
,
1310 if (List
->Line
>= 0 && List
->Line
<= Height
)
1312 WriteConsoleOutputCharacterA (StdOutput
,
1314 min ((USHORT
)strlen (LineBuffer
), Width
- 2),
1320 /* Print separator line */
1321 PrintEmptyLine (List
);
1323 /* Print partition lines*/
1324 LIST_FOR_EACH(PartEntry
, &DiskEntry
->PartListHead
, PARTENTRY
, ListEntry
)
1326 /* Print disk entry */
1327 PrintPartitionData (List
,
1332 /* Print separator line */
1333 PrintEmptyLine (List
);
1338 DrawPartitionList (PPARTLIST List
)
1340 PLIST_ENTRY Entry
, Entry2
;
1341 PDISKENTRY DiskEntry
;
1342 PPARTENTRY PartEntry
= NULL
;
1346 SHORT CurrentDiskLine
;
1347 SHORT CurrentPartLine
;
1349 BOOL CurrentPartLineFound
= FALSE
;
1350 BOOL CurrentDiskLineFound
= FALSE
;
1352 /* Calculate the line of the current disk and partition */
1353 CurrentDiskLine
= 0;
1354 CurrentPartLine
= 0;
1356 Entry
= List
->DiskListHead
.Flink
;
1357 while (Entry
!= &List
->DiskListHead
)
1359 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1361 if (CurrentPartLineFound
== FALSE
)
1363 CurrentPartLine
+= 2;
1365 Entry2
= DiskEntry
->PartListHead
.Flink
;
1366 while (Entry2
!= &DiskEntry
->PartListHead
)
1368 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1369 if (PartEntry
== List
->CurrentPartition
)
1371 CurrentPartLineFound
= TRUE
;
1373 Entry2
= Entry2
->Flink
;
1374 if (CurrentPartLineFound
== FALSE
)
1380 if (DiskEntry
== List
->CurrentDisk
)
1382 CurrentDiskLineFound
= TRUE
;
1384 Entry
= Entry
->Flink
;
1385 if (Entry
!= &List
->DiskListHead
)
1387 if (CurrentDiskLineFound
== FALSE
)
1390 CurrentDiskLine
= CurrentPartLine
;
1400 /* If it possible, make the disk name visible */
1401 if (CurrentPartLine
< List
->Offset
)
1403 List
->Offset
= CurrentPartLine
;
1405 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1407 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1409 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1411 List
->Offset
= CurrentDiskLine
;
1415 /* draw upper left corner */
1416 coPos
.X
= List
->Left
;
1417 coPos
.Y
= List
->Top
;
1418 FillConsoleOutputCharacterA (StdOutput
,
1424 /* draw upper edge */
1425 coPos
.X
= List
->Left
+ 1;
1426 coPos
.Y
= List
->Top
;
1427 if (List
->Offset
== 0)
1429 FillConsoleOutputCharacterA (StdOutput
,
1431 List
->Right
- List
->Left
- 1,
1437 FillConsoleOutputCharacterA (StdOutput
,
1439 List
->Right
- List
->Left
- 5,
1442 coPos
.X
= List
->Right
- 5;
1443 WriteConsoleOutputCharacterA (StdOutput
,
1448 coPos
.X
= List
->Right
- 2;
1449 FillConsoleOutputCharacterA (StdOutput
,
1456 /* draw upper right corner */
1457 coPos
.X
= List
->Right
;
1458 coPos
.Y
= List
->Top
;
1459 FillConsoleOutputCharacterA (StdOutput
,
1465 /* draw left and right edge */
1466 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1468 coPos
.X
= List
->Left
;
1470 FillConsoleOutputCharacterA (StdOutput
,
1476 coPos
.X
= List
->Right
;
1477 FillConsoleOutputCharacterA (StdOutput
,
1484 /* draw lower left corner */
1485 coPos
.X
= List
->Left
;
1486 coPos
.Y
= List
->Bottom
;
1487 FillConsoleOutputCharacterA (StdOutput
,
1493 /* draw lower edge */
1494 coPos
.X
= List
->Left
+ 1;
1495 coPos
.Y
= List
->Bottom
;
1496 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1498 FillConsoleOutputCharacterA (StdOutput
,
1500 List
->Right
- List
->Left
- 1,
1506 FillConsoleOutputCharacterA (StdOutput
,
1508 List
->Right
- List
->Left
- 5,
1511 coPos
.X
= List
->Right
- 5;
1512 WriteConsoleOutputCharacterA (StdOutput
,
1513 "(\x19)", // "(down)"
1517 coPos
.X
= List
->Right
- 2;
1518 FillConsoleOutputCharacterA (StdOutput
,
1525 /* draw lower right corner */
1526 coPos
.X
= List
->Right
;
1527 coPos
.Y
= List
->Bottom
;
1528 FillConsoleOutputCharacterA (StdOutput
,
1534 /* print list entries */
1535 List
->Line
= - List
->Offset
;
1537 LIST_FOR_EACH(DiskEntry
, &List
->DiskListHead
, DISKENTRY
, ListEntry
)
1539 /* Print disk entry */
1540 PrintDiskData (List
,
1547 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1549 PDISKENTRY DiskEntry
;
1550 PPARTENTRY PartEntry
;
1555 /* Check for empty disks */
1556 if (IsListEmpty (&List
->DiskListHead
))
1559 /* Check for first usable entry on next disk */
1560 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1561 while (Entry1
!= &List
->DiskListHead
)
1563 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1565 if (DiskEntry
->DiskNumber
== DiskNumber
)
1567 Entry2
= DiskEntry
->PartListHead
.Flink
;
1568 while (Entry2
!= &DiskEntry
->PartListHead
)
1570 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1572 for (i
= 0; i
< 4; i
++)
1574 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1576 List
->CurrentDisk
= DiskEntry
;
1577 List
->CurrentPartition
= PartEntry
;
1578 DrawPartitionList (List
);
1582 Entry2
= Entry2
->Flink
;
1586 Entry1
= Entry1
->Flink
;
1592 ScrollDownPartitionList (PPARTLIST List
)
1594 PDISKENTRY DiskEntry
;
1595 PPARTENTRY PartEntry
;
1599 /* Check for empty disks */
1600 if (IsListEmpty (&List
->DiskListHead
))
1603 /* Check for next usable entry on current disk */
1604 if (List
->CurrentPartition
!= NULL
)
1606 Entry2
= List
->CurrentPartition
->ListEntry
.Flink
;
1607 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1609 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1611 // if (PartEntry->HidePartEntry == FALSE)
1613 List
->CurrentPartition
= PartEntry
;
1614 DrawPartitionList (List
);
1617 Entry2
= Entry2
->Flink
;
1621 /* Check for first usable entry on next disk */
1622 if (List
->CurrentDisk
!= NULL
)
1624 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1625 while (Entry1
!= &List
->DiskListHead
)
1627 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1629 Entry2
= DiskEntry
->PartListHead
.Flink
;
1630 while (Entry2
!= &DiskEntry
->PartListHead
)
1632 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1634 // if (PartEntry->HidePartEntry == FALSE)
1636 List
->CurrentDisk
= DiskEntry
;
1637 List
->CurrentPartition
= PartEntry
;
1638 DrawPartitionList (List
);
1642 Entry2
= Entry2
->Flink
;
1645 Entry1
= Entry1
->Flink
;
1652 ScrollUpPartitionList (PPARTLIST List
)
1654 PDISKENTRY DiskEntry
;
1655 PPARTENTRY PartEntry
;
1659 /* Check for empty disks */
1660 if (IsListEmpty (&List
->DiskListHead
))
1663 /* check for previous usable entry on current disk */
1664 if (List
->CurrentPartition
!= NULL
)
1666 Entry2
= List
->CurrentPartition
->ListEntry
.Blink
;
1667 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1669 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1671 // if (PartEntry->HidePartEntry == FALSE)
1673 List
->CurrentPartition
= PartEntry
;
1674 DrawPartitionList (List
);
1677 Entry2
= Entry2
->Blink
;
1682 /* check for last usable entry on previous disk */
1683 if (List
->CurrentDisk
!= NULL
)
1685 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1686 while (Entry1
!= &List
->DiskListHead
)
1688 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1690 Entry2
= DiskEntry
->PartListHead
.Blink
;
1691 while (Entry2
!= &DiskEntry
->PartListHead
)
1693 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1695 // if (PartEntry->HidePartEntry == FALSE)
1697 List
->CurrentDisk
= DiskEntry
;
1698 List
->CurrentPartition
= PartEntry
;
1699 DrawPartitionList (List
);
1703 Entry2
= Entry2
->Blink
;
1706 Entry1
= Entry1
->Blink
;
1713 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1714 PPARTENTRY CurrentEntry
)
1716 PPARTENTRY PrevEntry
;
1719 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1722 Entry
= CurrentEntry
->ListEntry
.Blink
;
1723 while (Entry
!= &DiskEntry
->PartListHead
)
1725 PrevEntry
= CONTAINING_RECORD (Entry
,
1728 if (PrevEntry
->Unpartitioned
== FALSE
)
1731 Entry
= Entry
->Blink
;
1739 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1740 PPARTENTRY CurrentEntry
)
1742 PPARTENTRY NextEntry
;
1745 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1748 Entry
= CurrentEntry
->ListEntry
.Flink
;
1749 while (Entry
!= &DiskEntry
->PartListHead
)
1751 NextEntry
= CONTAINING_RECORD (Entry
,
1754 if (NextEntry
->Unpartitioned
== FALSE
)
1757 Entry
= Entry
->Flink
;
1765 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1766 PPARTENTRY PartEntry
)
1768 PPARTENTRY PrevPartEntry
;
1770 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1772 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1775 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1776 return PrevPartEntry
;
1784 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1785 PPARTENTRY PartEntry
)
1787 PPARTENTRY NextPartEntry
;
1789 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1791 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1794 if (NextPartEntry
->Unpartitioned
== TRUE
)
1795 return NextPartEntry
;
1803 CreateNewPartition (PPARTLIST List
,
1804 ULONGLONG PartitionSize
,
1807 PDISKENTRY DiskEntry
;
1808 PPARTENTRY PartEntry
;
1809 PPARTENTRY PrevPartEntry
;
1810 PPARTENTRY NextPartEntry
;
1811 PPARTENTRY NewPartEntry
;
1814 List
->CurrentDisk
== NULL
||
1815 List
->CurrentPartition
== NULL
||
1816 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1821 DiskEntry
= List
->CurrentDisk
;
1822 PartEntry
= List
->CurrentPartition
;
1824 if (AutoCreate
== TRUE
||
1825 PartitionSize
== PartEntry
->UnpartitionedLength
)
1827 /* Convert current entry to 'new (unformatted)' */
1828 PartEntry
->FormatState
= Unformatted
;
1829 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1830 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1831 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1832 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1833 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1834 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1835 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1836 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1837 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1838 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1840 /* Get previous and next partition entries */
1841 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1843 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1846 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1848 /* Current entry is in the middle of the list */
1850 /* Copy previous container partition data to current entry */
1851 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1852 &PrevPartEntry
->PartInfo
[1],
1853 sizeof(PARTITION_INFORMATION
));
1854 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1856 /* Update previous container partition data */
1858 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1859 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1861 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1863 /* Special case - previous partition is first partition */
1864 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1865 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1869 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1870 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1873 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1875 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1877 /* Current entry is the first entry */
1880 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1882 /* Current entry is the last entry */
1884 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1885 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1887 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1889 /* Special case - previous partition is first partition */
1890 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1891 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1895 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1896 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1899 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
1900 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
1901 (1024LL * 255LL * 63LL * 512LL))
1903 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
1907 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
1910 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1911 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1914 PartEntry
->AutoCreate
= AutoCreate
;
1915 PartEntry
->New
= TRUE
;
1916 PartEntry
->Unpartitioned
= FALSE
;
1917 PartEntry
->UnpartitionedOffset
= 0ULL;
1918 PartEntry
->UnpartitionedLength
= 0ULL;
1922 /* Insert an initialize a new partition entry */
1923 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
1926 if (NewPartEntry
== NULL
)
1929 RtlZeroMemory (NewPartEntry
,
1932 /* Insert the new entry into the list */
1933 InsertTailList (&PartEntry
->ListEntry
,
1934 &NewPartEntry
->ListEntry
);
1936 NewPartEntry
->New
= TRUE
;
1938 NewPartEntry
->FormatState
= Unformatted
;
1939 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1940 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1941 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1942 PartitionSize
- DiskEntry
->TrackSize
;
1943 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1944 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1945 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1946 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1947 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1948 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1950 /* Get previous and next partition entries */
1951 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1953 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1956 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1958 /* Current entry is in the middle of the list */
1960 /* Copy previous container partition data to current entry */
1961 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
1962 &PrevPartEntry
->PartInfo
[1],
1963 sizeof(PARTITION_INFORMATION
));
1964 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1966 /* Update previous container partition data */
1968 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1969 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1971 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1973 /* Special case - previous partition is first partition */
1974 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1975 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1979 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1980 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1983 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1985 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1987 /* Current entry is the first entry */
1990 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1992 /* Current entry is the last entry */
1994 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1995 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1997 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1999 /* Special case - previous partition is first partition */
2000 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2001 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
2005 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
2006 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2009 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
2010 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
2011 (1024LL * 255LL * 63LL * 512LL))
2013 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
2017 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
2020 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
2021 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2024 /* Update offset and size of the remaining unpartitioned disk space */
2025 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
2026 PartEntry
->UnpartitionedLength
-= PartitionSize
;
2029 DiskEntry
->Modified
= TRUE
;
2031 UpdatePartitionNumbers (DiskEntry
);
2033 AssignDriverLetters (List
);
2038 DeleteCurrentPartition (PPARTLIST List
)
2040 PDISKENTRY DiskEntry
;
2041 PPARTENTRY PartEntry
;
2042 PPARTENTRY PrevPartEntry
;
2043 PPARTENTRY NextPartEntry
;
2046 List
->CurrentDisk
== NULL
||
2047 List
->CurrentPartition
== NULL
||
2048 List
->CurrentPartition
->Unpartitioned
== TRUE
)
2053 DiskEntry
= List
->CurrentDisk
;
2054 PartEntry
= List
->CurrentPartition
;
2056 /* Adjust container partition entries */
2058 /* Get previous and next partition entries */
2059 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
2061 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
2064 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2066 /* Current entry is in the middle of the list */
2069 * The first extended partition can not be deleted
2070 * as long as other extended partitions are present.
2072 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
2075 /* Copy previous container partition data to current entry */
2076 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
2077 &PartEntry
->PartInfo
[1],
2078 sizeof(PARTITION_INFORMATION
));
2079 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2081 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2084 * A primary partition can not be deleted as long as
2085 * extended partitions are present.
2089 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2091 /* Current entry is the last entry */
2092 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
2093 sizeof(PARTITION_INFORMATION
));
2094 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
2098 /* Adjust unpartitioned disk space entries */
2100 /* Get pointer to previous and next unpartitioned entries */
2101 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
2104 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
2107 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2109 /* Merge previous, current and next unpartitioned entry */
2111 /* Adjust the previous entries length */
2112 PrevPartEntry
->UnpartitionedLength
+=
2113 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
2114 NextPartEntry
->UnpartitionedLength
);
2116 /* Remove the current entry */
2117 RemoveEntryList (&PartEntry
->ListEntry
);
2118 RtlFreeHeap (ProcessHeap
,
2122 /* Remove the next entry */
2123 RemoveEntryList (&NextPartEntry
->ListEntry
);
2124 RtlFreeHeap (ProcessHeap
,
2128 /* Update current partition */
2129 List
->CurrentPartition
= PrevPartEntry
;
2131 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2133 /* Merge current and previous unpartitioned entry */
2135 /* Adjust the previous entries length */
2136 PrevPartEntry
->UnpartitionedLength
+=
2137 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2139 /* Remove the current entry */
2140 RemoveEntryList (&PartEntry
->ListEntry
);
2141 RtlFreeHeap (ProcessHeap
,
2145 /* Update current partition */
2146 List
->CurrentPartition
= PrevPartEntry
;
2148 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2150 /* Merge current and next unpartitioned entry */
2152 /* Adjust the next entries offset and length */
2153 NextPartEntry
->UnpartitionedOffset
=
2154 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2155 NextPartEntry
->UnpartitionedLength
+=
2156 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
2158 /* Remove the current entry */
2159 RemoveEntryList (&PartEntry
->ListEntry
);
2160 RtlFreeHeap (ProcessHeap
,
2164 /* Update current partition */
2165 List
->CurrentPartition
= NextPartEntry
;
2169 /* Nothing to merge but change current entry */
2170 PartEntry
->New
= FALSE
;
2171 PartEntry
->Unpartitioned
= TRUE
;
2172 PartEntry
->UnpartitionedOffset
=
2173 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
2174 PartEntry
->UnpartitionedLength
=
2175 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
2177 /* Wipe the partition table */
2178 RtlZeroMemory (&PartEntry
->PartInfo
,
2179 sizeof(PartEntry
->PartInfo
));
2182 DiskEntry
->Modified
= TRUE
;
2184 UpdatePartitionNumbers (DiskEntry
);
2186 AssignDriverLetters (List
);
2191 CheckActiveBootPartition (PPARTLIST List
)
2193 PDISKENTRY DiskEntry
;
2194 PPARTENTRY PartEntry
;
2196 /* Check for empty disk list */
2197 if (IsListEmpty (&List
->DiskListHead
))
2199 List
->ActiveBootDisk
= NULL
;
2200 List
->ActiveBootPartition
= NULL
;
2205 if (List
->ActiveBootDisk
!= NULL
&&
2206 List
->ActiveBootPartition
!= NULL
)
2208 /* We already have an active boot partition */
2213 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
2217 /* Check for empty partition list */
2218 if (IsListEmpty (&DiskEntry
->PartListHead
))
2220 List
->ActiveBootDisk
= NULL
;
2221 List
->ActiveBootPartition
= NULL
;
2225 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
2229 /* Set active boot partition */
2230 if ((DiskEntry
->NewDisk
== TRUE
) ||
2231 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
2232 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
2233 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
2234 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
2236 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
2237 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
2238 DiskEntry
->Modified
= TRUE
;
2241 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2242 List
->ActiveBootDisk
= DiskEntry
;
2243 List
->ActiveBootPartition
= PartEntry
;
2248 CheckForLinuxFdiskPartitions (PPARTLIST List
)
2250 PDISKENTRY DiskEntry
;
2251 PPARTENTRY PartEntry
;
2254 ULONG PartitionCount
;
2257 Entry1
= List
->DiskListHead
.Flink
;
2258 while (Entry1
!= &List
->DiskListHead
)
2260 DiskEntry
= CONTAINING_RECORD (Entry1
,
2264 Entry2
= DiskEntry
->PartListHead
.Flink
;
2265 while (Entry2
!= &DiskEntry
->PartListHead
)
2267 PartEntry
= CONTAINING_RECORD (Entry2
,
2271 if (PartEntry
->Unpartitioned
== FALSE
)
2275 for (i
= 0; i
< 4; i
++)
2277 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
2278 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2284 if (PartitionCount
> 1)
2290 Entry2
= Entry2
->Flink
;
2293 Entry1
= Entry1
->Flink
;
2301 WritePartitionsToDisk (PPARTLIST List
)
2303 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
2304 OBJECT_ATTRIBUTES ObjectAttributes
;
2305 IO_STATUS_BLOCK Iosb
;
2306 WCHAR SrcPath
[MAX_PATH
];
2307 WCHAR DstPath
[MAX_PATH
];
2308 UNICODE_STRING Name
;
2310 PDISKENTRY DiskEntry1
;
2311 PDISKENTRY DiskEntry2
;
2312 PPARTENTRY PartEntry
;
2315 ULONG PartitionCount
;
2316 ULONG DriveLayoutSize
;
2325 Entry1
= List
->DiskListHead
.Flink
;
2326 while (Entry1
!= &List
->DiskListHead
)
2328 DiskEntry1
= CONTAINING_RECORD (Entry1
,
2332 if (DiskEntry1
->Modified
== TRUE
)
2334 /* Count partitioned entries */
2336 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2337 while (Entry2
!= &DiskEntry1
->PartListHead
)
2339 PartEntry
= CONTAINING_RECORD (Entry2
,
2342 if (PartEntry
->Unpartitioned
== FALSE
)
2344 PartitionCount
+= 4;
2347 Entry2
= Entry2
->Flink
;
2349 if (PartitionCount
== 0)
2351 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2352 ((4 - 1) * sizeof (PARTITION_INFORMATION
));
2356 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2357 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2359 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
2362 if (DriveLayout
== NULL
)
2364 DPRINT1 ("RtlAllocateHeap() failed\n");
2368 RtlZeroMemory (DriveLayout
,
2371 if (PartitionCount
== 0)
2373 /* delete all partitions in the mbr */
2374 DriveLayout
->PartitionCount
= 4;
2375 for (Index
= 0; Index
< 4; Index
++)
2377 DriveLayout
->PartitionEntry
[Index
].RewritePartition
= TRUE
;
2382 DriveLayout
->PartitionCount
= PartitionCount
;
2385 Entry2
= DiskEntry1
->PartListHead
.Flink
;
2386 while (Entry2
!= &DiskEntry1
->PartListHead
)
2388 PartEntry
= CONTAINING_RECORD (Entry2
,
2391 if (PartEntry
->Unpartitioned
== FALSE
)
2393 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2394 &PartEntry
->PartInfo
[0],
2395 4 * sizeof (PARTITION_INFORMATION
));
2399 Entry2
= Entry2
->Flink
;
2402 if (DiskEntry1
->Signature
== 0)
2404 LARGE_INTEGER SystemTime
;
2405 TIME_FIELDS TimeFields
;
2407 Buffer
= (PUCHAR
)&DiskEntry1
->Signature
;
2411 NtQuerySystemTime (&SystemTime
);
2412 RtlTimeToTimeFields (&SystemTime
, &TimeFields
);
2414 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
2415 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
2416 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
2417 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
2419 if (DiskEntry1
->Signature
== 0)
2424 /* check if the signature already exist */
2426 * Check also signatures from disks, which are
2427 * not visible (bootable) by the bios.
2429 Entry2
= List
->DiskListHead
.Flink
;
2430 while (Entry2
!= &List
->DiskListHead
)
2432 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
2433 if (DiskEntry1
!= DiskEntry2
&&
2434 DiskEntry1
->Signature
== DiskEntry2
->Signature
)
2438 Entry2
= Entry2
->Flink
;
2440 if (Entry2
== &List
->DiskListHead
)
2446 /* set one partition entry to dirty, this will update the signature */
2447 DriveLayout
->PartitionEntry
[0].RewritePartition
= TRUE
;
2451 DriveLayout
->Signature
= DiskEntry1
->Signature
;
2455 L
"\\Device\\Harddisk%d\\Partition0",
2456 DiskEntry1
->DiskNumber
);
2457 RtlInitUnicodeString (&Name
,
2459 InitializeObjectAttributes (&ObjectAttributes
,
2465 Status
= NtOpenFile (&FileHandle
,
2470 FILE_SYNCHRONOUS_IO_NONALERT
);
2472 if (!NT_SUCCESS (Status
))
2474 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2478 Status
= NtDeviceIoControlFile (FileHandle
,
2483 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2488 if (!NT_SUCCESS (Status
))
2490 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2491 NtClose (FileHandle
);
2495 RtlFreeHeap (ProcessHeap
,
2499 NtClose (FileHandle
);
2501 /* Install MBR code if the disk is new */
2502 if (DiskEntry1
->NewDisk
== TRUE
&&
2503 DiskEntry1
->BiosDiskNumber
== 0)
2505 wcscpy (SrcPath
, SourceRootPath
.Buffer
);
2506 wcscat (SrcPath
, L
"\\loader\\dosmbr.bin");
2508 DPRINT ("Install MBR bootcode: %S ==> %S\n",
2511 /* Install MBR bootcode */
2512 Status
= InstallMbrBootCodeToDisk (SrcPath
,
2514 if (!NT_SUCCESS (Status
))
2516 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
2521 DiskEntry1
->NewDisk
= FALSE
;
2525 Entry1
= Entry1
->Flink
;
2531 BOOL
SetMountedDeviceValues(PPARTLIST List
)
2533 PLIST_ENTRY Entry1
, Entry2
;
2534 PDISKENTRY DiskEntry
;
2535 PPARTENTRY PartEntry
;
2542 Entry1
= List
->DiskListHead
.Flink
;
2543 while (Entry1
!= &List
->DiskListHead
)
2545 DiskEntry
= CONTAINING_RECORD (Entry1
,
2549 Entry2
= DiskEntry
->PartListHead
.Flink
;
2550 while (Entry2
!= &DiskEntry
->PartListHead
)
2552 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2553 if (!PartEntry
->Unpartitioned
&& PartEntry
->DriveLetter
)
2555 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
, DiskEntry
->Signature
, PartEntry
->PartInfo
[0].StartingOffset
))
2560 Entry2
= Entry2
->Flink
;
2562 Entry1
= Entry1
->Flink
;