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 **********************************************/
34 GetPartTypeStringFromPartitionType(
35 IN UCHAR partitionType
,
36 OUT PCHAR strPartType
,
39 /* Determine partition type */
41 if (IsContainerPartition(partitionType
))
43 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_EXTENDED_PARTITION
));
45 else if (partitionType
== PARTITION_ENTRY_UNUSED
)
47 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNUSED
));
53 /* Do the table lookup */
54 for (i
= 0; i
< ARRAYSIZE(PartitionTypes
); i
++)
56 if (partitionType
== PartitionTypes
[i
].Type
)
58 RtlStringCchCopyA(strPartType
, cchPartType
, PartitionTypes
[i
].Description
);
63 /* We are here because the partition type is unknown */
64 RtlStringCchCopyA(strPartType
, cchPartType
, MUIGetString(STRING_FORMATUNKNOWN
));
69 /* FUNCTIONS ****************************************************************/
73 IN OUT PPARTLIST_UI ListUi
,
81 // ListUi->FirstShown = NULL;
82 // ListUi->LastShown = NULL;
86 ListUi
->Right
= Right
;
87 ListUi
->Bottom
= Bottom
;
92 // ListUi->Redraw = TRUE;
98 IN PPARTLIST_UI ListUi
)
105 Width
= ListUi
->Right
- ListUi
->Left
- 1;
106 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
108 coPos
.X
= ListUi
->Left
+ 1;
109 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
111 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
113 FillConsoleOutputAttribute(StdOutput
,
114 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
119 FillConsoleOutputCharacterA(StdOutput
,
132 IN PPARTLIST_UI ListUi
,
133 IN PDISKENTRY DiskEntry
,
134 IN PPARTENTRY PartEntry
)
136 PPARTLIST List
= ListUi
->List
;
137 CHAR LineBuffer
[128];
142 LARGE_INTEGER PartSize
;
145 CHAR PartTypeString
[32];
146 PCHAR PartType
= PartTypeString
;
148 Width
= ListUi
->Right
- ListUi
->Left
- 1;
149 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
151 coPos
.X
= ListUi
->Left
+ 1;
152 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
154 /* Get the partition size */
155 PartSize
.QuadPart
= PartEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
157 if (PartSize
.QuadPart
>= 10 * GB
) /* 10 GB */
159 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, GB
);
160 Unit
= MUIGetString(STRING_GB
);
164 if (PartSize
.QuadPart
>= 10 * MB
) /* 10 MB */
166 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, MB
);
167 Unit
= MUIGetString(STRING_MB
);
171 PartSize
.QuadPart
= RoundingDivide(PartSize
.QuadPart
, KB
);
172 Unit
= MUIGetString(STRING_KB
);
175 if (PartEntry
->IsPartitioned
== FALSE
)
178 MUIGetString(STRING_UNPSPACE
),
179 PartEntry
->LogicalPartition
? " " : "",
180 PartEntry
->LogicalPartition
? "" : " ",
186 /* Determine partition type */
187 PartTypeString
[0] = '\0';
188 if (PartEntry
->New
!= FALSE
)
190 PartType
= MUIGetString(STRING_UNFORMATTED
);
192 else if (PartEntry
->IsPartitioned
!= FALSE
)
194 GetPartTypeStringFromPartitionType(PartEntry
->PartitionType
,
196 ARRAYSIZE(PartTypeString
));
197 PartType
= PartTypeString
;
200 if (strcmp(PartType
, MUIGetString(STRING_FORMATUNKNOWN
)) == 0)
203 MUIGetString(STRING_HDDINFOUNK5
),
204 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
205 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
206 PartEntry
->BootIndicator
? '*' : ' ',
207 PartEntry
->LogicalPartition
? " " : "",
208 PartEntry
->PartitionType
,
209 PartEntry
->LogicalPartition
? "" : " ",
216 "%c%c %c %s%-24s%s %6lu %s",
217 (PartEntry
->DriveLetter
== 0) ? '-' : (CHAR
)PartEntry
->DriveLetter
,
218 (PartEntry
->DriveLetter
== 0) ? '-' : ':',
219 PartEntry
->BootIndicator
? '*' : ' ',
220 PartEntry
->LogicalPartition
? " " : "",
222 PartEntry
->LogicalPartition
? "" : " ",
228 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
229 List
->CurrentPartition
== PartEntry
) ?
230 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
231 FOREGROUND_WHITE
| BACKGROUND_BLUE
;
233 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
235 FillConsoleOutputCharacterA(StdOutput
,
243 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
245 FillConsoleOutputAttribute(StdOutput
,
253 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
255 WriteConsoleOutputCharacterA(StdOutput
,
257 min(strlen(LineBuffer
), Width
),
268 IN PPARTLIST_UI ListUi
,
269 IN PDISKENTRY DiskEntry
)
271 // PPARTLIST List = ListUi->List;
272 PPARTENTRY PrimaryPartEntry
, LogicalPartEntry
;
273 PLIST_ENTRY PrimaryEntry
, LogicalEntry
;
274 CHAR LineBuffer
[128];
279 ULARGE_INTEGER DiskSize
;
282 Width
= ListUi
->Right
- ListUi
->Left
- 1;
283 Height
= ListUi
->Bottom
- ListUi
->Top
- 2;
285 coPos
.X
= ListUi
->Left
+ 1;
286 coPos
.Y
= ListUi
->Top
+ 1 + ListUi
->Line
;
288 DiskSize
.QuadPart
= DiskEntry
->SectorCount
.QuadPart
* DiskEntry
->BytesPerSector
;
289 if (DiskSize
.QuadPart
>= 10 * GB
) /* 10 GB */
291 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, GB
);
292 Unit
= MUIGetString(STRING_GB
);
296 DiskSize
.QuadPart
= RoundingDivide(DiskSize
.QuadPart
, MB
);
297 if (DiskSize
.QuadPart
== 0)
298 DiskSize
.QuadPart
= 1;
299 Unit
= MUIGetString(STRING_MB
);
303 // FIXME: We *MUST* use TXTSETUP.SIF strings from section "DiskDriverMap" !!
305 if (DiskEntry
->DriverName
.Length
> 0)
308 MUIGetString(STRING_HDINFOPARTSELECT_1
),
311 DiskEntry
->DiskNumber
,
315 &DiskEntry
->DriverName
,
316 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
317 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
323 MUIGetString(STRING_HDINFOPARTSELECT_2
),
326 DiskEntry
->DiskNumber
,
330 DiskEntry
->DiskStyle
== PARTITION_STYLE_MBR
? "MBR" :
331 DiskEntry
->DiskStyle
== PARTITION_STYLE_GPT
? "GPT" :
335 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
337 FillConsoleOutputAttribute(StdOutput
,
338 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
343 FillConsoleOutputCharacterA(StdOutput
,
351 if (ListUi
->Line
>= 0 && ListUi
->Line
<= Height
)
353 WriteConsoleOutputCharacterA(StdOutput
,
355 min((USHORT
)strlen(LineBuffer
), Width
- 2),
362 /* Print separator line */
363 PrintEmptyLine(ListUi
);
365 /* Print partition lines */
366 PrimaryEntry
= DiskEntry
->PrimaryPartListHead
.Flink
;
367 while (PrimaryEntry
!= &DiskEntry
->PrimaryPartListHead
)
369 PrimaryPartEntry
= CONTAINING_RECORD(PrimaryEntry
, PARTENTRY
, ListEntry
);
371 PrintPartitionData(ListUi
,
375 if (IsContainerPartition(PrimaryPartEntry
->PartitionType
))
377 LogicalEntry
= DiskEntry
->LogicalPartListHead
.Flink
;
378 while (LogicalEntry
!= &DiskEntry
->LogicalPartListHead
)
380 LogicalPartEntry
= CONTAINING_RECORD(LogicalEntry
, PARTENTRY
, ListEntry
);
382 PrintPartitionData(ListUi
,
386 LogicalEntry
= LogicalEntry
->Flink
;
390 PrimaryEntry
= PrimaryEntry
->Flink
;
393 /* Print separator line */
394 PrintEmptyLine(ListUi
);
399 IN PPARTLIST_UI ListUi
)
401 PPARTLIST List
= ListUi
->List
;
402 PLIST_ENTRY Entry
, Entry2
;
403 PDISKENTRY DiskEntry
;
404 PPARTENTRY PartEntry
= NULL
;
408 SHORT CurrentDiskLine
;
409 SHORT CurrentPartLine
;
411 BOOLEAN CurrentPartLineFound
= FALSE
;
412 BOOLEAN CurrentDiskLineFound
= FALSE
;
414 /* Calculate the line of the current disk and partition */
419 Entry
= List
->DiskListHead
.Flink
;
420 while (Entry
!= &List
->DiskListHead
)
422 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
425 if (CurrentPartLineFound
== FALSE
)
427 CurrentPartLine
+= 2;
430 Entry2
= DiskEntry
->PrimaryPartListHead
.Flink
;
431 while (Entry2
!= &DiskEntry
->PrimaryPartListHead
)
433 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
434 if (PartEntry
== List
->CurrentPartition
)
436 CurrentPartLineFound
= TRUE
;
439 Entry2
= Entry2
->Flink
;
440 if (CurrentPartLineFound
== FALSE
)
448 if (CurrentPartLineFound
== FALSE
)
450 Entry2
= DiskEntry
->LogicalPartListHead
.Flink
;
451 while (Entry2
!= &DiskEntry
->LogicalPartListHead
)
453 PartEntry
= CONTAINING_RECORD(Entry2
, PARTENTRY
, ListEntry
);
454 if (PartEntry
== List
->CurrentPartition
)
456 CurrentPartLineFound
= TRUE
;
459 Entry2
= Entry2
->Flink
;
460 if (CurrentPartLineFound
== FALSE
)
469 if (DiskEntry
== List
->CurrentDisk
)
471 CurrentDiskLineFound
= TRUE
;
474 Entry
= Entry
->Flink
;
475 if (Entry
!= &List
->DiskListHead
)
477 if (CurrentDiskLineFound
== FALSE
)
480 CurrentDiskLine
= CurrentPartLine
;
491 /* If it possible, make the disk name visible */
492 if (CurrentPartLine
< ListUi
->Offset
)
494 ListUi
->Offset
= CurrentPartLine
;
496 else if (CurrentPartLine
- ListUi
->Offset
> ListUi
->Bottom
- ListUi
->Top
- 2)
498 ListUi
->Offset
= CurrentPartLine
- (ListUi
->Bottom
- ListUi
->Top
- 2);
501 if (CurrentDiskLine
< ListUi
->Offset
&& CurrentPartLine
- CurrentDiskLine
< ListUi
->Bottom
- ListUi
->Top
- 2)
503 ListUi
->Offset
= CurrentDiskLine
;
506 /* Draw upper left corner */
507 coPos
.X
= ListUi
->Left
;
508 coPos
.Y
= ListUi
->Top
;
509 FillConsoleOutputCharacterA(StdOutput
,
515 /* Draw upper edge */
516 coPos
.X
= ListUi
->Left
+ 1;
517 coPos
.Y
= ListUi
->Top
;
518 if (ListUi
->Offset
== 0)
520 FillConsoleOutputCharacterA(StdOutput
,
522 ListUi
->Right
- ListUi
->Left
- 1,
528 FillConsoleOutputCharacterA(StdOutput
,
530 ListUi
->Right
- ListUi
->Left
- 5,
533 coPos
.X
= ListUi
->Right
- 5;
534 WriteConsoleOutputCharacterA(StdOutput
,
539 coPos
.X
= ListUi
->Right
- 2;
540 FillConsoleOutputCharacterA(StdOutput
,
547 /* Draw upper right corner */
548 coPos
.X
= ListUi
->Right
;
549 coPos
.Y
= ListUi
->Top
;
550 FillConsoleOutputCharacterA(StdOutput
,
556 /* Draw left and right edge */
557 for (i
= ListUi
->Top
+ 1; i
< ListUi
->Bottom
; i
++)
559 coPos
.X
= ListUi
->Left
;
561 FillConsoleOutputCharacterA(StdOutput
,
567 coPos
.X
= ListUi
->Right
;
568 FillConsoleOutputCharacterA(StdOutput
,
575 /* Draw lower left corner */
576 coPos
.X
= ListUi
->Left
;
577 coPos
.Y
= ListUi
->Bottom
;
578 FillConsoleOutputCharacterA(StdOutput
,
584 /* Draw lower edge */
585 coPos
.X
= ListUi
->Left
+ 1;
586 coPos
.Y
= ListUi
->Bottom
;
587 if (LastLine
- ListUi
->Offset
<= ListUi
->Bottom
- ListUi
->Top
- 2)
589 FillConsoleOutputCharacterA(StdOutput
,
591 ListUi
->Right
- ListUi
->Left
- 1,
597 FillConsoleOutputCharacterA(StdOutput
,
599 ListUi
->Right
- ListUi
->Left
- 5,
602 coPos
.X
= ListUi
->Right
- 5;
603 WriteConsoleOutputCharacterA(StdOutput
,
604 "(\x19)", // "(down)"
608 coPos
.X
= ListUi
->Right
- 2;
609 FillConsoleOutputCharacterA(StdOutput
,
616 /* Draw lower right corner */
617 coPos
.X
= ListUi
->Right
;
618 coPos
.Y
= ListUi
->Bottom
;
619 FillConsoleOutputCharacterA(StdOutput
,
625 /* print list entries */
626 ListUi
->Line
= - ListUi
->Offset
;
628 Entry
= List
->DiskListHead
.Flink
;
629 while (Entry
!= &List
->DiskListHead
)
631 DiskEntry
= CONTAINING_RECORD(Entry
, DISKENTRY
, ListEntry
);
633 /* Print disk entry */
634 PrintDiskData(ListUi
, DiskEntry
);
636 Entry
= Entry
->Flink
;
641 ScrollDownPartitionList(
642 IN PPARTLIST_UI ListUi
)
644 if (GetNextPartition(ListUi
->List
))
645 DrawPartitionList(ListUi
);
649 ScrollUpPartitionList(
650 IN PPARTLIST_UI ListUi
)
652 if (GetPrevPartition(ListUi
->List
))
653 DrawPartitionList(ListUi
);