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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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)
34 #define DUMP_PARTITION_TABLE
36 /* FUNCTIONS ****************************************************************/
38 #ifdef DUMP_PARTITION_TABLE
44 PPARTITION_INFORMATION PartitionInfo
;
47 for (i
= 0; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
49 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[i
];
50 DbgPrint("%lu: %12I64u %12I64u %10lu %2lu %2x %c %c\n",
52 PartitionInfo
->StartingOffset
.QuadPart
,
53 PartitionInfo
->PartitionLength
.QuadPart
,
54 PartitionInfo
->HiddenSectors
,
55 PartitionInfo
->PartitionNumber
,
56 PartitionInfo
->PartitionType
,
57 PartitionInfo
->BootIndicator
? '*': ' ',
58 PartitionInfo
->RewritePartition
? 'Y': 'N');
71 Temp
= Value
/ Alignment
;
73 return Temp
* Alignment
;
79 IN ULONGLONG Dividend
,
82 return (Dividend
+ Divisor
/ 2) / Divisor
;
91 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
95 RtlInitUnicodeString(&DiskEntry
->DriverName
,
99 L
"\\Scsi\\Scsi Port %lu",
102 RtlZeroMemory(&QueryTable
,
105 QueryTable
[0].Name
= L
"Driver";
106 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
107 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
109 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
114 if (!NT_SUCCESS(Status
))
116 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
126 PDISKENTRY DiskEntry
;
127 PPARTENTRY PartEntry
;
134 /* Assign drive letters to primary partitions */
135 Entry1
= List
->DiskListHead
.Flink
;
136 while (Entry1
!= &List
->DiskListHead
)
138 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
140 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
141 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
143 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
145 PartEntry
->DriveLetter
= 0;
147 if (PartEntry
->IsPartitioned
&&
148 !IsContainerPartition(PartEntry
->PartitionType
))
150 if (IsRecognizedPartition(PartEntry
->PartitionType
) ||
151 (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
152 PartEntry
->SectorCount
.QuadPart
!= 0LL))
156 PartEntry
->DriveLetter
= Letter
;
162 Entry2
= Entry2
->Flink
;
165 Entry1
= Entry1
->Flink
;
168 /* Assign drive letters to logical drives */
170 Entry1
= List
->DiskListHead
.Flink
;
171 while (Entry1
!= &List
->DiskListHead
)
173 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
175 Entry2
= DiskEntry
->PartListHead
.Flink
;
176 if (Entry2
!= &DiskEntry
->PartListHead
)
178 Entry2
= Entry2
->Flink
;
179 while (Entry2
!= &DiskEntry
->PartListHead
)
181 PartEntry
= CONTAINING_RECORD(Entry2
,
185 PartEntry
->DriveLetter
= 0;
187 if (PartEntry
->Unpartitioned
== FALSE
&&
188 !IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
190 if (IsRecognizedPartition(PartEntry
->PartInfo
[0].PartitionType
) ||
191 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
192 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
196 PartEntry
->DriveLetter
= Letter
;
202 Entry2
= Entry2
->Flink
;
206 Entry1
= Entry1
->Flink
;
214 UpdatePartitionNumbers(
215 PDISKENTRY DiskEntry
)
217 PPARTENTRY PartEntry
;
219 // ULONG PartitionNumber = 1;
220 ULONG PartitionIndex
= 0;
222 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
223 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
225 PartEntry
= CONTAINING_RECORD(Entry
,
229 if (PartEntry
->IsPartitioned
== FALSE
)
231 // PartEntry->PartitionNumber = 0;
232 PartEntry
->PartitionIndex
= (ULONG
)-1;
236 if (IsContainerPartition(PartEntry
->PartitionType
))
238 // PartEntry->PartitionNumber = 0;
240 else if (PartEntry
->PartitionType
== PARTITION_ENTRY_UNUSED
&&
241 PartEntry
->SectorCount
.QuadPart
== 0ULL)
243 // PartEntry->PartitionNumber = 0;
247 // PartEntry->PartitionNumber = PartitionNumber++;
250 PartEntry
->PartitionIndex
= PartitionIndex
++;
253 Entry
= Entry
->Flink
;
260 DiskIdentifierQueryRoutine(
268 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
269 UNICODE_STRING NameU
;
271 if (ValueType
== REG_SZ
&&
272 ValueLength
== 20 * sizeof(WCHAR
))
274 NameU
.Buffer
= (PWCHAR
)ValueData
;
275 NameU
.Length
= NameU
.MaximumLength
= 8 * sizeof(WCHAR
);
276 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Checksum
);
278 NameU
.Buffer
= (PWCHAR
)ValueData
+ 9;
279 RtlUnicodeStringToInteger(&NameU
, 16, &BiosDiskEntry
->Signature
);
281 return STATUS_SUCCESS
;
284 return STATUS_UNSUCCESSFUL
;
290 DiskConfigurationDataQueryRoutine(
298 PBIOSDISKENTRY BiosDiskEntry
= (PBIOSDISKENTRY
)Context
;
299 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
300 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
;
303 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
304 ValueLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
305 return STATUS_UNSUCCESSFUL
;
307 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
309 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
311 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
312 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
313 return STATUS_UNSUCCESSFUL
;
316 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
318 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
319 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
!= sizeof(CM_DISK_GEOMETRY_DEVICE_DATA
))
322 DiskGeometry
= (PCM_DISK_GEOMETRY_DEVICE_DATA
)&FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1];
323 BiosDiskEntry
->DiskGeometry
= *DiskGeometry
;
325 return STATUS_SUCCESS
;
328 return STATUS_UNSUCCESSFUL
;
334 SystemConfigurationDataQueryRoutine(
342 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
;
343 PCM_INT13_DRIVE_PARAMETER
* Int13Drives
= (PCM_INT13_DRIVE_PARAMETER
*)Context
;
346 if (ValueType
!= REG_FULL_RESOURCE_DESCRIPTOR
||
347 ValueLength
< sizeof (CM_FULL_RESOURCE_DESCRIPTOR
))
348 return STATUS_UNSUCCESSFUL
;
350 FullResourceDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)ValueData
;
352 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
354 if (FullResourceDescriptor
->PartialResourceList
.Version
!= 1 ||
355 FullResourceDescriptor
->PartialResourceList
.Revision
!= 1)
356 return STATUS_UNSUCCESSFUL
;
359 for (i
= 0; i
< FullResourceDescriptor
->PartialResourceList
.Count
; i
++)
361 if (FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].Type
!= CmResourceTypeDeviceSpecific
||
362 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
% sizeof(CM_INT13_DRIVE_PARAMETER
) != 0)
365 *Int13Drives
= (CM_INT13_DRIVE_PARAMETER
*) RtlAllocateHeap(ProcessHeap
, 0, FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
366 if (*Int13Drives
== NULL
)
367 return STATUS_NO_MEMORY
;
370 &FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
+ 1],
371 FullResourceDescriptor
->PartialResourceList
.PartialDescriptors
[i
].u
.DeviceSpecificData
.DataSize
);
372 return STATUS_SUCCESS
;
375 return STATUS_UNSUCCESSFUL
;
379 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
382 EnumerateBiosDiskEntries(
385 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
390 PCM_INT13_DRIVE_PARAMETER Int13Drives
;
391 PBIOSDISKENTRY BiosDiskEntry
;
393 memset(QueryTable
, 0, sizeof(QueryTable
));
395 QueryTable
[1].Name
= L
"Configuration Data";
396 QueryTable
[1].QueryRoutine
= SystemConfigurationDataQueryRoutine
;
398 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
399 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
403 if (!NT_SUCCESS(Status
))
405 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status
);
412 swprintf(Name
, L
"%s\\%lu", ROOT_NAME
, AdapterCount
);
413 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
418 if (!NT_SUCCESS(Status
))
423 swprintf(Name
, L
"%s\\%lu\\DiskController", ROOT_NAME
, AdapterCount
);
424 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
429 if (NT_SUCCESS(Status
))
433 swprintf(Name
, L
"%s\\%lu\\DiskController\\0", ROOT_NAME
, AdapterCount
);
434 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
439 if (!NT_SUCCESS(Status
))
441 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
445 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME
, AdapterCount
);
446 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
451 if (NT_SUCCESS(Status
))
453 QueryTable
[0].Name
= L
"Identifier";
454 QueryTable
[0].QueryRoutine
= DiskIdentifierQueryRoutine
;
455 QueryTable
[1].Name
= L
"Configuration Data";
456 QueryTable
[1].QueryRoutine
= DiskConfigurationDataQueryRoutine
;
461 BiosDiskEntry
= (BIOSDISKENTRY
*) RtlAllocateHeap(ProcessHeap
, HEAP_ZERO_MEMORY
, sizeof(BIOSDISKENTRY
));
462 if (BiosDiskEntry
== NULL
)
467 swprintf(Name
, L
"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME
, AdapterCount
, DiskCount
);
468 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
471 (PVOID
)BiosDiskEntry
,
473 if (!NT_SUCCESS(Status
))
475 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
479 BiosDiskEntry
->DiskNumber
= DiskCount
;
480 BiosDiskEntry
->Recognized
= FALSE
;
482 if (DiskCount
< Int13Drives
[0].NumberDrives
)
484 BiosDiskEntry
->Int13DiskData
= Int13Drives
[DiskCount
];
488 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount
);
491 InsertTailList(&PartList
->BiosDiskListHead
, &BiosDiskEntry
->ListEntry
);
493 DPRINT("DiskNumber: %lu\n", BiosDiskEntry
->DiskNumber
);
494 DPRINT("Signature: %08lx\n", BiosDiskEntry
->Signature
);
495 DPRINT("Checksum: %08lx\n", BiosDiskEntry
->Checksum
);
496 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry
->DiskGeometry
.BytesPerSector
);
497 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfCylinders
);
498 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry
->DiskGeometry
.NumberOfHeads
);
499 DPRINT("DriveSelect: %02x\n", BiosDiskEntry
->Int13DiskData
.DriveSelect
);
500 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry
->Int13DiskData
.MaxCylinders
);
501 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry
->Int13DiskData
.SectorsPerTrack
);
502 DPRINT("MaxHeads: %d\n", BiosDiskEntry
->Int13DiskData
.MaxHeads
);
503 DPRINT("NumberDrives: %d\n", BiosDiskEntry
->Int13DiskData
.NumberDrives
);
509 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
517 RtlFreeHeap(ProcessHeap
, 0, Int13Drives
);
523 AddPrimaryPartitionToDisk(
525 PDISKENTRY DiskEntry
,
526 ULONG PartitionIndex
)
528 PPARTITION_INFORMATION PartitionInfo
;
529 PPARTENTRY PartEntry
;
531 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[PartitionIndex
];
533 PartEntry
= RtlAllocateHeap(ProcessHeap
,
536 if (PartEntry
== NULL
)
541 PartEntry
->StartSector
.QuadPart
= (ULONGLONG
)PartitionInfo
->StartingOffset
.QuadPart
/ DiskEntry
->BytesPerSector
;
542 PartEntry
->SectorCount
.QuadPart
= (ULONGLONG
)PartitionInfo
->PartitionLength
.QuadPart
/ DiskEntry
->BytesPerSector
;
544 PartEntry
->BootIndicator
= PartitionInfo
->BootIndicator
;
545 PartEntry
->PartitionType
= PartitionInfo
->PartitionType
;
546 PartEntry
->HiddenSectors
= PartitionInfo
->HiddenSectors
;
548 PartEntry
->IsPartitioned
= TRUE
;
549 PartEntry
->PartitionNumber
= PartitionInfo
->PartitionNumber
;
550 PartEntry
->PartitionIndex
= PartitionIndex
;
552 if (IsContainerPartition(PartEntry
->PartitionType
))
554 PartEntry
->FormatState
= Unformatted
;
556 else if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
557 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
558 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
559 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
560 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
561 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
564 if (CheckFatFormat())
566 PartEntry
->FormatState
= Preformatted
;
570 PartEntry
->FormatState
= Unformatted
;
573 PartEntry
->FormatState
= Preformatted
;
575 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
578 if (CheckExt2Format())
580 PartEntry
->FormatState
= Preformatted
;
584 PartEntry
->FormatState
= Unformatted
;
587 PartEntry
->FormatState
= Preformatted
;
589 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
592 if (CheckNtfsFormat())
594 PartEntry
->FormatState
= Preformatted
;
596 else if (CheckHpfsFormat())
598 PartEntry
->FormatState
= Preformatted
;
602 PartEntry
->FormatState
= Unformatted
;
605 PartEntry
->FormatState
= Preformatted
;
609 PartEntry
->FormatState
= UnknownFormat
;
612 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
613 &PartEntry
->ListEntry
);
619 ScanForUnpartitionedDiskSpace(
620 PDISKENTRY DiskEntry
)
622 ULONGLONG LastStartSector
;
623 ULONGLONG LastSectorCount
;
624 ULONGLONG LastUnusedSectorCount
;
625 PPARTENTRY PartEntry
;
626 PPARTENTRY NewPartEntry
;
629 DPRINT1("ScanForUnpartitionedDiskSpace()\n");
631 if (IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
633 DPRINT1("No primary partition!\n");
635 /* Create a partition table that represents the empty disk */
636 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
639 if (NewPartEntry
== NULL
)
642 NewPartEntry
->DiskEntry
= DiskEntry
;
644 NewPartEntry
->IsPartitioned
= FALSE
;
645 NewPartEntry
->StartSector
.QuadPart
= (ULONGLONG
)DiskEntry
->SectorsPerTrack
;
646 NewPartEntry
->SectorCount
.QuadPart
= Align(DiskEntry
->SectorCount
.QuadPart
, DiskEntry
->SectorAlignment
) -
647 DiskEntry
->SectorsPerTrack
;
648 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
649 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
650 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
652 NewPartEntry
->FormatState
= Unformatted
;
654 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
655 &NewPartEntry
->ListEntry
);
660 /* Start partition at head 1, cylinder 0 */
661 LastStartSector
= DiskEntry
->SectorsPerTrack
;
662 LastSectorCount
= 0ULL;
663 LastUnusedSectorCount
= 0ULL;
665 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
666 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
668 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
670 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
||
671 PartEntry
->SectorCount
.QuadPart
!= 0ULL)
673 LastUnusedSectorCount
=
674 PartEntry
->StartSector
.QuadPart
- (LastStartSector
+ LastSectorCount
);
676 if (PartEntry
->StartSector
.QuadPart
> (LastStartSector
+ LastSectorCount
) &&
677 LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
679 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount
);
681 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
684 if (NewPartEntry
== NULL
)
687 NewPartEntry
->DiskEntry
= DiskEntry
;
689 NewPartEntry
->IsPartitioned
= FALSE
;
690 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
691 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
692 NewPartEntry
->StartSector
.QuadPart
;
693 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
694 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
695 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
697 NewPartEntry
->FormatState
= Unformatted
;
699 /* Insert the table into the list */
700 InsertTailList(&PartEntry
->ListEntry
,
701 &NewPartEntry
->ListEntry
);
704 LastStartSector
= PartEntry
->StartSector
.QuadPart
;
705 LastSectorCount
= PartEntry
->SectorCount
.QuadPart
;
708 Entry
= Entry
->Flink
;
711 /* Check for trailing unpartitioned disk space */
712 if ((LastStartSector
+ LastSectorCount
) < DiskEntry
->SectorCount
.QuadPart
)
714 LastUnusedSectorCount
= Align(DiskEntry
->SectorCount
.QuadPart
- (LastStartSector
+ LastSectorCount
), DiskEntry
->SectorAlignment
);
716 if (LastUnusedSectorCount
>= (ULONGLONG
)DiskEntry
->SectorAlignment
)
718 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount
);
720 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
723 if (NewPartEntry
== NULL
)
726 NewPartEntry
->DiskEntry
= DiskEntry
;
728 NewPartEntry
->IsPartitioned
= FALSE
;
729 NewPartEntry
->StartSector
.QuadPart
= LastStartSector
+ LastSectorCount
;
730 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ LastUnusedSectorCount
, DiskEntry
->SectorAlignment
) -
731 NewPartEntry
->StartSector
.QuadPart
;
732 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
733 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
734 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
736 NewPartEntry
->FormatState
= Unformatted
;
738 /* Append the table to the list */
739 InsertTailList(&DiskEntry
->PrimaryPartListHead
,
740 &NewPartEntry
->ListEntry
);
744 DPRINT1("ScanForUnpartitionedDiskSpace() done\n");
752 IN PDISKENTRY DiskEntry
)
754 LARGE_INTEGER SystemTime
;
755 TIME_FIELDS TimeFields
;
757 PDISKENTRY DiskEntry2
;
760 Buffer
= (PUCHAR
)&DiskEntry
->LayoutBuffer
->Signature
;
764 NtQuerySystemTime(&SystemTime
);
765 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
767 Buffer
[0] = (UCHAR
)(TimeFields
.Year
& 0xFF) + (UCHAR
)(TimeFields
.Hour
& 0xFF);
768 Buffer
[1] = (UCHAR
)(TimeFields
.Year
>> 8) + (UCHAR
)(TimeFields
.Minute
& 0xFF);
769 Buffer
[2] = (UCHAR
)(TimeFields
.Month
& 0xFF) + (UCHAR
)(TimeFields
.Second
& 0xFF);
770 Buffer
[3] = (UCHAR
)(TimeFields
.Day
& 0xFF) + (UCHAR
)(TimeFields
.Milliseconds
& 0xFF);
772 if (DiskEntry
->LayoutBuffer
->Signature
== 0)
777 /* check if the signature already exist */
779 * Check also signatures from disks, which are
780 * not visible (bootable) by the bios.
782 Entry2
= List
->DiskListHead
.Flink
;
783 while (Entry2
!= &List
->DiskListHead
)
785 DiskEntry2
= CONTAINING_RECORD(Entry2
, DISKENTRY
, ListEntry
);
787 if (DiskEntry
!= DiskEntry2
&&
788 DiskEntry
->LayoutBuffer
->Signature
== DiskEntry2
->LayoutBuffer
->Signature
)
791 Entry2
= Entry2
->Flink
;
794 if (Entry2
== &List
->DiskListHead
)
802 UpdateDiskSignatures(
806 PDISKENTRY DiskEntry
;
808 /* Print partition lines*/
809 Entry
= List
->DiskListHead
.Flink
;
810 while (Entry
!= &List
->DiskListHead
)
812 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
814 if (DiskEntry
->LayoutBuffer
&&
815 DiskEntry
->LayoutBuffer
->Signature
== 0)
817 SetDiskSignature(List
, DiskEntry
);
818 DiskEntry
->LayoutBuffer
->PartitionEntry
[0].RewritePartition
= TRUE
;
821 Entry
= Entry
->Flink
;
833 DISK_GEOMETRY DiskGeometry
;
834 SCSI_ADDRESS ScsiAddress
;
835 PDISKENTRY DiskEntry
;
836 IO_STATUS_BLOCK Iosb
;
838 PPARTITION_SECTOR Mbr
;
840 LARGE_INTEGER FileOffset
;
841 WCHAR Identifier
[20];
845 PLIST_ENTRY ListEntry
;
846 PBIOSDISKENTRY BiosDiskEntry
;
847 ULONG LayoutBufferSize
;
849 Status
= NtDeviceIoControlFile(FileHandle
,
854 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
858 sizeof(DISK_GEOMETRY
));
859 if (!NT_SUCCESS(Status
))
864 if (DiskGeometry
.MediaType
!= FixedMedia
&&
865 DiskGeometry
.MediaType
!= RemovableMedia
)
870 Status
= NtDeviceIoControlFile(FileHandle
,
875 IOCTL_SCSI_GET_ADDRESS
,
879 sizeof(SCSI_ADDRESS
));
880 if (!NT_SUCCESS(Status
))
885 Mbr
= (PARTITION_SECTOR
*)RtlAllocateHeap(ProcessHeap
,
887 DiskGeometry
.BytesPerSector
);
893 FileOffset
.QuadPart
= 0;
894 Status
= NtReadFile(FileHandle
,
900 DiskGeometry
.BytesPerSector
,
903 if (!NT_SUCCESS(Status
))
905 RtlFreeHeap(ProcessHeap
,
908 DPRINT1("NtReadFile failed, status=%x\n", Status
);
911 Signature
= Mbr
->Signature
;
913 /* Calculate the MBR checksum */
915 Buffer
= (PULONG
)Mbr
;
916 for (i
= 0; i
< 128; i
++)
918 Checksum
+= Buffer
[i
];
920 Checksum
= ~Checksum
+ 1;
922 swprintf(Identifier
, L
"%08x-%08x-A", Checksum
, Signature
);
923 DPRINT("Identifier: %S\n", Identifier
);
925 DiskEntry
= RtlAllocateHeap(ProcessHeap
,
928 if (DiskEntry
== NULL
)
933 // DiskEntry->Checksum = Checksum;
934 // DiskEntry->Signature = Signature;
935 DiskEntry
->BiosFound
= FALSE
;
937 /* Check if this disk has a valid MBR */
938 if (Mbr
->BootCode
[0] == 0 && Mbr
->BootCode
[1] == 0)
939 DiskEntry
->NoMbr
= TRUE
;
941 DiskEntry
->NoMbr
= FALSE
;
943 /* Free Mbr sector buffer */
944 RtlFreeHeap(ProcessHeap
,
948 ListEntry
= List
->BiosDiskListHead
.Flink
;
949 while(ListEntry
!= &List
->BiosDiskListHead
)
951 BiosDiskEntry
= CONTAINING_RECORD(ListEntry
, BIOSDISKENTRY
, ListEntry
);
953 * Compare the size from bios and the reported size from driver.
954 * If we have more than one disk with a zero or with the same signatur
955 * we must create new signatures and reboot. After the reboot,
956 * it is possible to identify the disks.
958 if (BiosDiskEntry
->Signature
== Signature
&&
959 BiosDiskEntry
->Checksum
== Checksum
&&
960 !BiosDiskEntry
->Recognized
)
962 if (!DiskEntry
->BiosFound
)
964 DiskEntry
->BiosDiskNumber
= BiosDiskEntry
->DiskNumber
;
965 DiskEntry
->BiosFound
= TRUE
;
966 BiosDiskEntry
->Recognized
= TRUE
;
972 ListEntry
= ListEntry
->Flink
;
975 if (!DiskEntry
->BiosFound
)
978 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
981 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber
);
985 InitializeListHead(&DiskEntry
->PrimaryPartListHead
);
986 InitializeListHead(&DiskEntry
->ExtendedPartListHead
);
988 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
989 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
990 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
991 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
993 DPRINT("Cylinders %I64u\n", DiskEntry
->Cylinders
);
994 DPRINT("TracksPerCylinder %I64u\n", DiskEntry
->TracksPerCylinder
);
995 DPRINT("SectorsPerTrack %I64u\n", DiskEntry
->SectorsPerTrack
);
996 DPRINT("BytesPerSector %I64u\n", DiskEntry
->BytesPerSector
);
998 DiskEntry
->SectorCount
.QuadPart
= DiskGeometry
.Cylinders
.QuadPart
*
999 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
1000 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
;
1002 DiskEntry
->SectorAlignment
= DiskGeometry
.SectorsPerTrack
;
1004 DPRINT("SectorCount %I64u\n", DiskEntry
->SectorCount
);
1005 DPRINT("SectorAlignment %lu\n", DiskEntry
->SectorAlignment
);
1007 DiskEntry
->DiskNumber
= DiskNumber
;
1008 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
1009 DiskEntry
->Bus
= ScsiAddress
.PathId
;
1010 DiskEntry
->Id
= ScsiAddress
.TargetId
;
1012 GetDriverName(DiskEntry
);
1014 InsertAscendingList(&List
->DiskListHead
, DiskEntry
, DISKENTRY
, ListEntry
, DiskNumber
);
1017 * Allocate a buffer for 26 logical drives (2 entries each == 52)
1018 * plus the main partiton table (4 entries). Total 56 entries.
1020 LayoutBufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
1021 ((56 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
1022 DiskEntry
->LayoutBuffer
= RtlAllocateHeap(ProcessHeap
,
1025 if (DiskEntry
->LayoutBuffer
== NULL
)
1030 Status
= NtDeviceIoControlFile(FileHandle
,
1035 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1038 DiskEntry
->LayoutBuffer
,
1040 if (NT_SUCCESS(Status
))
1042 #ifdef DUMP_PARTITION_TABLE
1043 DumpPartitionTable(DiskEntry
);
1046 if (DiskEntry
->LayoutBuffer
->PartitionCount
== 0)
1048 DiskEntry
->NewDisk
= TRUE
;
1049 DiskEntry
->LayoutBuffer
->PartitionCount
= 4;
1051 for (i
= 0; i
< 4; i
++)
1052 DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].RewritePartition
= TRUE
;
1056 for (i
= 0; i
< 4; i
++)
1058 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].PartitionType
!= 0)
1060 AddPrimaryPartitionToDisk(DiskNumber
,
1066 for (i
= 4; i
< DiskEntry
->LayoutBuffer
->PartitionCount
; i
++)
1068 if (DiskEntry
->LayoutBuffer
->PartitionEntry
[i
].PartitionType
!= 0)
1071 AddExtendedPartitionToDisk(DiskNumber
,
1080 ScanForUnpartitionedDiskSpace(DiskEntry
);
1085 CreatePartitionList(
1092 OBJECT_ATTRIBUTES ObjectAttributes
;
1093 SYSTEM_DEVICE_INFORMATION Sdi
;
1094 IO_STATUS_BLOCK Iosb
;
1098 WCHAR Buffer
[MAX_PATH
];
1099 UNICODE_STRING Name
;
1102 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
,
1110 List
->Right
= Right
;
1111 List
->Bottom
= Bottom
;
1116 List
->TopDisk
= (ULONG
)-1;
1117 List
->TopPartition
= (ULONG
)-1;
1119 List
->CurrentDisk
= NULL
;
1120 List
->CurrentPartition
= NULL
;
1122 InitializeListHead(&List
->DiskListHead
);
1123 InitializeListHead(&List
->BiosDiskListHead
);
1125 EnumerateBiosDiskEntries(List
);
1127 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
1129 sizeof(SYSTEM_DEVICE_INFORMATION
),
1131 if (!NT_SUCCESS(Status
))
1133 RtlFreeHeap(ProcessHeap
, 0, List
);
1137 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
1140 L
"\\Device\\Harddisk%d\\Partition0",
1142 RtlInitUnicodeString(&Name
,
1145 InitializeObjectAttributes(&ObjectAttributes
,
1151 Status
= NtOpenFile(&FileHandle
,
1152 FILE_READ_DATA
| FILE_READ_ATTRIBUTES
| SYNCHRONIZE
,
1156 FILE_SYNCHRONOUS_IO_NONALERT
);
1157 if (NT_SUCCESS(Status
))
1159 AddDiskToList(FileHandle
,
1163 NtClose(FileHandle
);
1167 UpdateDiskSignatures(List
);
1169 AssignDriveLetters(List
);
1172 List
->TopPartition
= 0;
1174 /* Search for first usable disk and partition */
1175 if (IsListEmpty(&List
->DiskListHead
))
1177 List
->CurrentDisk
= NULL
;
1178 List
->CurrentPartition
= NULL
;
1182 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
1186 if (IsListEmpty(&List
->CurrentDisk
->PrimaryPartListHead
))
1188 List
->CurrentPartition
= 0;
1192 List
->CurrentPartition
= CONTAINING_RECORD(List
->CurrentDisk
->PrimaryPartListHead
.Flink
,
1203 DestroyPartitionList(
1206 PDISKENTRY DiskEntry
;
1207 PBIOSDISKENTRY BiosDiskEntry
;
1208 PPARTENTRY PartEntry
;
1211 /* Release disk and partition info */
1212 while (!IsListEmpty(&List
->DiskListHead
))
1214 Entry
= RemoveHeadList(&List
->DiskListHead
);
1215 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1217 /* Release driver name */
1218 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
1220 /* Release primary partition list */
1221 while (!IsListEmpty(&DiskEntry
->PrimaryPartListHead
))
1223 Entry
= RemoveHeadList(&DiskEntry
->PrimaryPartListHead
);
1224 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1226 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1229 /* Release extended partition list */
1230 while (!IsListEmpty(&DiskEntry
->ExtendedPartListHead
))
1232 Entry
= RemoveHeadList(&DiskEntry
->ExtendedPartListHead
);
1233 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1235 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
1238 /* Release layout buffer */
1239 if (DiskEntry
->LayoutBuffer
!= NULL
)
1240 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->LayoutBuffer
);
1243 /* Release disk entry */
1244 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
);
1247 /* release the bios disk info */
1248 while(!IsListEmpty(&List
->BiosDiskListHead
))
1250 Entry
= RemoveHeadList(&List
->BiosDiskListHead
);
1251 BiosDiskEntry
= CONTAINING_RECORD(Entry
, BIOSDISKENTRY
, ListEntry
);
1253 RtlFreeHeap(ProcessHeap
, 0, BiosDiskEntry
);
1256 /* Release list head */
1257 RtlFreeHeap(ProcessHeap
, 0, List
);
1271 Width
= List
->Right
- List
->Left
- 1;
1272 Height
= List
->Bottom
- List
->Top
- 2;
1274 coPos
.X
= List
->Left
+ 1;
1275 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1277 if (List
->Line
>= 0 && List
->Line
<= Height
)
1279 FillConsoleOutputAttribute(StdOutput
,
1280 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1285 FillConsoleOutputCharacterA(StdOutput
,
1300 PDISKENTRY DiskEntry
,
1301 PPARTENTRY PartEntry
)
1303 CHAR LineBuffer
[128];
1308 LARGE_INTEGER PartSize
;
1313 Width
= List
->Right
- List
->Left
- 1;
1314 Height
= List
->Bottom
- List
->Top
- 2;
1316 coPos
.X
= List
->Left
+ 1;
1317 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1319 if (PartEntry
->IsPartitioned
== FALSE
)
1321 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1323 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1325 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1326 Unit
= MUIGetString(STRING_GB
);
1330 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1332 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1333 Unit
= MUIGetString(STRING_MB
);
1337 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1338 Unit
= MUIGetString(STRING_KB
);
1342 MUIGetString(STRING_UNPSPACE
),
1348 /* Determine partition type */
1350 if (PartEntry
->New
== TRUE
)
1352 PartType
= MUIGetString(STRING_UNFORMATTED
);
1354 else if (PartEntry
->IsPartitioned
== TRUE
)
1356 if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
1357 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
1358 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
1359 (PartEntry
->PartitionType
== PARTITION_XINT13
))
1363 else if ((PartEntry
->PartitionType
== PARTITION_FAT32
) ||
1364 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
1368 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
1372 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
1374 PartType
= "NTFS"; /* FIXME: Not quite correct! */
1378 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1380 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
1382 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
1383 Unit
= MUIGetString(STRING_GB
);
1387 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
1389 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
1390 Unit
= MUIGetString(STRING_MB
);
1394 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
1395 Unit
= MUIGetString(STRING_KB
);
1398 if (PartType
== NULL
)
1401 MUIGetString(STRING_HDDINFOUNK5
),
1402 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1403 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1404 PartEntry
->PartitionType
,
1411 "%c%c %-24s %6lu %s",
1412 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
1413 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
1420 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
1421 List
->CurrentPartition
== PartEntry
) ?
1422 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
1423 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
1425 if (List
->Line
>= 0 && List
->Line
<= Height
)
1427 FillConsoleOutputCharacterA(StdOutput
,
1435 if (List
->Line
>= 0 && List
->Line
<= Height
)
1437 FillConsoleOutputAttribute(StdOutput
,
1445 if (List
->Line
>= 0 && List
->Line
<= Height
)
1447 WriteConsoleOutputCharacterA(StdOutput
,
1449 min(strlen(LineBuffer
), Width
),
1462 PDISKENTRY DiskEntry
)
1464 PPARTENTRY PartEntry
;
1466 CHAR LineBuffer
[128];
1471 ULARGE_INTEGER DiskSize
;
1474 Width
= List
->Right
- List
->Left
- 1;
1475 Height
= List
->Bottom
- List
->Top
- 2;
1477 coPos
.X
= List
->Left
+ 1;
1478 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
1480 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
1481 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
1483 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
1484 Unit
= MUIGetString(STRING_GB
);
1488 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
1489 if (DiskSize
.QuadPart
== 0)
1490 DiskSize
.QuadPart
= 1;
1491 Unit
= MUIGetString(STRING_MB
);
1494 if (DiskEntry
->DriverName
.Length
> 0)
1497 MUIGetString(STRING_HDINFOPARTSELECT
),
1500 DiskEntry
->DiskNumber
,
1504 DiskEntry
->DriverName
.Buffer
);
1509 MUIGetString(STRING_HDDINFOUNK6
),
1512 DiskEntry
->DiskNumber
,
1518 if (List
->Line
>= 0 && List
->Line
<= Height
)
1520 FillConsoleOutputAttribute(StdOutput
,
1521 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
1526 FillConsoleOutputCharacterA(StdOutput
,
1534 if (List
->Line
>= 0 && List
->Line
<= Height
)
1536 WriteConsoleOutputCharacterA(StdOutput
,
1538 min((USHORT
)strlen(LineBuffer
), Width
- 2),
1545 /* Print separator line */
1546 PrintEmptyLine(List
);
1548 /* Print partition lines*/
1549 Entry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1550 while (Entry
!= &DiskEntry
->PrimaryPartListHead
)
1552 PartEntry
= CONTAINING_RECORD(Entry
, PARTENTRY
, ListEntry
);
1554 PrintPartitionData(List
,
1558 Entry
= Entry
->Flink
;
1561 /* Print separator line */
1562 PrintEmptyLine(List
);
1570 PLIST_ENTRY Entry
, Entry2
;
1571 PDISKENTRY DiskEntry
;
1572 PPARTENTRY PartEntry
= NULL
;
1576 SHORT CurrentDiskLine
;
1577 SHORT CurrentPartLine
;
1579 BOOL CurrentPartLineFound
= FALSE
;
1580 BOOL CurrentDiskLineFound
= FALSE
;
1582 /* Calculate the line of the current disk and partition */
1583 CurrentDiskLine
= 0;
1584 CurrentPartLine
= 0;
1587 Entry
= List
->DiskListHead
.Flink
;
1588 while (Entry
!= &List
->DiskListHead
)
1590 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1593 if (CurrentPartLineFound
== FALSE
)
1595 CurrentPartLine
+= 2;
1598 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1599 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1601 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1602 if (PartEntry
== List
->CurrentPartition
)
1604 CurrentPartLineFound
= TRUE
;
1607 Entry2
= Entry2
->Flink
;
1608 if (CurrentPartLineFound
== FALSE
)
1616 if (DiskEntry
== List
->CurrentDisk
)
1618 CurrentDiskLineFound
= TRUE
;
1621 Entry
= Entry
->Flink
;
1622 if (Entry
!= &List
->DiskListHead
)
1624 if (CurrentDiskLineFound
== FALSE
)
1627 CurrentDiskLine
= CurrentPartLine
;
1638 /* If it possible, make the disk name visible */
1639 if (CurrentPartLine
< List
->Offset
)
1641 List
->Offset
= CurrentPartLine
;
1643 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1645 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1648 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1650 List
->Offset
= CurrentDiskLine
;
1653 /* draw upper left corner */
1654 coPos
.X
= List
->Left
;
1655 coPos
.Y
= List
->Top
;
1656 FillConsoleOutputCharacterA(StdOutput
,
1662 /* draw upper edge */
1663 coPos
.X
= List
->Left
+ 1;
1664 coPos
.Y
= List
->Top
;
1665 if (List
->Offset
== 0)
1667 FillConsoleOutputCharacterA(StdOutput
,
1669 List
->Right
- List
->Left
- 1,
1675 FillConsoleOutputCharacterA(StdOutput
,
1677 List
->Right
- List
->Left
- 5,
1680 coPos
.X
= List
->Right
- 5;
1681 WriteConsoleOutputCharacterA(StdOutput
,
1686 coPos
.X
= List
->Right
- 2;
1687 FillConsoleOutputCharacterA(StdOutput
,
1694 /* draw upper right corner */
1695 coPos
.X
= List
->Right
;
1696 coPos
.Y
= List
->Top
;
1697 FillConsoleOutputCharacterA(StdOutput
,
1703 /* draw left and right edge */
1704 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1706 coPos
.X
= List
->Left
;
1708 FillConsoleOutputCharacterA(StdOutput
,
1714 coPos
.X
= List
->Right
;
1715 FillConsoleOutputCharacterA(StdOutput
,
1722 /* draw lower left corner */
1723 coPos
.X
= List
->Left
;
1724 coPos
.Y
= List
->Bottom
;
1725 FillConsoleOutputCharacterA(StdOutput
,
1731 /* draw lower edge */
1732 coPos
.X
= List
->Left
+ 1;
1733 coPos
.Y
= List
->Bottom
;
1734 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1736 FillConsoleOutputCharacterA(StdOutput
,
1738 List
->Right
- List
->Left
- 1,
1744 FillConsoleOutputCharacterA(StdOutput
,
1746 List
->Right
- List
->Left
- 5,
1749 coPos
.X
= List
->Right
- 5;
1750 WriteConsoleOutputCharacterA(StdOutput
,
1751 "(\x19)", // "(down)"
1755 coPos
.X
= List
->Right
- 2;
1756 FillConsoleOutputCharacterA(StdOutput
,
1763 /* draw lower right corner */
1764 coPos
.X
= List
->Right
;
1765 coPos
.Y
= List
->Bottom
;
1766 FillConsoleOutputCharacterA(StdOutput
,
1772 /* print list entries */
1773 List
->Line
= - List
->Offset
;
1775 Entry
= List
->DiskListHead
.Flink
;
1776 while (Entry
!= &List
->DiskListHead
)
1778 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
1780 /* Print disk entry */
1784 Entry
= Entry
->Flink
;
1793 ULONG PartitionNumber
)
1795 PDISKENTRY DiskEntry
;
1796 PPARTENTRY PartEntry
;
1800 /* Check for empty disks */
1801 if (IsListEmpty(&List
->DiskListHead
))
1804 /* Check for first usable entry on next disk */
1805 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1806 while (Entry1
!= &List
->DiskListHead
)
1808 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1810 if (DiskEntry
->DiskNumber
== DiskNumber
)
1812 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
1813 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1815 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1817 if (PartEntry
->PartitionNumber
== PartitionNumber
)
1819 List
->CurrentDisk
= DiskEntry
;
1820 List
->CurrentPartition
= PartEntry
;
1821 DrawPartitionList(List
);
1825 Entry2
= Entry2
->Flink
;
1831 Entry1
= Entry1
->Flink
;
1839 ScrollDownPartitionList(
1842 // PDISKENTRY DiskEntry;
1843 PPARTENTRY PartEntry
;
1844 // PLIST_ENTRY Entry1;
1847 /* Check for empty disks */
1848 if (IsListEmpty(&List
->DiskListHead
))
1851 /* Check for next usable entry on current disk */
1852 if (List
->CurrentPartition
!= NULL
)
1854 Entry2
= List
->CurrentPartition
->ListEntry
.Flink
;
1855 if (Entry2
!= &List
->CurrentDisk
->PrimaryPartListHead
)
1857 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1859 List
->CurrentPartition
= PartEntry
;
1860 DrawPartitionList(List
);
1866 /* Check for first usable entry on next disk */
1867 if (List
->CurrentDisk
!= NULL
)
1869 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1870 while (Entry1
!= &List
->DiskListHead
)
1872 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1874 Entry2
= DiskEntry
->PartListHead
.Flink
;
1875 if (Entry2
!= &DiskEntry
->PartListHead
)
1877 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1879 List
->CurrentDisk
= DiskEntry
;
1880 List
->CurrentPartition
= PartEntry
;
1881 DrawPartitionList(List
);
1885 Entry1
= Entry1
->Flink
;
1893 ScrollUpPartitionList(
1896 // PDISKENTRY DiskEntry;
1897 PPARTENTRY PartEntry
;
1898 // PLIST_ENTRY Entry1;
1901 /* Check for empty disks */
1902 if (IsListEmpty(&List
->DiskListHead
))
1905 /* check for previous usable entry on current disk */
1906 if (List
->CurrentPartition
!= NULL
)
1908 Entry2
= List
->CurrentPartition
->ListEntry
.Blink
;
1909 if (Entry2
!= &List
->CurrentDisk
->PrimaryPartListHead
)
1911 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1913 List
->CurrentPartition
= PartEntry
;
1915 /* Draw partition list and return */
1916 DrawPartitionList(List
);
1922 /* check for last usable entry on previous disk */
1923 if (List
->CurrentDisk
!= NULL
)
1925 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1926 while (Entry1
!= &List
->DiskListHead
)
1928 DiskEntry
= CONTAINING_RECORD(Entry1
, DISKENTRY
, ListEntry
);
1930 Entry2
= DiskEntry
->PrimaryPartListHead
.Blink
;
1931 if (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
1933 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
1935 List
->CurrentDisk
= DiskEntry
;
1936 List
->CurrentPartition
= PartEntry
;
1938 /* Draw partition list and return */
1939 DrawPartitionList(List
);
1943 Entry1
= Entry1
->Blink
;
1953 PPARTITION_INFORMATION PartitionInfo
)
1955 if (PartitionInfo
->StartingOffset
.QuadPart
== 0 &&
1956 PartitionInfo
->PartitionLength
.QuadPart
== 0)
1957 // PartitionInfo->PartitionType == 0)
1966 IsSamePrimaryLayoutEntry(
1967 IN PPARTITION_INFORMATION PartitionInfo
,
1968 IN PDISKENTRY DiskEntry
,
1969 IN PPARTENTRY PartEntry
)
1971 if (PartitionInfo
->StartingOffset
.QuadPart
== PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
&&
1972 PartitionInfo
->PartitionLength
.QuadPart
== PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
)
1973 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
1974 // PartitionInfo->PartitionType == PartEntry->PartitionType
1984 IN PDISKENTRY DiskEntry
)
1986 PPARTITION_INFORMATION PartitionInfo
;
1987 PLIST_ENTRY ListEntry
;
1988 PPARTENTRY PartEntry
;
1990 ULONG PartitionNumber
= 1;
1992 DPRINT1("UpdateDiskLayout()\n");
1994 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
1995 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
1997 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
1999 if (PartEntry
->IsPartitioned
== TRUE
)
2001 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2003 if (!IsSamePrimaryLayoutEntry(PartitionInfo
, DiskEntry
, PartEntry
))
2005 DPRINT1("Updating partition entry %lu\n", Index
);
2006 PartitionInfo
->StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2007 PartitionInfo
->PartitionLength
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
2008 PartitionInfo
->HiddenSectors
= 0;
2009 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartEntry
->PartitionType
)) ? PartitionNumber
: 0;
2010 PartitionInfo
->PartitionType
= PartEntry
->PartitionType
;
2011 PartitionInfo
->BootIndicator
= PartEntry
->BootIndicator
;
2012 PartitionInfo
->RecognizedPartition
= FALSE
;
2013 PartitionInfo
->RewritePartition
= TRUE
;
2015 PartEntry
->PartitionNumber
= PartitionNumber
;
2016 PartEntry
->PartitionIndex
= Index
;
2020 else if (!IsEmptyLayoutEntry(PartitionInfo
))
2028 ListEntry
= ListEntry
->Flink
;
2031 for (;Index
< 4; Index
++)
2033 PartitionInfo
= &DiskEntry
->LayoutBuffer
->PartitionEntry
[Index
];
2035 if (!IsEmptyLayoutEntry(PartitionInfo
))
2037 DPRINT1("Wiping partition entry %lu\n", Index
);
2038 PartitionInfo
->StartingOffset
.QuadPart
= 0;
2039 PartitionInfo
->PartitionLength
.QuadPart
= 0;
2040 PartitionInfo
->HiddenSectors
= 0;
2041 PartitionInfo
->PartitionNumber
= 0;
2042 PartitionInfo
->PartitionType
= 0;
2043 PartitionInfo
->BootIndicator
= FALSE
;
2044 PartitionInfo
->RecognizedPartition
= FALSE
;
2045 PartitionInfo
->RewritePartition
= TRUE
;
2049 #ifdef DUMP_PARTITION_TABLE
2050 DumpPartitionTable(DiskEntry
);
2057 GetPrevUnpartitionedEntry(
2058 PDISKENTRY DiskEntry
,
2059 PPARTENTRY PartEntry
)
2061 PPARTENTRY PrevPartEntry
;
2063 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PrimaryPartListHead
)
2065 PrevPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Blink
,
2068 if (PrevPartEntry
->IsPartitioned
== FALSE
)
2069 return PrevPartEntry
;
2078 GetNextUnpartitionedEntry(
2079 PDISKENTRY DiskEntry
,
2080 PPARTENTRY PartEntry
)
2082 PPARTENTRY NextPartEntry
;
2084 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PrimaryPartListHead
)
2086 NextPartEntry
= CONTAINING_RECORD(PartEntry
->ListEntry
.Flink
,
2089 if (NextPartEntry
->IsPartitioned
== FALSE
)
2090 return NextPartEntry
;
2100 ULONGLONG SectorCount
,
2103 PDISKENTRY DiskEntry
;
2104 PPARTENTRY PartEntry
;
2105 PPARTENTRY NewPartEntry
;
2107 DPRINT1("CreateNewPartition(%I64u)\n", SectorCount
);
2110 List
->CurrentDisk
== NULL
||
2111 List
->CurrentPartition
== NULL
||
2112 List
->CurrentPartition
->IsPartitioned
== TRUE
)
2117 DiskEntry
= List
->CurrentDisk
;
2118 PartEntry
= List
->CurrentPartition
;
2120 DPRINT1("Current partition sector count: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2122 if (AutoCreate
== TRUE
||
2123 Align(PartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) - PartEntry
->StartSector
.QuadPart
== PartEntry
->SectorCount
.QuadPart
)
2125 DPRINT1("Convert existing partition entry\n");
2126 /* Convert current entry to 'new (unformatted)' */
2127 PartEntry
->IsPartitioned
= TRUE
;
2128 PartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2129 PartEntry
->FormatState
= Unformatted
;
2130 PartEntry
->AutoCreate
= AutoCreate
;
2131 PartEntry
->New
= TRUE
;
2132 PartEntry
->BootIndicator
= FALSE
; /* FIXME */
2134 DPRINT1("First Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
);
2135 DPRINT1("Last Sector: %I64u\n", PartEntry
->StartSector
.QuadPart
+ PartEntry
->SectorCount
.QuadPart
- 1);
2136 DPRINT1("Total Sectors: %I64u\n", PartEntry
->SectorCount
.QuadPart
);
2140 DPRINT1("Add new partition entry\n");
2142 /* Insert and initialize a new partition entry */
2143 NewPartEntry
= RtlAllocateHeap(ProcessHeap
,
2146 if (NewPartEntry
== NULL
)
2149 /* Insert the new entry into the list */
2150 InsertTailList(&PartEntry
->ListEntry
,
2151 &NewPartEntry
->ListEntry
);
2153 NewPartEntry
->DiskEntry
= DiskEntry
;
2155 NewPartEntry
->IsPartitioned
= TRUE
;
2156 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2157 NewPartEntry
->SectorCount
.QuadPart
= Align(NewPartEntry
->StartSector
.QuadPart
+ SectorCount
, DiskEntry
->SectorAlignment
) -
2158 NewPartEntry
->StartSector
.QuadPart
;
2159 NewPartEntry
->PartitionType
= PARTITION_ENTRY_UNUSED
;
2161 DPRINT1("First Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
);
2162 DPRINT1("Last Sector: %I64u\n", NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
- 1);
2163 DPRINT1("Total Sectors: %I64u\n", NewPartEntry
->SectorCount
.QuadPart
);
2165 NewPartEntry
->New
= TRUE
;
2166 NewPartEntry
->FormatState
= Unformatted
;
2167 NewPartEntry
->BootIndicator
= FALSE
; /* FIXME */
2169 PartEntry
->StartSector
.QuadPart
= NewPartEntry
->StartSector
.QuadPart
+ NewPartEntry
->SectorCount
.QuadPart
;
2170 PartEntry
->SectorCount
.QuadPart
-= (PartEntry
->StartSector
.QuadPart
- NewPartEntry
->StartSector
.QuadPart
);
2173 UpdateDiskLayout(DiskEntry
);
2175 DiskEntry
->Dirty
= TRUE
;
2177 UpdatePartitionNumbers(DiskEntry
);
2179 AssignDriveLetters(List
);
2184 DeleteCurrentPartition(
2187 PDISKENTRY DiskEntry
;
2188 PPARTENTRY PartEntry
;
2189 PPARTENTRY PrevPartEntry
;
2190 PPARTENTRY NextPartEntry
;
2193 List
->CurrentDisk
== NULL
||
2194 List
->CurrentPartition
== NULL
||
2195 List
->CurrentPartition
->IsPartitioned
== FALSE
)
2200 DiskEntry
= List
->CurrentDisk
;
2201 PartEntry
= List
->CurrentPartition
;
2203 /* Adjust unpartitioned disk space entries */
2205 /* Get pointer to previous and next unpartitioned entries */
2206 PrevPartEntry
= GetPrevUnpartitionedEntry(DiskEntry
,
2209 NextPartEntry
= GetNextUnpartitionedEntry(DiskEntry
,
2212 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
2214 /* Merge previous, current and next unpartitioned entry */
2216 /* Adjust the previous entries length */
2217 PrevPartEntry
->SectorCount
.QuadPart
+= (PartEntry
->SectorCount
.QuadPart
+ NextPartEntry
->SectorCount
.QuadPart
);
2219 /* Remove the current entry */
2220 RemoveEntryList(&PartEntry
->ListEntry
);
2221 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2223 /* Remove the next entry */
2224 RemoveEntryList (&NextPartEntry
->ListEntry
);
2225 RtlFreeHeap(ProcessHeap
, 0, NextPartEntry
);
2227 /* Update current partition */
2228 List
->CurrentPartition
= PrevPartEntry
;
2230 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
2232 /* Merge current and previous unpartitioned entry */
2234 /* Adjust the previous entries length */
2235 PrevPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2237 /* Remove the current entry */
2238 RemoveEntryList(&PartEntry
->ListEntry
);
2239 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2241 /* Update current partition */
2242 List
->CurrentPartition
= PrevPartEntry
;
2244 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
2246 /* Merge current and next unpartitioned entry */
2248 /* Adjust the next entries offset and length */
2249 NextPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
2250 NextPartEntry
->SectorCount
.QuadPart
+= PartEntry
->SectorCount
.QuadPart
;
2252 /* Remove the current entry */
2253 RemoveEntryList(&PartEntry
->ListEntry
);
2254 RtlFreeHeap(ProcessHeap
, 0, PartEntry
);
2256 /* Update current partition */
2257 List
->CurrentPartition
= NextPartEntry
;
2261 /* Nothing to merge but change current entry */
2262 PartEntry
->IsPartitioned
= FALSE
;
2263 PartEntry
->FormatState
= Unformatted
;
2264 PartEntry
->DriveLetter
= 0;
2267 UpdateDiskLayout(DiskEntry
);
2269 DiskEntry
->Dirty
= TRUE
;
2271 UpdatePartitionNumbers(DiskEntry
);
2273 AssignDriveLetters(List
);
2278 CheckActiveBootPartition(
2281 PDISKENTRY DiskEntry
;
2282 PPARTENTRY PartEntry
;
2283 PLIST_ENTRY ListEntry
;
2285 /* Check for empty disk list */
2286 if (IsListEmpty (&List
->DiskListHead
))
2288 List
->ActiveBootDisk
= NULL
;
2289 List
->ActiveBootPartition
= NULL
;
2294 if (List
->ActiveBootDisk
!= NULL
&&
2295 List
->ActiveBootPartition
!= NULL
)
2297 /* We already have an active boot partition */
2302 /* Choose the currently selected disk */
2303 DiskEntry
= List
->CurrentDisk
;
2305 /* Check for empty partition list */
2306 if (IsListEmpty (&DiskEntry
->PrimaryPartListHead
))
2308 List
->ActiveBootDisk
= NULL
;
2309 List
->ActiveBootPartition
= NULL
;
2313 PartEntry
= CONTAINING_RECORD(DiskEntry
->PrimaryPartListHead
.Flink
,
2317 /* Set active boot partition */
2318 if ((DiskEntry
->NewDisk
== TRUE
) ||
2319 (PartEntry
->BootIndicator
== FALSE
))
2321 PartEntry
->BootIndicator
= TRUE
;
2322 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].BootIndicator
= TRUE
;
2323 DiskEntry
->LayoutBuffer
->PartitionEntry
[PartEntry
->PartitionIndex
].RewritePartition
= TRUE
;
2324 DiskEntry
->Dirty
= TRUE
;
2326 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2327 List
->ActiveBootDisk
= DiskEntry
;
2328 List
->ActiveBootPartition
= PartEntry
;
2333 /* Disk is not new, scan all partitions to find a bootable one */
2334 List
->ActiveBootDisk
= NULL
;
2335 List
->ActiveBootPartition
= NULL
;
2337 ListEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
2338 while (ListEntry
!= &DiskEntry
->PrimaryPartListHead
)
2340 PartEntry
= CONTAINING_RECORD(ListEntry
,
2344 /* Check if it is partitioned */
2345 if (PartEntry
->IsPartitioned
)
2347 if (PartEntry
->PartitionType
!= PARTITION_ENTRY_UNUSED
&&
2348 PartEntry
->BootIndicator
)
2350 /* Yes, we found it */
2351 List
->ActiveBootDisk
= DiskEntry
;
2352 List
->ActiveBootPartition
= PartEntry
;
2354 DPRINT("Found bootable partition disk %d, drive letter %c\n",
2355 DiskEntry
->DiskNumber
, PartEntry
->DriveLetter
);
2360 /* Go to the next one */
2361 ListEntry
= ListEntry
->Flink
;
2367 CheckForLinuxFdiskPartitions(
2371 PDISKENTRY DiskEntry
;
2372 PPARTENTRY PartEntry
;
2375 ULONG PartitionCount
;
2378 Entry1
= List
->DiskListHead
.Flink
;
2379 while (Entry1
!= &List
->DiskListHead
)
2381 DiskEntry
= CONTAINING_RECORD(Entry1
,
2385 Entry2
= DiskEntry
->PartListHead
.Flink
;
2386 while (Entry2
!= &DiskEntry
->PartListHead
)
2388 PartEntry
= CONTAINING_RECORD(Entry2
,
2392 if (PartEntry
->Unpartitioned
== FALSE
)
2396 for (i
= 0; i
< 4; i
++)
2398 if (!IsContainerPartition(PartEntry
->PartInfo
[i
].PartitionType
) &&
2399 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
2405 if (PartitionCount
> 1)
2411 Entry2
= Entry2
->Flink
;
2414 Entry1
= Entry1
->Flink
;
2426 IN PDISKENTRY DiskEntry
)
2428 WCHAR DstPath
[MAX_PATH
];
2429 OBJECT_ATTRIBUTES ObjectAttributes
;
2430 IO_STATUS_BLOCK Iosb
;
2431 UNICODE_STRING Name
;
2433 HANDLE FileHandle
= NULL
;
2436 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry
->DiskNumber
);
2439 L
"\\Device\\Harddisk%d\\Partition0",
2440 DiskEntry
->DiskNumber
);
2441 RtlInitUnicodeString(&Name
,
2443 InitializeObjectAttributes(&ObjectAttributes
,
2449 Status
= NtOpenFile(&FileHandle
,
2450 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
2454 FILE_SYNCHRONOUS_IO_NONALERT
);
2455 if (!NT_SUCCESS(Status
))
2457 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status
);
2461 #ifdef DUMP_PARTITION_TABLE
2462 DumpPartitionTable(DiskEntry
);
2465 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
2466 ((DiskEntry
->LayoutBuffer
->PartitionCount
- 1) * sizeof(PARTITION_INFORMATION
));
2467 Status
= NtDeviceIoControlFile(FileHandle
,
2472 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2473 DiskEntry
->LayoutBuffer
,
2477 if (!NT_SUCCESS(Status
))
2479 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status
);
2482 if (FileHandle
!= NULL
)
2483 NtClose(FileHandle
);
2490 WritePartitionsToDisk(
2494 PDISKENTRY DiskEntry
;
2499 Entry
= List
->DiskListHead
.Flink
;
2500 while (Entry
!= &List
->DiskListHead
)
2502 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
2504 if (DiskEntry
->Dirty
== TRUE
)
2506 WritePartitons(List
, DiskEntry
);
2509 Entry
= Entry
->Flink
;
2517 SetMountedDeviceValues(
2520 PLIST_ENTRY Entry1
, Entry2
;
2521 PDISKENTRY DiskEntry
;
2522 PPARTENTRY PartEntry
;
2523 LARGE_INTEGER StartingOffset
;
2530 Entry1
= List
->DiskListHead
.Flink
;
2531 while (Entry1
!= &List
->DiskListHead
)
2533 DiskEntry
= CONTAINING_RECORD(Entry1
,
2537 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
2538 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
2540 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
2541 if (PartEntry
->IsPartitioned
)
2543 if (PartEntry
->DriveLetter
)
2545 StartingOffset
.QuadPart
= PartEntry
->StartSector
.QuadPart
* DiskEntry
->BytesPerSector
;
2546 if (!SetMountedDeviceValue(PartEntry
->DriveLetter
,
2547 DiskEntry
->LayoutBuffer
->Signature
,
2555 Entry2
= Entry2
->Flink
;
2558 Entry1
= Entry1
->Flink
;