diff --git a/reactos/ChangeLog b/reactos/ChangeLog index 5ee99c74274..7ba434a93fc 100644 --- a/reactos/ChangeLog +++ b/reactos/ChangeLog @@ -1,3 +1,32 @@ +2003-04-18 Casper S. Hornstrup + + * subsys/system/usetup/partlist.c (AddPartitionList): Create + unpartitioned areas. + (CreatePartitionListNoGUI): Save disk geometry. + (PrintDiskData): Do not print hidden partition list entries. + (ScrollDownPartitionList, ScrollUpPartitionList): Skip hidden partition + list entries. + (GetActiveBootPartition): Use CurrentDisk as index. + (CreateSelectedPartition): New function. + * subsys/system/usetup/partlist.h (PARTDATA): Add field NewPartSize. + (PARTENTRY): Add fields StartingOffset and HidePartEntry. + (DISKENTRY): Add fields Cylinders, TracksPerCylinder, SectorsPerTrack, + and BytesPerSector; + (CreateSelectedPartition): Add Prototype. + * subsys/system/usetup/usetup.c (PAGE_NUMBER): Add CREATE_PARTITION_PAGE + and FORMAT_PARTITION_PAGE + (CurrentPartitionList, CurrentFileSystemList): New globals. + (SelectPartitionPage): Set CurrentPartitionList. + (PARTITION_SIZE_INPUT_FIELD_LENGTH): Define as 6. + (DrawInputField, ShowPartitionSizeInputBox, CreatePartitionPage, + CreateFileSystemList, DestroyFileSystemList, DrawFileSystemList, + ScrollDownFileSystemList, ScrollUpFileSystemList, FormatPartitionPage): + New functions. + (SelectFileSystemPage): Draw partition screen. + (CheckFileSystemPage): Handle CREATE_PARTITION_PAGE and + FORMAT_PARTITION_PAGE. + * subsys/system/usetup/usetup.h (FILE_SYSTEM, FILE_SYSTEM_LIST): Add enums. + 2003-04-17 Casper S. Hornstrup * tools/mkhive/infcache.c (InfpCacheFindSection, InfpCacheFindKeyLine, diff --git a/reactos/subsys/system/usetup/partlist.c b/reactos/subsys/system/usetup/partlist.c index 8bcb1f0c88e..83f404806c1 100644 --- a/reactos/subsys/system/usetup/partlist.c +++ b/reactos/subsys/system/usetup/partlist.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: partlist.c,v 1.7 2003/04/05 15:36:34 chorns Exp $ +/* $Id: partlist.c,v 1.8 2003/04/18 14:00:17 chorns Exp $ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS text-mode setup * FILE: subsys/system/usetup/partlist.c @@ -47,7 +47,11 @@ AddPartitionList(ULONG DiskNumber, PPARTENTRY PartEntry; ULONG i; ULONG EntryCount; - + BOOLEAN LastEntryWasUnused; + ULONGLONG LastStartingOffset; + ULONGLONG LastPartitionSize; + ULONGLONG LastUnusedPartitionSize; + ULONG LastUnusedEntry; /* * FIXME: @@ -62,14 +66,6 @@ AddPartitionList(ULONG DiskNumber, } else { - -#if 0 - for (i = 0; i < LayoutBuffer->PartitionCount; i++) - { - - } -#endif - EntryCount = LayoutBuffer->PartitionCount; } @@ -88,12 +84,20 @@ AddPartitionList(ULONG DiskNumber, PartEntry = &DiskEntry->PartArray[0]; PartEntry->Unpartitioned = TRUE; - PartEntry->PartSize = 0; /* ?? */ - - PartEntry->Used = TRUE; + // Start partition at head 1, cylinder 0 + PartEntry->StartingOffset = DiskEntry->SectorsPerTrack * DiskEntry->BytesPerSector; + PartEntry->PartSize = DiskEntry->DiskSize - PartEntry->StartingOffset; + PartEntry->Used = FALSE; + PartEntry->HidePartEntry = FALSE; } else { + LastEntryWasUnused = FALSE; + // Start partition at head 1, cylinder 0 + LastStartingOffset = DiskEntry->SectorsPerTrack * DiskEntry->BytesPerSector; + LastPartitionSize = 0; + LastUnusedEntry = -1; + LastUnusedPartitionSize = 0; for (i = 0; i < LayoutBuffer->PartitionCount; i++) { PartEntry = &DiskEntry->PartArray[i]; @@ -101,6 +105,17 @@ AddPartitionList(ULONG DiskNumber, if ((LayoutBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED) && (!IsContainerPartition(LayoutBuffer->PartitionEntry[i].PartitionType))) { + LastUnusedPartitionSize = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart + - (LastStartingOffset + LastPartitionSize); + if (LastUnusedEntry != -1) + { + DiskEntry->PartArray[LastUnusedEntry].StartingOffset = LastStartingOffset + LastPartitionSize; + DiskEntry->PartArray[LastUnusedEntry].PartSize = LastUnusedPartitionSize; + } + LastStartingOffset = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart; + LastPartitionSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart; + + PartEntry->StartingOffset = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart; PartEntry->PartSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart; PartEntry->PartNumber = LayoutBuffer->PartitionEntry[i].PartitionNumber, PartEntry->PartType = LayoutBuffer->PartitionEntry[i].PartitionType; @@ -112,12 +127,36 @@ AddPartitionList(ULONG DiskNumber, PartEntry->Unpartitioned = FALSE; PartEntry->Used = TRUE; + PartEntry->HidePartEntry = FALSE; + LastEntryWasUnused = FALSE; + LastUnusedEntry = -1; } else { + if (LastEntryWasUnused) + { + /* Group unused entries into one unpartitioned disk space area */ + PartEntry->HidePartEntry = TRUE; + PartEntry->PartSize = 0; + } + else + { + LastUnusedEntry = i; + } + + PartEntry->Unpartitioned = TRUE; + PartEntry->Used = FALSE; + LastEntryWasUnused = TRUE; } } + LastUnusedPartitionSize = DiskEntry->DiskSize + - (LastStartingOffset + LastPartitionSize); + if (LastUnusedEntry != -1) + { + DiskEntry->PartArray[LastUnusedEntry].StartingOffset = LastStartingOffset + LastPartitionSize; + DiskEntry->PartArray[LastUnusedEntry].PartSize = LastUnusedPartitionSize; + } } } @@ -256,6 +295,16 @@ CreatePartitionListNoGUI() sizeof(SCSI_ADDRESS)); + List->DiskArray[DiskNumber].Cylinders = DiskGeometry.Cylinders.QuadPart; + List->DiskArray[DiskNumber].TracksPerCylinder = DiskGeometry.TracksPerCylinder; + List->DiskArray[DiskNumber].SectorsPerTrack = DiskGeometry.SectorsPerTrack; + List->DiskArray[DiskNumber].BytesPerSector = DiskGeometry.BytesPerSector; + + DPRINT("Cylinders %d\n", List->DiskArray[DiskNumber].Cylinders); + DPRINT("TracksPerCylinder %d\n", List->DiskArray[DiskNumber].TracksPerCylinder); + DPRINT("SectorsPerTrack %d\n", List->DiskArray[DiskNumber].SectorsPerTrack); + DPRINT("BytesPerSector %d\n", List->DiskArray[DiskNumber].BytesPerSector); + List->DiskArray[DiskNumber].DiskSize = DiskGeometry.Cylinders.QuadPart * (ULONGLONG)DiskGeometry.TracksPerCylinder * @@ -654,7 +703,7 @@ PrintPartitionData(PPARTLIST List, if (PartEntry->Unpartitioned == TRUE) { sprintf(LineBuffer, - " Unpartitioned space %I64u %s", + " Unpartitioned space %I64u %s", PartSize, Unit); } @@ -816,12 +865,12 @@ PrintDiskData(PPARTLIST List, /* Print partition lines*/ for (PartIndex = 0; PartIndex < DiskEntry->PartCount; PartIndex++) { - if (DiskEntry->PartArray[PartIndex].Used == TRUE) - { - PrintPartitionData(List, - DiskIndex, - PartIndex); - } + if (!DiskEntry->PartArray[PartIndex].HidePartEntry) + { + PrintPartitionData(List, + DiskIndex, + PartIndex); + } } /* Print separator line */ @@ -930,12 +979,12 @@ ScrollDownPartitionList(PPARTLIST List) /* check for next usable entry on current disk */ for (i = List->CurrentPartition + 1; i < List->DiskArray[List->CurrentDisk].PartCount; i++) { - if (List->DiskArray[List->CurrentDisk].PartArray[i].Used == TRUE) - { - List->CurrentPartition = i; - DrawPartitionList(List); - return; - } + if (!List->DiskArray[List->CurrentDisk].PartArray[i].HidePartEntry) + { + List->CurrentPartition = i; + DrawPartitionList(List); + return; + } } /* check for first usable entry on next disk */ @@ -943,13 +992,13 @@ ScrollDownPartitionList(PPARTLIST List) { for (i = 0; i < List->DiskArray[j].PartCount; i++) { - if (List->DiskArray[j].PartArray[i].Used == TRUE) - { + if (!List->DiskArray[j].PartArray[i].HidePartEntry) + { List->CurrentDisk = j; List->CurrentPartition = i; DrawPartitionList(List); return; - } + } } } } @@ -968,7 +1017,7 @@ ScrollUpPartitionList(PPARTLIST List) /* check for previous usable entry on current disk */ for (i = List->CurrentPartition - 1; i != (ULONG)-1; i--) { - if (List->DiskArray[List->CurrentDisk].PartArray[i].Used == TRUE) + if (!List->DiskArray[List->CurrentDisk].PartArray[i].HidePartEntry) { List->CurrentPartition = i; DrawPartitionList(List); @@ -981,7 +1030,7 @@ ScrollUpPartitionList(PPARTLIST List) { for (i = List->DiskArray[j].PartCount - 1; i != (ULONG)-1; i--) { - if (List->DiskArray[j].PartArray[i].Used == TRUE) + if (!List->DiskArray[j].PartArray[i].HidePartEntry) { List->CurrentDisk = j; List->CurrentPartition = i; @@ -1063,7 +1112,7 @@ GetActiveBootPartition(PPARTLIST List, if (List->CurrentDisk >= List->DiskCount) return(FALSE); - DiskEntry = &List->DiskArray[0]; + DiskEntry = &List->DiskArray[List->CurrentDisk]; if (DiskEntry->FixedDisk == FALSE) { @@ -1120,4 +1169,113 @@ GetActiveBootPartition(PPARTLIST List, } +BOOL +CreateSelectedPartition(PPARTLIST List, + ULONG PartType, + ULONGLONG NewPartSize) +{ + PDISKENTRY DiskEntry; + PPARTENTRY PartEntry; + ULONG PartEntryNumber; + OBJECT_ATTRIBUTES ObjectAttributes; + DRIVE_LAYOUT_INFORMATION *LayoutBuffer; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + WCHAR Buffer[MAX_PATH]; + UNICODE_STRING Name; + HANDLE FileHandle; + LARGE_INTEGER li; + + DiskEntry = &List->DiskArray[List->CurrentDisk]; + PartEntry = &DiskEntry->PartArray[List->CurrentPartition]; + PartEntry->PartType = PartType; + PartEntryNumber = PartEntry->PartNumber; + + DPRINT("NewPartSize %d (%d MB)\n", NewPartSize, NewPartSize / (1024 * 1024)); + DPRINT("PartEntry->StartingOffset %d\n", PartEntry->StartingOffset); + DPRINT("PartEntry->PartSize %d\n", PartEntry->PartSize); + DPRINT("PartEntry->PartNumber %d\n", PartEntry->PartNumber); + DPRINT("PartEntry->PartType 0x%x\n", PartEntry->PartType); + DPRINT("PartEntry->FileSystemName %s\n", PartEntry->FileSystemName); + + swprintf(Buffer, + L"\\Device\\Harddisk%d\\Partition0", + DiskEntry->DiskNumber); + RtlInitUnicodeString(&Name, Buffer); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + 0x10001, + &ObjectAttributes, + &Iosb, + 1, + FILE_SYNCHRONOUS_IO_NONALERT); + if (NT_SUCCESS(Status)) + { + LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192); + + Status = NtDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_GET_DRIVE_LAYOUT, + NULL, + 0, + LayoutBuffer, + 8192); + if (!NT_SUCCESS(Status)) + { + DPRINT("IOCTL_DISK_GET_DRIVE_LAYOUT failed() 0x%.08x\n", Status); + NtClose(FileHandle); + RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); + return FALSE; + } + + li.QuadPart = PartEntry->StartingOffset; + LayoutBuffer->PartitionEntry[PartEntryNumber].StartingOffset = li; + li.QuadPart = NewPartSize; + LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionLength = li; + LayoutBuffer->PartitionEntry[PartEntryNumber].HiddenSectors = 0; /* FIXME: ? */ + LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionType = PartType; + LayoutBuffer->PartitionEntry[PartEntryNumber].RecognizedPartition = TRUE; + LayoutBuffer->PartitionEntry[PartEntryNumber].RewritePartition = TRUE; + + Status = NtDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_SET_DRIVE_LAYOUT, + LayoutBuffer, + 8192, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT("IOCTL_DISK_SET_DRIVE_LAYOUT failed() 0x%.08x\n", Status); + NtClose(FileHandle); + RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); + return FALSE; + } + } + else + { + DPRINT("NtOpenFile failed() 0x%.08x\n", Status); + NtClose(FileHandle); + RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); + return FALSE; + } + + NtClose(FileHandle); + RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); + + return TRUE; +} + /* EOF */ diff --git a/reactos/subsys/system/usetup/partlist.h b/reactos/subsys/system/usetup/partlist.h index fe8bf0bfbaa..b9a795127fe 100644 --- a/reactos/subsys/system/usetup/partlist.h +++ b/reactos/subsys/system/usetup/partlist.h @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: partlist.h,v 1.8 2003/04/05 15:36:34 chorns Exp $ +/* $Id: partlist.h,v 1.9 2003/04/18 14:00:17 chorns Exp $ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS text-mode setup * FILE: subsys/system/usetup/partlist.h @@ -36,6 +36,7 @@ typedef struct _PARTDATA USHORT Id; ULONGLONG PartSize; + ULONGLONG NewPartSize; ULONG PartNumber; ULONG PartType; @@ -47,6 +48,7 @@ typedef struct _PARTDATA typedef struct _PARTENTRY { + ULONGLONG StartingOffset; ULONGLONG PartSize; ULONG PartNumber; ULONG PartType; @@ -59,11 +61,17 @@ typedef struct _PARTENTRY BOOL Unpartitioned; BOOL Used; + + BOOLEAN HidePartEntry; } PARTENTRY, *PPARTENTRY; typedef struct _DISKENTRY { ULONGLONG DiskSize; + ULONGLONG Cylinders; + ULONGLONG TracksPerCylinder; + ULONGLONG SectorsPerTrack; + ULONGLONG BytesPerSector; ULONG DiskNumber; USHORT Port; USHORT Bus; @@ -132,6 +140,11 @@ BOOL GetActiveBootPartition(PPARTLIST List, PPARTDATA Data); +BOOL +CreateSelectedPartition(PPARTLIST List, + ULONG PartType, + ULONGLONG NewPartSize); + #endif /* __PARTLIST_H__ */ /* EOF */ diff --git a/reactos/subsys/system/usetup/usetup.c b/reactos/subsys/system/usetup/usetup.c index b9575d70f39..4521ccf3d74 100644 --- a/reactos/subsys/system/usetup/usetup.c +++ b/reactos/subsys/system/usetup/usetup.c @@ -40,6 +40,8 @@ #include "bootsup.h" #include "registry.h" +#define NDEBUG +#include typedef enum _PAGE_NUMBER { @@ -48,7 +50,9 @@ typedef enum _PAGE_NUMBER INSTALL_INTRO_PAGE, SELECT_PARTITION_PAGE, + CREATE_PARTITION_PAGE, SELECT_FILE_SYSTEM_PAGE, + FORMAT_PARTITION_PAGE, CHECK_FILE_SYSTEM_PAGE, PREPARE_COPY_PAGE, INSTALL_DIRECTORY_PAGE, @@ -74,26 +78,31 @@ typedef struct _COPYCONTEXT /* GLOBALS ******************************************************************/ HANDLE ProcessHeap; - -BOOLEAN PartDataValid; -PARTDATA PartData; - -BOOLEAN ActivePartitionValid; -PARTDATA ActivePartition; - -UNICODE_STRING SourcePath; UNICODE_STRING SourceRootPath; -UNICODE_STRING InstallPath; -UNICODE_STRING DestinationPath; -UNICODE_STRING DestinationArcPath; -UNICODE_STRING DestinationRootPath; +/* LOCALS *******************************************************************/ -UNICODE_STRING SystemRootPath; /* Path to the active partition */ +static BOOLEAN PartDataValid; +static PARTDATA PartData; -HINF SetupInf; +static BOOLEAN ActivePartitionValid; +static PARTDATA ActivePartition; -HSPFILEQ SetupFileQueue = NULL; +static UNICODE_STRING SourcePath; + +static UNICODE_STRING InstallPath; +static UNICODE_STRING DestinationPath; +static UNICODE_STRING DestinationArcPath; +static UNICODE_STRING DestinationRootPath; + +static UNICODE_STRING SystemRootPath; /* Path to the active partition */ + +static HINF SetupInf; + +static HSPFILEQ SetupFileQueue = NULL; + +static PPARTLIST CurrentPartitionList = NULL; +static PFILE_SYSTEM_LIST CurrentFileSystemList; /* FUNCTIONS ****************************************************************/ @@ -644,6 +653,12 @@ SelectPartitionPage(PINPUT_RECORD Ir) return(QUIT_PAGE); } + if (CurrentPartitionList != NULL) + { + DestroyPartitionList(CurrentPartitionList); + } + CurrentPartitionList = PartList; + SetStatusText(" ENTER = Continue F3 = Quit"); while(TRUE) @@ -670,58 +685,486 @@ SelectPartitionPage(PINPUT_RECORD Ir) { ScrollUpPartitionList(PartList); } - else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ { PartDataValid = GetSelectedPartition(PartList, &PartData); - ActivePartitionValid = GetActiveBootPartition(PartList, - &ActivePartition); - DestroyPartitionList(PartList); - - RtlFreeUnicodeString(&DestinationRootPath); - swprintf(PathBuffer, - L"\\Device\\Harddisk%lu\\Partition%lu", - PartData.DiskNumber, - PartData.PartNumber); - RtlCreateUnicodeString(&DestinationRootPath, - PathBuffer); - - RtlFreeUnicodeString(&SystemRootPath); - - if (ActivePartitionValid) - { - swprintf(PathBuffer, - L"\\Device\\Harddisk%lu\\Partition%lu", - ActivePartition.DiskNumber, - ActivePartition.PartNumber); - } - else - { - /* We mark the selected partition as bootable */ - swprintf(PathBuffer, - L"\\Device\\Harddisk%lu\\Partition%lu", - PartData.DiskNumber, - PartData.PartNumber); - } - RtlCreateUnicodeString(&SystemRootPath, - PathBuffer); - - return(SELECT_FILE_SYSTEM_PAGE); + if (PartDataValid) + { + ActivePartitionValid = GetActiveBootPartition(PartList, + &ActivePartition); + + RtlFreeUnicodeString(&DestinationRootPath); + swprintf(PathBuffer, + L"\\Device\\Harddisk%lu\\Partition%lu", + PartData.DiskNumber, + PartData.PartNumber); + RtlCreateUnicodeString(&DestinationRootPath, + PathBuffer); + + RtlFreeUnicodeString(&SystemRootPath); + + if (ActivePartitionValid) + { + swprintf(PathBuffer, + L"\\Device\\Harddisk%lu\\Partition%lu", + ActivePartition.DiskNumber, + ActivePartition.PartNumber); + } + else + { + /* We mark the selected partition as bootable */ + swprintf(PathBuffer, + L"\\Device\\Harddisk%lu\\Partition%lu", + PartData.DiskNumber, + PartData.PartNumber); + } + RtlCreateUnicodeString(&SystemRootPath, + PathBuffer); + + return(SELECT_FILE_SYSTEM_PAGE); + } + else + { + /* FIXME: show an error dialog */ + return(SELECT_PARTITION_PAGE); + } + } + else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_C) /* C */ + { +#ifdef ENABLE_FORMAT + /* Don't destroy the parition list here */; + return(CREATE_PARTITION_PAGE); +#endif } /* FIXME: Update status text */ } - DestroyPartitionList(PartList); + return(SELECT_PARTITION_PAGE); +} + +static VOID +DrawInputField(ULONG FieldLength, + SHORT Left, + SHORT Top, + PCHAR FieldContent) +{ + CHAR buf[100]; + COORD coPos; + + coPos.X = Left; + coPos.Y = Top; + memset(buf, '_', sizeof(buf)); + buf[FieldLength - strlen(FieldContent)] = 0; + strcat(buf, FieldContent); + WriteConsoleOutputCharacters(buf, + strlen(buf), + coPos); +} + +#define PARTITION_SIZE_INPUT_FIELD_LENGTH 6 + +static VOID +ShowPartitionSizeInputBox(ULONG MaxSize, + PCHAR InputBuffer, + PBOOLEAN Quit, + PBOOLEAN Cancel) +{ + SHORT Left; + SHORT Top; + SHORT Right; + SHORT Bottom; + INPUT_RECORD Ir; + COORD coPos; + ULONG Written; + SHORT i; + CHAR buf[100]; + ULONG index; + CHAR ch; + SHORT iLeft; + SHORT iTop; + SHORT xScreen; + SHORT yScreen; + + if (Quit != NULL) + *Quit = FALSE; + if (Cancel != NULL) + *Cancel = FALSE; + + GetScreenSize(&xScreen, &yScreen); + Left = 12; + Top = 11; + Right = xScreen - 12; + Bottom = 15; + + /* draw upper left corner */ + coPos.X = Left; + coPos.Y = Top; + FillConsoleOutputCharacter(0xDA, // '+', + 1, + coPos, + &Written); + + /* draw upper edge */ + coPos.X = Left + 1; + coPos.Y = Top; + FillConsoleOutputCharacter(0xC4, // '-', + Right - Left - 1, + coPos, + &Written); + + /* draw upper right corner */ + coPos.X = Right; + coPos.Y = Top; + FillConsoleOutputCharacter(0xBF, // '+', + 1, + coPos, + &Written); + + /* draw left and right edge */ + for (i = Top + 1; i < Bottom; i++) + { + coPos.X = Left; + coPos.Y = i; + FillConsoleOutputCharacter(0xB3, // '|', + 1, + coPos, + &Written); + + coPos.X = Right; + FillConsoleOutputCharacter(0xB3, //'|', + 1, + coPos, + &Written); + } + + /* draw lower left corner */ + coPos.X = Left; + coPos.Y = Bottom; + FillConsoleOutputCharacter(0xC0, // '+', + 1, + coPos, + &Written); + + /* draw lower edge */ + coPos.X = Left + 1; + coPos.Y = Bottom; + FillConsoleOutputCharacter(0xC4, // '-', + Right - Left - 1, + coPos, + &Written); + + /* draw lower right corner */ + coPos.X = Right; + coPos.Y = Bottom; + FillConsoleOutputCharacter(0xD9, // '+', + 1, + coPos, + &Written); + + /* Print message */ + coPos.X = Left + 2; + coPos.Y = Top + 2; + strcpy(buf, "Size of new partition:"); + iLeft = coPos.X + strlen(buf) + 1; + iTop = coPos.Y; + WriteConsoleOutputCharacters(buf, + strlen(buf), + coPos); + + sprintf(buf, "MB (max. %d MB)", MaxSize / (1024 * 1024)); + coPos.X = iLeft + PARTITION_SIZE_INPUT_FIELD_LENGTH + 1; + coPos.Y = iTop; + WriteConsoleOutputCharacters(buf, + strlen(buf), + coPos); + + buf[0] = 0; + index = 0; + DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH, iLeft, iTop, buf); + + while(TRUE) + { + ConInKey(&Ir); + if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ + { + if (Quit != NULL) + *Quit = TRUE; + buf[0] = 0; + break; + } + else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ + { + break; + } + else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */ + { + if (Cancel != NULL) + *Cancel = FALSE; + buf[0] = 0; + break; + } + else if ((Ir.Event.KeyEvent.wVirtualKeyCode == VK_BACK) && (index > 0)) /* BACKSPACE */ + { + index--; + buf[index] = 0; + DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH, iLeft, iTop, buf); + } + else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) + && (index < PARTITION_SIZE_INPUT_FIELD_LENGTH)) + { + ch = Ir.Event.KeyEvent.uChar.AsciiChar; + if ((ch >= '0') && (ch <= '9')) + { + buf[index] = ch; + index++; + buf[index] = 0; + DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH, iLeft, iTop, buf); + } + } + } + strcpy(InputBuffer, buf); +} + + +static PAGE_NUMBER +CreatePartitionPage(PINPUT_RECORD Ir) +{ + BOOLEAN Valid; + WCHAR PathBuffer[MAX_PATH]; + PPARTLIST PartList; + PPARTENTRY PartEntry; + SHORT xScreen; + SHORT yScreen; + BOOLEAN Quit; + BOOLEAN Cancel; + CHAR InputBuffer[50]; + ULONG MaxSize; + ULONGLONG PartSize; + + SetTextXY(6, 8, "You have chosen to create a new partition in the unused disk space."); + SetTextXY(6, 9, "Please enter the size of the new partition in megabytes."); + + SetStatusText(" Please wait..."); + + GetScreenSize(&xScreen, &yScreen); + + PartList = CurrentPartitionList; + + SetStatusText(" ENTER = Continue ESC = Cancel F3 = Quit"); + + PartEntry = &PartList->DiskArray[PartList->CurrentDisk].PartArray[PartList->CurrentPartition]; + while (TRUE) + { + MaxSize = PartEntry->PartSize; + ShowPartitionSizeInputBox(MaxSize, InputBuffer, &Quit, &Cancel); + if (Quit == TRUE) + { + if (ConfirmQuit(Ir) == TRUE) + { + DestroyPartitionList(PartList); + return(QUIT_PAGE); + } + } + else if (Cancel == TRUE) + { + break; + } + else + { + PartSize = atoi(InputBuffer); + if (PartSize < 1) + { + // Too small + continue; + } + /* Convert to bytes */ + PartSize *= 1024 * 1024; + + if (PartSize > PartEntry->PartSize) + { + // Too large + continue; + } + + assert(PartEntry->Unpartitioned == TRUE); + PartEntry->PartType = PARTITION_ENTRY_UNUSED; + PartEntry->Used = TRUE; + + PartDataValid = GetSelectedPartition(PartList, + &PartData); + if (PartDataValid) + { + PartData.NewPartSize = PartSize; + + ActivePartitionValid = GetActiveBootPartition(PartList, + &ActivePartition); + + RtlFreeUnicodeString(&DestinationRootPath); + swprintf(PathBuffer, + L"\\Device\\Harddisk%lu\\Partition%lu", + PartData.DiskNumber, + PartData.PartNumber); + RtlCreateUnicodeString(&DestinationRootPath, + PathBuffer); + + RtlFreeUnicodeString(&SystemRootPath); + + if (ActivePartitionValid) + { + swprintf(PathBuffer, + L"\\Device\\Harddisk%lu\\Partition%lu", + ActivePartition.DiskNumber, + ActivePartition.PartNumber); + } + else + { + /* We mark the selected partition as bootable */ + swprintf(PathBuffer, + L"\\Device\\Harddisk%lu\\Partition%lu", + PartData.DiskNumber, + PartData.PartNumber); + } + RtlCreateUnicodeString(&SystemRootPath, + PathBuffer); + + return(SELECT_FILE_SYSTEM_PAGE); + } + else + { + /* FIXME: show an error dialog */ + return(SELECT_PARTITION_PAGE); + } + } + } return(SELECT_PARTITION_PAGE); } +static PFILE_SYSTEM_LIST +CreateFileSystemList(SHORT Left, + SHORT Top, + BOOLEAN ForceFormat, + FILE_SYSTEM ForceFileSystem) +{ + PFILE_SYSTEM_LIST List; + + List = (PFILE_SYSTEM_LIST)RtlAllocateHeap(ProcessHeap, 0, sizeof(FILE_SYSTEM_LIST)); + if (List == NULL) + return(NULL); + + List->Left = Left; + List->Top = Top; + +#if ENABLE_FORMAT + List->FileSystemCount = 1; +#else + List->FileSystemCount = 0; +#endif + if (ForceFormat) + { + List->CurrentFileSystem = ForceFileSystem; + } + else + { + List->FileSystemCount++; + List->CurrentFileSystem = FsKeep; + } + return(List); +} + + +static VOID +DestroyFileSystemList(PFILE_SYSTEM_LIST List) +{ + RtlFreeHeap(ProcessHeap, 0, List); +} + + +static VOID +DrawFileSystemList(PFILE_SYSTEM_LIST List) +{ + COORD coPos; + ULONG Written; + ULONG index; + + index = 0; + +#ifdef ENABLE_FORMAT + coPos.X = List->Left; + coPos.Y = List->Top + index; + FillConsoleOutputAttribute(0x17, + 50, + coPos, + &Written); + FillConsoleOutputCharacter(' ', + 50, + coPos, + &Written); + + if (List->CurrentFileSystem == FsFat) + { + SetInvertedTextXY(List->Left, List->Top + index, " Format partition as FAT file system "); + } + else + { + SetTextXY(List->Left, List->Top + index, " Format partition as FAT file system "); + } + index++; +#endif + + coPos.X = List->Left; + coPos.Y = List->Top + index; + FillConsoleOutputAttribute(0x17, + 50, + coPos, + &Written); + FillConsoleOutputCharacter(' ', + 50, + coPos, + &Written); + + if (List->CurrentFileSystem == FsKeep) + { + SetInvertedTextXY(List->Left, List->Top + index, " Keep current file system (no changes) "); + } + else + { + SetTextXY(List->Left, List->Top + index, " Keep current file system (no changes) "); + } +} + + +static VOID +ScrollDownFileSystemList(PFILE_SYSTEM_LIST List) +{ + if ((ULONG) List->CurrentFileSystem < List->FileSystemCount - 1) + { + (ULONG) List->CurrentFileSystem++; + DrawFileSystemList(List); + } +} + + +static VOID +ScrollUpFileSystemList(PFILE_SYSTEM_LIST List) +{ + if ((ULONG) List->CurrentFileSystem > 0) + { + (ULONG) List->CurrentFileSystem--; + DrawFileSystemList(List); + } +} + + static PAGE_NUMBER SelectFileSystemPage(PINPUT_RECORD Ir) { + PFILE_SYSTEM_LIST FileSystemList; ULONGLONG DiskSize; ULONGLONG PartSize; PCHAR DiskUnit; @@ -775,6 +1218,10 @@ SelectFileSystemPage(PINPUT_RECORD Ir) { PartType = "NTFS"; /* FIXME: Not quite correct! */ } + else if (PartData.PartType == PARTITION_ENTRY_UNUSED) + { + PartType = "Unused"; + } else { PartType = "Unknown"; @@ -804,9 +1251,16 @@ SelectFileSystemPage(PINPUT_RECORD Ir) SetTextXY(8, 21, "\xfa Press ENTER to format the partition."); SetTextXY(8, 23, "\xfa Press ESC to select another partition."); - /* FIXME: use a real list later */ - SetInvertedTextXY(6, 26, " Keep current file system (no changes) "); + FileSystemList = CreateFileSystemList(6, 26, FALSE, FsKeep); + if (FileSystemList == NULL) + { + /* FIXME: show an error dialog */ + return(QUIT_PAGE); + } + CurrentFileSystemList = FileSystemList; + + DrawFileSystemList(FileSystemList); SetStatusText(" ENTER = Continue ESC = Cancel F3 = Quit"); @@ -824,18 +1278,111 @@ SelectFileSystemPage(PINPUT_RECORD Ir) else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */ { + DestroyFileSystemList(FileSystemList); return(SELECT_PARTITION_PAGE); } - else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) /* DOWN */ { - return(CHECK_FILE_SYSTEM_PAGE); + ScrollDownFileSystemList(FileSystemList); + } + else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) /* UP */ + { + ScrollUpFileSystemList(FileSystemList); + } + else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ + { + if (FileSystemList->CurrentFileSystem == FsKeep) + { + return(CHECK_FILE_SYSTEM_PAGE); + } + else + { + return(FORMAT_PARTITION_PAGE); + } + } + } +} + +static ULONG +FormatPartitionPage(PINPUT_RECORD Ir) +{ + BOOLEAN CreatePartition; + ULONG PartType; + BOOLEAN Valid; + + SetTextXY(6, 8, "Format partition"); + + SetTextXY(6, 10, "Setup will now format the partition. Press ENTER to continue."); + + SetStatusText(" ENTER = Continue F3 = Quit"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ + { + if (ConfirmQuit(Ir) == TRUE) + { + return(QUIT_PAGE); + } + break; + } + else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ + { + SetStatusText(" Please wait ..."); + + CreatePartition = FALSE; + switch (CurrentFileSystemList->CurrentFileSystem) + { +#ifdef ENABLE_FORMAT + case FsFat: + PartType = PARTITION_FAT32_XINT13; + CreatePartition = TRUE; + break; +#endif + case FsKeep: + CreatePartition = FALSE; + break; + default: + return QUIT_PAGE; + } + + if (CreatePartition) + { + Valid = CreateSelectedPartition(CurrentPartitionList, PartType, PartData.NewPartSize); + if (Valid) + { + return(INSTALL_DIRECTORY_PAGE); + } + else + { + DPRINT("CreateSelectedPartition() failed\n"); + /* FIXME: show an error dialog */ + return(QUIT_PAGE); + } + } + + switch (CurrentFileSystemList->CurrentFileSystem) + { +#ifdef ENABLE_FORMAT + case FsFat: + break; +#endif + case FsKeep: + break; + default: + return QUIT_PAGE; + } } } - return(SELECT_FILE_SYSTEM_PAGE); + return(INSTALL_DIRECTORY_PAGE); } - static ULONG CheckFileSystemPage(PINPUT_RECORD Ir) { @@ -2190,10 +2737,18 @@ NtProcessStartup(PPEB Peb) Page = SelectPartitionPage(&Ir); break; + case CREATE_PARTITION_PAGE: + Page = CreatePartitionPage(&Ir); + break; + case SELECT_FILE_SYSTEM_PAGE: Page = SelectFileSystemPage(&Ir); break; + case FORMAT_PARTITION_PAGE: + Page = FormatPartitionPage(&Ir); + break; + case CHECK_FILE_SYSTEM_PAGE: Page = CheckFileSystemPage(&Ir); break; diff --git a/reactos/subsys/system/usetup/usetup.h b/reactos/subsys/system/usetup/usetup.h index ebb83c636a6..2fab1522f62 100644 --- a/reactos/subsys/system/usetup/usetup.h +++ b/reactos/subsys/system/usetup/usetup.h @@ -27,6 +27,8 @@ #ifndef __USETUP_H__ #define __USETUP_H__ +// Define to allow creating a new partition and format it +//#define ENABLE_FORMAT #define DPRINT1(args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); #define CHECKPOINT1 do { DbgPrint("%s:%d\n",__FILE__,__LINE__); } while(0); @@ -34,6 +36,23 @@ #define DPRINT(args...) #define CHECKPOINT +typedef enum +{ +#ifdef ENABLE_FORMAT + FsFat = 0, + FsKeep = 1 +#else + FsKeep = 0 +#endif +} FILE_SYSTEM; + +typedef struct _FILE_SYSTEM_LIST +{ + SHORT Left; + SHORT Top; + FILE_SYSTEM CurrentFileSystem; + ULONG FileSystemCount; +} FILE_SYSTEM_LIST, *PFILE_SYSTEM_LIST; extern HANDLE ProcessHeap;