diff --git a/base/system/diskpart/CMakeLists.txt b/base/system/diskpart/CMakeLists.txt index 6d7d49a3090..9f2cc50b0ff 100644 --- a/base/system/diskpart/CMakeLists.txt +++ b/base/system/diskpart/CMakeLists.txt @@ -24,6 +24,7 @@ list(APPEND SOURCE filesystems.c format.c gpt.c + guid.c help.c import.c inactive.c diff --git a/base/system/diskpart/active.c b/base/system/diskpart/active.c index c247f5b0564..2ff674638ab 100644 --- a/base/system/diskpart/active.c +++ b/base/system/diskpart/active.c @@ -35,16 +35,16 @@ active_main( if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) { - if (CurrentPartition->BootIndicator) + if (CurrentPartition->Mbr.BootIndicator) { ConResPuts(StdOut, IDS_ACTIVE_ALREADY); return TRUE; } - CurrentPartition->BootIndicator = TRUE; + CurrentPartition->Mbr.BootIndicator = TRUE; CurrentDisk->Dirty = TRUE; - UpdateDiskLayout(CurrentDisk); - Status = WritePartitions(CurrentDisk); + UpdateMbrDiskLayout(CurrentDisk); + Status = WriteMbrPartitions(CurrentDisk); if (NT_SUCCESS(Status)) { ConResPuts(StdOut, IDS_ACTIVE_SUCCESS); diff --git a/base/system/diskpart/clean.c b/base/system/diskpart/clean.c index 5057000bf99..2fa04c8b08e 100644 --- a/base/system/diskpart/clean.c +++ b/base/system/diskpart/clean.c @@ -63,7 +63,7 @@ clean_main( PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); /* Dismount the logical partition */ - if (PartEntry->PartitionType != 0) + if (PartEntry->Mbr.PartitionType != 0) { DismountVolume(PartEntry); VolumeEntry = GetVolumeFromPartition(PartEntry); @@ -82,8 +82,8 @@ clean_main( PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); /* Dismount the primary partition */ - if ((PartEntry->PartitionType != 0) && - (IsContainerPartition(PartEntry->PartitionType) == FALSE)) + if ((PartEntry->Mbr.PartitionType != 0) && + (IsContainerPartition(PartEntry->Mbr.PartitionType) == FALSE)) { DismountVolume(PartEntry); VolumeEntry = GetVolumeFromPartition(PartEntry); diff --git a/base/system/diskpart/convert.c b/base/system/diskpart/convert.c index 5878e39280c..0f65042be80 100644 --- a/base/system/diskpart/convert.c +++ b/base/system/diskpart/convert.c @@ -23,7 +23,7 @@ CreateDisk( IO_STATUS_BLOCK Iosb; NTSTATUS Status; - DPRINT1("CreateDisk(%lu %p)\n", DiskNumber, DiskInfo); + DPRINT("CreateDisk(%lu %p)\n", DiskNumber, DiskInfo); StringCchPrintfW(DstPath, ARRAYSIZE(DstPath), L"\\Device\\Harddisk%lu\\Partition0", @@ -64,24 +64,18 @@ CreateDisk( goto done; } - CurrentDisk->PartitionStyle = DiskInfo->PartitionStyle; - /* Free the layout buffer */ if (CurrentDisk->LayoutBuffer) - { RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDisk->LayoutBuffer); - CurrentDisk->LayoutBuffer = NULL; - CurrentDisk->ExtendedPartition = NULL; - } + + CurrentDisk->LayoutBuffer = NULL; + CurrentDisk->ExtendedPartition = NULL; + CurrentDisk->Dirty = FALSE; + CurrentDisk->NewDisk = TRUE; + CurrentDisk->PartitionStyle = DiskInfo->PartitionStyle; ReadLayoutBuffer(FileHandle, CurrentDisk); - DPRINT1("PartitionCount: %lu\n", CurrentDisk->LayoutBuffer->PartitionCount); - -#ifdef DUMP_PARTITION_TABLE - DumpPartitionTable(CurrentDisk); -#endif - done: if (FileHandle) NtClose(FileHandle); @@ -112,7 +106,7 @@ ConvertGPT( return TRUE; } - if (CurrentDisk->LayoutBuffer->PartitionCount != 0) + if (GetPrimaryPartitionCount(CurrentDisk) != 0) { ConResPuts(StdOut, IDS_CONVERT_GPT_NOT_EMPTY); return TRUE; @@ -134,12 +128,17 @@ ConvertGPT( Status = CreateDisk(CurrentDisk->DiskNumber, &DiskInfo); if (!NT_SUCCESS(Status)) { + DPRINT1("CreateDisk() failed!\n"); + return TRUE; + } - } - else - { - ConResPuts(StdOut, IDS_CONVERT_GPT_SUCCESS); - } + CurrentDisk->StartSector.QuadPart = AlignDown(CurrentDisk->LayoutBuffer->Gpt.StartingUsableOffset.QuadPart / CurrentDisk->BytesPerSector, + CurrentDisk->SectorAlignment) + (ULONGLONG)CurrentDisk->SectorAlignment; + CurrentDisk->EndSector.QuadPart = AlignDown(CurrentDisk->StartSector.QuadPart + (CurrentDisk->LayoutBuffer->Gpt.UsableLength.QuadPart / CurrentDisk->BytesPerSector) - 1, + CurrentDisk->SectorAlignment); + + ScanForUnpartitionedGptDiskSpace(CurrentDisk); + ConResPuts(StdOut, IDS_CONVERT_GPT_SUCCESS); return TRUE; } @@ -168,7 +167,7 @@ ConvertMBR( return TRUE; } - if (CurrentDisk->LayoutBuffer->PartitionCount != 0) + if (GetPrimaryPartitionCount(CurrentDisk) != 0) { ConResPuts(StdOut, IDS_CONVERT_MBR_NOT_EMPTY); return TRUE; @@ -180,12 +179,15 @@ ConvertMBR( Status = CreateDisk(CurrentDisk->DiskNumber, &DiskInfo); if (!NT_SUCCESS(Status)) { + DPRINT1("CreateDisk() failed!\n"); + return TRUE; + } - } - else - { - ConResPuts(StdOut, IDS_CONVERT_MBR_SUCCESS); - } + CurrentDisk->StartSector.QuadPart = (ULONGLONG)CurrentDisk->SectorAlignment; + CurrentDisk->EndSector.QuadPart = min(CurrentDisk->SectorCount.QuadPart, 0x100000000) - 1; + + ScanForUnpartitionedMbrDiskSpace(CurrentDisk); + ConResPuts(StdOut, IDS_CONVERT_MBR_SUCCESS); return TRUE; } diff --git a/base/system/diskpart/create.c b/base/system/diskpart/create.c index f2cbcb3723d..bd467202829 100644 --- a/base/system/diskpart/create.c +++ b/base/system/diskpart/create.c @@ -42,8 +42,23 @@ CreateExtendedPartition( } else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_RAW) { - /* FIXME: Initialize disk properly! */ - CurrentDisk->PartitionStyle = PARTITION_STYLE_MBR; + CREATE_DISK DiskInfo; + NTSTATUS Status; + + DiskInfo.PartitionStyle = PARTITION_STYLE_MBR; + CreateSignature(&DiskInfo.Mbr.Signature); + + Status = CreateDisk(CurrentDisk->DiskNumber, &DiskInfo); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CreateDisk() failed!\n"); + return TRUE; + } + + CurrentDisk->StartSector.QuadPart = (ULONGLONG)CurrentDisk->SectorAlignment; + CurrentDisk->EndSector.QuadPart = min(CurrentDisk->SectorCount.QuadPart, 0x100000000) - 1; + + ScanForUnpartitionedMbrDiskSpace(CurrentDisk); } for (i = 3; i < argc; i++) @@ -136,7 +151,7 @@ CreateExtendedPartition( { PartEntry->IsPartitioned = TRUE; PartEntry->New = TRUE; - PartEntry->PartitionType = PARTITION_EXTENDED; + PartEntry->Mbr.PartitionType = PARTITION_EXTENDED; PartEntry->FormatState = Unformatted; PartEntry->FileSystemName[0] = L'\0'; @@ -149,7 +164,7 @@ CreateExtendedPartition( { PartEntry->IsPartitioned = TRUE; PartEntry->New = TRUE; - PartEntry->PartitionType = PARTITION_EXTENDED; + PartEntry->Mbr.PartitionType = PARTITION_EXTENDED; PartEntry->FormatState = Unformatted; PartEntry->FileSystemName[0] = L'\0'; @@ -173,7 +188,7 @@ CreateExtendedPartition( NewPartEntry->LogicalPartition = FALSE; NewPartEntry->IsPartitioned = TRUE; NewPartEntry->New = TRUE; - NewPartEntry->PartitionType = PARTITION_EXTENDED; + NewPartEntry->Mbr.PartitionType = PARTITION_EXTENDED; NewPartEntry->FormatState = Unformatted; NewPartEntry->FileSystemName[0] = L'\0'; @@ -187,8 +202,8 @@ CreateExtendedPartition( } } - UpdateDiskLayout(CurrentDisk); - Status = WritePartitions(CurrentDisk); + UpdateMbrDiskLayout(CurrentDisk); + Status = WriteMbrPartitions(CurrentDisk); if (!NT_SUCCESS(Status)) { ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); @@ -226,7 +241,7 @@ CreateLogicalPartition( return TRUE; } - if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) + if (CurrentDisk->PartitionStyle != PARTITION_STYLE_MBR) { ConResPuts(StdOut, IDS_CREATE_PARTITION_INVALID_STYLE); return TRUE; @@ -332,7 +347,7 @@ CreateLogicalPartition( { PartEntry->IsPartitioned = TRUE; PartEntry->New = TRUE; - PartEntry->PartitionType = PartitionType; + PartEntry->Mbr.PartitionType = PartitionType; PartEntry->FormatState = Unformatted; PartEntry->FileSystemName[0] = L'\0'; @@ -346,7 +361,7 @@ CreateLogicalPartition( { PartEntry->IsPartitioned = TRUE; PartEntry->New = TRUE; - PartEntry->PartitionType = PartitionType; + PartEntry->Mbr.PartitionType = PartitionType; PartEntry->FormatState = Unformatted; PartEntry->FileSystemName[0] = L'\0'; @@ -371,7 +386,7 @@ CreateLogicalPartition( NewPartEntry->LogicalPartition = TRUE; NewPartEntry->IsPartitioned = TRUE; NewPartEntry->New = TRUE; - NewPartEntry->PartitionType = PartitionType; + NewPartEntry->Mbr.PartitionType = PartitionType; NewPartEntry->FormatState = Unformatted; NewPartEntry->FileSystemName[0] = L'\0'; @@ -387,8 +402,8 @@ CreateLogicalPartition( } } - UpdateDiskLayout(CurrentDisk); - Status = WritePartitions(CurrentDisk); + UpdateMbrDiskLayout(CurrentDisk); + Status = WriteMbrPartitions(CurrentDisk); if (!NT_SUCCESS(Status)) { ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); @@ -402,23 +417,280 @@ CreateLogicalPartition( } +static +VOID +CreatePrimaryMbrPartition( + _In_ ULONGLONG ullSize, + _In_ PWSTR pszPartitionType) +{ + PPARTENTRY PartEntry, NewPartEntry; + PLIST_ENTRY ListEntry; + ULONGLONG ullSectorCount; + UCHAR PartitionType; + INT length; + NTSTATUS Status; + + if (pszPartitionType) + { + length = wcslen(pszPartitionType); + if ((length != 1) && (length != 2)) + { + ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); + return; + } + + PartitionType = (UCHAR)wcstoul(pszPartitionType, NULL, 16); + if ((PartitionType == 0) && (errno == ERANGE)) + { + ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); + return; + } + } + else + { + PartitionType = PARTITION_HUGE; + } + + if (GetPrimaryPartitionCount(CurrentDisk) >= 4) + { + ConPuts(StdOut, L"No space left for another primary partition!\n"); + return; + } + + if (ullSize != 0) + ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; + else + ullSectorCount = 0; + + DPRINT1("SectorCount: %I64u\n", ullSectorCount); + + for (ListEntry = CurrentDisk->PrimaryPartListHead.Flink; + ListEntry != &CurrentDisk->PrimaryPartListHead; + ListEntry = ListEntry->Flink) + { + PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); + if (PartEntry->IsPartitioned) + continue; + + if (ullSectorCount == 0) + { + PartEntry->IsPartitioned = TRUE; + PartEntry->New = TRUE; + PartEntry->Mbr.PartitionType = PartitionType; + PartEntry->FormatState = Unformatted; + PartEntry->FileSystemName[0] = L'\0'; + + CurrentPartition = PartEntry; + CurrentDisk->Dirty = TRUE; + break; + } + else + { + if (PartEntry->SectorCount.QuadPart == ullSectorCount) + { + PartEntry->IsPartitioned = TRUE; + PartEntry->New = TRUE; + PartEntry->Mbr.PartitionType = PartitionType; + PartEntry->FormatState = Unformatted; + PartEntry->FileSystemName[0] = L'\0'; + + CurrentPartition = PartEntry; + CurrentDisk->Dirty = TRUE; + break; + } + else if (PartEntry->SectorCount.QuadPart > ullSectorCount) + { + NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PPARTENTRY)); + if (NewPartEntry == NULL) + { + ConPuts(StdOut, L"Memory allocation failed!\n"); + return; + } + + NewPartEntry->DiskEntry = PartEntry->DiskEntry; + + NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; + NewPartEntry->SectorCount.QuadPart = ullSectorCount; + + NewPartEntry->LogicalPartition = FALSE; + NewPartEntry->IsPartitioned = TRUE; + NewPartEntry->New = TRUE; + NewPartEntry->Mbr.PartitionType = PartitionType; + NewPartEntry->FormatState = Unformatted; + NewPartEntry->FileSystemName[0] = L'\0'; + + PartEntry->StartSector.QuadPart += ullSectorCount; + PartEntry->SectorCount.QuadPart -= ullSectorCount; + + InsertTailList(ListEntry, &NewPartEntry->ListEntry); + + CurrentPartition = NewPartEntry; + CurrentDisk->Dirty = TRUE; + break; + } + } + } + + UpdateMbrDiskLayout(CurrentDisk); + Status = WriteMbrPartitions(CurrentDisk); + if (!NT_SUCCESS(Status)) + { + ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); + CurrentPartition = NULL; + return; + } + + ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); +} + + +static +VOID +CreatePrimaryGptPartition( + _In_ ULONGLONG ullSize, + _In_ PWSTR pszPartitionType) +{ + PPARTENTRY PartEntry, NewPartEntry; + PLIST_ENTRY ListEntry; + ULONGLONG ullSectorCount; + GUID guidPartitionType; + NTSTATUS Status; + + /* Partition Type */ + if (pszPartitionType) + { + if (!StringToGUID(&guidPartitionType, pszPartitionType)) + { + ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); + return; + } + } + else + { + CopyMemory(&guidPartitionType, &PARTITION_BASIC_DATA_GUID, sizeof(GUID)); + } + + /* Size */ + if (ullSize != 0) + ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; + else + ullSectorCount = 0; + + DPRINT1("SectorCount: %I64u\n", ullSectorCount); + +#ifdef DUMP_PARTITION_LIST + DumpPartitionList(CurrentDisk); +#endif + + for (ListEntry = CurrentDisk->PrimaryPartListHead.Flink; + ListEntry != &CurrentDisk->PrimaryPartListHead; + ListEntry = ListEntry->Flink) + { + PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); + if (PartEntry->IsPartitioned) + continue; + + if (ullSectorCount == 0) + { + DPRINT("Claim whole unused space!\n"); + PartEntry->IsPartitioned = TRUE; + PartEntry->New = TRUE; + CopyMemory(&PartEntry->Gpt.PartitionType, &guidPartitionType, sizeof(GUID)); + CreateGUID(&PartEntry->Gpt.PartitionId); + PartEntry->Gpt.Attributes = 0ULL; + PartEntry->PartitionNumber = 0; + PartEntry->FormatState = Unformatted; + PartEntry->FileSystemName[0] = L'\0'; + + CurrentPartition = PartEntry; + CurrentDisk->Dirty = TRUE; + break; + } + else + { + if (ullSectorCount == PartEntry->SectorCount.QuadPart) + { + DPRINT("Claim matching unused space!\n"); + PartEntry->IsPartitioned = TRUE; + PartEntry->New = TRUE; + CopyMemory(&PartEntry->Gpt.PartitionType, &guidPartitionType, sizeof(GUID)); + CreateGUID(&PartEntry->Gpt.PartitionId); + PartEntry->Gpt.Attributes = 0ULL; + PartEntry->PartitionNumber = 0; + PartEntry->FormatState = Unformatted; + PartEntry->FileSystemName[0] = L'\0'; + + CurrentPartition = PartEntry; + CurrentDisk->Dirty = TRUE; + break; + } + else if (ullSectorCount < PartEntry->SectorCount.QuadPart) + { + DPRINT("Claim part of unused space\n"); + NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PPARTENTRY)); + if (NewPartEntry == NULL) + { + ConPuts(StdOut, L"Memory allocation failed!\n"); + return; + } + + NewPartEntry->DiskEntry = PartEntry->DiskEntry; + + NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; + NewPartEntry->SectorCount.QuadPart = ullSectorCount; + + NewPartEntry->LogicalPartition = FALSE; + NewPartEntry->IsPartitioned = TRUE; + NewPartEntry->New = TRUE; + CopyMemory(&NewPartEntry->Gpt.PartitionType, &guidPartitionType, sizeof(GUID)); + CreateGUID(&NewPartEntry->Gpt.PartitionId); + NewPartEntry->Gpt.Attributes = 0ULL; + NewPartEntry->PartitionNumber = 0; + NewPartEntry->FormatState = Unformatted; + NewPartEntry->FileSystemName[0] = L'\0'; + + PartEntry->StartSector.QuadPart += ullSectorCount; + PartEntry->SectorCount.QuadPart -= ullSectorCount; + + InsertTailList(ListEntry, &NewPartEntry->ListEntry); + + CurrentPartition = NewPartEntry; + CurrentDisk->Dirty = TRUE; + break; + } + } + } + +#ifdef DUMP_PARTITION_LIST + DumpPartitionList(CurrentDisk); +#endif + + UpdateGptDiskLayout(CurrentDisk, FALSE); + Status = WriteGptPartitions(CurrentDisk); + if (!NT_SUCCESS(Status)) + { + ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); + CurrentPartition = NULL; + return; + } + + ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); +} + + BOOL CreatePrimaryPartition( _In_ INT argc, _In_ PWSTR *argv) { - PPARTENTRY PartEntry, NewPartEntry; - PLIST_ENTRY ListEntry; ULONGLONG ullSize = 0ULL; - ULONGLONG ullSectorCount; #if 0 ULONGLONG ullOffset = 0ULL; BOOL bNoErr = FALSE; #endif - UCHAR PartitionType = PARTITION_HUGE; - INT i, length; + INT i; PWSTR pszSuffix = NULL; - NTSTATUS Status; + PWSTR pszPartitionType = NULL; if (CurrentDisk == NULL) { @@ -426,15 +698,25 @@ CreatePrimaryPartition( return TRUE; } - if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) + if (CurrentDisk->PartitionStyle == PARTITION_STYLE_RAW) { - ConPuts(StdOut, L"GPT Partitions are not supported yet!\n"); - return TRUE; - } - else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_RAW) - { - /* FIXME: Initialize disk properly! */ - CurrentDisk->PartitionStyle = PARTITION_STYLE_MBR; + CREATE_DISK DiskInfo; + NTSTATUS Status; + + DiskInfo.PartitionStyle = PARTITION_STYLE_MBR; + CreateSignature(&DiskInfo.Mbr.Signature); + + Status = CreateDisk(CurrentDisk->DiskNumber, &DiskInfo); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CreateDisk() failed!\n"); + return TRUE; + } + + CurrentDisk->StartSector.QuadPart = (ULONGLONG)CurrentDisk->SectorAlignment; + CurrentDisk->EndSector.QuadPart = min(CurrentDisk->SectorCount.QuadPart, 0x100000000) - 1; + + ScanForUnpartitionedMbrDiskSpace(CurrentDisk); } for (i = 3; i < argc; i++) @@ -469,29 +751,7 @@ CreatePrimaryPartition( { /* id=| */ DPRINT("Id : %s\n", pszSuffix); - - length = wcslen(pszSuffix); - if ((length == 1) || (length == 2)) - { - /* Byte */ - PartitionType = (UCHAR)wcstoul(pszSuffix, NULL, 16); - if ((PartitionType == 0) && (errno == ERANGE)) - { - ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); - return TRUE; - } - } -#if 0 - else if () - { - /* GUID */ - } -#endif - else - { - ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); - return TRUE; - } + pszPartitionType = pszSuffix; } else if (HasPrefix(argv[i], L"align=", &pszSuffix)) { @@ -518,102 +778,20 @@ CreatePrimaryPartition( } } - DPRINT1("Size: %I64u\n", ullSize); + DPRINT("Size: %I64u\n", ullSize); #if 0 DPRINT1("Offset: %I64u\n", ullOffset); #endif - DPRINT1("Partition Type: %hx\n", PartitionType); - if (GetPrimaryPartitionCount(CurrentDisk) >= 4) + if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) { - ConPuts(StdOut, L"No space left for another primary partition!\n"); - return TRUE; + DPRINT("Partition Type: %s\n", pszPartitionType); + CreatePrimaryMbrPartition(ullSize, pszPartitionType); } - - if (ullSize != 0) - ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; - else - ullSectorCount = 0; - - DPRINT1("SectorCount: %I64u\n", ullSectorCount); - - for (ListEntry = CurrentDisk->PrimaryPartListHead.Flink; - ListEntry != &CurrentDisk->PrimaryPartListHead; - ListEntry = ListEntry->Flink) + else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) { - PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); - if (PartEntry->IsPartitioned) - continue; - - if (ullSectorCount == 0) - { - PartEntry->IsPartitioned = TRUE; - PartEntry->New = TRUE; - PartEntry->PartitionType = PartitionType; - PartEntry->FormatState = Unformatted; - PartEntry->FileSystemName[0] = L'\0'; - - CurrentPartition = PartEntry; - CurrentDisk->Dirty = TRUE; - break; - } - else - { - if (PartEntry->SectorCount.QuadPart == ullSectorCount) - { - PartEntry->IsPartitioned = TRUE; - PartEntry->New = TRUE; - PartEntry->PartitionType = PartitionType; - PartEntry->FormatState = Unformatted; - PartEntry->FileSystemName[0] = L'\0'; - - CurrentPartition = PartEntry; - CurrentDisk->Dirty = TRUE; - break; - } - else if (PartEntry->SectorCount.QuadPart > ullSectorCount) - { - NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PPARTENTRY)); - if (NewPartEntry == NULL) - { - ConPuts(StdOut, L"Memory allocation failed!\n"); - return TRUE; - } - - NewPartEntry->DiskEntry = PartEntry->DiskEntry; - - NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; - NewPartEntry->SectorCount.QuadPart = ullSectorCount; - - NewPartEntry->LogicalPartition = FALSE; - NewPartEntry->IsPartitioned = TRUE; - NewPartEntry->New = TRUE; - NewPartEntry->PartitionType = PartitionType; - NewPartEntry->FormatState = Unformatted; - NewPartEntry->FileSystemName[0] = L'\0'; - - PartEntry->StartSector.QuadPart += ullSectorCount; - PartEntry->SectorCount.QuadPart -= ullSectorCount; - - InsertTailList(ListEntry, &NewPartEntry->ListEntry); - - CurrentPartition = NewPartEntry; - CurrentDisk->Dirty = TRUE; - break; - } - } + CreatePrimaryGptPartition(ullSize, pszPartitionType); } - UpdateDiskLayout(CurrentDisk); - Status = WritePartitions(CurrentDisk); - if (!NT_SUCCESS(Status)) - { - ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); - CurrentPartition = NULL; - return TRUE; - } - - ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); - return TRUE; } diff --git a/base/system/diskpart/delete.c b/base/system/diskpart/delete.c index 53b560100cb..304eed72be9 100644 --- a/base/system/diskpart/delete.c +++ b/base/system/diskpart/delete.c @@ -16,8 +16,8 @@ BOOL IsKnownPartition( _In_ PPARTENTRY PartEntry) { - if (IsRecognizedPartition(PartEntry->PartitionType) || - IsContainerPartition(PartEntry->PartitionType)) + if (IsRecognizedPartition(PartEntry->Mbr.PartitionType) || + IsContainerPartition(PartEntry->Mbr.PartitionType)) return TRUE; return FALSE; @@ -33,59 +33,18 @@ DeleteDisk( } -BOOL -DeletePartition( - _In_ INT argc, - _In_ PWSTR *argv) +static +VOID +DeleteMbrPartition( + _In_ BOOL bOverride) { PPARTENTRY PrevPartEntry; PPARTENTRY NextPartEntry; PPARTENTRY LogicalPartEntry; PLIST_ENTRY Entry; - INT i; - BOOL bOverride = FALSE; NTSTATUS Status; - DPRINT("DeletePartition()\n"); - - if (CurrentDisk == NULL) - { - ConResPuts(StdOut, IDS_SELECT_NO_DISK); - return TRUE; - } - - if (CurrentPartition == NULL) - { - ConResPuts(StdOut, IDS_SELECT_NO_PARTITION); - return TRUE; - } - - ASSERT(CurrentPartition->PartitionType != PARTITION_ENTRY_UNUSED); - - for (i = 2; i < argc; i++) - { - if (_wcsicmp(argv[i], L"noerr") == 0) - { - /* noerr */ - DPRINT("NOERR\n"); - ConPuts(StdOut, L"The NOERR option is not supported yet!\n"); -#if 0 - bNoErr = TRUE; -#endif - } - else if (_wcsicmp(argv[i], L"override") == 0) - { - /* override */ - DPRINT("OVERRIDE\n"); - bOverride = TRUE; - } - else - { - ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); - return TRUE; - } - } - + ASSERT(CurrentPartition->Mbr.PartitionType != PARTITION_ENTRY_UNUSED); /* Clear the system partition if it is being deleted */ #if 0 @@ -99,7 +58,7 @@ DeletePartition( if ((bOverride == FALSE) && (IsKnownPartition(CurrentPartition) == FALSE)) { ConResPuts(StdOut, IDS_DELETE_PARTITION_FAIL); - return FALSE; + return; } /* Check which type of partition (primary/logical or extended) is being deleted */ @@ -175,8 +134,8 @@ DeletePartition( CurrentPartition->OnDiskPartitionNumber = 0; CurrentPartition->PartitionNumber = 0; // CurrentPartition->PartitionIndex = 0; - CurrentPartition->BootIndicator = FALSE; - CurrentPartition->PartitionType = PARTITION_ENTRY_UNUSED; + CurrentPartition->Mbr.BootIndicator = FALSE; + CurrentPartition->Mbr.PartitionType = PARTITION_ENTRY_UNUSED; CurrentPartition->FormatState = Unformatted; CurrentPartition->FileSystemName[0] = L'\0'; CurrentPartition->DriveLetter = 0; @@ -185,15 +144,185 @@ DeletePartition( CurrentPartition = NULL; - UpdateDiskLayout(CurrentDisk); - Status = WritePartitions(CurrentDisk); + UpdateMbrDiskLayout(CurrentDisk); + Status = WriteMbrPartitions(CurrentDisk); if (!NT_SUCCESS(Status)) { ConResPuts(StdOut, IDS_DELETE_PARTITION_FAIL); - return TRUE; + return; } ConResPuts(StdOut, IDS_DELETE_PARTITION_SUCCESS); +} + + +static +VOID +DeleteGptPartition( + _In_ BOOL bOverride) +{ + PPARTENTRY PrevPartEntry; + PPARTENTRY NextPartEntry; + NTSTATUS Status; + + /* Clear the system partition if it is being deleted */ +#if 0 + if (List->SystemPartition == PartEntry) + { + ASSERT(List->SystemPartition); + List->SystemPartition = NULL; + } +#endif +#if 0 + if ((bOverride == FALSE) && (IsKnownPartition(CurrentPartition) == FALSE)) + { + ConResPuts(StdOut, IDS_DELETE_PARTITION_FAIL); + return; + } +#endif + +#ifdef DUMP_PARTITION_LIST + DumpPartitionList(CurrentDisk); +#endif + + /* Dismount the partition */ + DismountVolume(CurrentPartition); + + /* Adjust the unpartitioned disk space entries */ + + /* Get pointer to previous and next unpartitioned entries */ + PrevPartEntry = GetPrevUnpartitionedEntry(CurrentPartition); + NextPartEntry = GetNextUnpartitionedEntry(CurrentPartition); + + if (PrevPartEntry != NULL && NextPartEntry != NULL) + { + /* Merge the previous, current and next unpartitioned entries */ + + /* Adjust the previous entry length */ + PrevPartEntry->SectorCount.QuadPart += (CurrentPartition->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart); + + /* Remove the current and next entries */ + RemoveEntryList(&CurrentPartition->ListEntry); + RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentPartition); + RemoveEntryList(&NextPartEntry->ListEntry); + RtlFreeHeap(RtlGetProcessHeap(), 0, NextPartEntry); + } + else if (PrevPartEntry != NULL && NextPartEntry == NULL) + { + /* Merge the current and the previous unpartitioned entries */ + + /* Adjust the previous entry length */ + PrevPartEntry->SectorCount.QuadPart += CurrentPartition->SectorCount.QuadPart; + + /* Remove the current entry */ + RemoveEntryList(&CurrentPartition->ListEntry); + RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentPartition); + } + else if (PrevPartEntry == NULL && NextPartEntry != NULL) + { + /* Merge the current and the next unpartitioned entries */ + + /* Adjust the next entry offset and length */ + NextPartEntry->StartSector.QuadPart = CurrentPartition->StartSector.QuadPart; + NextPartEntry->SectorCount.QuadPart += CurrentPartition->SectorCount.QuadPart; + + /* Remove the current entry */ + RemoveEntryList(&CurrentPartition->ListEntry); + RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentPartition); + } + else + { + /* Nothing to merge but change the current entry */ + CurrentPartition->IsPartitioned = FALSE; + CurrentPartition->OnDiskPartitionNumber = 0; + CurrentPartition->PartitionNumber = 0; + // CurrentPartition->PartitionIndex = 0; + + ZeroMemory(&CurrentPartition->Gpt.PartitionType, sizeof(GUID)); + ZeroMemory(&CurrentPartition->Gpt.PartitionId, sizeof(GUID)); + CurrentPartition->Gpt.Attributes = 0ULL; + + CurrentPartition->FormatState = Unformatted; + CurrentPartition->FileSystemName[0] = L'\0'; + CurrentPartition->DriveLetter = 0; + RtlZeroMemory(CurrentPartition->VolumeLabel, sizeof(CurrentPartition->VolumeLabel)); + } + + CurrentPartition = NULL; + +#ifdef DUMP_PARTITION_LIST + DumpPartitionList(CurrentDisk); +#endif + + UpdateGptDiskLayout(CurrentDisk, TRUE); +#ifdef DUMP_PARTITION_TABLE + DumpPartitionTable(CurrentDisk); +#endif + Status = WriteGptPartitions(CurrentDisk); + if (!NT_SUCCESS(Status)) + { + ConResPuts(StdOut, IDS_DELETE_PARTITION_FAIL); + return; + } + + ConResPuts(StdOut, IDS_DELETE_PARTITION_SUCCESS); +} + + +BOOL +DeletePartition( + _In_ INT argc, + _In_ PWSTR *argv) +{ + INT i; + BOOL bOverride = FALSE; + + DPRINT("DeletePartition()\n"); + + if (CurrentDisk == NULL) + { + ConResPuts(StdOut, IDS_SELECT_NO_DISK); + return TRUE; + } + + if (CurrentPartition == NULL) + { + ConResPuts(StdOut, IDS_SELECT_NO_PARTITION); + return TRUE; + } + + for (i = 2; i < argc; i++) + { + if (_wcsicmp(argv[i], L"noerr") == 0) + { + /* noerr */ + DPRINT("NOERR\n"); + ConPuts(StdOut, L"The NOERR option is not supported yet!\n"); +#if 0 + bNoErr = TRUE; +#endif + } + else if (_wcsicmp(argv[i], L"override") == 0) + { + /* override */ + DPRINT("OVERRIDE\n"); + bOverride = TRUE; + } + else + { + ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); + return TRUE; + } + } + + if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) + { + DeleteMbrPartition(bOverride); + } + else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) + { + DeleteGptPartition(bOverride); + } return TRUE; } diff --git a/base/system/diskpart/detail.c b/base/system/diskpart/detail.c index 2bdee7b03a8..f2f09d820c2 100644 --- a/base/system/diskpart/detail.c +++ b/base/system/diskpart/detail.c @@ -138,6 +138,7 @@ DetailPartition( PLIST_ENTRY Entry; PVOLENTRY VolumeEntry; BOOL bVolumeFound = FALSE, bPrintHeader = TRUE; + WCHAR szBuffer[40]; DPRINT("DetailPartition()\n"); @@ -165,9 +166,21 @@ DetailPartition( /* TODO: Print more partition details */ ConPuts(StdOut, L"\n"); ConResPrintf(StdOut, IDS_DETAIL_PARTITION_NUMBER, PartEntry->PartitionNumber); - ConResPrintf(StdOut, IDS_DETAIL_PARTITION_TYPE, PartEntry->PartitionType); - ConResPrintf(StdOut, IDS_DETAIL_PARTITION_HIDDEN, ""); - ConResPrintf(StdOut, IDS_DETAIL_PARTITION_ACTIVE, PartEntry->BootIndicator ? L"Yes" : L"No"); + if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) + { + PrintGUID(szBuffer, &PartEntry->Gpt.PartitionType); + ConResPrintf(StdOut, IDS_DETAIL_PARTITION_TYPE, szBuffer); + ConResPrintf(StdOut, IDS_DETAIL_PARTITION_HIDDEN, (PartEntry->Gpt.Attributes & GPT_BASIC_DATA_ATTRIBUTE_HIDDEN) ? L"Yes" : L"No"); + ConResPrintf(StdOut, IDS_DETAIL_PARTITION_REQUIRED, (PartEntry->Gpt.Attributes & GPT_ATTRIBUTE_PLATFORM_REQUIRED) ? L"Yes" : L"No"); + ConResPrintf(StdOut, IDS_DETAIL_PARTITION_ATTRIBUTE, PartEntry->Gpt.Attributes); + } + else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) + { + swprintf(szBuffer, L"%02x", PartEntry->Mbr.PartitionType); + ConResPrintf(StdOut, IDS_DETAIL_PARTITION_TYPE, szBuffer); + ConResPrintf(StdOut, IDS_DETAIL_PARTITION_HIDDEN, ""); + ConResPrintf(StdOut, IDS_DETAIL_PARTITION_ACTIVE, PartEntry->Mbr.BootIndicator ? L"Yes" : L"No"); + } ConResPrintf(StdOut, IDS_DETAIL_PARTITION_OFFSET, PartOffset); Entry = VolumeListHead.Flink; diff --git a/base/system/diskpart/diskpart.h b/base/system/diskpart/diskpart.h index dafbcce4016..5372f1ac5f1 100644 --- a/base/system/diskpart/diskpart.h +++ b/base/system/diskpart/diskpart.h @@ -50,10 +50,13 @@ #include #include +#include +#include "guid.h" #include "resource.h" //#define DUMP_PARTITION_TABLE +//#define DUMP_PARTITION_LIST /* DEFINES *******************************************************************/ @@ -98,6 +101,19 @@ typedef enum _VOLUME_TYPE VOLUME_TYPE_UNKNOWN } VOLUME_TYPE, *PVOLUME_TYPE; +typedef struct _MBR_PARTITION_DATA +{ + BOOLEAN BootIndicator; + UCHAR PartitionType; +} MBR_PARTITION_DATA, *PMBR_PARTITION_DATA; + +typedef struct _GPT_PARTITION_DATA +{ + GUID PartitionType; + GUID PartitionId; + DWORD64 Attributes; +} GPT_PARTITION_DATA, *PGPT_PARTITION_DATA; + typedef struct _PARTENTRY { LIST_ENTRY ListEntry; @@ -107,8 +123,12 @@ typedef struct _PARTENTRY ULARGE_INTEGER StartSector; ULARGE_INTEGER SectorCount; - BOOLEAN BootIndicator; - UCHAR PartitionType; + union + { + MBR_PARTITION_DATA Mbr; + GPT_PARTITION_DATA Gpt; + }; + ULONG OnDiskPartitionNumber; ULONG PartitionNumber; ULONG PartitionIndex; @@ -161,6 +181,9 @@ typedef struct _DISKENTRY ULONG SectorAlignment; ULONG CylinderAlignment; + ULARGE_INTEGER StartSector; + ULARGE_INTEGER EndSector; + BOOLEAN BiosFound; ULONG BiosDiskNumber; // ULONG Signature; @@ -434,6 +457,11 @@ PrintGUID( _Out_ PWSTR pszBuffer, _In_ GUID *pGuid); +BOOL +StringToGUID( + _Out_ GUID *pGuid, + _In_ PWSTR pszString); + /* offline.c */ BOOL offline_main(INT argc, LPWSTR *argv); @@ -447,6 +475,12 @@ DumpPartitionTable( _In_ PDISKENTRY DiskEntry); #endif +#ifdef DUMP_PARTITION_LIST +VOID +DumpPartitionList( + _In_ PDISKENTRY DiskEntry); +#endif + ULONGLONG AlignDown( _In_ ULONGLONG Value, @@ -464,19 +498,36 @@ CreateVolumeList(VOID); VOID DestroyVolumeList(VOID); +VOID +ScanForUnpartitionedMbrDiskSpace( + PDISKENTRY DiskEntry); + +VOID +ScanForUnpartitionedGptDiskSpace( + PDISKENTRY DiskEntry); + VOID ReadLayoutBuffer( _In_ HANDLE FileHandle, _In_ PDISKENTRY DiskEntry); NTSTATUS -WritePartitions( +WriteMbrPartitions( + _In_ PDISKENTRY DiskEntry); + +NTSTATUS +WriteGptPartitions( _In_ PDISKENTRY DiskEntry); VOID -UpdateDiskLayout( +UpdateMbrDiskLayout( _In_ PDISKENTRY DiskEntry); +VOID +UpdateGptDiskLayout( + _In_ PDISKENTRY DiskEntry, + _In_ BOOL DeleteEntry); + PPARTENTRY GetPrevUnpartitionedEntry( _In_ PPARTENTRY PartEntry); diff --git a/base/system/diskpart/guid.c b/base/system/diskpart/guid.c new file mode 100644 index 00000000000..6c44c329871 --- /dev/null +++ b/base/system/diskpart/guid.c @@ -0,0 +1,6 @@ + +#define INITGUID +#include + +#include "guid.h" + diff --git a/base/system/diskpart/guid.h b/base/system/diskpart/guid.h new file mode 100644 index 00000000000..69b12a4bea7 --- /dev/null +++ b/base/system/diskpart/guid.h @@ -0,0 +1,9 @@ + +DEFINE_GUID(PARTITION_ENTRY_UNUSED_GUID, 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +DEFINE_GUID(PARTITION_SYSTEM_GUID, 0xc12a7328L, 0xf81f, 0x11d2, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b); +DEFINE_GUID(PARTITION_MSFT_RESERVED_GUID, 0xe3c9e316L, 0x0b5c, 0x4db8, 0x81, 0x7d, 0xf9, 0x2d, 0xf0, 0x02, 0x15, 0xae); +DEFINE_GUID(PARTITION_BASIC_DATA_GUID, 0xebd0a0a2L, 0xb9e5, 0x4433, 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7); + +DEFINE_GUID(PARTITION_LDM_METADATA_GUID, 0x5808c8aaL, 0x7e8f, 0x42e0, 0x85, 0xd2, 0xe1, 0xe9, 0x04, 0x34, 0xcf, 0xb3); +DEFINE_GUID(PARTITION_LDM_DATA_GUID, 0xaf9b60a0L, 0x1431, 0x4f62, 0xbc, 0x68, 0x33, 0x11, 0x71, 0x4a, 0x69, 0xad); +DEFINE_GUID(PARTITION_MSFT_RECOVERY_GUID, 0xde94bba4L, 0x06d1, 0x4d40, 0xa1, 0x6a, 0xbf, 0xd5, 0x01, 0x79, 0xd6, 0xac); diff --git a/base/system/diskpart/inactive.c b/base/system/diskpart/inactive.c index d09db310eeb..9fb7a05ad06 100644 --- a/base/system/diskpart/inactive.c +++ b/base/system/diskpart/inactive.c @@ -35,16 +35,16 @@ inactive_main( if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) { - if (!CurrentPartition->BootIndicator) + if (!CurrentPartition->Mbr.BootIndicator) { ConResPuts(StdOut, IDS_INACTIVE_ALREADY); return TRUE; } - CurrentPartition->BootIndicator = FALSE; + CurrentPartition->Mbr.BootIndicator = FALSE; CurrentDisk->Dirty = TRUE; - UpdateDiskLayout(CurrentDisk); - Status = WritePartitions(CurrentDisk); + UpdateMbrDiskLayout(CurrentDisk); + Status = WriteMbrPartitions(CurrentDisk); if (NT_SUCCESS(Status)) { ConResPuts(StdOut, IDS_INACTIVE_SUCCESS); diff --git a/base/system/diskpart/lang/de-DE.rc b/base/system/diskpart/lang/de-DE.rc index 0cbb4c769ac..34378eb73e2 100644 --- a/base/system/diskpart/lang/de-DE.rc +++ b/base/system/diskpart/lang/de-DE.rc @@ -71,10 +71,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "Crashdump Disk" IDS_DETAIL_INFO_CLST_DSK "Clustered Disk" IDS_DETAIL_PARTITION_NUMBER "Partition %lu\n" - IDS_DETAIL_PARTITION_TYPE "Type : %02x\n" + IDS_DETAIL_PARTITION_TYPE "Type : %s\n" IDS_DETAIL_PARTITION_HIDDEN "Hidden : %s\n" IDS_DETAIL_PARTITION_ACTIVE "Active : %s\n" IDS_DETAIL_PARTITION_OFFSET "Offset in Byte: %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\nThere are no disks attached to this volume.\n" IDS_DETAIL_NO_VOLUME "\nThere is no volume associated with this partition.\n" END diff --git a/base/system/diskpart/lang/en-US.rc b/base/system/diskpart/lang/en-US.rc index 507e647ba31..ce7cfc6b697 100644 --- a/base/system/diskpart/lang/en-US.rc +++ b/base/system/diskpart/lang/en-US.rc @@ -71,10 +71,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "Crashdump Disk" IDS_DETAIL_INFO_CLST_DSK "Clustered Disk" IDS_DETAIL_PARTITION_NUMBER "Partition %lu\n" - IDS_DETAIL_PARTITION_TYPE "Type : %02x\n" + IDS_DETAIL_PARTITION_TYPE "Type : %s\n" IDS_DETAIL_PARTITION_HIDDEN "Hidden : %s\n" IDS_DETAIL_PARTITION_ACTIVE "Active : %s\n" IDS_DETAIL_PARTITION_OFFSET "Offset in Byte: %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\nThere are no disks attached to this volume.\n" IDS_DETAIL_NO_VOLUME "\nThere is no volume associated with this partition.\n" END diff --git a/base/system/diskpart/lang/it-IT.rc b/base/system/diskpart/lang/it-IT.rc index 734d681e51e..7b729e0934a 100644 --- a/base/system/diskpart/lang/it-IT.rc +++ b/base/system/diskpart/lang/it-IT.rc @@ -78,10 +78,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "Disco di crashdump" IDS_DETAIL_INFO_CLST_DSK "Disco clustered" IDS_DETAIL_PARTITION_NUMBER "Partizione %lu\n" - IDS_DETAIL_PARTITION_TYPE "Tipo : %02x\n" + IDS_DETAIL_PARTITION_TYPE "Tipo : %s\n" IDS_DETAIL_PARTITION_HIDDEN "Nascosto : %s\n" IDS_DETAIL_PARTITION_ACTIVE "Attivo : %s\n" IDS_DETAIL_PARTITION_OFFSET "Offset in Byte: %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\nNon ci sono dischi collegati a questo volume.\n" IDS_DETAIL_NO_VOLUME "\nNon c'è nessun volume associato a questa partizione.\n" END diff --git a/base/system/diskpart/lang/pl-PL.rc b/base/system/diskpart/lang/pl-PL.rc index fa89afde1d0..6201af74fb9 100644 --- a/base/system/diskpart/lang/pl-PL.rc +++ b/base/system/diskpart/lang/pl-PL.rc @@ -71,10 +71,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "Dysk zrzutu awarii systemu" IDS_DETAIL_INFO_CLST_DSK "Dysk klastrowany" IDS_DETAIL_PARTITION_NUMBER "Partycja %lu\n" - IDS_DETAIL_PARTITION_TYPE "Typ : %02x\n" + IDS_DETAIL_PARTITION_TYPE "Typ : %s\n" IDS_DETAIL_PARTITION_HIDDEN "Ukryta : %s\n" IDS_DETAIL_PARTITION_ACTIVE "Aktywna : %s\n" IDS_DETAIL_PARTITION_OFFSET "Przesunięcie w bajtach: %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\nThere are no disks attached to this volume.\n" IDS_DETAIL_NO_VOLUME "\nThere is no volume associated with this partition.\n" END diff --git a/base/system/diskpart/lang/pt-PT.rc b/base/system/diskpart/lang/pt-PT.rc index e5cfd040312..7376c92b802 100644 --- a/base/system/diskpart/lang/pt-PT.rc +++ b/base/system/diskpart/lang/pt-PT.rc @@ -73,10 +73,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "Despejo de memória de disco" IDS_DETAIL_INFO_CLST_DSK "Disco em cluster" IDS_DETAIL_PARTITION_NUMBER "Partition %lu\n" - IDS_DETAIL_PARTITION_TYPE "Type : %02x\n" + IDS_DETAIL_PARTITION_TYPE "Type : %s\n" IDS_DETAIL_PARTITION_HIDDEN "Hidden : %s\n" IDS_DETAIL_PARTITION_ACTIVE "Active : %s\n" IDS_DETAIL_PARTITION_OFFSET "Offset in Byte: %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\nThere are no disks attached to this volume.\n" IDS_DETAIL_NO_VOLUME "\nThere is no volume associated with this partition.\n" END diff --git a/base/system/diskpart/lang/ro-RO.rc b/base/system/diskpart/lang/ro-RO.rc index 0dbe573e0f7..f54c7386b8f 100644 --- a/base/system/diskpart/lang/ro-RO.rc +++ b/base/system/diskpart/lang/ro-RO.rc @@ -79,10 +79,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "Disc cu fișier «crashdump»" IDS_DETAIL_INFO_CLST_DSK "Disc în «cluster»" IDS_DETAIL_PARTITION_NUMBER "Partiție %lu\n" - IDS_DETAIL_PARTITION_TYPE "Tip : %02x\n" + IDS_DETAIL_PARTITION_TYPE "Tip : %s\n" IDS_DETAIL_PARTITION_HIDDEN "Ascuns : %s\n" IDS_DETAIL_PARTITION_ACTIVE "Activ : %s\n" IDS_DETAIL_PARTITION_OFFSET "Offset în octet: %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\nNu există discuri atașate acestui volum.\n" IDS_DETAIL_NO_VOLUME "\nNu există volum asociat cu această partiție.\n" END diff --git a/base/system/diskpart/lang/ru-RU.rc b/base/system/diskpart/lang/ru-RU.rc index 275b709bf7b..ab4db71aaad 100644 --- a/base/system/diskpart/lang/ru-RU.rc +++ b/base/system/diskpart/lang/ru-RU.rc @@ -73,10 +73,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "Crashdump диск" IDS_DETAIL_INFO_CLST_DSK "Кластерный диск" IDS_DETAIL_PARTITION_NUMBER "Partition %lu\n" - IDS_DETAIL_PARTITION_TYPE "Type : %02x\n" + IDS_DETAIL_PARTITION_TYPE "Type : %s\n" IDS_DETAIL_PARTITION_HIDDEN "Hidden : %s\n" IDS_DETAIL_PARTITION_ACTIVE "Active : %s\n" IDS_DETAIL_PARTITION_OFFSET "Offset in Byte: %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\nThere are no disks attached to this volume.\n" IDS_DETAIL_NO_VOLUME "\nThere is no volume associated with this partition.\n" END diff --git a/base/system/diskpart/lang/sq-AL.rc b/base/system/diskpart/lang/sq-AL.rc index de44192acb1..6464c6eed62 100644 --- a/base/system/diskpart/lang/sq-AL.rc +++ b/base/system/diskpart/lang/sq-AL.rc @@ -75,10 +75,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "Hedhja e te dhenave Disk" IDS_DETAIL_INFO_CLST_DSK "Grupimet ne Disk" IDS_DETAIL_PARTITION_NUMBER "Partition %lu\n" - IDS_DETAIL_PARTITION_TYPE "Type : %02x\n" + IDS_DETAIL_PARTITION_TYPE "Type : %s\n" IDS_DETAIL_PARTITION_HIDDEN "Hidden : %s\n" IDS_DETAIL_PARTITION_ACTIVE "Active : %s\n" IDS_DETAIL_PARTITION_OFFSET "Offset in Byte: %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\nThere are no disks attached to this volume.\n" IDS_DETAIL_NO_VOLUME "\nThere is no volume associated with this partition.\n" END diff --git a/base/system/diskpart/lang/tr-TR.rc b/base/system/diskpart/lang/tr-TR.rc index c918648fef3..4129d7712fb 100644 --- a/base/system/diskpart/lang/tr-TR.rc +++ b/base/system/diskpart/lang/tr-TR.rc @@ -81,10 +81,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "Çökme Dökümü Diski" IDS_DETAIL_INFO_CLST_DSK "Kümelenmiş Disk" IDS_DETAIL_PARTITION_NUMBER "Bölüm %lu\n" - IDS_DETAIL_PARTITION_TYPE "Tür : %02x\n" + IDS_DETAIL_PARTITION_TYPE "Tür : %s\n" IDS_DETAIL_PARTITION_HIDDEN "Gizli : %s\n" IDS_DETAIL_PARTITION_ACTIVE "Etkin : %s\n" IDS_DETAIL_PARTITION_OFFSET "Bayt cinsinden ofset: %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\nBu birime bağlı disk yok.\n" IDS_DETAIL_NO_VOLUME "\nBu bölümle ilişkilendirilmiş bir birim yok.\n" END diff --git a/base/system/diskpart/lang/zh-CN.rc b/base/system/diskpart/lang/zh-CN.rc index 3ba411191de..2fa8302b5d3 100644 --- a/base/system/diskpart/lang/zh-CN.rc +++ b/base/system/diskpart/lang/zh-CN.rc @@ -80,10 +80,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "故障转储磁盘" IDS_DETAIL_INFO_CLST_DSK "群集的磁盘" IDS_DETAIL_PARTITION_NUMBER "Partition %lu\n" - IDS_DETAIL_PARTITION_TYPE "Type : %02x\n" + IDS_DETAIL_PARTITION_TYPE "Type : %s\n" IDS_DETAIL_PARTITION_HIDDEN "Hidden : %s\n" IDS_DETAIL_PARTITION_ACTIVE "Active : %s\n" IDS_DETAIL_PARTITION_OFFSET "Offset in Byte: %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\nThere are no disks attached to this volume.\n" IDS_DETAIL_NO_VOLUME "\nThere is no volume associated with this partition.\n" END diff --git a/base/system/diskpart/lang/zh-TW.rc b/base/system/diskpart/lang/zh-TW.rc index bd7d6a85ca6..2ae1d505929 100644 --- a/base/system/diskpart/lang/zh-TW.rc +++ b/base/system/diskpart/lang/zh-TW.rc @@ -80,10 +80,12 @@ BEGIN IDS_DETAIL_INFO_CRASH_DSK "損毀傾印磁碟" IDS_DETAIL_INFO_CLST_DSK "叢集磁碟" IDS_DETAIL_PARTITION_NUMBER "磁碟分割 %lu\n" - IDS_DETAIL_PARTITION_TYPE "類型 : %02x\n" + IDS_DETAIL_PARTITION_TYPE "類型 : %s\n" IDS_DETAIL_PARTITION_HIDDEN "已隱藏 : %s\n" IDS_DETAIL_PARTITION_ACTIVE "使用中 : %s\n" IDS_DETAIL_PARTITION_OFFSET "位移 (位元組) : %I64u\n" + IDS_DETAIL_PARTITION_REQUIRED "Required : %s\n" + IDS_DETAIL_PARTITION_ATTRIBUTE "Attributes : %016I64x\n" IDS_DETAIL_NO_DISKS "\n沒有磁碟附加到這個磁碟區。\n" IDS_DETAIL_NO_VOLUME "\n沒有磁碟區與這個磁碟分割有關聯。\n" END diff --git a/base/system/diskpart/list.c b/base/system/diskpart/list.c index 9d408cbe3b1..1a04da9160c 100644 --- a/base/system/diskpart/list.c +++ b/base/system/diskpart/list.c @@ -108,116 +108,200 @@ ListPartition( ConResPuts(StdOut, IDS_LIST_PARTITION_HEAD); ConResPuts(StdOut, IDS_LIST_PARTITION_LINE); - Entry = CurrentDisk->PrimaryPartListHead.Flink; - while (Entry != &CurrentDisk->PrimaryPartListHead) + if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) { - PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); - - if (PartEntry->PartitionType != 0) + Entry = CurrentDisk->PrimaryPartListHead.Flink; + while (Entry != &CurrentDisk->PrimaryPartListHead) { - PartSize = PartEntry->SectorCount.QuadPart * CurrentDisk->BytesPerSector; + PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); - if (PartSize >= 10737418240) /* 10 GB */ + if (PartEntry->Mbr.PartitionType != 0) { - PartSize = RoundingDivide(PartSize, 1073741824); - lpSizeUnit = L"GB"; - } - else if (PartSize >= 10485760) /* 10 MB */ - { - PartSize = RoundingDivide(PartSize, 1048576); - lpSizeUnit = L"MB"; - } - else - { - PartSize = RoundingDivide(PartSize, 1024); - lpSizeUnit = L"KB"; + PartSize = PartEntry->SectorCount.QuadPart * CurrentDisk->BytesPerSector; + + if (PartSize >= 10737418240) /* 10 GB */ + { + PartSize = RoundingDivide(PartSize, 1073741824); + lpSizeUnit = L"GB"; + } + else if (PartSize >= 10485760) /* 10 MB */ + { + PartSize = RoundingDivide(PartSize, 1048576); + lpSizeUnit = L"MB"; + } + else + { + PartSize = RoundingDivide(PartSize, 1024); + lpSizeUnit = L"KB"; + } + + PartOffset = PartEntry->StartSector.QuadPart * CurrentDisk->BytesPerSector; + + if (PartOffset >= 10737418240) /* 10 GB */ + { + PartOffset = RoundingDivide(PartOffset, 1073741824); + lpOffsetUnit = L"GB"; + } + else if (PartOffset >= 10485760) /* 10 MB */ + { + PartOffset = RoundingDivide(PartOffset, 1048576); + lpOffsetUnit = L"MB"; + } + else + { + PartOffset = RoundingDivide(PartOffset, 1024); + lpOffsetUnit = L"KB"; + } + + ConResPrintf(StdOut, IDS_LIST_PARTITION_FORMAT, + (CurrentPartition == PartEntry) ? L'*' : L' ', + PartNumber++, + IsContainerPartition(PartEntry->Mbr.PartitionType) ? L"Extended" : L"Primary", + PartSize, + lpSizeUnit, + PartOffset, + lpOffsetUnit); } - PartOffset = PartEntry->StartSector.QuadPart * CurrentDisk->BytesPerSector; - - if (PartOffset >= 10737418240) /* 10 GB */ - { - PartOffset = RoundingDivide(PartOffset, 1073741824); - lpOffsetUnit = L"GB"; - } - else if (PartOffset >= 10485760) /* 10 MB */ - { - PartOffset = RoundingDivide(PartOffset, 1048576); - lpOffsetUnit = L"MB"; - } - else - { - PartOffset = RoundingDivide(PartOffset, 1024); - lpOffsetUnit = L"KB"; - } - - ConResPrintf(StdOut, IDS_LIST_PARTITION_FORMAT, - (CurrentPartition == PartEntry) ? L'*' : L' ', - PartNumber++, - IsContainerPartition(PartEntry->PartitionType) ? L"Extended" : L"Primary", - PartSize, - lpSizeUnit, - PartOffset, - lpOffsetUnit); + Entry = Entry->Flink; } - Entry = Entry->Flink; + Entry = CurrentDisk->LogicalPartListHead.Flink; + while (Entry != &CurrentDisk->LogicalPartListHead) + { + PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); + + if (PartEntry->Mbr.PartitionType != 0) + { + PartSize = PartEntry->SectorCount.QuadPart * CurrentDisk->BytesPerSector; + + if (PartSize >= 10737418240) /* 10 GB */ + { + PartSize = RoundingDivide(PartSize, 1073741824); + lpSizeUnit = L"GB"; + } + else if (PartSize >= 10485760) /* 10 MB */ + { + PartSize = RoundingDivide(PartSize, 1048576); + lpSizeUnit = L"MB"; + } + else + { + PartSize = RoundingDivide(PartSize, 1024); + lpSizeUnit = L"KB"; + } + + PartOffset = PartEntry->StartSector.QuadPart * CurrentDisk->BytesPerSector; + + if (PartOffset >= 10737418240) /* 10 GB */ + { + PartOffset = RoundingDivide(PartOffset, 1073741824); + lpOffsetUnit = L"GB"; + } + else if (PartOffset >= 10485760) /* 10 MB */ + { + PartOffset = RoundingDivide(PartOffset, 1048576); + lpOffsetUnit = L"MB"; + } + else + { + PartOffset = RoundingDivide(PartOffset, 1024); + lpOffsetUnit = L"KB"; + } + + ConResPrintf(StdOut, IDS_LIST_PARTITION_FORMAT, + (CurrentPartition == PartEntry) ? L'*' : L' ', + PartNumber++, + L"Logical", + PartSize, + lpSizeUnit, + PartOffset, + lpOffsetUnit); + } + + Entry = Entry->Flink; + } } - - Entry = CurrentDisk->LogicalPartListHead.Flink; - while (Entry != &CurrentDisk->LogicalPartListHead) + else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) { - PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); + LPWSTR lpPartitionType; - if (PartEntry->PartitionType != 0) + Entry = CurrentDisk->PrimaryPartListHead.Flink; + while (Entry != &CurrentDisk->PrimaryPartListHead) { - PartSize = PartEntry->SectorCount.QuadPart * CurrentDisk->BytesPerSector; + PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); - if (PartSize >= 10737418240) /* 10 GB */ + if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) { - PartSize = RoundingDivide(PartSize, 1073741824); - lpSizeUnit = L"GB"; - } - else if (PartSize >= 10485760) /* 10 MB */ - { - PartSize = RoundingDivide(PartSize, 1048576); - lpSizeUnit = L"MB"; - } - else - { - PartSize = RoundingDivide(PartSize, 1024); - lpSizeUnit = L"KB"; + PartSize = PartEntry->SectorCount.QuadPart * CurrentDisk->BytesPerSector; + + if (PartSize >= 10737418240) /* 10 GB */ + { + PartSize = RoundingDivide(PartSize, 1073741824); + lpSizeUnit = L"GB"; + } + else if (PartSize >= 10485760) /* 10 MB */ + { + PartSize = RoundingDivide(PartSize, 1048576); + lpSizeUnit = L"MB"; + } + else + { + PartSize = RoundingDivide(PartSize, 1024); + lpSizeUnit = L"KB"; + } + + PartOffset = PartEntry->StartSector.QuadPart * CurrentDisk->BytesPerSector; + + if (PartOffset >= 10737418240) /* 10 GB */ + { + PartOffset = RoundingDivide(PartOffset, 1073741824); + lpOffsetUnit = L"GB"; + } + else if (PartOffset >= 10485760) /* 10 MB */ + { + PartOffset = RoundingDivide(PartOffset, 1048576); + lpOffsetUnit = L"MB"; + } + else + { + PartOffset = RoundingDivide(PartOffset, 1024); + lpOffsetUnit = L"KB"; + } + + if (IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) + { + lpPartitionType = L"Unused"; + } + else if (IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_BASIC_DATA_GUID)) + { + lpPartitionType = L"Primary"; + } + else if (IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_SYSTEM_GUID)) + { + lpPartitionType = L"System"; + } + else if (IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_MSFT_RESERVED_GUID)) + { + lpPartitionType = L"Reserved"; + } + else + { + lpPartitionType = L"Other"; /* ??? */ + } + + ConResPrintf(StdOut, IDS_LIST_PARTITION_FORMAT, + (CurrentPartition == PartEntry) ? L'*' : L' ', + PartNumber++, + lpPartitionType, + PartSize, + lpSizeUnit, + PartOffset, + lpOffsetUnit); } - PartOffset = PartEntry->StartSector.QuadPart * CurrentDisk->BytesPerSector; - - if (PartOffset >= 10737418240) /* 10 GB */ - { - PartOffset = RoundingDivide(PartOffset, 1073741824); - lpOffsetUnit = L"GB"; - } - else if (PartOffset >= 10485760) /* 10 MB */ - { - PartOffset = RoundingDivide(PartOffset, 1048576); - lpOffsetUnit = L"MB"; - } - else - { - PartOffset = RoundingDivide(PartOffset, 1024); - lpOffsetUnit = L"KB"; - } - - ConResPrintf(StdOut, IDS_LIST_PARTITION_FORMAT, - (CurrentPartition == PartEntry) ? L'*' : L' ', - PartNumber++, - L"Logical", - PartSize, - lpSizeUnit, - PartOffset, - lpOffsetUnit); + Entry = Entry->Flink; } - - Entry = Entry->Flink; } ConPuts(StdOut, L"\n"); diff --git a/base/system/diskpart/misc.c b/base/system/diskpart/misc.c index eb8e45e4917..a4a72586753 100644 --- a/base/system/diskpart/misc.c +++ b/base/system/diskpart/misc.c @@ -202,3 +202,90 @@ PrintGUID( pGuid->Data4[6], pGuid->Data4[7]); } + +static +BYTE +CharToByte( + WCHAR Char) +{ + if (iswdigit(Char)) + { + return (BYTE)((INT)Char - (INT)'0'); + } + else if (iswalpha(Char)) + { + if (iswupper(Char)) + return (INT)Char - ((INT)'A' - 10); + else + return (INT)Char - ((INT)'a' - 10); + } + return 0; +} + + +BOOL +StringToGUID( + _Out_ GUID *pGuid, + _In_ PWSTR pszString) +{ + INT i; + + if (pszString == NULL) + return FALSE; + + pGuid->Data1 = 0; + for (i = 0; i < 8; i++) + { + if (!iswxdigit(pszString[i])) + return FALSE; + + pGuid->Data1 = (pGuid->Data1 << 4) | CharToByte(pszString[i]); + } + + if (pszString[8] != L'-') + return FALSE; + + pGuid->Data2 = 0; + for (i = 9; i < 13; i++) + { + if (!iswxdigit(pszString[i])) + return FALSE; + + pGuid->Data2 = (pGuid->Data2 << 4) | CharToByte(pszString[i]); + } + + if (pszString[13] != L'-') + return FALSE; + + pGuid->Data3 = 0; + for (i = 14; i < 18; i++) + { + if (!iswxdigit(pszString[i])) + return FALSE; + + pGuid->Data3 = (pGuid->Data3 << 4) | CharToByte(pszString[i]); + } + + if (pszString[18] != L'-') + return FALSE; + + for (i = 19; i < 36; i += 2) + { + if (i == 23) + { + if (pszString[i] != L'-') + return FALSE; + i++; + } + + if (!iswxdigit(pszString[i]) || !iswxdigit(pszString[i + 1])) + return FALSE; + + pGuid->Data4[(i - 19) / 2] = CharToByte(pszString[i]) << 4 | CharToByte(pszString[i + 1]); + } + + if (pszString[36] == L'\0') + return TRUE; + + return FALSE; +} diff --git a/base/system/diskpart/partlist.c b/base/system/diskpart/partlist.c index 49169e98df1..c452d06bec1 100644 --- a/base/system/diskpart/partlist.c +++ b/base/system/diskpart/partlist.c @@ -9,6 +9,7 @@ /* INCLUDES *******************************************************************/ #include "diskpart.h" +#include "guid.h" #include #define NDEBUG @@ -131,6 +132,61 @@ DumpPartitionTable( } #endif +#ifdef DUMP_PARTITION_LIST +VOID +DumpPartitionList( + _In_ PDISKENTRY DiskEntry) +{ + PLIST_ENTRY ListEntry; + PPARTENTRY PartEntry; + + DbgPrint("\n"); + + if (DiskEntry->PartitionStyle == PARTITION_STYLE_GPT) + { + DbgPrint("Disk Start Disk End Disk Length \n"); + DbgPrint("------------ ------------ ------------\n"); + DbgPrint("%12I64u %12I64u %12I64u\n", + DiskEntry->StartSector.QuadPart, + DiskEntry->EndSector.QuadPart, + DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1); + + DbgPrint("\n"); + + DbgPrint("Start End Length Nr Type P\n"); + DbgPrint("------------ ------------ ------------ --- -------- --\n"); + + for (ListEntry = DiskEntry->PrimaryPartListHead.Flink; + ListEntry != &DiskEntry->PrimaryPartListHead; + ListEntry = ListEntry->Flink) + { + PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); + + DbgPrint("%12I64u %12I64u %12I64u %3lu %08lx %c\n", + PartEntry->StartSector.QuadPart, + PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1, + PartEntry->SectorCount.QuadPart, + PartEntry->PartitionNumber, + PartEntry->Gpt.PartitionType.Data1, + PartEntry->IsPartitioned ? 'Y': 'N'); + } + } + else if (DiskEntry->PartitionStyle == PARTITION_STYLE_MBR) + { + DbgPrint("Disk Start Disk End Disk Length \n"); + DbgPrint("------------ ------------ ------------\n"); + DbgPrint("%12I64u %12I64u %12I64u\n", + DiskEntry->StartSector.QuadPart, + DiskEntry->EndSector.QuadPart, + DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1); + + } + + DbgPrint("\n"); +} +#endif + + ULONGLONG AlignDown( _In_ ULONGLONG Value, @@ -449,7 +505,7 @@ EnumerateBiosDiskEntries(VOID) static VOID -AddPartitionToDisk( +AddMbrPartitionToDisk( ULONG DiskNumber, PDISKENTRY DiskEntry, ULONG PartitionIndex, @@ -468,6 +524,7 @@ AddPartitionToDisk( sizeof(PARTENTRY)); if (PartEntry == NULL) { + /* TODO: Error message */ return; } @@ -476,27 +533,27 @@ AddPartitionToDisk( PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector; PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector; - PartEntry->BootIndicator = PartitionInfo->Mbr.BootIndicator; - PartEntry->PartitionType = PartitionInfo->Mbr.PartitionType; + PartEntry->Mbr.BootIndicator = PartitionInfo->Mbr.BootIndicator; + PartEntry->Mbr.PartitionType = PartitionInfo->Mbr.PartitionType; PartEntry->LogicalPartition = LogicalPartition; PartEntry->IsPartitioned = TRUE; PartEntry->PartitionNumber = PartitionInfo->PartitionNumber; PartEntry->PartitionIndex = PartitionIndex; - if (IsContainerPartition(PartEntry->PartitionType)) + if (IsContainerPartition(PartEntry->Mbr.PartitionType)) { PartEntry->FormatState = Unformatted; if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL) 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)) + else if ((PartEntry->Mbr.PartitionType == PARTITION_FAT_12) || + (PartEntry->Mbr.PartitionType == PARTITION_FAT_16) || + (PartEntry->Mbr.PartitionType == PARTITION_HUGE) || + (PartEntry->Mbr.PartitionType == PARTITION_XINT13) || + (PartEntry->Mbr.PartitionType == PARTITION_FAT32) || + (PartEntry->Mbr.PartitionType == PARTITION_FAT32_XINT13)) { #if 0 if (CheckFatFormat()) @@ -510,7 +567,7 @@ AddPartitionToDisk( #endif PartEntry->FormatState = Preformatted; } - else if (PartEntry->PartitionType == PARTITION_LINUX) + else if (PartEntry->Mbr.PartitionType == PARTITION_LINUX) { #if 0 if (CheckExt2Format()) @@ -524,7 +581,7 @@ AddPartitionToDisk( #endif PartEntry->FormatState = Preformatted; } - else if (PartEntry->PartitionType == PARTITION_IFS) + else if (PartEntry->Mbr.PartitionType == PARTITION_IFS) { #if 0 if (CheckNtfsFormat()) @@ -558,9 +615,54 @@ AddPartitionToDisk( static VOID -ScanForUnpartitionedDiskSpace( +AddGptPartitionToDisk( + ULONG DiskNumber, + PDISKENTRY DiskEntry, + ULONG PartitionIndex) +{ + PPARTITION_INFORMATION_EX PartitionInfo; + PPARTENTRY PartEntry; + + PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex]; + if (IsEqualGUID(&PartitionInfo->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) + return; + + PartEntry = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(PARTENTRY)); + if (PartEntry == NULL) + { + /* TODO: Error message */ + return; + } + + PartEntry->DiskEntry = DiskEntry; + + PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector; + PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector; + + CopyMemory(&PartEntry->Gpt.PartitionType, &PartitionInfo->Gpt.PartitionType, sizeof(GUID)); + CopyMemory(&PartEntry->Gpt.PartitionId, &PartitionInfo->Gpt.PartitionId, sizeof(GUID)); + PartEntry->Gpt.Attributes = PartitionInfo->Gpt.Attributes; + + PartEntry->LogicalPartition = FALSE; + PartEntry->IsPartitioned = TRUE; + PartEntry->PartitionNumber = PartitionInfo->PartitionNumber; + PartEntry->PartitionIndex = PartitionIndex; + + /* TODO: Determine the format state */ + PartEntry->FormatState = Unformatted; + + InsertTailList(&DiskEntry->PrimaryPartListHead, + &PartEntry->ListEntry); +} + + +VOID +ScanForUnpartitionedMbrDiskSpace( PDISKENTRY DiskEntry) { + ULONGLONG StartSector, EndSector; ULONGLONG LastStartSector; ULONGLONG LastSectorCount; ULONGLONG LastUnusedSectorCount; @@ -568,7 +670,12 @@ ScanForUnpartitionedDiskSpace( PPARTENTRY NewPartEntry; PLIST_ENTRY Entry; - DPRINT("ScanForUnpartitionedDiskSpace()\n"); + DPRINT("ScanForUnpartitionedMbrDiskSpace()\n"); + + /* Calculate the disk sector limits */ + /* Limit the SectorCount to 2^32 sectors for MBR disks */ + StartSector = (ULONGLONG)DiskEntry->SectorAlignment; + EndSector = min(DiskEntry->SectorCount.QuadPart, 0x100000000) - 1; if (IsListEmpty(&DiskEntry->PrimaryPartListHead)) { @@ -584,8 +691,8 @@ ScanForUnpartitionedDiskSpace( NewPartEntry->DiskEntry = DiskEntry; NewPartEntry->IsPartitioned = FALSE; - NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment; - NewPartEntry->SectorCount.QuadPart = AlignDown(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) - + NewPartEntry->StartSector.QuadPart = StartSector; + NewPartEntry->SectorCount.QuadPart = AlignDown(EndSector + 1, DiskEntry->SectorAlignment) - NewPartEntry->StartSector.QuadPart; DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); @@ -600,8 +707,8 @@ ScanForUnpartitionedDiskSpace( return; } - /* Start partition at head 1, cylinder 0 */ - LastStartSector = DiskEntry->SectorAlignment; + /* Start at the first usable sector */ + LastStartSector = StartSector; LastSectorCount = 0ULL; LastUnusedSectorCount = 0ULL; @@ -610,7 +717,7 @@ ScanForUnpartitionedDiskSpace( { PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); - if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || + if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->SectorCount.QuadPart != 0ULL) { LastUnusedSectorCount = @@ -653,9 +760,9 @@ ScanForUnpartitionedDiskSpace( } /* Check for trailing unpartitioned disk space */ - if ((LastStartSector + LastSectorCount) < DiskEntry->SectorCount.QuadPart) + if ((LastStartSector + LastSectorCount) < (EndSector + 1)) { - LastUnusedSectorCount = AlignDown(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment); + LastUnusedSectorCount = AlignDown((EndSector + 1) - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment); if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment) { @@ -728,7 +835,7 @@ ScanForUnpartitionedDiskSpace( { PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); - if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || + if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->SectorCount.QuadPart != 0ULL) { LastUnusedSectorCount = @@ -808,7 +915,151 @@ ScanForUnpartitionedDiskSpace( } } - DPRINT("ScanForUnpartitionedDiskSpace() done\n"); + DPRINT("ScanForUnpartitionedMbrDiskSpace() done\n"); +} + + +VOID +ScanForUnpartitionedGptDiskSpace( + PDISKENTRY DiskEntry) +{ + ULONGLONG LastStartSector; + ULONGLONG LastSectorCount; + ULONGLONG LastUnusedSectorCount; + PPARTENTRY PartEntry; + PPARTENTRY NewPartEntry; + PLIST_ENTRY Entry; + + DPRINT("ScanForUnpartitionedGptDiskSpace()\n"); + +#ifdef DUMP_PARTITION_LIST + DumpPartitionList(DiskEntry); +#endif + + if (IsListEmpty(&DiskEntry->PrimaryPartListHead)) + { + DPRINT("No partitions!\n"); + + /* Create a partition table that represents the empty disk */ + NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(PARTENTRY)); + if (NewPartEntry == NULL) + return; + + NewPartEntry->DiskEntry = DiskEntry; + + NewPartEntry->IsPartitioned = FALSE; + NewPartEntry->StartSector.QuadPart = DiskEntry->StartSector.QuadPart; + NewPartEntry->SectorCount.QuadPart = DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1; + + DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); + DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); + DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart); + + NewPartEntry->FormatState = Unformatted; + + InsertTailList(&DiskEntry->PrimaryPartListHead, + &NewPartEntry->ListEntry); + +#ifdef DUMP_PARTITION_LIST + DumpPartitionList(DiskEntry); +#endif + + return; + } + + /* Start at the first usable sector */ + LastStartSector = DiskEntry->StartSector.QuadPart; + LastSectorCount = 0ULL; + LastUnusedSectorCount = 0ULL; + + Entry = DiskEntry->PrimaryPartListHead.Flink; + while (Entry != &DiskEntry->PrimaryPartListHead) + { + PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); + + if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID) || + PartEntry->SectorCount.QuadPart != 0ULL) + { + LastUnusedSectorCount = + PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount); + + if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) && + LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment) + { + DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount); + + NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(PARTENTRY)); + if (NewPartEntry == NULL) + return; + + NewPartEntry->DiskEntry = DiskEntry; + + NewPartEntry->IsPartitioned = FALSE; + NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount; + NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) - + NewPartEntry->StartSector.QuadPart; + + DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); + DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); + DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart); + + NewPartEntry->FormatState = Unformatted; + + /* Insert the table into the list */ + InsertTailList(&PartEntry->ListEntry, + &NewPartEntry->ListEntry); + } + + LastStartSector = PartEntry->StartSector.QuadPart; + LastSectorCount = PartEntry->SectorCount.QuadPart; + } + + Entry = Entry->Flink; + } + + /* Check for trailing unpartitioned disk space */ + if ((LastStartSector + LastSectorCount) < DiskEntry->EndSector.QuadPart + 1) + { + LastUnusedSectorCount = AlignDown(DiskEntry->EndSector.QuadPart + 1 - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment); + + if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment) + { + DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount); + + NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(PARTENTRY)); + if (NewPartEntry == NULL) + return; + + NewPartEntry->DiskEntry = DiskEntry; + + NewPartEntry->IsPartitioned = FALSE; + NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount; + NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) - + NewPartEntry->StartSector.QuadPart; + + DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); + DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); + DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart); + + NewPartEntry->FormatState = Unformatted; + + /* Append the table to the list */ + InsertTailList(&DiskEntry->PrimaryPartListHead, + &NewPartEntry->ListEntry); + } + } + +#ifdef DUMP_PARTITION_LIST + DumpPartitionList(DiskEntry); +#endif + + DPRINT("ScanForUnpartitionedGptDiskSpace() done\n"); } @@ -869,6 +1120,7 @@ ReadLayoutBuffer( DiskEntry->LayoutBuffer = NewLayoutBuffer; } + } @@ -1084,51 +1336,80 @@ AddDiskToList( DumpPartitionTable(DiskEntry); #endif - if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 && - DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 && - DiskEntry->LayoutBuffer->PartitionEntry[0].Mbr.PartitionType != 0) + if (DiskEntry->PartitionStyle == PARTITION_STYLE_MBR) { - if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0) + if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 && + DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 && + DiskEntry->LayoutBuffer->PartitionEntry[0].Mbr.PartitionType != 0) { - DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack); - } - else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0) - { - DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector); + if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0) + { + DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack); + } + else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0) + { + DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector); + } + else + { + DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart); + } } else { - DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart); + DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector); } - } - else - { - DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector); - } + /* Calculate the number of usable sectors */ + /* Limit the number of usable sectors to 2^32 */ + DiskEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment; + DiskEntry->EndSector.QuadPart = min(DiskEntry->SectorCount.QuadPart, 0x100000000) - 1; - if (DiskEntry->LayoutBuffer->PartitionCount == 0) - { - DiskEntry->NewDisk = TRUE; - DiskEntry->LayoutBuffer->PartitionCount = 4; - - for (i = 0; i < 4; i++) - DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE; - } - else - { - for (i = 0; i < 4; i++) + if (DiskEntry->LayoutBuffer->PartitionCount == 0) { - AddPartitionToDisk(DiskNumber, DiskEntry, i, FALSE); - } + DiskEntry->NewDisk = TRUE; + DiskEntry->LayoutBuffer->PartitionCount = 4; - for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4) + for (i = 0; i < 4; i++) + DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE; + } + else { - AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE); - } - } + for (i = 0; i < 4; i++) + { + AddMbrPartitionToDisk(DiskNumber, DiskEntry, i, FALSE); + } - ScanForUnpartitionedDiskSpace(DiskEntry); + for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4) + { + AddMbrPartitionToDisk(DiskNumber, DiskEntry, i, TRUE); + } + } + + ScanForUnpartitionedMbrDiskSpace(DiskEntry); + } + else if (DiskEntry->PartitionStyle == PARTITION_STYLE_GPT) + { + /* Calculate the number of usable sectors */ + DiskEntry->StartSector.QuadPart = AlignDown(DiskEntry->LayoutBuffer->Gpt.StartingUsableOffset.QuadPart / DiskEntry->BytesPerSector, + DiskEntry->SectorAlignment) + (ULONGLONG)DiskEntry->SectorAlignment; + DiskEntry->EndSector.QuadPart = AlignDown(DiskEntry->StartSector.QuadPart + (DiskEntry->LayoutBuffer->Gpt.UsableLength.QuadPart / DiskEntry->BytesPerSector) - 1, + DiskEntry->SectorAlignment); + + if (DiskEntry->LayoutBuffer->PartitionCount == 0) + { + DiskEntry->NewDisk = TRUE; + } + else + { + for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++) + { + AddGptPartitionToDisk(DiskNumber, DiskEntry, i); + } + } + + ScanForUnpartitionedGptDiskSpace(DiskEntry); + } } @@ -1555,7 +1836,7 @@ DestroyVolumeList(VOID) NTSTATUS -WritePartitions( +WriteMbrPartitions( _In_ PDISKENTRY DiskEntry) { NTSTATUS Status; @@ -1570,7 +1851,7 @@ WritePartitions( PPARTENTRY PartEntry; WCHAR DstPath[MAX_PATH]; - DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber); + DPRINT("WriteMbrPartitions() Disk: %lu\n", DiskEntry->DiskNumber); /* If the disk is not dirty, there is nothing to do */ if (!DiskEntry->Dirty) @@ -1650,7 +1931,7 @@ WritePartitions( if (PartEntry->IsPartitioned) { - ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED); + ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED); PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex]; PartEntry->PartitionNumber = PartitionInfo->PartitionNumber; } @@ -1665,7 +1946,7 @@ WritePartitions( if (PartEntry->IsPartitioned) { - ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED); + ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED); PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex]; PartEntry->PartitionNumber = PartitionInfo->PartitionNumber; } @@ -1678,6 +1959,82 @@ WritePartitions( } +NTSTATUS +WriteGptPartitions( + _In_ PDISKENTRY DiskEntry) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING Name; + HANDLE FileHandle; + IO_STATUS_BLOCK Iosb; + ULONG BufferSize; + WCHAR DstPath[MAX_PATH]; + + DPRINT("WriteGptPartitions() Disk: %lu\n", DiskEntry->DiskNumber); + + /* If the disk is not dirty, there is nothing to do */ + if (!DiskEntry->Dirty) + return STATUS_SUCCESS; + + StringCchPrintfW(DstPath, ARRAYSIZE(DstPath), + L"\\Device\\Harddisk%lu\\Partition0", + DiskEntry->DiskNumber); + RtlInitUnicodeString(&Name, DstPath); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &Iosb, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); + return Status; + } + + // + // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize + // the disk in MBR or GPT format in case the disk was not initialized!! + // For this we must ask the user which format to use. + // + + /* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */ + BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + + ((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION_EX)); + Status = NtDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_SET_DRIVE_LAYOUT_EX, + DiskEntry->LayoutBuffer, + BufferSize, + DiskEntry->LayoutBuffer, + BufferSize); + NtClose(FileHandle); + + /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT_EX call succeeded */ + if (!NT_SUCCESS(Status)) + { + DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT_EX failed (Status 0x%08lx)\n", Status); + return Status; + } + + /* The layout has been successfully updated, the disk is not dirty anymore */ + DiskEntry->Dirty = FALSE; + + return Status; +} + + static BOOLEAN IsEmptyLayoutEntry( @@ -1807,7 +2164,7 @@ ReAllocateLayoutBuffer( VOID -UpdateDiskLayout( +UpdateMbrDiskLayout( _In_ PDISKENTRY DiskEntry) { PPARTITION_INFORMATION_EX PartitionInfo; @@ -1818,7 +2175,7 @@ UpdateDiskLayout( ULONG Index; ULONG PartitionNumber = 1; - DPRINT1("UpdateDiskLayout()\n"); + DPRINT("UpdateMbrDiskLayout()\n"); /* Resize the layout buffer if necessary */ if (ReAllocateLayoutBuffer(DiskEntry) == FALSE) @@ -1839,7 +2196,7 @@ UpdateDiskLayout( if (PartEntry->IsPartitioned) { - ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED); + ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED); PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; PartEntry->PartitionIndex = Index; @@ -1848,7 +2205,7 @@ UpdateDiskLayout( if (PartEntry->New) PartEntry->PartitionNumber = 0; - PartEntry->OnDiskPartitionNumber = (!IsContainerPartition(PartEntry->PartitionType) ? PartitionNumber : 0); + PartEntry->OnDiskPartitionNumber = (!IsContainerPartition(PartEntry->Mbr.PartitionType) ? PartitionNumber : 0); if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry)) { @@ -1859,13 +2216,13 @@ UpdateDiskLayout( PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; PartitionInfo->Mbr.HiddenSectors = PartEntry->StartSector.LowPart; PartitionInfo->PartitionNumber = PartEntry->PartitionNumber; - PartitionInfo->Mbr.PartitionType = PartEntry->PartitionType; - PartitionInfo->Mbr.BootIndicator = PartEntry->BootIndicator; - PartitionInfo->Mbr.RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType); + PartitionInfo->Mbr.PartitionType = PartEntry->Mbr.PartitionType; + PartitionInfo->Mbr.BootIndicator = PartEntry->Mbr.BootIndicator; + PartitionInfo->Mbr.RecognizedPartition = IsRecognizedPartition(PartEntry->Mbr.PartitionType); PartitionInfo->RewritePartition = TRUE; } - if (!IsContainerPartition(PartEntry->PartitionType)) + if (!IsContainerPartition(PartEntry->Mbr.PartitionType)) PartitionNumber++; Index++; @@ -1884,7 +2241,7 @@ UpdateDiskLayout( if (PartEntry->IsPartitioned) { - ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED); + ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED); PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; PartEntry->PartitionIndex = Index; @@ -1902,9 +2259,9 @@ UpdateDiskLayout( PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; PartitionInfo->Mbr.HiddenSectors = DiskEntry->SectorAlignment; PartitionInfo->PartitionNumber = PartEntry->PartitionNumber; - PartitionInfo->Mbr.PartitionType = PartEntry->PartitionType; + PartitionInfo->Mbr.PartitionType = PartEntry->Mbr.PartitionType; PartitionInfo->Mbr.BootIndicator = FALSE; - PartitionInfo->Mbr.RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType); + PartitionInfo->Mbr.RecognizedPartition = IsRecognizedPartition(PartEntry->Mbr.PartitionType); PartitionInfo->RewritePartition = TRUE; /* Fill the link entry of the previous partition entry */ @@ -1983,6 +2340,94 @@ UpdateDiskLayout( } +VOID +UpdateGptDiskLayout( + _In_ PDISKENTRY DiskEntry, + _In_ BOOL DeleteEntry) +{ + PLIST_ENTRY ListEntry; + PPARTENTRY PartEntry; + PPARTITION_INFORMATION_EX PartitionInfo; + ULONG Count, Index; + + DPRINT("UpdateGptDiskLayout()\n"); + + /* Count used partition entries */ + Count = 0; + for (ListEntry = DiskEntry->PrimaryPartListHead.Flink; + ListEntry != &DiskEntry->PrimaryPartListHead; + ListEntry = ListEntry->Flink) + { + PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); + + if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) + Count++; + } + + DPRINT("Used partition entries: %lu\n", Count); + + if (DeleteEntry) + Count++; + + /* Reallocate the layout buffer */ + if (Count != DiskEntry->LayoutBuffer->PartitionCount) + { + PDRIVE_LAYOUT_INFORMATION_EX NewLayoutBuffer; + ULONG NewLayoutBufferSize; + + NewLayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + + ((Count - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION_EX)); + NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + DiskEntry->LayoutBuffer, + NewLayoutBufferSize); + if (NewLayoutBuffer == NULL) + { + DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", NewLayoutBufferSize); + return; + } + + NewLayoutBuffer->PartitionCount = Count; + DiskEntry->LayoutBuffer = NewLayoutBuffer; + } + + /* Fill the new layout buffer */ + Index = 0; + for (ListEntry = DiskEntry->PrimaryPartListHead.Flink; + ListEntry != &DiskEntry->PrimaryPartListHead; + ListEntry = ListEntry->Flink) + { + PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); + + if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) + { + PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; + PartEntry->PartitionIndex = Index; + + DPRINT("Updating primary partition entry %lu\n", Index); + PartitionInfo->PartitionStyle = PARTITION_STYLE_GPT; + PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector; + PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; + PartitionInfo->PartitionNumber = Index + 1; + PartitionInfo->RewritePartition = TRUE; + CopyMemory(&PartitionInfo->Gpt.PartitionType, &PartEntry->Gpt.PartitionType, sizeof(GUID)); + CopyMemory(&PartitionInfo->Gpt.PartitionId, &PartEntry->Gpt.PartitionId, sizeof(GUID)); + PartitionInfo->Gpt.Attributes = PartEntry->Gpt.Attributes; + ZeroMemory(&PartitionInfo->Gpt.Name, 36 * sizeof(WCHAR)); /* ??? */ + + Index++; + } + } + + if (DeleteEntry) + { + PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; + ZeroMemory(PartitionInfo, sizeof(PARTITION_INFORMATION_EX)); + PartitionInfo->RewritePartition = TRUE; + } +} + + PPARTENTRY GetPrevUnpartitionedEntry( _In_ PPARTENTRY PartEntry) @@ -2003,7 +2448,7 @@ GetPrevUnpartitionedEntry( ListEntry); if (!PrevPartEntry->IsPartitioned) { - ASSERT(PrevPartEntry->PartitionType == PARTITION_ENTRY_UNUSED); + ASSERT(PrevPartEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED); return PrevPartEntry; } } @@ -2032,7 +2477,7 @@ GetNextUnpartitionedEntry( ListEntry); if (!NextPartEntry->IsPartitioned) { - ASSERT(NextPartEntry->PartitionType == PARTITION_ENTRY_UNUSED); + ASSERT(NextPartEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED); return NextPartEntry; } } @@ -2055,8 +2500,8 @@ DismountVolume( /* Check whether the partition is valid and was mounted by the system */ if (!PartEntry->IsPartitioned || - IsContainerPartition(PartEntry->PartitionType) || - !IsRecognizedPartition(PartEntry->PartitionType) || + IsContainerPartition(PartEntry->Mbr.PartitionType) || + !IsRecognizedPartition(PartEntry->Mbr.PartitionType) || PartEntry->FormatState == UnknownFormat || // NOTE: If FormatState == Unformatted but *FileSystem != 0 this means // it has been usually mounted with RawFS and thus needs to be dismounted. @@ -2067,7 +2512,7 @@ DismountVolume( return STATUS_SUCCESS; } - ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED); + ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED); /* Open the volume */ StringCchPrintfW(Buffer, ARRAYSIZE(Buffer), diff --git a/base/system/diskpart/resource.h b/base/system/diskpart/resource.h index b6144957800..ec83e8969b7 100644 --- a/base/system/diskpart/resource.h +++ b/base/system/diskpart/resource.h @@ -61,9 +61,10 @@ #define IDS_DETAIL_PARTITION_HIDDEN 1132 #define IDS_DETAIL_PARTITION_ACTIVE 1133 #define IDS_DETAIL_PARTITION_OFFSET 1134 - -#define IDS_DETAIL_NO_DISKS 1135 -#define IDS_DETAIL_NO_VOLUME 1136 +#define IDS_DETAIL_PARTITION_REQUIRED 1135 +#define IDS_DETAIL_PARTITION_ATTRIBUTE 1136 +#define IDS_DETAIL_NO_DISKS 1137 +#define IDS_DETAIL_NO_VOLUME 1138 #define IDS_FILESYSTEMS_CURRENT 1180 #define IDS_FILESYSTEMS_FORMATTING 1181 diff --git a/base/system/diskpart/select.c b/base/system/diskpart/select.c index aa39ae6bb9a..0074a96891f 100644 --- a/base/system/diskpart/select.c +++ b/base/system/diskpart/select.c @@ -161,43 +161,68 @@ SelectPartition( return TRUE; } - Entry = CurrentDisk->PrimaryPartListHead.Flink; - while (Entry != &CurrentDisk->PrimaryPartListHead) + if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) { - PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); - - if (PartEntry->PartitionType != 0) + Entry = CurrentDisk->PrimaryPartListHead.Flink; + while (Entry != &CurrentDisk->PrimaryPartListHead) { - if (PartNumber == ulValue) + PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); + + if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED) { - CurrentPartition = PartEntry; - ConResPrintf(StdOut, IDS_SELECT_PARTITION, PartNumber); - return TRUE; + if (PartNumber == ulValue) + { + CurrentPartition = PartEntry; + ConResPrintf(StdOut, IDS_SELECT_PARTITION, PartNumber); + return TRUE; + } + + PartNumber++; } - PartNumber++; + Entry = Entry->Flink; } - Entry = Entry->Flink; + Entry = CurrentDisk->LogicalPartListHead.Flink; + while (Entry != &CurrentDisk->LogicalPartListHead) + { + PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); + + if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED) + { + if (PartNumber == ulValue) + { + CurrentPartition = PartEntry; + ConResPrintf(StdOut, IDS_SELECT_PARTITION, PartNumber); + return TRUE; + } + + PartNumber++; + } + Entry = Entry->Flink; + } } - - Entry = CurrentDisk->LogicalPartListHead.Flink; - while (Entry != &CurrentDisk->LogicalPartListHead) + else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) { - PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); - - if (PartEntry->PartitionType != 0) + Entry = CurrentDisk->PrimaryPartListHead.Flink; + while (Entry != &CurrentDisk->PrimaryPartListHead) { - if (PartNumber == ulValue) + PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); + + if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) { - CurrentPartition = PartEntry; - ConResPrintf(StdOut, IDS_SELECT_PARTITION, PartNumber); - return TRUE; + if (PartNumber == ulValue) + { + CurrentPartition = PartEntry; + ConResPrintf(StdOut, IDS_SELECT_PARTITION, PartNumber); + return TRUE; + } + + PartNumber++; } - PartNumber++; + Entry = Entry->Flink; } - Entry = Entry->Flink; } ConResPuts(StdErr, IDS_SELECT_PARTITION_INVALID); diff --git a/base/system/diskpart/setid.c b/base/system/diskpart/setid.c index a7ab413ae2f..1380c8f1620 100644 --- a/base/system/diskpart/setid.c +++ b/base/system/diskpart/setid.c @@ -17,7 +17,6 @@ setid_main( _In_ INT argc, _In_ PWSTR *argv) { - UCHAR PartitionType = 0; INT i, length; PWSTR pszSuffix, pszId = NULL; NTSTATUS Status; @@ -65,11 +64,25 @@ setid_main( if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) { - ConPuts(StdErr, L"The setid command does not support GPT disks yet!\n"); - return TRUE; + if (!StringToGUID(&CurrentPartition->Gpt.PartitionType, pszId)) + { + ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); + return TRUE; + } + + CurrentDisk->Dirty = TRUE; + UpdateGptDiskLayout(CurrentDisk, FALSE); + Status = WriteGptPartitions(CurrentDisk); + if (!NT_SUCCESS(Status)) + { + ConResPuts(StdOut, IDS_SETID_FAIL); + return TRUE; + } } else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) { + UCHAR PartitionType = 0; + length = wcslen(pszId); if (length == 0) { @@ -96,10 +109,10 @@ setid_main( return TRUE; } - CurrentPartition->PartitionType = PartitionType; + CurrentPartition->Mbr.PartitionType = PartitionType; CurrentDisk->Dirty = TRUE; - UpdateDiskLayout(CurrentDisk); - Status = WritePartitions(CurrentDisk); + UpdateMbrDiskLayout(CurrentDisk); + Status = WriteMbrPartitions(CurrentDisk); if (!NT_SUCCESS(Status)) { ConResPuts(StdOut, IDS_SETID_FAIL); diff --git a/base/system/diskpart/uniqueid.c b/base/system/diskpart/uniqueid.c index a56981c73ac..e38bba03ac0 100644 --- a/base/system/diskpart/uniqueid.c +++ b/base/system/diskpart/uniqueid.c @@ -72,7 +72,15 @@ UniqueIdDisk( if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) { - ConPuts(StdErr, L"The uniqueid disk command does not support GPT disks yet!\n"); + if (!StringToGUID(&CurrentDisk->LayoutBuffer->Gpt.DiskId, pszId)) + { + ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); + return TRUE; + } + + CurrentDisk->Dirty = TRUE; + UpdateGptDiskLayout(CurrentDisk, FALSE); + WriteGptPartitions(CurrentDisk); } else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) { @@ -94,8 +102,8 @@ UniqueIdDisk( DPRINT("New Signature: 0x%08lx\n", ulValue); CurrentDisk->LayoutBuffer->Mbr.Signature = ulValue; CurrentDisk->Dirty = TRUE; - UpdateDiskLayout(CurrentDisk); - WritePartitions(CurrentDisk); + UpdateMbrDiskLayout(CurrentDisk); + WriteMbrPartitions(CurrentDisk); } else {