/*
* ReactOS kernel
- * Copyright (C) 2002 ReactOS Team
+ * Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: partlist.c,v 1.8 2003/04/18 14:00:17 chorns Exp $
+/* $Id$
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: subsys/system/usetup/partlist.c
* PURPOSE: Partition list functions
* PROGRAMMER: Eric Kohl
+ * Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * Hartmut Birr
*/
-#include <ddk/ntddk.h>
-#include <ddk/ntddscsi.h>
+#include <usetup.h>
-#include <ntdll/rtl.h>
+#define NDEBUG
+#include <debug.h>
-#include <ntos/minmax.h>
+/* FUNCTIONS ****************************************************************/
+
+static VOID
+GetDriverName (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);
+
+ 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))
+ {
+ DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
+ }
+}
+
+
+static VOID
+AssignDriverLetters (PPARTLIST List)
+{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry1;
+ PLIST_ENTRY Entry2;
+ CHAR Letter;
+
+ Letter = 'C';
+
+ /* Assign drive letters to primary partitions */
+ Entry1 = List->DiskListHead.Flink;
+ while (Entry1 != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
+
+ if (!IsListEmpty (&DiskEntry->PartListHead))
+ {
+ PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink,
+ 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++;
+ }
+ }
+ }
+ }
+
+ 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)
+ {
+ 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;
+ }
+ }
+
+ Entry1 = Entry1->Flink;
+ }
+}
+
+
+static VOID
+UpdatePartitionNumbers (PDISKENTRY DiskEntry)
+{
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry;
+ ULONG PartNumber;
+ ULONG i;
+
+ PartNumber = 1;
+ Entry = DiskEntry->PartListHead.Flink;
+ while (Entry != &DiskEntry->PartListHead)
+ {
+ PartEntry = CONTAINING_RECORD (Entry,
+ PARTENTRY,
+ ListEntry);
+
+ 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++;
+ }
+ }
+ }
+
+ Entry = Entry->Flink;
+ }
+}
+
+
+static VOID
+AddPartitionToList (ULONG DiskNumber,
+ PDISKENTRY DiskEntry,
+ DRIVE_LAYOUT_INFORMATION *LayoutBuffer)
+{
+ PPARTENTRY PartEntry;
+ ULONG i;
+ ULONG j;
+
+ 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;
+ }
+
+ RtlZeroMemory (PartEntry,
+ sizeof(PARTENTRY));
+
+ PartEntry->Unpartitioned = FALSE;
+
+ 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;
+ }
+
+ InsertTailList (&DiskEntry->PartListHead,
+ &PartEntry->ListEntry);
+ }
+}
+
+
+static VOID
+ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry)
+{
+ ULONGLONG LastStartingOffset;
+ ULONGLONG LastPartitionLength;
+ ULONGLONG LastUnusedPartitionLength;
+ PPARTENTRY PartEntry;
+ PPARTENTRY NewPartEntry;
+ PLIST_ENTRY Entry;
+ ULONG i;
+ ULONG j;
+
+ if (IsListEmpty (&DiskEntry->PartListHead))
+ {
+ /* Create a partition table that represents the empty disk */
+ PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
+ 0,
+ sizeof(PARTENTRY));
+ if (PartEntry == NULL)
+ return;
+
+ RtlZeroMemory (PartEntry,
+ sizeof(PARTENTRY));
+
+ PartEntry->Unpartitioned = TRUE;
+ PartEntry->UnpartitionedOffset = 0ULL;
+ PartEntry->UnpartitionedLength = DiskEntry->DiskSize;
+
+ PartEntry->FormatState = Unformatted;
+
+ InsertTailList (&DiskEntry->PartListHead,
+ &PartEntry->ListEntry);
+ }
+ else
+ {
+ /* Start partition at head 1, cylinder 0 */
+ LastStartingOffset = DiskEntry->TrackSize;
+ LastPartitionLength = 0ULL;
+ LastUnusedPartitionLength = 0ULL;
+
+ i = 0;
+ Entry = DiskEntry->PartListHead.Flink;
+ while (Entry != &DiskEntry->PartListHead)
+ {
+ PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);
+
+ for (j = 0; j < 4; j++)
+ {
+ if ((!IsContainerPartition (PartEntry->PartInfo[j].PartitionType)) &&
+ (PartEntry->PartInfo[j].PartitionType != PARTITION_ENTRY_UNUSED ||
+ PartEntry->PartInfo[j].PartitionLength.QuadPart != 0LL))
+ {
+ LastUnusedPartitionLength =
+ PartEntry->PartInfo[j].StartingOffset.QuadPart -
+ (LastStartingOffset + LastPartitionLength);
+
+ if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
+ {
+ 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);
+ }
+
+ LastStartingOffset = PartEntry->PartInfo[j].StartingOffset.QuadPart;
+ LastPartitionLength = PartEntry->PartInfo[j].PartitionLength.QuadPart;
+ }
+ }
+
+ i += 4;
+ Entry = Entry->Flink;
+ }
+
+ /* 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);
+
+ if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
+ {
+ 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;
+
+ /* Append the table to the list */
+ InsertTailList (&DiskEntry->PartListHead,
+ &NewPartEntry->ListEntry);
+ }
+ }
+ }
+}
+
+NTSTATUS
+STDCALL
+DiskQueryRoutine(PWSTR ValueName,
+ ULONG ValueType,
+ PVOID ValueData,
+ ULONG ValueLength,
+ PVOID Context,
+ PVOID EntryContext)
+{
+ PLIST_ENTRY ListHead = (PLIST_ENTRY)Context;
+ PULONG GlobalDiskCount = (PULONG)EntryContext;
+ PBIOSDISKENTRY BiosDiskEntry;
+ UNICODE_STRING NameU;
+
+ if (ValueType == REG_SZ &&
+ ValueLength == 20 * sizeof(WCHAR))
+ {
+ BiosDiskEntry = RtlAllocateHeap(ProcessHeap, 0, sizeof(BIOSDISKENTRY));
+ if (BiosDiskEntry == NULL)
+ {
+ return STATUS_NO_MEMORY;
+ }
+ BiosDiskEntry->DiskNumber = (*GlobalDiskCount)++;
+
+ NameU.Buffer = (PWCHAR)ValueData;
+ NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
+ RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
+
+ NameU.Buffer = (PWCHAR)ValueData + 9;
+ RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
+
+ InsertTailList(ListHead, &BiosDiskEntry->ListEntry);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+#define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
+
+STATIC VOID
+EnumerateBiosDiskEntries(PPARTLIST PartList)
+{
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ WCHAR Name[100];
+ ULONG AdapterCount;
+ ULONG ControllerCount;
+ ULONG DiskCount;
+ NTSTATUS Status;
+ ULONG GlobalDiskCount=0;
+
+
+ memset(QueryTable, 0, sizeof(QueryTable));
+ QueryTable[0].Name = L"Identifier";
+ QueryTable[0].QueryRoutine = DiskQueryRoutine;
+ QueryTable[0].EntryContext = (PVOID)&GlobalDiskCount;
+
+ AdapterCount = 0;
+ while (1)
+ {
+ swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+ Name,
+ &QueryTable[1],
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+
+ swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+ Name,
+ &QueryTable[1],
+ NULL,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ ControllerCount = 0;
+ while (1)
+ {
+ swprintf(Name, L"%s\\%lu\\DiskController\\%lu", ROOT_NAME, AdapterCount, ControllerCount);
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+ Name,
+ &QueryTable[1],
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+
+ swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral", ROOT_NAME, AdapterCount, ControllerCount);
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+ Name,
+ &QueryTable[1],
+ NULL,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ DiskCount = 0;
+ while (1)
+ {
+ swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+ Name,
+ QueryTable,
+ (PVOID)&PartList->BiosDiskListHead,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+ DiskCount++;
+ }
+ }
+ ControllerCount++;
+ }
+ }
+ AdapterCount++;
+ }
+}
+
+static VOID
+AddDiskToList (HANDLE FileHandle,
+ ULONG DiskNumber,
+ PPARTLIST List)
+{
+ DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
+ DISK_GEOMETRY DiskGeometry;
+ SCSI_ADDRESS ScsiAddress;
+ PDISKENTRY DiskEntry;
+ IO_STATUS_BLOCK Iosb;
+ NTSTATUS Status;
+ PPARTITION_SECTOR Mbr;
+ PULONG Buffer;
+ LARGE_INTEGER FileOffset;
+ WCHAR Identifier[20];
+ ULONG Checksum;
+ ULONG Signature;
+ ULONG i;
+ PLIST_ENTRY ListEntry;
+ PBIOSDISKENTRY BiosDiskEntry;
+
+ Status = NtDeviceIoControlFile (FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL,
+ 0,
+ &DiskGeometry,
+ sizeof(DISK_GEOMETRY));
+ if (!NT_SUCCESS (Status))
+ {
+ return;
+ }
+
+ if (DiskGeometry.MediaType != FixedMedia)
+ {
+ return;
+ }
+
+ Status = NtDeviceIoControlFile (FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ IOCTL_SCSI_GET_ADDRESS,
+ NULL,
+ 0,
+ &ScsiAddress,
+ sizeof(SCSI_ADDRESS));
+ if (!NT_SUCCESS(Status))
+ {
+ return;
+ }
+
+ Mbr = RtlAllocateHeap(ProcessHeap,
+ 0,
+ DiskGeometry.BytesPerSector);
+
+ if (Mbr == NULL)
+ {
+ return;
+ }
+
+ FileOffset.QuadPart = 0;
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ (PVOID)Mbr,
+ DiskGeometry.BytesPerSector,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Mbr);
+ DPRINT1("NtReadFile failed, status=%x\n", Status);
+ return;
+ }
+ Signature = Mbr->Signature;
+
+ /* Calculate the MBR checksum */
+ Checksum = 0;
+ Buffer = (PULONG)Mbr;
+ for (i = 0; i < 128; i++)
+ {
+ Checksum += Buffer[i];
+ }
+ Checksum = ~Checksum + 1;
+
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ Mbr);
+
+ swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
+ DPRINT("Identifier: %S\n", Identifier);
+
+ DiskEntry = (PDISKENTRY)RtlAllocateHeap (ProcessHeap,
+ 0,
+ sizeof(DISKENTRY));
+ if (DiskEntry == NULL)
+ {
+ return;
+ }
+
+ DiskEntry->Checksum = Checksum;
+ DiskEntry->Signature = Signature;
+ DiskEntry->BiosFound = FALSE;
+
+ ListEntry = List->BiosDiskListHead.Flink;
+ while(ListEntry != &List->BiosDiskListHead)
+ {
+ BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
+ if (BiosDiskEntry->Signature == Signature &&
+ BiosDiskEntry->Checksum == Checksum)
+ {
+ if (!DiskEntry->BiosFound)
+ {
+ DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
+ DiskEntry->BiosFound = TRUE;
+ }
+ else
+ {
+ }
+ }
+ ListEntry = ListEntry->Flink;
+ }
+
+ if (!DiskEntry->BiosFound)
+ {
+ RtlFreeHeap(ProcessHeap, 0, DiskEntry);
+ return;
+ }
+
+ 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);
+
+ InsertAscendingList(&List->DiskListHead, DISKENTRY, ListEntry, DiskEntry, BiosDiskNumber);
+
+ LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap (ProcessHeap,
+ 0,
+ 8192);
+ if (LayoutBuffer == NULL)
+ {
+ return;
+ }
+
+ 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);
+}
+
+
+PPARTLIST
+CreatePartitionList (SHORT Left,
+ SHORT Top,
+ SHORT Right,
+ SHORT Bottom)
+{
+ PPARTLIST List;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ SYSTEM_DEVICE_INFORMATION Sdi;
+ IO_STATUS_BLOCK Iosb;
+ ULONG ReturnSize;
+ NTSTATUS Status;
+ ULONG DiskNumber;
+ WCHAR Buffer[MAX_PATH];
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+
+ 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);
+ InitializeListHead (&List->BiosDiskListHead);
+
+ EnumerateBiosDiskEntries(List);
+
+ Status = NtQuerySystemInformation (SystemDeviceInformation,
+ &Sdi,
+ sizeof(SYSTEM_DEVICE_INFORMATION),
+ &ReturnSize);
+ if (!NT_SUCCESS (Status))
+ {
+ RtlFreeHeap (ProcessHeap, 0, List);
+ return NULL;
+ }
+
+ for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
+ {
+ 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);
-#include "usetup.h"
-#include "console.h"
-#include "partlist.h"
-#include "drivesup.h"
+ NtClose(FileHandle);
+ }
+ }
+ AssignDriverLetters (List);
-/* FUNCTIONS ****************************************************************/
+ List->TopDisk = 0;
+ List->TopPartition = 0;
+
+ /* Search for first usable disk and partition */
+ if (IsListEmpty (&List->DiskListHead))
+ {
+ List->CurrentDisk = NULL;
+ List->CurrentPartition = NULL;
+ }
+ else
+ {
+ List->CurrentDisk =
+ CONTAINING_RECORD (List->DiskListHead.Flink,
+ DISKENTRY,
+ ListEntry);
+
+ if (IsListEmpty (&List->CurrentDisk->PartListHead))
+ {
+ List->CurrentPartition = 0;
+ }
+ else
+ {
+ List->CurrentPartition =
+ CONTAINING_RECORD (List->CurrentDisk->PartListHead.Flink,
+ PARTENTRY,
+ ListEntry);
+ }
+ }
+
+ return List;
+}
+
+
+VOID
+DestroyPartitionList (PPARTLIST List)
+{
+ PDISKENTRY DiskEntry;
+ PBIOSDISKENTRY BiosDiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry;
+
+ /* Release disk and partition info */
+ while (!IsListEmpty (&List->DiskListHead))
+ {
+ Entry = RemoveHeadList (&List->DiskListHead);
+ DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
+
+ /* Release driver name */
+ RtlFreeUnicodeString(&DiskEntry->DriverName);
+
+ /* Release partition array */
+ while (!IsListEmpty (&DiskEntry->PartListHead))
+ {
+ Entry = RemoveHeadList (&DiskEntry->PartListHead);
+ PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);
+
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ PartEntry);
+ }
+
+ /* Release disk entry */
+ RtlFreeHeap (ProcessHeap, 0, DiskEntry);
+ }
+
+ /* release the bios disk info */
+ while(!IsListEmpty(&List->BiosDiskListHead))
+ {
+ Entry = RemoveHeadList(&List->BiosDiskListHead);
+ BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
+
+ RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
+ }
+
+ /* Release list head */
+ RtlFreeHeap (ProcessHeap, 0, List);
+}
+
+
+static VOID
+PrintEmptyLine (PPARTLIST List)
+{
+ COORD coPos;
+ ULONG Written;
+ USHORT Width;
+ USHORT Height;
+
+ Width = List->Right - List->Left - 1;
+ Height = List->Bottom - List->Top - 2;
+
+
+ coPos.X = List->Left + 1;
+ coPos.Y = List->Top + 1 + List->Line;
+
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ FillConsoleOutputAttribute (0x17,
+ Width,
+ coPos,
+ &Written);
+
+ FillConsoleOutputCharacter (' ',
+ Width,
+ coPos,
+ &Written);
+ }
+ List->Line++;
+}
+
+
+static VOID
+PrintPartitionData (PPARTLIST List,
+ PDISKENTRY DiskEntry,
+ PPARTENTRY PartEntry)
+{
+ CHAR LineBuffer[128];
+ COORD coPos;
+ ULONG Written;
+ USHORT Width;
+ USHORT Height;
+
+ ULONGLONG PartSize;
+ PCHAR Unit;
+ UCHAR Attribute;
+ PCHAR PartType;
+
+ Width = List->Right - List->Left - 1;
+ Height = List->Bottom - List->Top - 2;
+
+
+ coPos.X = List->Left + 1;
+ coPos.Y = List->Top + 1 + List->Line;
+
+ if (PartEntry->Unpartitioned == TRUE)
+ {
+#if 0
+ if (PartEntry->UnpartitionledLength >= 0x280000000ULL) /* 10 GB */
+ {
+ PartSize = (PartEntry->UnpartitionedLength + (1 << 29)) >> 30;
+ Unit = "GB";
+ }
+ else
+#endif
+ if (PartEntry->UnpartitionedLength >= 0xA00000ULL) /* 10 MB */
+ {
+ PartSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20;
+ Unit = "MB";
+ }
+ else
+ {
+ PartSize = (PartEntry->UnpartitionedLength + (1 << 9)) >> 10;
+ Unit = "KB";
+ }
+
+ sprintf (LineBuffer,
+ " Unpartitioned space %6I64u %s",
+ PartSize,
+ Unit);
+ }
+ else
+ {
+ /* 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 >= 0x280000000LL) /* 10 GB */
+ {
+ PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 29)) >> 30;
+ Unit = "GB";
+ }
+ else
+#endif
+ if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0xA00000LL) /* 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 (PartType == NULL)
+ {
+ sprintf (LineBuffer,
+ "%c%c Type %-3u %6I64u %s",
+ (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+ (PartEntry->DriveLetter == 0) ? '-' : ':',
+ PartEntry->PartInfo[0].PartitionType,
+ PartSize,
+ Unit);
+ }
+ else
+ {
+ sprintf (LineBuffer,
+ "%c%c %-24s %6I64u %s",
+ (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+ (PartEntry->DriveLetter == 0) ? '-' : ':',
+ PartType,
+ PartSize,
+ Unit);
+ }
+ }
+
+ Attribute = (List->CurrentDisk == DiskEntry &&
+ List->CurrentPartition == PartEntry) ? 0x71 : 0x17;
+
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ FillConsoleOutputCharacter (' ',
+ Width,
+ coPos,
+ &Written);
+ }
+ coPos.X += 4;
+ Width -= 8;
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ FillConsoleOutputAttribute (Attribute,
+ Width,
+ coPos,
+ &Written);
+ }
+ coPos.X++;
+ Width -= 2;
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ WriteConsoleOutputCharacters (LineBuffer,
+ min (strlen (LineBuffer), Width),
+ coPos);
+ }
+ List->Line++;
+}
+
+
+static VOID
+PrintDiskData (PPARTLIST List,
+ PDISKENTRY DiskEntry)
+{
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry;
+ CHAR LineBuffer[128];
+ COORD coPos;
+ ULONG Written;
+ USHORT Width;
+ USHORT Height;
+ ULONGLONG DiskSize;
+ PCHAR Unit;
+
+ Width = List->Right - List->Left - 1;
+ Height = List->Bottom - List->Top - 2;
+
+
+ coPos.X = List->Left + 1;
+ coPos.Y = List->Top + 1 + List->Line;
+
+#if 0
+ if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
+ {
+ DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
+ Unit = "GB";
+ }
+ else
+#endif
+ {
+ DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
+ if (DiskSize == 0)
+ DiskSize = 1;
+ Unit = "MB";
+ }
+
+ if (DiskEntry->DriverName.Length > 0)
+ {
+ 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,
+ "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
+ DiskSize,
+ Unit,
+ DiskEntry->DiskNumber,
+ DiskEntry->Port,
+ DiskEntry->Bus,
+ DiskEntry->Id);
+ }
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ FillConsoleOutputAttribute (0x17,
+ Width,
+ coPos,
+ &Written);
+
+ FillConsoleOutputCharacter (' ',
+ Width,
+ coPos,
+ &Written);
+ }
+
+ coPos.X++;
+ if (List->Line >= 0 && List->Line <= Height)
+ {
+ 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, Entry2;
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry = NULL;
+ COORD coPos;
+ ULONG Written;
+ SHORT i;
+ SHORT CurrentDiskLine;
+ SHORT CurrentPartLine;
+ SHORT LastLine;
+ BOOL CurrentPartLineFound = FALSE;
+ BOOL CurrentDiskLineFound = FALSE;
+
+ /* Calculate the line of the current disk and partition */
+ CurrentDiskLine = 0;
+ CurrentPartLine = 0;
+ LastLine = 0;
+ Entry = List->DiskListHead.Flink;
+ while (Entry != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
+ LastLine += 2;
+ if (CurrentPartLineFound == FALSE)
+ {
+ CurrentPartLine += 2;
+ }
+ Entry2 = DiskEntry->PartListHead.Flink;
+ while (Entry2 != &DiskEntry->PartListHead)
+ {
+ PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
+ if (PartEntry == List->CurrentPartition)
+ {
+ CurrentPartLineFound = TRUE;
+ }
+ Entry2 = Entry2->Flink;
+ if (CurrentPartLineFound == FALSE)
+ {
+ CurrentPartLine++;
+ }
+ LastLine++;
+ }
+ if (DiskEntry == List->CurrentDisk)
+ {
+ CurrentDiskLineFound = TRUE;
+ }
+ Entry = Entry->Flink;
+ if (Entry != &List->DiskListHead)
+ {
+ if (CurrentDiskLineFound == FALSE)
+ {
+ CurrentPartLine ++;
+ CurrentDiskLine = CurrentPartLine;
+ }
+ LastLine++;
+ }
+ else
+ {
+ LastLine--;
+ }
+ }
+
+ /* If it possible, make the disk name visible */
+ if (CurrentPartLine < List->Offset)
+ {
+ List->Offset = CurrentPartLine;
+ }
+ else if (CurrentPartLine - List->Offset > List->Bottom - List->Top - 2)
+ {
+ List->Offset = CurrentPartLine - (List->Bottom - List->Top - 2);
+ }
+ if (CurrentDiskLine < List->Offset && CurrentPartLine - CurrentDiskLine < List->Bottom - List->Top - 2)
+ {
+ List->Offset = CurrentDiskLine;
+ }
+
+
+ /* 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;
+ if (List->Offset == 0)
+ {
+ FillConsoleOutputCharacter (0xC4, // '-',
+ List->Right - List->Left - 1,
+ coPos,
+ &Written);
+ }
+ else
+ {
+ FillConsoleOutputCharacter (0xC4, // '-',
+ List->Right - List->Left - 5,
+ coPos,
+ &Written);
+ coPos.X = List->Right - 5;
+ WriteConsoleOutputCharacters ("(\x18)", // "(up)"
+ 3,
+ coPos);
+ coPos.X = List->Right - 2;
+ FillConsoleOutputCharacter (0xC4, // '-',
+ 2,
+ 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);
-static VOID
-AddPartitionList(ULONG DiskNumber,
- PDISKENTRY DiskEntry,
- DRIVE_LAYOUT_INFORMATION *LayoutBuffer)
-{
- PPARTENTRY PartEntry;
- ULONG i;
- ULONG EntryCount;
- BOOLEAN LastEntryWasUnused;
- ULONGLONG LastStartingOffset;
- ULONGLONG LastPartitionSize;
- ULONGLONG LastUnusedPartitionSize;
- ULONG LastUnusedEntry;
+ coPos.X = List->Right;
+ FillConsoleOutputCharacter (0xB3, //'|',
+ 1,
+ coPos,
+ &Written);
+ }
- /*
- * FIXME:
- * Determine required number of partiton entries.
- * This must include entries for unused disk space.
- */
+ /* draw lower left corner */
+ coPos.X = List->Left;
+ coPos.Y = List->Bottom;
+ FillConsoleOutputCharacter (0xC0, // '+',
+ 1,
+ coPos,
+ &Written);
- /* Check for unpartitioned disk */
- if (LayoutBuffer->PartitionCount == 0)
+ /* draw lower edge */
+ coPos.X = List->Left + 1;
+ coPos.Y = List->Bottom;
+ if (LastLine - List->Offset <= List->Bottom - List->Top - 2)
{
- EntryCount = 1;
+ FillConsoleOutputCharacter (0xC4, // '-',
+ List->Right - List->Left - 1,
+ coPos,
+ &Written);
}
else
{
- EntryCount = LayoutBuffer->PartitionCount;
+ FillConsoleOutputCharacter (0xC4, // '-',
+ List->Right - List->Left - 5,
+ coPos,
+ &Written);
+ coPos.X = List->Right - 5;
+ WriteConsoleOutputCharacters ("(\x19)", // "(down)"
+ 3,
+ coPos);
+ coPos.X = List->Right - 2;
+ FillConsoleOutputCharacter (0xC4, // '-',
+ 2,
+ coPos,
+ &Written);
}
+ /* draw lower right corner */
+ coPos.X = List->Right;
+ coPos.Y = List->Bottom;
+ FillConsoleOutputCharacter (0xD9, // '+',
+ 1,
+ coPos,
+ &Written);
- DiskEntry->PartArray = (PPARTENTRY)RtlAllocateHeap(ProcessHeap,
- 0,
- EntryCount * sizeof(PARTENTRY));
- DiskEntry->PartCount = EntryCount;
-
- RtlZeroMemory(DiskEntry->PartArray,
- EntryCount * sizeof(PARTENTRY));
+ /* print list entries */
+ List->Line = - List->Offset;
- if (LayoutBuffer->PartitionCount == 0)
+ Entry = List->DiskListHead.Flink;
+ while (Entry != &List->DiskListHead)
{
- /* Initialize an 'Unpartitioned space' entry */
- PartEntry = &DiskEntry->PartArray[0];
+ DiskEntry = CONTAINING_RECORD (Entry, 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;
+ /* Print disk entry */
+ PrintDiskData (List,
+ DiskEntry);
+
+ Entry = Entry->Flink;
}
- else
- {
- LastEntryWasUnused = FALSE;
- // Start partition at head 1, cylinder 0
- LastStartingOffset = DiskEntry->SectorsPerTrack * DiskEntry->BytesPerSector;
- LastPartitionSize = 0;
- LastUnusedEntry = -1;
- LastUnusedPartitionSize = 0;
- for (i = 0; i < LayoutBuffer->PartitionCount; i++)
- {
- PartEntry = &DiskEntry->PartArray[i];
+}
- if ((LayoutBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED) &&
- (!IsContainerPartition(LayoutBuffer->PartitionEntry[i].PartitionType)))
- {
- LastUnusedPartitionSize = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart
- - (LastStartingOffset + LastPartitionSize);
- if (LastUnusedEntry != -1)
- {
- DiskEntry->PartArray[LastUnusedEntry].StartingOffset = LastStartingOffset + LastPartitionSize;
- DiskEntry->PartArray[LastUnusedEntry].PartSize = LastUnusedPartitionSize;
- }
- LastStartingOffset = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart;
- LastPartitionSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart;
-
- PartEntry->StartingOffset = LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart;
- PartEntry->PartSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart;
- PartEntry->PartNumber = LayoutBuffer->PartitionEntry[i].PartitionNumber,
- PartEntry->PartType = LayoutBuffer->PartitionEntry[i].PartitionType;
- 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;
- }
- else
- {
- if (LastEntryWasUnused)
- {
- /* Group unused entries into one unpartitioned disk space area */
- PartEntry->HidePartEntry = TRUE;
- PartEntry->PartSize = 0;
- }
- else
- {
- LastUnusedEntry = i;
- }
- PartEntry->Unpartitioned = TRUE;
+VOID
+SelectPartition(PPARTLIST List, ULONG DiskNumber, ULONG PartitionNumber)
+{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry1;
+ PLIST_ENTRY Entry2;
+ ULONG i;
+
+ /* Check for empty disks */
+ if (IsListEmpty (&List->DiskListHead))
+ return;
- PartEntry->Used = FALSE;
- LastEntryWasUnused = TRUE;
- }
- }
- LastUnusedPartitionSize = DiskEntry->DiskSize
- - (LastStartingOffset + LastPartitionSize);
- if (LastUnusedEntry != -1)
+ /* Check for first usable entry on next disk */
+ Entry1 = List->CurrentDisk->ListEntry.Flink;
+ while (Entry1 != &List->DiskListHead)
+ {
+ DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
+
+ if (DiskEntry->DiskNumber == DiskNumber)
{
- DiskEntry->PartArray[LastUnusedEntry].StartingOffset = LastStartingOffset + LastPartitionSize;
- DiskEntry->PartArray[LastUnusedEntry].PartSize = LastUnusedPartitionSize;
+ Entry2 = DiskEntry->PartListHead.Flink;
+ while (Entry2 != &DiskEntry->PartListHead)
+ {
+ PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
+
+ for (i = 0; i < 4; i++)
+ {
+ if (PartEntry->PartInfo[i].PartitionNumber == PartitionNumber)
+ {
+ List->CurrentDisk = DiskEntry;
+ List->CurrentPartition = PartEntry;
+ DrawPartitionList (List);
+ return;
+ }
+ }
+ Entry2 = Entry2->Flink;
+ }
+ return;
}
+ Entry1 = Entry1->Flink;
}
}
-static VOID
-GetDriverName(PDISKENTRY DiskEntry)
+VOID
+ScrollDownPartitionList (PPARTLIST List)
{
- 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));
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry1;
+ PLIST_ENTRY Entry2;
- QueryTable[0].Name = L"Driver";
- QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
- QueryTable[0].EntryContext = &DiskEntry->DriverName;
+ /* Check for empty disks */
+ if (IsListEmpty (&List->DiskListHead))
+ return;
- Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
- KeyName,
- QueryTable,
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
+ /* Check for next usable entry on current disk */
+ if (List->CurrentPartition != NULL)
{
- DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
- }
-}
+ 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;
+ }
+ }
-PPARTLIST
-CreatePartitionListNoGUI()
-{
- 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;
+ /* 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);
- List = (PPARTLIST)RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTLIST));
- if (List == NULL)
- return(NULL);
+ Entry2 = DiskEntry->PartListHead.Flink;
+ while (Entry2 != &DiskEntry->PartListHead)
+ {
+ PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
- List->Left = 0;
- List->Top = 0;
- List->Right = 0;
- List->Bottom = 0;
+// if (PartEntry->HidePartEntry == FALSE)
+ {
+ List->CurrentDisk = DiskEntry;
+ List->CurrentPartition = PartEntry;
+ DrawPartitionList (List);
+ return;
+ }
- List->Line = 0;
+ Entry2 = Entry2->Flink;
+ }
- List->TopDisk = (ULONG)-1;
- List->TopPartition = (ULONG)-1;
+ Entry1 = Entry1->Flink;
+ }
+ }
+}
- List->CurrentDisk = (ULONG)-1;
- List->CurrentPartition = (ULONG)-1;
- List->DiskCount = 0;
- List->DiskArray = NULL;
+VOID
+ScrollUpPartitionList (PPARTLIST List)
+{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry1;
+ PLIST_ENTRY Entry2;
+ /* Check for empty disks */
+ if (IsListEmpty (&List->DiskListHead))
+ return;
- Status = NtQuerySystemInformation(SystemDeviceInformation,
- &Sdi,
- sizeof(SYSTEM_DEVICE_INFORMATION),
- &ReturnSize);
- if (!NT_SUCCESS(Status))
+ /* check for previous usable entry on current disk */
+ if (List->CurrentPartition != NULL)
{
- RtlFreeHeap(ProcessHeap, 0, List);
- return(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;
+ }
}
- List->DiskArray = (PDISKENTRY)RtlAllocateHeap(ProcessHeap,
- 0,
- Sdi.NumberOfDisks * sizeof(DISKENTRY));
- List->DiskCount = Sdi.NumberOfDisks;
- for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
+ /* check for last usable entry on previous disk */
+ if (List->CurrentDisk != NULL)
{
- 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))
+ Entry1 = List->CurrentDisk->ListEntry.Blink;
+ while (Entry1 != &List->DiskListHead)
{
- Status = NtDeviceIoControlFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- IOCTL_DISK_GET_DRIVE_GEOMETRY,
- NULL,
- 0,
- &DiskGeometry,
- sizeof(DISK_GEOMETRY));
- if (NT_SUCCESS(Status))
+ DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
+
+ Entry2 = DiskEntry->PartListHead.Blink;
+ while (Entry2 != &DiskEntry->PartListHead)
{
- if (DiskGeometry.MediaType == FixedMedia)
- {
- 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))
- {
- AddPartitionList(DiskNumber,
- &List->DiskArray[DiskNumber],
- LayoutBuffer);
- }
+ PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
- RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
- }
- else
+// if (PartEntry->HidePartEntry == FALSE)
{
- /* mark removable disk entry */
- List->DiskArray[DiskNumber].FixedDisk = FALSE;
- List->DiskArray[DiskNumber].PartCount = 0;
- List->DiskArray[DiskNumber].PartArray = NULL;
+ List->CurrentDisk = DiskEntry;
+ List->CurrentPartition = PartEntry;
+ DrawPartitionList (List);
+ return;
}
+
+ Entry2 = Entry2->Blink;
}
- NtClose(FileHandle);
+ Entry1 = Entry1->Blink;
}
}
-
- List->TopDisk = 0;
- List->TopPartition = 0;
-
- /* FIXME: search for first usable disk and partition */
- List->CurrentDisk = 0;
- List->CurrentPartition = 0;
-
- return(List);
}
-PPARTLIST
-CreatePartitionList(SHORT Left,
- SHORT Top,
- SHORT Right,
- SHORT Bottom)
+
+static PPARTENTRY
+GetPrevPartitionedEntry (PDISKENTRY DiskEntry,
+ PPARTENTRY CurrentEntry)
{
- PPARTLIST List;
+ PPARTENTRY PrevEntry;
+ PLIST_ENTRY Entry;
- List = CreatePartitionListNoGUI();
- if (List == NULL)
- return(NULL);
+ if (CurrentEntry->ListEntry.Blink == &DiskEntry->PartListHead)
+ return NULL;
- List->Left = Left;
- List->Top = Top;
- List->Right = Right;
- List->Bottom = Bottom;
+ Entry = CurrentEntry->ListEntry.Blink;
+ while (Entry != &DiskEntry->PartListHead)
+ {
+ PrevEntry = CONTAINING_RECORD (Entry,
+ PARTENTRY,
+ ListEntry);
+ if (PrevEntry->Unpartitioned == FALSE)
+ return PrevEntry;
- DrawPartitionList(List);
+ Entry = Entry->Blink;
+ }
- return(List);
+ return NULL;
}
-PPARTENTRY
-GetPartitionInformation(PPARTLIST List,
- ULONG DiskNumber,
- ULONG PartitionNumber,
- PULONG PartEntryNumber)
+static PPARTENTRY
+GetNextPartitionedEntry (PDISKENTRY DiskEntry,
+ PPARTENTRY CurrentEntry)
{
- PPARTENTRY PartEntry;
- ULONG i;
+ PPARTENTRY NextEntry;
+ PLIST_ENTRY Entry;
- if (List->DiskArray == NULL)
- {
- return(FALSE);
- }
-
- if (DiskNumber >= List->DiskCount)
- {
- return(FALSE);
- }
+ if (CurrentEntry->ListEntry.Flink == &DiskEntry->PartListHead)
+ return NULL;
- if (PartitionNumber >= List->DiskArray[DiskNumber].PartCount)
+ Entry = CurrentEntry->ListEntry.Flink;
+ while (Entry != &DiskEntry->PartListHead)
{
- return(FALSE);
- }
+ NextEntry = CONTAINING_RECORD (Entry,
+ PARTENTRY,
+ ListEntry);
+ if (NextEntry->Unpartitioned == FALSE)
+ return NextEntry;
- if (List->DiskArray[DiskNumber].FixedDisk != TRUE)
- {
- return(FALSE);
+ Entry = Entry->Flink;
}
- for (i = 0; i < List->DiskArray[DiskNumber].PartCount; i++)
- {
- PartEntry = &List->DiskArray[DiskNumber].PartArray[i];
- if (PartEntry->PartNumber == PartitionNumber)
- {
- *PartEntryNumber = i;
- return PartEntry;
- }
- }
return NULL;
}
-BOOLEAN
-MarkPartitionActive(ULONG DiskNumber,
- ULONG PartitionNumber,
- PPARTDATA ActivePartition)
+
+static PPARTENTRY
+GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry,
+ PPARTENTRY PartEntry)
{
- PPARTLIST List;
- 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;
+ PPARTENTRY PrevPartEntry;
- List = CreatePartitionListNoGUI();
- if (List == NULL)
+ if (PartEntry->ListEntry.Blink != &DiskEntry->PartListHead)
{
- return(FALSE);
+ PrevPartEntry = CONTAINING_RECORD (PartEntry->ListEntry.Blink,
+ PARTENTRY,
+ ListEntry);
+ if (PrevPartEntry->Unpartitioned == TRUE)
+ return PrevPartEntry;
}
- PartEntry = GetPartitionInformation(List,
- DiskNumber,
- PartitionNumber,
- &PartEntryNumber);
- if (List == NULL)
- {
- DestroyPartitionList(List);
- return(FALSE);
- }
-
-
- 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))
- {
- 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;
- }
+ return NULL;
+}
- LayoutBuffer->PartitionEntry[PartEntryNumber].BootIndicator = TRUE;
+static PPARTENTRY
+GetNextUnpartitionedEntry (PDISKENTRY DiskEntry,
+ PPARTENTRY PartEntry)
+{
+ PPARTENTRY NextPartEntry;
- 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;
- }
- }
- else
+ if (PartEntry->ListEntry.Flink != &DiskEntry->PartListHead)
{
- NtClose(FileHandle);
- RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
- DestroyPartitionList(List);
- return FALSE;
+ NextPartEntry = CONTAINING_RECORD (PartEntry->ListEntry.Flink,
+ PARTENTRY,
+ ListEntry);
+ if (NextPartEntry->Unpartitioned == TRUE)
+ return NextPartEntry;
}
- NtClose(FileHandle);
- RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
-
- PartEntry->Active = TRUE;
- if (!GetActiveBootPartition(List, ActivePartition))
- {
- DestroyPartitionList(List);
- DPRINT("GetActiveBootPartition() failed\n");
- return FALSE;
- }
-
- DestroyPartitionList(List);
-
- return TRUE;
+ return NULL;
}
VOID
-DestroyPartitionList(PPARTLIST List)
+CreateNewPartition (PPARTLIST List,
+ ULONGLONG PartitionSize,
+ BOOLEAN AutoCreate)
{
- 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++)
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PPARTENTRY PrevPartEntry;
+ PPARTENTRY NextPartEntry;
+ PPARTENTRY NewPartEntry;
+
+ if (List == NULL ||
+ List->CurrentDisk == NULL ||
+ List->CurrentPartition == NULL ||
+ List->CurrentPartition->Unpartitioned == FALSE)
{
- FillConsoleOutputAttribute(0x17,
- Width,
- coPos,
- &i);
-
- FillConsoleOutputCharacter(' ',
- Width,
- coPos,
- &i);
+ return;
}
-#endif
- /* Release disk and partition info */
- if (List->DiskArray != NULL)
+ DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
+
+ if (AutoCreate == TRUE ||
+ PartitionSize == PartEntry->UnpartitionedLength)
{
- for (i = 0; i < List->DiskCount; i++)
+ /* 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)
{
- /* Release driver name */
- RtlFreeUnicodeString(&List->DiskArray[i].DriverName);
-
- /* 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;
- }
- }
-
- /* Release disk array */
- RtlFreeHeap(ProcessHeap, 0, List->DiskArray);
- List->DiskCount = 0;
- List->DiskArray = NULL;
- }
-
- /* Release list head */
- RtlFreeHeap(ProcessHeap, 0, List);
-}
+ /* 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;
-static VOID
-PrintEmptyLine(PPARTLIST List)
-{
- COORD coPos;
- ULONG Written;
- USHORT Width;
- USHORT Height;
-
- Width = List->Right - List->Left - 1;
- Height = List->Bottom - List->Top - 1;
+ /* Update previous container partition data */
- if (List->Line < 0 || List->Line > Height)
- return;
+ PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
+ PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
- coPos.X = List->Left + 1;
- coPos.Y = List->Top + 1 + List->Line;
+ 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;
+ }
- FillConsoleOutputAttribute(0x17,
- Width,
- coPos,
- &Written);
+ 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 */
- FillConsoleOutputCharacter(' ',
- Width,
- coPos,
- &Written);
+ PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
+ PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
- List->Line++;
-}
+ 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) <
+ (1024LL * 255LL * 63LL * 512LL))
+ {
+ PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
+ }
+ else
+ {
+ PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED;
+ }
-static VOID
-PrintPartitionData(PPARTLIST List,
- SHORT DiskIndex,
- SHORT PartIndex)
-{
- PPARTENTRY PartEntry;
- CHAR LineBuffer[128];
- COORD coPos;
- ULONG Written;
- USHORT Width;
- USHORT Height;
+ PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
+ PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
+ }
- ULONGLONG PartSize;
- PCHAR Unit;
- UCHAR Attribute;
- PCHAR PartType;
+ PartEntry->AutoCreate = AutoCreate;
+ PartEntry->New = TRUE;
+ PartEntry->Unpartitioned = FALSE;
+ PartEntry->UnpartitionedOffset = 0ULL;
+ PartEntry->UnpartitionedLength = 0ULL;
+ }
+ else
+ {
+ /* 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)
+ {
+ /* Current entry is in the middle of the list */
- Width = List->Right - List->Left - 1;
- Height = List->Bottom - List->Top - 1;
+ /* Copy previous container partition data to current entry */
+ RtlCopyMemory (&NewPartEntry->PartInfo[1],
+ &PrevPartEntry->PartInfo[1],
+ sizeof(PARTITION_INFORMATION));
+ NewPartEntry->PartInfo[1].RewritePartition = TRUE;
- if (List->Line < 0 || List->Line > Height)
- return;
+ /* Update previous container partition data */
- coPos.X = List->Left + 1;
- coPos.Y = List->Top + 1 + List->Line;
+ PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
+ NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
- PartEntry = &List->DiskArray[DiskIndex].PartArray[PartIndex];
+ 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;
+ }
- /* Determine partition type */
- PartType = NULL;
- if (PartEntry->Unpartitioned == FALSE)
- {
- if ((PartEntry->PartType == PARTITION_FAT_12) ||
- (PartEntry->PartType == PARTITION_FAT_16) ||
- (PartEntry->PartType == PARTITION_HUGE) ||
- (PartEntry->PartType == PARTITION_XINT13))
- {
- PartType = "FAT";
+ PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
}
- else if ((PartEntry->PartType == PARTITION_FAT32) ||
- (PartEntry->PartType == PARTITION_FAT32_XINT13))
+ else if (PrevPartEntry == NULL && NextPartEntry != NULL)
{
- PartType = "FAT32";
+ /* Current entry is the first entry */
+ return;
}
- else if (PartEntry->PartType == PARTITION_IFS)
+ else if (PrevPartEntry != NULL && NextPartEntry == NULL)
{
- PartType = "NTFS"; /* FIXME: Not quite correct! */
- }
- }
+ /* Current entry is the last entry */
+ PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
+ NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
-#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";
- }
- else
- {
- PartSize = (PartEntry->PartSize + (1 << 9)) >> 10;
- Unit = "KB";
- }
+ 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) <
+ (1024LL * 255LL * 63LL * 512LL))
+ {
+ PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
+ }
+ else
+ {
+ PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED;
+ }
- 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);
- }
- else
- {
- sprintf(LineBuffer,
- "%c: %s %I64u %s",
- PartEntry->DriveLetter,
- PartType,
- PartSize,
- Unit);
+ PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
+ PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
}
-#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);
+ /* Update offset and size of the remaining unpartitioned disk space */
+ PartEntry->UnpartitionedOffset += PartitionSize;
+ PartEntry->UnpartitionedLength -= PartitionSize;
}
- Attribute = (List->CurrentDisk == DiskIndex &&
- List->CurrentPartition == PartIndex) ? 0x71 : 0x17;
-
- FillConsoleOutputCharacter(' ',
- Width,
- coPos,
- &Written);
-
- coPos.X += 4;
- Width -= 8;
- FillConsoleOutputAttribute(Attribute,
- Width,
- coPos,
- &Written);
+ DiskEntry->Modified = TRUE;
- coPos.X++;
- Width -= 2;
- WriteConsoleOutputCharacters(LineBuffer,
- min(strlen(LineBuffer), Width),
- coPos);
+ UpdatePartitionNumbers (DiskEntry);
- List->Line++;
+ AssignDriverLetters (List);
}
-static VOID
-PrintDiskData(PPARTLIST List,
- SHORT DiskIndex)
+VOID
+DeleteCurrentPartition (PPARTLIST List)
{
PDISKENTRY DiskEntry;
- CHAR LineBuffer[128];
- COORD coPos;
- ULONG Written;
- USHORT Width;
- USHORT Height;
- ULONGLONG DiskSize;
- PCHAR Unit;
- SHORT PartIndex;
+ PPARTENTRY PartEntry;
+ PPARTENTRY PrevPartEntry;
+ PPARTENTRY NextPartEntry;
- DiskEntry = &List->DiskArray[DiskIndex];
+ if (List == NULL ||
+ List->CurrentDisk == NULL ||
+ List->CurrentPartition == NULL ||
+ List->CurrentPartition->Unpartitioned == TRUE)
+ {
+ return;
+ }
- Width = List->Right - List->Left - 1;
- Height = List->Bottom - List->Top - 1;
+ DiskEntry = List->CurrentDisk;
+ PartEntry = List->CurrentPartition;
- if (List->Line < 0 || List->Line > Height)
- return;
+ /* Adjust container partition entries */
- coPos.X = List->Left + 1;
- coPos.Y = List->Top + 1 + List->Line;
+ /* Get previous and next partition entries */
+ PrevPartEntry = GetPrevPartitionedEntry (DiskEntry,
+ PartEntry);
+ NextPartEntry = GetNextPartitionedEntry (DiskEntry,
+ PartEntry);
-#if 0
- if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
- {
- DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
- Unit = "GB";
- }
- else
-#endif
+ if (PrevPartEntry != NULL && NextPartEntry != NULL)
{
- DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
- if (DiskSize == 0)
- DiskSize = 1;
- Unit = "MB";
+ /* 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;
}
-
- if (DiskEntry->DriverName.Length > 0)
+ else if (PrevPartEntry == NULL && NextPartEntry != NULL)
{
- 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);
+ /*
+ * A primary partition can not be deleted as long as
+ * extended partitions are present.
+ */
+ return;
}
- else
+ else if (PrevPartEntry != NULL && NextPartEntry == NULL)
{
- sprintf(LineBuffer,
- "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
- DiskSize,
- Unit,
- DiskEntry->DiskNumber,
- DiskEntry->Port,
- DiskEntry->Bus,
- DiskEntry->Id);
+ /* Current entry is the last entry */
+ RtlZeroMemory (&PrevPartEntry->PartInfo[1],
+ sizeof(PARTITION_INFORMATION));
+ PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
}
- FillConsoleOutputAttribute(0x17,
- Width,
- coPos,
- &Written);
- FillConsoleOutputCharacter(' ',
- Width,
- coPos,
- &Written);
+ /* Adjust unpartitioned disk space entries */
- coPos.X++;
- WriteConsoleOutputCharacters(LineBuffer,
- min(strlen(LineBuffer), Width - 2),
- coPos);
+ /* Get pointer to previous and next unpartitioned entries */
+ PrevPartEntry = GetPrevUnpartitionedEntry (DiskEntry,
+ PartEntry);
- List->Line++;
+ NextPartEntry = GetNextUnpartitionedEntry (DiskEntry,
+ PartEntry);
- /* Print separator line */
- PrintEmptyLine(List);
+ if (PrevPartEntry != NULL && NextPartEntry != NULL)
+ {
+ /* 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);
- /* Print partition lines*/
- for (PartIndex = 0; PartIndex < DiskEntry->PartCount; PartIndex++)
+ /* Remove the current entry */
+ RemoveEntryList (&PartEntry->ListEntry);
+ RtlFreeHeap (ProcessHeap,
+ 0,
+ PartEntry);
+
+ /* Update current partition */
+ List->CurrentPartition = PrevPartEntry;
+ }
+ else if (PrevPartEntry == NULL && NextPartEntry != NULL)
{
- if (!DiskEntry->PartArray[PartIndex].HidePartEntry)
- {
- PrintPartitionData(List,
- DiskIndex,
- PartIndex);
- }
+ /* 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));
}
- /* Print separator line */
- PrintEmptyLine(List);
+ DiskEntry->Modified = TRUE;
+
+ UpdatePartitionNumbers (DiskEntry);
+
+ AssignDriverLetters (List);
}
VOID
-DrawPartitionList(PPARTLIST List)
+CheckActiveBootPartition (PPARTLIST List)
{
- 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);
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
- /* draw left and right edge */
- for (i = List->Top + 1; i < List->Bottom; i++)
+ /* Check for empty disk list */
+ if (IsListEmpty (&List->DiskListHead))
{
- coPos.X = List->Left;
- coPos.Y = i;
- FillConsoleOutputCharacter(0xB3, // '|',
- 1,
- coPos,
- &Written);
+ List->ActiveBootDisk = NULL;
+ List->ActiveBootPartition = NULL;
+ return;
+ }
- coPos.X = List->Right;
- FillConsoleOutputCharacter(0xB3, //'|',
- 1,
- coPos,
- &Written);
+#if 0
+ if (List->ActiveBootDisk != NULL &&
+ List->ActiveBootPartition != NULL)
+ {
+ /* We already have an active boot partition */
+ return;
}
+#endif
- /* draw lower left corner */
- coPos.X = List->Left;
- coPos.Y = List->Bottom;
- FillConsoleOutputCharacter(0xC0, // '+',
- 1,
- coPos,
- &Written);
+ DiskEntry = CONTAINING_RECORD (List->DiskListHead.Flink,
+ DISKENTRY,
+ ListEntry);
- /* draw lower edge */
- coPos.X = List->Left + 1;
- coPos.Y = List->Bottom;
- FillConsoleOutputCharacter(0xC4, // '-',
- List->Right - List->Left - 1,
- coPos,
- &Written);
+ /* Check for empty partition list */
+ if (IsListEmpty (&DiskEntry->PartListHead))
+ {
+ List->ActiveBootDisk = NULL;
+ List->ActiveBootPartition = NULL;
+ return;
+ }
- /* draw lower right corner */
- coPos.X = List->Right;
- coPos.Y = List->Bottom;
- FillConsoleOutputCharacter(0xD9, // '+',
- 1,
- coPos,
- &Written);
+ PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink,
+ PARTENTRY,
+ ListEntry);
- /* print list entries */
- List->Line = 0;
- for (DiskIndex = 0; DiskIndex < List->DiskCount; DiskIndex++)
+ /* 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))
{
- if (List->DiskArray[DiskIndex].FixedDisk == TRUE)
- {
- /* Print disk entry */
- PrintDiskData(List,
- DiskIndex);
- }
+ PartEntry->PartInfo[0].BootIndicator = TRUE;
+ PartEntry->PartInfo[0].RewritePartition = TRUE;
+ DiskEntry->Modified = TRUE;
}
+
+ /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
+ List->ActiveBootDisk = DiskEntry;
+ List->ActiveBootPartition = PartEntry;
}
-VOID
-ScrollDownPartitionList(PPARTLIST List)
+BOOLEAN
+CheckForLinuxFdiskPartitions (PPARTLIST List)
{
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry1;
+ PLIST_ENTRY Entry2;
+ ULONG PartitionCount;
ULONG i;
- ULONG j;
- /* 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++)
+ Entry1 = List->DiskListHead.Flink;
+ while (Entry1 != &List->DiskListHead)
{
- if (!List->DiskArray[List->CurrentDisk].PartArray[i].HidePartEntry)
- {
- List->CurrentPartition = i;
- DrawPartitionList(List);
- return;
- }
- }
+ DiskEntry = CONTAINING_RECORD (Entry1,
+ DISKENTRY,
+ ListEntry);
- /* 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++)
+ Entry2 = DiskEntry->PartListHead.Flink;
+ while (Entry2 != &DiskEntry->PartListHead)
{
- if (!List->DiskArray[j].PartArray[i].HidePartEntry)
- {
- List->CurrentDisk = j;
- List->CurrentPartition = i;
- DrawPartitionList(List);
- return;
- }
+ PartEntry = CONTAINING_RECORD (Entry2,
+ PARTENTRY,
+ ListEntry);
+
+ if (PartEntry->Unpartitioned == FALSE)
+ {
+ PartitionCount = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (!IsContainerPartition (PartEntry->PartInfo[i].PartitionType) &&
+ PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
+ {
+ PartitionCount++;
+ }
+ }
+
+ if (PartitionCount > 1)
+ {
+ return TRUE;
+ }
+ }
+
+ Entry2 = Entry2->Flink;
}
+
+ Entry1 = Entry1->Flink;
}
+
+ return FALSE;
}
-VOID
-ScrollUpPartitionList(PPARTLIST List)
+BOOLEAN
+WritePartitionsToDisk (PPARTLIST List)
{
- ULONG i;
- ULONG j;
-
- /* check for available disks */
- if (List->DiskCount == 0)
- return;
+ PDRIVE_LAYOUT_INFORMATION DriveLayout;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK Iosb;
+ WCHAR SrcPath[MAX_PATH];
+ WCHAR DstPath[MAX_PATH];
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ PDISKENTRY DiskEntry;
+ PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry1;
+ PLIST_ENTRY Entry2;
+ ULONG PartitionCount;
+ ULONG DriveLayoutSize;
+ ULONG Index;
+ NTSTATUS Status;
- /* check for previous usable entry on current disk */
- for (i = List->CurrentPartition - 1; i != (ULONG)-1; i--)
+ if (List == NULL)
{
- if (!List->DiskArray[List->CurrentDisk].PartArray[i].HidePartEntry)
- {
- List->CurrentPartition = i;
- DrawPartitionList(List);
- return;
- }
+ return TRUE;
}
- /* check for last usable entry on previous disk */
- for (j = List->CurrentDisk - 1; j != (ULONG)-1; j--)
+ Entry1 = List->DiskListHead.Flink;
+ while (Entry1 != &List->DiskListHead)
{
- for (i = List->DiskArray[j].PartCount - 1; i != (ULONG)-1; i--)
+ DiskEntry = CONTAINING_RECORD (Entry1,
+ DISKENTRY,
+ ListEntry);
+
+ if (DiskEntry->Modified == TRUE)
{
- if (!List->DiskArray[j].PartArray[i].HidePartEntry)
+ /* Count partitioned entries */
+ PartitionCount = 0;
+ Entry2 = DiskEntry->PartListHead.Flink;
+ while (Entry2 != &DiskEntry->PartListHead)
{
- List->CurrentDisk = j;
- List->CurrentPartition = i;
- DrawPartitionList(List);
- return;
+ 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;
+ }
-BOOL
-GetSelectedPartition(PPARTLIST List,
- PPARTDATA Data)
-{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
+ RtlZeroMemory (DriveLayout,
+ DriveLayoutSize);
- if (List->CurrentDisk >= List->DiskCount)
- return(FALSE);
+ DriveLayout->PartitionCount = PartitionCount;
+ if (DiskEntry->Signature == 0)
+ {
+ LARGE_INTEGER SystemTime;
+ TIME_FIELDS TimeFields;
+ PUCHAR Buffer;
- DiskEntry = &List->DiskArray[List->CurrentDisk];
+ NtQuerySystemTime (&SystemTime);
+ RtlTimeToTimeFields (&SystemTime, &TimeFields);
- if (DiskEntry->FixedDisk == FALSE)
- return(FALSE);
+ Buffer = (PUCHAR)&DiskEntry->Signature;
+ Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
+ Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
+ Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
+ Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
- if (List->CurrentPartition >= DiskEntry->PartCount)
- return(FALSE);
+ /* FIXME:
+ * check for an existing signature
+ */
- PartEntry = &DiskEntry->PartArray[List->CurrentPartition];
+ }
- if (PartEntry->Used == FALSE)
- {
- return(FALSE);
- }
+ DriveLayout->Signature = DiskEntry->Signature;
+
+ 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;
+ }
- /* Copy disk-specific data */
- Data->DiskSize = DiskEntry->DiskSize;
- Data->DiskNumber = DiskEntry->DiskNumber;
- Data->Port = DiskEntry->Port;
- Data->Bus = DiskEntry->Bus;
- Data->Id = DiskEntry->Id;
+ Entry2 = Entry2->Flink;
+ }
- /* 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);
- }
- }
+ 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;
+ }
- /* Copy partition-specific data */
- Data->PartSize = PartEntry->PartSize;
- Data->PartNumber = PartEntry->PartNumber;
- Data->PartType = PartEntry->PartType;
- Data->DriveLetter = PartEntry->DriveLetter;
- return(TRUE);
-}
+ 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);
-BOOL
-GetActiveBootPartition(PPARTLIST List,
- PPARTDATA Data)
-{
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- ULONG i;
+ NtClose (FileHandle);
- if (List->CurrentDisk >= List->DiskCount)
- return(FALSE);
+ /* Install MBR code if the disk is new */
+ if (DiskEntry->NewDisk == TRUE)
+ {
+ wcscpy (SrcPath, SourceRootPath.Buffer);
+ wcscat (SrcPath, L"\\loader\\dosmbr.bin");
- DiskEntry = &List->DiskArray[List->CurrentDisk];
+ DPRINT1 ("Install MBR bootcode: %S ==> %S\n",
+ SrcPath, DstPath);
- if (DiskEntry->FixedDisk == FALSE)
- {
- return(FALSE);
- }
+ /* Install MBR bootcode */
+ Status = InstallMbrBootCodeToDisk (SrcPath,
+ DstPath);
+ if (!NT_SUCCESS (Status))
+ {
+ DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
+ Status);
+ return FALSE;
+ }
- for (i = 0; i < DiskEntry->PartCount; i++)
- {
- 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);
+ DiskEntry->NewDisk = FALSE;
}
}
-
- /* Copy partition-specific data */
- Data->PartSize = PartEntry->PartSize;
- Data->PartNumber = PartEntry->PartNumber;
- Data->PartType = PartEntry->PartType;
- Data->DriveLetter = PartEntry->DriveLetter;
-
- return(TRUE);
}
+
+ Entry1 = Entry1->Flink;
}
- return(FALSE);
+ return TRUE;
}
-
-BOOL
-CreateSelectedPartition(PPARTLIST List,
- ULONG PartType,
- ULONGLONG NewPartSize)
+BOOL SetMountedDeviceValues(PPARTLIST List)
{
+ PLIST_ENTRY Entry1, Entry2;
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- ULONG PartEntryNumber;
- OBJECT_ATTRIBUTES ObjectAttributes;
- DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
- IO_STATUS_BLOCK Iosb;
- NTSTATUS Status;
- WCHAR Buffer[MAX_PATH];
- UNICODE_STRING Name;
- HANDLE FileHandle;
- LARGE_INTEGER li;
-
- DiskEntry = &List->DiskArray[List->CurrentDisk];
- PartEntry = &DiskEntry->PartArray[List->CurrentPartition];
- PartEntry->PartType = PartType;
- PartEntryNumber = PartEntry->PartNumber;
-
- DPRINT("NewPartSize %d (%d MB)\n", NewPartSize, NewPartSize / (1024 * 1024));
- DPRINT("PartEntry->StartingOffset %d\n", PartEntry->StartingOffset);
- DPRINT("PartEntry->PartSize %d\n", PartEntry->PartSize);
- DPRINT("PartEntry->PartNumber %d\n", PartEntry->PartNumber);
- DPRINT("PartEntry->PartType 0x%x\n", PartEntry->PartType);
- DPRINT("PartEntry->FileSystemName %s\n", PartEntry->FileSystemName);
-
- swprintf(Buffer,
- L"\\Device\\Harddisk%d\\Partition0",
- DiskEntry->DiskNumber);
- RtlInitUnicodeString(&Name, Buffer);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- 0,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandle,
- 0x10001,
- &ObjectAttributes,
- &Iosb,
- 1,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (NT_SUCCESS(Status))
- {
- LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192);
-
- Status = NtDeviceIoControlFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- IOCTL_DISK_GET_DRIVE_LAYOUT,
- NULL,
- 0,
- LayoutBuffer,
- 8192);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("IOCTL_DISK_GET_DRIVE_LAYOUT failed() 0x%.08x\n", Status);
- NtClose(FileHandle);
- RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
- return FALSE;
- }
- li.QuadPart = PartEntry->StartingOffset;
- LayoutBuffer->PartitionEntry[PartEntryNumber].StartingOffset = li;
- li.QuadPart = NewPartSize;
- LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionLength = li;
- LayoutBuffer->PartitionEntry[PartEntryNumber].HiddenSectors = 0; /* FIXME: ? */
- LayoutBuffer->PartitionEntry[PartEntryNumber].PartitionType = PartType;
- LayoutBuffer->PartitionEntry[PartEntryNumber].RecognizedPartition = TRUE;
- LayoutBuffer->PartitionEntry[PartEntryNumber].RewritePartition = TRUE;
-
- Status = NtDeviceIoControlFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- IOCTL_DISK_SET_DRIVE_LAYOUT,
- LayoutBuffer,
- 8192,
- NULL,
- 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("IOCTL_DISK_SET_DRIVE_LAYOUT failed() 0x%.08x\n", Status);
- NtClose(FileHandle);
- RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
- return FALSE;
- }
- }
- else
+ if (List == NULL)
{
- DPRINT("NtOpenFile failed() 0x%.08x\n", Status);
- NtClose(FileHandle);
- RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
return FALSE;
}
- NtClose(FileHandle);
- RtlFreeHeap(ProcessHeap, 0, LayoutBuffer);
+ Entry1 = List->DiskListHead.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->Unpartitioned && PartEntry->DriveLetter)
+ {
+ if (!SetMountedDeviceValue(PartEntry->DriveLetter, DiskEntry->Signature, PartEntry->PartInfo[0].StartingOffset))
+ {
+ return FALSE;
+ }
+ }
+ Entry2 = Entry2->Flink;
+ }
+ Entry1 = Entry1->Flink;
+ }
return TRUE;
}
+
+
/* EOF */