3 * Copyright (C) 2002 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
27 #include <ddk/ntddk.h>
28 #include <ddk/ntddscsi.h>
30 #include <ntdll/rtl.h>
32 #include <ntos/minmax.h>
39 /* FUNCTIONS ****************************************************************/
42 CreatePartitionList(SHORT Left,
48 OBJECT_ATTRIBUTES ObjectAttributes;
49 SYSTEM_DEVICE_INFORMATION Sdi;
50 DISK_GEOMETRY DiskGeometry;
55 WCHAR Buffer[MAX_PATH];
58 DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
59 SCSI_ADDRESS ScsiAddress;
62 List = (PPARTLIST)RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTLIST));
69 List->Bottom = Bottom;
73 List->TopDisk = (ULONG)-1;
74 List->TopPartition = (ULONG)-1;
76 List->CurrentDisk = (ULONG)-1;
77 List->CurrentPartition = (ULONG)-1;
80 List->DiskArray = NULL;
83 Status = NtQuerySystemInformation(SystemDeviceInformation,
85 sizeof(SYSTEM_DEVICE_INFORMATION),
87 if (!NT_SUCCESS(Status))
89 RtlFreeHeap(ProcessHeap, 0, List);
93 List->DiskArray = (PDISKENTRY)RtlAllocateHeap(ProcessHeap,
95 Sdi.NumberOfDisks * sizeof(DISKENTRY));
96 List->DiskCount = Sdi.NumberOfDisks;
98 for (DiskCount = 0; DiskCount < Sdi.NumberOfDisks; DiskCount++)
101 L"\\Device\\Harddisk%d\\Partition0",
103 RtlInitUnicodeString(&Name,
106 InitializeObjectAttributes(&ObjectAttributes,
112 Status = NtOpenFile(&FileHandle,
117 FILE_SYNCHRONOUS_IO_NONALERT);
118 if (NT_SUCCESS(Status))
120 Status = NtDeviceIoControlFile(FileHandle,
125 IOCTL_DISK_GET_DRIVE_GEOMETRY,
129 sizeof(DISK_GEOMETRY));
130 if (NT_SUCCESS(Status))
132 if (DiskGeometry.MediaType == FixedMedia)
134 Status = NtDeviceIoControlFile(FileHandle,
139 IOCTL_SCSI_GET_ADDRESS,
143 sizeof(SCSI_ADDRESS));
146 List->DiskArray[DiskCount].DiskSize =
147 DiskGeometry.Cylinders.QuadPart *
148 (ULONGLONG)DiskGeometry.TracksPerCylinder *
149 (ULONGLONG)DiskGeometry.SectorsPerTrack *
150 (ULONGLONG)DiskGeometry.BytesPerSector;
151 List->DiskArray[DiskCount].DiskNumber = DiskCount;
152 List->DiskArray[DiskCount].Port = ScsiAddress.PortNumber;
153 List->DiskArray[DiskCount].Bus = ScsiAddress.PathId;
154 List->DiskArray[DiskCount].Id = ScsiAddress.TargetId;
156 List->DiskArray[DiskCount].FixedDisk = TRUE;
159 LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192);
161 Status = NtDeviceIoControlFile(FileHandle,
166 IOCTL_DISK_GET_DRIVE_LAYOUT,
171 if (NT_SUCCESS(Status))
174 List->DiskArray[DiskCount].PartArray = (PPARTENTRY)RtlAllocateHeap(ProcessHeap,
176 LayoutBuffer->PartitionCount * sizeof(PARTENTRY));
177 List->DiskArray[DiskCount].PartCount = LayoutBuffer->PartitionCount;
179 for (i = 0; i < LayoutBuffer->PartitionCount; i++)
181 if ((LayoutBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED) &&
182 !IsContainerPartition(LayoutBuffer->PartitionEntry[i].PartitionType))
184 List->DiskArray[DiskCount].PartArray[i].PartSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart;
185 List->DiskArray[DiskCount].PartArray[i].PartNumber = LayoutBuffer->PartitionEntry[i].PartitionNumber,
186 List->DiskArray[DiskCount].PartArray[i].PartType = LayoutBuffer->PartitionEntry[i].PartitionType;
187 List->DiskArray[DiskCount].PartArray[i].Used = TRUE;
191 List->DiskArray[DiskCount].PartArray[i].Used = FALSE;
196 RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
200 /* mark removable disk entry */
201 List->DiskArray[DiskCount].FixedDisk = FALSE;
202 List->DiskArray[DiskCount].PartCount = 0;
203 List->DiskArray[DiskCount].PartArray = NULL;
212 List->TopPartition = 0;
214 /* FIXME: search for first usable disk and partition */
215 List->CurrentDisk = 0;
216 List->CurrentPartition = 0;
218 DrawPartitionList(List);
225 DestroyPartitionList(PPARTLIST List)
232 /* clear occupied screen area */
233 coPos.X = List->Left;
234 Width = List->Right - List->Left + 1;
235 for (coPos.Y = List->Top; coPos.Y <= List->Bottom; coPos.Y++)
237 FillConsoleOutputAttribute(0x17,
242 FillConsoleOutputCharacter(' ',
249 /* free disk and partition info */
250 if (List->DiskArray != NULL)
252 /* free partition arrays */
253 for (i = 0; i < List->DiskCount; i++)
255 if (List->DiskArray[i].PartArray != NULL)
257 RtlFreeHeap(ProcessHeap, 0, List->DiskArray[i].PartArray);
258 List->DiskArray[i].PartCount = 0;
259 List->DiskArray[i].PartArray = NULL;
263 /* free disk array */
264 RtlFreeHeap(ProcessHeap, 0, List->DiskArray);
266 List->DiskArray = NULL;
270 RtlFreeHeap(ProcessHeap, 0, List);
275 PrintEmptyLine(PPARTLIST List)
282 Width = List->Right - List->Left - 1;
283 Height = List->Bottom - List->Top - 1;
285 if (List->Line < 0 || List->Line > Height)
288 coPos.X = List->Left + 1;
289 coPos.Y = List->Top + 1 + List->Line;
291 FillConsoleOutputAttribute(0x17,
296 FillConsoleOutputCharacter(' ',
306 PrintPartitionData(PPARTLIST List,
310 PPARTENTRY PartEntry;
311 CHAR LineBuffer[128];
323 Width = List->Right - List->Left - 1;
324 Height = List->Bottom - List->Top - 1;
326 if (List->Line < 0 || List->Line > Height)
329 coPos.X = List->Left + 1;
330 coPos.Y = List->Top + 1 + List->Line;
332 PartEntry = &List->DiskArray[DiskIndex].PartArray[PartIndex];
334 if ((PartEntry->PartType == PARTITION_FAT_12) ||
335 (PartEntry->PartType == PARTITION_FAT_16) ||
336 (PartEntry->PartType == PARTITION_HUGE) ||
337 (PartEntry->PartType == PARTITION_XINT13))
341 else if ((PartEntry->PartType == PARTITION_FAT32) ||
342 (PartEntry->PartType == PARTITION_FAT32_XINT13))
346 else if (PartEntry->PartType == PARTITION_IFS)
348 PartType = "NTFS"; /* FIXME: Not quite correct! */
352 PartType = "Unknown";
355 if (PartEntry->PartSize >= 0x280000000ULL) /* 10 GB */
357 PartSize = (PartEntry->PartSize + (1 << 29)) >> 30;
360 else if (PartEntry->PartSize >= 0xA00000ULL) /* 10 MB */
362 PartSize = (PartEntry->PartSize + (1 << 19)) >> 20;
367 PartSize = (PartEntry->PartSize + (1 << 9)) >> 10;
372 "%d: nr: %d type: %x (%s) %I64u %s",
374 PartEntry->PartNumber,
381 Attribute = (List->CurrentDisk == DiskIndex &&
382 List->CurrentPartition == PartIndex) ? 0x71 : 0x17;
384 FillConsoleOutputCharacter(' ',
391 FillConsoleOutputAttribute(Attribute,
398 WriteConsoleOutputCharacters(LineBuffer,
399 min(strlen(LineBuffer), Width),
407 PrintDiskData(PPARTLIST List,
410 PDISKENTRY DiskEntry;
411 CHAR LineBuffer[128];
421 DiskEntry = &List->DiskArray[DiskIndex];
423 Width = List->Right - List->Left - 1;
424 Height = List->Bottom - List->Top - 1;
426 if (List->Line < 0 || List->Line > Height)
429 coPos.X = List->Left + 1;
430 coPos.Y = List->Top + 1 + List->Line;
432 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
434 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
437 else if (DiskEntry->DiskSize >= 0xA00000ULL) /* 10 MB */
439 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
444 DiskSize = (DiskEntry->DiskSize + (1 << 9)) >> 10;
449 "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
452 DiskEntry->DiskNumber,
457 FillConsoleOutputAttribute(0x17,
462 FillConsoleOutputCharacter(' ',
468 WriteConsoleOutputCharacters(LineBuffer,
469 min(strlen(LineBuffer), Width - 2),
474 /* Print separator line */
475 PrintEmptyLine(List);
480 /* Print partition lines*/
481 for (PartIndex = 0; PartIndex < List->DiskArray[DiskIndex].PartCount; PartIndex++)
483 if (List->DiskArray[DiskIndex].PartArray[PartIndex].Used == TRUE)
485 PrintPartitionData(List,
492 /* Print separator line */
493 if (PartPrinted == TRUE)
495 PrintEmptyLine(List);
501 DrawPartitionList(PPARTLIST List)
503 CHAR LineBuffer[128];
509 /* draw upper left corner */
510 coPos.X = List->Left;
512 FillConsoleOutputCharacter(0xDA, // '+',
517 /* draw upper edge */
518 coPos.X = List->Left + 1;
520 FillConsoleOutputCharacter(0xC4, // '-',
521 List->Right - List->Left - 1,
525 /* draw upper right corner */
526 coPos.X = List->Right;
528 FillConsoleOutputCharacter(0xBF, // '+',
533 /* draw left and right edge */
534 for (i = List->Top + 1; i < List->Bottom; i++)
536 coPos.X = List->Left;
538 FillConsoleOutputCharacter(0xB3, // '|',
543 coPos.X = List->Right;
544 FillConsoleOutputCharacter(0xB3, //'|',
550 /* draw lower left corner */
551 coPos.X = List->Left;
552 coPos.Y = List->Bottom;
553 FillConsoleOutputCharacter(0xC0, // '+',
558 /* draw lower edge */
559 coPos.X = List->Left + 1;
560 coPos.Y = List->Bottom;
561 FillConsoleOutputCharacter(0xC4, // '-',
562 List->Right - List->Left - 1,
566 /* draw upper right corner */
567 coPos.X = List->Right;
568 coPos.Y = List->Bottom;
569 FillConsoleOutputCharacter(0xD9, // '+',
574 /* print list entries */
576 for (DiskIndex = 0; DiskIndex < List->DiskCount; DiskIndex++)
578 if (List->DiskArray[DiskIndex].FixedDisk == TRUE)
580 /* Print disk entry */
589 ScrollDownPartitionList(PPARTLIST List)
594 /* check for available disks */
595 if (List->DiskCount == 0)
598 /* check for next usable entry on current disk */
599 for (i = List->CurrentPartition + 1; i < List->DiskArray[List->CurrentDisk].PartCount; i++)
601 if (List->DiskArray[List->CurrentDisk].PartArray[i].Used == TRUE)
603 List->CurrentPartition = i;
604 DrawPartitionList(List);
609 /* check for first usable entry on next disk */
610 for (j = List->CurrentDisk + 1; j < List->DiskCount; j++)
612 for (i = 0; i < List->DiskArray[j].PartCount; i++)
614 if (List->DiskArray[j].PartArray[i].Used == TRUE)
616 List->CurrentDisk = j;
617 List->CurrentPartition = i;
618 DrawPartitionList(List);
627 ScrollUpPartitionList(PPARTLIST List)
632 /* check for available disks */
633 if (List->DiskCount == 0)
636 /* check for previous usable entry on current disk */
637 for (i = List->CurrentPartition - 1; i != (ULONG)-1; i--)
639 if (List->DiskArray[List->CurrentDisk].PartArray[i].Used == TRUE)
641 List->CurrentPartition = i;
642 DrawPartitionList(List);
647 /* check for last usable entry on previous disk */
648 for (j = List->CurrentDisk - 1; j != (ULONG)-1; j--)
650 for (i = List->DiskArray[j].PartCount - 1; i != (ULONG)-1; i--)
652 if (List->DiskArray[j].PartArray[i].Used == TRUE)
654 List->CurrentDisk = j;
655 List->CurrentPartition = i;
656 DrawPartitionList(List);
665 GetPartitionData(PPARTLIST List,
668 if (List->CurrentDisk >= List->DiskCount)
671 if (List->DiskArray[List->CurrentDisk].FixedDisk == FALSE)
674 if (List->CurrentPartition >= List->DiskArray[List->CurrentDisk].PartCount)
677 if (List->DiskArray[List->CurrentDisk].PartArray[List->CurrentPartition].Used == FALSE)
680 Data->DiskSize = List->DiskArray[List->CurrentDisk].DiskSize;
681 Data->DiskNumber = List->DiskArray[List->CurrentDisk].DiskNumber;
682 Data->Port = List->DiskArray[List->CurrentDisk].Port;
683 Data->Bus = List->DiskArray[List->CurrentDisk].Bus;
684 Data->Id = List->DiskArray[List->CurrentDisk].Id;
686 Data->PartSize = List->DiskArray[List->CurrentDisk].PartArray[List->CurrentPartition].PartSize;
687 Data->PartNumber = List->DiskArray[List->CurrentDisk].PartArray[List->CurrentPartition].PartNumber;
688 Data->PartType = List->DiskArray[List->CurrentDisk].PartArray[List->CurrentPartition].PartType;