Index: reactos/base/setup/usetup/interface/usetup.c =================================================================== --- reactos/base/setup/usetup/interface/usetup.c (revision 67507) +++ reactos/base/setup/usetup/interface/usetup.c (working copy) @@ -24,8 +24,24 @@ * PROGRAMMER: Eric Kohl * Casper S. Hornstrup (chorns@users.sourceforge.net) * Hervé Poussineau (hpoussin@reactos.org) + * Gerhard Gruber (sparhawk@gmx.at) */ +/** + ChangeLog: + + 2015.05.02 sparhawk + When pressing ENTER on an unpartitioned logical diskspace + a primary partition was wrongly created. + + 2015.04.15 sparhawk + Added support for installation on logical partitions. + + 2015.03.15 sparhawk + Changed the input field for creating a partition with user defined + size, to make it looke like an input field. +*/ + #include #include "bootsup.h" @@ -392,7 +408,7 @@ Result = TRUE; break; } - else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ { Result = FALSE; break; @@ -1456,7 +1472,7 @@ if (PartitionList == NULL) { PartitionList = CreatePartitionList(2, - 21, + 23, xScreen - 3, yScreen - 3); if (PartitionList == NULL) @@ -1535,6 +1551,8 @@ while (TRUE) { + PPARTENTRY PartEntry; + /* Update status text */ if (PartitionList->CurrentPartition == NULL) { @@ -1604,9 +1622,20 @@ if (PartitionList->CurrentPartition == NULL || PartitionList->CurrentPartition->IsPartitioned == FALSE) { - CreatePrimaryPartition(PartitionList, - 0ULL, - TRUE); + if(PartitionList->CurrentPartition->LogicalPartition) + { + DPRINT1("Creating a logical partition\n"); + CreateLogicalPartition(PartitionList, + 0ULL, + TRUE); + } + else + { + DPRINT1("Creating a primary partition\n"); + CreatePrimaryPartition(PartitionList, + 0ULL, + TRUE); + } } if (!IsDiskSizeValid(PartitionList->CurrentPartition)) @@ -1672,6 +1701,9 @@ return DELETE_PARTITION_PAGE; } + + PartEntry = PartitionList->CurrentPartition; + DumpPartition("[Selected] ", PartEntry); } return SELECT_PARTITION_PAGE; @@ -1724,6 +1756,7 @@ CHAR ch; SHORT iLeft; SHORT iTop; + DWORD redraw; if (Quit != NULL) *Quit = FALSE; @@ -1757,15 +1790,43 @@ sprintf(Buffer, "%lu", MaxSize); Index = strlen(Buffer); - DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH, - iLeft, - iTop, - Buffer); + coPos.X = iLeft; + coPos.Y = iTop; + redraw = TRUE; + while (TRUE) { - CONSOLE_ConInKey(&Ir); + if(redraw) + { + DWORD blen = strlen(Buffer); + COORD cursor; + FillConsoleOutputAttribute( + StdOutput, + BACKGROUND_WHITE, + blen, + coPos, + &Written); + + cursor.Y = coPos.Y; + cursor.X = coPos.X+PARTITION_SIZE_INPUT_FIELD_LENGTH-1; + FillConsoleOutputAttribute( + StdOutput, + FOREGROUND_WHITE, + 1, + cursor, + &Written); + + DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH, + iLeft, + iTop, + Buffer); + } + redraw = FALSE; + +CONSOLE_ConInKey(&Ir); + if ((Ir.Event.KeyEvent.uChar.AsciiChar == 0x00) && (Ir.Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ { @@ -1775,11 +1836,11 @@ Buffer[0] = 0; break; } - else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ + else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */ { break; } - else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */ + else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) /* ESCAPE */ { if (Cancel != NULL) *Cancel = TRUE; @@ -1792,11 +1853,7 @@ { Index--; Buffer[Index] = 0; - - DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH, - iLeft, - iTop, - Buffer); + redraw = TRUE; } else if ((Ir.Event.KeyEvent.uChar.AsciiChar != 0x00) && (Index < PARTITION_SIZE_INPUT_FIELD_LENGTH)) @@ -1808,11 +1865,7 @@ Buffer[Index] = ch; Index++; Buffer[Index] = 0; - - DrawInputField(PARTITION_SIZE_INPUT_FIELD_LENGTH, - iLeft, - iTop, - Buffer); + redraw = TRUE; } } } @@ -2247,11 +2300,9 @@ SectorCount = PartEntry->SectorCount.QuadPart; } - DPRINT("Partition size: %I64u bytes\n", PartSize); + DPRINT1("Partition size: %I64u bytes, SectorCount: %I64u\n", PartSize, SectorCount); + CreateLogicalPartition(PartitionList, SectorCount, FALSE); - CreateLogicalPartition(PartitionList, - SectorCount); - return SELECT_PARTITION_PAGE; } } @@ -2530,7 +2581,6 @@ CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT)); - PartEntry->AutoCreate = FALSE; } else if (PartEntry->New == TRUE) @@ -2650,7 +2700,6 @@ return SELECT_FILE_SYSTEM_PAGE; } - static ULONG FormatPartitionPage(PINPUT_RECORD Ir) { @@ -2794,7 +2843,7 @@ if (WritePartitionsToDisk(PartitionList) == FALSE) { - DPRINT("WritePartitionsToDisk() failed\n"); + DPRINT1("WritePartitionsToDisk() failed\n"); MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER); return QUIT_PAGE; } @@ -2807,7 +2856,7 @@ PartitionList->CurrentPartition->PartitionNumber); RtlCreateUnicodeString(&DestinationRootPath, PathBuffer); - DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath); + DPRINT1("Partition: %p DestinationRootPath: %wZ\n", PartitionList->CurrentPartition, &DestinationRootPath); if (FileSystemList->Selected->FormatFunc) { @@ -2821,7 +2870,6 @@ } PartEntry->New = FALSE; - } #ifndef NDEBUG @@ -2838,7 +2886,6 @@ return FORMAT_PARTITION_PAGE; } - static ULONG CheckFileSystemPage(PINPUT_RECORD Ir) { @@ -3290,7 +3337,7 @@ Status = SetupCreateDirectory(PathBuffer); if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION) { - DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status); + DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status); MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER); return FALSE; } @@ -3910,7 +3957,7 @@ break; } - else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ { if (Line == 12) { @@ -3958,7 +4005,7 @@ break; } - else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ { if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE) { Index: reactos/base/setup/usetup/lang/de-DE.h =================================================================== --- reactos/base/setup/usetup/lang/de-DE.h (revision 67507) +++ reactos/base/setup/usetup/lang/de-DE.h (working copy) @@ -826,6 +826,12 @@ { 8, 19, + "\x07 L erstellt eine logische Partition.", + TEXT_STYLE_NORMAL + }, + { + 8, + 21, "\x07 D l”scht eine vorhandene Partition.", TEXT_STYLE_NORMAL }, Index: reactos/base/setup/usetup/lang/en-US.h =================================================================== --- reactos/base/setup/usetup/lang/en-US.h (revision 67507) +++ reactos/base/setup/usetup/lang/en-US.h (working copy) @@ -831,6 +831,12 @@ { 8, 19, + "\x07 Press L to create a logical partition.", + TEXT_STYLE_NORMAL + }, + { + 8, + 21, "\x07 Press D to delete an existing partition.", TEXT_STYLE_NORMAL }, Index: reactos/base/setup/usetup/partlist.c =================================================================== --- reactos/base/setup/usetup/partlist.c (revision 67507) +++ reactos/base/setup/usetup/partlist.c (working copy) @@ -22,8 +22,16 @@ * PURPOSE: Partition list functions * PROGRAMMER: Eric Kohl * Casper S. Hornstrup (chorns@users.sourceforge.net) + * Gerhard Gruber (sparhawk@gmx.at) */ +/** + ChangeLog: + + 2015.04.15 sparhawk + Added support for installation on logical partitions. +*/ + #include "usetup.h" #include @@ -31,45 +39,134 @@ #define NDEBUG #include -#define DUMP_PARTITION_TABLE - /* FUNCTIONS ****************************************************************/ -#ifdef DUMP_PARTITION_TABLE -static -VOID -DumpPartitionTable( - PDISKENTRY DiskEntry) +static VOID DumpPartitionTable(PDISKENTRY DiskEntry) { PPARTITION_INFORMATION PartitionInfo; ULONG i; + TCHAR buffer[11]; + DPRINT1("DiskEntry: %p #: %lu dirty: %c partitions: %lu %I64u/%lu/%lu/%lu sec: %I64u align: %lu\n", + DiskEntry, + DiskEntry->DiskNumber, + DiskEntry->Dirty ? 'D' : '-', + DiskEntry->LayoutBuffer->PartitionCount, + DiskEntry->Cylinders, + DiskEntry->TracksPerCylinder, + DiskEntry->SectorsPerTrack, + DiskEntry->BytesPerSector, + DiskEntry->SectorCount, + DiskEntry->SectorAlignment + ); + DPRINT1(" # Addr StartOfs PartLength HiddenSect P# Typ Boot Rewr. Known Size\n"); for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++) { PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i]; - DPRINT("\n%lu: %12I64u %12I64u %10lu %2lu %2x %c %c\n", - i, - PartitionInfo->StartingOffset.QuadPart, - PartitionInfo->PartitionLength.QuadPart, - PartitionInfo->HiddenSectors, - PartitionInfo->PartitionNumber, - PartitionInfo->PartitionType, - PartitionInfo->BootIndicator ? '*': ' ', - PartitionInfo->RewritePartition ? 'Y': 'N'); + snprintf(buffer, sizeof(buffer)-1, "%02lu: ", i); + DumpPartitionInfo(buffer, PartitionInfo); } } -#endif +VOID DumpPartition(TCHAR *pPrefix, PPARTENTRY pPartition) +{ + TCHAR *prefix = ""; + char c; -ULONGLONG -Align( - IN ULONGLONG Value, - IN ULONG Alignment) + if(pPrefix != NULL) + prefix = pPrefix; + + if(pPartition == NULL) + { + DPRINT1("%sPartition: NULL\n", prefix); + return; + } + + if(pPartition->IsPartitioned == FALSE) + c = 'U'; + else + { + if(pPartition == pPartition->DiskEntry->ExtendedPartition) + c = 'E'; + else + { + if(pPartition->LogicalPartition) + c = 'L'; + else + c = 'P'; + } + } + + DPRINT1("%sPartition: %p Flink: %p Blink: %p %2u/%2u %2u %c %c %c %c %12I64u %12I64u %7I64u MB\n", + prefix, + pPartition, + pPartition->ListEntry.Flink, + pPartition->ListEntry.Blink, + pPartition->PartitionNumber, + pPartition->PartitionIndex, + pPartition->PartitionType, + c, + pPartition->IsPartitioned ? 'Y1' : 'N', + pPartition->New ? 'N' : 'O', + pPartition->BootIndicator ? '*' : '-', + pPartition->StartSector.QuadPart, + pPartition->SectorCount.QuadPart, + (pPartition->SectorCount.QuadPart*pPartition->DiskEntry->BytesPerSector)/(1024*1024) + ); +} + +VOID DumpPartitionInfo(TCHAR *pPrefix, PPARTITION_INFORMATION pPartitionInfo) { + TCHAR *prefix = ""; + ULONGLONG PartSize; + TCHAR *Unit; + + if(pPrefix != NULL) + prefix = pPrefix; + + PartSize = pPartitionInfo->PartitionLength.QuadPart; +/* if (PartSize >= 10737418240) // 10 GB + { + PartSize = PartSize / 1073741824; + Unit = "GB"; + } + else*/ + if (PartSize >= 10485760) // 10 MB + { + PartSize = PartSize / 1048576; + Unit = "MB"; + } + else + { + PartSize = PartSize / 1024; + Unit = "KB"; + } + + DPRINT1("%s%p %13I64u %13I64u %10lu %2lu %2x %c %c %c %9I64u %s\n", + prefix, + pPartitionInfo, + pPartitionInfo->StartingOffset.QuadPart, + pPartitionInfo->PartitionLength.QuadPart, + pPartitionInfo->HiddenSectors, + pPartitionInfo->PartitionNumber, + pPartitionInfo->PartitionType, + pPartitionInfo->BootIndicator ? '*': '-', + pPartitionInfo->RecognizedPartition ? 'Y' : 'N', + pPartitionInfo->RewritePartition ? 'Y': 'N', + PartSize, + Unit + ); +} + +ULONGLONG Align(IN ULONGLONG Value, IN ULONG Alignment) +{ ULONGLONG Temp; Temp = Value / Alignment; +// if((Temp * Alignment) < Value) +// Temp++; + return Temp * Alignment; } @@ -92,6 +189,8 @@ WCHAR KeyName[32]; NTSTATUS Status; + DPRINT1("GetDriverName()\n"); + RtlInitUnicodeString(&DiskEntry->DriverName, NULL); @@ -129,6 +228,8 @@ PLIST_ENTRY Entry2; CHAR Letter; + DPRINT1("AssignDriveLetters()\n"); + Letter = 'C'; /* Assign drive letters to primary partitions */ @@ -216,38 +317,46 @@ { PPARTENTRY PartEntry; PLIST_ENTRY Entry; -// ULONG PartitionNumber = 1; + ULONG PartitionNumber = 1; ULONG PartitionIndex = 0; + DPRINT1("UpdatePartitionNumbers()\n"); + Entry = DiskEntry->PrimaryPartListHead.Flink; while (Entry != &DiskEntry->PrimaryPartListHead) { - PartEntry = CONTAINING_RECORD(Entry, - PARTENTRY, - ListEntry); + PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); if (PartEntry->IsPartitioned == FALSE) { -// PartEntry->PartitionNumber = 0; PartEntry->PartitionIndex = (ULONG)-1; + PartEntry->PartitionNumber = 0; } else { - if (IsContainerPartition(PartEntry->PartitionType)) - { -// PartEntry->PartitionNumber = 0; - } - else if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED && - PartEntry->SectorCount.QuadPart == 0ULL) - { -// PartEntry->PartitionNumber = 0; - } - else - { -// PartEntry->PartitionNumber = PartitionNumber++; - } + PartEntry->PartitionIndex = PartitionIndex++; + PartEntry->PartitionNumber = PartitionNumber++; + } + Entry = Entry->Flink; + } + + Entry = DiskEntry->LogicalPartListHead.Flink; + PartitionIndex = 4; + PartitionNumber--; + while (Entry != &DiskEntry->LogicalPartListHead) + { + PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); + + if (PartEntry->IsPartitioned == FALSE) + { + PartEntry->PartitionIndex = (ULONG)-1; + PartEntry->PartitionNumber = 0; + } + else + { PartEntry->PartitionIndex = PartitionIndex++; + PartEntry->PartitionNumber = PartitionNumber++; } Entry = Entry->Flink; @@ -268,6 +377,8 @@ PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context; UNICODE_STRING NameU; + DPRINT1("DiskIdentifierQueryRoutine()\n"); + if (ValueType == REG_SZ && ValueLength == 20 * sizeof(WCHAR)) { @@ -300,6 +411,8 @@ PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry; ULONG i; + DPRINT1("DiskConfigurationDataQueryRoutine()\n"); + if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR || ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) return STATUS_UNSUCCESSFUL; @@ -343,6 +456,8 @@ PCM_INT13_DRIVE_PARAMETER* Int13Drives = (PCM_INT13_DRIVE_PARAMETER*)Context; ULONG i; + DPRINT1("SystemConfigurationDataQueryRoutine()\n"); + if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR || ValueLength < sizeof (CM_FULL_RESOURCE_DESCRIPTOR)) return STATUS_UNSUCCESSFUL; @@ -390,6 +505,8 @@ PCM_INT13_DRIVE_PARAMETER Int13Drives; PBIOSDISKENTRY BiosDiskEntry; + DPRINT1("EnumerateBiosDiskEntries()\n"); + memset(QueryTable, 0, sizeof(QueryTable)); QueryTable[1].Name = L"Configuration Data"; @@ -529,6 +646,8 @@ PPARTITION_INFORMATION PartitionInfo; PPARTENTRY PartEntry; + DPRINT1("AddPartitionToDisk()\n"); + PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex]; if (PartitionInfo->PartitionType == 0 || (LogicalPartition == TRUE && IsContainerPartition(PartitionInfo->PartitionType))) @@ -538,14 +657,12 @@ HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (PartEntry == NULL) - { return; - } PartEntry->DiskEntry = DiskEntry; - PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector; - PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector; + PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart/DiskEntry->BytesPerSector; + PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart/DiskEntry->BytesPerSector; PartEntry->BootIndicator = PartitionInfo->BootIndicator; PartEntry->PartitionType = PartitionInfo->PartitionType; @@ -561,24 +678,20 @@ PartEntry->FormatState = Unformatted; if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL) - DiskEntry->ExtendedPartition = PartEntry; + DiskEntry->ExtendedPartition = PartEntry; } else if ((PartEntry->PartitionType == PARTITION_FAT_12) || - (PartEntry->PartitionType == PARTITION_FAT_16) || - (PartEntry->PartitionType == PARTITION_HUGE) || - (PartEntry->PartitionType == PARTITION_XINT13) || - (PartEntry->PartitionType == PARTITION_FAT32) || - (PartEntry->PartitionType == PARTITION_FAT32_XINT13)) + (PartEntry->PartitionType == PARTITION_FAT_16) || + (PartEntry->PartitionType == PARTITION_HUGE) || + (PartEntry->PartitionType == PARTITION_XINT13) || + (PartEntry->PartitionType == PARTITION_FAT32) || + (PartEntry->PartitionType == PARTITION_FAT32_XINT13)) { #if 0 if (CheckFatFormat()) - { PartEntry->FormatState = Preformatted; - } else - { PartEntry->FormatState = Unformatted; - } #endif PartEntry->FormatState = Preformatted; } @@ -586,13 +699,9 @@ { #if 0 if (CheckExt2Format()) - { PartEntry->FormatState = Preformatted; - } else - { PartEntry->FormatState = Unformatted; - } #endif PartEntry->FormatState = Preformatted; } @@ -600,17 +709,11 @@ { #if 0 if (CheckNtfsFormat()) - { PartEntry->FormatState = Preformatted; - } else if (CheckHpfsFormat()) - { PartEntry->FormatState = Preformatted; - } else - { PartEntry->FormatState = Unformatted; - } #endif PartEntry->FormatState = Preformatted; } @@ -618,13 +721,17 @@ { PartEntry->FormatState = UnknownFormat; } - + if (LogicalPartition) + { InsertTailList(&DiskEntry->LogicalPartListHead, - &PartEntry->ListEntry); + &PartEntry->ListEntry); + } else + { InsertTailList(&DiskEntry->PrimaryPartListHead, - &PartEntry->ListEntry); + &PartEntry->ListEntry); + } } @@ -648,8 +755,8 @@ /* Create a partition table that represents the empty disk */ NewPartEntry = RtlAllocateHeap(ProcessHeap, - HEAP_ZERO_MEMORY, - sizeof(PARTENTRY)); + HEAP_ZERO_MEMORY, + sizeof(PARTENTRY)); if (NewPartEntry == NULL) return; @@ -656,17 +763,18 @@ NewPartEntry->DiskEntry = DiskEntry; NewPartEntry->IsPartitioned = FALSE; - NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorsPerTrack; + //NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorsPerTrack; + NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment; NewPartEntry->SectorCount.QuadPart = Align(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) - - DiskEntry->SectorsPerTrack; -DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); -DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); -DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart); + DiskEntry->SectorAlignment; + DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); + DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); + DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart); + NewPartEntry->FormatState = Unformatted; - InsertTailList(&DiskEntry->PrimaryPartListHead, - &NewPartEntry->ListEntry); + InsertTailList(&DiskEntry->PrimaryPartListHead, &NewPartEntry->ListEntry); return; } @@ -890,6 +998,8 @@ PDISKENTRY DiskEntry2; PUCHAR Buffer; + DPRINT1("SetDiskSignature()\n"); + Buffer = (PUCHAR)&DiskEntry->LayoutBuffer->Signature; while (1) @@ -938,6 +1048,8 @@ PLIST_ENTRY Entry; PDISKENTRY DiskEntry; + DPRINT1("UpdateDiskSignatures()\n"); + /* Print partition lines*/ Entry = List->DiskListHead.Flink; while (Entry != &List->DiskListHead) @@ -979,6 +1091,8 @@ PBIOSDISKENTRY BiosDiskEntry; ULONG LayoutBufferSize; + DPRINT1("AddDiskToList()\n"); + Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, @@ -1069,9 +1183,9 @@ /* Check if this disk has a valid MBR */ if (Mbr->BootCode[0] == 0 && Mbr->BootCode[1] == 0) - DiskEntry->NoMbr = TRUE; + DiskEntry->Mbr = FALSE; else - DiskEntry->NoMbr = FALSE; + DiskEntry->Mbr = TRUE; /* Free Mbr sector buffer */ RtlFreeHeap(ProcessHeap, @@ -1100,6 +1214,7 @@ } else { + // TODO: ? } } ListEntry = ListEntry->Flink; @@ -1132,10 +1247,16 @@ (ULONGLONG)DiskGeometry.TracksPerCylinder * (ULONGLONG)DiskGeometry.SectorsPerTrack; - DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack; + //DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack; + // If the disk is smaller than 4GB, an alignment of 63 is ok, otherwise + // the alignment should be bigger and 2048 is a suggested value. + if((DiskEntry->SectorCount.QuadPart * DiskGeometry.SectorsPerTrack) < 4294967296) // 4GB + DiskEntry->SectorAlignment = 63; + else + DiskEntry->SectorAlignment = 2048; - DPRINT("SectorCount %I64u\n", DiskEntry->SectorCount); - DPRINT("SectorAlignment %lu\n", DiskEntry->SectorAlignment); + DPRINT("SectorCount: %I64u\n", DiskEntry->SectorCount); + DPRINT("SectorAlignment: %lu\n", DiskEntry->SectorAlignment); DiskEntry->DiskNumber = DiskNumber; DiskEntry->Port = ScsiAddress.PortNumber; @@ -1172,9 +1293,7 @@ LayoutBufferSize); if (NT_SUCCESS(Status)) { -#ifdef DUMP_PARTITION_TABLE DumpPartitionTable(DiskEntry); -#endif if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 && DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 && @@ -1198,13 +1317,13 @@ DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry->BytesPerSector); } - + DPRINT1("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount); if (DiskEntry->LayoutBuffer->PartitionCount == 0) { DiskEntry->NewDisk = TRUE; DiskEntry->LayoutBuffer->PartitionCount = 4; - for (i = 0; i < 4; i++) + for (i = 0; i < 8; i++) DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE; } else @@ -1249,6 +1368,8 @@ UNICODE_STRING Name; HANDLE FileHandle; + DPRINT1("CreatePartitionList()\n"); + List = (PPARTLIST)RtlAllocateHeap(ProcessHeap, 0, sizeof (PARTLIST)); @@ -1358,6 +1479,8 @@ PPARTENTRY PartEntry; PLIST_ENTRY Entry; + DPRINT1("DestroyPartitionList()\n"); + /* Release disk and partition info */ while (!IsListEmpty(&List->DiskListHead)) { @@ -2218,7 +2341,10 @@ return FALSE; } - +/** + * Check if the entry in the partition info slot is the same as in the + * possibly new partition entry. + */ static BOOLEAN IsSamePrimaryLayoutEntry( @@ -2228,71 +2354,270 @@ { if (PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector && PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) -// PartitionInfo->PartitionNumber = PartEntry->PartitionNumber && -// PartitionInfo->PartitionType == PartEntry->PartitionType return TRUE; return FALSE; } +static ULONG GetLogicalPartitionCount(PDISKENTRY DiskEntry) +{ + ULONG logical = 0; + PLIST_ENTRY ListEntry; + PLIST_ENTRY ListHead; + PPARTENTRY PartEntry; -static -VOID -UpdateDiskLayout( - IN PDISKENTRY DiskEntry) + ListEntry = DiskEntry->LogicalPartListHead.Flink; + ListHead = &DiskEntry->LogicalPartListHead; + while (ListEntry != ListHead) + { + PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); + if(PartEntry->IsPartitioned) + logical++; + ListEntry = ListEntry->Flink; + } + + return logical; +} + +/** + * In case of logical drives, we have to create additional partition entries + * in the table. Since we don't know how many logical partitions will be created + * we have to reallocate the drive info to accomodate new entries. + * + * The first four entries are always there and reserved for up to four primary + * and at most one extended partitions (allowing for three primaries in this case). + * For each logical partition added, it needs a separate set of four entries + * where the first slot takes the data of the logical partition layout. + * If another logical partition follows, then the second slot will take + * another partition entry marked as extended. If it is the last logical + * partition, then this slot stays empty. The other two slots are always + * unused. + */ +BOOL ReallocDriveLayout(PDISKENTRY DiskEntry) { - PPARTITION_INFORMATION PartitionInfo; + ULONG primary = 0; + ULONG extended = 0; + ULONG logical = 0; + ULONG total = 0; PLIST_ENTRY ListEntry; + PLIST_ENTRY ListHead; PPARTENTRY PartEntry; - ULONG Index = 0; + PDRIVE_LAYOUT_INFORMATION layout; + ULONG LayoutBufferSize; + + DPRINT1("ReallocDriveLayout()\n"); + + if(DiskEntry == NULL) + return FALSE; + + ListEntry = DiskEntry->PrimaryPartListHead.Flink; + ListHead = &DiskEntry->PrimaryPartListHead; + while (ListEntry != ListHead) + { + PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); + if (PartEntry->IsPartitioned == TRUE) + { + if(IsContainerPartition(PartEntry->PartitionType)) + extended++; + else + primary++; + } + + ListEntry = ListEntry->Flink; + } + logical = GetLogicalPartitionCount(DiskEntry); + + DPRINT1("Primary: %lu Extended: %lu Logical: %lu\n", primary, extended, logical); + if(primary > 4 || extended > 1 || (primary + extended) > 4) + { + DPRINT1("Invalid combination of partitions\n"); + return FALSE; + } + + total = primary+extended; + if(total < 4) + total = 4; + total += logical*4; + + if(DiskEntry->LayoutBuffer) + { + DPRINT1("New #: %lu Current #: %lu\n", total, DiskEntry->LayoutBuffer->PartitionCount); + + // Nothing to do if the new count is the same as before. + if(total == DiskEntry->LayoutBuffer->PartitionCount) + return TRUE; + } + + LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) + + ((total - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION)); + layout = RtlAllocateHeap(ProcessHeap, + HEAP_ZERO_MEMORY, + LayoutBufferSize); + if (layout == NULL) + { + DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize); + return FALSE; + } + + if(DiskEntry->LayoutBuffer) + { + // Copy the existing entries to the new layout buffer. + if(DiskEntry->LayoutBuffer->PartitionCount < total) + LayoutBufferSize = DiskEntry->LayoutBuffer->PartitionCount; // partitions have been removed + else + LayoutBufferSize = total; // partitions have been added + + LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) + + ((LayoutBufferSize - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION)); + RtlCopyMemory(layout, DiskEntry->LayoutBuffer, LayoutBufferSize); + RtlFreeHeap(ProcessHeap, 0, DiskEntry->LayoutBuffer); + } + + DiskEntry->LayoutBuffer = layout; + DiskEntry->LayoutBuffer->PartitionCount = total; + + return TRUE; +} + +static VOID UpdateDiskLayout(IN PDISKENTRY DiskEntry) +{ + PLIST_ENTRY ListEntry; + PLIST_ENTRY ListHead; + ULONG Index; + PPARTITION_INFORMATION PartitionInfo; + PPARTITION_INFORMATION ExtendedInfo; + PPARTITION_INFORMATION LogicalPartitionInfo; + PPARTENTRY PartEntry; + LONGLONG BaseOfs; + LONGLONG ofs; ULONG PartitionNumber = 1; + ULONG i; + ULONG logical; -DPRINT1("UpdateDiskLayout()\n"); + DPRINT1("UpdateDiskLayout()\n"); + // Make sure that we have enough entries in the array to handle all + // logical drives. + if(ReallocDriveLayout(DiskEntry) == FALSE) + { + DPRINT1("ReallocDriveLayout() failed.\n"); + return; + } + ListEntry = DiskEntry->PrimaryPartListHead.Flink; - while (ListEntry != &DiskEntry->PrimaryPartListHead) + ListHead = &DiskEntry->PrimaryPartListHead; + Index = 0; + + while (ListEntry != ListHead) { PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); + DumpPartition("[Layout]", PartEntry); if (PartEntry->IsPartitioned == TRUE) { PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; + // If the layout of the partition hasn't changed, we can leave this + // entry as it is. if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry)) { -DPRINT1("Updating partition entry %lu\n", Index); + DPRINT1("Updating partition entry %lu\n", Index); + PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector; PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; PartitionInfo->HiddenSectors = 0; - PartitionInfo->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0; PartitionInfo->PartitionType = PartEntry->PartitionType; PartitionInfo->BootIndicator = PartEntry->BootIndicator; PartitionInfo->RecognizedPartition = FALSE; PartitionInfo->RewritePartition = TRUE; - + PartitionInfo->PartitionNumber = PartitionNumber; PartEntry->PartitionNumber = PartitionNumber; PartEntry->PartitionIndex = Index; - - PartitionNumber++; } - else if (!IsEmptyLayoutEntry(PartitionInfo)) - { - PartitionNumber++; - } Index++; + PartitionNumber++; + + DumpPartitionInfo("[Layout]", PartitionInfo); } ListEntry = ListEntry->Flink; } - for (;Index < 4; Index++) + Index = 4; + logical = GetLogicalPartitionCount(DiskEntry); + BaseOfs = DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart; + ofs = BaseOfs; + ExtendedInfo = NULL; + + // Now process the logical partitions. If there is no extended + // partition this can be skipped, because there can be no logical + // ones either (and if there were some it would be wrong anyway). + if(DiskEntry->ExtendedPartition) { - PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; + PartitionNumber = DiskEntry->ExtendedPartition->PartitionNumber; + ListEntry = DiskEntry->LogicalPartListHead.Flink; + ListHead = &DiskEntry->LogicalPartListHead; - if (!IsEmptyLayoutEntry(PartitionInfo)) + while(ListEntry != ListHead) { -DPRINT1("Wiping partition entry %lu\n", Index); + PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); + DumpPartition("[Layout]", PartEntry); + if(PartEntry->IsPartitioned) + { + PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; + LogicalPartitionInfo = PartitionInfo; + + PartitionInfo->StartingOffset.QuadPart = BaseOfs+ofs; + PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; + PartitionInfo->HiddenSectors = 0; + PartitionInfo->PartitionType = PartEntry->PartitionType; + PartitionInfo->BootIndicator = PartEntry->BootIndicator; + PartitionInfo->RecognizedPartition = FALSE; + PartitionInfo->RewritePartition = TRUE; + PartitionInfo->PartitionNumber = PartitionNumber; + PartEntry->PartitionNumber = PartitionNumber; + PartEntry->PartitionIndex = Index; + if(ExtendedInfo) + ExtendedInfo->PartitionLength.QuadPart = PartitionInfo->PartitionLength.QuadPart + BaseOfs; + + // Create the corresponding extended partition entry + // for the chain of logical partitions. + Index++; + + // If it is the last logical partition, we don't need + // a corresponding extended entry + if((Index+4) <= DiskEntry->LayoutBuffer->PartitionCount) + { + PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; + ExtendedInfo = PartitionInfo; + PartitionInfo->PartitionNumber = PartitionNumber+logical; + PartitionInfo->PartitionType = PARTITION_EXTENDED; + PartitionInfo->StartingOffset.QuadPart = LogicalPartitionInfo->StartingOffset.QuadPart + LogicalPartitionInfo->PartitionLength.QuadPart; + ofs = PartitionInfo->StartingOffset.QuadPart; + + PartitionInfo->RecognizedPartition = FALSE; + PartitionInfo->RewritePartition = TRUE; + + PartitionNumber++; + } + else + ExtendedInfo = NULL; + + Index += 3; + } + ListEntry = ListEntry->Flink; + } + } + + for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++) + { + PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i]; + + if (IsEmptyLayoutEntry(PartitionInfo)) + { + DPRINT1("Wiping partition entry %lu\n", i); + PartitionInfo->StartingOffset.QuadPart = 0; PartitionInfo->PartitionLength.QuadPart = 0; PartitionInfo->HiddenSectors = 0; @@ -2304,9 +2629,7 @@ } } -#ifdef DUMP_PARTITION_TABLE DumpPartitionTable(DiskEntry); -#endif } @@ -2365,9 +2688,9 @@ DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount); if (List == NULL || - List->CurrentDisk == NULL || - List->CurrentPartition == NULL || - List->CurrentPartition->IsPartitioned == TRUE) + List->CurrentDisk == NULL || + List->CurrentPartition == NULL || + List->CurrentPartition->IsPartitioned == TRUE) { return; } @@ -2375,59 +2698,50 @@ DiskEntry = List->CurrentDisk; PartEntry = List->CurrentPartition; -DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart); + DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart); if (AutoCreate == TRUE || Align(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart) { -DPRINT1("Convert existing partition entry\n"); - /* Convert current entry to 'new (unformatted)' */ - PartEntry->IsPartitioned = TRUE; - PartEntry->PartitionType = PARTITION_ENTRY_UNUSED; - PartEntry->FormatState = Unformatted; - PartEntry->AutoCreate = AutoCreate; - PartEntry->New = TRUE; - PartEntry->BootIndicator = FALSE; - -DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart); -DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1); -DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart); + DPRINT1("Convert existing partition entry\n"); } else { -DPRINT1("Add new partition entry\n"); + DPRINT1("Add new partition entry\n"); /* Insert and initialize a new partition entry */ NewPartEntry = RtlAllocateHeap(ProcessHeap, - HEAP_ZERO_MEMORY, - sizeof(PARTENTRY)); + HEAP_ZERO_MEMORY, + sizeof(PARTENTRY)); if (NewPartEntry == NULL) return; /* Insert the new entry into the list */ - InsertTailList(&PartEntry->ListEntry, - &NewPartEntry->ListEntry); + InsertTailList(&PartEntry->ListEntry, &NewPartEntry->ListEntry); NewPartEntry->DiskEntry = DiskEntry; - NewPartEntry->IsPartitioned = TRUE; NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - - NewPartEntry->StartSector.QuadPart; - NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED; + NewPartEntry->StartSector.QuadPart; -DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); -DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); -DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart); - - NewPartEntry->New = TRUE; - NewPartEntry->FormatState = Unformatted; - NewPartEntry->BootIndicator = FALSE; - PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart; PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart); + + PartEntry = NewPartEntry; } + PartEntry->IsPartitioned = TRUE; + PartEntry->FormatState = Unformatted; + PartEntry->BootIndicator = FALSE; + PartEntry->AutoCreate = AutoCreate; + PartEntry->PartitionType = PARTITION_ENTRY_UNUSED; + PartEntry->New = TRUE; + + DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart); + DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1); + DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart); + UpdateDiskLayout(DiskEntry); DiskEntry->Dirty = TRUE; @@ -2437,7 +2751,6 @@ AssignDriveLetters(List); } - static VOID AddLogicalDiskSpace( @@ -2469,6 +2782,8 @@ InsertTailList(&DiskEntry->LogicalPartListHead, &NewPartEntry->ListEntry); + + DumpPartition("[NewLogicalDiskspace]", NewPartEntry); } @@ -2494,82 +2809,65 @@ DiskEntry = List->CurrentDisk; PartEntry = List->CurrentPartition; -DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart); + DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart); if (Align(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart) { -DPRINT1("Convert existing partition entry\n"); + DPRINT1("Convert existing partition entry\n"); + /* Convert current entry to 'new (unformatted)' */ - PartEntry->IsPartitioned = TRUE; - PartEntry->FormatState = Formatted; - PartEntry->AutoCreate = FALSE; - PartEntry->New = FALSE; - PartEntry->BootIndicator = FALSE; - - if (PartEntry->StartSector.QuadPart < 1450560) - { - /* Partition starts below the 8.4GB boundary ==> CHS partition */ - PartEntry->PartitionType = PARTITION_EXTENDED; - } - else - { - /* Partition starts above the 8.4GB boundary ==> LBA partition */ - PartEntry->PartitionType = PARTITION_XINT13_EXTENDED; - } - DiskEntry->ExtendedPartition = PartEntry; - -DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart); -DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1); -DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart); } else { -DPRINT1("Add new partition entry\n"); + DPRINT1("Add new partition entry\n"); /* Insert and initialize a new partition entry */ NewPartEntry = RtlAllocateHeap(ProcessHeap, - HEAP_ZERO_MEMORY, - sizeof(PARTENTRY)); + HEAP_ZERO_MEMORY, + sizeof(PARTENTRY)); + if (NewPartEntry == NULL) return; /* Insert the new entry into the list */ InsertTailList(&PartEntry->ListEntry, - &NewPartEntry->ListEntry); + &NewPartEntry->ListEntry); NewPartEntry->DiskEntry = DiskEntry; - NewPartEntry->IsPartitioned = TRUE; NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - - NewPartEntry->StartSector.QuadPart; + NewPartEntry->StartSector.QuadPart; - NewPartEntry->New = FALSE; - NewPartEntry->FormatState = Formatted; - NewPartEntry->BootIndicator = FALSE; - - if (NewPartEntry->StartSector.QuadPart < 1450560) - { - /* Partition starts below the 8.4GB boundary ==> CHS partition */ - NewPartEntry->PartitionType = PARTITION_EXTENDED; - } - else - { - /* Partition starts above the 8.4GB boundary ==> LBA partition */ - NewPartEntry->PartitionType = PARTITION_XINT13_EXTENDED; - } - DiskEntry->ExtendedPartition = NewPartEntry; - PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart; PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart); -DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); -DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); -DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart); + PartEntry = NewPartEntry; } + PartEntry->AutoCreate = FALSE; + PartEntry->BootIndicator = FALSE; + PartEntry->FormatState = Formatted; + PartEntry->IsPartitioned = TRUE; + PartEntry->New = FALSE; + + if (PartEntry->StartSector.QuadPart < 1450560) + { + /* Partition starts below the 8.4GB boundary ==> CHS partition */ + PartEntry->PartitionType = PARTITION_EXTENDED; + } + else + { + /* Partition starts above the 8.4GB boundary ==> LBA partition */ + PartEntry->PartitionType = PARTITION_XINT13_EXTENDED; + } + + DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart); + DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1); + DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart); + AddLogicalDiskSpace(DiskEntry); UpdateDiskLayout(DiskEntry); @@ -2581,15 +2879,11 @@ AssignDriveLetters(List); } - -VOID -CreateLogicalPartition( - PPARTLIST List, - ULONGLONG SectorCount) +VOID CreateLogicalPartition(PPARTLIST List, ULONGLONG SectorCount, BOOLEAN AutoCreate) { -// PDISKENTRY DiskEntry; + PDISKENTRY DiskEntry; PPARTENTRY PartEntry; -// PPARTENTRY NewPartEntry; + PPARTENTRY NewPartEntry; DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount); @@ -2601,13 +2895,58 @@ return; } -// DiskEntry = List->CurrentDisk; + DiskEntry = List->CurrentDisk; PartEntry = List->CurrentPartition; - DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart); + if(DiskEntry == NULL || PartEntry == NULL) + return; + + DumpPartition("[Current]", PartEntry); + + // If the new partition uses the remainder of the available space + // we reuse the current entry, otherwise we have to add a new + // entry. + if (AutoCreate == FALSE && Align(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart != PartEntry->SectorCount.QuadPart) + { + /* Insert and initialize a new partition entry */ + NewPartEntry = RtlAllocateHeap(ProcessHeap, + HEAP_ZERO_MEMORY, + sizeof(PARTENTRY)); + + if (NewPartEntry == NULL) + return; + + /* Insert the new entry into the list */ + InsertTailList(&PartEntry->ListEntry, &NewPartEntry->ListEntry); + + NewPartEntry->DiskEntry = DiskEntry; + NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; + NewPartEntry->SectorCount.QuadPart = SectorCount; + + PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart; + PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart); + + PartEntry = NewPartEntry; + } + + PartEntry->SectorCount.QuadPart = Align(PartEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment); + PartEntry->IsPartitioned = TRUE; + PartEntry->FormatState = Unformatted; + PartEntry->AutoCreate = FALSE; + PartEntry->New = FALSE; + PartEntry->BootIndicator = FALSE; + PartEntry->LogicalPartition = TRUE; + PartEntry->PartitionType = 0; + PartEntry->PartitionType = PARTITION_FAT32; + //PartEntry->PartitionType = PARTITION_FAT32_XINT13; + + UpdateDiskLayout(DiskEntry); + DiskEntry->Dirty = TRUE; + UpdatePartitionNumbers(DiskEntry); + AssignDriveLetters(List); + DumpPartition("[LogicalCreated]", PartEntry); } - VOID DeleteCurrentPartition( PPARTLIST List) @@ -2881,15 +3220,14 @@ DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber); swprintf(DstPath, - L"\\Device\\Harddisk%d\\Partition0", - DiskEntry->DiskNumber); - RtlInitUnicodeString(&Name, - DstPath); + L"\\Device\\Harddisk%d\\Partition0", + DiskEntry->DiskNumber); + RtlInitUnicodeString(&Name, DstPath); InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); + &Name, + 0, + NULL, + NULL); Status = NtOpenFile(&FileHandle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, @@ -2899,34 +3237,30 @@ FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { - DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); + DPRINT1("NtOpenFile(\\Device\\Harddisk%d\\Partition0) failed (Status %lx)\n", DiskEntry->DiskNumber, Status); return Status; } -#ifdef DUMP_PARTITION_TABLE DumpPartitionTable(DiskEntry); -#endif BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) + - ((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION)); + ((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION)); Status = NtDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_DISK_SET_DRIVE_LAYOUT, - DiskEntry->LayoutBuffer, - BufferSize, - NULL, - 0); + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_SET_DRIVE_LAYOUT, + DiskEntry->LayoutBuffer, + BufferSize, + NULL, + 0); if (!NT_SUCCESS(Status)) { DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status); } + NtClose(FileHandle); - if (FileHandle != NULL) - NtClose(FileHandle); - return Status; } @@ -2938,6 +3272,8 @@ PLIST_ENTRY Entry; PDISKENTRY DiskEntry; + DPRINT1("WritePartitionsToDisk(%p)\n", List); + if (List == NULL) return TRUE; @@ -2949,6 +3285,7 @@ if (DiskEntry->Dirty == TRUE) { WritePartitons(List, DiskEntry); + DiskEntry->Dirty = FALSE; } Entry = Entry->Flink; @@ -3006,11 +3343,7 @@ return TRUE; } - -static -ULONG -GetPrimaryPartitionCount( - IN PDISKENTRY DiskEntry) +static ULONG GetPrimaryPartitionCount(IN PDISKENTRY DiskEntry) { PLIST_ENTRY Entry; PPARTENTRY PartEntry; @@ -3021,7 +3354,7 @@ { PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); if (PartEntry->IsPartitioned == TRUE) - nCount++; + nCount++; Entry = Entry->Flink; } @@ -3029,7 +3362,6 @@ return nCount; } - ULONG PrimaryPartitionCreationChecks( IN PPARTLIST List) @@ -3077,7 +3409,6 @@ return ERROR_SUCCESS; } - ULONG LogicalPartitionCreationChecks( IN PPARTLIST List) @@ -3095,4 +3426,5 @@ return ERROR_SUCCESS; } + /* EOF */ Index: reactos/base/setup/usetup/partlist.h =================================================================== --- reactos/base/setup/usetup/partlist.h (revision 67507) +++ reactos/base/setup/usetup/partlist.h (working copy) @@ -111,7 +111,7 @@ BOOLEAN Dirty; BOOLEAN NewDisk; - BOOLEAN NoMbr; /* MBR is absent */ + BOOLEAN Mbr; /* MBR is available */ UNICODE_STRING DriverName; @@ -222,18 +222,19 @@ VOID CreatePrimaryPartition( PPARTLIST List, - ULONGLONG PartitionSize, + ULONGLONG SectorCount, BOOLEAN AutoCreate); VOID CreateExtendedPartition( PPARTLIST List, - ULONGLONG PartitionSize); + ULONGLONG SectorCount); VOID CreateLogicalPartition( PPARTLIST List, - ULONGLONG PartitionSize); + ULONGLONG SectorCount, + BOOLEAN AutoCreate); VOID DeleteCurrentPartition( @@ -263,4 +264,17 @@ LogicalPartitionCreationChecks( IN PPARTLIST List); +/** + * Reallocates the drivelayout structure. The function checks how many primary + * and logical partitions are configured in the disk. If more then four primary + * or more than three primary and more than one extended partition is defined + * FALSE is returned and the layout stays untouched. At minimum four entries + * will be allocated, and for each logical partition additional four + * entries are added. The layoutpointer can be NULL. + */ +BOOL ReallocDriveLayout(PDISKENTRY pDiskEntry); + +VOID DumpPartition(TCHAR *pPrefix, PPARTENTRY pPartition); +VOID DumpPartitionInfo(TCHAR *pPrefix, PPARTITION_INFORMATION pPartitionInfo); + /* EOF */