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: Casper S. Hornstrup (chorns@users.sourceforge.net)
31 /* HELPERS FOR PARTITION TYPES **********************************************/
33 typedef struct _PARTITION_TYPE
37 } PARTITION_TYPE
, *PPARTITION_TYPE
;
40 * This partition type list was ripped off the kernelDisk.c module from:
42 * Visopsys Operating System
43 * Copyright (C) 1998-2015 J. Andrew McLaughlin
45 * This program is free software; you can redistribute it and/or modify it
46 * under the terms of the GNU General Public License as published by the Free
47 * Software Foundation; either version 2 of the License, or (at your option)
50 * This program is distributed in the hope that it will be useful, but
51 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
52 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
55 * You should have received a copy of the GNU General Public License along
56 * with this program; if not, write to the Free Software Foundation, Inc.,
57 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
60 * See also https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs
61 * and http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
62 * for a complete list.
65 /* This is a table for keeping known partition type codes and descriptions */
66 static PARTITION_TYPE PartitionTypes
[] =
70 { 0x02, "XENIX root" },
71 { 0x03, "XENIX /usr" },
72 { 0x04, "FAT16 (small)" },
75 { 0x07, "NTFS/HPFS/exFAT" },
76 { 0x08, "OS/2 or AIX boot" },
78 { 0x0A, "OS/2 Boot Manager" },
80 { 0x0C, "FAT32 (LBA)" },
81 { 0x0E, "FAT16 (LBA)" },
82 { 0x0F, "Extended (LBA)" },
83 { 0x11, "Hidden FAT12" },
84 { 0x12, "FAT diagnostic" },
85 { 0x14, "Hidden FAT16 (small)" },
86 { 0x16, "Hidden FAT16" },
87 { 0x17, "Hidden HPFS or NTFS" },
88 { 0x1B, "Hidden FAT32" },
89 { 0x1C, "Hidden FAT32 (LBA)" },
90 { 0x1E, "Hidden FAT16 (LBA)" },
93 { 0x3C, "PartitionMagic" },
94 { 0x3D, "Hidden Netware" },
95 { 0x41, "PowerPC PReP" },
96 { 0x42, "Win2K dynamic extended" },
97 { 0x43, "Old Linux" },
100 { 0x4D, "QNX4.x 2nd" },
101 { 0x4D, "QNX4.x 3rd" },
102 { 0x50, "Ontrack R/O" },
103 { 0x51, "Ontrack R/W or Novell" },
105 { 0x63, "GNU HURD or UNIX SysV" },
106 { 0x64, "Netware 2" },
107 { 0x65, "Netware 3/4" },
108 { 0x66, "Netware SMS" },
111 { 0x69, "Netware 5+" },
112 { 0x7E, "Veritas VxVM public" },
113 { 0x7F, "Veritas VxVM private" },
115 { 0x81, "Linux or Minix" },
116 { 0x82, "Linux swap or Solaris" },
118 { 0x84, "Hibernation" },
119 { 0x85, "Linux extended" },
120 { 0x86, "HPFS or NTFS mirrored" },
121 { 0x87, "HPFS or NTFS mirrored" },
122 { 0x8E, "Linux LVM" },
123 { 0x93, "Hidden Linux" },
124 { 0x96, "CDFS/ISO-9660" },
126 { 0xA0, "Laptop hibernation" },
127 { 0xA1, "Laptop hibernation" },
128 { 0xA5, "BSD, NetBSD, FreeBSD" },
130 { 0xA7, "NeXTSTEP" },
131 { 0xA8, "OS-X UFS" },
133 { 0xAB, "OS-X boot" },
134 { 0xAF, "OS-X HFS" },
135 { 0xB6, "NT corrupt mirror" },
137 { 0xB8, "BSDI swap" },
138 { 0xBE, "Solaris 8 boot" },
139 { 0xBF, "Solaris x86" },
141 { 0xC1, "DR-DOS FAT12" },
142 { 0xC2, "Hidden Linux" },
143 { 0xC3, "Hidden Linux swap" },
144 { 0xC4, "DR-DOS FAT16 (small)" },
145 { 0xC5, "DR-DOS Extended" },
146 { 0xC6, "DR-DOS FAT16" },
147 { 0xC7, "HPFS mirrored" },
148 { 0xCB, "DR-DOS FAT32" },
149 { 0xCC, "DR-DOS FAT32 (LBA)" },
150 { 0xCE, "DR-DOS FAT16 (LBA)" },
152 { 0xD1, "MDOS FAT12" },
153 { 0xD4, "MDOS FAT16 (small)" },
154 { 0xD5, "MDOS Extended" },
155 { 0xD6, "MDOS FAT16" },
157 { 0xDF, "BootIt EMBRM(FAT16/32)" },
158 { 0xEB, "BeOS BFS" },
159 { 0xEE, "EFI GPT protective" },
160 { 0xEF, "EFI filesystem" },
161 { 0xF0, "Linux/PA-RISC boot" },
162 { 0xF2, "DOS 3.3+ second" },
165 { 0xFC, "VmWare swap" },
166 { 0xFD, "Linux RAID" },
167 { 0xFE, "NT hidden" },
171 GetPartTypeStringFromPartitionType(
172 IN UCHAR partitionType
,
173 OUT PCHAR strPartType
,
174 IN ULONG cchPartType
)
176 /* Determine partition type */
178 if (IsContainerPartition(partitionType
))
180 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_EXTENDED_PARTITION
));
182 else if (partitionType
== PARTITION_ENTRY_UNUSED
)
184 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNUSED
));
190 /* Do the table lookup */
191 for (i
= 0; i
< ARRAYSIZE(PartitionTypes
); i
++)
193 if (partitionType
== PartitionTypes
[i
].Type
)
195 RtlStringCchCopyA(strPartType
, cchPartType
, PartitionTypes
[i
].Description
);
200 /* We are here because the partition type is unknown */
201 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNKNOWN
));
206 /* FUNCTIONS ****************************************************************/
210 IN OUT PPARTLIST_UI ListUi
,
218 // ListUi->FirstShown = NULL;
219 // ListUi->LastShown = NULL;
223 ListUi
->Right
= Right
;
224 ListUi
->Bottom
= Bottom
;
229 // ListUi->Redraw = TRUE;
235 IN PPARTLIST_UI ListUi
)
242 Width
= ListUi
->Right
- ListUi
->Left
- 1;
243 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
245 coPos
.X
= ListUi
->Left
+ 1;
246 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
248 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
250 FillConsoleOutputAttribute(StdOutput
,
251 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
256 FillConsoleOutputCharacterA(StdOutput
,
269 IN PPARTLIST_UI ListUi
,
270 IN PDISKENTRY DiskEntry
,
271 IN PPARTENTRY PartEntry
)
273 PPARTLIST List
= ListUi
->List
;
274 CHAR LineBuffer
[128];
279 LARGE_INTEGER PartSize
;
282 CHAR PartTypeString
[32];
283 PCHAR PartType
= PartTypeString
;
285 Width
= ListUi
->Right
- ListUi
->Left
- 1;
286 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
288 coPos
.X
= ListUi
->Left
+ 1;
289 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
291 if (PartEntry
->IsPartitioned
== FALSE
)
293 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
295 if (PartSize
.QuadPart
>= 10 * GB
) /* 10 GB */
297 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, GB
);
298 Unit
= MUIGetString(STRING_GB
);
302 if (PartSize
.QuadPart
>= 10 * MB
) /* 10 MB */
304 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, MB
);
305 Unit
= MUIGetString(STRING_MB
);
309 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, KB
);
310 Unit
= MUIGetString(STRING_KB
);
314 MUIGetString(STRING_UNPSPACE
),
315 PartEntry
->LogicalPartition
? " " : "",
316 PartEntry
->LogicalPartition
? "" : " ",
322 /* Determine partition type */
323 PartTypeString
[0] = '\0';
324 if (PartEntry
->New
!= FALSE
)
326 PartType
= MUIGetString(STRING_UNFORMATTED
);
328 else if (PartEntry
->IsPartitioned
!= FALSE
)
330 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
332 ARRAYSIZE(PartTypeString
));
333 PartType
= PartTypeString
;
336 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
338 if (PartSize
.QuadPart
>= 10 * GB
) /* 10 GB */
340 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, GB
);
341 Unit
= MUIGetString(STRING_GB
);
345 if (PartSize
.QuadPart
>= 10 * MB
) /* 10 MB */
347 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, MB
);
348 Unit
= MUIGetString(STRING_MB
);
352 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, KB
);
353 Unit
= MUIGetString(STRING_KB
);
356 if (strcmp(PartType
, MUIGetString(STRING_FORMATUNKNOWN
)) == 0)
359 MUIGetString(STRING_HDDINFOUNK5
),
360 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
361 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
362 PartEntry
->BootIndicator
? '*' : ' ',
363 PartEntry
->LogicalPartition
? " " : "",
364 PartEntry
->PartitionType
,
365 PartEntry
->LogicalPartition
? "" : " ",
372 "%c%c %c %s%-24s%s %6lu %s",
373 (PartEntry
->DriveLetter
== 0) ? '-' : PartEntry
->DriveLetter
,
374 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
375 PartEntry
->BootIndicator
? '*' : ' ',
376 PartEntry
->LogicalPartition
? " " : "",
378 PartEntry
->LogicalPartition
? "" : " ",
384 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
385 List
->CurrentPartition
== PartEntry
) ?
386 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
387 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
389 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
391 FillConsoleOutputCharacterA(StdOutput
,
399 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
401 FillConsoleOutputAttribute(StdOutput
,
409 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
411 WriteConsoleOutputCharacterA(StdOutput
,
413 min(strlen(LineBuffer
), Width
),
424 IN PPARTLIST_UI ListUi
,
425 IN PDISKENTRY DiskEntry
)
427 // PPARTLIST List = ListUi->List;
428 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
429 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
430 CHAR LineBuffer
[128];
435 ULARGE_INTEGER DiskSize
;
438 Width
= ListUi
->Right
- ListUi
->Left
- 1;
439 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
441 coPos
.X
= ListUi
->Left
+ 1;
442 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
444 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
445 if (DiskSize
.QuadPart
>= 10 * GB
) /* 10 GB */
447 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, GB
);
448 Unit
= MUIGetString(STRING_GB
);
452 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, MB
);
453 if (DiskSize
.QuadPart
== 0)
454 DiskSize
.QuadPart
= 1;
455 Unit
= MUIGetString(STRING_MB
);
458 if (DiskEntry
->DriverName
.Length
> 0)
461 MUIGetString(STRING_HDINFOPARTSELECT_1
),
464 DiskEntry
->DiskNumber
,
468 &DiskEntry
->DriverName
,
469 DiskEntry
->NoMbr
? "GPT" : "MBR");
474 MUIGetString(STRING_HDINFOPARTSELECT_2
),
477 DiskEntry
->DiskNumber
,
481 DiskEntry
->NoMbr
? "GPT" : "MBR");
484 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
486 FillConsoleOutputAttribute(StdOutput
,
487 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
492 FillConsoleOutputCharacterA(StdOutput
,
500 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
502 WriteConsoleOutputCharacterA(StdOutput
,
504 min((USHORT
)strlen(LineBuffer
), Width
- 2),
511 /* Print separator line */
512 PrintEmptyLine(ListUi
);
514 /* Print partition lines */
515 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
516 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
518 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
520 PrintPartitionData(ListUi
,
524 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
526 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
527 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
529 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
531 PrintPartitionData(ListUi
,
535 LogicalEntry
= LogicalEntry
->Flink
;
539 PrimaryEntry
= PrimaryEntry
->Flink
;
542 /* Print separator line */
543 PrintEmptyLine(ListUi
);
548 IN PPARTLIST_UI ListUi
)
550 PPARTLIST List
= ListUi
->List
;
551 PLIST_ENTRY Entry
, Entry2
;
552 PDISKENTRY DiskEntry
;
553 PPARTENTRY PartEntry
= NULL
;
557 SHORT CurrentDiskLine
;
558 SHORT CurrentPartLine
;
560 BOOLEAN CurrentPartLineFound
= FALSE
;
561 BOOLEAN CurrentDiskLineFound
= FALSE
;
563 /* Calculate the line of the current disk and partition */
568 Entry
= List
->DiskListHead
.Flink
;
569 while (Entry
!= &List
->DiskListHead
)
571 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
574 if (CurrentPartLineFound
== FALSE
)
576 CurrentPartLine
+= 2;
579 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
580 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
582 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
583 if (PartEntry
== List
->CurrentPartition
)
585 CurrentPartLineFound
= TRUE
;
588 Entry2
= Entry2
->Flink
;
589 if (CurrentPartLineFound
== FALSE
)
597 if (CurrentPartLineFound
== FALSE
)
599 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
600 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
602 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
603 if (PartEntry
== List
->CurrentPartition
)
605 CurrentPartLineFound
= TRUE
;
608 Entry2
= Entry2
->Flink
;
609 if (CurrentPartLineFound
== FALSE
)
618 if (DiskEntry
== List
->CurrentDisk
)
620 CurrentDiskLineFound
= TRUE
;
623 Entry
= Entry
->Flink
;
624 if (Entry
!= &List
->DiskListHead
)
626 if (CurrentDiskLineFound
== FALSE
)
629 CurrentDiskLine
= CurrentPartLine
;
640 /* If it possible, make the disk name visible */
641 if (CurrentPartLine
< ListUi
->Offset
)
643 ListUi
->Offset
= CurrentPartLine
;
645 else if (CurrentPartLine
- ListUi
->Offset
> ListUi
->Bottom
- ListUi
->Top
- 2)
647 ListUi
->Offset
= CurrentPartLine
- (ListUi
->Bottom
- ListUi
->Top
- 2);
650 if (CurrentDiskLine
< ListUi
->Offset
&& CurrentPartLine
- CurrentDiskLine
< ListUi
->Bottom
- ListUi
->Top
- 2)
652 ListUi
->Offset
= CurrentDiskLine
;
655 /* Draw upper left corner */
656 coPos
.X
= ListUi
->Left
;
657 coPos
.Y
= ListUi
->Top
;
658 FillConsoleOutputCharacterA(StdOutput
,
664 /* Draw upper edge */
665 coPos
.X
= ListUi
->Left
+ 1;
666 coPos
.Y
= ListUi
->Top
;
667 if (ListUi
->Offset
== 0)
669 FillConsoleOutputCharacterA(StdOutput
,
671 ListUi
->Right
- ListUi
->Left
- 1,
677 FillConsoleOutputCharacterA(StdOutput
,
679 ListUi
->Right
- ListUi
->Left
- 5,
682 coPos
.X
= ListUi
->Right
- 5;
683 WriteConsoleOutputCharacterA(StdOutput
,
688 coPos
.X
= ListUi
->Right
- 2;
689 FillConsoleOutputCharacterA(StdOutput
,
696 /* Draw upper right corner */
697 coPos
.X
= ListUi
->Right
;
698 coPos
.Y
= ListUi
->Top
;
699 FillConsoleOutputCharacterA(StdOutput
,
705 /* Draw left and right edge */
706 for (i
= ListUi
->Top
+ 1; i
< ListUi
->Bottom
; i
++)
708 coPos
.X
= ListUi
->Left
;
710 FillConsoleOutputCharacterA(StdOutput
,
716 coPos
.X
= ListUi
->Right
;
717 FillConsoleOutputCharacterA(StdOutput
,
724 /* Draw lower left corner */
725 coPos
.X
= ListUi
->Left
;
726 coPos
.Y
= ListUi
->Bottom
;
727 FillConsoleOutputCharacterA(StdOutput
,
733 /* Draw lower edge */
734 coPos
.X
= ListUi
->Left
+ 1;
735 coPos
.Y
= ListUi
->Bottom
;
736 if (LastLine
- ListUi
->Offset
<= ListUi
->Bottom
- ListUi
->Top
- 2)
738 FillConsoleOutputCharacterA(StdOutput
,
740 ListUi
->Right
- ListUi
->Left
- 1,
746 FillConsoleOutputCharacterA(StdOutput
,
748 ListUi
->Right
- ListUi
->Left
- 5,
751 coPos
.X
= ListUi
->Right
- 5;
752 WriteConsoleOutputCharacterA(StdOutput
,
753 "(\x19)", // "(down)"
757 coPos
.X
= ListUi
->Right
- 2;
758 FillConsoleOutputCharacterA(StdOutput
,
765 /* Draw lower right corner */
766 coPos
.X
= ListUi
->Right
;
767 coPos
.Y
= ListUi
->Bottom
;
768 FillConsoleOutputCharacterA(StdOutput
,
774 /* print list entries */
775 ListUi
->Line
= - ListUi
->Offset
;
777 Entry
= List
->DiskListHead
.Flink
;
778 while (Entry
!= &List
->DiskListHead
)
780 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
782 /* Print disk entry */
783 PrintDiskData(ListUi
, DiskEntry
);
785 Entry
= Entry
->Flink
;
790 ScrollDownPartitionList(
791 IN PPARTLIST_UI ListUi
)
793 if (GetNextPartition(ListUi
->List
))
794 DrawPartitionList(ListUi
);
798 ScrollUpPartitionList(
799 IN PPARTLIST_UI ListUi
)
801 if (GetPrevPartition(ListUi
->List
))
802 DrawPartitionList(ListUi
);