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.18 2003/08/18 17:39:26 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 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
226 if (PartEntry
== NULL
)
231 RtlZeroMemory (PartEntry
,
234 PartEntry
->Unpartitioned
= FALSE
;
236 for (j
= 0; j
< 4; j
++)
238 RtlCopyMemory (&PartEntry
->PartInfo
[j
],
239 &LayoutBuffer
->PartitionEntry
[i
+j
],
240 sizeof(PARTITION_INFORMATION
));
243 InsertTailList (&DiskEntry
->PartListHead
,
244 &PartEntry
->ListEntry
);
250 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry
)
252 ULONGLONG LastStartingOffset
;
253 ULONGLONG LastPartitionLength
;
254 ULONGLONG LastUnusedPartitionLength
;
255 PPARTENTRY PartEntry
;
256 PPARTENTRY NewPartEntry
;
261 if (IsListEmpty (&DiskEntry
->PartListHead
))
263 /* Create a partition table that represents the empty disk */
264 PartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
267 if (PartEntry
== NULL
)
270 RtlZeroMemory (PartEntry
,
273 PartEntry
->Unpartitioned
= TRUE
;
274 PartEntry
->UnpartitionedOffset
= 0ULL;
275 PartEntry
->UnpartitionedLength
= DiskEntry
->DiskSize
;
277 InsertTailList (&DiskEntry
->PartListHead
,
278 &PartEntry
->ListEntry
);
282 /* Start partition at head 1, cylinder 0 */
283 LastStartingOffset
= DiskEntry
->TrackSize
;
284 LastPartitionLength
= 0ULL;
285 LastUnusedPartitionLength
= 0ULL;
288 Entry
= DiskEntry
->PartListHead
.Flink
;
289 while (Entry
!= &DiskEntry
->PartListHead
)
291 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
293 for (j
= 0; j
< 4; j
++)
295 if ((!IsContainerPartition (PartEntry
->PartInfo
[j
].PartitionType
)) &&
296 (PartEntry
->PartInfo
[j
].PartitionType
!= PARTITION_ENTRY_UNUSED
||
297 PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
!= 0LL))
299 LastUnusedPartitionLength
=
300 PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
-
301 (LastStartingOffset
+ LastPartitionLength
);
303 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
305 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
307 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
310 if (NewPartEntry
== NULL
)
313 RtlZeroMemory (NewPartEntry
,
316 NewPartEntry
->Unpartitioned
= TRUE
;
317 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
318 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
320 NewPartEntry
->UnpartitionedLength
-= DiskEntry
->TrackSize
;
322 /* Insert the table into the list */
323 InsertTailList (&PartEntry
->ListEntry
,
324 &NewPartEntry
->ListEntry
);
327 LastStartingOffset
= PartEntry
->PartInfo
[j
].StartingOffset
.QuadPart
;
328 LastPartitionLength
= PartEntry
->PartInfo
[j
].PartitionLength
.QuadPart
;
333 Entry
= Entry
->Flink
;
336 /* Check for trailing unpartitioned disk space */
337 if (DiskEntry
->DiskSize
> (LastStartingOffset
+ LastPartitionLength
))
339 /* Round-down to cylinder size */
340 LastUnusedPartitionLength
=
341 ROUND_DOWN (DiskEntry
->DiskSize
- (LastStartingOffset
+ LastPartitionLength
),
342 DiskEntry
->CylinderSize
);
344 if (LastUnusedPartitionLength
>= DiskEntry
->CylinderSize
)
346 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength
);
348 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
351 if (NewPartEntry
== NULL
)
354 RtlZeroMemory (NewPartEntry
,
357 NewPartEntry
->Unpartitioned
= TRUE
;
358 NewPartEntry
->UnpartitionedOffset
= LastStartingOffset
+ LastPartitionLength
;
359 NewPartEntry
->UnpartitionedLength
= LastUnusedPartitionLength
;
361 /* Append the table to the list */
362 InsertTailList (&DiskEntry
->PartListHead
,
363 &NewPartEntry
->ListEntry
);
371 AddDiskToList (HANDLE FileHandle
,
375 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
376 DISK_GEOMETRY DiskGeometry
;
377 SCSI_ADDRESS ScsiAddress
;
378 PDISKENTRY DiskEntry
;
379 IO_STATUS_BLOCK Iosb
;
382 Status
= NtDeviceIoControlFile (FileHandle
,
387 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
391 sizeof(DISK_GEOMETRY
));
392 if (!NT_SUCCESS (Status
))
397 if (DiskGeometry
.MediaType
!= FixedMedia
)
402 Status
= NtDeviceIoControlFile (FileHandle
,
407 IOCTL_SCSI_GET_ADDRESS
,
411 sizeof(SCSI_ADDRESS
));
412 if (!NT_SUCCESS(Status
))
417 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
420 if (DiskEntry
== NULL
)
425 InitializeListHead (&DiskEntry
->PartListHead
);
427 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
428 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
429 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
430 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
432 DPRINT ("Cylinders %d\n", DiskEntry
->Cylinders
);
433 DPRINT ("TracksPerCylinder %d\n", DiskEntry
->TracksPerCylinder
);
434 DPRINT ("SectorsPerTrack %d\n", DiskEntry
->SectorsPerTrack
);
435 DPRINT ("BytesPerSector %d\n", DiskEntry
->BytesPerSector
);
437 DiskEntry
->DiskSize
=
438 DiskGeometry
.Cylinders
.QuadPart
*
439 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
440 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
441 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
442 DiskEntry
->CylinderSize
=
443 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
444 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
445 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
446 DiskEntry
->TrackSize
=
447 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
448 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
450 DiskEntry
->DiskNumber
= DiskNumber
;
451 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
452 DiskEntry
->Bus
= ScsiAddress
.PathId
;
453 DiskEntry
->Id
= ScsiAddress
.TargetId
;
455 DiskEntry
->UseLba
= (DiskEntry
->DiskSize
> (1024ULL * 255ULL * 63ULL * 512ULL));
457 GetDriverName (DiskEntry
);
459 InsertTailList (&List
->DiskListHead
,
460 &DiskEntry
->ListEntry
);
462 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
465 if (LayoutBuffer
== NULL
)
470 Status
= NtDeviceIoControlFile (FileHandle
,
475 IOCTL_DISK_GET_DRIVE_LAYOUT
,
480 if (NT_SUCCESS (Status
))
482 AddPartitionToList (DiskNumber
,
486 ScanForUnpartitionedDiskSpace (DiskEntry
);
489 RtlFreeHeap (ProcessHeap
,
496 CreatePartitionList (SHORT Left
,
502 OBJECT_ATTRIBUTES ObjectAttributes
;
503 SYSTEM_DEVICE_INFORMATION Sdi
;
504 DISK_GEOMETRY DiskGeometry
;
505 IO_STATUS_BLOCK Iosb
;
509 WCHAR Buffer
[MAX_PATH
];
513 List
= (PPARTLIST
)RtlAllocateHeap (ProcessHeap
,
522 List
->Bottom
= Bottom
;
526 List
->TopDisk
= (ULONG
)-1;
527 List
->TopPartition
= (ULONG
)-1;
529 List
->CurrentDisk
= NULL
;
530 List
->CurrentPartition
= NULL
;
532 InitializeListHead (&List
->DiskListHead
);
534 Status
= NtQuerySystemInformation (SystemDeviceInformation
,
536 sizeof(SYSTEM_DEVICE_INFORMATION
),
538 if (!NT_SUCCESS (Status
))
540 RtlFreeHeap (ProcessHeap
, 0, List
);
544 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
547 L
"\\Device\\Harddisk%d\\Partition0",
549 RtlInitUnicodeString (&Name
,
552 InitializeObjectAttributes (&ObjectAttributes
,
558 Status
= NtOpenFile (&FileHandle
,
563 FILE_SYNCHRONOUS_IO_NONALERT
);
564 if (NT_SUCCESS(Status
))
566 AddDiskToList (FileHandle
,
574 AssignDriverLetters (List
);
577 List
->TopPartition
= 0;
579 /* Search for first usable disk and partition */
580 if (IsListEmpty (&List
->DiskListHead
))
582 List
->CurrentDisk
= NULL
;
583 List
->CurrentPartition
= NULL
;
588 CONTAINING_RECORD (List
->DiskListHead
.Flink
,
592 if (IsListEmpty (&List
->CurrentDisk
->PartListHead
))
594 List
->CurrentPartition
= 0;
598 List
->CurrentPartition
=
599 CONTAINING_RECORD (List
->CurrentDisk
->PartListHead
.Flink
,
610 DestroyPartitionList (PPARTLIST List
)
612 PDISKENTRY DiskEntry
;
613 PPARTENTRY PartEntry
;
616 /* Release disk and partition info */
617 while (!IsListEmpty (&List
->DiskListHead
))
619 Entry
= RemoveHeadList (&List
->DiskListHead
);
620 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
622 /* Release driver name */
623 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
625 /* Release partition array */
626 while (!IsListEmpty (&DiskEntry
->PartListHead
))
628 Entry
= RemoveHeadList (&DiskEntry
->PartListHead
);
629 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
631 RtlFreeHeap (ProcessHeap
,
636 /* Release disk entry */
637 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
640 /* Release list head */
641 RtlFreeHeap (ProcessHeap
, 0, List
);
646 PrintEmptyLine (PPARTLIST List
)
653 Width
= List
->Right
- List
->Left
- 1;
654 Height
= List
->Bottom
- List
->Top
- 1;
656 if (List
->Line
< 0 || List
->Line
> Height
)
659 coPos
.X
= List
->Left
+ 1;
660 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
662 FillConsoleOutputAttribute (0x17,
667 FillConsoleOutputCharacter (' ',
677 PrintPartitionData (PPARTLIST List
,
678 PDISKENTRY DiskEntry
,
679 PPARTENTRY PartEntry
)
681 CHAR LineBuffer
[128];
692 Width
= List
->Right
- List
->Left
- 1;
693 Height
= List
->Bottom
- List
->Top
- 1;
695 if (List
->Line
< 0 || List
->Line
> Height
)
698 coPos
.X
= List
->Left
+ 1;
699 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
701 if (PartEntry
->Unpartitioned
== TRUE
)
704 if (PartEntry
->UnpartitionledLength
>= 0x280000000ULL
) /* 10 GB */
706 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 29)) >> 30;
711 if (PartEntry
->UnpartitionedLength
>= 0xA00000ULL
) /* 10 MB */
713 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 19)) >> 20;
718 PartSize
= (PartEntry
->UnpartitionedLength
+ (1 << 9)) >> 10;
723 " Unpartitioned space %6I64u %s",
729 /* Determine partition type */
731 if (PartEntry
->New
== TRUE
)
733 PartType
= "New (Unformatted)";
735 else if (PartEntry
->Unpartitioned
== FALSE
)
737 if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_12
) ||
738 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT_16
) ||
739 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_HUGE
) ||
740 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_XINT13
))
744 else if ((PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32
) ||
745 (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_FAT32_XINT13
))
749 else if (PartEntry
->PartInfo
[0].PartitionType
== PARTITION_IFS
)
751 PartType
= "NTFS"; /* FIXME: Not quite correct! */
756 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0x280000000ULL
) /* 10 GB */
758 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 29)) >> 30;
763 if (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
>= 0xA00000ULL
) /* 10 MB */
765 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 19)) >> 20;
770 PartSize
= (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ (1 << 9)) >> 10;
774 if (PartType
== NULL
)
777 "%c%c Type %-3lu %6I64u %s",
778 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
779 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
780 PartEntry
->PartInfo
[0].PartitionType
,
787 "%c%c %-24s %6I64u %s",
788 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
789 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
796 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
797 List
->CurrentPartition
== PartEntry
) ? 0x71 : 0x17;
799 FillConsoleOutputCharacter (' ',
806 FillConsoleOutputAttribute (Attribute
,
813 WriteConsoleOutputCharacters (LineBuffer
,
814 min (strlen (LineBuffer
), Width
),
822 PrintDiskData (PPARTLIST List
,
823 PDISKENTRY DiskEntry
)
825 PPARTENTRY PartEntry
;
827 CHAR LineBuffer
[128];
836 Width
= List
->Right
- List
->Left
- 1;
837 Height
= List
->Bottom
- List
->Top
- 1;
839 if (List
->Line
< 0 || List
->Line
> Height
)
842 coPos
.X
= List
->Left
+ 1;
843 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
846 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
848 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
854 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
860 if (DiskEntry
->DriverName
.Length
> 0)
863 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ",
866 DiskEntry
->DiskNumber
,
870 &DiskEntry
->DriverName
);
875 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
878 DiskEntry
->DiskNumber
,
884 FillConsoleOutputAttribute (0x17,
889 FillConsoleOutputCharacter (' ',
895 WriteConsoleOutputCharacters (LineBuffer
,
896 min (strlen (LineBuffer
), Width
- 2),
901 /* Print separator line */
902 PrintEmptyLine (List
);
904 /* Print partition lines*/
905 Entry
= DiskEntry
->PartListHead
.Flink
;
906 while (Entry
!= &DiskEntry
->PartListHead
)
908 PartEntry
= CONTAINING_RECORD (Entry
, PARTENTRY
, ListEntry
);
910 /* Print disk entry */
911 PrintPartitionData (List
,
915 Entry
= Entry
->Flink
;
918 /* Print separator line */
919 PrintEmptyLine (List
);
924 DrawPartitionList (PPARTLIST List
)
927 PDISKENTRY DiskEntry
;
928 CHAR LineBuffer
[128];
934 /* draw upper left corner */
935 coPos
.X
= List
->Left
;
937 FillConsoleOutputCharacter (0xDA, // '+',
942 /* draw upper edge */
943 coPos
.X
= List
->Left
+ 1;
945 FillConsoleOutputCharacter (0xC4, // '-',
946 List
->Right
- List
->Left
- 1,
950 /* draw upper right corner */
951 coPos
.X
= List
->Right
;
953 FillConsoleOutputCharacter (0xBF, // '+',
958 /* draw left and right edge */
959 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
961 coPos
.X
= List
->Left
;
963 FillConsoleOutputCharacter (0xB3, // '|',
968 coPos
.X
= List
->Right
;
969 FillConsoleOutputCharacter (0xB3, //'|',
975 /* draw lower left corner */
976 coPos
.X
= List
->Left
;
977 coPos
.Y
= List
->Bottom
;
978 FillConsoleOutputCharacter (0xC0, // '+',
983 /* draw lower edge */
984 coPos
.X
= List
->Left
+ 1;
985 coPos
.Y
= List
->Bottom
;
986 FillConsoleOutputCharacter (0xC4, // '-',
987 List
->Right
- List
->Left
- 1,
991 /* draw lower right corner */
992 coPos
.X
= List
->Right
;
993 coPos
.Y
= List
->Bottom
;
994 FillConsoleOutputCharacter (0xD9, // '+',
999 /* print list entries */
1002 Entry
= List
->DiskListHead
.Flink
;
1003 while (Entry
!= &List
->DiskListHead
)
1005 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
1007 /* Print disk entry */
1008 PrintDiskData (List
,
1011 Entry
= Entry
->Flink
;
1017 ScrollDownPartitionList (PPARTLIST List
)
1019 PDISKENTRY DiskEntry
;
1020 PPARTENTRY PartEntry
;
1024 /* Check for empty disks */
1025 if (IsListEmpty (&List
->DiskListHead
))
1028 /* Check for next usable entry on current disk */
1029 if (List
->CurrentPartition
!= NULL
)
1031 Entry2
= List
->CurrentPartition
->ListEntry
.Flink
;
1032 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1034 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1036 // if (PartEntry->HidePartEntry == FALSE)
1038 List
->CurrentPartition
= PartEntry
;
1039 DrawPartitionList (List
);
1042 Entry2
= Entry2
->Flink
;
1046 /* Check for first usable entry on next disk */
1047 if (List
->CurrentDisk
!= NULL
)
1049 Entry1
= List
->CurrentDisk
->ListEntry
.Flink
;
1050 while (Entry1
!= &List
->DiskListHead
)
1052 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1054 Entry2
= DiskEntry
->PartListHead
.Flink
;
1055 while (Entry2
!= &DiskEntry
->PartListHead
)
1057 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1059 // if (PartEntry->HidePartEntry == FALSE)
1061 List
->CurrentDisk
= DiskEntry
;
1062 List
->CurrentPartition
= PartEntry
;
1063 DrawPartitionList (List
);
1067 Entry2
= Entry2
->Flink
;
1070 Entry1
= Entry1
->Flink
;
1077 ScrollUpPartitionList (PPARTLIST List
)
1079 PDISKENTRY DiskEntry
;
1080 PPARTENTRY PartEntry
;
1085 /* Check for empty disks */
1086 if (IsListEmpty (&List
->DiskListHead
))
1089 /* check for previous usable entry on current disk */
1090 if (List
->CurrentPartition
!= NULL
)
1092 Entry2
= List
->CurrentPartition
->ListEntry
.Blink
;
1093 while (Entry2
!= &List
->CurrentDisk
->PartListHead
)
1095 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1097 // if (PartEntry->HidePartEntry == FALSE)
1099 List
->CurrentPartition
= PartEntry
;
1100 DrawPartitionList (List
);
1103 Entry2
= Entry2
->Blink
;
1108 /* check for last usable entry on previous disk */
1109 if (List
->CurrentDisk
!= NULL
)
1111 Entry1
= List
->CurrentDisk
->ListEntry
.Blink
;
1112 while (Entry1
!= &List
->DiskListHead
)
1114 DiskEntry
= CONTAINING_RECORD (Entry1
, DISKENTRY
, ListEntry
);
1116 Entry2
= DiskEntry
->PartListHead
.Blink
;
1117 while (Entry2
!= &DiskEntry
->PartListHead
)
1119 PartEntry
= CONTAINING_RECORD (Entry2
, PARTENTRY
, ListEntry
);
1121 // if (PartEntry->HidePartEntry == FALSE)
1123 List
->CurrentDisk
= DiskEntry
;
1124 List
->CurrentPartition
= PartEntry
;
1125 DrawPartitionList (List
);
1129 Entry2
= Entry2
->Blink
;
1132 Entry1
= Entry1
->Blink
;
1139 SetActiveBootPartition (PPARTLIST List
)
1141 PDISKENTRY DiskEntry
;
1142 PPARTENTRY PartEntry
;
1144 /* Check for empty disk list */
1145 if (IsListEmpty (&List
->DiskListHead
))
1147 List
->ActiveBootDisk
= NULL
;
1148 List
->ActiveBootPartition
= NULL
;
1152 DiskEntry
= CONTAINING_RECORD (List
->DiskListHead
.Flink
,
1156 /* Check for empty partition list */
1157 if (IsListEmpty (&DiskEntry
->PartListHead
))
1159 List
->ActiveBootDisk
= NULL
;
1160 List
->ActiveBootPartition
= NULL
;
1164 PartEntry
= CONTAINING_RECORD (DiskEntry
->PartListHead
.Flink
,
1168 /* Set active boot partition 1 */
1169 if (PartEntry
->PartInfo
[0].BootIndicator
== FALSE
&&
1170 PartEntry
->PartInfo
[1].BootIndicator
== FALSE
&&
1171 PartEntry
->PartInfo
[2].BootIndicator
== FALSE
&&
1172 PartEntry
->PartInfo
[3].BootIndicator
== FALSE
)
1174 PartEntry
->PartInfo
[0].BootIndicator
== TRUE
;
1175 PartEntry
->PartInfo
[0].RewritePartition
== TRUE
;
1176 DiskEntry
->Modified
= TRUE
;
1179 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
1180 List
->ActiveBootDisk
= DiskEntry
;
1181 List
->ActiveBootPartition
= PartEntry
;
1186 GetPrevPartitionedEntry (PDISKENTRY DiskEntry
,
1187 PPARTENTRY CurrentEntry
)
1189 PPARTENTRY PrevEntry
;
1192 if (CurrentEntry
->ListEntry
.Blink
== &DiskEntry
->PartListHead
)
1195 Entry
= CurrentEntry
->ListEntry
.Blink
;
1196 while (Entry
!= &DiskEntry
->PartListHead
)
1198 PrevEntry
= CONTAINING_RECORD (Entry
,
1201 if (PrevEntry
->Unpartitioned
== FALSE
)
1204 Entry
= Entry
->Blink
;
1212 GetNextPartitionedEntry (PDISKENTRY DiskEntry
,
1213 PPARTENTRY CurrentEntry
)
1215 PPARTENTRY NextEntry
;
1218 if (CurrentEntry
->ListEntry
.Flink
== &DiskEntry
->PartListHead
)
1221 Entry
= CurrentEntry
->ListEntry
.Flink
;
1222 while (Entry
!= &DiskEntry
->PartListHead
)
1224 NextEntry
= CONTAINING_RECORD (Entry
,
1227 if (NextEntry
->Unpartitioned
== FALSE
)
1230 Entry
= Entry
->Flink
;
1238 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry
,
1239 PPARTENTRY PartEntry
)
1241 PPARTENTRY PrevPartEntry
;
1243 if (PartEntry
->ListEntry
.Blink
!= &DiskEntry
->PartListHead
)
1245 PrevPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Blink
,
1248 if (PrevPartEntry
->Unpartitioned
== TRUE
)
1249 return PrevPartEntry
;
1257 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry
,
1258 PPARTENTRY PartEntry
)
1260 PPARTENTRY NextPartEntry
;
1262 if (PartEntry
->ListEntry
.Flink
!= &DiskEntry
->PartListHead
)
1264 NextPartEntry
= CONTAINING_RECORD (PartEntry
->ListEntry
.Flink
,
1267 if (NextPartEntry
->Unpartitioned
== TRUE
)
1268 return NextPartEntry
;
1276 CreateNewPartition (PPARTLIST List
,
1277 ULONGLONG PartitionSize
,
1280 PDISKENTRY DiskEntry
;
1281 PPARTENTRY PartEntry
;
1282 PPARTENTRY PrevPartEntry
;
1283 PPARTENTRY NextPartEntry
;
1284 PPARTENTRY NewPartEntry
;
1287 List
->CurrentDisk
== NULL
||
1288 List
->CurrentPartition
== NULL
||
1289 List
->CurrentPartition
->Unpartitioned
== FALSE
)
1294 DiskEntry
= List
->CurrentDisk
;
1295 PartEntry
= List
->CurrentPartition
;
1297 if (AutoCreate
== TRUE
||
1298 PartitionSize
== PartEntry
->UnpartitionedLength
)
1300 /* Convert current entry to 'new (unformatted)' */
1301 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1302 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1303 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1304 PartEntry
->UnpartitionedLength
- DiskEntry
->TrackSize
;
1305 PartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1306 PartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1307 PartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1308 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1309 PartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1310 PartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1312 /* Get previous and next partition entries */
1313 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1315 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1318 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1320 /* Current entry is in the middle of the list */
1322 /* Copy previous container partition data to current entry */
1323 RtlCopyMemory (&PartEntry
->PartInfo
[1],
1324 &PrevPartEntry
->PartInfo
[1],
1325 sizeof(PARTITION_INFORMATION
));
1326 PartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1328 /* Update previous container partition data */
1330 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1331 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1333 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1335 /* Special case - previous partition is first partition */
1336 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1337 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1341 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1342 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1345 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1347 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1349 /* Current entry is the first entry */
1351 /* FIXME: Update extended partition entries */
1353 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1355 /* Current entry is the last entry */
1357 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1358 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1360 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1362 /* Special case - previous partition is first partition */
1363 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1364 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1368 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1369 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1372 PrevPartEntry
->PartInfo
[1].PartitionType
=
1373 (DiskEntry
->UseLba
== TRUE
) ? PARTITION_XINT13_EXTENDED
: PARTITION_EXTENDED
;
1374 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1375 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1378 PartEntry
->AutoCreate
= AutoCreate
;
1379 PartEntry
->New
= TRUE
;
1380 PartEntry
->Unpartitioned
= FALSE
;
1381 PartEntry
->UnpartitionedOffset
= 0ULL;
1382 PartEntry
->UnpartitionedLength
= 0ULL;
1386 /* Insert an initialize a new partition entry */
1387 NewPartEntry
= (PPARTENTRY
)RtlAllocateHeap (ProcessHeap
,
1390 if (NewPartEntry
== NULL
)
1393 RtlZeroMemory (NewPartEntry
,
1396 /* Insert the new entry into the list */
1397 InsertTailList (&PartEntry
->ListEntry
,
1398 &NewPartEntry
->ListEntry
);
1400 NewPartEntry
->New
= TRUE
;
1402 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
=
1403 PartEntry
->UnpartitionedOffset
+ DiskEntry
->TrackSize
;
1404 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
=
1405 PartitionSize
- DiskEntry
->TrackSize
;
1406 NewPartEntry
->PartInfo
[0].PartitionType
= PARTITION_ENTRY_UNUSED
;
1407 NewPartEntry
->PartInfo
[0].BootIndicator
= FALSE
; /* FIXME */
1408 NewPartEntry
->PartInfo
[0].RewritePartition
= TRUE
;
1409 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1410 NewPartEntry
->PartInfo
[2].RewritePartition
= TRUE
;
1411 NewPartEntry
->PartInfo
[3].RewritePartition
= TRUE
;
1413 /* Get previous and next partition entries */
1414 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1416 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1419 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1421 /* Current entry is in the middle of the list */
1423 /* Copy previous container partition data to current entry */
1424 RtlCopyMemory (&NewPartEntry
->PartInfo
[1],
1425 &PrevPartEntry
->PartInfo
[1],
1426 sizeof(PARTITION_INFORMATION
));
1427 NewPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1429 /* Update previous container partition data */
1431 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1432 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1434 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1436 /* Special case - previous partition is first partition */
1437 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1438 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1442 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1443 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1446 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1448 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1450 /* Current entry is the first entry */
1452 /* FIXME: Update extended partition entries */
1454 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1456 /* Current entry is the last entry */
1458 PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
=
1459 NewPartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1461 if (DiskEntry
->PartListHead
.Flink
== &PrevPartEntry
->ListEntry
)
1463 /* Special case - previous partition is first partition */
1464 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1465 DiskEntry
->DiskSize
- PrevPartEntry
->PartInfo
[1].StartingOffset
.QuadPart
;
1469 PrevPartEntry
->PartInfo
[1].PartitionLength
.QuadPart
=
1470 NewPartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1473 PrevPartEntry
->PartInfo
[1].PartitionType
=
1474 (DiskEntry
->UseLba
== TRUE
) ? PARTITION_XINT13_EXTENDED
: PARTITION_EXTENDED
;
1475 PrevPartEntry
->PartInfo
[1].BootIndicator
= FALSE
;
1476 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1479 /* Update offset and size of the remaining unpartitioned disk space */
1480 PartEntry
->UnpartitionedOffset
+= PartitionSize
;
1481 PartEntry
->UnpartitionedLength
-= PartitionSize
;
1484 DiskEntry
->Modified
= TRUE
;
1486 UpdatePartitionNumbers (DiskEntry
);
1488 AssignDriverLetters (List
);
1493 DeleteCurrentPartition (PPARTLIST List
)
1495 PDISKENTRY DiskEntry
;
1496 PPARTENTRY PartEntry
;
1497 PPARTENTRY PrevPartEntry
;
1498 PPARTENTRY NextPartEntry
;
1501 List
->CurrentDisk
== NULL
||
1502 List
->CurrentPartition
== NULL
||
1503 List
->CurrentPartition
->Unpartitioned
== TRUE
)
1508 DiskEntry
= List
->CurrentDisk
;
1509 PartEntry
= List
->CurrentPartition
;
1511 /* Adjust container partition entries */
1513 /* Get previous and next partition entries */
1514 PrevPartEntry
= GetPrevPartitionedEntry (DiskEntry
,
1516 NextPartEntry
= GetNextPartitionedEntry (DiskEntry
,
1519 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1521 /* Current entry is in the middle of the list */
1522 /* Copy previous container partition data to current entry */
1523 RtlCopyMemory (&PrevPartEntry
->PartInfo
[1],
1524 &PartEntry
->PartInfo
[1],
1525 sizeof(PARTITION_INFORMATION
));
1526 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1528 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1530 /* Current entry is the first entry */
1532 /* FIXME: Update extended partition entries */
1534 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1536 /* Current entry is the last entry */
1537 RtlZeroMemory (&PrevPartEntry
->PartInfo
[1],
1538 sizeof(PARTITION_INFORMATION
));
1539 PrevPartEntry
->PartInfo
[1].RewritePartition
= TRUE
;
1543 /* Adjust unpartitioned disk space entries */
1545 /* Get pointer to previous and next unpartitioned entries */
1546 PrevPartEntry
= GetPrevUnpartitionedEntry (DiskEntry
,
1549 NextPartEntry
= GetNextUnpartitionedEntry (DiskEntry
,
1552 if (PrevPartEntry
!= NULL
&& NextPartEntry
!= NULL
)
1554 /* Merge previous, current and next unpartitioned entry */
1556 /* Adjust the previous entries length */
1557 PrevPartEntry
->UnpartitionedLength
+=
1558 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
+
1559 NextPartEntry
->UnpartitionedLength
);
1561 /* Remove the current entry */
1562 RemoveEntryList (&PartEntry
->ListEntry
);
1563 RtlFreeHeap (ProcessHeap
,
1567 /* Remove the next entry */
1568 RemoveEntryList (&NextPartEntry
->ListEntry
);
1569 RtlFreeHeap (ProcessHeap
,
1573 /* Update current partition */
1574 List
->CurrentPartition
= PrevPartEntry
;
1576 else if (PrevPartEntry
!= NULL
&& NextPartEntry
== NULL
)
1578 /* Merge current and previous unpartitioned entry */
1580 /* Adjust the previous entries length */
1581 PrevPartEntry
->UnpartitionedLength
+=
1582 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
1584 /* Remove the current entry */
1585 RemoveEntryList (&PartEntry
->ListEntry
);
1586 RtlFreeHeap (ProcessHeap
,
1590 /* Update current partition */
1591 List
->CurrentPartition
= PrevPartEntry
;
1593 else if (PrevPartEntry
== NULL
&& NextPartEntry
!= NULL
)
1595 /* Merge current and next unpartitioned entry */
1597 /* Adjust the next entries offset and length */
1598 NextPartEntry
->UnpartitionedOffset
=
1599 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1600 NextPartEntry
->UnpartitionedLength
+=
1601 (PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
);
1603 /* Remove the current entry */
1604 RemoveEntryList (&PartEntry
->ListEntry
);
1605 RtlFreeHeap (ProcessHeap
,
1609 /* Update current partition */
1610 List
->CurrentPartition
= NextPartEntry
;
1614 /* Nothing to merge but change current entry */
1615 PartEntry
->New
= FALSE
;
1616 PartEntry
->Unpartitioned
= TRUE
;
1617 PartEntry
->UnpartitionedOffset
=
1618 PartEntry
->PartInfo
[0].StartingOffset
.QuadPart
- DiskEntry
->TrackSize
;
1619 PartEntry
->UnpartitionedLength
=
1620 PartEntry
->PartInfo
[0].PartitionLength
.QuadPart
+ DiskEntry
->TrackSize
;
1622 /* Wipe the partition table */
1623 RtlZeroMemory (&PartEntry
->PartInfo
,
1624 sizeof(PartEntry
->PartInfo
));
1627 DiskEntry
->Modified
= TRUE
;
1629 UpdatePartitionNumbers (DiskEntry
);
1631 AssignDriverLetters (List
);
1636 WritePartitionsToDisk (PPARTLIST List
)
1638 PDRIVE_LAYOUT_INFORMATION DriveLayout
;
1639 OBJECT_ATTRIBUTES ObjectAttributes
;
1640 IO_STATUS_BLOCK Iosb
;
1641 WCHAR Buffer
[MAX_PATH
];
1642 UNICODE_STRING Name
;
1644 PDISKENTRY DiskEntry
;
1645 PPARTENTRY PartEntry
;
1648 ULONG PartitionCount
;
1649 ULONG DriveLayoutSize
;
1658 Entry1
= List
->DiskListHead
.Flink
;
1659 while (Entry1
!= &List
->DiskListHead
)
1661 DiskEntry
= CONTAINING_RECORD (Entry1
,
1665 if (DiskEntry
->Modified
== TRUE
)
1667 /* Count partitioned entries */
1669 Entry2
= DiskEntry
->PartListHead
.Flink
;
1670 while (Entry2
!= &DiskEntry
->PartListHead
)
1672 PartEntry
= CONTAINING_RECORD (Entry2
,
1675 if (PartEntry
->Unpartitioned
== FALSE
)
1677 PartitionCount
+= 4;
1680 Entry2
= Entry2
->Flink
;
1683 if (PartitionCount
> 0)
1685 DriveLayoutSize
= sizeof (DRIVE_LAYOUT_INFORMATION
) +
1686 ((PartitionCount
- 1) * sizeof (PARTITION_INFORMATION
));
1687 DriveLayout
= (PDRIVE_LAYOUT_INFORMATION
)RtlAllocateHeap (ProcessHeap
,
1690 if (DriveLayout
== NULL
)
1692 DPRINT1 ("RtlAllocateHeap() failed\n");
1696 RtlZeroMemory (DriveLayout
,
1699 DriveLayout
->PartitionCount
= PartitionCount
;
1702 Entry2
= DiskEntry
->PartListHead
.Flink
;
1703 while (Entry2
!= &DiskEntry
->PartListHead
)
1705 PartEntry
= CONTAINING_RECORD (Entry2
,
1708 if (PartEntry
->Unpartitioned
== FALSE
)
1710 RtlCopyMemory (&DriveLayout
->PartitionEntry
[Index
],
1711 &PartEntry
->PartInfo
[0],
1712 4 * sizeof (PARTITION_INFORMATION
));
1716 Entry2
= Entry2
->Flink
;
1720 L
"\\Device\\Harddisk%d\\Partition0",
1721 DiskEntry
->DiskNumber
);
1722 RtlInitUnicodeString (&Name
,
1724 InitializeObjectAttributes (&ObjectAttributes
,
1730 Status
= NtOpenFile (&FileHandle
,
1735 FILE_SYNCHRONOUS_IO_NONALERT
);
1736 if (!NT_SUCCESS (Status
))
1738 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status
);
1742 Status
= NtDeviceIoControlFile (FileHandle
,
1747 IOCTL_DISK_SET_DRIVE_LAYOUT
,
1752 if (!NT_SUCCESS (Status
))
1754 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status
);
1755 NtClose (FileHandle
);
1759 RtlFreeHeap (ProcessHeap
,
1763 /* FIXME: Install MBR code */
1765 NtClose (FileHandle
);
1769 Entry1
= Entry1
->Flink
;