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)
29 #include <ddk/ntddscsi.h>
31 #include <ntdll/rtl.h>
33 #include <ntos/minmax.h>
44 /* FUNCTIONS ****************************************************************/
47 GetDriverName (PDISKENTRY DiskEntry
)
49 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
53 RtlInitUnicodeString (&DiskEntry
->DriverName
,
57 L
"\\Scsi\\Scsi Port %lu",
60 RtlZeroMemory (&QueryTable
,
63 QueryTable
[0].Name
= L
"Driver";
64 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
65 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
67 Status
= RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP
,
72 if (!NT_SUCCESS (Status
))
74 DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
80 AssignDriverLetters (PPARTLIST List
)
90 /* Assign drive letters to primary partitions */
91 Entry1
= List
->DiskListHead
.Flink
;
92 while (Entry1
!= &List
->DiskListHead
)
94 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
96 if (!IsListEmpty (&DiskEntry
->PartListHead
))
98 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
102 PartEntry
->DriveLetter
= 0;
104 if (PartEntry
->Unpartitioned
== FALSE
&&
105 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
107 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
108 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
109 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
113 PartEntry
->DriveLetter
= Letter
;
120 Entry1
= Entry1
->Flink
;
124 /* Assign drive letters to logical drives */
125 Entry1
= List
->DiskListHead
.Flink
;
126 while (Entry1
!= &List
->DiskListHead
)
128 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
130 Entry2
= DiskEntry
->PartListHead
.Flink
;
131 if (Entry2
!= &DiskEntry
->PartListHead
)
133 Entry2
= Entry2
->Flink
;
134 while (Entry2
!= &DiskEntry
->PartListHead
)
136 PartEntry
= CONTAINING_RECORD (Entry2
,
140 PartEntry
->DriveLetter
= 0;
142 if (PartEntry
->Unpartitioned
== FALSE
&&
143 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
145 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
146 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
147 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
151 PartEntry
->DriveLetter
= Letter
;
157 Entry2
= Entry2
->Flink
;
161 Entry1
= Entry1
->Flink
;
167 UpdatePartitionNumbers (PDISKENTRY DiskEntry
)
169 PPARTENTRY PartEntry
;
175 Entry
= DiskEntry
->PartListHead
.Flink
;
176 while (Entry
!= &DiskEntry
->PartListHead
)
178 PartEntry
= CONTAINING_RECORD (Entry
,
182 if (PartEntry
->Unpartitioned
== TRUE
)
184 for (i
= 0; i
< 4; i
++)
186 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
191 for (i
= 0; i
< 4; i
++)
193 if (IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
))
195 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
197 else if (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
198 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
== 0ULL)
200 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
204 PartEntry
->PartInfo
[i
].PartitionNumber
= PartNumber
;
210 Entry
= Entry
->Flink
;
216 AddPartitionToList (ULONG DiskNumber
,
217 PDISKENTRY DiskEntry
,
218 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
)
220 PPARTENTRY PartEntry
;
224 for (i
= 0; i
< LayoutBuffer
->PartitionCount
; i
+= 4)
226 for (j
= 0; j
< 4; j
++)
228 if (LayoutBuffer
->PartitionEntry
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
229 LayoutBuffer
->PartitionEntry
[j
].PartitionLength
.QuadPart
!= 0ULL)
239 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
242 if (PartEntry
== NULL
)
247 RtlZeroMemory (PartEntry
,
250 PartEntry
->Unpartitioned
= FALSE
;
252 for (j
= 0; j
< 4; j
++)
254 RtlCopyMemory (&PartEntry
->PartInfo
[j
],
255 &LayoutBuffer
->PartitionEntry
[i
+j
],
256 sizeof(PARTITION_INFORMATION
));
259 if (IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
261 PartEntry
->FormatState
= Unformatted
;
263 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
264 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
265 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
266 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
) ||
267 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
268 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
271 if (CheckFatFormat())
273 PartEntry
->FormatState
= Preformatted
;
277 PartEntry
->FormatState
= Unformatted
;
280 PartEntry
->FormatState
= Preformatted
;
282 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
285 if (CheckNtfsFormat())
287 PartEntry
->FormatState
= Preformatted
;
289 else if (CheckHpfsFormat())
291 PartEntry
->FormatState
= Preformatted
;
295 PartEntry
->FormatState
= Unformatted
;
298 PartEntry
->FormatState
= Preformatted
;
302 PartEntry
->FormatState
= Unknown
;
305 InsertTailList (&DiskEntry
->PartListHead
,
306 &PartEntry
->ListEntry
);
312 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry
)
314 ULONGLONG LastStartingOffset
;
315 ULONGLONG LastPartitionLength
;
316 ULONGLONG LastUnusedPartitionLength
;
317 PPARTENTRY PartEntry
;
318 PPARTENTRY NewPartEntry
;
323 if (IsListEmpty (&DiskEntry
->PartListHead
))
325 /* Create a partition table that represents the empty disk */
326 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
329 if (PartEntry
== NULL
)
332 RtlZeroMemory (PartEntry
,
335 PartEntry
->Unpartitioned
= TRUE
;
336 PartEntry
->UnpartitionedOffset
= 0ULL;
337 PartEntry
->UnpartitionedLength
= DiskEntry
->DiskSize
;
339 PartEntry
->FormatState
= Unformatted
;
341 InsertTailList (&DiskEntry
->PartListHead
,
342 &PartEntry
->ListEntry
);
346 /* Start partition at head 1, cylinder 0 */
347 LastStartingOffset
= DiskEntry
->TrackSize
;
348 LastPartitionLength
= 0ULL;
349 LastUnusedPartitionLength
= 0ULL;
352 Entry
= DiskEntry
->PartListHead
.Flink
;
353 while (Entry
!= &DiskEntry
->PartListHead
)
355 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
357 for (j
= 0; j
< 4; j
++)
359 if ((!IsContainerPartition (PartEntry
->PartInfo
[j
].PartitionType
)) &&
360 (PartEntry
->PartInfo
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
361 PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
!= 0LL))
363 LastUnusedPartitionLength
=
364 PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
-
365 (LastStartingOffset
+ LastPartitionLength
);
367 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
369 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
371 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
374 if (NewPartEntry
== NULL
)
377 RtlZeroMemory (NewPartEntry
,
380 NewPartEntry
->Unpartitioned
= TRUE
;
381 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
382 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
384 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
386 NewPartEntry
->FormatState
= Unformatted
;
388 /* Insert the table into the list */
389 InsertTailList (&PartEntry
->ListEntry
,
390 &NewPartEntry
->ListEntry
);
393 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
394 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
399 Entry
= Entry
->Flink
;
402 /* Check for trailing unpartitioned disk space */
403 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
405 /* Round-down to cylinder size */
406 LastUnusedPartitionLength
=
407 ROUND_DOWN (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
),
408 DiskEntry
->CylinderSize
);
410 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
412 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
414 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
417 if (NewPartEntry
== NULL
)
420 RtlZeroMemory (NewPartEntry
,
423 NewPartEntry
->Unpartitioned
= TRUE
;
424 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
425 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
427 /* Append the table to the list */
428 InsertTailList (&DiskEntry
->PartListHead
,
429 &NewPartEntry
->ListEntry
);
437 AddDiskToList (HANDLE FileHandle
,
441 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
442 DISK_GEOMETRY DiskGeometry
;
443 SCSI_ADDRESS ScsiAddress
;
444 PDISKENTRY DiskEntry
;
445 IO_STATUS_BLOCK Iosb
;
448 Status
= NtDeviceIoControlFile (FileHandle
,
453 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
457 sizeof(DISK_GEOMETRY
));
458 if (!NT_SUCCESS (Status
))
463 if (DiskGeometry
.MediaType
!= FixedMedia
)
468 Status
= NtDeviceIoControlFile (FileHandle
,
473 IOCTL_SCSI_GET_ADDRESS
,
477 sizeof(SCSI_ADDRESS
));
478 if (!NT_SUCCESS(Status
))
483 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
486 if (DiskEntry
== NULL
)
491 InitializeListHead (&DiskEntry
->PartListHead
);
493 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
494 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
495 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
496 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
498 DPRINT ("Cylinders %d\n", DiskEntry
->Cylinders
);
499 DPRINT ("TracksPerCylinder %d\n", DiskEntry
->TracksPerCylinder
);
500 DPRINT ("SectorsPerTrack %d\n", DiskEntry
->SectorsPerTrack
);
501 DPRINT ("BytesPerSector %d\n", DiskEntry
->BytesPerSector
);
503 DiskEntry
->DiskSize
=
504 DiskGeometry
.Cylinders
.QuadPart
*
505 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
506 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
507 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
508 DiskEntry
->CylinderSize
=
509 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
510 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
511 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
512 DiskEntry
->TrackSize
=
513 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
514 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
516 DiskEntry
->DiskNumber
= DiskNumber
;
517 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
518 DiskEntry
->Bus
= ScsiAddress
.PathId
;
519 DiskEntry
->Id
= ScsiAddress
.TargetId
;
521 GetDriverName (DiskEntry
);
523 InsertTailList (&List
->DiskListHead
,
524 &DiskEntry
->ListEntry
);
526 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
529 if (LayoutBuffer
== NULL
)
534 Status
= NtDeviceIoControlFile (FileHandle
,
539 IOCTL_DISK_GET_DRIVE_LAYOUT
,
544 if (NT_SUCCESS (Status
))
546 if (LayoutBuffer
->PartitionCount
== 0)
548 DiskEntry
->NewDisk
= TRUE
;
551 AddPartitionToList (DiskNumber
,
555 ScanForUnpartitionedDiskSpace (DiskEntry
);
558 RtlFreeHeap (ProcessHeap
,
565 CreatePartitionList (SHORT Left
,
571 OBJECT_ATTRIBUTES ObjectAttributes
;
572 SYSTEM_DEVICE_INFORMATION Sdi
;
573 IO_STATUS_BLOCK Iosb
;
577 WCHAR Buffer
[MAX_PATH
];
581 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
590 List
->Bottom
= Bottom
;
594 List
->TopDisk
= (ULONG
)-1;
595 List
->TopPartition
= (ULONG
)-1;
597 List
->CurrentDisk
= NULL
;
598 List
->CurrentPartition
= NULL
;
600 InitializeListHead (&List
->DiskListHead
);
602 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
604 sizeof(SYSTEM_DEVICE_INFORMATION
),
606 if (!NT_SUCCESS (Status
))
608 RtlFreeHeap (ProcessHeap
, 0, List
);
612 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
615 L
"\\Device\\Harddisk%d\\Partition0",
617 RtlInitUnicodeString (&Name
,
620 InitializeObjectAttributes (&ObjectAttributes
,
626 Status
= NtOpenFile (&FileHandle
,
631 FILE_SYNCHRONOUS_IO_NONALERT
);
632 if (NT_SUCCESS(Status
))
634 AddDiskToList (FileHandle
,
642 AssignDriverLetters (List
);
645 List
->TopPartition
= 0;
647 /* Search for first usable disk and partition */
648 if (IsListEmpty (&List
->DiskListHead
))
650 List
->CurrentDisk
= NULL
;
651 List
->CurrentPartition
= NULL
;
656 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
660 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
662 List
->CurrentPartition
= 0;
666 List
->CurrentPartition
=
667 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
678 DestroyPartitionList (PPARTLIST List
)
680 PDISKENTRY DiskEntry
;
681 PPARTENTRY PartEntry
;
684 /* Release disk and partition info */
685 while (!IsListEmpty (&List
->DiskListHead
))
687 Entry
= RemoveHeadList (&List
->DiskListHead
);
688 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
690 /* Release driver name */
691 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
693 /* Release partition array */
694 while (!IsListEmpty (&DiskEntry
->PartListHead
))
696 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
697 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
699 RtlFreeHeap (ProcessHeap
,
704 /* Release disk entry */
705 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
708 /* Release list head */
709 RtlFreeHeap (ProcessHeap
, 0, List
);
714 PrintEmptyLine (PPARTLIST List
)
721 Width
= List
->Right
- List
->Left
- 1;
722 Height
= List
->Bottom
- List
->Top
- 2;
725 coPos
.X
= List
->Left
+ 1;
726 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
728 if (List
->Line
>= 0 && List
->Line
<= Height
)
730 FillConsoleOutputAttribute (0x17,
735 FillConsoleOutputCharacter (' ',
745 PrintPartitionData (PPARTLIST List
,
746 PDISKENTRY DiskEntry
,
747 PPARTENTRY PartEntry
)
749 CHAR LineBuffer
[128];
760 Width
= List
->Right
- List
->Left
- 1;
761 Height
= List
->Bottom
- List
->Top
- 2;
764 coPos
.X
= List
->Left
+ 1;
765 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
767 if (PartEntry
->Unpartitioned
== TRUE
)
770 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
772 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
777 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
779 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
784 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
789 " Unpartitioned space %6I64u %s",
795 /* Determine partition type */
797 if (PartEntry
->New
== TRUE
)
799 PartType
= "New (Unformatted)";
801 else if (PartEntry
->Unpartitioned
== FALSE
)
803 if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
804 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
805 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
806 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
))
810 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
811 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
815 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
817 PartType
= "NTFS"; /* FIXME: Not quite correct! */
822 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0x280000000ULL
) /* 10 GB */
824 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
829 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0xA00000ULL
) /* 10 MB */
831 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
836 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
840 if (PartType
== NULL
)
843 "%c%c Type %-3u %6I64u %s",
844 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
845 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
846 PartEntry
->PartInfo
[0].PartitionType
,
853 "%c%c %-24s %6I64u %s",
854 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
855 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
862 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
863 List
->CurrentPartition
== PartEntry
) ? 0x71 : 0x17;
865 if (List
->Line
>= 0 && List
->Line
<= Height
)
867 FillConsoleOutputCharacter (' ',
874 if (List
->Line
>= 0 && List
->Line
<= Height
)
876 FillConsoleOutputAttribute (Attribute
,
883 if (List
->Line
>= 0 && List
->Line
<= Height
)
885 WriteConsoleOutputCharacters (LineBuffer
,
886 min (strlen (LineBuffer
), Width
),
894 PrintDiskData (PPARTLIST List
,
895 PDISKENTRY DiskEntry
)
897 PPARTENTRY PartEntry
;
899 CHAR LineBuffer
[128];
907 Width
= List
->Right
- List
->Left
- 1;
908 Height
= List
->Bottom
- List
->Top
- 2;
911 coPos
.X
= List
->Left
+ 1;
912 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
915 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
917 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
923 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
929 if (DiskEntry
->DriverName
.Length
> 0)
932 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ",
935 DiskEntry
->DiskNumber
,
939 &DiskEntry
->DriverName
);
944 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
947 DiskEntry
->DiskNumber
,
952 if (List
->Line
>= 0 && List
->Line
<= Height
)
954 FillConsoleOutputAttribute (0x17,
959 FillConsoleOutputCharacter (' ',
966 if (List
->Line
>= 0 && List
->Line
<= Height
)
968 WriteConsoleOutputCharacters (LineBuffer
,
969 min (strlen (LineBuffer
), Width
- 2),
974 /* Print separator line */
975 PrintEmptyLine (List
);
977 /* Print partition lines*/
978 Entry
= DiskEntry
->PartListHead
.Flink
;
979 while (Entry
!= &DiskEntry
->PartListHead
)
981 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
983 /* Print disk entry */
984 PrintPartitionData (List
,
988 Entry
= Entry
->Flink
;
991 /* Print separator line */
992 PrintEmptyLine (List
);
997 DrawPartitionList (PPARTLIST List
)
999 PLIST_ENTRY Entry
, Entry2
;
1000 PDISKENTRY DiskEntry
;
1001 PPARTENTRY PartEntry
= NULL
;
1005 SHORT CurrentDiskLine
;
1006 SHORT CurrentPartLine
;
1008 BOOL CurrentPartLineFound
= FALSE
;
1009 BOOL CurrentDiskLineFound
= FALSE
;
1011 /* Calculate the line of the current disk and partition */
1012 CurrentDiskLine
= 0;
1013 CurrentPartLine
= 0;
1015 Entry
= List
->DiskListHead
.Flink
;
1016 while (Entry
!= &List
->DiskListHead
)
1018 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1020 if (CurrentPartLineFound
== FALSE
)
1022 CurrentPartLine
+= 2;
1024 Entry2
= DiskEntry
->PartListHead
.Flink
;
1025 while (Entry2
!= &DiskEntry
->PartListHead
)
1027 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1028 if (PartEntry
== List
->CurrentPartition
)
1030 CurrentPartLineFound
= TRUE
;
1032 Entry2
= Entry2
->Flink
;
1033 if (CurrentPartLineFound
== FALSE
)
1039 if (DiskEntry
== List
->CurrentDisk
)
1041 CurrentDiskLineFound
= TRUE
;
1043 Entry
= Entry
->Flink
;
1044 if (Entry
!= &List
->DiskListHead
)
1046 if (CurrentDiskLineFound
== FALSE
)
1049 CurrentDiskLine
= CurrentPartLine
;
1059 /* If it possible, make the disk name visible */
1060 if (CurrentPartLine
< List
->Offset
)
1062 List
->Offset
= CurrentPartLine
;
1064 else if (CurrentPartLine
- List
->Offset
> List
->Bottom
- List
->Top
- 2)
1066 List
->Offset
= CurrentPartLine
- (List
->Bottom
- List
->Top
- 2);
1068 if (CurrentDiskLine
< List
->Offset
&& CurrentPartLine
- CurrentDiskLine
< List
->Bottom
- List
->Top
- 2)
1070 List
->Offset
= CurrentDiskLine
;
1074 /* draw upper left corner */
1075 coPos
.X
= List
->Left
;
1076 coPos
.Y
= List
->Top
;
1077 FillConsoleOutputCharacter (0xDA, // '+',
1082 /* draw upper edge */
1083 coPos
.X
= List
->Left
+ 1;
1084 coPos
.Y
= List
->Top
;
1085 if (List
->Offset
== 0)
1087 FillConsoleOutputCharacter (0xC4, // '-',
1088 List
->Right
- List
->Left
- 1,
1094 FillConsoleOutputCharacter (0xC4, // '-',
1095 List
->Right
- List
->Left
- 5,
1098 coPos
.X
= List
->Right
- 5;
1099 WriteConsoleOutputCharacters ("(\x18)", // "(up)"
1102 coPos
.X
= List
->Right
- 2;
1103 FillConsoleOutputCharacter (0xC4, // '-',
1109 /* draw upper right corner */
1110 coPos
.X
= List
->Right
;
1111 coPos
.Y
= List
->Top
;
1112 FillConsoleOutputCharacter (0xBF, // '+',
1117 /* draw left and right edge */
1118 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1120 coPos
.X
= List
->Left
;
1122 FillConsoleOutputCharacter (0xB3, // '|',
1127 coPos
.X
= List
->Right
;
1128 FillConsoleOutputCharacter (0xB3, //'|',
1134 /* draw lower left corner */
1135 coPos
.X
= List
->Left
;
1136 coPos
.Y
= List
->Bottom
;
1137 FillConsoleOutputCharacter (0xC0, // '+',
1142 /* draw lower edge */
1143 coPos
.X
= List
->Left
+ 1;
1144 coPos
.Y
= List
->Bottom
;
1145 if (LastLine
- List
->Offset
<= List
->Bottom
- List
->Top
- 2)
1147 FillConsoleOutputCharacter (0xC4, // '-',
1148 List
->Right
- List
->Left
- 1,
1154 FillConsoleOutputCharacter (0xC4, // '-',
1155 List
->Right
- List
->Left
- 5,
1158 coPos
.X
= List
->Right
- 5;
1159 WriteConsoleOutputCharacters ("(\x19)", // "(down)"
1162 coPos
.X
= List
->Right
- 2;
1163 FillConsoleOutputCharacter (0xC4, // '-',
1169 /* draw lower right corner */
1170 coPos
.X
= List
->Right
;
1171 coPos
.Y
= List
->Bottom
;
1172 FillConsoleOutputCharacter (0xD9, // '+',
1177 /* print list entries */
1178 List
->Line
= - List
->Offset
;
1180 Entry
= List
->DiskListHead
.Flink
;
1181 while (Entry
!= &List
->DiskListHead
)
1183 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1185 /* Print disk entry */
1186 PrintDiskData (List
,
1189 Entry
= Entry
->Flink
;
1195 SelectPartition(PPARTLIST List
, ULONG DiskNumber
, ULONG PartitionNumber
)
1197 PDISKENTRY DiskEntry
;
1198 PPARTENTRY PartEntry
;
1203 /* Check for empty disks */
1204 if (IsListEmpty (&List
->DiskListHead
))
1207 /* Check for first usable entry on next disk */
1208 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1209 while (Entry1
!= &List
->DiskListHead
)
1211 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1213 if (DiskEntry
->DiskNumber
== DiskNumber
)
1215 Entry2
= DiskEntry
->PartListHead
.Flink
;
1216 while (Entry2
!= &DiskEntry
->PartListHead
)
1218 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1220 for (i
= 0; i
< 4; i
++)
1222 if (PartEntry
->PartInfo
[i
].PartitionNumber
== PartitionNumber
)
1224 List
->CurrentDisk
= DiskEntry
;
1225 List
->CurrentPartition
= PartEntry
;
1226 DrawPartitionList (List
);
1230 Entry2
= Entry2
->Flink
;
1234 Entry1
= Entry1
->Flink
;
1240 ScrollDownPartitionList (PPARTLIST List
)
1242 PDISKENTRY DiskEntry
;
1243 PPARTENTRY PartEntry
;
1247 /* Check for empty disks */
1248 if (IsListEmpty (&List
->DiskListHead
))
1251 /* Check for next usable entry on current disk */
1252 if (List
->CurrentPartition
!= NULL
)
1254 Entry2
= List
->CurrentPartition
->ListEntry
.Flink
;
1255 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1257 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1259 // if (PartEntry->HidePartEntry == FALSE)
1261 List
->CurrentPartition
= PartEntry
;
1262 DrawPartitionList (List
);
1265 Entry2
= Entry2
->Flink
;
1269 /* Check for first usable entry on next disk */
1270 if (List
->CurrentDisk
!= NULL
)
1272 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1273 while (Entry1
!= &List
->DiskListHead
)
1275 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1277 Entry2
= DiskEntry
->PartListHead
.Flink
;
1278 while (Entry2
!= &DiskEntry
->PartListHead
)
1280 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1282 // if (PartEntry->HidePartEntry == FALSE)
1284 List
->CurrentDisk
= DiskEntry
;
1285 List
->CurrentPartition
= PartEntry
;
1286 DrawPartitionList (List
);
1290 Entry2
= Entry2
->Flink
;
1293 Entry1
= Entry1
->Flink
;
1300 ScrollUpPartitionList (PPARTLIST List
)
1302 PDISKENTRY DiskEntry
;
1303 PPARTENTRY PartEntry
;
1307 /* Check for empty disks */
1308 if (IsListEmpty (&List
->DiskListHead
))
1311 /* check for previous usable entry on current disk */
1312 if (List
->CurrentPartition
!= NULL
)
1314 Entry2
= List
->CurrentPartition
->ListEntry
.Blink
;
1315 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1317 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1319 // if (PartEntry->HidePartEntry == FALSE)
1321 List
->CurrentPartition
= PartEntry
;
1322 DrawPartitionList (List
);
1325 Entry2
= Entry2
->Blink
;
1330 /* check for last usable entry on previous disk */
1331 if (List
->CurrentDisk
!= NULL
)
1333 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1334 while (Entry1
!= &List
->DiskListHead
)
1336 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1338 Entry2
= DiskEntry
->PartListHead
.Blink
;
1339 while (Entry2
!= &DiskEntry
->PartListHead
)
1341 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1343 // if (PartEntry->HidePartEntry == FALSE)
1345 List
->CurrentDisk
= DiskEntry
;
1346 List
->CurrentPartition
= PartEntry
;
1347 DrawPartitionList (List
);
1351 Entry2
= Entry2
->Blink
;
1354 Entry1
= Entry1
->Blink
;
1361 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1362 PPARTENTRY CurrentEntry
)
1364 PPARTENTRY PrevEntry
;
1367 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1370 Entry
= CurrentEntry
->ListEntry
.Blink
;
1371 while (Entry
!= &DiskEntry
->PartListHead
)
1373 PrevEntry
= CONTAINING_RECORD (Entry
,
1376 if (PrevEntry
->Unpartitioned
== FALSE
)
1379 Entry
= Entry
->Blink
;
1387 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1388 PPARTENTRY CurrentEntry
)
1390 PPARTENTRY NextEntry
;
1393 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1396 Entry
= CurrentEntry
->ListEntry
.Flink
;
1397 while (Entry
!= &DiskEntry
->PartListHead
)
1399 NextEntry
= CONTAINING_RECORD (Entry
,
1402 if (NextEntry
->Unpartitioned
== FALSE
)
1405 Entry
= Entry
->Flink
;
1413 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1414 PPARTENTRY PartEntry
)
1416 PPARTENTRY PrevPartEntry
;
1418 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1420 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1423 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1424 return PrevPartEntry
;
1432 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1433 PPARTENTRY PartEntry
)
1435 PPARTENTRY NextPartEntry
;
1437 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1439 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1442 if (NextPartEntry
->Unpartitioned
== TRUE
)
1443 return NextPartEntry
;
1451 CreateNewPartition (PPARTLIST List
,
1452 ULONGLONG PartitionSize
,
1455 PDISKENTRY DiskEntry
;
1456 PPARTENTRY PartEntry
;
1457 PPARTENTRY PrevPartEntry
;
1458 PPARTENTRY NextPartEntry
;
1459 PPARTENTRY NewPartEntry
;
1462 List
->CurrentDisk
== NULL
||
1463 List
->CurrentPartition
== NULL
||
1464 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1469 DiskEntry
= List
->CurrentDisk
;
1470 PartEntry
= List
->CurrentPartition
;
1472 if (AutoCreate
== TRUE
||
1473 PartitionSize
== PartEntry
->UnpartitionedLength
)
1475 /* Convert current entry to 'new (unformatted)' */
1476 PartEntry
->FormatState
= Unformatted
;
1477 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1478 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1479 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1480 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1481 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1482 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1483 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1484 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1485 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1486 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1488 /* Get previous and next partition entries */
1489 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1491 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1494 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1496 /* Current entry is in the middle of the list */
1498 /* Copy previous container partition data to current entry */
1499 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1500 &PrevPartEntry
->PartInfo
[1],
1501 sizeof(PARTITION_INFORMATION
));
1502 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1504 /* Update previous container partition data */
1506 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1507 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1509 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1511 /* Special case - previous partition is first partition */
1512 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1513 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1517 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1518 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1521 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1523 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1525 /* Current entry is the first entry */
1528 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1530 /* Current entry is the last entry */
1532 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1533 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1535 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1537 /* Special case - previous partition is first partition */
1538 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1539 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1543 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1544 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1547 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
1548 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
1549 (1024ULL * 255ULL * 63ULL * 512ULL))
1551 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
1555 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
1558 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1559 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1562 PartEntry
->AutoCreate
= AutoCreate
;
1563 PartEntry
->New
= TRUE
;
1564 PartEntry
->Unpartitioned
= FALSE
;
1565 PartEntry
->UnpartitionedOffset
= 0ULL;
1566 PartEntry
->UnpartitionedLength
= 0ULL;
1570 /* Insert an initialize a new partition entry */
1571 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
1574 if (NewPartEntry
== NULL
)
1577 RtlZeroMemory (NewPartEntry
,
1580 /* Insert the new entry into the list */
1581 InsertTailList (&PartEntry
->ListEntry
,
1582 &NewPartEntry
->ListEntry
);
1584 NewPartEntry
->New
= TRUE
;
1586 NewPartEntry
->FormatState
= Unformatted
;
1587 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1588 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1589 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1590 PartitionSize
- DiskEntry
->TrackSize
;
1591 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1592 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1593 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1594 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1595 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1596 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1598 /* Get previous and next partition entries */
1599 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1601 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1604 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1606 /* Current entry is in the middle of the list */
1608 /* Copy previous container partition data to current entry */
1609 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
1610 &PrevPartEntry
->PartInfo
[1],
1611 sizeof(PARTITION_INFORMATION
));
1612 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1614 /* Update previous container partition data */
1616 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1617 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1619 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1621 /* Special case - previous partition is first partition */
1622 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1623 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1627 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1628 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1631 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1633 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1635 /* Current entry is the first entry */
1638 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1640 /* Current entry is the last entry */
1642 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1643 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1645 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1647 /* Special case - previous partition is first partition */
1648 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1649 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1653 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1654 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1657 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
1658 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
1659 (1024ULL * 255ULL * 63ULL * 512ULL))
1661 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
1665 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
1668 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1669 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1672 /* Update offset and size of the remaining unpartitioned disk space */
1673 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
1674 PartEntry
->UnpartitionedLength
-= PartitionSize
;
1677 DiskEntry
->Modified
= TRUE
;
1679 UpdatePartitionNumbers (DiskEntry
);
1681 AssignDriverLetters (List
);
1686 DeleteCurrentPartition (PPARTLIST List
)
1688 PDISKENTRY DiskEntry
;
1689 PPARTENTRY PartEntry
;
1690 PPARTENTRY PrevPartEntry
;
1691 PPARTENTRY NextPartEntry
;
1694 List
->CurrentDisk
== NULL
||
1695 List
->CurrentPartition
== NULL
||
1696 List
->CurrentPartition
->Unpartitioned
== TRUE
)
1701 DiskEntry
= List
->CurrentDisk
;
1702 PartEntry
= List
->CurrentPartition
;
1704 /* Adjust container partition entries */
1706 /* Get previous and next partition entries */
1707 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1709 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1712 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1714 /* Current entry is in the middle of the list */
1717 * The first extended partition can not be deleted
1718 * as long as other extended partitions are present.
1720 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1723 /* Copy previous container partition data to current entry */
1724 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
1725 &PartEntry
->PartInfo
[1],
1726 sizeof(PARTITION_INFORMATION
));
1727 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1729 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1732 * A primary partition can not be deleted as long as
1733 * extended partitions are present.
1737 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1739 /* Current entry is the last entry */
1740 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
1741 sizeof(PARTITION_INFORMATION
));
1742 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1746 /* Adjust unpartitioned disk space entries */
1748 /* Get pointer to previous and next unpartitioned entries */
1749 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
1752 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
1755 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1757 /* Merge previous, current and next unpartitioned entry */
1759 /* Adjust the previous entries length */
1760 PrevPartEntry
->UnpartitionedLength
+=
1761 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
1762 NextPartEntry
->UnpartitionedLength
);
1764 /* Remove the current entry */
1765 RemoveEntryList (&PartEntry
->ListEntry
);
1766 RtlFreeHeap (ProcessHeap
,
1770 /* Remove the next entry */
1771 RemoveEntryList (&NextPartEntry
->ListEntry
);
1772 RtlFreeHeap (ProcessHeap
,
1776 /* Update current partition */
1777 List
->CurrentPartition
= PrevPartEntry
;
1779 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1781 /* Merge current and previous unpartitioned entry */
1783 /* Adjust the previous entries length */
1784 PrevPartEntry
->UnpartitionedLength
+=
1785 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
1787 /* Remove the current entry */
1788 RemoveEntryList (&PartEntry
->ListEntry
);
1789 RtlFreeHeap (ProcessHeap
,
1793 /* Update current partition */
1794 List
->CurrentPartition
= PrevPartEntry
;
1796 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1798 /* Merge current and next unpartitioned entry */
1800 /* Adjust the next entries offset and length */
1801 NextPartEntry
->UnpartitionedOffset
=
1802 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1803 NextPartEntry
->UnpartitionedLength
+=
1804 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
1806 /* Remove the current entry */
1807 RemoveEntryList (&PartEntry
->ListEntry
);
1808 RtlFreeHeap (ProcessHeap
,
1812 /* Update current partition */
1813 List
->CurrentPartition
= NextPartEntry
;
1817 /* Nothing to merge but change current entry */
1818 PartEntry
->New
= FALSE
;
1819 PartEntry
->Unpartitioned
= TRUE
;
1820 PartEntry
->UnpartitionedOffset
=
1821 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1822 PartEntry
->UnpartitionedLength
=
1823 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1825 /* Wipe the partition table */
1826 RtlZeroMemory (&PartEntry
->PartInfo
,
1827 sizeof(PartEntry
->PartInfo
));
1830 DiskEntry
->Modified
= TRUE
;
1832 UpdatePartitionNumbers (DiskEntry
);
1834 AssignDriverLetters (List
);
1839 CheckActiveBootPartition (PPARTLIST List
)
1841 PDISKENTRY DiskEntry
;
1842 PPARTENTRY PartEntry
;
1844 /* Check for empty disk list */
1845 if (IsListEmpty (&List
->DiskListHead
))
1847 List
->ActiveBootDisk
= NULL
;
1848 List
->ActiveBootPartition
= NULL
;
1853 if (List
->ActiveBootDisk
!= NULL
&&
1854 List
->ActiveBootPartition
!= NULL
)
1856 /* We already have an active boot partition */
1861 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
1865 /* Check for empty partition list */
1866 if (IsListEmpty (&DiskEntry
->PartListHead
))
1868 List
->ActiveBootDisk
= NULL
;
1869 List
->ActiveBootPartition
= NULL
;
1873 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
1877 /* Set active boot partition */
1878 if ((DiskEntry
->NewDisk
== TRUE
) ||
1879 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
1880 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
1881 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
1882 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
1884 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
1885 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1886 DiskEntry
->Modified
= TRUE
;
1889 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
1890 List
->ActiveBootDisk
= DiskEntry
;
1891 List
->ActiveBootPartition
= PartEntry
;
1896 CheckForLinuxFdiskPartitions (PPARTLIST List
)
1898 PDISKENTRY DiskEntry
;
1899 PPARTENTRY PartEntry
;
1902 ULONG PartitionCount
;
1905 Entry1
= List
->DiskListHead
.Flink
;
1906 while (Entry1
!= &List
->DiskListHead
)
1908 DiskEntry
= CONTAINING_RECORD (Entry1
,
1912 Entry2
= DiskEntry
->PartListHead
.Flink
;
1913 while (Entry2
!= &DiskEntry
->PartListHead
)
1915 PartEntry
= CONTAINING_RECORD (Entry2
,
1919 if (PartEntry
->Unpartitioned
== FALSE
)
1923 for (i
= 0; i
< 4; i
++)
1925 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
1926 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
1932 if (PartitionCount
> 1)
1938 Entry2
= Entry2
->Flink
;
1941 Entry1
= Entry1
->Flink
;
1949 WritePartitionsToDisk (PPARTLIST List
)
1951 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
1952 OBJECT_ATTRIBUTES ObjectAttributes
;
1953 IO_STATUS_BLOCK Iosb
;
1954 WCHAR SrcPath
[MAX_PATH
];
1955 WCHAR DstPath
[MAX_PATH
];
1956 UNICODE_STRING Name
;
1958 PDISKENTRY DiskEntry
;
1959 PPARTENTRY PartEntry
;
1962 ULONG PartitionCount
;
1963 ULONG DriveLayoutSize
;
1972 Entry1
= List
->DiskListHead
.Flink
;
1973 while (Entry1
!= &List
->DiskListHead
)
1975 DiskEntry
= CONTAINING_RECORD (Entry1
,
1979 if (DiskEntry
->Modified
== TRUE
)
1981 /* Count partitioned entries */
1983 Entry2
= DiskEntry
->PartListHead
.Flink
;
1984 while (Entry2
!= &DiskEntry
->PartListHead
)
1986 PartEntry
= CONTAINING_RECORD (Entry2
,
1989 if (PartEntry
->Unpartitioned
== FALSE
)
1991 PartitionCount
+= 4;
1994 Entry2
= Entry2
->Flink
;
1997 if (PartitionCount
> 0)
1999 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
2000 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
2001 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
2004 if (DriveLayout
== NULL
)
2006 DPRINT1 ("RtlAllocateHeap() failed\n");
2010 RtlZeroMemory (DriveLayout
,
2013 DriveLayout
->PartitionCount
= PartitionCount
;
2016 Entry2
= DiskEntry
->PartListHead
.Flink
;
2017 while (Entry2
!= &DiskEntry
->PartListHead
)
2019 PartEntry
= CONTAINING_RECORD (Entry2
,
2022 if (PartEntry
->Unpartitioned
== FALSE
)
2024 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
2025 &PartEntry
->PartInfo
[0],
2026 4 * sizeof (PARTITION_INFORMATION
));
2030 Entry2
= Entry2
->Flink
;
2034 L
"\\Device\\Harddisk%d\\Partition0",
2035 DiskEntry
->DiskNumber
);
2036 RtlInitUnicodeString (&Name
,
2038 InitializeObjectAttributes (&ObjectAttributes
,
2044 Status
= NtOpenFile (&FileHandle
,
2049 FILE_SYNCHRONOUS_IO_NONALERT
);
2050 if (!NT_SUCCESS (Status
))
2052 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
2056 Status
= NtDeviceIoControlFile (FileHandle
,
2061 IOCTL_DISK_SET_DRIVE_LAYOUT
,
2066 if (!NT_SUCCESS (Status
))
2068 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
2069 NtClose (FileHandle
);
2073 RtlFreeHeap (ProcessHeap
,
2077 NtClose (FileHandle
);
2079 /* Install MBR code if the disk is new */
2080 if (DiskEntry
->NewDisk
== TRUE
)
2082 wcscpy (SrcPath
, SourceRootPath
.Buffer
);
2083 wcscat (SrcPath
, L
"\\loader\\dosmbr.bin");
2085 DPRINT1 ("Install MBR bootcode: %S ==> %S\n",
2088 /* Install MBR bootcode */
2089 Status
= InstallMbrBootCodeToDisk (SrcPath
,
2091 if (!NT_SUCCESS (Status
))
2093 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
2098 DiskEntry
->NewDisk
= FALSE
;
2103 Entry1
= Entry1
->Flink
;