Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835/* * ReactOS kernel * Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *//* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS text-mode setup * FILE: base/setup/usetup/partlist.c * PURPOSE: Partition list functions * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) */
#include "usetup.h"
#define NDEBUG#include <debug.h>
/* HELPERS FOR DISK AND PARTITION DESCRIPTIONS ******************************/
VOIDGetPartitionTypeString( IN PPARTENTRY PartEntry, OUT PSTR strBuffer, IN ULONG cchBuffer){ if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED) { RtlStringCchCopyA(strBuffer, cchBuffer, MUIGetString(STRING_FORMATUNUSED)); } else if (IsContainerPartition(PartEntry->PartitionType)) { RtlStringCchCopyA(strBuffer, cchBuffer, MUIGetString(STRING_EXTENDED_PARTITION)); } else { /* Do the table lookup */ PCSTR Description = LookupPartitionTypeString(PartEntry->DiskEntry->DiskStyle, &PartEntry->PartitionType); if (Description) { RtlStringCchCopyA(strBuffer, cchBuffer, Description); return; }
/* We are here because the partition type is unknown */ if (cchBuffer > 0) *strBuffer = '\0'; }
if ((cchBuffer > 0) && (*strBuffer == '\0')) { RtlStringCchPrintfA(strBuffer, cchBuffer, MUIGetString(STRING_PARTTYPE), PartEntry->PartitionType); }}
VOIDPrettifySize1( IN OUT PULONGLONG Size, OUT PCSTR* Unit){ ULONGLONG DiskSize = *Size;
if (DiskSize >= 10 * GB) /* 10 GB */ { DiskSize = RoundingDivide(DiskSize, GB); *Unit = MUIGetString(STRING_GB); } else { DiskSize = RoundingDivide(DiskSize, MB); if (DiskSize == 0) DiskSize = 1; *Unit = MUIGetString(STRING_MB); }
*Size = DiskSize;}
VOIDPrettifySize2( IN OUT PULONGLONG Size, OUT PCSTR* Unit){ ULONGLONG PartSize = *Size;
#if 0 if (PartSize >= 10 * GB) /* 10 GB */ { PartSize = RoundingDivide(PartSize, GB); *Unit = MUIGetString(STRING_GB); } else#endif if (PartSize >= 10 * MB) /* 10 MB */ { PartSize = RoundingDivide(PartSize, MB); *Unit = MUIGetString(STRING_MB); } else { PartSize = RoundingDivide(PartSize, KB); *Unit = MUIGetString(STRING_KB); }
*Size = PartSize;}
VOIDPartitionDescription( IN PPARTENTRY PartEntry, OUT PSTR strBuffer, IN SIZE_T cchBuffer){ PSTR pBuffer = strBuffer; size_t cchBufferSize = cchBuffer; ULONGLONG PartSize; PCSTR Unit; PVOLINFO VolInfo = (PartEntry->Volume ? &PartEntry->Volume->Info : NULL);
/* Get the partition size */ PartSize = GetPartEntrySizeInBytes(PartEntry); PrettifySize2(&PartSize, &Unit);
if (PartEntry->IsPartitioned == FALSE) { /* Unpartitioned space: Just display the description and size */ RtlStringCchPrintfExA(pBuffer, cchBufferSize, &pBuffer, &cchBufferSize, 0, " %s%-.30s", PartEntry->LogicalPartition ? " " : "", // Optional indentation MUIGetString(STRING_UNPSPACE));
RtlStringCchPrintfA(pBuffer, cchBufferSize, "%*s%6I64u %s", 38 - min(strlen(strBuffer), 38), "", // Indentation PartSize, Unit); return; }
//// NOTE: This could be done with the next case.// if ((PartEntry->DiskEntry->DiskStyle == PARTITION_STYLE_MBR) && IsContainerPartition(PartEntry->PartitionType)) { /* Extended partition container: Just display the partition's type and size */ RtlStringCchPrintfExA(pBuffer, cchBufferSize, &pBuffer, &cchBufferSize, 0, " %-.30s", MUIGetString(STRING_EXTENDED_PARTITION));
RtlStringCchPrintfA(pBuffer, cchBufferSize, "%*s%6I64u %s", 38 - min(strlen(strBuffer), 38), "", // Indentation PartSize, Unit); return; }
/* * Not an extended partition container. */
/* Drive letter and partition number */ RtlStringCchPrintfExA(pBuffer, cchBufferSize, &pBuffer, &cchBufferSize, 0, "%c%c %c %s(%lu) ", !(VolInfo && VolInfo->DriveLetter) ? '-' : (CHAR)VolInfo->DriveLetter, !(VolInfo && VolInfo->DriveLetter) ? '-' : ':', PartEntry->BootIndicator ? '*' : ' ', PartEntry->LogicalPartition ? " " : "", // Optional indentation PartEntry->PartitionNumber);
/* * If the volume's file system is recognized, display the volume label * (if any) and the file system name. Otherwise, display the partition * type if it's not a new partition. */ if (VolInfo && IsFormatted(VolInfo)) { size_t cchLabelSize = 0; if (*VolInfo->VolumeLabel) { RtlStringCchPrintfExA(pBuffer, cchBufferSize, &pBuffer, &cchLabelSize, 0, "\"%-.11S\" ", VolInfo->VolumeLabel); cchLabelSize = cchBufferSize - cchLabelSize; // Actual length of the label part. cchBufferSize -= cchLabelSize; // And reset cchBufferSize to what it should be. }
// TODO: Group this part together with the similar one // from below once the strings are in the same encoding... RtlStringCchPrintfExA(pBuffer, cchBufferSize, &pBuffer, &cchBufferSize, 0, "[%-.*S]", /* The minimum length can be at most 11 since * cchLabelSize can be at most == 11 + 3 == 14 */ 25 - min(cchLabelSize, 25), VolInfo->FileSystem); } else { CHAR PartTypeString[32]; PCSTR PartType = PartTypeString;
if (PartEntry->New) { /* Use this description if the partition is new (and thus, not formatted) */ PartType = MUIGetString(STRING_UNFORMATTED); } else { /* If the partition is not new but its file system is not recognized * (or is not formatted), use the partition type description. */ GetPartitionTypeString(PartEntry, PartTypeString, ARRAYSIZE(PartTypeString)); PartType = PartTypeString; } if (!PartType || !*PartType) { PartType = MUIGetString(STRING_FORMATUNKNOWN); }
// TODO: Group this part together with the similar one // from above once the strings are in the same encoding... RtlStringCchPrintfExA(pBuffer, cchBufferSize, &pBuffer, &cchBufferSize, 0, "[%-.*s]", 25, PartType); }
/* Show the remaining free space only if a FS is mounted */ // FIXME: We don't support that yet!#if 0 if (VolInfo && *VolInfo->FileSystem) { RtlStringCchPrintfA(pBuffer, cchBufferSize, "%*s%6I64u %s (%6I64u %s %s)", 38 - min(strlen(strBuffer), 38), "", // Indentation PartSize, Unit, PartFreeSize, Unit, "free"); } else#endif { RtlStringCchPrintfA(pBuffer, cchBufferSize, "%*s%6I64u %s", 38 - min(strlen(strBuffer), 38), "", // Indentation PartSize, Unit); }}
VOIDDiskDescription( IN PDISKENTRY DiskEntry, OUT PSTR strBuffer, IN SIZE_T cchBuffer){ ULONGLONG DiskSize; PCSTR Unit;
/* Get the disk size */ DiskSize = GetDiskSizeInBytes(DiskEntry); PrettifySize1(&DiskSize, &Unit);
// // FIXME: We *MUST* use TXTSETUP.SIF strings from section "DiskDriverMap" !! // if (DiskEntry->DriverName.Length > 0) { RtlStringCchPrintfA(strBuffer, cchBuffer, MUIGetString(STRING_HDDINFO1), DiskSize, Unit, DiskEntry->DiskNumber, DiskEntry->Port, DiskEntry->Bus, DiskEntry->Id, &DiskEntry->DriverName, DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" : DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" : "RAW"); } else { RtlStringCchPrintfA(strBuffer, cchBuffer, MUIGetString(STRING_HDDINFO2), DiskSize, Unit, DiskEntry->DiskNumber, DiskEntry->Port, DiskEntry->Bus, DiskEntry->Id, DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" : DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" : "RAW"); }}
/* FUNCTIONS ****************************************************************/
VOIDInitPartitionListUi( IN OUT PPARTLIST_UI ListUi, IN PPARTLIST List, IN PPARTENTRY CurrentEntry OPTIONAL, IN SHORT Left, IN SHORT Top, IN SHORT Right, IN SHORT Bottom){ ListUi->List = List; // ListUi->FirstShown = NULL; // ListUi->LastShown = NULL;
ListUi->Left = Left; ListUi->Top = Top; ListUi->Right = Right; ListUi->Bottom = Bottom;
ListUi->Line = 0; ListUi->Offset = 0;
// ListUi->Redraw = TRUE;
/* Search for first usable disk and partition */ if (!CurrentEntry) { ListUi->CurrentDisk = NULL; ListUi->CurrentPartition = NULL;
if (!IsListEmpty(&List->DiskListHead)) { ListUi->CurrentDisk = CONTAINING_RECORD(List->DiskListHead.Flink, DISKENTRY, ListEntry);
if (!IsListEmpty(&ListUi->CurrentDisk->PrimaryPartListHead)) { ListUi->CurrentPartition = CONTAINING_RECORD(ListUi->CurrentDisk->PrimaryPartListHead.Flink, PARTENTRY, ListEntry); } } } else { /* * The CurrentEntry must belong to the associated partition list, * and the latter must therefore not be empty. */ ASSERT(!IsListEmpty(&List->DiskListHead)); ASSERT(CurrentEntry->DiskEntry->PartList == List);
ListUi->CurrentPartition = CurrentEntry; ListUi->CurrentDisk = CurrentEntry->DiskEntry; }}
staticVOIDPrintEmptyLine( IN PPARTLIST_UI ListUi){ COORD coPos; ULONG Written; USHORT Width; USHORT Height;
Width = ListUi->Right - ListUi->Left - 1; Height = ListUi->Bottom - ListUi->Top - 2;
coPos.X = ListUi->Left + 1; coPos.Y = ListUi->Top + 1 + ListUi->Line;
if (ListUi->Line >= 0 && ListUi->Line <= Height) { FillConsoleOutputAttribute(StdOutput, FOREGROUND_WHITE | BACKGROUND_BLUE, Width, coPos, &Written);
FillConsoleOutputCharacterA(StdOutput, ' ', Width, coPos, &Written); }
ListUi->Line++;}
staticVOIDPrintPartitionData( IN PPARTLIST_UI ListUi, IN PDISKENTRY DiskEntry, IN PPARTENTRY PartEntry){ COORD coPos; ULONG Written; USHORT Width; USHORT Height; UCHAR Attribute; CHAR LineBuffer[100];
PartitionDescription(PartEntry, LineBuffer, ARRAYSIZE(LineBuffer));
Width = ListUi->Right - ListUi->Left - 1; Height = ListUi->Bottom - ListUi->Top - 2;
coPos.X = ListUi->Left + 1; coPos.Y = ListUi->Top + 1 + ListUi->Line;
Attribute = (ListUi->CurrentDisk == DiskEntry && ListUi->CurrentPartition == PartEntry) ? FOREGROUND_BLUE | BACKGROUND_WHITE : FOREGROUND_WHITE | BACKGROUND_BLUE;
if (ListUi->Line >= 0 && ListUi->Line <= Height) { FillConsoleOutputCharacterA(StdOutput, ' ', Width, coPos, &Written); } coPos.X += 4; Width -= 8; if (ListUi->Line >= 0 && ListUi->Line <= Height) { FillConsoleOutputAttribute(StdOutput, Attribute, Width, coPos, &Written); } coPos.X++; Width -= 2; if (ListUi->Line >= 0 && ListUi->Line <= Height) { WriteConsoleOutputCharacterA(StdOutput, LineBuffer, min(strlen(LineBuffer), Width), coPos, &Written); }
ListUi->Line++;}
staticVOIDPrintDiskData( IN PPARTLIST_UI ListUi, IN PDISKENTRY DiskEntry){ PPARTENTRY PrimaryPartEntry, LogicalPartEntry; PLIST_ENTRY PrimaryEntry, LogicalEntry; COORD coPos; ULONG Written; USHORT Width; USHORT Height; CHAR LineBuffer[100];
DiskDescription(DiskEntry, LineBuffer, ARRAYSIZE(LineBuffer));
Width = ListUi->Right - ListUi->Left - 1; Height = ListUi->Bottom - ListUi->Top - 2;
coPos.X = ListUi->Left + 1; coPos.Y = ListUi->Top + 1 + ListUi->Line;
if (ListUi->Line >= 0 && ListUi->Line <= Height) { FillConsoleOutputAttribute(StdOutput, FOREGROUND_WHITE | BACKGROUND_BLUE, Width, coPos, &Written);
FillConsoleOutputCharacterA(StdOutput, ' ', Width, coPos, &Written); }
coPos.X++; if (ListUi->Line >= 0 && ListUi->Line <= Height) { WriteConsoleOutputCharacterA(StdOutput, LineBuffer, min((USHORT)strlen(LineBuffer), Width - 2), coPos, &Written); }
ListUi->Line++;
/* Print separator line */ PrintEmptyLine(ListUi);
/* Print partition lines */ for (PrimaryEntry = DiskEntry->PrimaryPartListHead.Flink; PrimaryEntry != &DiskEntry->PrimaryPartListHead; PrimaryEntry = PrimaryEntry->Flink) { PrimaryPartEntry = CONTAINING_RECORD(PrimaryEntry, PARTENTRY, ListEntry);
PrintPartitionData(ListUi, DiskEntry, PrimaryPartEntry);
if (IsContainerPartition(PrimaryPartEntry->PartitionType)) { for (LogicalEntry = DiskEntry->LogicalPartListHead.Flink; LogicalEntry != &DiskEntry->LogicalPartListHead; LogicalEntry = LogicalEntry->Flink) { LogicalPartEntry = CONTAINING_RECORD(LogicalEntry, PARTENTRY, ListEntry);
PrintPartitionData(ListUi, DiskEntry, LogicalPartEntry); } } }
/* Print separator line */ PrintEmptyLine(ListUi);}
VOIDDrawPartitionList( IN PPARTLIST_UI ListUi){ PPARTLIST List = ListUi->List; PLIST_ENTRY Entry, Entry2; PDISKENTRY DiskEntry; PPARTENTRY PartEntry = NULL; COORD coPos; ULONG Written; USHORT Width; USHORT Height; SHORT i; SHORT CurrentDiskLine; SHORT CurrentPartLine; SHORT LastLine; BOOLEAN CurrentPartLineFound = FALSE; BOOLEAN CurrentDiskLineFound = FALSE;
Width = ListUi->Right - ListUi->Left - 1; Height = ListUi->Bottom - ListUi->Top - 2;
/* Calculate the line of the current disk and partition */ CurrentDiskLine = 0; CurrentPartLine = 0; LastLine = 0;
for (Entry = List->DiskListHead.Flink; Entry != &List->DiskListHead; Entry = Entry->Flink) { DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
LastLine += 2; if (CurrentPartLineFound == FALSE) { CurrentPartLine += 2; }
for (Entry2 = DiskEntry->PrimaryPartListHead.Flink; Entry2 != &DiskEntry->PrimaryPartListHead; Entry2 = Entry2->Flink) { PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry); if (PartEntry == ListUi->CurrentPartition) { CurrentPartLineFound = TRUE; }
if (CurrentPartLineFound == FALSE) { CurrentPartLine++; }
LastLine++; }
if (CurrentPartLineFound == FALSE) { for (Entry2 = DiskEntry->LogicalPartListHead.Flink; Entry2 != &DiskEntry->LogicalPartListHead; Entry2 = Entry2->Flink) { PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry); if (PartEntry == ListUi->CurrentPartition) { CurrentPartLineFound = TRUE; }
if (CurrentPartLineFound == FALSE) { CurrentPartLine++; }
LastLine++; } }
if (DiskEntry == ListUi->CurrentDisk) { CurrentDiskLineFound = TRUE; }
if (Entry->Flink != &List->DiskListHead) { if (CurrentDiskLineFound == FALSE) { CurrentPartLine++; CurrentDiskLine = CurrentPartLine; }
LastLine++; } else { LastLine--; } }
/* If it possible, make the disk name visible */ if (CurrentPartLine < ListUi->Offset) { ListUi->Offset = CurrentPartLine; } else if (CurrentPartLine - ListUi->Offset > Height) { ListUi->Offset = CurrentPartLine - Height; }
if (CurrentDiskLine < ListUi->Offset && CurrentPartLine - CurrentDiskLine < Height) { ListUi->Offset = CurrentDiskLine; }
/* Draw upper left corner */ coPos.X = ListUi->Left; coPos.Y = ListUi->Top; FillConsoleOutputCharacterA(StdOutput, CharUpperLeftCorner, // '+', 1, coPos, &Written);
/* Draw upper edge */ coPos.X = ListUi->Left + 1; coPos.Y = ListUi->Top; if (ListUi->Offset == 0) { FillConsoleOutputCharacterA(StdOutput, CharHorizontalLine, // '-', Width, coPos, &Written); } else { FillConsoleOutputCharacterA(StdOutput, CharHorizontalLine, // '-', Width - 4, coPos, &Written); { CHAR szBuff[] = "(.)"; // "(up)" szBuff[1] = CharUpArrow; coPos.X = ListUi->Right - 5; WriteConsoleOutputCharacterA(StdOutput, szBuff, 3, coPos, &Written); } coPos.X = ListUi->Right - 2; FillConsoleOutputCharacterA(StdOutput, CharHorizontalLine, // '-', 2, coPos, &Written); }
/* Draw upper right corner */ coPos.X = ListUi->Right; coPos.Y = ListUi->Top; FillConsoleOutputCharacterA(StdOutput, CharUpperRightCorner, // '+', 1, coPos, &Written);
/* Draw left and right edge */ for (i = ListUi->Top + 1; i < ListUi->Bottom; i++) { coPos.X = ListUi->Left; coPos.Y = i; FillConsoleOutputCharacterA(StdOutput, CharVerticalLine, // '|', 1, coPos, &Written);
coPos.X = ListUi->Right; FillConsoleOutputCharacterA(StdOutput, CharVerticalLine, //'|', 1, coPos, &Written); }
/* Draw lower left corner */ coPos.X = ListUi->Left; coPos.Y = ListUi->Bottom; FillConsoleOutputCharacterA(StdOutput, CharLowerLeftCorner, // '+', 1, coPos, &Written);
/* Draw lower edge */ coPos.X = ListUi->Left + 1; coPos.Y = ListUi->Bottom; if (LastLine - ListUi->Offset <= Height) { FillConsoleOutputCharacterA(StdOutput, CharHorizontalLine, // '-', Width, coPos, &Written); } else { FillConsoleOutputCharacterA(StdOutput, CharHorizontalLine, // '-', Width - 4, coPos, &Written); { CHAR szBuff[] = "(.)"; // "(down)" szBuff[1] = CharDownArrow; coPos.X = ListUi->Right - 5; WriteConsoleOutputCharacterA(StdOutput, szBuff, 3, coPos, &Written); } coPos.X = ListUi->Right - 2; FillConsoleOutputCharacterA(StdOutput, CharHorizontalLine, // '-', 2, coPos, &Written); }
/* Draw lower right corner */ coPos.X = ListUi->Right; coPos.Y = ListUi->Bottom; FillConsoleOutputCharacterA(StdOutput, CharLowerRightCorner, // '+', 1, coPos, &Written);
/* Print list entries */ ListUi->Line = -ListUi->Offset;
for (Entry = List->DiskListHead.Flink; Entry != &List->DiskListHead; Entry = Entry->Flink) { DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
/* Print disk entry */ PrintDiskData(ListUi, DiskEntry); }}
/** * @param[in] Direction * TRUE or FALSE to scroll to the next (down) or previous (up) entry, respectively. **/VOIDScrollUpDownPartitionList( _In_ PPARTLIST_UI ListUi, _In_ BOOLEAN Direction){ PPARTENTRY PartEntry = (Direction ? GetNextPartition : GetPrevPartition)(ListUi->List, ListUi->CurrentPartition); if (PartEntry) { ListUi->CurrentPartition = PartEntry; ListUi->CurrentDisk = PartEntry->DiskEntry; DrawPartitionList(ListUi); }}
/* EOF */