X-Git-Url: http://git.jankratochvil.net/?p=reactos.git;a=blobdiff_plain;f=subsys%2Fsystem%2Fusetup%2Fpartlist.c;fp=subsys%2Fsystem%2Fusetup%2Fpartlist.c;h=633376bb6104ebe6cde9979a753559885ee60036;hp=121a628c29ed7f6747e4992563893c5dabf72ff4;hb=7c0cf90e3b750f1f0dc83b2eec9e5c68a512c30f;hpb=ee8b63255465d8c28be3e7bd11628015708fc1ab diff --git a/subsys/system/usetup/partlist.c b/subsys/system/usetup/partlist.c index 121a628..633376b 100644 --- a/subsys/system/usetup/partlist.c +++ b/subsys/system/usetup/partlist.c @@ -1,6 +1,6 @@ /* * ReactOS kernel - * Copyright (C) 2002 ReactOS Team + * Copyright (C) 2002, 2003 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,569 +41,675 @@ /* FUNCTIONS ****************************************************************/ static VOID -AddPartitionList(ULONG DiskNumber, - PDISKENTRY DiskEntry, - DRIVE_LAYOUT_INFORMATION *LayoutBuffer) +GetDriverName (PDISKENTRY DiskEntry) { - PPARTENTRY PartEntry; - ULONG i; - ULONG EntryCount; - BOOLEAN LastEntryWasUnused; - ULONGLONG LastStartingOffset; - ULONGLONG LastPartitionSize; - ULONGLONG LastUnusedPartitionSize; - ULONG LastUnusedEntry; - - /* - * FIXME: - * Determine required number of partiton entries. - * This must include entries for unused disk space. - */ - - /* Check for unpartitioned disk */ - if (LayoutBuffer->PartitionCount == 0) - { - EntryCount = 1; - } - else + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + WCHAR KeyName[32]; + NTSTATUS Status; + + RtlInitUnicodeString (&DiskEntry->DriverName, + NULL); + + swprintf (KeyName, + L"\\Scsi\\Scsi Port %lu", + DiskEntry->Port); + + RtlZeroMemory (&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"Driver"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = &DiskEntry->DriverName; + + Status = RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP, + KeyName, + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS (Status)) { - EntryCount = LayoutBuffer->PartitionCount; + DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status); } +} - DiskEntry->PartArray = (PPARTENTRY)RtlAllocateHeap(ProcessHeap, - 0, - EntryCount * sizeof(PARTENTRY)); - DiskEntry->PartCount = EntryCount; +static VOID +AssignDriverLetters (PPARTLIST List) +{ + PDISKENTRY DiskEntry; + PPARTENTRY PartEntry; + PLIST_ENTRY Entry1; + PLIST_ENTRY Entry2; + CHAR Letter; - RtlZeroMemory(DiskEntry->PartArray, - EntryCount * sizeof(PARTENTRY)); + Letter = 'C'; - if (LayoutBuffer->PartitionCount == 0) + /* Assign drive letters to primary partitions */ + Entry1 = List->DiskListHead.Flink; + while (Entry1 != &List->DiskListHead) { - /* Initialize an 'Unpartitioned space' entry */ - PartEntry = &DiskEntry->PartArray[0]; + DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry); - PartEntry->Unpartitioned = TRUE; - // Start partition at head 1, cylinder 0 - PartEntry->StartingOffset = DiskEntry->SectorsPerTrack * DiskEntry->BytesPerSector; - PartEntry->PartSize = DiskEntry->DiskSize - PartEntry->StartingOffset; - PartEntry->Used = FALSE; - PartEntry->HidePartEntry = FALSE; - PartEntry->PartNumber = 1; - } - else - { - LastEntryWasUnused = FALSE; - // Start partition at head 1, cylinder 0 - LastStartingOffset = DiskEntry->SectorsPerTrack * DiskEntry->BytesPerSector; - LastPartitionSize = 0; - LastUnusedEntry = -1; - LastUnusedPartitionSize = 0; - for (i = 0; i < LayoutBuffer->PartitionCount; i++) + if (!IsListEmpty (&DiskEntry->PartListHead)) { - PartEntry = &DiskEntry->PartArray[i]; + PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink, + PARTENTRY, + ListEntry); - if ((LayoutBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED) && - (!IsContainerPartition(LayoutBuffer->PartitionEntry[i].PartitionType))) + PartEntry->DriveLetter = 0; + + if (PartEntry->Unpartitioned == FALSE && + !IsContainerPartition (PartEntry->PartInfo[0].PartitionType)) { - LastUnusedPartitionSize = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart - - (LastStartingOffset + LastPartitionSize); - if (LastUnusedEntry != -1) - { - DiskEntry->PartArray[LastUnusedEntry].StartingOffset = LastStartingOffset + LastPartitionSize; - DiskEntry->PartArray[LastUnusedEntry].PartSize = LastUnusedPartitionSize; - DiskEntry->PartArray[LastUnusedEntry].PartNumber = LastUnusedEntry + 1; /* FIXME: Is this always correct? */ - } - LastStartingOffset = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart; - LastPartitionSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart; - - PartEntry->StartingOffset = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart; - PartEntry->PartSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart; - PartEntry->PartNumber = LayoutBuffer->PartitionEntry[i].PartitionNumber, - PartEntry->PartType = LayoutBuffer->PartitionEntry[i].PartitionType; - PartEntry->Active = LayoutBuffer->PartitionEntry[i].BootIndicator; - - PartEntry->DriveLetter = GetDriveLetter(DiskNumber, - LayoutBuffer->PartitionEntry[i].PartitionNumber); - - PartEntry->Unpartitioned = FALSE; - - PartEntry->Used = TRUE; - PartEntry->HidePartEntry = FALSE; - LastEntryWasUnused = FALSE; - LastUnusedEntry = -1; + if (IsRecognizedPartition (PartEntry->PartInfo[0].PartitionType) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED && + PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL)) + { + if (Letter <= 'Z') + { + PartEntry->DriveLetter = Letter; + Letter++; + } + } } - else + } + + Entry1 = Entry1->Flink; + } + + + /* Assign drive letters to logical drives */ + Entry1 = List->DiskListHead.Flink; + while (Entry1 != &List->DiskListHead) + { + DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry); + + Entry2 = DiskEntry->PartListHead.Flink; + if (Entry2 != &DiskEntry->PartListHead) + { + Entry2 = Entry2->Flink; + while (Entry2 != &DiskEntry->PartListHead) { - if (LastEntryWasUnused) - { - /* Group unused entries into one unpartitioned disk space area */ - PartEntry->HidePartEntry = TRUE; - PartEntry->PartSize = 0; - } - else - { - LastUnusedEntry = i; - } - - PartEntry->Unpartitioned = TRUE; - - PartEntry->Used = FALSE; - LastEntryWasUnused = TRUE; + PartEntry = CONTAINING_RECORD (Entry2, + PARTENTRY, + ListEntry); + + PartEntry->DriveLetter = 0; + + if (PartEntry->Unpartitioned == FALSE && + !IsContainerPartition (PartEntry->PartInfo[0].PartitionType)) + { + if (IsRecognizedPartition (PartEntry->PartInfo[0].PartitionType) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED && + PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL)) + { + if (Letter <= 'Z') + { + PartEntry->DriveLetter = Letter; + Letter++; + } + } + } + + Entry2 = Entry2->Flink; } } - LastUnusedPartitionSize = DiskEntry->DiskSize - - (LastStartingOffset + LastPartitionSize); - if (LastUnusedEntry != -1) - { - DiskEntry->PartArray[LastUnusedEntry].StartingOffset = LastStartingOffset + LastPartitionSize; - DiskEntry->PartArray[LastUnusedEntry].PartSize = LastUnusedPartitionSize; - DiskEntry->PartArray[LastUnusedEntry].PartNumber = LastUnusedEntry + 1; /* FIXME: Is this always correct? */ - } + + Entry1 = Entry1->Flink; } } static VOID -GetDriverName(PDISKENTRY DiskEntry) +UpdatePartitionNumbers (PDISKENTRY DiskEntry) { - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - WCHAR KeyName[32]; - NTSTATUS Status; - - RtlInitUnicodeString(&DiskEntry->DriverName, - NULL); - - swprintf(KeyName, - L"\\Scsi\\Scsi Port %lu", - DiskEntry->Port); + PPARTENTRY PartEntry; + PLIST_ENTRY Entry; + ULONG PartNumber; + ULONG i; - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); + PartNumber = 1; + Entry = DiskEntry->PartListHead.Flink; + while (Entry != &DiskEntry->PartListHead) + { + PartEntry = CONTAINING_RECORD (Entry, + PARTENTRY, + ListEntry); - QueryTable[0].Name = L"Driver"; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[0].EntryContext = &DiskEntry->DriverName; + if (PartEntry->Unpartitioned == TRUE) + { + for (i = 0; i < 4; i++) + { + PartEntry->PartInfo[i].PartitionNumber = 0; + } + } + else + { + for (i = 0; i < 4; i++) + { + if (IsContainerPartition (PartEntry->PartInfo[i].PartitionType)) + { + PartEntry->PartInfo[i].PartitionNumber = 0; + } + else if (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED && + PartEntry->PartInfo[i].PartitionLength.QuadPart == 0ULL) + { + PartEntry->PartInfo[i].PartitionNumber = 0; + } + else + { + PartEntry->PartInfo[i].PartitionNumber = PartNumber; + PartNumber++; + } + } + } - Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP, - KeyName, - QueryTable, - NULL, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status); + Entry = Entry->Flink; } } -PPARTLIST -CreatePartitionListNoGUI() +static VOID +AddPartitionToList (ULONG DiskNumber, + PDISKENTRY DiskEntry, + DRIVE_LAYOUT_INFORMATION *LayoutBuffer) { - PPARTLIST List; - OBJECT_ATTRIBUTES ObjectAttributes; - SYSTEM_DEVICE_INFORMATION Sdi; - DISK_GEOMETRY DiskGeometry; - IO_STATUS_BLOCK Iosb; - ULONG ReturnSize; - NTSTATUS Status; - ULONG DiskNumber; - WCHAR Buffer[MAX_PATH]; - UNICODE_STRING Name; - HANDLE FileHandle; - DRIVE_LAYOUT_INFORMATION *LayoutBuffer; - SCSI_ADDRESS ScsiAddress; + PPARTENTRY PartEntry; + ULONG i; + ULONG j; - List = (PPARTLIST)RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTLIST)); - if (List == NULL) - return(NULL); + for (i = 0; i < LayoutBuffer->PartitionCount; i += 4) + { + for (j = 0; j < 4; j++) + { + if (LayoutBuffer->PartitionEntry[j].PartitionType != PARTITION_ENTRY_UNUSED || + LayoutBuffer->PartitionEntry[j].PartitionLength.QuadPart != 0ULL) + { + break; + } + } + if (j >= 4) + { + continue; + } + + PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap, + 0, + sizeof(PARTENTRY)); + if (PartEntry == NULL) + { + return; + } - List->Left = 0; - List->Top = 0; - List->Right = 0; - List->Bottom = 0; + RtlZeroMemory (PartEntry, + sizeof(PARTENTRY)); - List->Line = 0; + PartEntry->Unpartitioned = FALSE; - List->TopDisk = (ULONG)-1; - List->TopPartition = (ULONG)-1; + for (j = 0; j < 4; j++) + { + RtlCopyMemory (&PartEntry->PartInfo[j], + &LayoutBuffer->PartitionEntry[i+j], + sizeof(PARTITION_INFORMATION)); + } + + if (IsContainerPartition(PartEntry->PartInfo[0].PartitionType)) + { + PartEntry->FormatState = Unformatted; + } + else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13)) + { +#if 0 + if (CheckFatFormat()) + { + PartEntry->FormatState = Preformatted; + } + else + { + PartEntry->FormatState = Unformatted; + } +#endif + PartEntry->FormatState = Preformatted; + } + else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS) + { +#if 0 + if (CheckNtfsFormat()) + { + PartEntry->FormatState = Preformatted; + } + else if (CheckHpfsFormat()) + { + PartEntry->FormatState = Preformatted; + } + else + { + PartEntry->FormatState = Unformatted; + } +#endif + PartEntry->FormatState = Preformatted; + } + else + { + PartEntry->FormatState = Unknown; + } - List->CurrentDisk = (ULONG)-1; - List->CurrentPartition = (ULONG)-1; + InsertTailList (&DiskEntry->PartListHead, + &PartEntry->ListEntry); + } +} - List->DiskCount = 0; - List->DiskArray = NULL; +static VOID +ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry) +{ + ULONGLONG LastStartingOffset; + ULONGLONG LastPartitionLength; + ULONGLONG LastUnusedPartitionLength; + PPARTENTRY PartEntry; + PPARTENTRY NewPartEntry; + PLIST_ENTRY Entry; + ULONG i; + ULONG j; - Status = NtQuerySystemInformation(SystemDeviceInformation, - &Sdi, - sizeof(SYSTEM_DEVICE_INFORMATION), - &ReturnSize); - if (!NT_SUCCESS(Status)) + if (IsListEmpty (&DiskEntry->PartListHead)) { - RtlFreeHeap(ProcessHeap, 0, List); - return(NULL); - } + /* Create a partition table that represents the empty disk */ + PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap, + 0, + sizeof(PARTENTRY)); + if (PartEntry == NULL) + return; - List->DiskArray = (PDISKENTRY)RtlAllocateHeap(ProcessHeap, - 0, - Sdi.NumberOfDisks * sizeof(DISKENTRY)); - List->DiskCount = Sdi.NumberOfDisks; + RtlZeroMemory (PartEntry, + sizeof(PARTENTRY)); - for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++) + PartEntry->Unpartitioned = TRUE; + PartEntry->UnpartitionedOffset = 0ULL; + PartEntry->UnpartitionedLength = DiskEntry->DiskSize; + + PartEntry->FormatState = Unformatted; + + InsertTailList (&DiskEntry->PartListHead, + &PartEntry->ListEntry); + } + else { - swprintf(Buffer, - L"\\Device\\Harddisk%d\\Partition0", - DiskNumber); - RtlInitUnicodeString(&Name, - Buffer); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - 0x10001, - &ObjectAttributes, - &Iosb, - 1, - FILE_SYNCHRONOUS_IO_NONALERT); - if (NT_SUCCESS(Status)) + /* Start partition at head 1, cylinder 0 */ + LastStartingOffset = DiskEntry->TrackSize; + LastPartitionLength = 0ULL; + LastUnusedPartitionLength = 0ULL; + + i = 0; + Entry = DiskEntry->PartListHead.Flink; + while (Entry != &DiskEntry->PartListHead) { - Status = NtDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_DISK_GET_DRIVE_GEOMETRY, - NULL, - 0, - &DiskGeometry, - sizeof(DISK_GEOMETRY)); - if (NT_SUCCESS(Status)) + PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry); + + for (j = 0; j < 4; j++) { - if (DiskGeometry.MediaType == FixedMedia) + if ((!IsContainerPartition (PartEntry->PartInfo[j].PartitionType)) && + (PartEntry->PartInfo[j].PartitionType != PARTITION_ENTRY_UNUSED || + PartEntry->PartInfo[j].PartitionLength.QuadPart != 0LL)) { - Status = NtDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_SCSI_GET_ADDRESS, - NULL, - 0, - &ScsiAddress, - sizeof(SCSI_ADDRESS)); - - - List->DiskArray[DiskNumber].Cylinders = DiskGeometry.Cylinders.QuadPart; - List->DiskArray[DiskNumber].TracksPerCylinder = DiskGeometry.TracksPerCylinder; - List->DiskArray[DiskNumber].SectorsPerTrack = DiskGeometry.SectorsPerTrack; - List->DiskArray[DiskNumber].BytesPerSector = DiskGeometry.BytesPerSector; - - DPRINT("Cylinders %d\n", List->DiskArray[DiskNumber].Cylinders); - DPRINT("TracksPerCylinder %d\n", List->DiskArray[DiskNumber].TracksPerCylinder); - DPRINT("SectorsPerTrack %d\n", List->DiskArray[DiskNumber].SectorsPerTrack); - DPRINT("BytesPerSector %d\n", List->DiskArray[DiskNumber].BytesPerSector); - - List->DiskArray[DiskNumber].DiskSize = - DiskGeometry.Cylinders.QuadPart * - (ULONGLONG)DiskGeometry.TracksPerCylinder * - (ULONGLONG)DiskGeometry.SectorsPerTrack * - (ULONGLONG)DiskGeometry.BytesPerSector; - List->DiskArray[DiskNumber].DiskNumber = DiskNumber; - List->DiskArray[DiskNumber].Port = ScsiAddress.PortNumber; - List->DiskArray[DiskNumber].Bus = ScsiAddress.PathId; - List->DiskArray[DiskNumber].Id = ScsiAddress.TargetId; - - List->DiskArray[DiskNumber].FixedDisk = TRUE; - - GetDriverName(&List->DiskArray[DiskNumber]); - - LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192); - - Status = NtDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_DISK_GET_DRIVE_LAYOUT, - NULL, - 0, - LayoutBuffer, - 8192); - if (NT_SUCCESS(Status)) + LastUnusedPartitionLength = + PartEntry->PartInfo[j].StartingOffset.QuadPart - + (LastStartingOffset + LastPartitionLength); + + if (LastUnusedPartitionLength >= DiskEntry->CylinderSize) { - AddPartitionList(DiskNumber, - &List->DiskArray[DiskNumber], - LayoutBuffer); + DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength); + + NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap, + 0, + sizeof(PARTENTRY)); + if (NewPartEntry == NULL) + return; + + RtlZeroMemory (NewPartEntry, + sizeof(PARTENTRY)); + + NewPartEntry->Unpartitioned = TRUE; + NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength; + NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength; + if (j == 0) + NewPartEntry->UnpartitionedLength -= DiskEntry->TrackSize; + + NewPartEntry->FormatState = Unformatted; + + /* Insert the table into the list */ + InsertTailList (&PartEntry->ListEntry, + &NewPartEntry->ListEntry); } - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); - } - else - { - /* mark removable disk entry */ - List->DiskArray[DiskNumber].FixedDisk = FALSE; - List->DiskArray[DiskNumber].PartCount = 0; - List->DiskArray[DiskNumber].PartArray = NULL; + LastStartingOffset = PartEntry->PartInfo[j].StartingOffset.QuadPart; + LastPartitionLength = PartEntry->PartInfo[j].PartitionLength.QuadPart; } } - NtClose(FileHandle); + i += 4; + Entry = Entry->Flink; } - } - - List->TopDisk = 0; - List->TopPartition = 0; - - /* FIXME: search for first usable disk and partition */ - List->CurrentDisk = 0; - List->CurrentPartition = 0; - return(List); -} + /* Check for trailing unpartitioned disk space */ + if (DiskEntry->DiskSize > (LastStartingOffset + LastPartitionLength)) + { + /* Round-down to cylinder size */ + LastUnusedPartitionLength = + ROUND_DOWN (DiskEntry->DiskSize - (LastStartingOffset + LastPartitionLength), + DiskEntry->CylinderSize); -PPARTLIST -CreatePartitionList(SHORT Left, - SHORT Top, - SHORT Right, - SHORT Bottom) -{ - PPARTLIST List; + if (LastUnusedPartitionLength >= DiskEntry->CylinderSize) + { + DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength); - List = CreatePartitionListNoGUI(); - if (List == NULL) - return(NULL); + NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap, + 0, + sizeof(PARTENTRY)); + if (NewPartEntry == NULL) + return; - List->Left = Left; - List->Top = Top; - List->Right = Right; - List->Bottom = Bottom; + RtlZeroMemory (NewPartEntry, + sizeof(PARTENTRY)); - DrawPartitionList(List); + NewPartEntry->Unpartitioned = TRUE; + NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength; + NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength; - return(List); + /* Append the table to the list */ + InsertTailList (&DiskEntry->PartListHead, + &NewPartEntry->ListEntry); + } + } + } } -PPARTENTRY -GetPartitionInformation(PPARTLIST List, - ULONG DiskNumber, - ULONG PartitionNumber, - PULONG PartEntryNumber) +static VOID +AddDiskToList (HANDLE FileHandle, + ULONG DiskNumber, + PPARTLIST List) { - PPARTENTRY PartEntry; - ULONG i; + DRIVE_LAYOUT_INFORMATION *LayoutBuffer; + DISK_GEOMETRY DiskGeometry; + SCSI_ADDRESS ScsiAddress; + PDISKENTRY DiskEntry; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; - if (List->DiskArray == NULL) + Status = NtDeviceIoControlFile (FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + sizeof(DISK_GEOMETRY)); + if (!NT_SUCCESS (Status)) { - return(FALSE); + return; } - if (DiskNumber >= List->DiskCount) + if (DiskGeometry.MediaType != FixedMedia) { - return(FALSE); + return; } - if (PartitionNumber >= List->DiskArray[DiskNumber].PartCount) + Status = NtDeviceIoControlFile (FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_SCSI_GET_ADDRESS, + NULL, + 0, + &ScsiAddress, + sizeof(SCSI_ADDRESS)); + if (!NT_SUCCESS(Status)) { - return(FALSE); + return; } - if (List->DiskArray[DiskNumber].FixedDisk != TRUE) + DiskEntry = (PDISKENTRY)RtlAllocateHeap (ProcessHeap, + 0, + sizeof(DISKENTRY)); + if (DiskEntry == NULL) { - return(FALSE); + return; } - for (i = 0; i < List->DiskArray[DiskNumber].PartCount; i++) + InitializeListHead (&DiskEntry->PartListHead); + + DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart; + DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder; + DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack; + DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector; + + DPRINT ("Cylinders %d\n", DiskEntry->Cylinders); + DPRINT ("TracksPerCylinder %d\n", DiskEntry->TracksPerCylinder); + DPRINT ("SectorsPerTrack %d\n", DiskEntry->SectorsPerTrack); + DPRINT ("BytesPerSector %d\n", DiskEntry->BytesPerSector); + + DiskEntry->DiskSize = + DiskGeometry.Cylinders.QuadPart * + (ULONGLONG)DiskGeometry.TracksPerCylinder * + (ULONGLONG)DiskGeometry.SectorsPerTrack * + (ULONGLONG)DiskGeometry.BytesPerSector; + DiskEntry->CylinderSize = + (ULONGLONG)DiskGeometry.TracksPerCylinder * + (ULONGLONG)DiskGeometry.SectorsPerTrack * + (ULONGLONG)DiskGeometry.BytesPerSector; + DiskEntry->TrackSize = + (ULONGLONG)DiskGeometry.SectorsPerTrack * + (ULONGLONG)DiskGeometry.BytesPerSector; + + DiskEntry->DiskNumber = DiskNumber; + DiskEntry->Port = ScsiAddress.PortNumber; + DiskEntry->Bus = ScsiAddress.PathId; + DiskEntry->Id = ScsiAddress.TargetId; + + GetDriverName (DiskEntry); + + InsertTailList (&List->DiskListHead, + &DiskEntry->ListEntry); + + LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap (ProcessHeap, + 0, + 8192); + if (LayoutBuffer == NULL) { - PartEntry = &List->DiskArray[DiskNumber].PartArray[i]; - if (PartEntry->PartNumber == PartitionNumber) - { - *PartEntryNumber = i; - return PartEntry; - } + return; } - return NULL; + + Status = NtDeviceIoControlFile (FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_GET_DRIVE_LAYOUT, + NULL, + 0, + LayoutBuffer, + 8192); + if (NT_SUCCESS (Status)) + { + if (LayoutBuffer->PartitionCount == 0) + { + DiskEntry->NewDisk = TRUE; + } + + AddPartitionToList (DiskNumber, + DiskEntry, + LayoutBuffer); + + ScanForUnpartitionedDiskSpace (DiskEntry); + } + + RtlFreeHeap (ProcessHeap, + 0, + LayoutBuffer); } -BOOLEAN -MarkPartitionActive(ULONG DiskNumber, - ULONG PartitionNumber, - PPARTDATA ActivePartition) + +PPARTLIST +CreatePartitionList (SHORT Left, + SHORT Top, + SHORT Right, + SHORT Bottom) { PPARTLIST List; - PPARTENTRY PartEntry; - ULONG PartEntryNumber; OBJECT_ATTRIBUTES ObjectAttributes; - DRIVE_LAYOUT_INFORMATION *LayoutBuffer; + SYSTEM_DEVICE_INFORMATION Sdi; + DISK_GEOMETRY DiskGeometry; IO_STATUS_BLOCK Iosb; + ULONG ReturnSize; NTSTATUS Status; + ULONG DiskNumber; WCHAR Buffer[MAX_PATH]; UNICODE_STRING Name; HANDLE FileHandle; - List = CreatePartitionListNoGUI(); + List = (PPARTLIST)RtlAllocateHeap (ProcessHeap, + 0, + sizeof (PARTLIST)); if (List == NULL) + return NULL; + + List->Left = Left; + List->Top = Top; + List->Right = Right; + List->Bottom = Bottom; + + List->Line = 0; + + List->TopDisk = (ULONG)-1; + List->TopPartition = (ULONG)-1; + + List->CurrentDisk = NULL; + List->CurrentPartition = NULL; + + InitializeListHead (&List->DiskListHead); + + Status = NtQuerySystemInformation (SystemDeviceInformation, + &Sdi, + sizeof(SYSTEM_DEVICE_INFORMATION), + &ReturnSize); + if (!NT_SUCCESS (Status)) { - return(FALSE); + RtlFreeHeap (ProcessHeap, 0, List); + return NULL; } - PartEntry = GetPartitionInformation(List, - DiskNumber, - PartitionNumber, - &PartEntryNumber); - if (List == NULL) + for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++) { - DestroyPartitionList(List); - return(FALSE); + swprintf (Buffer, + L"\\Device\\Harddisk%d\\Partition0", + DiskNumber); + RtlInitUnicodeString (&Name, + Buffer); + + InitializeObjectAttributes (&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtOpenFile (&FileHandle, + FILE_GENERIC_READ, + &ObjectAttributes, + &Iosb, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + if (NT_SUCCESS(Status)) + { + AddDiskToList (FileHandle, + DiskNumber, + List); + + NtClose(FileHandle); + } } + AssignDriverLetters (List); + + List->TopDisk = 0; + List->TopPartition = 0; - swprintf(Buffer, - L"\\Device\\Harddisk%d\\Partition0", - DiskNumber); - RtlInitUnicodeString(&Name, Buffer); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - 0x10001, - &ObjectAttributes, - &Iosb, - 1, - FILE_SYNCHRONOUS_IO_NONALERT); - if (NT_SUCCESS(Status)) + /* Search for first usable disk and partition */ + if (IsListEmpty (&List->DiskListHead)) { - LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192); - - Status = NtDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_DISK_GET_DRIVE_LAYOUT, - NULL, - 0, - LayoutBuffer, - 8192); - if (!NT_SUCCESS(Status)) - { - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); - DestroyPartitionList(List); - return FALSE; - } - - - LayoutBuffer->PartitionEntry[PartEntryNumber].BootIndicator = TRUE; - - Status = NtDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_DISK_SET_DRIVE_LAYOUT, - LayoutBuffer, - 8192, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); - DestroyPartitionList(List); - return FALSE; - } + List->CurrentDisk = NULL; + List->CurrentPartition = NULL; } else { - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); - DestroyPartitionList(List); - return FALSE; - } - - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); + List->CurrentDisk = + CONTAINING_RECORD (List->DiskListHead.Flink, + DISKENTRY, + ListEntry); - PartEntry->Active = TRUE; - if (!GetActiveBootPartition(List, ActivePartition)) - { - DestroyPartitionList(List); - DPRINT("GetActiveBootPartition() failed\n"); - return FALSE; - } - - DestroyPartitionList(List); + if (IsListEmpty (&List->CurrentDisk->PartListHead)) + { + List->CurrentPartition = 0; + } + else + { + List->CurrentPartition = + CONTAINING_RECORD (List->CurrentDisk->PartListHead.Flink, + PARTENTRY, + ListEntry); + } + } - return TRUE; + return List; } VOID -DestroyPartitionList(PPARTLIST List) +DestroyPartitionList (PPARTLIST List) { - ULONG i; -#if 0 - COORD coPos; - USHORT Width; - - /* clear occupied screen area */ - coPos.X = List->Left; - Width = List->Right - List->Left + 1; - for (coPos.Y = List->Top; coPos.Y <= List->Bottom; coPos.Y++) - { - FillConsoleOutputAttribute(0x17, - Width, - coPos, - &i); - - FillConsoleOutputCharacter(' ', - Width, - coPos, - &i); - } -#endif + PDISKENTRY DiskEntry; + PPARTENTRY PartEntry; + PLIST_ENTRY Entry; /* Release disk and partition info */ - if (List->DiskArray != NULL) + while (!IsListEmpty (&List->DiskListHead)) { - for (i = 0; i < List->DiskCount; i++) + Entry = RemoveHeadList (&List->DiskListHead); + DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry); + + /* Release driver name */ + RtlFreeUnicodeString(&DiskEntry->DriverName); + + /* Release partition array */ + while (!IsListEmpty (&DiskEntry->PartListHead)) { - /* Release driver name */ - RtlFreeUnicodeString(&List->DiskArray[i].DriverName); + Entry = RemoveHeadList (&DiskEntry->PartListHead); + PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry); - /* Release partition array */ - if (List->DiskArray[i].PartArray != NULL) - { - RtlFreeHeap(ProcessHeap, 0, List->DiskArray[i].PartArray); - List->DiskArray[i].PartCount = 0; - List->DiskArray[i].PartArray = NULL; - } + RtlFreeHeap (ProcessHeap, + 0, + PartEntry); } - /* Release disk array */ - RtlFreeHeap(ProcessHeap, 0, List->DiskArray); - List->DiskCount = 0; - List->DiskArray = NULL; + /* Release disk entry */ + RtlFreeHeap (ProcessHeap, 0, DiskEntry); } /* Release list head */ - RtlFreeHeap(ProcessHeap, 0, List); + RtlFreeHeap (ProcessHeap, 0, List); } static VOID -PrintEmptyLine(PPARTLIST List) +PrintEmptyLine (PPARTLIST List) { COORD coPos; ULONG Written; @@ -619,26 +725,25 @@ PrintEmptyLine(PPARTLIST List) coPos.X = List->Left + 1; coPos.Y = List->Top + 1 + List->Line; - FillConsoleOutputAttribute(0x17, - Width, - coPos, - &Written); + FillConsoleOutputAttribute (0x17, + Width, + coPos, + &Written); - FillConsoleOutputCharacter(' ', - Width, - coPos, - &Written); + FillConsoleOutputCharacter (' ', + Width, + coPos, + &Written); List->Line++; } static VOID -PrintPartitionData(PPARTLIST List, - SHORT DiskIndex, - SHORT PartIndex) +PrintPartitionData (PPARTLIST List, + PDISKENTRY DiskEntry, + PPARTENTRY PartEntry) { - PPARTENTRY PartEntry; CHAR LineBuffer[128]; COORD coPos; ULONG Written; @@ -659,133 +764,132 @@ PrintPartitionData(PPARTLIST List, coPos.X = List->Left + 1; coPos.Y = List->Top + 1 + List->Line; - PartEntry = &List->DiskArray[DiskIndex].PartArray[PartIndex]; - - /* Determine partition type */ - PartType = NULL; - if (PartEntry->Unpartitioned == FALSE) + if (PartEntry->Unpartitioned == TRUE) { - if ((PartEntry->PartType == PARTITION_FAT_12) || - (PartEntry->PartType == PARTITION_FAT_16) || - (PartEntry->PartType == PARTITION_HUGE) || - (PartEntry->PartType == PARTITION_XINT13)) +#if 0 + if (PartEntry->UnpartitionledLength >= 0x280000000ULL) /* 10 GB */ { - PartType = "FAT"; + PartSize = (PartEntry->UnpartitionedLength + (1 << 29)) >> 30; + Unit = "GB"; } - else if ((PartEntry->PartType == PARTITION_FAT32) || - (PartEntry->PartType == PARTITION_FAT32_XINT13)) + else +#endif + if (PartEntry->UnpartitionedLength >= 0xA00000ULL) /* 10 MB */ { - PartType = "FAT32"; + PartSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20; + Unit = "MB"; } - else if (PartEntry->PartType == PARTITION_IFS) + else { - PartType = "NTFS"; /* FIXME: Not quite correct! */ + PartSize = (PartEntry->UnpartitionedLength + (1 << 9)) >> 10; + Unit = "KB"; } - } - -#if 0 - if (PartEntry->PartSize >= 0x280000000ULL) /* 10 GB */ - { - PartSize = (PartEntry->PartSize + (1 << 29)) >> 30; - Unit = "GB"; - } - else -#endif - if (PartEntry->PartSize >= 0xA00000ULL) /* 10 MB */ - { - PartSize = (PartEntry->PartSize + (1 << 19)) >> 20; - Unit = "MB"; + sprintf (LineBuffer, + " Unpartitioned space %6I64u %s", + PartSize, + Unit); } else { - PartSize = (PartEntry->PartSize + (1 << 9)) >> 10; - Unit = "KB"; - } + /* Determine partition type */ + PartType = NULL; + if (PartEntry->New == TRUE) + { + PartType = "New (Unformatted)"; + } + else if (PartEntry->Unpartitioned == FALSE) + { + if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13)) + { + PartType = "FAT"; + } + else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) || + (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13)) + { + PartType = "FAT32"; + } + else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS) + { + PartType = "NTFS"; /* FIXME: Not quite correct! */ + } + } +#if 0 + if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0x280000000ULL) /* 10 GB */ + { + PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 29)) >> 30; + Unit = "GB"; + } + else +#endif + if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0xA00000ULL) /* 10 MB */ + { + PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 19)) >> 20; + Unit = "MB"; + } + else + { + PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 9)) >> 10; + Unit = "KB"; + } - if (PartEntry->Unpartitioned == TRUE) - { - sprintf(LineBuffer, - " Unpartitioned space %I64u %s", - PartSize, - Unit); - } - else if (PartEntry->DriveLetter != (CHAR)0) - { if (PartType == NULL) { - sprintf(LineBuffer, - "%c: Type %-3lu %I64u %s", - PartEntry->DriveLetter, - PartEntry->PartType, - PartSize, - Unit); + sprintf (LineBuffer, + "%c%c Type %-3lu %6I64u %s", + (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter, + (PartEntry->DriveLetter == 0) ? '-' : ':', + PartEntry->PartInfo[0].PartitionType, + PartSize, + Unit); } else { - sprintf(LineBuffer, - "%c: %s %I64u %s", - PartEntry->DriveLetter, - PartType, - PartSize, - Unit); + sprintf (LineBuffer, + "%c%c %-24s %6I64u %s", + (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter, + (PartEntry->DriveLetter == 0) ? '-' : ':', + PartType, + PartSize, + Unit); } - -#if 0 - sprintf(LineBuffer, - "%c: %s (%d: nr: %d type: %x) %I64u %s", - PartEntry->DriveLetter, - PartType, - PartIndex, - PartEntry->PartNumber, - PartEntry->PartType, - PartSize, - Unit); -#endif - } - else - { - sprintf(LineBuffer, - "-- %s (%d: nr: %d type: %x) %I64u %s", - PartEntry->FileSystemName, - PartIndex, - PartEntry->PartNumber, - PartEntry->PartType, - PartSize, - Unit); } - Attribute = (List->CurrentDisk == DiskIndex && - List->CurrentPartition == PartIndex) ? 0x71 : 0x17; + Attribute = (List->CurrentDisk == DiskEntry && + List->CurrentPartition == PartEntry) ? 0x71 : 0x17; - FillConsoleOutputCharacter(' ', - Width, - coPos, - &Written); + FillConsoleOutputCharacter (' ', + Width, + coPos, + &Written); coPos.X += 4; Width -= 8; - FillConsoleOutputAttribute(Attribute, - Width, - coPos, - &Written); + FillConsoleOutputAttribute (Attribute, + Width, + coPos, + &Written); coPos.X++; Width -= 2; - WriteConsoleOutputCharacters(LineBuffer, - min(strlen(LineBuffer), Width), - coPos); + WriteConsoleOutputCharacters (LineBuffer, + min (strlen (LineBuffer), Width), + coPos); List->Line++; } static VOID -PrintDiskData(PPARTLIST List, - SHORT DiskIndex) +PrintDiskData (PPARTLIST List, + PDISKENTRY DiskEntry) { - PDISKENTRY DiskEntry; + PPARTENTRY PartEntry; + PLIST_ENTRY Entry; CHAR LineBuffer[128]; COORD coPos; ULONG Written; @@ -795,8 +899,6 @@ PrintDiskData(PPARTLIST List, PCHAR Unit; SHORT PartIndex; - DiskEntry = &List->DiskArray[DiskIndex]; - Width = List->Right - List->Left - 1; Height = List->Bottom - List->Top - 1; @@ -823,571 +925,1027 @@ PrintDiskData(PPARTLIST List, if (DiskEntry->DriverName.Length > 0) { - sprintf(LineBuffer, - "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ", - DiskSize, - Unit, - DiskEntry->DiskNumber, - DiskEntry->Port, - DiskEntry->Bus, - DiskEntry->Id, - &DiskEntry->DriverName); + sprintf (LineBuffer, + "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ", + DiskSize, + Unit, + DiskEntry->DiskNumber, + DiskEntry->Port, + DiskEntry->Bus, + DiskEntry->Id, + &DiskEntry->DriverName); } else { - sprintf(LineBuffer, - "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)", - DiskSize, - Unit, - DiskEntry->DiskNumber, - DiskEntry->Port, - DiskEntry->Bus, - DiskEntry->Id); + sprintf (LineBuffer, + "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)", + DiskSize, + Unit, + DiskEntry->DiskNumber, + DiskEntry->Port, + DiskEntry->Bus, + DiskEntry->Id); } - FillConsoleOutputAttribute(0x17, - Width, - coPos, - &Written); + FillConsoleOutputAttribute (0x17, + Width, + coPos, + &Written); - FillConsoleOutputCharacter(' ', - Width, - coPos, - &Written); + FillConsoleOutputCharacter (' ', + Width, + coPos, + &Written); coPos.X++; - WriteConsoleOutputCharacters(LineBuffer, - min(strlen(LineBuffer), Width - 2), - coPos); + WriteConsoleOutputCharacters (LineBuffer, + min (strlen (LineBuffer), Width - 2), + coPos); + + List->Line++; + + /* Print separator line */ + PrintEmptyLine (List); + + /* Print partition lines*/ + Entry = DiskEntry->PartListHead.Flink; + while (Entry != &DiskEntry->PartListHead) + { + PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry); + + /* Print disk entry */ + PrintPartitionData (List, + DiskEntry, + PartEntry); + + Entry = Entry->Flink; + } + + /* Print separator line */ + PrintEmptyLine (List); +} + + +VOID +DrawPartitionList (PPARTLIST List) +{ + PLIST_ENTRY Entry; + PDISKENTRY DiskEntry; + CHAR LineBuffer[128]; + COORD coPos; + ULONG Written; + SHORT i; + SHORT DiskIndex; + + /* draw upper left corner */ + coPos.X = List->Left; + coPos.Y = List->Top; + FillConsoleOutputCharacter (0xDA, // '+', + 1, + coPos, + &Written); + + /* draw upper edge */ + coPos.X = List->Left + 1; + coPos.Y = List->Top; + FillConsoleOutputCharacter (0xC4, // '-', + List->Right - List->Left - 1, + coPos, + &Written); + + /* draw upper right corner */ + coPos.X = List->Right; + coPos.Y = List->Top; + FillConsoleOutputCharacter (0xBF, // '+', + 1, + coPos, + &Written); + + /* draw left and right edge */ + for (i = List->Top + 1; i < List->Bottom; i++) + { + coPos.X = List->Left; + coPos.Y = i; + FillConsoleOutputCharacter (0xB3, // '|', + 1, + coPos, + &Written); + + coPos.X = List->Right; + FillConsoleOutputCharacter (0xB3, //'|', + 1, + coPos, + &Written); + } + + /* draw lower left corner */ + coPos.X = List->Left; + coPos.Y = List->Bottom; + FillConsoleOutputCharacter (0xC0, // '+', + 1, + coPos, + &Written); + + /* draw lower edge */ + coPos.X = List->Left + 1; + coPos.Y = List->Bottom; + FillConsoleOutputCharacter (0xC4, // '-', + List->Right - List->Left - 1, + coPos, + &Written); + + /* draw lower right corner */ + coPos.X = List->Right; + coPos.Y = List->Bottom; + FillConsoleOutputCharacter (0xD9, // '+', + 1, + coPos, + &Written); + + /* print list entries */ + List->Line = 0; + + Entry = List->DiskListHead.Flink; + while (Entry != &List->DiskListHead) + { + DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry); + + /* Print disk entry */ + PrintDiskData (List, + DiskEntry); + + Entry = Entry->Flink; + } +} + + +VOID +ScrollDownPartitionList (PPARTLIST List) +{ + PDISKENTRY DiskEntry; + PPARTENTRY PartEntry; + PLIST_ENTRY Entry1; + PLIST_ENTRY Entry2; + + /* Check for empty disks */ + if (IsListEmpty (&List->DiskListHead)) + return; + + /* Check for next usable entry on current disk */ + if (List->CurrentPartition != NULL) + { + Entry2 = List->CurrentPartition->ListEntry.Flink; + while (Entry2 != &List->CurrentDisk->PartListHead) + { + PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry); + +// if (PartEntry->HidePartEntry == FALSE) + { + List->CurrentPartition = PartEntry; + DrawPartitionList (List); + return; + } + Entry2 = Entry2->Flink; + } + } + + /* Check for first usable entry on next disk */ + if (List->CurrentDisk != NULL) + { + Entry1 = List->CurrentDisk->ListEntry.Flink; + while (Entry1 != &List->DiskListHead) + { + DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry); + + Entry2 = DiskEntry->PartListHead.Flink; + while (Entry2 != &DiskEntry->PartListHead) + { + PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry); + +// if (PartEntry->HidePartEntry == FALSE) + { + List->CurrentDisk = DiskEntry; + List->CurrentPartition = PartEntry; + DrawPartitionList (List); + return; + } + + Entry2 = Entry2->Flink; + } + + Entry1 = Entry1->Flink; + } + } +} + + +VOID +ScrollUpPartitionList (PPARTLIST List) +{ + PDISKENTRY DiskEntry; + PPARTENTRY PartEntry; + PLIST_ENTRY Entry1; + PLIST_ENTRY Entry2; + ULONG i; + + /* Check for empty disks */ + if (IsListEmpty (&List->DiskListHead)) + return; + + /* check for previous usable entry on current disk */ + if (List->CurrentPartition != NULL) + { + Entry2 = List->CurrentPartition->ListEntry.Blink; + while (Entry2 != &List->CurrentDisk->PartListHead) + { + PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry); + +// if (PartEntry->HidePartEntry == FALSE) + { + List->CurrentPartition = PartEntry; + DrawPartitionList (List); + return; + } + Entry2 = Entry2->Blink; + } + } + + + /* check for last usable entry on previous disk */ + if (List->CurrentDisk != NULL) + { + Entry1 = List->CurrentDisk->ListEntry.Blink; + while (Entry1 != &List->DiskListHead) + { + DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry); + + Entry2 = DiskEntry->PartListHead.Blink; + while (Entry2 != &DiskEntry->PartListHead) + { + PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry); + +// if (PartEntry->HidePartEntry == FALSE) + { + List->CurrentDisk = DiskEntry; + List->CurrentPartition = PartEntry; + DrawPartitionList (List); + return; + } + + Entry2 = Entry2->Blink; + } + + Entry1 = Entry1->Blink; + } + } +} - List->Line++; - /* Print separator line */ - PrintEmptyLine(List); +static PPARTENTRY +GetPrevPartitionedEntry (PDISKENTRY DiskEntry, + PPARTENTRY CurrentEntry) +{ + PPARTENTRY PrevEntry; + PLIST_ENTRY Entry; + if (CurrentEntry->ListEntry.Blink == &DiskEntry->PartListHead) + return NULL; - /* Print partition lines*/ - for (PartIndex = 0; PartIndex < DiskEntry->PartCount; PartIndex++) + Entry = CurrentEntry->ListEntry.Blink; + while (Entry != &DiskEntry->PartListHead) { - if (!DiskEntry->PartArray[PartIndex].HidePartEntry) - { - PrintPartitionData(List, - DiskIndex, - PartIndex); - } + PrevEntry = CONTAINING_RECORD (Entry, + PARTENTRY, + ListEntry); + if (PrevEntry->Unpartitioned == FALSE) + return PrevEntry; + + Entry = Entry->Blink; } - /* Print separator line */ - PrintEmptyLine(List); + return NULL; } -VOID -DrawPartitionList(PPARTLIST List) +static PPARTENTRY +GetNextPartitionedEntry (PDISKENTRY DiskEntry, + PPARTENTRY CurrentEntry) { - CHAR LineBuffer[128]; - COORD coPos; - ULONG Written; - SHORT i; - SHORT DiskIndex; - - /* draw upper left corner */ - coPos.X = List->Left; - coPos.Y = List->Top; - FillConsoleOutputCharacter(0xDA, // '+', - 1, - coPos, - &Written); - - /* draw upper edge */ - coPos.X = List->Left + 1; - coPos.Y = List->Top; - FillConsoleOutputCharacter(0xC4, // '-', - List->Right - List->Left - 1, - coPos, - &Written); + PPARTENTRY NextEntry; + PLIST_ENTRY Entry; - /* draw upper right corner */ - coPos.X = List->Right; - coPos.Y = List->Top; - FillConsoleOutputCharacter(0xBF, // '+', - 1, - coPos, - &Written); + if (CurrentEntry->ListEntry.Flink == &DiskEntry->PartListHead) + return NULL; - /* draw left and right edge */ - for (i = List->Top + 1; i < List->Bottom; i++) + Entry = CurrentEntry->ListEntry.Flink; + while (Entry != &DiskEntry->PartListHead) { - coPos.X = List->Left; - coPos.Y = i; - FillConsoleOutputCharacter(0xB3, // '|', - 1, - coPos, - &Written); + NextEntry = CONTAINING_RECORD (Entry, + PARTENTRY, + ListEntry); + if (NextEntry->Unpartitioned == FALSE) + return NextEntry; - coPos.X = List->Right; - FillConsoleOutputCharacter(0xB3, //'|', - 1, - coPos, - &Written); + Entry = Entry->Flink; } - /* draw lower left corner */ - coPos.X = List->Left; - coPos.Y = List->Bottom; - FillConsoleOutputCharacter(0xC0, // '+', - 1, - coPos, - &Written); + return NULL; +} - /* draw lower edge */ - coPos.X = List->Left + 1; - coPos.Y = List->Bottom; - FillConsoleOutputCharacter(0xC4, // '-', - List->Right - List->Left - 1, - coPos, - &Written); - /* draw lower right corner */ - coPos.X = List->Right; - coPos.Y = List->Bottom; - FillConsoleOutputCharacter(0xD9, // '+', - 1, - coPos, - &Written); +static PPARTENTRY +GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry, + PPARTENTRY PartEntry) +{ + PPARTENTRY PrevPartEntry; - /* print list entries */ - List->Line = 0; - for (DiskIndex = 0; DiskIndex < List->DiskCount; DiskIndex++) + if (PartEntry->ListEntry.Blink != &DiskEntry->PartListHead) { - if (List->DiskArray[DiskIndex].FixedDisk == TRUE) - { - /* Print disk entry */ - PrintDiskData(List, - DiskIndex); - } + PrevPartEntry = CONTAINING_RECORD (PartEntry->ListEntry.Blink, + PARTENTRY, + ListEntry); + if (PrevPartEntry->Unpartitioned == TRUE) + return PrevPartEntry; } + + return NULL; } -VOID -ScrollDownPartitionList(PPARTLIST List) +static PPARTENTRY +GetNextUnpartitionedEntry (PDISKENTRY DiskEntry, + PPARTENTRY PartEntry) { - ULONG i; - ULONG j; + PPARTENTRY NextPartEntry; - /* check for available disks */ - if (List->DiskCount == 0) - return; - - /* check for next usable entry on current disk */ - for (i = List->CurrentPartition + 1; i < List->DiskArray[List->CurrentDisk].PartCount; i++) + if (PartEntry->ListEntry.Flink != &DiskEntry->PartListHead) { - if (!List->DiskArray[List->CurrentDisk].PartArray[i].HidePartEntry) - { - List->CurrentPartition = i; - DrawPartitionList(List); - return; - } + NextPartEntry = CONTAINING_RECORD (PartEntry->ListEntry.Flink, + PARTENTRY, + ListEntry); + if (NextPartEntry->Unpartitioned == TRUE) + return NextPartEntry; } - /* check for first usable entry on next disk */ - for (j = List->CurrentDisk + 1; j < List->DiskCount; j++) - { - for (i = 0; i < List->DiskArray[j].PartCount; i++) - { - if (!List->DiskArray[j].PartArray[i].HidePartEntry) - { - List->CurrentDisk = j; - List->CurrentPartition = i; - DrawPartitionList(List); - return; - } - } - } + return NULL; } VOID -ScrollUpPartitionList(PPARTLIST List) +CreateNewPartition (PPARTLIST List, + ULONGLONG PartitionSize, + BOOLEAN AutoCreate) { - ULONG i; - ULONG j; + PDISKENTRY DiskEntry; + PPARTENTRY PartEntry; + PPARTENTRY PrevPartEntry; + PPARTENTRY NextPartEntry; + PPARTENTRY NewPartEntry; + + if (List == NULL || + List->CurrentDisk == NULL || + List->CurrentPartition == NULL || + List->CurrentPartition->Unpartitioned == FALSE) + { + return; + } - /* check for available disks */ - if (List->DiskCount == 0) - return; + DiskEntry = List->CurrentDisk; + PartEntry = List->CurrentPartition; - /* check for previous usable entry on current disk */ - for (i = List->CurrentPartition - 1; i != (ULONG)-1; i--) + if (AutoCreate == TRUE || + PartitionSize == PartEntry->UnpartitionedLength) { - if (!List->DiskArray[List->CurrentDisk].PartArray[i].HidePartEntry) + /* Convert current entry to 'new (unformatted)' */ + PartEntry->FormatState = Unformatted; + PartEntry->PartInfo[0].StartingOffset.QuadPart = + PartEntry->UnpartitionedOffset + DiskEntry->TrackSize; + PartEntry->PartInfo[0].PartitionLength.QuadPart = + PartEntry->UnpartitionedLength - DiskEntry->TrackSize; + PartEntry->PartInfo[0].PartitionType = PARTITION_ENTRY_UNUSED; + PartEntry->PartInfo[0].BootIndicator = FALSE; /* FIXME */ + PartEntry->PartInfo[0].RewritePartition = TRUE; + PartEntry->PartInfo[1].RewritePartition = TRUE; + PartEntry->PartInfo[2].RewritePartition = TRUE; + PartEntry->PartInfo[3].RewritePartition = TRUE; + + /* Get previous and next partition entries */ + PrevPartEntry = GetPrevPartitionedEntry (DiskEntry, + PartEntry); + NextPartEntry = GetNextPartitionedEntry (DiskEntry, + PartEntry); + + if (PrevPartEntry != NULL && NextPartEntry != NULL) + { + /* Current entry is in the middle of the list */ + + /* Copy previous container partition data to current entry */ + RtlCopyMemory (&PartEntry->PartInfo[1], + &PrevPartEntry->PartInfo[1], + sizeof(PARTITION_INFORMATION)); + PartEntry->PartInfo[1].RewritePartition = TRUE; + + /* Update previous container partition data */ + + PrevPartEntry->PartInfo[1].StartingOffset.QuadPart = + PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize; + + if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry) + { + /* Special case - previous partition is first partition */ + PrevPartEntry->PartInfo[1].PartitionLength.QuadPart = + DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart; + } + else + { + PrevPartEntry->PartInfo[1].PartitionLength.QuadPart = + PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize; + } + + PrevPartEntry->PartInfo[1].RewritePartition = TRUE; + } + else if (PrevPartEntry == NULL && NextPartEntry != NULL) { - List->CurrentPartition = i; - DrawPartitionList(List); + /* Current entry is the first entry */ return; } - } + else if (PrevPartEntry != NULL && NextPartEntry == NULL) + { + /* Current entry is the last entry */ - /* check for last usable entry on previous disk */ - for (j = List->CurrentDisk - 1; j != (ULONG)-1; j--) + PrevPartEntry->PartInfo[1].StartingOffset.QuadPart = + PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize; + + if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry) + { + /* Special case - previous partition is first partition */ + PrevPartEntry->PartInfo[1].PartitionLength.QuadPart = + DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart; + } + else + { + PrevPartEntry->PartInfo[1].PartitionLength.QuadPart = + PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize; + } + + if ((PartEntry->PartInfo[1].StartingOffset.QuadPart + + PartEntry->PartInfo[1].PartitionLength.QuadPart) < + (1024ULL * 255ULL * 63ULL * 512ULL)) + { + PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED; + } + else + { + PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED; + } + + PrevPartEntry->PartInfo[1].BootIndicator = FALSE; + PrevPartEntry->PartInfo[1].RewritePartition = TRUE; + } + + PartEntry->AutoCreate = AutoCreate; + PartEntry->New = TRUE; + PartEntry->Unpartitioned = FALSE; + PartEntry->UnpartitionedOffset = 0ULL; + PartEntry->UnpartitionedLength = 0ULL; + } + else { - for (i = List->DiskArray[j].PartCount - 1; i != (ULONG)-1; i--) + /* Insert an initialize a new partition entry */ + NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap, + 0, + sizeof(PARTENTRY)); + if (NewPartEntry == NULL) + return; + + RtlZeroMemory (NewPartEntry, + sizeof(PARTENTRY)); + + /* Insert the new entry into the list */ + InsertTailList (&PartEntry->ListEntry, + &NewPartEntry->ListEntry); + + NewPartEntry->New = TRUE; + + NewPartEntry->FormatState = Unformatted; + NewPartEntry->PartInfo[0].StartingOffset.QuadPart = + PartEntry->UnpartitionedOffset + DiskEntry->TrackSize; + NewPartEntry->PartInfo[0].PartitionLength.QuadPart = + PartitionSize - DiskEntry->TrackSize; + NewPartEntry->PartInfo[0].PartitionType = PARTITION_ENTRY_UNUSED; + NewPartEntry->PartInfo[0].BootIndicator = FALSE; /* FIXME */ + NewPartEntry->PartInfo[0].RewritePartition = TRUE; + NewPartEntry->PartInfo[1].RewritePartition = TRUE; + NewPartEntry->PartInfo[2].RewritePartition = TRUE; + NewPartEntry->PartInfo[3].RewritePartition = TRUE; + + /* Get previous and next partition entries */ + PrevPartEntry = GetPrevPartitionedEntry (DiskEntry, + NewPartEntry); + NextPartEntry = GetNextPartitionedEntry (DiskEntry, + NewPartEntry); + + if (PrevPartEntry != NULL && NextPartEntry != NULL) { - if (!List->DiskArray[j].PartArray[i].HidePartEntry) + /* Current entry is in the middle of the list */ + + /* Copy previous container partition data to current entry */ + RtlCopyMemory (&NewPartEntry->PartInfo[1], + &PrevPartEntry->PartInfo[1], + sizeof(PARTITION_INFORMATION)); + NewPartEntry->PartInfo[1].RewritePartition = TRUE; + + /* Update previous container partition data */ + + PrevPartEntry->PartInfo[1].StartingOffset.QuadPart = + NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize; + + if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry) { - List->CurrentDisk = j; - List->CurrentPartition = i; - DrawPartitionList(List); - return; + /* Special case - previous partition is first partition */ + PrevPartEntry->PartInfo[1].PartitionLength.QuadPart = + DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart; + } + else + { + PrevPartEntry->PartInfo[1].PartitionLength.QuadPart = + NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize; + } + + PrevPartEntry->PartInfo[1].RewritePartition = TRUE; + } + else if (PrevPartEntry == NULL && NextPartEntry != NULL) + { + /* Current entry is the first entry */ + return; + } + else if (PrevPartEntry != NULL && NextPartEntry == NULL) + { + /* Current entry is the last entry */ + + PrevPartEntry->PartInfo[1].StartingOffset.QuadPart = + NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize; + + if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry) + { + /* Special case - previous partition is first partition */ + PrevPartEntry->PartInfo[1].PartitionLength.QuadPart = + DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart; + } + else + { + PrevPartEntry->PartInfo[1].PartitionLength.QuadPart = + NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize; + } + + if ((PartEntry->PartInfo[1].StartingOffset.QuadPart + + PartEntry->PartInfo[1].PartitionLength.QuadPart) < + (1024ULL * 255ULL * 63ULL * 512ULL)) + { + PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED; } + else + { + PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED; + } + + PrevPartEntry->PartInfo[1].BootIndicator = FALSE; + PrevPartEntry->PartInfo[1].RewritePartition = TRUE; } + + /* Update offset and size of the remaining unpartitioned disk space */ + PartEntry->UnpartitionedOffset += PartitionSize; + PartEntry->UnpartitionedLength -= PartitionSize; } + + DiskEntry->Modified = TRUE; + + UpdatePartitionNumbers (DiskEntry); + + AssignDriverLetters (List); } -BOOL -GetSelectedPartition(PPARTLIST List, - PPARTDATA Data) +VOID +DeleteCurrentPartition (PPARTLIST List) { PDISKENTRY DiskEntry; PPARTENTRY PartEntry; + PPARTENTRY PrevPartEntry; + PPARTENTRY NextPartEntry; + + if (List == NULL || + List->CurrentDisk == NULL || + List->CurrentPartition == NULL || + List->CurrentPartition->Unpartitioned == TRUE) + { + return; + } - if (List->CurrentDisk >= List->DiskCount) - return(FALSE); + DiskEntry = List->CurrentDisk; + PartEntry = List->CurrentPartition; + + /* Adjust container partition entries */ + + /* Get previous and next partition entries */ + PrevPartEntry = GetPrevPartitionedEntry (DiskEntry, + PartEntry); + NextPartEntry = GetNextPartitionedEntry (DiskEntry, + PartEntry); + + if (PrevPartEntry != NULL && NextPartEntry != NULL) + { + /* Current entry is in the middle of the list */ + + /* + * The first extended partition can not be deleted + * as long as other extended partitions are present. + */ + if (PrevPartEntry->ListEntry.Blink == &DiskEntry->PartListHead) + return; + + /* Copy previous container partition data to current entry */ + RtlCopyMemory (&PrevPartEntry->PartInfo[1], + &PartEntry->PartInfo[1], + sizeof(PARTITION_INFORMATION)); + PrevPartEntry->PartInfo[1].RewritePartition = TRUE; + } + else if (PrevPartEntry == NULL && NextPartEntry != NULL) + { + /* + * A primary partition can not be deleted as long as + * extended partitions are present. + */ + return; + } + else if (PrevPartEntry != NULL && NextPartEntry == NULL) + { + /* Current entry is the last entry */ + RtlZeroMemory (&PrevPartEntry->PartInfo[1], + sizeof(PARTITION_INFORMATION)); + PrevPartEntry->PartInfo[1].RewritePartition = TRUE; + } - DiskEntry = &List->DiskArray[List->CurrentDisk]; - if (DiskEntry->FixedDisk == FALSE) - return(FALSE); + /* Adjust unpartitioned disk space entries */ - if (List->CurrentPartition >= DiskEntry->PartCount) - return(FALSE); + /* Get pointer to previous and next unpartitioned entries */ + PrevPartEntry = GetPrevUnpartitionedEntry (DiskEntry, + PartEntry); - PartEntry = &DiskEntry->PartArray[List->CurrentPartition]; + NextPartEntry = GetNextUnpartitionedEntry (DiskEntry, + PartEntry); - if (PartEntry->Used == FALSE) + if (PrevPartEntry != NULL && NextPartEntry != NULL) { - return(FALSE); + /* Merge previous, current and next unpartitioned entry */ + + /* Adjust the previous entries length */ + PrevPartEntry->UnpartitionedLength += + (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize + + NextPartEntry->UnpartitionedLength); + + /* Remove the current entry */ + RemoveEntryList (&PartEntry->ListEntry); + RtlFreeHeap (ProcessHeap, + 0, + PartEntry); + + /* Remove the next entry */ + RemoveEntryList (&NextPartEntry->ListEntry); + RtlFreeHeap (ProcessHeap, + 0, + NextPartEntry); + + /* Update current partition */ + List->CurrentPartition = PrevPartEntry; } + else if (PrevPartEntry != NULL && NextPartEntry == NULL) + { + /* Merge current and previous unpartitioned entry */ + + /* Adjust the previous entries length */ + PrevPartEntry->UnpartitionedLength += + (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize); + + /* Remove the current entry */ + RemoveEntryList (&PartEntry->ListEntry); + RtlFreeHeap (ProcessHeap, + 0, + PartEntry); - /* Copy disk-specific data */ - Data->DiskSize = DiskEntry->DiskSize; - Data->DiskNumber = DiskEntry->DiskNumber; - Data->Port = DiskEntry->Port; - Data->Bus = DiskEntry->Bus; - Data->Id = DiskEntry->Id; - - /* Copy driver name */ - RtlInitUnicodeString(&Data->DriverName, - NULL); - if (DiskEntry->DriverName.Length != 0) + /* Update current partition */ + List->CurrentPartition = PrevPartEntry; + } + else if (PrevPartEntry == NULL && NextPartEntry != NULL) { - Data->DriverName.Buffer = RtlAllocateHeap(ProcessHeap, - 0, - DiskEntry->DriverName.MaximumLength); - if (Data->DriverName.Buffer != NULL) - { - Data->DriverName.MaximumLength = DiskEntry->DriverName.MaximumLength; - Data->DriverName.Length = DiskEntry->DriverName.Length; - RtlCopyMemory(Data->DriverName.Buffer, - DiskEntry->DriverName.Buffer, - DiskEntry->DriverName.MaximumLength); - } + /* Merge current and next unpartitioned entry */ + + /* Adjust the next entries offset and length */ + NextPartEntry->UnpartitionedOffset = + PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize; + NextPartEntry->UnpartitionedLength += + (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize); + + /* Remove the current entry */ + RemoveEntryList (&PartEntry->ListEntry); + RtlFreeHeap (ProcessHeap, + 0, + PartEntry); + + /* Update current partition */ + List->CurrentPartition = NextPartEntry; + } + else + { + /* Nothing to merge but change current entry */ + PartEntry->New = FALSE; + PartEntry->Unpartitioned = TRUE; + PartEntry->UnpartitionedOffset = + PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize; + PartEntry->UnpartitionedLength = + PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize; + + /* Wipe the partition table */ + RtlZeroMemory (&PartEntry->PartInfo, + sizeof(PartEntry->PartInfo)); } - /* Copy partition-specific data */ - Data->CreatePartition = FALSE; - Data->NewPartSize = 0; - Data->PartSize = PartEntry->PartSize; - Data->PartNumber = PartEntry->PartNumber; - Data->PartType = PartEntry->PartType; - Data->DriveLetter = PartEntry->DriveLetter; - return(TRUE); + DiskEntry->Modified = TRUE; + + UpdatePartitionNumbers (DiskEntry); + + AssignDriverLetters (List); } -BOOL -GetActiveBootPartition(PPARTLIST List, - PPARTDATA Data) +VOID +CheckActiveBootPartition (PPARTLIST List) { PDISKENTRY DiskEntry; PPARTENTRY PartEntry; - ULONG i; - if (List->CurrentDisk >= List->DiskCount) - return(FALSE); + /* Check for empty disk list */ + if (IsListEmpty (&List->DiskListHead)) + { + List->ActiveBootDisk = NULL; + List->ActiveBootPartition = NULL; + return; + } - DiskEntry = &List->DiskArray[List->CurrentDisk]; +#if 0 + if (List->ActiveBootDisk != NULL && + List->ActiveBootPartition != NULL) + { + /* We already have an active boot partition */ + return; + } +#endif - if (DiskEntry->FixedDisk == FALSE) - { - return(FALSE); - } + DiskEntry = CONTAINING_RECORD (List->DiskListHead.Flink, + DISKENTRY, + ListEntry); - for (i = 0; i < DiskEntry->PartCount; i++) + /* Check for empty partition list */ + if (IsListEmpty (&DiskEntry->PartListHead)) { - if (DiskEntry->PartArray[i].Active) - { - PartEntry = &DiskEntry->PartArray[i]; - - if (PartEntry->Used == FALSE) - { - return(FALSE); - } - - /* Copy disk-specific data */ - Data->DiskSize = DiskEntry->DiskSize; - Data->DiskNumber = DiskEntry->DiskNumber; - Data->Port = DiskEntry->Port; - Data->Bus = DiskEntry->Bus; - Data->Id = DiskEntry->Id; - - /* Copy driver name */ - RtlInitUnicodeString(&Data->DriverName, - NULL); - if (DiskEntry->DriverName.Length != 0) - { - Data->DriverName.Buffer = RtlAllocateHeap(ProcessHeap, - 0, - DiskEntry->DriverName.MaximumLength); - if (Data->DriverName.Buffer != NULL) - { - Data->DriverName.MaximumLength = DiskEntry->DriverName.MaximumLength; - Data->DriverName.Length = DiskEntry->DriverName.Length; - RtlCopyMemory(Data->DriverName.Buffer, - DiskEntry->DriverName.Buffer, - DiskEntry->DriverName.MaximumLength); - } - } + List->ActiveBootDisk = NULL; + List->ActiveBootPartition = NULL; + return; + } - /* Copy partition-specific data */ - Data->PartSize = PartEntry->PartSize; - Data->PartNumber = PartEntry->PartNumber; - Data->PartType = PartEntry->PartType; - Data->DriveLetter = PartEntry->DriveLetter; + PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink, + PARTENTRY, + ListEntry); - return(TRUE); - } + /* Set active boot partition */ + if ((DiskEntry->NewDisk == TRUE) || + (PartEntry->PartInfo[0].BootIndicator == FALSE && + PartEntry->PartInfo[1].BootIndicator == FALSE && + PartEntry->PartInfo[2].BootIndicator == FALSE && + PartEntry->PartInfo[3].BootIndicator == FALSE)) + { + PartEntry->PartInfo[0].BootIndicator = TRUE; + PartEntry->PartInfo[0].RewritePartition = TRUE; + DiskEntry->Modified = TRUE; } - return(FALSE); + /* FIXME: Might be incorrect if partitions were created by Linux FDISK */ + List->ActiveBootDisk = DiskEntry; + List->ActiveBootPartition = PartEntry; } -BOOL -CreateSelectedPartition(PPARTLIST List, - ULONG PartType, - ULONGLONG NewPartSize) +BOOLEAN +CheckForLinuxFdiskPartitions (PPARTLIST List) { PDISKENTRY DiskEntry; PPARTENTRY PartEntry; - ULONG PartEntryNumber; - OBJECT_ATTRIBUTES ObjectAttributes; - DRIVE_LAYOUT_INFORMATION *LayoutBuffer; - IO_STATUS_BLOCK Iosb; - NTSTATUS Status; - WCHAR Buffer[MAX_PATH]; - UNICODE_STRING Name; - HANDLE FileHandle; - LARGE_INTEGER li; - - DiskEntry = &List->DiskArray[List->CurrentDisk]; - PartEntry = &DiskEntry->PartArray[List->CurrentPartition]; - PartEntry->PartType = PartType; - PartEntryNumber = List->CurrentPartition; - - DPRINT("NewPartSize %d (%d MB)\n", NewPartSize, NewPartSize / (1024 * 1024)); - DPRINT("PartEntry->StartingOffset %d\n", PartEntry->StartingOffset); - DPRINT("PartEntry->PartSize %d\n", PartEntry->PartSize); - DPRINT("PartEntry->PartNumber %d\n", PartEntry->PartNumber); - DPRINT("PartEntry->PartType 0x%x\n", PartEntry->PartType); - DPRINT("PartEntry->FileSystemName %s\n", PartEntry->FileSystemName); - - swprintf(Buffer, - L"\\Device\\Harddisk%d\\Partition0", - DiskEntry->DiskNumber); - RtlInitUnicodeString(&Name, Buffer); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - 0x10001, - &ObjectAttributes, - &Iosb, - 1, - FILE_SYNCHRONOUS_IO_NONALERT); - if (NT_SUCCESS(Status)) + PLIST_ENTRY Entry1; + PLIST_ENTRY Entry2; + ULONG PartitionCount; + ULONG i; + + Entry1 = List->DiskListHead.Flink; + while (Entry1 != &List->DiskListHead) { - LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192); - - Status = NtDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_DISK_GET_DRIVE_LAYOUT, - NULL, - 0, - LayoutBuffer, - 8192); - if (!NT_SUCCESS(Status)) + DiskEntry = CONTAINING_RECORD (Entry1, + DISKENTRY, + ListEntry); + + Entry2 = DiskEntry->PartListHead.Flink; + while (Entry2 != &DiskEntry->PartListHead) + { + PartEntry = CONTAINING_RECORD (Entry2, + PARTENTRY, + ListEntry); + + if (PartEntry->Unpartitioned == FALSE) { - DPRINT("IOCTL_DISK_GET_DRIVE_LAYOUT failed() 0x%.08x\n", Status); - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); - return FALSE; - } - - li.QuadPart = PartEntry->StartingOffset; - LayoutBuffer->PartitionEntry[PartEntryNumber].StartingOffset = li; - li.QuadPart = NewPartSize; - LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionLength = li; - LayoutBuffer->PartitionEntry[PartEntryNumber].HiddenSectors = 0; /* FIXME: ? */ - LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionType = PartType; - LayoutBuffer->PartitionEntry[PartEntryNumber].RecognizedPartition = TRUE; - LayoutBuffer->PartitionEntry[PartEntryNumber].RewritePartition = TRUE; - - Status = NtDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_DISK_SET_DRIVE_LAYOUT, - LayoutBuffer, - 8192, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT("IOCTL_DISK_SET_DRIVE_LAYOUT failed() 0x%.08x\n", Status); - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); - return FALSE; - } - } - else - { - DPRINT("NtOpenFile failed() 0x%.08x\n", Status); - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); - return FALSE; - } + PartitionCount = 0; + + for (i = 0; i < 4; i++) + { + if (!IsContainerPartition (PartEntry->PartInfo[i].PartitionType) && + PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL) + { + PartitionCount++; + } + } - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); + if (PartitionCount > 1) + { + return TRUE; + } + } - return TRUE; + Entry2 = Entry2->Flink; + } + + Entry1 = Entry1->Flink; + } + + return FALSE; } -BOOL -DeleteSelectedPartition(PPARTLIST List) +BOOLEAN +WritePartitionsToDisk (PPARTLIST List) { - PDISKENTRY DiskEntry; - PPARTENTRY PartEntry; - ULONG PartEntryNumber; + PDRIVE_LAYOUT_INFORMATION DriveLayout; OBJECT_ATTRIBUTES ObjectAttributes; - DRIVE_LAYOUT_INFORMATION *LayoutBuffer; IO_STATUS_BLOCK Iosb; - NTSTATUS Status; - WCHAR Buffer[MAX_PATH]; + WCHAR SrcPath[MAX_PATH]; + WCHAR DstPath[MAX_PATH]; UNICODE_STRING Name; HANDLE FileHandle; - LARGE_INTEGER li; - - DiskEntry = &List->DiskArray[List->CurrentDisk]; - PartEntry = &DiskEntry->PartArray[List->CurrentPartition]; - PartEntry->PartType = PARTITION_ENTRY_UNUSED; - PartEntryNumber = List->CurrentPartition; - - DPRINT1("DeleteSelectedPartition(PartEntryNumber = %d)\n", PartEntryNumber); - DPRINT1("PartEntry->StartingOffset %d\n", PartEntry->StartingOffset); - DPRINT1("PartEntry->PartSize %d\n", PartEntry->PartSize); - DPRINT1("PartEntry->PartNumber %d\n", PartEntry->PartNumber); - DPRINT1("PartEntry->PartType 0x%x\n", PartEntry->PartType); - DPRINT1("PartEntry->FileSystemName %s\n", PartEntry->FileSystemName); - - swprintf(Buffer, - L"\\Device\\Harddisk%d\\Partition0", - DiskEntry->DiskNumber); - RtlInitUnicodeString(&Name, Buffer); - - InitializeObjectAttributes(&ObjectAttributes, - &Name, - 0, - NULL, - NULL); - - Status = NtOpenFile(&FileHandle, - 0x10001, - &ObjectAttributes, - &Iosb, - 1, - FILE_SYNCHRONOUS_IO_NONALERT); - if (NT_SUCCESS(Status)) + PDISKENTRY DiskEntry; + PPARTENTRY PartEntry; + PLIST_ENTRY Entry1; + PLIST_ENTRY Entry2; + ULONG PartitionCount; + ULONG DriveLayoutSize; + ULONG Index; + NTSTATUS Status; + + if (List == NULL) { - LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192); - - Status = NtDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_DISK_GET_DRIVE_LAYOUT, - NULL, - 0, - LayoutBuffer, - 8192); - if (!NT_SUCCESS(Status)) - { - DPRINT("IOCTL_DISK_GET_DRIVE_LAYOUT failed() 0x%.08x\n", Status); - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); - return FALSE; - } - - li.QuadPart = 0; - LayoutBuffer->PartitionEntry[PartEntryNumber].StartingOffset = li; - li.QuadPart = 0; - LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionLength = li; - LayoutBuffer->PartitionEntry[PartEntryNumber].HiddenSectors = 0; - LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionType = 0; - LayoutBuffer->PartitionEntry[PartEntryNumber].RecognizedPartition = FALSE; - LayoutBuffer->PartitionEntry[PartEntryNumber].RewritePartition = TRUE; - - Status = NtDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_DISK_SET_DRIVE_LAYOUT, - LayoutBuffer, - 8192, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT("IOCTL_DISK_SET_DRIVE_LAYOUT failed() 0x%.08x\n", Status); - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); - return FALSE; - } + return TRUE; } - else + + Entry1 = List->DiskListHead.Flink; + while (Entry1 != &List->DiskListHead) { - DPRINT("NtOpenFile failed() 0x%.08x\n", Status); - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); - return FALSE; - } + DiskEntry = CONTAINING_RECORD (Entry1, + DISKENTRY, + ListEntry); + + if (DiskEntry->Modified == TRUE) + { + /* Count partitioned entries */ + PartitionCount = 0; + Entry2 = DiskEntry->PartListHead.Flink; + while (Entry2 != &DiskEntry->PartListHead) + { + PartEntry = CONTAINING_RECORD (Entry2, + PARTENTRY, + ListEntry); + if (PartEntry->Unpartitioned == FALSE) + { + PartitionCount += 4; + } + + Entry2 = Entry2->Flink; + } + + if (PartitionCount > 0) + { + DriveLayoutSize = sizeof (DRIVE_LAYOUT_INFORMATION) + + ((PartitionCount - 1) * sizeof (PARTITION_INFORMATION)); + DriveLayout = (PDRIVE_LAYOUT_INFORMATION)RtlAllocateHeap (ProcessHeap, + 0, + DriveLayoutSize); + if (DriveLayout == NULL) + { + DPRINT1 ("RtlAllocateHeap() failed\n"); + return FALSE; + } + + RtlZeroMemory (DriveLayout, + DriveLayoutSize); + + DriveLayout->PartitionCount = PartitionCount; + + Index = 0; + Entry2 = DiskEntry->PartListHead.Flink; + while (Entry2 != &DiskEntry->PartListHead) + { + PartEntry = CONTAINING_RECORD (Entry2, + PARTENTRY, + ListEntry); + if (PartEntry->Unpartitioned == FALSE) + { + RtlCopyMemory (&DriveLayout->PartitionEntry[Index], + &PartEntry->PartInfo[0], + 4 * sizeof (PARTITION_INFORMATION)); + Index += 4; + } + + Entry2 = Entry2->Flink; + } + + swprintf (DstPath, + L"\\Device\\Harddisk%d\\Partition0", + DiskEntry->DiskNumber); + RtlInitUnicodeString (&Name, + DstPath); + InitializeObjectAttributes (&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtOpenFile (&FileHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + &Iosb, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS (Status)) + { + DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status); + return FALSE; + } - NtClose(FileHandle); - RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); + Status = NtDeviceIoControlFile (FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_SET_DRIVE_LAYOUT, + DriveLayout, + DriveLayoutSize, + NULL, + 0); + if (!NT_SUCCESS (Status)) + { + DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status); + NtClose (FileHandle); + return FALSE; + } + + RtlFreeHeap (ProcessHeap, + 0, + DriveLayout); + + NtClose (FileHandle); + + /* Install MBR code if the disk is new */ + if (DiskEntry->NewDisk == TRUE) + { + wcscpy (SrcPath, SourceRootPath.Buffer); + wcscat (SrcPath, L"\\loader\\dosmbr.bin"); + + DPRINT1 ("Install MBR bootcode: %S ==> %S\n", + SrcPath, DstPath); + + /* Install MBR bootcode */ + Status = InstallMbrBootCodeToDisk (SrcPath, + DstPath); + if (!NT_SUCCESS (Status)) + { + DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n", + Status); + return FALSE; + } + + DiskEntry->NewDisk = FALSE; + } + } + } + + Entry1 = Entry1->Flink; + } return TRUE; }