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
;
521 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
522 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
523 return STATUS_SUCCESS
;
525 return STATUS_UNSUCCESSFUL
;
527 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
530 EnumerateBiosDiskEntries(PPARTLIST PartList
)
532 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
537 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
538 PBIOSDISKENTRY BiosDiskEntry
;
540 memset(QueryTable
, 0, sizeof(QueryTable
));
542 QueryTable
[1].Name
= L
"Configuration Data";
543 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
545 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
546 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
550 if (!NT_SUCCESS(Status
))
552 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
559 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
560 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
565 if (!NT_SUCCESS(Status
))
570 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
571 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
576 if (NT_SUCCESS(Status
))
580 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
581 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
586 if (!NT_SUCCESS(Status
))
588 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
592 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
593 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
598 if (NT_SUCCESS(Status
))
600 QueryTable
[0].Name
= L
"Identifier";
601 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
602 QueryTable
[1].Name
= L
"Configuration Data";
603 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
607 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
608 if (BiosDiskEntry
== NULL
)
612 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
613 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
616 (PVOID
)BiosDiskEntry
,
618 if (!NT_SUCCESS(Status
))
620 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
623 BiosDiskEntry
->DiskNumber
= DiskCount
;
624 BiosDiskEntry
->Recognized
= FALSE
;
626 if (DiskCount
< Int13Drives
[0].NumberDrives
)
628 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
632 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
636 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
638 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
639 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
640 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
641 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
642 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
643 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
644 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
645 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
646 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
647 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
648 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
653 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
659 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
663 AddDiskToList (HANDLE FileHandle
,
667 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
668 DISK_GEOMETRY DiskGeometry
;
669 SCSI_ADDRESS ScsiAddress
;
670 PDISKENTRY DiskEntry
;
671 IO_STATUS_BLOCK Iosb
;
673 PPARTITION_SECTOR Mbr
;
675 LARGE_INTEGER FileOffset
;
676 WCHAR Identifier
[20];
680 PLIST_ENTRY ListEntry
;
681 PBIOSDISKENTRY BiosDiskEntry
;
683 Status
= NtDeviceIoControlFile (FileHandle
,
688 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
692 sizeof(DISK_GEOMETRY
));
693 if (!NT_SUCCESS (Status
))
698 if (DiskGeometry
.MediaType
!= FixedMedia
)
703 Status
= NtDeviceIoControlFile (FileHandle
,
708 IOCTL_SCSI_GET_ADDRESS
,
712 sizeof(SCSI_ADDRESS
));
713 if (!NT_SUCCESS(Status
))
718 Mbr
= (PARTITION_SECTOR
*) RtlAllocateHeap(ProcessHeap
,
720 DiskGeometry
.BytesPerSector
);
727 FileOffset
.QuadPart
= 0;
728 Status
= NtReadFile(FileHandle
,
734 DiskGeometry
.BytesPerSector
,
737 if (!NT_SUCCESS(Status
))
739 RtlFreeHeap(ProcessHeap
,
742 DPRINT1("NtReadFile failed, status=%x\n", Status
);
745 Signature
= Mbr
->Signature
;
747 /* Calculate the MBR checksum */
749 Buffer
= (PULONG
)Mbr
;
750 for (i
= 0; i
< 128; i
++)
752 Checksum
+= Buffer
[i
];
754 Checksum
= ~Checksum
+ 1;
756 RtlFreeHeap (ProcessHeap
,
760 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
761 DPRINT("Identifier: %S\n", Identifier
);
763 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
766 if (DiskEntry
== NULL
)
771 DiskEntry
->Checksum
= Checksum
;
772 DiskEntry
->Signature
= Signature
;
775 /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
776 DiskEntry
->Modified
= TRUE
;
778 DiskEntry
->BiosFound
= FALSE
;
780 ListEntry
= List
->BiosDiskListHead
.Flink
;
781 while(ListEntry
!= &List
->BiosDiskListHead
)
783 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
785 * Compare the size from bios and the reported size from driver.
786 * If we have more than one disk with a zero or with the same signatur
787 * we must create new signatures and reboot. After the reboot,
788 * it is possible to identify the disks.
790 if (BiosDiskEntry
->Signature
== Signature
&&
791 BiosDiskEntry
->Checksum
== Checksum
&&
792 !BiosDiskEntry
->Recognized
)
794 if (!DiskEntry
->BiosFound
)
796 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
797 DiskEntry
->BiosFound
= TRUE
;
798 BiosDiskEntry
->Recognized
= TRUE
;
804 ListEntry
= ListEntry
->Flink
;
807 if (!DiskEntry
->BiosFound
)
809 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
813 InitializeListHead (&DiskEntry
->PartListHead
);
815 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
816 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
817 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
818 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
820 DPRINT ("Cylinders %d\n", DiskEntry
->Cylinders
);
821 DPRINT ("TracksPerCylinder %d\n", DiskEntry
->TracksPerCylinder
);
822 DPRINT ("SectorsPerTrack %d\n", DiskEntry
->SectorsPerTrack
);
823 DPRINT ("BytesPerSector %d\n", DiskEntry
->BytesPerSector
);
825 DiskEntry
->DiskSize
=
826 DiskGeometry
.Cylinders
.QuadPart
*
827 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
828 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
829 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
830 DiskEntry
->CylinderSize
=
831 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
832 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
833 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
834 DiskEntry
->TrackSize
=
835 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
836 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
838 DiskEntry
->DiskNumber
= DiskNumber
;
839 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
840 DiskEntry
->Bus
= ScsiAddress
.PathId
;
841 DiskEntry
->Id
= ScsiAddress
.TargetId
;
843 GetDriverName (DiskEntry
);
845 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, BiosDiskNumber
);
847 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
850 if (LayoutBuffer
== NULL
)
855 Status
= NtDeviceIoControlFile (FileHandle
,
860 IOCTL_DISK_GET_DRIVE_LAYOUT
,
865 if (NT_SUCCESS (Status
))
867 if (LayoutBuffer
->PartitionCount
== 0)
869 DiskEntry
->NewDisk
= TRUE
;
872 AddPartitionToList (DiskNumber
,
876 ScanForUnpartitionedDiskSpace (DiskEntry
);
879 RtlFreeHeap (ProcessHeap
,
886 CreatePartitionList (SHORT Left
,
892 OBJECT_ATTRIBUTES ObjectAttributes
;
893 SYSTEM_DEVICE_INFORMATION Sdi
;
894 IO_STATUS_BLOCK Iosb
;
898 WCHAR Buffer
[MAX_PATH
];
902 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
911 List
->Bottom
= Bottom
;
915 List
->TopDisk
= (ULONG
)-1;
916 List
->TopPartition
= (ULONG
)-1;
918 List
->CurrentDisk
= NULL
;
919 List
->CurrentPartition
= NULL
;
921 InitializeListHead (&List
->DiskListHead
);
922 InitializeListHead (&List
->BiosDiskListHead
);
924 EnumerateBiosDiskEntries(List
);
926 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
928 sizeof(SYSTEM_DEVICE_INFORMATION
),
930 if (!NT_SUCCESS (Status
))
932 RtlFreeHeap (ProcessHeap
, 0, List
);
936 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
939 L
"\\Device\\Harddisk%d\\Partition0",
941 RtlInitUnicodeString (&Name
,
944 InitializeObjectAttributes (&ObjectAttributes
,
950 Status
= NtOpenFile (&FileHandle
,
951 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
955 FILE_SYNCHRONOUS_IO_NONALERT
);
956 if (NT_SUCCESS(Status
))
958 AddDiskToList (FileHandle
,
966 AssignDriverLetters (List
);
969 List
->TopPartition
= 0;
971 /* Search for first usable disk and partition */
972 if (IsListEmpty (&List
->DiskListHead
))
974 List
->CurrentDisk
= NULL
;
975 List
->CurrentPartition
= NULL
;
980 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
984 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
986 List
->CurrentPartition
= 0;
990 List
->CurrentPartition
=
991 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
1002 DestroyPartitionList (PPARTLIST List
)
1004 PDISKENTRY DiskEntry
;
1005 PBIOSDISKENTRY BiosDiskEntry
;
1006 PPARTENTRY PartEntry
;
1009 /* Release disk and partition info */
1010 while (!IsListEmpty (&List
->DiskListHead
))
1012 Entry
= RemoveHeadList (&List
->DiskListHead
);
1013 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1015 /* Release driver name */
1016 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1018 /* Release partition array */
1019 while (!IsListEmpty (&DiskEntry
->PartListHead
))
1021 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
1022 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
1024 RtlFreeHeap (ProcessHeap
,
1029 /* Release disk entry */
1030 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
1033 /* release the bios disk info */
1034 while(!IsListEmpty(&List
->BiosDiskListHead
))
1036 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1037 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1039 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1042 /* Release list head */
1043 RtlFreeHeap (ProcessHeap
, 0, List
);
1048 PrintEmptyLine (PPARTLIST List
)
1055 Width
= List
->Right
- List
->Left
- 1;
1056 Height
= List
->Bottom
- List
->Top
- 2;
1059 coPos
.X
= List
->Left
+ 1;
1060 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1062 if (List
->Line
>= 0 && List
->Line
<= Height
)
1064 FillConsoleOutputAttribute (StdOutput
,
1065 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1070 FillConsoleOutputCharacterA (StdOutput
,
1081 PrintPartitionData (PPARTLIST List
,
1082 PDISKENTRY DiskEntry
,
1083 PPARTENTRY PartEntry
)
1085 CHAR LineBuffer
[128];
1091 LARGE_INTEGER PartSize
;
1096 Width
= List
->Right
- List
->Left
- 1;
1097 Height
= List
->Bottom
- List
->Top
- 2;
1100 coPos
.X
= List
->Left
+ 1;
1101 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1103 if (PartEntry
->Unpartitioned
== TRUE
)
1106 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
1108 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
1113 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
1115 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
1120 PartSize
.QuadPart
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
1124 sprintf (LineBuffer
,
1125 " Unpartitioned space %6lu %s",
1131 /* Determine partition type */
1133 if (PartEntry
->New
== TRUE
)
1135 PartType
= "New (Unformatted)";
1137 else if (PartEntry
->Unpartitioned
== FALSE
)
1139 if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
1140 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
1141 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
1142 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
))
1146 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
1147 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
1151 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
1153 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1158 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
1160 PartSize
.QuadPart
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
1165 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
1167 PartSize
.QuadPart
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
1172 PartSize
.QuadPart
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
1176 if (PartType
== NULL
)
1178 sprintf (LineBuffer
,
1179 "%c%c Type %-3u %6lu %s",
1180 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1181 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1182 PartEntry
->PartInfo
[0].PartitionType
,
1188 sprintf (LineBuffer
,
1189 "%c%c %-24s %6lu %s",
1190 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1191 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1198 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1199 List
->CurrentPartition
== PartEntry
) ?
1200 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1201 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1203 if (List
->Line
>= 0 && List
->Line
<= Height
)
1205 FillConsoleOutputCharacterA (StdOutput
,
1213 if (List
->Line
>= 0 && List
->Line
<= Height
)
1215 FillConsoleOutputAttribute (StdOutput
,
1223 if (List
->Line
>= 0 && List
->Line
<= Height
)
1225 WriteConsoleOutputCharacterA (StdOutput
,
1227 min (strlen (LineBuffer
), Width
),
1236 PrintDiskData (PPARTLIST List
,
1237 PDISKENTRY DiskEntry
)
1239 PPARTENTRY PartEntry
;
1240 CHAR LineBuffer
[128];
1245 ULARGE_INTEGER DiskSize
;
1248 Width
= List
->Right
- List
->Left
- 1;
1249 Height
= List
->Bottom
- List
->Top
- 2;
1252 coPos
.X
= List
->Left
+ 1;
1253 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1256 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
1258 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
1264 DiskSize
.QuadPart
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
1265 if (DiskSize
.QuadPart
== 0)
1266 DiskSize
.QuadPart
= 1;
1270 if (DiskEntry
->DriverName
.Length
> 0)
1272 sprintf (LineBuffer
,
1273 "%6lu %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %S",
1276 DiskEntry
->DiskNumber
,
1280 DiskEntry
->DriverName
.Buffer
);
1284 sprintf (LineBuffer
,
1285 "%6lu %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
1288 DiskEntry
->DiskNumber
,
1293 if (List
->Line
>= 0 && List
->Line
<= Height
)
1295 FillConsoleOutputAttribute (StdOutput
,
1296 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1301 FillConsoleOutputCharacterA (StdOutput
,
1309 if (List
->Line
>= 0 && List
->Line
<= Height
)
1311 WriteConsoleOutputCharacterA (StdOutput
,
1313 min ((USHORT
)strlen (LineBuffer
), Width
- 2),
1319 /* Print separator line */
1320 PrintEmptyLine (List
);
1322 /* Print partition lines*/
1323 LIST_FOR_EACH(PartEntry
, &DiskEntry
->PartListHead
, PARTENTRY
, ListEntry
)
1325 /* Print disk entry */
1326 PrintPartitionData (List
,
1331 /* Print separator line */
1332 PrintEmptyLine (List
);
1337 DrawPartitionList (PPARTLIST List
)
1339 PLIST_ENTRY Entry
, Entry2
;
1340 PDISKENTRY DiskEntry
;
1341 PPARTENTRY PartEntry
= NULL
;
1345 SHORT CurrentDiskLine
;
1346 SHORT CurrentPartLine
;
1348 BOOL CurrentPartLineFound
= FALSE
;
1349 BOOL CurrentDiskLineFound
= FALSE
;
1351 /* Calculate the line of the current disk and partition */
1352 CurrentDiskLine
= 0;
1353 CurrentPartLine
= 0;
1355 Entry
= List
->DiskListHead
.Flink
;
1356 while (Entry
!= &List
->DiskListHead
)
1358 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1360 if (CurrentPartLineFound
== FALSE
)
1362 CurrentPartLine
+= 2;
1364 Entry2
= DiskEntry
->PartListHead
.Flink
;
1365 while (Entry2
!= &DiskEntry
->PartListHead
)
1367 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1368 if (PartEntry
== List
->CurrentPartition
)
1370 CurrentPartLineFound
= TRUE
;
1372 Entry2
= Entry2
->Flink
;
1373 if (CurrentPartLineFound
== FALSE
)
1379 if (DiskEntry
== List
->CurrentDisk
)
1381 CurrentDiskLineFound
= TRUE
;
1383 Entry
= Entry
->Flink
;
1384 if (Entry
!= &List
->DiskListHead
)
1386 if (CurrentDiskLineFound
== FALSE
)
1389 CurrentDiskLine
= CurrentPartLine
;
1399 /* If it possible, make the disk name visible */
1400 if (CurrentPartLine
< List
->Offset
)
1402 List
->Offset
= CurrentPartLine
;
1404 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1406 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1408 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1410 List
->Offset
= CurrentDiskLine
;
1414 /* draw upper left corner */
1415 coPos
.X
= List
->Left
;
1416 coPos
.Y
= List
->Top
;
1417 FillConsoleOutputCharacterA (StdOutput
,
1423 /* draw upper edge */
1424 coPos
.X
= List
->Left
+ 1;
1425 coPos
.Y
= List
->Top
;
1426 if (List
->Offset
== 0)
1428 FillConsoleOutputCharacterA (StdOutput
,
1430 List
->Right
- List
->Left
- 1,
1436 FillConsoleOutputCharacterA (StdOutput
,
1438 List
->Right
- List
->Left
- 5,
1441 coPos
.X
= List
->Right
- 5;
1442 WriteConsoleOutputCharacterA (StdOutput
,
1447 coPos
.X
= List
->Right
- 2;
1448 FillConsoleOutputCharacterA (StdOutput
,
1455 /* draw upper right corner */
1456 coPos
.X
= List
->Right
;
1457 coPos
.Y
= List
->Top
;
1458 FillConsoleOutputCharacterA (StdOutput
,
1464 /* draw left and right edge */
1465 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1467 coPos
.X
= List
->Left
;
1469 FillConsoleOutputCharacterA (StdOutput
,
1475 coPos
.X
= List
->Right
;
1476 FillConsoleOutputCharacterA (StdOutput
,
1483 /* draw lower left corner */
1484 coPos
.X
= List
->Left
;
1485 coPos
.Y
= List
->Bottom
;
1486 FillConsoleOutputCharacterA (StdOutput
,
1492 /* draw lower edge */
1493 coPos
.X
= List
->Left
+ 1;
1494 coPos
.Y
= List
->Bottom
;
1495 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1497 FillConsoleOutputCharacterA (StdOutput
,
1499 List
->Right
- List
->Left
- 1,
1505 FillConsoleOutputCharacterA (StdOutput
,
1507 List
->Right
- List
->Left
- 5,
1510 coPos
.X
= List
->Right
- 5;
1511 WriteConsoleOutputCharacterA (StdOutput
,
1512 "(\x19)", // "(down)"
1516 coPos
.X
= List
->Right
- 2;
1517 FillConsoleOutputCharacterA (StdOutput
,
1524 /* draw lower right corner */
1525 coPos
.X
= List
->Right
;
1526 coPos
.Y
= List
->Bottom
;
1527 FillConsoleOutputCharacterA (StdOutput
,
1533 /* print list entries */
1534 List
->Line
= - List
->Offset
;
1536 LIST_FOR_EACH(DiskEntry
, &List
->DiskListHead
, DISKENTRY
, ListEntry
)
1538 /* Print disk entry */
1539 PrintDiskData (List
,
1546 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1548 PDISKENTRY DiskEntry
;
1549 PPARTENTRY PartEntry
;
1554 /* Check for empty disks */
1555 if (IsListEmpty (&List
->DiskListHead
))
1558 /* Check for first usable entry on next disk */
1559 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1560 while (Entry1
!= &List
->DiskListHead
)
1562 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1564 if (DiskEntry
->DiskNumber
== DiskNumber
)
1566 Entry2
= DiskEntry
->PartListHead
.Flink
;
1567 while (Entry2
!= &DiskEntry
->PartListHead
)
1569 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1571 for (i
= 0; i
< 4; i
++)
1573 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1575 List
->CurrentDisk
= DiskEntry
;
1576 List
->CurrentPartition
= PartEntry
;
1577 DrawPartitionList (List
);
1581 Entry2
= Entry2
->Flink
;
1585 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
;