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.
19 /* $Id: partlist.c,v 1.23 2003/08/29 11:27:16 ekohl Exp $
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)
28 #include <ddk/ntddk.h>
29 #include <ddk/ntddscsi.h>
31 #include <ntdll/rtl.h>
33 #include <ntos/minmax.h>
41 /* FUNCTIONS ****************************************************************/
44 GetDriverName (PDISKENTRY DiskEntry
)
46 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
50 RtlInitUnicodeString (&DiskEntry
->DriverName
,
54 L
"\\Scsi\\Scsi Port %lu",
57 RtlZeroMemory (&QueryTable
,
60 QueryTable
[0].Name
= L
"Driver";
61 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
62 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
64 Status
= RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP
,
69 if (!NT_SUCCESS (Status
))
71 DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
77 AssignDriverLetters (PPARTLIST List
)
87 /* Assign drive letters to primary partitions */
88 Entry1
= List
->DiskListHead
.Flink
;
89 while (Entry1
!= &List
->DiskListHead
)
91 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
93 if (!IsListEmpty (&DiskEntry
->PartListHead
))
95 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
99 PartEntry
->DriveLetter
= 0;
101 if (PartEntry
->Unpartitioned
== FALSE
&&
102 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
104 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
105 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
106 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
110 PartEntry
->DriveLetter
= Letter
;
117 Entry1
= Entry1
->Flink
;
121 /* Assign drive letters to logical drives */
122 Entry1
= List
->DiskListHead
.Flink
;
123 while (Entry1
!= &List
->DiskListHead
)
125 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
127 Entry2
= DiskEntry
->PartListHead
.Flink
;
128 if (Entry2
!= &DiskEntry
->PartListHead
)
130 Entry2
= Entry2
->Flink
;
131 while (Entry2
!= &DiskEntry
->PartListHead
)
133 PartEntry
= CONTAINING_RECORD (Entry2
,
137 PartEntry
->DriveLetter
= 0;
139 if (PartEntry
->Unpartitioned
== FALSE
&&
140 !IsContainerPartition (PartEntry
->PartInfo
[0].PartitionType
))
142 if (IsRecognizedPartition (PartEntry
->PartInfo
[0].PartitionType
) ||
143 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_ENTRY_UNUSED
&&
144 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
!= 0LL))
148 PartEntry
->DriveLetter
= Letter
;
154 Entry2
= Entry2
->Flink
;
158 Entry1
= Entry1
->Flink
;
164 UpdatePartitionNumbers (PDISKENTRY DiskEntry
)
166 PPARTENTRY PartEntry
;
172 Entry
= DiskEntry
->PartListHead
.Flink
;
173 while (Entry
!= &DiskEntry
->PartListHead
)
175 PartEntry
= CONTAINING_RECORD (Entry
,
179 if (PartEntry
->Unpartitioned
== TRUE
)
181 for (i
= 0; i
< 4; i
++)
183 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
188 for (i
= 0; i
< 4; i
++)
190 if (IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
))
192 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
194 else if (PartEntry
->PartInfo
[i
].PartitionType
== PARTITION_ENTRY_UNUSED
&&
195 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
== 0ULL)
197 PartEntry
->PartInfo
[i
].PartitionNumber
= 0;
201 PartEntry
->PartInfo
[i
].PartitionNumber
= PartNumber
;
207 Entry
= Entry
->Flink
;
213 AddPartitionToList (ULONG DiskNumber
,
214 PDISKENTRY DiskEntry
,
215 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
)
217 PPARTENTRY PartEntry
;
221 for (i
= 0; i
< LayoutBuffer
->PartitionCount
; i
+= 4)
223 for (j
= 0; j
< 4; j
++)
225 if (LayoutBuffer
->PartitionEntry
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
226 LayoutBuffer
->PartitionEntry
[j
].PartitionLength
.QuadPart
!= 0ULL)
236 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
239 if (PartEntry
== NULL
)
244 RtlZeroMemory (PartEntry
,
247 PartEntry
->Unpartitioned
= FALSE
;
249 for (j
= 0; j
< 4; j
++)
251 RtlCopyMemory (&PartEntry
->PartInfo
[j
],
252 &LayoutBuffer
->PartitionEntry
[i
+j
],
253 sizeof(PARTITION_INFORMATION
));
256 if (IsContainerPartition(PartEntry
->PartInfo
[0].PartitionType
))
258 PartEntry
->FormatState
= Unformatted
;
260 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
261 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
262 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
263 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
) ||
264 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
265 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
268 if (CheckFatFormat())
270 PartEntry
->FormatState
= Preformatted
;
274 PartEntry
->FormatState
= Unformatted
;
277 PartEntry
->FormatState
= Preformatted
;
279 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
282 if (CheckNtfsFormat())
284 PartEntry
->FormatState
= Preformatted
;
286 else if (CheckHpfsFormat())
288 PartEntry
->FormatState
= Preformatted
;
292 PartEntry
->FormatState
= Unformatted
;
295 PartEntry
->FormatState
= Preformatted
;
299 PartEntry
->FormatState
= Unknown
;
302 InsertTailList (&DiskEntry
->PartListHead
,
303 &PartEntry
->ListEntry
);
309 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry
)
311 ULONGLONG LastStartingOffset
;
312 ULONGLONG LastPartitionLength
;
313 ULONGLONG LastUnusedPartitionLength
;
314 PPARTENTRY PartEntry
;
315 PPARTENTRY NewPartEntry
;
320 if (IsListEmpty (&DiskEntry
->PartListHead
))
322 /* Create a partition table that represents the empty disk */
323 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
326 if (PartEntry
== NULL
)
329 RtlZeroMemory (PartEntry
,
332 PartEntry
->Unpartitioned
= TRUE
;
333 PartEntry
->UnpartitionedOffset
= 0ULL;
334 PartEntry
->UnpartitionedLength
= DiskEntry
->DiskSize
;
336 PartEntry
->FormatState
= Unformatted
;
338 InsertTailList (&DiskEntry
->PartListHead
,
339 &PartEntry
->ListEntry
);
343 /* Start partition at head 1, cylinder 0 */
344 LastStartingOffset
= DiskEntry
->TrackSize
;
345 LastPartitionLength
= 0ULL;
346 LastUnusedPartitionLength
= 0ULL;
349 Entry
= DiskEntry
->PartListHead
.Flink
;
350 while (Entry
!= &DiskEntry
->PartListHead
)
352 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
354 for (j
= 0; j
< 4; j
++)
356 if ((!IsContainerPartition (PartEntry
->PartInfo
[j
].PartitionType
)) &&
357 (PartEntry
->PartInfo
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
358 PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
!= 0LL))
360 LastUnusedPartitionLength
=
361 PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
-
362 (LastStartingOffset
+ LastPartitionLength
);
364 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
366 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
368 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
371 if (NewPartEntry
== NULL
)
374 RtlZeroMemory (NewPartEntry
,
377 NewPartEntry
->Unpartitioned
= TRUE
;
378 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
379 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
381 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
383 NewPartEntry
->FormatState
= Unformatted
;
385 /* Insert the table into the list */
386 InsertTailList (&PartEntry
->ListEntry
,
387 &NewPartEntry
->ListEntry
);
390 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
391 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
396 Entry
= Entry
->Flink
;
399 /* Check for trailing unpartitioned disk space */
400 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
402 /* Round-down to cylinder size */
403 LastUnusedPartitionLength
=
404 ROUND_DOWN (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
),
405 DiskEntry
->CylinderSize
);
407 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
409 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
411 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
414 if (NewPartEntry
== NULL
)
417 RtlZeroMemory (NewPartEntry
,
420 NewPartEntry
->Unpartitioned
= TRUE
;
421 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
422 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
424 /* Append the table to the list */
425 InsertTailList (&DiskEntry
->PartListHead
,
426 &NewPartEntry
->ListEntry
);
434 AddDiskToList (HANDLE FileHandle
,
438 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
439 DISK_GEOMETRY DiskGeometry
;
440 SCSI_ADDRESS ScsiAddress
;
441 PDISKENTRY DiskEntry
;
442 IO_STATUS_BLOCK Iosb
;
445 Status
= NtDeviceIoControlFile (FileHandle
,
450 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
454 sizeof(DISK_GEOMETRY
));
455 if (!NT_SUCCESS (Status
))
460 if (DiskGeometry
.MediaType
!= FixedMedia
)
465 Status
= NtDeviceIoControlFile (FileHandle
,
470 IOCTL_SCSI_GET_ADDRESS
,
474 sizeof(SCSI_ADDRESS
));
475 if (!NT_SUCCESS(Status
))
480 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
483 if (DiskEntry
== NULL
)
488 InitializeListHead (&DiskEntry
->PartListHead
);
490 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
491 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
492 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
493 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
495 DPRINT ("Cylinders %d\n", DiskEntry
->Cylinders
);
496 DPRINT ("TracksPerCylinder %d\n", DiskEntry
->TracksPerCylinder
);
497 DPRINT ("SectorsPerTrack %d\n", DiskEntry
->SectorsPerTrack
);
498 DPRINT ("BytesPerSector %d\n", DiskEntry
->BytesPerSector
);
500 DiskEntry
->DiskSize
=
501 DiskGeometry
.Cylinders
.QuadPart
*
502 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
503 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
504 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
505 DiskEntry
->CylinderSize
=
506 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
507 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
508 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
509 DiskEntry
->TrackSize
=
510 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
511 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
513 DiskEntry
->DiskNumber
= DiskNumber
;
514 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
515 DiskEntry
->Bus
= ScsiAddress
.PathId
;
516 DiskEntry
->Id
= ScsiAddress
.TargetId
;
518 GetDriverName (DiskEntry
);
520 InsertTailList (&List
->DiskListHead
,
521 &DiskEntry
->ListEntry
);
523 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
526 if (LayoutBuffer
== NULL
)
531 Status
= NtDeviceIoControlFile (FileHandle
,
536 IOCTL_DISK_GET_DRIVE_LAYOUT
,
541 if (NT_SUCCESS (Status
))
543 if (LayoutBuffer
->PartitionCount
== 0)
545 DiskEntry
->NewDisk
= TRUE
;
548 AddPartitionToList (DiskNumber
,
552 ScanForUnpartitionedDiskSpace (DiskEntry
);
555 RtlFreeHeap (ProcessHeap
,
562 CreatePartitionList (SHORT Left
,
568 OBJECT_ATTRIBUTES ObjectAttributes
;
569 SYSTEM_DEVICE_INFORMATION Sdi
;
570 DISK_GEOMETRY DiskGeometry
;
571 IO_STATUS_BLOCK Iosb
;
575 WCHAR Buffer
[MAX_PATH
];
579 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
588 List
->Bottom
= Bottom
;
592 List
->TopDisk
= (ULONG
)-1;
593 List
->TopPartition
= (ULONG
)-1;
595 List
->CurrentDisk
= NULL
;
596 List
->CurrentPartition
= NULL
;
598 InitializeListHead (&List
->DiskListHead
);
600 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
602 sizeof(SYSTEM_DEVICE_INFORMATION
),
604 if (!NT_SUCCESS (Status
))
606 RtlFreeHeap (ProcessHeap
, 0, List
);
610 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
613 L
"\\Device\\Harddisk%d\\Partition0",
615 RtlInitUnicodeString (&Name
,
618 InitializeObjectAttributes (&ObjectAttributes
,
624 Status
= NtOpenFile (&FileHandle
,
629 FILE_SYNCHRONOUS_IO_NONALERT
);
630 if (NT_SUCCESS(Status
))
632 AddDiskToList (FileHandle
,
640 AssignDriverLetters (List
);
643 List
->TopPartition
= 0;
645 /* Search for first usable disk and partition */
646 if (IsListEmpty (&List
->DiskListHead
))
648 List
->CurrentDisk
= NULL
;
649 List
->CurrentPartition
= NULL
;
654 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
658 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
660 List
->CurrentPartition
= 0;
664 List
->CurrentPartition
=
665 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
676 DestroyPartitionList (PPARTLIST List
)
678 PDISKENTRY DiskEntry
;
679 PPARTENTRY PartEntry
;
682 /* Release disk and partition info */
683 while (!IsListEmpty (&List
->DiskListHead
))
685 Entry
= RemoveHeadList (&List
->DiskListHead
);
686 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
688 /* Release driver name */
689 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
691 /* Release partition array */
692 while (!IsListEmpty (&DiskEntry
->PartListHead
))
694 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
695 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
697 RtlFreeHeap (ProcessHeap
,
702 /* Release disk entry */
703 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
706 /* Release list head */
707 RtlFreeHeap (ProcessHeap
, 0, List
);
712 PrintEmptyLine (PPARTLIST List
)
719 Width
= List
->Right
- List
->Left
- 1;
720 Height
= List
->Bottom
- List
->Top
- 1;
722 if (List
->Line
< 0 || List
->Line
> Height
)
725 coPos
.X
= List
->Left
+ 1;
726 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
728 FillConsoleOutputAttribute (0x17,
733 FillConsoleOutputCharacter (' ',
743 PrintPartitionData (PPARTLIST List
,
744 PDISKENTRY DiskEntry
,
745 PPARTENTRY PartEntry
)
747 CHAR LineBuffer
[128];
758 Width
= List
->Right
- List
->Left
- 1;
759 Height
= List
->Bottom
- List
->Top
- 1;
761 if (List
->Line
< 0 || List
->Line
> Height
)
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 %-3lu %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 FillConsoleOutputCharacter (' ',
872 FillConsoleOutputAttribute (Attribute
,
879 WriteConsoleOutputCharacters (LineBuffer
,
880 min (strlen (LineBuffer
), Width
),
888 PrintDiskData (PPARTLIST List
,
889 PDISKENTRY DiskEntry
)
891 PPARTENTRY PartEntry
;
893 CHAR LineBuffer
[128];
902 Width
= List
->Right
- List
->Left
- 1;
903 Height
= List
->Bottom
- List
->Top
- 1;
905 if (List
->Line
< 0 || List
->Line
> Height
)
908 coPos
.X
= List
->Left
+ 1;
909 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
912 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
914 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
920 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
926 if (DiskEntry
->DriverName
.Length
> 0)
929 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ",
932 DiskEntry
->DiskNumber
,
936 &DiskEntry
->DriverName
);
941 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
944 DiskEntry
->DiskNumber
,
950 FillConsoleOutputAttribute (0x17,
955 FillConsoleOutputCharacter (' ',
961 WriteConsoleOutputCharacters (LineBuffer
,
962 min (strlen (LineBuffer
), Width
- 2),
967 /* Print separator line */
968 PrintEmptyLine (List
);
970 /* Print partition lines*/
971 Entry
= DiskEntry
->PartListHead
.Flink
;
972 while (Entry
!= &DiskEntry
->PartListHead
)
974 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
976 /* Print disk entry */
977 PrintPartitionData (List
,
981 Entry
= Entry
->Flink
;
984 /* Print separator line */
985 PrintEmptyLine (List
);
990 DrawPartitionList (PPARTLIST List
)
993 PDISKENTRY DiskEntry
;
994 CHAR LineBuffer
[128];
1000 /* draw upper left corner */
1001 coPos
.X
= List
->Left
;
1002 coPos
.Y
= List
->Top
;
1003 FillConsoleOutputCharacter (0xDA, // '+',
1008 /* draw upper edge */
1009 coPos
.X
= List
->Left
+ 1;
1010 coPos
.Y
= List
->Top
;
1011 FillConsoleOutputCharacter (0xC4, // '-',
1012 List
->Right
- List
->Left
- 1,
1016 /* draw upper right corner */
1017 coPos
.X
= List
->Right
;
1018 coPos
.Y
= List
->Top
;
1019 FillConsoleOutputCharacter (0xBF, // '+',
1024 /* draw left and right edge */
1025 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
1027 coPos
.X
= List
->Left
;
1029 FillConsoleOutputCharacter (0xB3, // '|',
1034 coPos
.X
= List
->Right
;
1035 FillConsoleOutputCharacter (0xB3, //'|',
1041 /* draw lower left corner */
1042 coPos
.X
= List
->Left
;
1043 coPos
.Y
= List
->Bottom
;
1044 FillConsoleOutputCharacter (0xC0, // '+',
1049 /* draw lower edge */
1050 coPos
.X
= List
->Left
+ 1;
1051 coPos
.Y
= List
->Bottom
;
1052 FillConsoleOutputCharacter (0xC4, // '-',
1053 List
->Right
- List
->Left
- 1,
1057 /* draw lower right corner */
1058 coPos
.X
= List
->Right
;
1059 coPos
.Y
= List
->Bottom
;
1060 FillConsoleOutputCharacter (0xD9, // '+',
1065 /* print list entries */
1068 Entry
= List
->DiskListHead
.Flink
;
1069 while (Entry
!= &List
->DiskListHead
)
1071 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1073 /* Print disk entry */
1074 PrintDiskData (List
,
1077 Entry
= Entry
->Flink
;
1083 ScrollDownPartitionList (PPARTLIST List
)
1085 PDISKENTRY DiskEntry
;
1086 PPARTENTRY PartEntry
;
1090 /* Check for empty disks */
1091 if (IsListEmpty (&List
->DiskListHead
))
1094 /* Check for next usable entry on current disk */
1095 if (List
->CurrentPartition
!= NULL
)
1097 Entry2
= List
->CurrentPartition
->ListEntry
.Flink
;
1098 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1100 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1102 // if (PartEntry->HidePartEntry == FALSE)
1104 List
->CurrentPartition
= PartEntry
;
1105 DrawPartitionList (List
);
1108 Entry2
= Entry2
->Flink
;
1112 /* Check for first usable entry on next disk */
1113 if (List
->CurrentDisk
!= NULL
)
1115 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1116 while (Entry1
!= &List
->DiskListHead
)
1118 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1120 Entry2
= DiskEntry
->PartListHead
.Flink
;
1121 while (Entry2
!= &DiskEntry
->PartListHead
)
1123 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1125 // if (PartEntry->HidePartEntry == FALSE)
1127 List
->CurrentDisk
= DiskEntry
;
1128 List
->CurrentPartition
= PartEntry
;
1129 DrawPartitionList (List
);
1133 Entry2
= Entry2
->Flink
;
1136 Entry1
= Entry1
->Flink
;
1143 ScrollUpPartitionList (PPARTLIST List
)
1145 PDISKENTRY DiskEntry
;
1146 PPARTENTRY PartEntry
;
1151 /* Check for empty disks */
1152 if (IsListEmpty (&List
->DiskListHead
))
1155 /* check for previous usable entry on current disk */
1156 if (List
->CurrentPartition
!= NULL
)
1158 Entry2
= List
->CurrentPartition
->ListEntry
.Blink
;
1159 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1161 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1163 // if (PartEntry->HidePartEntry == FALSE)
1165 List
->CurrentPartition
= PartEntry
;
1166 DrawPartitionList (List
);
1169 Entry2
= Entry2
->Blink
;
1174 /* check for last usable entry on previous disk */
1175 if (List
->CurrentDisk
!= NULL
)
1177 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1178 while (Entry1
!= &List
->DiskListHead
)
1180 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1182 Entry2
= DiskEntry
->PartListHead
.Blink
;
1183 while (Entry2
!= &DiskEntry
->PartListHead
)
1185 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1187 // if (PartEntry->HidePartEntry == FALSE)
1189 List
->CurrentDisk
= DiskEntry
;
1190 List
->CurrentPartition
= PartEntry
;
1191 DrawPartitionList (List
);
1195 Entry2
= Entry2
->Blink
;
1198 Entry1
= Entry1
->Blink
;
1205 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1206 PPARTENTRY CurrentEntry
)
1208 PPARTENTRY PrevEntry
;
1211 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1214 Entry
= CurrentEntry
->ListEntry
.Blink
;
1215 while (Entry
!= &DiskEntry
->PartListHead
)
1217 PrevEntry
= CONTAINING_RECORD (Entry
,
1220 if (PrevEntry
->Unpartitioned
== FALSE
)
1223 Entry
= Entry
->Blink
;
1231 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1232 PPARTENTRY CurrentEntry
)
1234 PPARTENTRY NextEntry
;
1237 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1240 Entry
= CurrentEntry
->ListEntry
.Flink
;
1241 while (Entry
!= &DiskEntry
->PartListHead
)
1243 NextEntry
= CONTAINING_RECORD (Entry
,
1246 if (NextEntry
->Unpartitioned
== FALSE
)
1249 Entry
= Entry
->Flink
;
1257 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1258 PPARTENTRY PartEntry
)
1260 PPARTENTRY PrevPartEntry
;
1262 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1264 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1267 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1268 return PrevPartEntry
;
1276 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1277 PPARTENTRY PartEntry
)
1279 PPARTENTRY NextPartEntry
;
1281 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1283 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1286 if (NextPartEntry
->Unpartitioned
== TRUE
)
1287 return NextPartEntry
;
1295 CreateNewPartition (PPARTLIST List
,
1296 ULONGLONG PartitionSize
,
1299 PDISKENTRY DiskEntry
;
1300 PPARTENTRY PartEntry
;
1301 PPARTENTRY PrevPartEntry
;
1302 PPARTENTRY NextPartEntry
;
1303 PPARTENTRY NewPartEntry
;
1306 List
->CurrentDisk
== NULL
||
1307 List
->CurrentPartition
== NULL
||
1308 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1313 DiskEntry
= List
->CurrentDisk
;
1314 PartEntry
= List
->CurrentPartition
;
1316 if (AutoCreate
== TRUE
||
1317 PartitionSize
== PartEntry
->UnpartitionedLength
)
1319 /* Convert current entry to 'new (unformatted)' */
1320 PartEntry
->FormatState
= Unformatted
;
1321 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1322 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1323 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1324 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1325 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1326 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1327 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1328 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1329 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1330 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1332 /* Get previous and next partition entries */
1333 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1335 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1338 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1340 /* Current entry is in the middle of the list */
1342 /* Copy previous container partition data to current entry */
1343 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1344 &PrevPartEntry
->PartInfo
[1],
1345 sizeof(PARTITION_INFORMATION
));
1346 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1348 /* Update previous container partition data */
1350 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1351 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1353 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1355 /* Special case - previous partition is first partition */
1356 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1357 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1361 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1362 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1365 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1367 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1369 /* Current entry is the first entry */
1372 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1374 /* Current entry is the last entry */
1376 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1377 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1379 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1381 /* Special case - previous partition is first partition */
1382 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1383 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1387 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1388 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1391 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
1392 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
1393 (1024ULL * 255ULL * 63ULL * 512ULL))
1395 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
1399 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
1402 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1403 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1406 PartEntry
->AutoCreate
= AutoCreate
;
1407 PartEntry
->New
= TRUE
;
1408 PartEntry
->Unpartitioned
= FALSE
;
1409 PartEntry
->UnpartitionedOffset
= 0ULL;
1410 PartEntry
->UnpartitionedLength
= 0ULL;
1414 /* Insert an initialize a new partition entry */
1415 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
1418 if (NewPartEntry
== NULL
)
1421 RtlZeroMemory (NewPartEntry
,
1424 /* Insert the new entry into the list */
1425 InsertTailList (&PartEntry
->ListEntry
,
1426 &NewPartEntry
->ListEntry
);
1428 NewPartEntry
->New
= TRUE
;
1430 NewPartEntry
->FormatState
= Unformatted
;
1431 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1432 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1433 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1434 PartitionSize
- DiskEntry
->TrackSize
;
1435 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1436 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1437 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1438 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1439 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1440 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1442 /* Get previous and next partition entries */
1443 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1445 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1448 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1450 /* Current entry is in the middle of the list */
1452 /* Copy previous container partition data to current entry */
1453 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
1454 &PrevPartEntry
->PartInfo
[1],
1455 sizeof(PARTITION_INFORMATION
));
1456 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1458 /* Update previous container partition data */
1460 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1461 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1463 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1465 /* Special case - previous partition is first partition */
1466 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1467 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1471 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1472 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1475 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1477 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1479 /* Current entry is the first entry */
1482 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1484 /* Current entry is the last entry */
1486 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1487 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1489 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1491 /* Special case - previous partition is first partition */
1492 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1493 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1497 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1498 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1501 if ((PartEntry
->PartInfo
[1].StartingOffset
.QuadPart
+
1502 PartEntry
->PartInfo
[1].PartitionLength
.QuadPart
) <
1503 (1024ULL * 255ULL * 63ULL * 512ULL))
1505 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_EXTENDED
;
1509 PrevPartEntry
->PartInfo
[1].PartitionType
= PARTITION_XINT13_EXTENDED
;
1512 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1513 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1516 /* Update offset and size of the remaining unpartitioned disk space */
1517 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
1518 PartEntry
->UnpartitionedLength
-= PartitionSize
;
1521 DiskEntry
->Modified
= TRUE
;
1523 UpdatePartitionNumbers (DiskEntry
);
1525 AssignDriverLetters (List
);
1530 DeleteCurrentPartition (PPARTLIST List
)
1532 PDISKENTRY DiskEntry
;
1533 PPARTENTRY PartEntry
;
1534 PPARTENTRY PrevPartEntry
;
1535 PPARTENTRY NextPartEntry
;
1538 List
->CurrentDisk
== NULL
||
1539 List
->CurrentPartition
== NULL
||
1540 List
->CurrentPartition
->Unpartitioned
== TRUE
)
1545 DiskEntry
= List
->CurrentDisk
;
1546 PartEntry
= List
->CurrentPartition
;
1548 /* Adjust container partition entries */
1550 /* Get previous and next partition entries */
1551 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1553 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1556 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1558 /* Current entry is in the middle of the list */
1561 * The first extended partition can not be deleted
1562 * as long as other extended partitions are present.
1564 if (PrevPartEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1567 /* Copy previous container partition data to current entry */
1568 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
1569 &PartEntry
->PartInfo
[1],
1570 sizeof(PARTITION_INFORMATION
));
1571 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1573 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1576 * A primary partition can not be deleted as long as
1577 * extended partitions are present.
1581 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1583 /* Current entry is the last entry */
1584 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
1585 sizeof(PARTITION_INFORMATION
));
1586 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1590 /* Adjust unpartitioned disk space entries */
1592 /* Get pointer to previous and next unpartitioned entries */
1593 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
1596 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
1599 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1601 /* Merge previous, current and next unpartitioned entry */
1603 /* Adjust the previous entries length */
1604 PrevPartEntry
->UnpartitionedLength
+=
1605 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
1606 NextPartEntry
->UnpartitionedLength
);
1608 /* Remove the current entry */
1609 RemoveEntryList (&PartEntry
->ListEntry
);
1610 RtlFreeHeap (ProcessHeap
,
1614 /* Remove the next entry */
1615 RemoveEntryList (&NextPartEntry
->ListEntry
);
1616 RtlFreeHeap (ProcessHeap
,
1620 /* Update current partition */
1621 List
->CurrentPartition
= PrevPartEntry
;
1623 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1625 /* Merge current and previous unpartitioned entry */
1627 /* Adjust the previous entries length */
1628 PrevPartEntry
->UnpartitionedLength
+=
1629 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
1631 /* Remove the current entry */
1632 RemoveEntryList (&PartEntry
->ListEntry
);
1633 RtlFreeHeap (ProcessHeap
,
1637 /* Update current partition */
1638 List
->CurrentPartition
= PrevPartEntry
;
1640 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1642 /* Merge current and next unpartitioned entry */
1644 /* Adjust the next entries offset and length */
1645 NextPartEntry
->UnpartitionedOffset
=
1646 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1647 NextPartEntry
->UnpartitionedLength
+=
1648 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
1650 /* Remove the current entry */
1651 RemoveEntryList (&PartEntry
->ListEntry
);
1652 RtlFreeHeap (ProcessHeap
,
1656 /* Update current partition */
1657 List
->CurrentPartition
= NextPartEntry
;
1661 /* Nothing to merge but change current entry */
1662 PartEntry
->New
= FALSE
;
1663 PartEntry
->Unpartitioned
= TRUE
;
1664 PartEntry
->UnpartitionedOffset
=
1665 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1666 PartEntry
->UnpartitionedLength
=
1667 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1669 /* Wipe the partition table */
1670 RtlZeroMemory (&PartEntry
->PartInfo
,
1671 sizeof(PartEntry
->PartInfo
));
1674 DiskEntry
->Modified
= TRUE
;
1676 UpdatePartitionNumbers (DiskEntry
);
1678 AssignDriverLetters (List
);
1683 CheckActiveBootPartition (PPARTLIST List
)
1685 PDISKENTRY DiskEntry
;
1686 PPARTENTRY PartEntry
;
1688 /* Check for empty disk list */
1689 if (IsListEmpty (&List
->DiskListHead
))
1691 List
->ActiveBootDisk
= NULL
;
1692 List
->ActiveBootPartition
= NULL
;
1697 if (List
->ActiveBootDisk
!= NULL
&&
1698 List
->ActiveBootPartition
!= NULL
)
1700 /* We already have an active boot partition */
1705 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
1709 /* Check for empty partition list */
1710 if (IsListEmpty (&DiskEntry
->PartListHead
))
1712 List
->ActiveBootDisk
= NULL
;
1713 List
->ActiveBootPartition
= NULL
;
1717 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
1721 /* Set active boot partition */
1722 if ((DiskEntry
->NewDisk
== TRUE
) ||
1723 (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
1724 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
1725 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
1726 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
))
1728 PartEntry
->PartInfo
[0].BootIndicator
= TRUE
;
1729 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1730 DiskEntry
->Modified
= TRUE
;
1733 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
1734 List
->ActiveBootDisk
= DiskEntry
;
1735 List
->ActiveBootPartition
= PartEntry
;
1740 CheckForLinuxFdiskPartitions (PPARTLIST List
)
1742 PDISKENTRY DiskEntry
;
1743 PPARTENTRY PartEntry
;
1746 ULONG PartitionCount
;
1749 Entry1
= List
->DiskListHead
.Flink
;
1750 while (Entry1
!= &List
->DiskListHead
)
1752 DiskEntry
= CONTAINING_RECORD (Entry1
,
1756 Entry2
= DiskEntry
->PartListHead
.Flink
;
1757 while (Entry2
!= &DiskEntry
->PartListHead
)
1759 PartEntry
= CONTAINING_RECORD (Entry2
,
1763 if (PartEntry
->Unpartitioned
== FALSE
)
1767 for (i
= 0; i
< 4; i
++)
1769 if (!IsContainerPartition (PartEntry
->PartInfo
[i
].PartitionType
) &&
1770 PartEntry
->PartInfo
[i
].PartitionLength
.QuadPart
!= 0ULL)
1776 if (PartitionCount
> 1)
1782 Entry2
= Entry2
->Flink
;
1785 Entry1
= Entry1
->Flink
;
1793 WritePartitionsToDisk (PPARTLIST List
)
1795 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
1796 OBJECT_ATTRIBUTES ObjectAttributes
;
1797 IO_STATUS_BLOCK Iosb
;
1798 WCHAR SrcPath
[MAX_PATH
];
1799 WCHAR DstPath
[MAX_PATH
];
1800 UNICODE_STRING Name
;
1802 PDISKENTRY DiskEntry
;
1803 PPARTENTRY PartEntry
;
1806 ULONG PartitionCount
;
1807 ULONG DriveLayoutSize
;
1816 Entry1
= List
->DiskListHead
.Flink
;
1817 while (Entry1
!= &List
->DiskListHead
)
1819 DiskEntry
= CONTAINING_RECORD (Entry1
,
1823 if (DiskEntry
->Modified
== TRUE
)
1825 /* Count partitioned entries */
1827 Entry2
= DiskEntry
->PartListHead
.Flink
;
1828 while (Entry2
!= &DiskEntry
->PartListHead
)
1830 PartEntry
= CONTAINING_RECORD (Entry2
,
1833 if (PartEntry
->Unpartitioned
== FALSE
)
1835 PartitionCount
+= 4;
1838 Entry2
= Entry2
->Flink
;
1841 if (PartitionCount
> 0)
1843 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
1844 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
1845 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
1848 if (DriveLayout
== NULL
)
1850 DPRINT1 ("RtlAllocateHeap() failed\n");
1854 RtlZeroMemory (DriveLayout
,
1857 DriveLayout
->PartitionCount
= PartitionCount
;
1860 Entry2
= DiskEntry
->PartListHead
.Flink
;
1861 while (Entry2
!= &DiskEntry
->PartListHead
)
1863 PartEntry
= CONTAINING_RECORD (Entry2
,
1866 if (PartEntry
->Unpartitioned
== FALSE
)
1868 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
1869 &PartEntry
->PartInfo
[0],
1870 4 * sizeof (PARTITION_INFORMATION
));
1874 Entry2
= Entry2
->Flink
;
1878 L
"\\Device\\Harddisk%d\\Partition0",
1879 DiskEntry
->DiskNumber
);
1880 RtlInitUnicodeString (&Name
,
1882 InitializeObjectAttributes (&ObjectAttributes
,
1888 Status
= NtOpenFile (&FileHandle
,
1893 FILE_SYNCHRONOUS_IO_NONALERT
);
1894 if (!NT_SUCCESS (Status
))
1896 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
1900 Status
= NtDeviceIoControlFile (FileHandle
,
1905 IOCTL_DISK_SET_DRIVE_LAYOUT
,
1910 if (!NT_SUCCESS (Status
))
1912 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
1913 NtClose (FileHandle
);
1917 RtlFreeHeap (ProcessHeap
,
1921 NtClose (FileHandle
);
1923 /* Install MBR code if the disk is new */
1924 if (DiskEntry
->NewDisk
== TRUE
)
1926 wcscpy (SrcPath
, SourceRootPath
.Buffer
);
1927 wcscat (SrcPath
, L
"\\loader\\dosmbr.bin");
1929 DPRINT1 ("Install MBR bootcode: %S ==> %S\n",
1932 /* Install MBR bootcode */
1933 Status
= InstallMbrBootCodeToDisk (SrcPath
,
1935 if (!NT_SUCCESS (Status
))
1937 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
1942 DiskEntry
->NewDisk
= FALSE
;
1947 Entry1
= Entry1
->Flink
;