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
>= 10737418240) /* 10 GB */
297 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
298 Unit
= MUIGetString(STRING_GB
);
302 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
304 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
305 Unit
= MUIGetString(STRING_MB
);
309 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
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
>= 10737418240) /* 10 GB */
340 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1073741824);
341 Unit
= MUIGetString(STRING_GB
);
345 if (PartSize
.QuadPart
>= 10485760) /* 10 MB */
347 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1048576);
348 Unit
= MUIGetString(STRING_MB
);
352 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, 1024);
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
>= 10737418240) /* 10 GB */
447 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1073741824);
448 Unit
= MUIGetString(STRING_GB
);
452 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, 1048576);
453 if (DiskSize
.QuadPart
== 0)
454 DiskSize
.QuadPart
= 1;
455 Unit
= MUIGetString(STRING_MB
);
458 if (DiskEntry
->DriverName
.Length
> 0)
461 MUIGetString(STRING_HDINFOPARTSELECT
),
464 DiskEntry
->DiskNumber
,
468 DiskEntry
->DriverName
.Buffer
);
473 MUIGetString(STRING_HDDINFOUNK6
),
476 DiskEntry
->DiskNumber
,
482 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
484 FillConsoleOutputAttribute(StdOutput
,
485 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
490 FillConsoleOutputCharacterA(StdOutput
,
498 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
500 WriteConsoleOutputCharacterA(StdOutput
,
502 min((USHORT
)strlen(LineBuffer
), Width
- 2),
509 /* Print separator line */
510 PrintEmptyLine(ListUi
);
512 /* Print partition lines */
513 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
514 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
516 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
518 PrintPartitionData(ListUi
,
522 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
524 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
525 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
527 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
529 PrintPartitionData(ListUi
,
533 LogicalEntry
= LogicalEntry
->Flink
;
537 PrimaryEntry
= PrimaryEntry
->Flink
;
540 /* Print separator line */
541 PrintEmptyLine(ListUi
);
546 IN PPARTLIST_UI ListUi
)
548 PPARTLIST List
= ListUi
->List
;
549 PLIST_ENTRY Entry
, Entry2
;
550 PDISKENTRY DiskEntry
;
551 PPARTENTRY PartEntry
= NULL
;
555 SHORT CurrentDiskLine
;
556 SHORT CurrentPartLine
;
558 BOOLEAN CurrentPartLineFound
= FALSE
;
559 BOOLEAN CurrentDiskLineFound
= FALSE
;
561 /* Calculate the line of the current disk and partition */
566 Entry
= List
->DiskListHead
.Flink
;
567 while (Entry
!= &List
->DiskListHead
)
569 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
572 if (CurrentPartLineFound
== FALSE
)
574 CurrentPartLine
+= 2;
577 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
578 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
580 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
581 if (PartEntry
== List
->CurrentPartition
)
583 CurrentPartLineFound
= TRUE
;
586 Entry2
= Entry2
->Flink
;
587 if (CurrentPartLineFound
== FALSE
)
595 if (CurrentPartLineFound
== FALSE
)
597 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
598 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
600 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
601 if (PartEntry
== List
->CurrentPartition
)
603 CurrentPartLineFound
= TRUE
;
606 Entry2
= Entry2
->Flink
;
607 if (CurrentPartLineFound
== FALSE
)
616 if (DiskEntry
== List
->CurrentDisk
)
618 CurrentDiskLineFound
= TRUE
;
621 Entry
= Entry
->Flink
;
622 if (Entry
!= &List
->DiskListHead
)
624 if (CurrentDiskLineFound
== FALSE
)
627 CurrentDiskLine
= CurrentPartLine
;
638 /* If it possible, make the disk name visible */
639 if (CurrentPartLine
< ListUi
->Offset
)
641 ListUi
->Offset
= CurrentPartLine
;
643 else if (CurrentPartLine
- ListUi
->Offset
> ListUi
->Bottom
- ListUi
->Top
- 2)
645 ListUi
->Offset
= CurrentPartLine
- (ListUi
->Bottom
- ListUi
->Top
- 2);
648 if (CurrentDiskLine
< ListUi
->Offset
&& CurrentPartLine
- CurrentDiskLine
< ListUi
->Bottom
- ListUi
->Top
- 2)
650 ListUi
->Offset
= CurrentDiskLine
;
653 /* Draw upper left corner */
654 coPos
.X
= ListUi
->Left
;
655 coPos
.Y
= ListUi
->Top
;
656 FillConsoleOutputCharacterA(StdOutput
,
662 /* Draw upper edge */
663 coPos
.X
= ListUi
->Left
+ 1;
664 coPos
.Y
= ListUi
->Top
;
665 if (ListUi
->Offset
== 0)
667 FillConsoleOutputCharacterA(StdOutput
,
669 ListUi
->Right
- ListUi
->Left
- 1,
675 FillConsoleOutputCharacterA(StdOutput
,
677 ListUi
->Right
- ListUi
->Left
- 5,
680 coPos
.X
= ListUi
->Right
- 5;
681 WriteConsoleOutputCharacterA(StdOutput
,
686 coPos
.X
= ListUi
->Right
- 2;
687 FillConsoleOutputCharacterA(StdOutput
,
694 /* Draw upper right corner */
695 coPos
.X
= ListUi
->Right
;
696 coPos
.Y
= ListUi
->Top
;
697 FillConsoleOutputCharacterA(StdOutput
,
703 /* Draw left and right edge */
704 for (i
= ListUi
->Top
+ 1; i
< ListUi
->Bottom
; i
++)
706 coPos
.X
= ListUi
->Left
;
708 FillConsoleOutputCharacterA(StdOutput
,
714 coPos
.X
= ListUi
->Right
;
715 FillConsoleOutputCharacterA(StdOutput
,
722 /* Draw lower left corner */
723 coPos
.X
= ListUi
->Left
;
724 coPos
.Y
= ListUi
->Bottom
;
725 FillConsoleOutputCharacterA(StdOutput
,
731 /* Draw lower edge */
732 coPos
.X
= ListUi
->Left
+ 1;
733 coPos
.Y
= ListUi
->Bottom
;
734 if (LastLine
- ListUi
->Offset
<= ListUi
->Bottom
- ListUi
->Top
- 2)
736 FillConsoleOutputCharacterA(StdOutput
,
738 ListUi
->Right
- ListUi
->Left
- 1,
744 FillConsoleOutputCharacterA(StdOutput
,
746 ListUi
->Right
- ListUi
->Left
- 5,
749 coPos
.X
= ListUi
->Right
- 5;
750 WriteConsoleOutputCharacterA(StdOutput
,
751 "(\x19)", // "(down)"
755 coPos
.X
= ListUi
->Right
- 2;
756 FillConsoleOutputCharacterA(StdOutput
,
763 /* Draw lower right corner */
764 coPos
.X
= ListUi
->Right
;
765 coPos
.Y
= ListUi
->Bottom
;
766 FillConsoleOutputCharacterA(StdOutput
,
772 /* print list entries */
773 ListUi
->Line
= - ListUi
->Offset
;
775 Entry
= List
->DiskListHead
.Flink
;
776 while (Entry
!= &List
->DiskListHead
)
778 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
780 /* Print disk entry */
781 PrintDiskData(ListUi
, DiskEntry
);
783 Entry
= Entry
->Flink
;
788 ScrollDownPartitionList(
789 IN PPARTLIST_UI ListUi
)
791 if (GetNextPartition(ListUi
->List
))
792 DrawPartitionList(ListUi
);
796 ScrollUpPartitionList(
797 IN PPARTLIST_UI ListUi
)
799 if (GetPrevPartition(ListUi
->List
))
800 DrawPartitionList(ListUi
);