3 * Copyright (C) 2002, 2003, 2004, 2005 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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS text-mode setup
21 * FILE: base/setup/usetup/partlist.c
22 * PURPOSE: Partition list functions
23 * PROGRAMMER: Eric Kohl
24 * Casper S. Hornstrup (chorns@users.sourceforge.net)
32 /* HELPERS FOR PARTITION TYPES **********************************************/
34 typedef struct _PARTITION_TYPE
38 } PARTITION_TYPE
, *PPARTITION_TYPE
;
41 * This partition type list was ripped off the kernelDisk.c module from:
43 * Visopsys Operating System
44 * Copyright (C) 1998-2015 J. Andrew McLaughlin
46 * This program is free software; you can redistribute it and/or modify it
47 * under the terms of the GNU General Public License as published by the Free
48 * Software Foundation; either version 2 of the License, or (at your option)
51 * This program is distributed in the hope that it will be useful, but
52 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
53 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
56 * You should have received a copy of the GNU General Public License along
57 * with this program; if not, write to the Free Software Foundation, Inc.,
58 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
61 * See also https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs
62 * and http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
63 * for a complete list.
66 /* This is a table for keeping known partition type codes and descriptions */
67 static PARTITION_TYPE PartitionTypes
[] =
71 { 0x02, "XENIX root" },
72 { 0x03, "XENIX /usr" },
73 { 0x04, "FAT16 (small)" },
76 { 0x07, "NTFS/HPFS/exFAT" },
77 { 0x08, "OS/2 or AIX boot" },
79 { 0x0A, "OS/2 Boot Manager" },
81 { 0x0C, "FAT32 (LBA)" },
82 { 0x0E, "FAT16 (LBA)" },
83 { 0x0F, "Extended (LBA)" },
84 { 0x11, "Hidden FAT12" },
85 { 0x12, "FAT diagnostic" },
86 { 0x14, "Hidden FAT16 (small)" },
87 { 0x16, "Hidden FAT16" },
88 { 0x17, "Hidden HPFS or NTFS" },
89 { 0x1B, "Hidden FAT32" },
90 { 0x1C, "Hidden FAT32 (LBA)" },
91 { 0x1E, "Hidden FAT16 (LBA)" },
94 { 0x3C, "PartitionMagic" },
95 { 0x3D, "Hidden Netware" },
96 { 0x41, "PowerPC PReP" },
97 { 0x42, "Win2K dynamic extended" },
98 { 0x43, "Old Linux" },
101 { 0x4D, "QNX4.x 2nd" },
102 { 0x4D, "QNX4.x 3rd" },
103 { 0x50, "Ontrack R/O" },
104 { 0x51, "Ontrack R/W or Novell" },
106 { 0x63, "GNU HURD or UNIX SysV" },
107 { 0x64, "Netware 2" },
108 { 0x65, "Netware 3/4" },
109 { 0x66, "Netware SMS" },
112 { 0x69, "Netware 5+" },
113 { 0x7E, "Veritas VxVM public" },
114 { 0x7F, "Veritas VxVM private" },
116 { 0x81, "Linux or Minix" },
117 { 0x82, "Linux swap or Solaris" },
119 { 0x84, "Hibernation" },
120 { 0x85, "Linux extended" },
121 { 0x86, "HPFS or NTFS mirrored" },
122 { 0x87, "HPFS or NTFS mirrored" },
123 { 0x8E, "Linux LVM" },
124 { 0x93, "Hidden Linux" },
125 { 0x96, "CDFS/ISO-9660" },
127 { 0xA0, "Laptop hibernation" },
128 { 0xA1, "Laptop hibernation" },
129 { 0xA5, "BSD, NetBSD, FreeBSD" },
131 { 0xA7, "NeXTSTEP" },
132 { 0xA8, "OS-X UFS" },
134 { 0xAB, "OS-X boot" },
135 { 0xAF, "OS-X HFS" },
136 { 0xB6, "NT corrupt mirror" },
138 { 0xB8, "BSDI swap" },
139 { 0xBE, "Solaris 8 boot" },
140 { 0xBF, "Solaris x86" },
142 { 0xC1, "DR-DOS FAT12" },
143 { 0xC2, "Hidden Linux" },
144 { 0xC3, "Hidden Linux swap" },
145 { 0xC4, "DR-DOS FAT16 (small)" },
146 { 0xC5, "DR-DOS Extended" },
147 { 0xC6, "DR-DOS FAT16" },
148 { 0xC7, "HPFS mirrored" },
149 { 0xCB, "DR-DOS FAT32" },
150 { 0xCC, "DR-DOS FAT32 (LBA)" },
151 { 0xCE, "DR-DOS FAT16 (LBA)" },
153 { 0xD1, "MDOS FAT12" },
154 { 0xD4, "MDOS FAT16 (small)" },
155 { 0xD5, "MDOS Extended" },
156 { 0xD6, "MDOS FAT16" },
158 { 0xDF, "BootIt EMBRM(FAT16/32)" },
159 { 0xEB, "BeOS BFS" },
160 { 0xEE, "EFI GPT protective" },
161 { 0xEF, "EFI filesystem" },
162 { 0xF0, "Linux/PA-RISC boot" },
163 { 0xF2, "DOS 3.3+ second" },
166 { 0xFC, "VmWare swap" },
167 { 0xFD, "Linux RAID" },
168 { 0xFE, "NT hidden" },
172 GetPartTypeStringFromPartitionType(
173 IN UCHAR partitionType
,
174 OUT PCHAR strPartType
,
175 IN ULONG cchPartType
)
177 /* Determine partition type */
179 if (IsContainerPartition(partitionType
))
181 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_EXTENDED_PARTITION
));
183 else if (partitionType
== PARTITION_ENTRY_UNUSED
)
185 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNUSED
));
191 /* Do the table lookup */
192 for (i
= 0; i
< ARRAYSIZE(PartitionTypes
); i
++)
194 if (partitionType
== PartitionTypes
[i
].Type
)
196 RtlStringCchCopyA(strPartType
, cchPartType
, PartitionTypes
[i
].Description
);
201 /* We are here because the partition type is unknown */
202 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNKNOWN
));
207 /* FUNCTIONS ****************************************************************/
211 IN OUT PPARTLIST_UI ListUi
,
219 // ListUi->FirstShown = NULL;
220 // ListUi->LastShown = NULL;
224 ListUi
->Right
= Right
;
225 ListUi
->Bottom
= Bottom
;
230 // ListUi->Redraw = TRUE;
236 IN PPARTLIST_UI ListUi
)
243 Width
= ListUi
->Right
- ListUi
->Left
- 1;
244 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
246 coPos
.X
= ListUi
->Left
+ 1;
247 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
249 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
251 FillConsoleOutputAttribute(StdOutput
,
252 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
257 FillConsoleOutputCharacterA(StdOutput
,
270 IN PPARTLIST_UI ListUi
,
271 IN PDISKENTRY DiskEntry
,
272 IN PPARTENTRY PartEntry
)
274 PPARTLIST List
= ListUi
->List
;
275 CHAR LineBuffer
[128];
280 LARGE_INTEGER PartSize
;
283 CHAR PartTypeString
[32];
284 PCHAR PartType
= PartTypeString
;
286 Width
= ListUi
->Right
- ListUi
->Left
- 1;
287 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
289 coPos
.X
= ListUi
->Left
+ 1;
290 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
292 if (PartEntry
->IsPartitioned
== FALSE
)
294 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
296 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
298 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
299 Unit
= MUIGetString(STRING_GB
);
303 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
305 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
306 Unit
= MUIGetString(STRING_MB
);
310 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
311 Unit
= MUIGetString(STRING_KB
);
315 MUIGetString(STRING_UNPSPACE
),
316 PartEntry
->LogicalPartition
? " " : "",
317 PartEntry
->LogicalPartition
? "" : " ",
323 /* Determine partition type */
324 PartTypeString
[0] = '\0';
325 if (PartEntry
->New
!= FALSE
)
327 PartType
= MUIGetString(STRING_UNFORMATTED
);
329 else if (PartEntry
->IsPartitioned
!= FALSE
)
331 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
333 ARRAYSIZE(PartTypeString
));
334 PartType
= PartTypeString
;
337 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
339 if (PartSize
.QuadPart
>= 10737418240) /* 10 GB */
341 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
342 Unit
= MUIGetString(STRING_GB
);
346 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
348 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
349 Unit
= MUIGetString(STRING_MB
);
353 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
354 Unit
= MUIGetString(STRING_KB
);
357 if (strcmp(PartType
, MUIGetString(STRING_FORMATUNKNOWN
)) == 0)
360 MUIGetString(STRING_HDDINFOUNK5
),
361 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
362 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
363 PartEntry
->BootIndicator
? '*' : ' ',
364 PartEntry
->LogicalPartition
? " " : "",
365 PartEntry
->PartitionType
,
366 PartEntry
->LogicalPartition
? "" : " ",
373 "%c%c %c %s%-24s%s %6lu %s",
374 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
375 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
376 PartEntry
->BootIndicator
? '*' : ' ',
377 PartEntry
->LogicalPartition
? " " : "",
379 PartEntry
->LogicalPartition
? "" : " ",
385 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
386 List
->CurrentPartition
== PartEntry
) ?
387 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
388 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
390 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
392 FillConsoleOutputCharacterA(StdOutput
,
400 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
402 FillConsoleOutputAttribute(StdOutput
,
410 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
412 WriteConsoleOutputCharacterA(StdOutput
,
414 min(strlen(LineBuffer
), Width
),
425 IN PPARTLIST_UI ListUi
,
426 IN PDISKENTRY DiskEntry
)
428 // PPARTLIST List = ListUi->List;
429 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
430 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
431 CHAR LineBuffer
[128];
436 ULARGE_INTEGER DiskSize
;
439 Width
= ListUi
->Right
- ListUi
->Left
- 1;
440 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
442 coPos
.X
= ListUi
->Left
+ 1;
443 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
445 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
446 if (DiskSize
.QuadPart
>= 10737418240) /* 10 GB */
448 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
449 Unit
= MUIGetString(STRING_GB
);
453 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
454 if (DiskSize
.QuadPart
== 0)
455 DiskSize
.QuadPart
= 1;
456 Unit
= MUIGetString(STRING_MB
);
459 if (DiskEntry
->DriverName
.Length
> 0)
462 MUIGetString(STRING_HDINFOPARTSELECT
),
465 DiskEntry
->DiskNumber
,
469 DiskEntry
->DriverName
.Buffer
);
474 MUIGetString(STRING_HDDINFOUNK6
),
477 DiskEntry
->DiskNumber
,
483 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
485 FillConsoleOutputAttribute(StdOutput
,
486 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
491 FillConsoleOutputCharacterA(StdOutput
,
499 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
501 WriteConsoleOutputCharacterA(StdOutput
,
503 min((USHORT
)strlen(LineBuffer
), Width
- 2),
510 /* Print separator line */
511 PrintEmptyLine(ListUi
);
513 /* Print partition lines */
514 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
515 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
517 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
519 PrintPartitionData(ListUi
,
523 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
525 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
526 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
528 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
530 PrintPartitionData(ListUi
,
534 LogicalEntry
= LogicalEntry
->Flink
;
538 PrimaryEntry
= PrimaryEntry
->Flink
;
541 /* Print separator line */
542 PrintEmptyLine(ListUi
);
547 IN PPARTLIST_UI ListUi
)
549 PPARTLIST List
= ListUi
->List
;
550 PLIST_ENTRY Entry
, Entry2
;
551 PDISKENTRY DiskEntry
;
552 PPARTENTRY PartEntry
= NULL
;
556 SHORT CurrentDiskLine
;
557 SHORT CurrentPartLine
;
559 BOOLEAN CurrentPartLineFound
= FALSE
;
560 BOOLEAN CurrentDiskLineFound
= FALSE
;
562 /* Calculate the line of the current disk and partition */
567 Entry
= List
->DiskListHead
.Flink
;
568 while (Entry
!= &List
->DiskListHead
)
570 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
573 if (CurrentPartLineFound
== FALSE
)
575 CurrentPartLine
+= 2;
578 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
579 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
581 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
582 if (PartEntry
== List
->CurrentPartition
)
584 CurrentPartLineFound
= TRUE
;
587 Entry2
= Entry2
->Flink
;
588 if (CurrentPartLineFound
== FALSE
)
596 if (CurrentPartLineFound
== FALSE
)
598 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
599 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
601 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
602 if (PartEntry
== List
->CurrentPartition
)
604 CurrentPartLineFound
= TRUE
;
607 Entry2
= Entry2
->Flink
;
608 if (CurrentPartLineFound
== FALSE
)
617 if (DiskEntry
== List
->CurrentDisk
)
619 CurrentDiskLineFound
= TRUE
;
622 Entry
= Entry
->Flink
;
623 if (Entry
!= &List
->DiskListHead
)
625 if (CurrentDiskLineFound
== FALSE
)
628 CurrentDiskLine
= CurrentPartLine
;
639 /* If it possible, make the disk name visible */
640 if (CurrentPartLine
< ListUi
->Offset
)
642 ListUi
->Offset
= CurrentPartLine
;
644 else if (CurrentPartLine
- ListUi
->Offset
> ListUi
->Bottom
- ListUi
->Top
- 2)
646 ListUi
->Offset
= CurrentPartLine
- (ListUi
->Bottom
- ListUi
->Top
- 2);
649 if (CurrentDiskLine
< ListUi
->Offset
&& CurrentPartLine
- CurrentDiskLine
< ListUi
->Bottom
- ListUi
->Top
- 2)
651 ListUi
->Offset
= CurrentDiskLine
;
654 /* Draw upper left corner */
655 coPos
.X
= ListUi
->Left
;
656 coPos
.Y
= ListUi
->Top
;
657 FillConsoleOutputCharacterA(StdOutput
,
663 /* Draw upper edge */
664 coPos
.X
= ListUi
->Left
+ 1;
665 coPos
.Y
= ListUi
->Top
;
666 if (ListUi
->Offset
== 0)
668 FillConsoleOutputCharacterA(StdOutput
,
670 ListUi
->Right
- ListUi
->Left
- 1,
676 FillConsoleOutputCharacterA(StdOutput
,
678 ListUi
->Right
- ListUi
->Left
- 5,
681 coPos
.X
= ListUi
->Right
- 5;
682 WriteConsoleOutputCharacterA(StdOutput
,
687 coPos
.X
= ListUi
->Right
- 2;
688 FillConsoleOutputCharacterA(StdOutput
,
695 /* Draw upper right corner */
696 coPos
.X
= ListUi
->Right
;
697 coPos
.Y
= ListUi
->Top
;
698 FillConsoleOutputCharacterA(StdOutput
,
704 /* Draw left and right edge */
705 for (i
= ListUi
->Top
+ 1; i
< ListUi
->Bottom
; i
++)
707 coPos
.X
= ListUi
->Left
;
709 FillConsoleOutputCharacterA(StdOutput
,
715 coPos
.X
= ListUi
->Right
;
716 FillConsoleOutputCharacterA(StdOutput
,
723 /* Draw lower left corner */
724 coPos
.X
= ListUi
->Left
;
725 coPos
.Y
= ListUi
->Bottom
;
726 FillConsoleOutputCharacterA(StdOutput
,
732 /* Draw lower edge */
733 coPos
.X
= ListUi
->Left
+ 1;
734 coPos
.Y
= ListUi
->Bottom
;
735 if (LastLine
- ListUi
->Offset
<= ListUi
->Bottom
- ListUi
->Top
- 2)
737 FillConsoleOutputCharacterA(StdOutput
,
739 ListUi
->Right
- ListUi
->Left
- 1,
745 FillConsoleOutputCharacterA(StdOutput
,
747 ListUi
->Right
- ListUi
->Left
- 5,
750 coPos
.X
= ListUi
->Right
- 5;
751 WriteConsoleOutputCharacterA(StdOutput
,
752 "(\x19)", // "(down)"
756 coPos
.X
= ListUi
->Right
- 2;
757 FillConsoleOutputCharacterA(StdOutput
,
764 /* Draw lower right corner */
765 coPos
.X
= ListUi
->Right
;
766 coPos
.Y
= ListUi
->Bottom
;
767 FillConsoleOutputCharacterA(StdOutput
,
773 /* print list entries */
774 ListUi
->Line
= - ListUi
->Offset
;
776 Entry
= List
->DiskListHead
.Flink
;
777 while (Entry
!= &List
->DiskListHead
)
779 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
781 /* Print disk entry */
782 PrintDiskData(ListUi
, DiskEntry
);
784 Entry
= Entry
->Flink
;
789 ScrollDownPartitionList(
790 IN PPARTLIST_UI ListUi
)
792 if (GetNextPartition(ListUi
->List
))
793 DrawPartitionList(ListUi
);
797 ScrollUpPartitionList(
798 IN PPARTLIST_UI ListUi
)
800 if (GetPrevPartition(ListUi
->List
))
801 DrawPartitionList(ListUi
);