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)
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;