3 * Copyright (C) 2002, 2003 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.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/partlist.c
23 * PURPOSE: Partition list functions
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
33 /* FUNCTIONS ****************************************************************/
36 GetDriverName (PDISKENTRY DiskEntry
)
38 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
42 RtlInitUnicodeString (&DiskEntry
->DriverName
,
46 L
"\\Scsi\\Scsi Port %lu",
49 RtlZeroMemory (&QueryTable
,
52 QueryTable
[0].Name
= L
"Driver";
53 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
54 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
56 Status
= RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP
,
61 if (!NT_SUCCESS (Status
))
63 DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
69 AssignDriverLetters (PPARTLIST List
)
79 /* Assign drive letters to primary partitions */
80 Entry1
= List
->DiskListHead
.Flink
;
81 while (Entry1
!= &List
->DiskListHead
)
83 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
85 if (!IsListEmpty (&DiskEntry
->PartListHead
))
87 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
91 PartEntry
->DriveLetter
= 0;
93 if (PartEntry
->Unpartitioned
== FALSE
&&
94 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
96 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
97 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
98 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
102 PartEntry
->DriveLetter
= Letter
;
109 Entry1
= Entry1
->Flink
;
113 /* Assign drive letters to logical drives */
114 Entry1
= List
->DiskListHead
.Flink
;
115 while (Entry1
!= &List
->DiskListHead
)
117 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
119 Entry2
= DiskEntry
->PartListHead
.Flink
;
120 if (Entry2
!= &DiskEntry
->PartListHead
)
122 Entry2
= Entry2
->Flink
;
123 while (Entry2
!= &DiskEntry
->PartListHead
)
125 PartEntry
= CONTAINING_RECORD (Entry2
,
129 PartEntry
->DriveLetter
= 0;
131 if (PartEntry
->Unpartitioned
== FALSE
&&
132 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
134 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
135 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
136 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
140 PartEntry
->DriveLetter
= Letter
;
146 Entry2
= Entry2
->Flink
;
150 Entry1
= Entry1
->Flink
;
156 UpdatePartitionNumbers (PDISKENTRY DiskEntry
)
158 PPARTENTRY PartEntry
;
164 Entry
= DiskEntry
->PartListHead
.Flink
;
165 while (Entry
!= &DiskEntry
->PartListHead
)
167 PartEntry
= CONTAINING_RECORD (Entry
,
171 if (PartEntry
->Unpartitioned
== TRUE
)
173 for (i
= 0; i
< 4; i
++)
175 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
180 for (i
= 0; i
< 4; i
++)
182 if (IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
))
184 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
186 else if (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
187 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
== 0ULL)
189 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
193 PartEntry
->PartInfo
[i
].PartitionNumber
= PartNumber
;
199 Entry
= Entry
->Flink
;
205 AddPartitionToList (ULONG DiskNumber
,
206 PDISKENTRY DiskEntry
,
207 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
)
209 PPARTENTRY PartEntry
;
213 for (i
= 0; i
< LayoutBuffer
->PartitionCount
; i
+= 4)
215 for (j
= 0; j
< 4; j
++)
217 if (LayoutBuffer
->PartitionEntry
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
218 LayoutBuffer
->PartitionEntry
[j
].PartitionLength
.QuadPart
!= 0ULL)
228 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
231 if (PartEntry
== NULL
)
236 RtlZeroMemory (PartEntry
,
239 PartEntry
->Unpartitioned
= FALSE
;
241 for (j
= 0; j
< 4; j
++)
243 RtlCopyMemory (&PartEntry
->PartInfo
[j
],
244 &LayoutBuffer
->PartitionEntry
[i
+j
],
245 sizeof(PARTITION_INFORMATION
));
248 if (IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
250 PartEntry
->FormatState
= Unformatted
;
252 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
253 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
254 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
255 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
) ||
256 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
257 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
260 if (CheckFatFormat())
262 PartEntry
->FormatState
= Preformatted
;
266 PartEntry
->FormatState
= Unformatted
;
269 PartEntry
->FormatState
= Preformatted
;
271 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
274 if (CheckNtfsFormat())
276 PartEntry
->FormatState
= Preformatted
;
278 else if (CheckHpfsFormat())
280 PartEntry
->FormatState
= Preformatted
;
284 PartEntry
->FormatState
= Unformatted
;
287 PartEntry
->FormatState
= Preformatted
;
291 PartEntry
->FormatState
= Unknown
;
294 InsertTailList (&DiskEntry
->PartListHead
,
295 &PartEntry
->ListEntry
);
301 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry
)
303 ULONGLONG LastStartingOffset
;
304 ULONGLONG LastPartitionLength
;
305 ULONGLONG LastUnusedPartitionLength
;
306 PPARTENTRY PartEntry
;
307 PPARTENTRY NewPartEntry
;
312 if (IsListEmpty (&DiskEntry
->PartListHead
))
314 /* Create a partition table that represents the empty disk */
315 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
318 if (PartEntry
== NULL
)
321 RtlZeroMemory (PartEntry
,
324 PartEntry
->Unpartitioned
= TRUE
;
325 PartEntry
->UnpartitionedOffset
= 0ULL;
326 PartEntry
->UnpartitionedLength
= DiskEntry
->DiskSize
;
328 PartEntry
->FormatState
= Unformatted
;
330 InsertTailList (&DiskEntry
->PartListHead
,
331 &PartEntry
->ListEntry
);
335 /* Start partition at head 1, cylinder 0 */
336 LastStartingOffset
= DiskEntry
->TrackSize
;
337 LastPartitionLength
= 0ULL;
338 LastUnusedPartitionLength
= 0ULL;
341 Entry
= DiskEntry
->PartListHead
.Flink
;
342 while (Entry
!= &DiskEntry
->PartListHead
)
344 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
346 for (j
= 0; j
< 4; j
++)
348 if ((!IsContainerPartition (PartEntry
->PartInfo
[j
].PartitionType
)) &&
349 (PartEntry
->PartInfo
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
350 PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
!= 0LL))
352 LastUnusedPartitionLength
=
353 PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
-
354 (LastStartingOffset
+ LastPartitionLength
);
356 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
358 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
360 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
363 if (NewPartEntry
== NULL
)
366 RtlZeroMemory (NewPartEntry
,
369 NewPartEntry
->Unpartitioned
= TRUE
;
370 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
371 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
373 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
375 NewPartEntry
->FormatState
= Unformatted
;
377 /* Insert the table into the list */
378 InsertTailList (&PartEntry
->ListEntry
,
379 &NewPartEntry
->ListEntry
);
382 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
383 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
388 Entry
= Entry
->Flink
;
391 /* Check for trailing unpartitioned disk space */
392 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
394 /* Round-down to cylinder size */
395 LastUnusedPartitionLength
=
396 ROUND_DOWN (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
),
397 DiskEntry
->CylinderSize
);
399 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
401 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
403 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
406 if (NewPartEntry
== NULL
)
409 RtlZeroMemory (NewPartEntry
,
412 NewPartEntry
->Unpartitioned
= TRUE
;
413 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
414 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
416 /* Append the table to the list */
417 InsertTailList (&DiskEntry
->PartListHead
,
418 &NewPartEntry
->ListEntry
);
426 AddDiskToList (HANDLE FileHandle
,
430 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
431 DISK_GEOMETRY DiskGeometry
;
432 SCSI_ADDRESS ScsiAddress
;
433 PDISKENTRY DiskEntry
;
434 IO_STATUS_BLOCK Iosb
;
437 Status
= NtDeviceIoControlFile (FileHandle
,
442 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
446 sizeof(DISK_GEOMETRY
));
447 if (!NT_SUCCESS (Status
))
452 if (DiskGeometry
.MediaType
!= FixedMedia
)
457 Status
= NtDeviceIoControlFile (FileHandle
,
462 IOCTL_SCSI_GET_ADDRESS
,
466 sizeof(SCSI_ADDRESS
));
467 if (!NT_SUCCESS(Status
))
472 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
475 if (DiskEntry
== NULL
)
480 InitializeListHead (&DiskEntry
->PartListHead
);
482 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
483 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
484 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
485 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
487 DPRINT ("Cylinders %d\n", DiskEntry
->Cylinders
);
488 DPRINT ("TracksPerCylinder %d\n", DiskEntry
->TracksPerCylinder
);
489 DPRINT ("SectorsPerTrack %d\n", DiskEntry
->SectorsPerTrack
);
490 DPRINT ("BytesPerSector %d\n", DiskEntry
->BytesPerSector
);
492 DiskEntry
->DiskSize
=
493 DiskGeometry
.Cylinders
.QuadPart
*
494 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
495 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
496 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
497 DiskEntry
->CylinderSize
=
498 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
499 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
500 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
501 DiskEntry
->TrackSize
=
502 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
503 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
505 DiskEntry
->DiskNumber
= DiskNumber
;
506 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
507 DiskEntry
->Bus
= ScsiAddress
.PathId
;
508 DiskEntry
->Id
= ScsiAddress
.TargetId
;
510 GetDriverName (DiskEntry
);
512 InsertTailList (&List
->DiskListHead
,
513 &DiskEntry
->ListEntry
);
515 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
518 if (LayoutBuffer
== NULL
)
523 Status
= NtDeviceIoControlFile (FileHandle
,
528 IOCTL_DISK_GET_DRIVE_LAYOUT
,
533 if (NT_SUCCESS (Status
))
535 if (LayoutBuffer
->PartitionCount
== 0)
537 DiskEntry
->NewDisk
= TRUE
;
540 AddPartitionToList (DiskNumber
,
544 ScanForUnpartitionedDiskSpace (DiskEntry
);
547 RtlFreeHeap (ProcessHeap
,
554 CreatePartitionList (SHORT Left
,
560 OBJECT_ATTRIBUTES ObjectAttributes
;
561 SYSTEM_DEVICE_INFORMATION Sdi
;
562 IO_STATUS_BLOCK Iosb
;
566 WCHAR Buffer
[MAX_PATH
];
570 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
579 List
->Bottom
= Bottom
;
583 List
->TopDisk
= (ULONG
)-1;
584 List
->TopPartition
= (ULONG
)-1;
586 List
->CurrentDisk
= NULL
;
587 List
->CurrentPartition
= NULL
;
589 InitializeListHead (&List
->DiskListHead
);
591 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
593 sizeof(SYSTEM_DEVICE_INFORMATION
),
595 if (!NT_SUCCESS (Status
))
597 RtlFreeHeap (ProcessHeap
, 0, List
);
601 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
604 L
"\\Device\\Harddisk%d\\Partition0",
606 RtlInitUnicodeString (&Name
,
609 InitializeObjectAttributes (&ObjectAttributes
,
615 Status
= NtOpenFile (&FileHandle
,
620 FILE_SYNCHRONOUS_IO_NONALERT
);
621 if (NT_SUCCESS(Status
))
623 AddDiskToList (FileHandle
,
631 AssignDriverLetters (List
);
634 List
->TopPartition
= 0;
636 /* Search for first usable disk and partition */
637 if (IsListEmpty (&List
->DiskListHead
))
639 List
->CurrentDisk
= NULL
;
640 List
->CurrentPartition
= NULL
;
645 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
649 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
651 List
->CurrentPartition
= 0;
655 List
->CurrentPartition
=
656 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
667 DestroyPartitionList (PPARTLIST List
)
669 PDISKENTRY DiskEntry
;
670 PPARTENTRY PartEntry
;
673 /* Release disk and partition info */
674 while (!IsListEmpty (&List
->DiskListHead
))
676 Entry
= RemoveHeadList (&List
->DiskListHead
);
677 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
679 /* Release driver name */
680 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
682 /* Release partition array */
683 while (!IsListEmpty (&DiskEntry
->PartListHead
))
685 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
686 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
688 RtlFreeHeap (ProcessHeap
,
693 /* Release disk entry */
694 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
697 /* Release list head */
698 RtlFreeHeap (ProcessHeap
, 0, List
);
703 PrintEmptyLine (PPARTLIST List
)
710 Width
= List
->Right
- List
->Left
- 1;
711 Height
= List
->Bottom
- List
->Top
- 2;
714 coPos
.X
= List
->Left
+ 1;
715 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
717 if (List
->Line
>= 0 && List
->Line
<= Height
)
719 FillConsoleOutputAttribute (0x17,
724 FillConsoleOutputCharacter (' ',
734 PrintPartitionData (PPARTLIST List
,
735 PDISKENTRY DiskEntry
,
736 PPARTENTRY PartEntry
)
738 CHAR LineBuffer
[128];
749 Width
= List
->Right
- List
->Left
- 1;
750 Height
= List
->Bottom
- List
->Top
- 2;
753 coPos
.X
= List
->Left
+ 1;
754 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
756 if (PartEntry
->Unpartitioned
== TRUE
)
759 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
761 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
766 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
768 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
773 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
778 " Unpartitioned space %6I64u %s",
784 /* Determine partition type */
786 if (PartEntry
->New
== TRUE
)
788 PartType
= "New (Unformatted)";
790 else if (PartEntry
->Unpartitioned
== FALSE
)
792 if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
793 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
794 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
795 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
))
799 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
800 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
804 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
806 PartType
= "NTFS"; /* FIXME: Not quite correct! */
811 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0x280000000LL
) /* 10 GB */
813 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
818 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0xA00000LL
) /* 10 MB */
820 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
825 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
829 if (PartType
== NULL
)
832 "%c%c Type %-3u %6I64u %s",
833 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
834 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
835 PartEntry
->PartInfo
[0].PartitionType
,
842 "%c%c %-24s %6I64u %s",
843 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
844 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
851 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
852 List
->CurrentPartition
== PartEntry
) ? 0x71 : 0x17;
854 if (List
->Line
>= 0 && List
->Line
<= Height
)
856 FillConsoleOutputCharacter (' ',
863 if (List
->Line
>= 0 && List
->Line
<= Height
)
865 FillConsoleOutputAttribute (Attribute
,
872 if (List
->Line
>= 0 && List
->Line
<= Height
)
874 WriteConsoleOutputCharacters (LineBuffer
,
875 min (strlen (LineBuffer
), Width
),
883 PrintDiskData (PPARTLIST List
,
884 PDISKENTRY DiskEntry
)
886 PPARTENTRY PartEntry
;
888 CHAR LineBuffer
[128];
896 Width
= List
->Right
- List
->Left
- 1;
897 Height
= List
->Bottom
- List
->Top
- 2;
900 coPos
.X
= List
->Left
+ 1;
901 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
904 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
906 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
912 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
918 if (DiskEntry
->DriverName
.Length
> 0)
921 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ",
924 DiskEntry
->DiskNumber
,
928 &DiskEntry
->DriverName
);
933 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
936 DiskEntry
->DiskNumber
,
941 if (List
->Line
>= 0 && List
->Line
<= Height
)
943 FillConsoleOutputAttribute (0x17,
948 FillConsoleOutputCharacter (' ',
955 if (List
->Line
>= 0 && List
->Line
<= Height
)
957 WriteConsoleOutputCharacters (LineBuffer
,
958 min (strlen (LineBuffer
), Width
- 2),
963 /* Print separator line */
964 PrintEmptyLine (List
);
966 /* Print partition lines*/
967 Entry
= DiskEntry
->PartListHead
.Flink
;
968 while (Entry
!= &DiskEntry
->PartListHead
)
970 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
972 /* Print disk entry */
973 PrintPartitionData (List
,
977 Entry
= Entry
->Flink
;
980 /* Print separator line */
981 PrintEmptyLine (List
);
986 DrawPartitionList (PPARTLIST List
)
988 PLIST_ENTRY Entry
, Entry2
;
989 PDISKENTRY DiskEntry
;
990 PPARTENTRY PartEntry
= NULL
;
994 SHORT CurrentDiskLine
;
995 SHORT CurrentPartLine
;
997 BOOL CurrentPartLineFound
= FALSE
;
998 BOOL CurrentDiskLineFound
= FALSE
;
1000 /* Calculate the line of the current disk and partition */
1001 CurrentDiskLine
= 0;
1002 CurrentPartLine
= 0;
1004 Entry
= List
->DiskListHead
.Flink
;
1005 while (Entry
!= &List
->DiskListHead
)
1007 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1009 if (CurrentPartLineFound
== FALSE
)
1011 CurrentPartLine
+= 2;
1013 Entry2
= DiskEntry
->PartListHead
.Flink
;
1014 while (Entry2
!= &DiskEntry
->PartListHead
)
1016 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1017 if (PartEntry
== List
->CurrentPartition
)
1019 CurrentPartLineFound
= TRUE
;
1021 Entry2
= Entry2
->Flink
;
1022 if (CurrentPartLineFound
== FALSE
)
1028 if (DiskEntry
== List
->CurrentDisk
)
1030 CurrentDiskLineFound
= TRUE
;
1032 Entry
= Entry
->Flink
;
1033 if (Entry
!= &List
->DiskListHead
)
1035 if (CurrentDiskLineFound
== FALSE
)
1038 CurrentDiskLine
= CurrentPartLine
;
1048 /* If it possible, make the disk name visible */
1049 if (CurrentPartLine
< List
->Offset
)
1051 List
->Offset
= CurrentPartLine
;
1053 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1055 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1057 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1059 List
->Offset
= CurrentDiskLine
;
1063 /* draw upper left corner */
1064 coPos
.X
= List
->Left
;
1065 coPos
.Y
= List
->Top
;
1066 FillConsoleOutputCharacter (0xDA, // '+',
1071 /* draw upper edge */
1072 coPos
.X
= List
->Left
+ 1;
1073 coPos
.Y
= List
->Top
;
1074 if (List
->Offset
== 0)
1076 FillConsoleOutputCharacter (0xC4, // '-',
1077 List
->Right
- List
->Left
- 1,
1083 FillConsoleOutputCharacter (0xC4, // '-',
1084 List
->Right
- List
->Left
- 5,
1087 coPos
.X
= List
->Right
- 5;
1088 WriteConsoleOutputCharacters ("(\x18)", // "(up)"
1091 coPos
.X
= List
->Right
- 2;
1092 FillConsoleOutputCharacter (0xC4, // '-',
1098 /* draw upper right corner */
1099 coPos
.X
= List
->Right
;
1100 coPos
.Y
= List
->Top
;
1101 FillConsoleOutputCharacter (0xBF, // '+',
1106 /* draw left and right edge */
1107 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1109 coPos
.X
= List
->Left
;
1111 FillConsoleOutputCharacter (0xB3, // '|',
1116 coPos
.X
= List
->Right
;
1117 FillConsoleOutputCharacter (0xB3, //'|',
1123 /* draw lower left corner */
1124 coPos
.X
= List
->Left
;
1125 coPos
.Y
= List
->Bottom
;
1126 FillConsoleOutputCharacter (0xC0, // '+',
1131 /* draw lower edge */
1132 coPos
.X
= List
->Left
+ 1;
1133 coPos
.Y
= List
->Bottom
;
1134 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1136 FillConsoleOutputCharacter (0xC4, // '-',
1137 List
->Right
- List
->Left
- 1,
1143 FillConsoleOutputCharacter (0xC4, // '-',
1144 List
->Right
- List
->Left
- 5,
1147 coPos
.X
= List
->Right
- 5;
1148 WriteConsoleOutputCharacters ("(\x19)", // "(down)"
1151 coPos
.X
= List
->Right
- 2;
1152 FillConsoleOutputCharacter (0xC4, // '-',
1158 /* draw lower right corner */
1159 coPos
.X
= List
->Right
;
1160 coPos
.Y
= List
->Bottom
;
1161 FillConsoleOutputCharacter (0xD9, // '+',
1166 /* print list entries */
1167 List
->Line
= - List
->Offset
;
1169 Entry
= List
->DiskListHead
.Flink
;
1170 while (Entry
!= &List
->DiskListHead
)
1172 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1174 /* Print disk entry */
1175 PrintDiskData (List
,
1178 Entry
= Entry
->Flink
;
1184 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1186 PDISKENTRY DiskEntry
;
1187 PPARTENTRY PartEntry
;
1192 /* Check for empty disks */
1193 if (IsListEmpty (&List
->DiskListHead
))
1196 /* Check for first usable entry on next disk */
1197 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1198 while (Entry1
!= &List
->DiskListHead
)
1200 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1202 if (DiskEntry
->DiskNumber
== DiskNumber
)
1204 Entry2
= DiskEntry
->PartListHead
.Flink
;
1205 while (Entry2
!= &DiskEntry
->PartListHead
)
1207 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1209 for (i
= 0; i
< 4; i
++)
1211 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1213 List
->CurrentDisk
= DiskEntry
;
1214 List
->CurrentPartition
= PartEntry
;
1215 DrawPartitionList (List
);
1219 Entry2
= Entry2
->Flink
;
1223 Entry1
= Entry1
->Flink
;
1229 ScrollDownPartitionList (PPARTLIST List
)
1231 PDISKENTRY DiskEntry
;
1232 PPARTENTRY PartEntry
;
1236 /* Check for empty disks */
1237 if (IsListEmpty (&List
->DiskListHead
))
1240 /* Check for next usable entry on current disk */
1241 if (List
->CurrentPartition
!= NULL
)
1243 Entry2
= List
->CurrentPartition
->ListEntry
.Flink
;
1244 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1246 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1248 // if (PartEntry->HidePartEntry == FALSE)
1250 List
->CurrentPartition
= PartEntry
;
1251 DrawPartitionList (List
);
1254 Entry2
= Entry2
->Flink
;
1258 /* Check for first usable entry on next disk */
1259 if (List
->CurrentDisk
!= NULL
)
1261 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1262 while (Entry1
!= &List
->DiskListHead
)
1264 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1266 Entry2
= DiskEntry
->PartListHead
.Flink
;
1267 while (Entry2
!= &DiskEntry
->PartListHead
)
1269 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1271 // if (PartEntry->HidePartEntry == FALSE)
1273 List
->CurrentDisk
= DiskEntry
;
1274 List
->CurrentPartition
= PartEntry
;
1275 DrawPartitionList (List
);
1279 Entry2
= Entry2
->Flink
;
1282 Entry1
= Entry1
->Flink
;
1289 ScrollUpPartitionList (PPARTLIST List
)
1291 PDISKENTRY DiskEntry
;
1292 PPARTENTRY PartEntry
;
1296 /* Check for empty disks */
1297 if (IsListEmpty (&List
->DiskListHead
))
1300 /* check for previous usable entry on current disk */
1301 if (List
->CurrentPartition
!= NULL
)
1303 Entry2
= List
->CurrentPartition
->ListEntry
.Blink
;
1304 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1306 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1308 // if (PartEntry->HidePartEntry == FALSE)
1310 List
->CurrentPartition
= PartEntry
;
1311 DrawPartitionList (List
);
1314 Entry2
= Entry2
->Blink
;
1319 /* check for last usable entry on previous disk */
1320 if (List
->CurrentDisk
!= NULL
)
1322 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1323 while (Entry1
!= &List
->DiskListHead
)
1325 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1327 Entry2
= DiskEntry
->PartListHead
.Blink
;
1328 while (Entry2
!= &DiskEntry
->PartListHead
)
1330 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1332 // if (PartEntry->HidePartEntry == FALSE)
1334 List
->CurrentDisk
= DiskEntry
;
1335 List
->CurrentPartition
= PartEntry
;
1336 DrawPartitionList (List
);
1340 Entry2
= Entry2
->Blink
;
1343 Entry1
= Entry1
->Blink
;
1350 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1351 PPARTENTRY CurrentEntry
)
1353 PPARTENTRY PrevEntry
;
1356 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1359 Entry
= CurrentEntry
->ListEntry
.Blink
;
1360 while (Entry
!= &DiskEntry
->PartListHead
)
1362 PrevEntry
= CONTAINING_RECORD (Entry
,
1365 if (PrevEntry
->Unpartitioned
== FALSE
)
1368 Entry
= Entry
->Blink
;
1376 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1377 PPARTENTRY CurrentEntry
)
1379 PPARTENTRY NextEntry
;
1382 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1385 Entry
= CurrentEntry
->ListEntry
.Flink
;
1386 while (Entry
!= &DiskEntry
->PartListHead
)
1388 NextEntry
= CONTAINING_RECORD (Entry
,
1391 if (NextEntry
->Unpartitioned
== FALSE
)
1394 Entry
= Entry
->Flink
;
1402 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1403 PPARTENTRY PartEntry
)
1405 PPARTENTRY PrevPartEntry
;
1407 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1409 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1412 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1413 return PrevPartEntry
;
1421 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1422 PPARTENTRY PartEntry
)
1424 PPARTENTRY NextPartEntry
;
1426 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1428 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1431 if (NextPartEntry
->Unpartitioned
== TRUE
)
1432 return NextPartEntry
;
1440 CreateNewPartition (PPARTLIST List
,
1441 ULONGLONG PartitionSize
,
1444 PDISKENTRY DiskEntry
;
1445 PPARTENTRY PartEntry
;
1446 PPARTENTRY PrevPartEntry
;
1447 PPARTENTRY NextPartEntry
;
1448 PPARTENTRY NewPartEntry
;
1451 List
->CurrentDisk
== NULL
||
1452 List
->CurrentPartition
== NULL
||
1453 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1458 DiskEntry
= List
->CurrentDisk
;
1459 PartEntry
= List
->CurrentPartition
;
1461 if (AutoCreate
== TRUE
||
1462 PartitionSize
== PartEntry
->UnpartitionedLength
)
1464 /* Convert current entry to 'new (unformatted)' */
1465 PartEntry
->FormatState
= Unformatted
;
1466 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1467 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1468 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1469 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1470 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1471 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1472 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1473 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1474 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1475 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1477 /* Get previous and next partition entries */
1478 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1480 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1483 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1485 /* Current entry is in the middle of the list */
1487 /* Copy previous container partition data to current entry */
1488 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1489 &PrevPartEntry
->PartInfo
[1],
1490 sizeof(PARTITION_INFORMATION
));
1491 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1493 /* Update previous container partition data */
1495 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1496 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1498 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1500 /* Special case - previous partition is first partition */
1501 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1502 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1506 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1507 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1510 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1512 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1514 /* Current entry is the first entry */
1517 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1519 /* Current entry is the last entry */
1521 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1522 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1524 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1526 /* Special case - previous partition is first partition */
1527 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1528 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1532 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1533 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1536 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
1537 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
1538 (1024LL * 255LL * 63LL * 512LL))
1540 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
1544 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
1547 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1548 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1551 PartEntry
->AutoCreate
= AutoCreate
;
1552 PartEntry
->New
= TRUE
;
1553 PartEntry
->Unpartitioned
= FALSE
;
1554 PartEntry
->UnpartitionedOffset
= 0ULL;
1555 PartEntry
->UnpartitionedLength
= 0ULL;
1559 /* Insert an initialize a new partition entry */
1560 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
1563 if (NewPartEntry
== NULL
)
1566 RtlZeroMemory (NewPartEntry
,
1569 /* Insert the new entry into the list */
1570 InsertTailList (&PartEntry
->ListEntry
,
1571 &NewPartEntry
->ListEntry
);
1573 NewPartEntry
->New
= TRUE
;
1575 NewPartEntry
->FormatState
= Unformatted
;
1576 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1577 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1578 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1579 PartitionSize
- DiskEntry
->TrackSize
;
1580 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1581 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1582 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1583 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1584 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1585 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1587 /* Get previous and next partition entries */
1588 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1590 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1593 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1595 /* Current entry is in the middle of the list */
1597 /* Copy previous container partition data to current entry */
1598 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
1599 &PrevPartEntry
->PartInfo
[1],
1600 sizeof(PARTITION_INFORMATION
));
1601 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1603 /* Update previous container partition data */
1605 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1606 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1608 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1610 /* Special case - previous partition is first partition */
1611 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1612 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1616 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1617 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1620 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1622 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1624 /* Current entry is the first entry */
1627 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1629 /* Current entry is the last entry */
1631 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1632 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1634 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1636 /* Special case - previous partition is first partition */
1637 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1638 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1642 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1643 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1646 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
1647 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
1648 (1024LL * 255LL * 63LL * 512LL))
1650 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
1654 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
1657 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1658 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1661 /* Update offset and size of the remaining unpartitioned disk space */
1662 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
1663 PartEntry
->UnpartitionedLength
-= PartitionSize
;
1666 DiskEntry
->Modified
= TRUE
;
1668 UpdatePartitionNumbers (DiskEntry
);
1670 AssignDriverLetters (List
);
1675 DeleteCurrentPartition (PPARTLIST List
)
1677 PDISKENTRY DiskEntry
;
1678 PPARTENTRY PartEntry
;
1679 PPARTENTRY PrevPartEntry
;
1680 PPARTENTRY NextPartEntry
;
1683 List
->CurrentDisk
== NULL
||
1684 List
->CurrentPartition
== NULL
||
1685 List
->CurrentPartition
->Unpartitioned
== TRUE
)
1690 DiskEntry
= List
->CurrentDisk
;
1691 PartEntry
= List
->CurrentPartition
;
1693 /* Adjust container partition entries */
1695 /* Get previous and next partition entries */
1696 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1698 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1701 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1703 /* Current entry is in the middle of the list */
1706 * The first extended partition can not be deleted
1707 * as long as other extended partitions are present.
1709 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1712 /* Copy previous container partition data to current entry */
1713 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
1714 &PartEntry
->PartInfo
[1],
1715 sizeof(PARTITION_INFORMATION
));
1716 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1718 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1721 * A primary partition can not be deleted as long as
1722 * extended partitions are present.
1726 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1728 /* Current entry is the last entry */
1729 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
1730 sizeof(PARTITION_INFORMATION
));
1731 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1735 /* Adjust unpartitioned disk space entries */
1737 /* Get pointer to previous and next unpartitioned entries */
1738 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
1741 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
1744 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1746 /* Merge previous, current and next unpartitioned entry */
1748 /* Adjust the previous entries length */
1749 PrevPartEntry
->UnpartitionedLength
+=
1750 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
1751 NextPartEntry
->UnpartitionedLength
);
1753 /* Remove the current entry */
1754 RemoveEntryList (&PartEntry
->ListEntry
);
1755 RtlFreeHeap (ProcessHeap
,
1759 /* Remove the next entry */
1760 RemoveEntryList (&NextPartEntry
->ListEntry
);
1761 RtlFreeHeap (ProcessHeap
,
1765 /* Update current partition */
1766 List
->CurrentPartition
= PrevPartEntry
;
1768 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1770 /* Merge current and previous unpartitioned entry */
1772 /* Adjust the previous entries length */
1773 PrevPartEntry
->UnpartitionedLength
+=
1774 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
1776 /* Remove the current entry */
1777 RemoveEntryList (&PartEntry
->ListEntry
);
1778 RtlFreeHeap (ProcessHeap
,
1782 /* Update current partition */
1783 List
->CurrentPartition
= PrevPartEntry
;
1785 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1787 /* Merge current and next unpartitioned entry */
1789 /* Adjust the next entries offset and length */
1790 NextPartEntry
->UnpartitionedOffset
=
1791 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1792 NextPartEntry
->UnpartitionedLength
+=
1793 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
1795 /* Remove the current entry */
1796 RemoveEntryList (&PartEntry
->ListEntry
);
1797 RtlFreeHeap (ProcessHeap
,
1801 /* Update current partition */
1802 List
->CurrentPartition
= NextPartEntry
;
1806 /* Nothing to merge but change current entry */
1807 PartEntry
->New
= FALSE
;
1808 PartEntry
->Unpartitioned
= TRUE
;
1809 PartEntry
->UnpartitionedOffset
=
1810 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1811 PartEntry
->UnpartitionedLength
=
1812 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1814 /* Wipe the partition table */
1815 RtlZeroMemory (&PartEntry
->PartInfo
,
1816 sizeof(PartEntry
->PartInfo
));
1819 DiskEntry
->Modified
= TRUE
;
1821 UpdatePartitionNumbers (DiskEntry
);
1823 AssignDriverLetters (List
);
1828 CheckActiveBootPartition (PPARTLIST List
)
1830 PDISKENTRY DiskEntry
;
1831 PPARTENTRY PartEntry
;
1833 /* Check for empty disk list */
1834 if (IsListEmpty (&List
->DiskListHead
))
1836 List
->ActiveBootDisk
= NULL
;
1837 List
->ActiveBootPartition
= NULL
;
1842 if (List
->ActiveBootDisk
!= NULL
&&
1843 List
->ActiveBootPartition
!= NULL
)
1845 /* We already have an active boot partition */
1850 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
1854 /* Check for empty partition list */
1855 if (IsListEmpty (&DiskEntry
->PartListHead
))
1857 List
->ActiveBootDisk
= NULL
;
1858 List
->ActiveBootPartition
= NULL
;
1862 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
1866 /* Set active boot partition */
1867 if ((DiskEntry
->NewDisk
== TRUE
) ||
1868 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
1869 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
1870 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
1871 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
1873 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
1874 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1875 DiskEntry
->Modified
= TRUE
;
1878 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
1879 List
->ActiveBootDisk
= DiskEntry
;
1880 List
->ActiveBootPartition
= PartEntry
;
1885 CheckForLinuxFdiskPartitions (PPARTLIST List
)
1887 PDISKENTRY DiskEntry
;
1888 PPARTENTRY PartEntry
;
1891 ULONG PartitionCount
;
1894 Entry1
= List
->DiskListHead
.Flink
;
1895 while (Entry1
!= &List
->DiskListHead
)
1897 DiskEntry
= CONTAINING_RECORD (Entry1
,
1901 Entry2
= DiskEntry
->PartListHead
.Flink
;
1902 while (Entry2
!= &DiskEntry
->PartListHead
)
1904 PartEntry
= CONTAINING_RECORD (Entry2
,
1908 if (PartEntry
->Unpartitioned
== FALSE
)
1912 for (i
= 0; i
< 4; i
++)
1914 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
1915 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
1921 if (PartitionCount
> 1)
1927 Entry2
= Entry2
->Flink
;
1930 Entry1
= Entry1
->Flink
;
1938 WritePartitionsToDisk (PPARTLIST List
)
1940 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
1941 OBJECT_ATTRIBUTES ObjectAttributes
;
1942 IO_STATUS_BLOCK Iosb
;
1943 WCHAR SrcPath
[MAX_PATH
];
1944 WCHAR DstPath
[MAX_PATH
];
1945 UNICODE_STRING Name
;
1947 PDISKENTRY DiskEntry
;
1948 PPARTENTRY PartEntry
;
1951 ULONG PartitionCount
;
1952 ULONG DriveLayoutSize
;
1961 Entry1
= List
->DiskListHead
.Flink
;
1962 while (Entry1
!= &List
->DiskListHead
)
1964 DiskEntry
= CONTAINING_RECORD (Entry1
,
1968 if (DiskEntry
->Modified
== TRUE
)
1970 /* Count partitioned entries */
1972 Entry2
= DiskEntry
->PartListHead
.Flink
;
1973 while (Entry2
!= &DiskEntry
->PartListHead
)
1975 PartEntry
= CONTAINING_RECORD (Entry2
,
1978 if (PartEntry
->Unpartitioned
== FALSE
)
1980 PartitionCount
+= 4;
1983 Entry2
= Entry2
->Flink
;
1986 if (PartitionCount
> 0)
1988 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
1989 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
1990 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
1993 if (DriveLayout
== NULL
)
1995 DPRINT1 ("RtlAllocateHeap() failed\n");
1999 RtlZeroMemory (DriveLayout
,
2002 DriveLayout
->PartitionCount
= PartitionCount
;
2005 Entry2
= DiskEntry
->PartListHead
.Flink
;
2006 while (Entry2
!= &DiskEntry
->PartListHead
)
2008 PartEntry
= CONTAINING_RECORD (Entry2
,
2011 if (PartEntry
->Unpartitioned
== FALSE
)
2013 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2014 &PartEntry
->PartInfo
[0],
2015 4 * sizeof (PARTITION_INFORMATION
));
2019 Entry2
= Entry2
->Flink
;
2023 L
"\\Device\\Harddisk%d\\Partition0",
2024 DiskEntry
->DiskNumber
);
2025 RtlInitUnicodeString (&Name
,
2027 InitializeObjectAttributes (&ObjectAttributes
,
2033 Status
= NtOpenFile (&FileHandle
,
2038 FILE_SYNCHRONOUS_IO_NONALERT
);
2039 if (!NT_SUCCESS (Status
))
2041 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2045 Status
= NtDeviceIoControlFile (FileHandle
,
2050 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2055 if (!NT_SUCCESS (Status
))
2057 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2058 NtClose (FileHandle
);
2062 RtlFreeHeap (ProcessHeap
,
2066 NtClose (FileHandle
);
2068 /* Install MBR code if the disk is new */
2069 if (DiskEntry
->NewDisk
== TRUE
)
2071 wcscpy (SrcPath
, SourceRootPath
.Buffer
);
2072 wcscat (SrcPath
, L
"\\loader\\dosmbr.bin");
2074 DPRINT1 ("Install MBR bootcode: %S ==> %S\n",
2077 /* Install MBR bootcode */
2078 Status
= InstallMbrBootCodeToDisk (SrcPath
,
2080 if (!NT_SUCCESS (Status
))
2082 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
2087 DiskEntry
->NewDisk
= FALSE
;
2092 Entry1
= Entry1
->Flink
;