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.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/partlist.c
23 * PURPOSE: Partition list functions
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
32 /* HELPERS FOR PARTITION TYPES **********************************************/
35 GetPartTypeStringFromPartitionType(
36 IN UCHAR partitionType
,
37 OUT PCHAR strPartType
,
40 /* Determine partition type */
42 if (IsContainerPartition(partitionType
))
44 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_EXTENDED_PARTITION
));
46 else if (partitionType
== PARTITION_ENTRY_UNUSED
)
48 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNUSED
));
54 /* Do the table lookup */
55 for (i
= 0; i
< ARRAYSIZE(PartitionTypes
); i
++)
57 if (partitionType
== PartitionTypes
[i
].Type
)
59 RtlStringCchCopyA(strPartType
, cchPartType
, PartitionTypes
[i
].Description
);
64 /* We are here because the partition type is unknown */
65 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNKNOWN
));
70 /* FUNCTIONS ****************************************************************/
74 IN OUT PPARTLIST_UI ListUi
,
76 IN PPARTENTRY CurrentEntry OPTIONAL
,
83 // ListUi->FirstShown = NULL;
84 // ListUi->LastShown = NULL;
88 ListUi
->Right
= Right
;
89 ListUi
->Bottom
= Bottom
;
94 // ListUi->Redraw = TRUE;
96 /* Search for first usable disk and partition */
99 ListUi
->CurrentDisk
= NULL
;
100 ListUi
->CurrentPartition
= NULL
;
102 if (!IsListEmpty(&List
->DiskListHead
))
104 ListUi
->CurrentDisk
= CONTAINING_RECORD(List
->DiskListHead
.Flink
,
105 DISKENTRY
, ListEntry
);
107 if (!IsListEmpty(&ListUi
->CurrentDisk
->PrimaryPartListHead
))
109 ListUi
->CurrentPartition
= CONTAINING_RECORD(ListUi
->CurrentDisk
->PrimaryPartListHead
.Flink
,
110 PARTENTRY
, ListEntry
);
117 * The CurrentEntry must belong to the associated partition list,
118 * and the latter must therefore not be empty.
120 ASSERT(!IsListEmpty(&List
->DiskListHead
));
121 ASSERT(CurrentEntry
->DiskEntry
->PartList
== List
);
123 ListUi
->CurrentPartition
= CurrentEntry
;
124 ListUi
->CurrentDisk
= CurrentEntry
->DiskEntry
;
131 IN PPARTLIST_UI ListUi
)
138 Width
= ListUi
->Right
- ListUi
->Left
- 1;
139 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
141 coPos
.X
= ListUi
->Left
+ 1;
142 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
144 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
146 FillConsoleOutputAttribute(StdOutput
,
147 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
152 FillConsoleOutputCharacterA(StdOutput
,
165 IN PPARTLIST_UI ListUi
,
166 IN PDISKENTRY DiskEntry
,
167 IN PPARTENTRY PartEntry
)
169 CHAR LineBuffer
[128];
174 LARGE_INTEGER PartSize
;
177 CHAR PartTypeString
[32];
178 PCHAR PartType
= PartTypeString
;
180 Width
= ListUi
->Right
- ListUi
->Left
- 1;
181 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
183 coPos
.X
= ListUi
->Left
+ 1;
184 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
186 /* Get the partition size */
187 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
189 if (PartSize
.QuadPart
>= 10 * GB
) /* 10 GB */
191 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, GB
);
192 Unit
= MUIGetString(STRING_GB
);
196 if (PartSize
.QuadPart
>= 10 * MB
) /* 10 MB */
198 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, MB
);
199 Unit
= MUIGetString(STRING_MB
);
203 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, KB
);
204 Unit
= MUIGetString(STRING_KB
);
207 if (PartEntry
->IsPartitioned
== FALSE
)
210 MUIGetString(STRING_UNPSPACE
),
211 PartEntry
->LogicalPartition
? " " : "",
212 PartEntry
->LogicalPartition
? "" : " ",
218 /* Determine partition type */
219 PartTypeString
[0] = '\0';
220 if (PartEntry
->New
!= FALSE
)
222 PartType
= MUIGetString(STRING_UNFORMATTED
);
224 else if (PartEntry
->IsPartitioned
!= FALSE
)
226 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
228 ARRAYSIZE(PartTypeString
));
229 PartType
= PartTypeString
;
232 if (strcmp(PartType
, MUIGetString(STRING_FORMATUNKNOWN
)) == 0)
235 MUIGetString(STRING_HDDINFOUNK5
),
236 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
237 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
238 PartEntry
->BootIndicator
? '*' : ' ',
239 PartEntry
->LogicalPartition
? " " : "",
240 PartEntry
->PartitionType
,
241 PartEntry
->LogicalPartition
? "" : " ",
248 "%c%c %c %s%-24s%s %6lu %s",
249 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
250 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
251 PartEntry
->BootIndicator
? '*' : ' ',
252 PartEntry
->LogicalPartition
? " " : "",
254 PartEntry
->LogicalPartition
? "" : " ",
260 Attribute
= (ListUi
->CurrentDisk
== DiskEntry
&&
261 ListUi
->CurrentPartition
== PartEntry
) ?
262 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
263 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
265 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
267 FillConsoleOutputCharacterA(StdOutput
,
275 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
277 FillConsoleOutputAttribute(StdOutput
,
285 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
287 WriteConsoleOutputCharacterA(StdOutput
,
289 min(strlen(LineBuffer
), Width
),
300 IN PPARTLIST_UI ListUi
,
301 IN PDISKENTRY DiskEntry
)
303 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
304 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
305 CHAR LineBuffer
[128];
310 ULARGE_INTEGER DiskSize
;
313 Width
= ListUi
->Right
- ListUi
->Left
- 1;
314 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
316 coPos
.X
= ListUi
->Left
+ 1;
317 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
319 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
320 if (DiskSize
.QuadPart
>= 10 * GB
) /* 10 GB */
322 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, GB
);
323 Unit
= MUIGetString(STRING_GB
);
327 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, MB
);
328 if (DiskSize
.QuadPart
== 0)
329 DiskSize
.QuadPart
= 1;
330 Unit
= MUIGetString(STRING_MB
);
334 // FIXME: We *MUST* use TXTSETUP.SIF strings from section "DiskDriverMap" !!
336 if (DiskEntry
->DriverName
.Length
> 0)
339 MUIGetString(STRING_HDINFOPARTSELECT_1
),
342 DiskEntry
->DiskNumber
,
346 &DiskEntry
->DriverName
,
347 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
348 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
354 MUIGetString(STRING_HDINFOPARTSELECT_2
),
357 DiskEntry
->DiskNumber
,
361 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
362 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
366 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
368 FillConsoleOutputAttribute(StdOutput
,
369 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
374 FillConsoleOutputCharacterA(StdOutput
,
382 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
384 WriteConsoleOutputCharacterA(StdOutput
,
386 min((USHORT
)strlen(LineBuffer
), Width
- 2),
393 /* Print separator line */
394 PrintEmptyLine(ListUi
);
396 /* Print partition lines */
397 for (PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
398 PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
;
399 PrimaryEntry
= PrimaryEntry
->Flink
)
401 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
403 PrintPartitionData(ListUi
,
407 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
409 for (LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
410 LogicalEntry
!= &DiskEntry
->LogicalPartListHead
;
411 LogicalEntry
= LogicalEntry
->Flink
)
413 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
415 PrintPartitionData(ListUi
,
422 /* Print separator line */
423 PrintEmptyLine(ListUi
);
428 IN PPARTLIST_UI ListUi
)
430 PPARTLIST List
= ListUi
->List
;
431 PLIST_ENTRY Entry
, Entry2
;
432 PDISKENTRY DiskEntry
;
433 PPARTENTRY PartEntry
= NULL
;
439 SHORT CurrentDiskLine
;
440 SHORT CurrentPartLine
;
442 BOOLEAN CurrentPartLineFound
= FALSE
;
443 BOOLEAN CurrentDiskLineFound
= FALSE
;
445 Width
= ListUi
->Right
- ListUi
->Left
- 1;
446 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
448 /* Calculate the line of the current disk and partition */
453 for (Entry
= List
->DiskListHead
.Flink
;
454 Entry
!= &List
->DiskListHead
;
455 Entry
= Entry
->Flink
)
457 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
460 if (CurrentPartLineFound
== FALSE
)
462 CurrentPartLine
+= 2;
465 for (Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
466 Entry2
!= &DiskEntry
->PrimaryPartListHead
;
467 Entry2
= Entry2
->Flink
)
469 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
470 if (PartEntry
== ListUi
->CurrentPartition
)
472 CurrentPartLineFound
= TRUE
;
475 if (CurrentPartLineFound
== FALSE
)
483 if (CurrentPartLineFound
== FALSE
)
485 for (Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
486 Entry2
!= &DiskEntry
->LogicalPartListHead
;
487 Entry2
= Entry2
->Flink
)
489 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
490 if (PartEntry
== ListUi
->CurrentPartition
)
492 CurrentPartLineFound
= TRUE
;
495 if (CurrentPartLineFound
== FALSE
)
504 if (DiskEntry
== ListUi
->CurrentDisk
)
506 CurrentDiskLineFound
= TRUE
;
509 if (Entry
->Flink
!= &List
->DiskListHead
)
511 if (CurrentDiskLineFound
== FALSE
)
514 CurrentDiskLine
= CurrentPartLine
;
525 /* If it possible, make the disk name visible */
526 if (CurrentPartLine
< ListUi
->Offset
)
528 ListUi
->Offset
= CurrentPartLine
;
530 else if (CurrentPartLine
- ListUi
->Offset
> Height
)
532 ListUi
->Offset
= CurrentPartLine
- Height
;
535 if (CurrentDiskLine
< ListUi
->Offset
&& CurrentPartLine
- CurrentDiskLine
< Height
)
537 ListUi
->Offset
= CurrentDiskLine
;
540 /* Draw upper left corner */
541 coPos
.X
= ListUi
->Left
;
542 coPos
.Y
= ListUi
->Top
;
543 FillConsoleOutputCharacterA(StdOutput
,
549 /* Draw upper edge */
550 coPos
.X
= ListUi
->Left
+ 1;
551 coPos
.Y
= ListUi
->Top
;
552 if (ListUi
->Offset
== 0)
554 FillConsoleOutputCharacterA(StdOutput
,
562 FillConsoleOutputCharacterA(StdOutput
,
567 coPos
.X
= ListUi
->Right
- 5;
568 WriteConsoleOutputCharacterA(StdOutput
,
573 coPos
.X
= ListUi
->Right
- 2;
574 FillConsoleOutputCharacterA(StdOutput
,
581 /* Draw upper right corner */
582 coPos
.X
= ListUi
->Right
;
583 coPos
.Y
= ListUi
->Top
;
584 FillConsoleOutputCharacterA(StdOutput
,
590 /* Draw left and right edge */
591 for (i
= ListUi
->Top
+ 1; i
< ListUi
->Bottom
; i
++)
593 coPos
.X
= ListUi
->Left
;
595 FillConsoleOutputCharacterA(StdOutput
,
601 coPos
.X
= ListUi
->Right
;
602 FillConsoleOutputCharacterA(StdOutput
,
609 /* Draw lower left corner */
610 coPos
.X
= ListUi
->Left
;
611 coPos
.Y
= ListUi
->Bottom
;
612 FillConsoleOutputCharacterA(StdOutput
,
618 /* Draw lower edge */
619 coPos
.X
= ListUi
->Left
+ 1;
620 coPos
.Y
= ListUi
->Bottom
;
621 if (LastLine
- ListUi
->Offset
<= Height
)
623 FillConsoleOutputCharacterA(StdOutput
,
631 FillConsoleOutputCharacterA(StdOutput
,
636 coPos
.X
= ListUi
->Right
- 5;
637 WriteConsoleOutputCharacterA(StdOutput
,
638 "(\x19)", // "(down)"
642 coPos
.X
= ListUi
->Right
- 2;
643 FillConsoleOutputCharacterA(StdOutput
,
650 /* Draw lower right corner */
651 coPos
.X
= ListUi
->Right
;
652 coPos
.Y
= ListUi
->Bottom
;
653 FillConsoleOutputCharacterA(StdOutput
,
659 /* Print list entries */
660 ListUi
->Line
= -ListUi
->Offset
;
662 for (Entry
= List
->DiskListHead
.Flink
;
663 Entry
!= &List
->DiskListHead
;
664 Entry
= Entry
->Flink
)
666 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
668 /* Print disk entry */
669 PrintDiskData(ListUi
, DiskEntry
);
674 ScrollDownPartitionList(
675 IN PPARTLIST_UI ListUi
)
677 PPARTENTRY NextPart
= GetNextPartition(ListUi
->List
, ListUi
->CurrentPartition
);
680 ListUi
->CurrentPartition
= NextPart
;
681 ListUi
->CurrentDisk
= NextPart
->DiskEntry
;
682 DrawPartitionList(ListUi
);
687 ScrollUpPartitionList(
688 IN PPARTLIST_UI ListUi
)
690 PPARTENTRY PrevPart
= GetPrevPartition(ListUi
->List
, ListUi
->CurrentPartition
);
693 ListUi
->CurrentPartition
= PrevPart
;
694 ListUi
->CurrentDisk
= PrevPart
->DiskEntry
;
695 DrawPartitionList(ListUi
);