2002-10-18 20:04:00 +00:00
|
|
|
/*
|
2002-10-29 18:40:02 +00:00
|
|
|
* ReactOS kernel
|
2005-09-15 17:19:31 +00:00
|
|
|
* Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team
|
2002-10-29 18:40:02 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
2009-10-27 10:34:16 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2002-10-29 18:40:02 +00:00
|
|
|
*/
|
2006-11-10 21:00:24 +00:00
|
|
|
/* COPYRIGHT: See COPYING in the top level directory
|
2002-10-29 18:40:02 +00:00
|
|
|
* PROJECT: ReactOS text-mode setup
|
2015-09-13 16:40:36 +00:00
|
|
|
* FILE: base/setup/usetup/partlist.c
|
2002-10-29 18:40:02 +00:00
|
|
|
* PURPOSE: Partition list functions
|
|
|
|
* PROGRAMMER: Eric Kohl
|
2003-04-28 19:44:13 +00:00
|
|
|
* Casper S. Hornstrup (chorns@users.sourceforge.net)
|
2002-10-18 20:04:00 +00:00
|
|
|
*/
|
|
|
|
|
2006-08-31 09:13:03 +00:00
|
|
|
#include "usetup.h"
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-01-13 13:01:38 +00:00
|
|
|
#include <ntddscsi.h>
|
|
|
|
|
2010-06-07 21:38:49 +00:00
|
|
|
#define NDEBUG
|
2003-12-01 18:28:54 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
2015-06-12 21:51:57 +00:00
|
|
|
//#define DUMP_PARTITION_TABLE
|
2014-05-18 15:14:24 +00:00
|
|
|
|
2016-02-27 20:49:17 +00:00
|
|
|
/* HELPERS FOR PARTITION TYPES **********************************************/
|
|
|
|
|
|
|
|
typedef struct _PARTITION_TYPE
|
|
|
|
{
|
|
|
|
UCHAR Type;
|
|
|
|
PCHAR Description;
|
|
|
|
} PARTITION_TYPE, *PPARTITION_TYPE;
|
|
|
|
|
|
|
|
/*
|
2016-02-29 01:22:02 +00:00
|
|
|
* This partition type list was ripped off the kernelDisk.c module from:
|
2016-02-27 20:49:17 +00:00
|
|
|
*
|
|
|
|
* Visopsys Operating System
|
|
|
|
* Copyright (C) 1998-2015 J. Andrew McLaughlin
|
|
|
|
*
|
|
|
|
* 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 the Free
|
|
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* See also https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs
|
|
|
|
* and http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
|
|
|
|
* for a complete list.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* This is a table for keeping known partition type codes and descriptions */
|
|
|
|
static PARTITION_TYPE PartitionTypes[] =
|
|
|
|
{
|
|
|
|
{ 0x00, "(Empty)" },
|
|
|
|
{ 0x01, "FAT12" },
|
|
|
|
{ 0x02, "XENIX root" },
|
|
|
|
{ 0x03, "XENIX /usr" },
|
|
|
|
{ 0x04, "FAT16 (small)" },
|
|
|
|
{ 0x05, "Extended" },
|
|
|
|
{ 0x06, "FAT16" },
|
|
|
|
{ 0x07, "NTFS/HPFS/exFAT" },
|
|
|
|
{ 0x08, "OS/2 or AIX boot" },
|
|
|
|
{ 0x09, "AIX data" },
|
|
|
|
{ 0x0A, "OS/2 Boot Manager" },
|
|
|
|
{ 0x0B, "FAT32" },
|
|
|
|
{ 0x0C, "FAT32 (LBA)" },
|
|
|
|
{ 0x0E, "FAT16 (LBA)" },
|
|
|
|
{ 0x0F, "Extended (LBA)" },
|
|
|
|
{ 0x11, "Hidden FAT12" },
|
|
|
|
{ 0x12, "FAT diagnostic" },
|
|
|
|
{ 0x14, "Hidden FAT16 (small)" },
|
|
|
|
{ 0x16, "Hidden FAT16" },
|
|
|
|
{ 0x17, "Hidden HPFS or NTFS" },
|
|
|
|
{ 0x1B, "Hidden FAT32" },
|
|
|
|
{ 0x1C, "Hidden FAT32 (LBA)" },
|
|
|
|
{ 0x1E, "Hidden FAT16 (LBA)" },
|
|
|
|
{ 0x35, "JFS" },
|
|
|
|
{ 0x39, "Plan 9" },
|
|
|
|
{ 0x3C, "PartitionMagic" },
|
|
|
|
{ 0x3D, "Hidden Netware" },
|
|
|
|
{ 0x41, "PowerPC PReP" },
|
|
|
|
{ 0x42, "Win2K dynamic extended" },
|
|
|
|
{ 0x43, "Old Linux" },
|
|
|
|
{ 0x44, "GoBack" },
|
|
|
|
{ 0x4D, "QNX4.x" },
|
|
|
|
{ 0x4D, "QNX4.x 2nd" },
|
|
|
|
{ 0x4D, "QNX4.x 3rd" },
|
|
|
|
{ 0x50, "Ontrack R/O" },
|
|
|
|
{ 0x51, "Ontrack R/W or Novell" },
|
|
|
|
{ 0x52, "CP/M" },
|
|
|
|
{ 0x63, "GNU HURD or UNIX SysV" },
|
|
|
|
{ 0x64, "Netware 2" },
|
|
|
|
{ 0x65, "Netware 3/4" },
|
|
|
|
{ 0x66, "Netware SMS" },
|
|
|
|
{ 0x67, "Novell" },
|
|
|
|
{ 0x68, "Novell" },
|
|
|
|
{ 0x69, "Netware 5+" },
|
|
|
|
{ 0x7E, "Veritas VxVM public" },
|
|
|
|
{ 0x7F, "Veritas VxVM private" },
|
|
|
|
{ 0x80, "Minix" },
|
|
|
|
{ 0x81, "Linux or Minix" },
|
|
|
|
{ 0x82, "Linux swap or Solaris" },
|
|
|
|
{ 0x83, "Linux" },
|
|
|
|
{ 0x84, "Hibernation" },
|
|
|
|
{ 0x85, "Linux extended" },
|
|
|
|
{ 0x86, "HPFS or NTFS mirrored" },
|
|
|
|
{ 0x87, "HPFS or NTFS mirrored" },
|
|
|
|
{ 0x8E, "Linux LVM" },
|
|
|
|
{ 0x93, "Hidden Linux" },
|
2017-08-19 14:53:54 +00:00
|
|
|
{ 0x96, "CDFS/ISO-9660" },
|
2016-02-27 20:49:17 +00:00
|
|
|
{ 0x9F, "BSD/OS" },
|
|
|
|
{ 0xA0, "Laptop hibernation" },
|
|
|
|
{ 0xA1, "Laptop hibernation" },
|
|
|
|
{ 0xA5, "BSD, NetBSD, FreeBSD" },
|
|
|
|
{ 0xA6, "OpenBSD" },
|
|
|
|
{ 0xA7, "NeXTSTEP" },
|
|
|
|
{ 0xA8, "OS-X UFS" },
|
|
|
|
{ 0xA9, "NetBSD" },
|
|
|
|
{ 0xAB, "OS-X boot" },
|
|
|
|
{ 0xAF, "OS-X HFS" },
|
|
|
|
{ 0xB6, "NT corrupt mirror" },
|
|
|
|
{ 0xB7, "BSDI" },
|
|
|
|
{ 0xB8, "BSDI swap" },
|
|
|
|
{ 0xBE, "Solaris 8 boot" },
|
|
|
|
{ 0xBF, "Solaris x86" },
|
|
|
|
{ 0xC0, "NTFT" },
|
|
|
|
{ 0xC1, "DR-DOS FAT12" },
|
|
|
|
{ 0xC2, "Hidden Linux" },
|
|
|
|
{ 0xC3, "Hidden Linux swap" },
|
|
|
|
{ 0xC4, "DR-DOS FAT16 (small)" },
|
|
|
|
{ 0xC5, "DR-DOS Extended" },
|
|
|
|
{ 0xC6, "DR-DOS FAT16" },
|
|
|
|
{ 0xC7, "HPFS mirrored" },
|
|
|
|
{ 0xCB, "DR-DOS FAT32" },
|
|
|
|
{ 0xCC, "DR-DOS FAT32 (LBA)" },
|
|
|
|
{ 0xCE, "DR-DOS FAT16 (LBA)" },
|
|
|
|
{ 0xD0, "MDOS" },
|
|
|
|
{ 0xD1, "MDOS FAT12" },
|
|
|
|
{ 0xD4, "MDOS FAT16 (small)" },
|
|
|
|
{ 0xD5, "MDOS Extended" },
|
|
|
|
{ 0xD6, "MDOS FAT16" },
|
|
|
|
{ 0xD8, "CP/M-86" },
|
|
|
|
{ 0xDF, "BootIt EMBRM(FAT16/32)" },
|
|
|
|
{ 0xEB, "BeOS BFS" },
|
|
|
|
{ 0xEE, "EFI GPT protective" },
|
|
|
|
{ 0xEF, "EFI filesystem" },
|
|
|
|
{ 0xF0, "Linux/PA-RISC boot" },
|
|
|
|
{ 0xF2, "DOS 3.3+ second" },
|
|
|
|
{ 0xFA, "Bochs" },
|
|
|
|
{ 0xFB, "VmWare" },
|
|
|
|
{ 0xFC, "VmWare swap" },
|
|
|
|
{ 0xFD, "Linux RAID" },
|
|
|
|
{ 0xFE, "NT hidden" },
|
|
|
|
};
|
|
|
|
|
|
|
|
VOID
|
|
|
|
GetPartTypeStringFromPartitionType(
|
|
|
|
UCHAR partitionType,
|
|
|
|
PCHAR strPartType,
|
|
|
|
DWORD cchPartType)
|
|
|
|
{
|
|
|
|
/* Determine partition type */
|
|
|
|
|
|
|
|
if (IsContainerPartition(partitionType))
|
|
|
|
{
|
|
|
|
StringCchCopy(strPartType, cchPartType, MUIGetString(STRING_EXTENDED_PARTITION));
|
|
|
|
}
|
|
|
|
else if (partitionType == PARTITION_ENTRY_UNUSED)
|
|
|
|
{
|
|
|
|
StringCchCopy(strPartType, cchPartType, MUIGetString(STRING_FORMATUNUSED));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UINT i;
|
|
|
|
|
|
|
|
/* Do the table lookup */
|
|
|
|
for (i = 0; i < ARRAYSIZE(PartitionTypes); i++)
|
|
|
|
{
|
|
|
|
if (partitionType == PartitionTypes[i].Type)
|
|
|
|
{
|
|
|
|
StringCchCopy(strPartType, cchPartType, PartitionTypes[i].Description);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We are here because the partition type is unknown */
|
|
|
|
StringCchCopy(strPartType, cchPartType, MUIGetString(STRING_FORMATUNKNOWN));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-29 18:40:02 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
#ifdef DUMP_PARTITION_TABLE
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
DumpPartitionTable(
|
|
|
|
PDISKENTRY DiskEntry)
|
|
|
|
{
|
|
|
|
PPARTITION_INFORMATION PartitionInfo;
|
|
|
|
ULONG i;
|
|
|
|
|
2015-06-20 18:17:03 +00:00
|
|
|
DbgPrint("\n");
|
|
|
|
DbgPrint("Index Start Length Hidden Nr Type Boot RW\n");
|
|
|
|
DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
|
|
|
|
{
|
|
|
|
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
|
2015-06-20 18:17:03 +00:00
|
|
|
DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n",
|
|
|
|
i,
|
|
|
|
PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
|
|
|
|
PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
|
|
|
|
PartitionInfo->HiddenSectors,
|
|
|
|
PartitionInfo->PartitionNumber,
|
|
|
|
PartitionInfo->PartitionType,
|
|
|
|
PartitionInfo->BootIndicator ? '*': ' ',
|
|
|
|
PartitionInfo->RewritePartition ? 'Y': 'N');
|
2014-05-18 15:14:24 +00:00
|
|
|
}
|
2015-06-20 18:17:03 +00:00
|
|
|
|
|
|
|
DbgPrint("\n");
|
2014-05-18 15:14:24 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
ULONGLONG
|
2015-08-09 13:14:00 +00:00
|
|
|
AlignDown(
|
2014-05-18 15:14:24 +00:00
|
|
|
IN ULONGLONG Value,
|
|
|
|
IN ULONG Alignment)
|
|
|
|
{
|
|
|
|
ULONGLONG Temp;
|
|
|
|
|
|
|
|
Temp = Value / Alignment;
|
|
|
|
|
|
|
|
return Temp * Alignment;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-09 13:14:00 +00:00
|
|
|
ULONGLONG
|
|
|
|
AlignUp(
|
|
|
|
IN ULONGLONG Value,
|
|
|
|
IN ULONG Alignment)
|
|
|
|
{
|
|
|
|
ULONGLONG Temp, Result;
|
|
|
|
|
|
|
|
Temp = Value / Alignment;
|
|
|
|
|
|
|
|
Result = Temp * Alignment;
|
|
|
|
if (Value % Alignment)
|
|
|
|
Result += Alignment;
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
ULONGLONG
|
|
|
|
RoundingDivide(
|
|
|
|
IN ULONGLONG Dividend,
|
|
|
|
IN ULONGLONG Divisor)
|
|
|
|
{
|
|
|
|
return (Dividend + Divisor / 2) / Divisor;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
GetDriverName(
|
|
|
|
PDISKENTRY DiskEntry)
|
2003-08-02 16:49:36 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
|
|
|
WCHAR KeyName[32];
|
|
|
|
NTSTATUS Status;
|
2003-08-02 16:49:36 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
RtlInitUnicodeString(&DiskEntry->DriverName,
|
|
|
|
NULL);
|
2003-08-02 16:49:36 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
swprintf(KeyName,
|
2016-05-12 15:30:49 +00:00
|
|
|
L"\\Scsi\\Scsi Port %hu",
|
2014-05-04 22:03:00 +00:00
|
|
|
DiskEntry->Port);
|
2003-08-02 16:49:36 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
RtlZeroMemory(&QueryTable,
|
|
|
|
sizeof(QueryTable));
|
2003-08-02 16:49:36 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
QueryTable[0].Name = L"Driver";
|
|
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
|
|
|
QueryTable[0].EntryContext = &DiskEntry->DriverName;
|
2003-08-02 16:49:36 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
|
|
|
|
KeyName,
|
|
|
|
QueryTable,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
|
|
|
|
}
|
2003-08-02 16:49:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
static
|
|
|
|
VOID
|
2014-05-18 15:14:24 +00:00
|
|
|
AssignDriveLetters(
|
2014-05-04 22:03:00 +00:00
|
|
|
PPARTLIST List)
|
2003-08-09 16:32:26 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
PLIST_ENTRY Entry1;
|
2014-05-18 15:14:24 +00:00
|
|
|
PLIST_ENTRY Entry2;
|
2014-05-04 22:03:00 +00:00
|
|
|
CHAR Letter;
|
2003-08-09 16:32:26 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
Letter = 'C';
|
2003-08-09 16:32:26 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Assign drive letters to primary partitions */
|
|
|
|
Entry1 = List->DiskListHead.Flink;
|
|
|
|
while (Entry1 != &List->DiskListHead)
|
2003-08-09 16:32:26 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
|
2003-08-09 16:32:26 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
Entry2 = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->PrimaryPartListHead)
|
2007-12-30 21:20:54 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
2009-04-09 18:59:28 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry->DriveLetter = 0;
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
if (PartEntry->IsPartitioned &&
|
|
|
|
!IsContainerPartition(PartEntry->PartitionType))
|
2009-04-09 18:59:28 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
if (IsRecognizedPartition(PartEntry->PartitionType) ||
|
|
|
|
(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
|
|
|
|
PartEntry->SectorCount.QuadPart != 0LL))
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
if (Letter <= 'Z')
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry->DriveLetter = Letter;
|
|
|
|
Letter++;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
}
|
2009-04-09 18:59:28 +00:00
|
|
|
}
|
2014-05-18 15:14:24 +00:00
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
2003-08-09 16:32:26 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
Entry1 = Entry1->Flink;
|
|
|
|
}
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Assign drive letters to logical drives */
|
|
|
|
Entry1 = List->DiskListHead.Flink;
|
|
|
|
while (Entry1 != &List->DiskListHead)
|
|
|
|
{
|
|
|
|
DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
|
2003-08-09 16:32:26 +00:00
|
|
|
|
2015-06-13 23:11:57 +00:00
|
|
|
Entry2 = DiskEntry->LogicalPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->LogicalPartListHead)
|
2007-12-30 21:20:54 +00:00
|
|
|
{
|
2015-06-13 23:11:57 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2015-06-13 23:11:57 +00:00
|
|
|
PartEntry->DriveLetter = 0;
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2015-06-13 23:11:57 +00:00
|
|
|
if (PartEntry->IsPartitioned)
|
|
|
|
{
|
|
|
|
if (IsRecognizedPartition(PartEntry->PartitionType) ||
|
|
|
|
(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
|
|
|
|
PartEntry->SectorCount.QuadPart != 0LL))
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2015-06-13 23:11:57 +00:00
|
|
|
if (Letter <= 'Z')
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2015-06-13 23:11:57 +00:00
|
|
|
PartEntry->DriveLetter = Letter;
|
|
|
|
Letter++;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
}
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
2015-06-13 23:11:57 +00:00
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
Entry1 = Entry1->Flink;
|
2003-08-09 16:32:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-15 17:19:31 +00:00
|
|
|
NTSTATUS
|
2006-06-26 14:23:44 +00:00
|
|
|
NTAPI
|
2014-05-04 22:03:00 +00:00
|
|
|
DiskIdentifierQueryRoutine(
|
|
|
|
PWSTR ValueName,
|
|
|
|
ULONG ValueType,
|
|
|
|
PVOID ValueData,
|
|
|
|
ULONG ValueLength,
|
|
|
|
PVOID Context,
|
|
|
|
PVOID EntryContext)
|
2005-09-15 17:19:31 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
|
|
|
|
UNICODE_STRING NameU;
|
|
|
|
|
|
|
|
if (ValueType == REG_SZ &&
|
|
|
|
ValueLength == 20 * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
2005-09-19 20:01:29 +00:00
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2005-09-19 20:01:29 +00:00
|
|
|
NTSTATUS
|
2006-06-26 14:23:44 +00:00
|
|
|
NTAPI
|
2014-05-04 22:03:00 +00:00
|
|
|
DiskConfigurationDataQueryRoutine(
|
|
|
|
PWSTR ValueName,
|
|
|
|
ULONG ValueType,
|
|
|
|
PVOID ValueData,
|
|
|
|
ULONG ValueLength,
|
|
|
|
PVOID Context,
|
|
|
|
PVOID EntryContext)
|
2005-09-19 20:01:29 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
|
|
|
|
PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
|
|
|
|
PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
|
|
|
|
ULONG i;
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
|
|
|
|
ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
|
|
|
|
FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
|
|
|
|
|
|
|
|
/* Hm. Version and Revision are not set on Microsoft Windows XP... */
|
|
|
|
#if 0
|
|
|
|
if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
|
|
|
|
FullResourceDescriptor->PartialResourceList.Revision != 1)
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
#endif
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
|
|
|
|
{
|
|
|
|
if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
|
|
|
|
FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize != sizeof(CM_DISK_GEOMETRY_DEVICE_DATA))
|
|
|
|
continue;
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1];
|
|
|
|
BiosDiskEntry->DiskGeometry = *DiskGeometry;
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
return STATUS_UNSUCCESSFUL;
|
2005-09-15 17:19:31 +00:00
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2005-09-19 20:01:29 +00:00
|
|
|
NTSTATUS
|
2006-06-26 14:23:44 +00:00
|
|
|
NTAPI
|
2014-05-04 22:03:00 +00:00
|
|
|
SystemConfigurationDataQueryRoutine(
|
|
|
|
PWSTR ValueName,
|
|
|
|
ULONG ValueType,
|
|
|
|
PVOID ValueData,
|
|
|
|
ULONG ValueLength,
|
|
|
|
PVOID Context,
|
|
|
|
PVOID EntryContext)
|
2005-09-19 20:01:29 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
|
|
|
|
PCM_INT13_DRIVE_PARAMETER* Int13Drives = (PCM_INT13_DRIVE_PARAMETER*)Context;
|
|
|
|
ULONG i;
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
|
2016-02-29 20:58:32 +00:00
|
|
|
ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
|
2014-05-04 22:03:00 +00:00
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
|
|
|
|
FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
|
|
|
|
|
|
|
|
/* Hm. Version and Revision are not set on Microsoft Windows XP... */
|
|
|
|
#if 0
|
|
|
|
if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
|
|
|
|
FullResourceDescriptor->PartialResourceList.Revision != 1)
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
|
|
|
|
{
|
|
|
|
if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
|
|
|
|
FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
|
|
|
|
continue;
|
|
|
|
|
2016-02-29 20:58:32 +00:00
|
|
|
*Int13Drives = (CM_INT13_DRIVE_PARAMETER*)RtlAllocateHeap(ProcessHeap, 0,
|
|
|
|
FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
|
2014-05-04 22:03:00 +00:00
|
|
|
if (*Int13Drives == NULL)
|
|
|
|
return STATUS_NO_MEMORY;
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
memcpy(*Int13Drives,
|
|
|
|
&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1],
|
|
|
|
FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
2005-09-19 20:01:29 +00:00
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
|
2005-09-15 17:19:31 +00:00
|
|
|
#define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
|
|
|
|
|
2005-11-22 03:18:13 +00:00
|
|
|
static VOID
|
2014-05-04 22:03:00 +00:00
|
|
|
EnumerateBiosDiskEntries(
|
|
|
|
PPARTLIST PartList)
|
2005-09-15 17:19:31 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
|
|
|
|
WCHAR Name[120];
|
|
|
|
ULONG AdapterCount;
|
|
|
|
ULONG DiskCount;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PCM_INT13_DRIVE_PARAMETER Int13Drives;
|
|
|
|
PBIOSDISKENTRY BiosDiskEntry;
|
|
|
|
|
|
|
|
memset(QueryTable, 0, sizeof(QueryTable));
|
|
|
|
|
|
|
|
QueryTable[1].Name = L"Configuration Data";
|
|
|
|
QueryTable[1].QueryRoutine = SystemConfigurationDataQueryRoutine;
|
|
|
|
Int13Drives = NULL;
|
2007-12-30 21:20:54 +00:00
|
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
2014-05-04 22:03:00 +00:00
|
|
|
L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
|
|
|
|
&QueryTable[1],
|
|
|
|
(PVOID)&Int13Drives,
|
2007-12-30 21:20:54 +00:00
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status);
|
|
|
|
return;
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
AdapterCount = 0;
|
|
|
|
while (1)
|
2007-12-30 21:20:54 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
|
2007-12-30 21:20:54 +00:00
|
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
|
|
|
Name,
|
|
|
|
&QueryTable[2],
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2005-09-15 17:19:31 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
break;
|
2005-09-15 17:19:31 +00:00
|
|
|
}
|
2007-01-05 20:19:21 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
|
2007-12-30 21:20:54 +00:00
|
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
|
|
|
Name,
|
|
|
|
&QueryTable[2],
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(Status))
|
2005-09-15 17:19:31 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
while (1)
|
2007-12-30 21:20:54 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
swprintf(Name, L"%s\\%lu\\DiskController\\0", ROOT_NAME, AdapterCount);
|
|
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
|
|
|
Name,
|
|
|
|
&QueryTable[2],
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
RtlFreeHeap(ProcessHeap, 0, Int13Drives);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
swprintf(Name, L"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME, AdapterCount);
|
|
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
|
|
|
Name,
|
|
|
|
&QueryTable[2],
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
QueryTable[0].Name = L"Identifier";
|
|
|
|
QueryTable[0].QueryRoutine = DiskIdentifierQueryRoutine;
|
|
|
|
QueryTable[1].Name = L"Configuration Data";
|
|
|
|
QueryTable[1].QueryRoutine = DiskConfigurationDataQueryRoutine;
|
|
|
|
|
|
|
|
DiskCount = 0;
|
|
|
|
while (1)
|
|
|
|
{
|
2016-02-29 20:58:32 +00:00
|
|
|
BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
|
2014-05-04 22:03:00 +00:00
|
|
|
if (BiosDiskEntry == NULL)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
swprintf(Name, L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, DiskCount);
|
|
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
|
|
|
Name,
|
|
|
|
QueryTable,
|
|
|
|
(PVOID)BiosDiskEntry,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
BiosDiskEntry->DiskNumber = DiskCount;
|
|
|
|
BiosDiskEntry->Recognized = FALSE;
|
|
|
|
|
|
|
|
if (DiskCount < Int13Drives[0].NumberDrives)
|
|
|
|
{
|
|
|
|
BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
InsertTailList(&PartList->BiosDiskListHead, &BiosDiskEntry->ListEntry);
|
|
|
|
|
|
|
|
DPRINT("DiskNumber: %lu\n", BiosDiskEntry->DiskNumber);
|
|
|
|
DPRINT("Signature: %08lx\n", BiosDiskEntry->Signature);
|
|
|
|
DPRINT("Checksum: %08lx\n", BiosDiskEntry->Checksum);
|
|
|
|
DPRINT("BytesPerSector: %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector);
|
|
|
|
DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders);
|
|
|
|
DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads);
|
|
|
|
DPRINT("DriveSelect: %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect);
|
|
|
|
DPRINT("MaxCylinders: %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders);
|
|
|
|
DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
|
|
|
|
DPRINT("MaxHeads: %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
|
|
|
|
DPRINT("NumberDrives: %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
|
|
|
|
|
|
|
|
DiskCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlFreeHeap(ProcessHeap, 0, Int13Drives);
|
|
|
|
return;
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
2005-09-15 17:19:31 +00:00
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
AdapterCount++;
|
2005-09-15 17:19:31 +00:00
|
|
|
}
|
2002-11-13 18:25:18 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
RtlFreeHeap(ProcessHeap, 0, Int13Drives);
|
2002-11-28 19:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
static
|
|
|
|
VOID
|
2014-05-21 20:20:18 +00:00
|
|
|
AddPartitionToDisk(
|
2014-05-04 22:03:00 +00:00
|
|
|
ULONG DiskNumber,
|
2014-05-18 15:14:24 +00:00
|
|
|
PDISKENTRY DiskEntry,
|
2014-05-21 20:20:18 +00:00
|
|
|
ULONG PartitionIndex,
|
2014-05-22 14:55:04 +00:00
|
|
|
BOOLEAN LogicalPartition)
|
2002-10-18 20:04:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PPARTITION_INFORMATION PartitionInfo;
|
|
|
|
PPARTENTRY PartEntry;
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
|
2014-05-22 23:31:39 +00:00
|
|
|
if (PartitionInfo->PartitionType == 0 ||
|
2017-10-01 14:42:04 +00:00
|
|
|
((LogicalPartition != FALSE) && IsContainerPartition(PartitionInfo->PartitionType)))
|
2014-05-21 20:20:18 +00:00
|
|
|
return;
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
|
|
|
if (PartEntry == NULL)
|
2003-08-02 16:49:36 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
return;
|
2003-08-02 16:49:36 +00:00
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-12-27 10:15:32 +00:00
|
|
|
PartEntry->DiskEntry = DiskEntry;
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
|
|
|
|
PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
|
2003-04-05 15:36:34 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry->BootIndicator = PartitionInfo->BootIndicator;
|
|
|
|
PartEntry->PartitionType = PartitionInfo->PartitionType;
|
|
|
|
PartEntry->HiddenSectors = PartitionInfo->HiddenSectors;
|
2003-08-02 16:49:36 +00:00
|
|
|
|
2014-05-22 14:55:04 +00:00
|
|
|
PartEntry->LogicalPartition = LogicalPartition;
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry->IsPartitioned = TRUE;
|
|
|
|
PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
|
|
|
|
PartEntry->PartitionIndex = PartitionIndex;
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
if (IsContainerPartition(PartEntry->PartitionType))
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2015-01-04 13:53:45 +00:00
|
|
|
PartEntry->FormatState = Unformatted;
|
2014-05-22 14:55:04 +00:00
|
|
|
|
|
|
|
if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
|
|
|
|
DiskEntry->ExtendedPartition = PartEntry;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
2014-05-18 15:14:24 +00:00
|
|
|
else if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
|
|
|
|
(PartEntry->PartitionType == PARTITION_FAT_16) ||
|
|
|
|
(PartEntry->PartitionType == PARTITION_HUGE) ||
|
|
|
|
(PartEntry->PartitionType == PARTITION_XINT13) ||
|
|
|
|
(PartEntry->PartitionType == PARTITION_FAT32) ||
|
|
|
|
(PartEntry->PartitionType == PARTITION_FAT32_XINT13))
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
if (CheckFatFormat())
|
|
|
|
{
|
|
|
|
PartEntry->FormatState = Preformatted;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PartEntry->FormatState = Unformatted;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
PartEntry->FormatState = Preformatted;
|
|
|
|
}
|
|
|
|
else if (PartEntry->PartitionType == PARTITION_EXT2)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
if (CheckExt2Format())
|
|
|
|
{
|
|
|
|
PartEntry->FormatState = Preformatted;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PartEntry->FormatState = Unformatted;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
PartEntry->FormatState = Preformatted;
|
|
|
|
}
|
|
|
|
else if (PartEntry->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 = UnknownFormat;
|
|
|
|
}
|
|
|
|
|
2014-05-22 14:55:04 +00:00
|
|
|
if (LogicalPartition)
|
|
|
|
InsertTailList(&DiskEntry->LogicalPartListHead,
|
2014-05-21 20:20:18 +00:00
|
|
|
&PartEntry->ListEntry);
|
|
|
|
else
|
|
|
|
InsertTailList(&DiskEntry->PrimaryPartListHead,
|
|
|
|
&PartEntry->ListEntry);
|
2014-05-18 15:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
ScanForUnpartitionedDiskSpace(
|
|
|
|
PDISKENTRY DiskEntry)
|
|
|
|
{
|
|
|
|
ULONGLONG LastStartSector;
|
|
|
|
ULONGLONG LastSectorCount;
|
|
|
|
ULONGLONG LastUnusedSectorCount;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
PPARTENTRY NewPartEntry;
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
|
2014-11-02 11:30:14 +00:00
|
|
|
DPRINT("ScanForUnpartitionedDiskSpace()\n");
|
2014-05-18 15:14:24 +00:00
|
|
|
|
|
|
|
if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
|
|
|
|
{
|
|
|
|
DPRINT1("No primary partition!\n");
|
|
|
|
|
|
|
|
/* Create a partition table that represents the empty disk */
|
|
|
|
NewPartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
|
|
|
if (NewPartEntry == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
NewPartEntry->DiskEntry = DiskEntry;
|
|
|
|
|
|
|
|
NewPartEntry->IsPartitioned = FALSE;
|
2015-05-29 14:06:01 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment;
|
2015-08-09 13:14:00 +00:00
|
|
|
NewPartEntry->SectorCount.QuadPart = AlignDown(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) -
|
2015-05-29 14:06:01 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart;
|
|
|
|
|
|
|
|
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
|
2014-05-18 15:14:24 +00:00
|
|
|
|
|
|
|
NewPartEntry->FormatState = Unformatted;
|
|
|
|
|
|
|
|
InsertTailList(&DiskEntry->PrimaryPartListHead,
|
|
|
|
&NewPartEntry->ListEntry);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Start partition at head 1, cylinder 0 */
|
2015-05-29 14:06:01 +00:00
|
|
|
LastStartSector = DiskEntry->SectorAlignment;
|
2014-05-18 15:14:24 +00:00
|
|
|
LastSectorCount = 0ULL;
|
|
|
|
LastUnusedSectorCount = 0ULL;
|
|
|
|
|
|
|
|
Entry = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (Entry != &DiskEntry->PrimaryPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
|
|
|
|
|
|
|
|
if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
|
|
|
|
PartEntry->SectorCount.QuadPart != 0ULL)
|
|
|
|
{
|
|
|
|
LastUnusedSectorCount =
|
|
|
|
PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
|
|
|
|
|
|
|
|
if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
|
|
|
|
LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
|
|
|
|
{
|
|
|
|
DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
|
|
|
|
|
|
|
|
NewPartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
|
|
|
if (NewPartEntry == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
NewPartEntry->DiskEntry = DiskEntry;
|
|
|
|
|
|
|
|
NewPartEntry->IsPartitioned = FALSE;
|
|
|
|
NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
|
2015-08-09 13:14:00 +00:00
|
|
|
NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
|
2014-05-18 15:14:24 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart;
|
2015-05-29 14:06:01 +00:00
|
|
|
|
|
|
|
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
|
2014-05-18 15:14:24 +00:00
|
|
|
|
|
|
|
NewPartEntry->FormatState = Unformatted;
|
|
|
|
|
|
|
|
/* Insert the table into the list */
|
|
|
|
InsertTailList(&PartEntry->ListEntry,
|
|
|
|
&NewPartEntry->ListEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
LastStartSector = PartEntry->StartSector.QuadPart;
|
|
|
|
LastSectorCount = PartEntry->SectorCount.QuadPart;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for trailing unpartitioned disk space */
|
|
|
|
if ((LastStartSector + LastSectorCount) < DiskEntry->SectorCount.QuadPart)
|
|
|
|
{
|
2015-08-09 13:14:00 +00:00
|
|
|
LastUnusedSectorCount = AlignDown(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
|
2014-05-18 15:14:24 +00:00
|
|
|
|
|
|
|
if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
|
|
|
|
{
|
|
|
|
DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
|
|
|
|
|
|
|
|
NewPartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
|
|
|
if (NewPartEntry == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
NewPartEntry->DiskEntry = DiskEntry;
|
|
|
|
|
|
|
|
NewPartEntry->IsPartitioned = FALSE;
|
|
|
|
NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
|
2015-08-09 13:14:00 +00:00
|
|
|
NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
|
2014-05-18 15:14:24 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart;
|
2015-05-29 14:06:01 +00:00
|
|
|
|
2014-11-02 11:30:14 +00:00
|
|
|
DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
|
2014-05-18 15:14:24 +00:00
|
|
|
|
|
|
|
NewPartEntry->FormatState = Unformatted;
|
|
|
|
|
|
|
|
/* Append the table to the list */
|
|
|
|
InsertTailList(&DiskEntry->PrimaryPartListHead,
|
|
|
|
&NewPartEntry->ListEntry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-22 23:31:39 +00:00
|
|
|
if (DiskEntry->ExtendedPartition != NULL)
|
|
|
|
{
|
|
|
|
if (IsListEmpty(&DiskEntry->LogicalPartListHead))
|
|
|
|
{
|
|
|
|
DPRINT1("No logical partition!\n");
|
|
|
|
|
|
|
|
/* Create a partition table entry that represents the empty extended partition */
|
|
|
|
NewPartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
|
|
|
if (NewPartEntry == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
NewPartEntry->DiskEntry = DiskEntry;
|
|
|
|
NewPartEntry->LogicalPartition = TRUE;
|
|
|
|
|
|
|
|
NewPartEntry->IsPartitioned = FALSE;
|
2015-05-29 14:06:01 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
|
|
|
|
NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
|
2014-05-22 23:31:39 +00:00
|
|
|
|
|
|
|
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
|
|
|
|
|
|
|
|
NewPartEntry->FormatState = Unformatted;
|
|
|
|
|
|
|
|
InsertTailList(&DiskEntry->LogicalPartListHead,
|
|
|
|
&NewPartEntry->ListEntry);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Start partition at head 1, cylinder 0 */
|
2015-05-29 14:06:01 +00:00
|
|
|
LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
|
2014-05-22 23:31:39 +00:00
|
|
|
LastSectorCount = 0ULL;
|
|
|
|
LastUnusedSectorCount = 0ULL;
|
|
|
|
|
|
|
|
Entry = DiskEntry->LogicalPartListHead.Flink;
|
|
|
|
while (Entry != &DiskEntry->LogicalPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
|
|
|
|
|
|
|
|
if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
|
|
|
|
PartEntry->SectorCount.QuadPart != 0ULL)
|
|
|
|
{
|
|
|
|
LastUnusedSectorCount =
|
2015-05-29 14:06:01 +00:00
|
|
|
PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment - (LastStartSector + LastSectorCount);
|
2014-05-22 23:31:39 +00:00
|
|
|
|
2015-05-29 14:06:01 +00:00
|
|
|
if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (LastStartSector + LastSectorCount) &&
|
2014-05-22 23:31:39 +00:00
|
|
|
LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
|
|
|
|
{
|
|
|
|
DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
|
|
|
|
|
|
|
|
NewPartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
|
|
|
if (NewPartEntry == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
NewPartEntry->DiskEntry = DiskEntry;
|
|
|
|
NewPartEntry->LogicalPartition = TRUE;
|
|
|
|
|
|
|
|
NewPartEntry->IsPartitioned = FALSE;
|
|
|
|
NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
|
2015-08-09 13:14:00 +00:00
|
|
|
NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
|
2014-05-22 23:31:39 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart;
|
2015-05-29 14:06:01 +00:00
|
|
|
|
2014-11-02 11:30:14 +00:00
|
|
|
DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
|
2014-05-22 23:31:39 +00:00
|
|
|
|
|
|
|
NewPartEntry->FormatState = Unformatted;
|
|
|
|
|
|
|
|
/* Insert the table into the list */
|
|
|
|
InsertTailList(&PartEntry->ListEntry,
|
|
|
|
&NewPartEntry->ListEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
LastStartSector = PartEntry->StartSector.QuadPart;
|
|
|
|
LastSectorCount = PartEntry->SectorCount.QuadPart;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for trailing unpartitioned disk space */
|
|
|
|
if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
|
|
|
|
{
|
2015-08-09 13:14:00 +00:00
|
|
|
LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
|
2014-05-22 23:31:39 +00:00
|
|
|
|
|
|
|
if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
|
|
|
|
{
|
|
|
|
DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
|
|
|
|
|
|
|
|
NewPartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
|
|
|
if (NewPartEntry == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
NewPartEntry->DiskEntry = DiskEntry;
|
|
|
|
NewPartEntry->LogicalPartition = TRUE;
|
|
|
|
|
|
|
|
NewPartEntry->IsPartitioned = FALSE;
|
|
|
|
NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
|
2015-08-09 13:14:00 +00:00
|
|
|
NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
|
2014-05-22 23:31:39 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart;
|
2015-05-29 14:06:01 +00:00
|
|
|
|
2014-11-02 11:30:14 +00:00
|
|
|
DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
|
2014-05-22 23:31:39 +00:00
|
|
|
|
|
|
|
NewPartEntry->FormatState = Unformatted;
|
|
|
|
|
|
|
|
/* Append the table to the list */
|
|
|
|
InsertTailList(&DiskEntry->LogicalPartListHead,
|
|
|
|
&NewPartEntry->ListEntry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-02 11:30:14 +00:00
|
|
|
DPRINT("ScanForUnpartitionedDiskSpace() done\n");
|
2014-05-18 15:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
SetDiskSignature(
|
|
|
|
IN PPARTLIST List,
|
|
|
|
IN PDISKENTRY DiskEntry)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER SystemTime;
|
|
|
|
TIME_FIELDS TimeFields;
|
|
|
|
PLIST_ENTRY Entry2;
|
|
|
|
PDISKENTRY DiskEntry2;
|
|
|
|
PUCHAR Buffer;
|
|
|
|
|
|
|
|
Buffer = (PUCHAR)&DiskEntry->LayoutBuffer->Signature;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
NtQuerySystemTime(&SystemTime);
|
|
|
|
RtlTimeToTimeFields(&SystemTime, &TimeFields);
|
|
|
|
|
|
|
|
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 (DiskEntry->LayoutBuffer->Signature == 0)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if the signature already exist */
|
|
|
|
/* FIXME:
|
|
|
|
* Check also signatures from disks, which are
|
|
|
|
* not visible (bootable) by the bios.
|
|
|
|
*/
|
|
|
|
Entry2 = List->DiskListHead.Flink;
|
|
|
|
while (Entry2 != &List->DiskListHead)
|
|
|
|
{
|
|
|
|
DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
|
|
|
|
|
|
|
|
if (DiskEntry != DiskEntry2 &&
|
|
|
|
DiskEntry->LayoutBuffer->Signature == DiskEntry2->LayoutBuffer->Signature)
|
|
|
|
break;
|
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Entry2 == &List->DiskListHead)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
UpdateDiskSignatures(
|
|
|
|
PPARTLIST List)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
|
|
|
|
/* Print partition lines*/
|
|
|
|
Entry = List->DiskListHead.Flink;
|
|
|
|
while (Entry != &List->DiskListHead)
|
|
|
|
{
|
|
|
|
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
|
|
|
|
|
|
|
|
if (DiskEntry->LayoutBuffer &&
|
|
|
|
DiskEntry->LayoutBuffer->Signature == 0)
|
|
|
|
{
|
|
|
|
SetDiskSignature(List, DiskEntry);
|
|
|
|
DiskEntry->LayoutBuffer->PartitionEntry[0].RewritePartition = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
AddDiskToList(
|
|
|
|
HANDLE FileHandle,
|
|
|
|
ULONG DiskNumber,
|
|
|
|
PPARTLIST List)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
ULONG LayoutBufferSize;
|
2015-06-20 17:59:14 +00:00
|
|
|
PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
|
2014-05-18 15:14:24 +00:00
|
|
|
|
|
|
|
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 &&
|
|
|
|
DiskGeometry.MediaType != RemovableMedia)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = NtDeviceIoControlFile(FileHandle,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Iosb,
|
|
|
|
IOCTL_SCSI_GET_ADDRESS,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&ScsiAddress,
|
|
|
|
sizeof(SCSI_ADDRESS));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Mbr = (PARTITION_SECTOR*)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))
|
|
|
|
{
|
2016-02-29 20:58:32 +00:00
|
|
|
RtlFreeHeap(ProcessHeap, 0, Mbr);
|
2014-05-18 15:14:24 +00:00
|
|
|
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;
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
|
|
|
|
DPRINT("Identifier: %S\n", Identifier);
|
2003-08-03 12:20:22 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
DiskEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(DISKENTRY));
|
2014-05-04 22:03:00 +00:00
|
|
|
if (DiskEntry == NULL)
|
2007-12-30 21:20:54 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
// DiskEntry->Checksum = Checksum;
|
|
|
|
// DiskEntry->Signature = Signature;
|
2014-05-04 22:03:00 +00:00
|
|
|
DiskEntry->BiosFound = FALSE;
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Check if this disk has a valid MBR */
|
|
|
|
if (Mbr->BootCode[0] == 0 && Mbr->BootCode[1] == 0)
|
|
|
|
DiskEntry->NoMbr = TRUE;
|
|
|
|
else
|
|
|
|
DiskEntry->NoMbr = FALSE;
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Free Mbr sector buffer */
|
2016-02-29 20:58:32 +00:00
|
|
|
RtlFreeHeap(ProcessHeap, 0, Mbr);
|
2007-01-05 20:19:21 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
ListEntry = List->BiosDiskListHead.Flink;
|
2016-02-29 20:58:32 +00:00
|
|
|
while (ListEntry != &List->BiosDiskListHead)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
|
|
|
BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
|
|
|
|
/* FIXME:
|
|
|
|
* Compare the size from bios and the reported size from driver.
|
|
|
|
* If we have more than one disk with a zero or with the same signatur
|
|
|
|
* we must create new signatures and reboot. After the reboot,
|
|
|
|
* it is possible to identify the disks.
|
|
|
|
*/
|
|
|
|
if (BiosDiskEntry->Signature == Signature &&
|
|
|
|
BiosDiskEntry->Checksum == Checksum &&
|
|
|
|
!BiosDiskEntry->Recognized)
|
|
|
|
{
|
|
|
|
if (!DiskEntry->BiosFound)
|
|
|
|
{
|
|
|
|
DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
|
|
|
|
DiskEntry->BiosFound = TRUE;
|
|
|
|
BiosDiskEntry->Recognized = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ListEntry = ListEntry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!DiskEntry->BiosFound)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
RtlFreeHeap(ProcessHeap, 0, DiskEntry);
|
|
|
|
return;
|
|
|
|
#else
|
|
|
|
DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
InitializeListHead(&DiskEntry->PrimaryPartListHead);
|
2014-05-22 14:55:04 +00:00
|
|
|
InitializeListHead(&DiskEntry->LogicalPartListHead);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
|
|
|
|
DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
|
|
|
|
DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
|
|
|
|
DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
|
2016-05-12 15:30:49 +00:00
|
|
|
DPRINT("TracksPerCylinder %lu\n", DiskEntry->TracksPerCylinder);
|
|
|
|
DPRINT("SectorsPerTrack %lu\n", DiskEntry->SectorsPerTrack);
|
|
|
|
DPRINT("BytesPerSector %lu\n", DiskEntry->BytesPerSector);
|
2014-05-18 15:14:24 +00:00
|
|
|
|
|
|
|
DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
|
|
|
|
(ULONGLONG)DiskGeometry.TracksPerCylinder *
|
|
|
|
(ULONGLONG)DiskGeometry.SectorsPerTrack;
|
|
|
|
|
|
|
|
DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
|
2015-08-09 13:14:00 +00:00
|
|
|
DiskEntry->CylinderAlignment = DiskGeometry.TracksPerCylinder *
|
|
|
|
DiskGeometry.SectorsPerTrack;
|
2014-05-18 15:14:24 +00:00
|
|
|
|
2016-05-12 15:30:49 +00:00
|
|
|
DPRINT("SectorCount %I64u\n", DiskEntry->SectorCount.QuadPart);
|
2014-11-02 11:30:14 +00:00
|
|
|
DPRINT("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
DiskEntry->DiskNumber = DiskNumber;
|
|
|
|
DiskEntry->Port = ScsiAddress.PortNumber;
|
|
|
|
DiskEntry->Bus = ScsiAddress.PathId;
|
|
|
|
DiskEntry->Id = ScsiAddress.TargetId;
|
|
|
|
|
|
|
|
GetDriverName(DiskEntry);
|
2005-09-15 17:19:31 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
|
|
|
|
|
2015-06-13 23:11:57 +00:00
|
|
|
/* Allocate a layout buffer with 4 partition entries first */
|
2014-05-04 22:03:00 +00:00
|
|
|
LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
|
2015-06-13 12:46:42 +00:00
|
|
|
((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
|
2014-05-18 15:14:24 +00:00
|
|
|
DiskEntry->LayoutBuffer = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
LayoutBufferSize);
|
|
|
|
if (DiskEntry->LayoutBuffer == NULL)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2015-06-20 17:59:14 +00:00
|
|
|
DPRINT1("Failed to allocate the disk layout buffer!\n");
|
2014-05-04 22:03:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-20 17:59:14 +00:00
|
|
|
for (;;)
|
2015-06-13 12:46:42 +00:00
|
|
|
{
|
2015-06-20 17:59:14 +00:00
|
|
|
DPRINT1("Buffer size: %lu\n", LayoutBufferSize);
|
2015-06-13 12:46:42 +00:00
|
|
|
Status = NtDeviceIoControlFile(FileHandle,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Iosb,
|
|
|
|
IOCTL_DISK_GET_DRIVE_LAYOUT,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
DiskEntry->LayoutBuffer,
|
|
|
|
LayoutBufferSize);
|
2015-06-20 17:59:14 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (Status != STATUS_BUFFER_TOO_SMALL)
|
|
|
|
{
|
|
|
|
DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION);
|
|
|
|
NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
DiskEntry->LayoutBuffer,
|
|
|
|
LayoutBufferSize);
|
|
|
|
if (NewLayoutBuffer == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to reallocate the disk layout buffer!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DiskEntry->LayoutBuffer = NewLayoutBuffer;
|
2015-06-13 12:46:42 +00:00
|
|
|
}
|
|
|
|
|
2015-06-20 17:59:14 +00:00
|
|
|
DPRINT1("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
#ifdef DUMP_PARTITION_TABLE
|
2015-06-20 17:59:14 +00:00
|
|
|
DumpPartitionTable(DiskEntry);
|
2014-05-18 15:14:24 +00:00
|
|
|
#endif
|
|
|
|
|
2015-06-20 17:59:14 +00:00
|
|
|
if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
|
|
|
|
DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
|
|
|
|
DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != 0)
|
|
|
|
{
|
|
|
|
if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
|
2014-06-07 20:02:26 +00:00
|
|
|
{
|
2015-06-20 17:59:14 +00:00
|
|
|
DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
|
|
|
|
}
|
|
|
|
else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
|
2014-06-07 20:02:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-05 14:55:55 +00:00
|
|
|
DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
|
2014-06-07 20:02:26 +00:00
|
|
|
}
|
2015-06-20 17:59:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-02-29 01:22:02 +00:00
|
|
|
DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
|
2015-06-20 17:59:14 +00:00
|
|
|
}
|
2014-06-07 20:02:26 +00:00
|
|
|
|
|
|
|
|
2015-06-20 17:59:14 +00:00
|
|
|
if (DiskEntry->LayoutBuffer->PartitionCount == 0)
|
|
|
|
{
|
|
|
|
DiskEntry->NewDisk = TRUE;
|
|
|
|
DiskEntry->LayoutBuffer->PartitionCount = 4;
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2015-06-20 17:59:14 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < 4; i++)
|
2014-05-18 15:14:24 +00:00
|
|
|
{
|
2016-02-29 20:58:32 +00:00
|
|
|
AddPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
|
2015-06-20 17:59:14 +00:00
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2015-06-20 17:59:14 +00:00
|
|
|
for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
|
|
|
|
{
|
2016-02-29 20:58:32 +00:00
|
|
|
AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
|
2014-05-18 15:14:24 +00:00
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
ScanForUnpartitionedDiskSpace(DiskEntry);
|
2002-10-18 20:04:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
PPARTLIST
|
|
|
|
CreatePartitionList(
|
|
|
|
SHORT Left,
|
|
|
|
SHORT Top,
|
|
|
|
SHORT Right,
|
|
|
|
SHORT Bottom)
|
2002-10-18 20:04:00 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
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->Offset = 0;
|
|
|
|
|
|
|
|
List->CurrentDisk = NULL;
|
|
|
|
List->CurrentPartition = NULL;
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2016-02-28 15:25:22 +00:00
|
|
|
List->SystemDisk = NULL;
|
|
|
|
List->SystemPartition = NULL;
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
List->OriginalSystemDisk = NULL;
|
|
|
|
List->OriginalSystemPartition = NULL;
|
2015-06-12 21:51:57 +00:00
|
|
|
|
|
|
|
List->TempDisk = NULL;
|
|
|
|
List->TempPartition = NULL;
|
|
|
|
List->FormatState = Start;
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
InitializeListHead(&List->DiskListHead);
|
|
|
|
InitializeListHead(&List->BiosDiskListHead);
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
EnumerateBiosDiskEntries(List);
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
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_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
|
|
|
|
&ObjectAttributes,
|
|
|
|
&Iosb,
|
|
|
|
FILE_SHARE_READ,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
2016-02-29 20:58:32 +00:00
|
|
|
AddDiskToList(FileHandle, DiskNumber, List);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
NtClose(FileHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
UpdateDiskSignatures(List);
|
|
|
|
|
|
|
|
AssignDriveLetters(List);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
if (IsListEmpty(&List->CurrentDisk->PrimaryPartListHead))
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
|
|
|
List->CurrentPartition = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
List->CurrentPartition = CONTAINING_RECORD(List->CurrentDisk->PrimaryPartListHead.Flink,
|
2014-05-04 22:03:00 +00:00
|
|
|
PARTENTRY,
|
|
|
|
ListEntry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return List;
|
2002-10-18 20:04:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
VOID
|
|
|
|
DestroyPartitionList(
|
|
|
|
PPARTLIST List)
|
2002-10-18 20:04:00 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
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);
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Release driver name */
|
|
|
|
RtlFreeUnicodeString(&DiskEntry->DriverName);
|
2002-10-29 18:40:02 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
/* Release primary partition list */
|
|
|
|
while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
Entry = RemoveHeadList(&DiskEntry->PrimaryPartListHead);
|
2014-05-04 22:03:00 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
RtlFreeHeap(ProcessHeap, 0, PartEntry);
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-22 14:55:04 +00:00
|
|
|
/* Release logical partition list */
|
|
|
|
while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
|
2014-05-18 15:14:24 +00:00
|
|
|
{
|
2014-05-22 14:55:04 +00:00
|
|
|
Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
|
|
|
|
|
|
|
|
RtlFreeHeap(ProcessHeap, 0, PartEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release layout buffer */
|
|
|
|
if (DiskEntry->LayoutBuffer != NULL)
|
|
|
|
RtlFreeHeap(ProcessHeap, 0, DiskEntry->LayoutBuffer);
|
|
|
|
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Release disk entry */
|
|
|
|
RtlFreeHeap(ProcessHeap, 0, DiskEntry);
|
|
|
|
}
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2016-02-29 20:58:32 +00:00
|
|
|
/* Release the bios disk info */
|
|
|
|
while (!IsListEmpty(&List->BiosDiskListHead))
|
2007-12-30 21:20:54 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
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;
|
|
|
|
DWORD 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(StdOutput,
|
|
|
|
FOREGROUND_WHITE | BACKGROUND_BLUE,
|
|
|
|
Width,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
' ',
|
|
|
|
Width,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
}
|
|
|
|
|
|
|
|
List->Line++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
PrintPartitionData(
|
|
|
|
PPARTLIST List,
|
|
|
|
PDISKENTRY DiskEntry,
|
2014-05-18 15:14:24 +00:00
|
|
|
PPARTENTRY PartEntry)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
|
|
|
CHAR LineBuffer[128];
|
|
|
|
COORD coPos;
|
|
|
|
DWORD Written;
|
|
|
|
USHORT Width;
|
|
|
|
USHORT Height;
|
|
|
|
LARGE_INTEGER PartSize;
|
|
|
|
PCHAR Unit;
|
|
|
|
UCHAR Attribute;
|
2015-12-06 20:14:29 +00:00
|
|
|
CHAR PartTypeString[32];
|
2014-05-04 22:03:00 +00:00
|
|
|
PCHAR PartType;
|
2015-12-06 20:14:29 +00:00
|
|
|
PartType = PartTypeString;
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
Width = List->Right - List->Left - 1;
|
|
|
|
Height = List->Bottom - List->Top - 2;
|
|
|
|
|
|
|
|
coPos.X = List->Left + 1;
|
|
|
|
coPos.Y = List->Top + 1 + List->Line;
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
if (PartEntry->IsPartitioned == FALSE)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
|
2014-05-04 22:03:00 +00:00
|
|
|
#if 0
|
2014-05-18 15:14:24 +00:00
|
|
|
if (PartSize.QuadPart >= 10737418240) /* 10 GB */
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1073741824);
|
2014-05-04 22:03:00 +00:00
|
|
|
Unit = MUIGetString(STRING_GB);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
2014-05-18 15:14:24 +00:00
|
|
|
if (PartSize.QuadPart >= 10485760) /* 10 MB */
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1048576);
|
2014-05-04 22:03:00 +00:00
|
|
|
Unit = MUIGetString(STRING_MB);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1024);
|
2014-05-04 22:03:00 +00:00
|
|
|
Unit = MUIGetString(STRING_KB);
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(LineBuffer,
|
|
|
|
MUIGetString(STRING_UNPSPACE),
|
2014-05-22 14:55:04 +00:00
|
|
|
PartEntry->LogicalPartition ? " " : "",
|
|
|
|
PartEntry->LogicalPartition ? "" : " ",
|
2014-05-04 22:03:00 +00:00
|
|
|
PartSize.u.LowPart,
|
|
|
|
Unit);
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
|
|
|
else
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
|
|
|
/* Determine partition type */
|
2015-12-06 20:14:29 +00:00
|
|
|
PartTypeString[0] = '\0';
|
2017-10-01 14:42:04 +00:00
|
|
|
if (PartEntry->New != FALSE)
|
2015-01-04 13:53:45 +00:00
|
|
|
{
|
|
|
|
PartType = MUIGetString(STRING_UNFORMATTED);
|
|
|
|
}
|
2017-10-01 14:42:04 +00:00
|
|
|
else if (PartEntry->IsPartitioned != FALSE)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2016-02-27 20:49:17 +00:00
|
|
|
GetPartTypeStringFromPartitionType(PartEntry->PartitionType,
|
|
|
|
PartTypeString,
|
2016-07-12 22:30:55 +00:00
|
|
|
ARRAYSIZE(PartTypeString));
|
2015-12-06 20:14:29 +00:00
|
|
|
PartType = PartTypeString;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
|
2014-05-04 22:03:00 +00:00
|
|
|
#if 0
|
2014-05-18 15:14:24 +00:00
|
|
|
if (PartSize.QuadPart >= 10737418240) /* 10 GB */
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1073741824);
|
2014-05-04 22:03:00 +00:00
|
|
|
Unit = MUIGetString(STRING_GB);
|
|
|
|
}
|
|
|
|
else
|
2003-08-03 12:20:22 +00:00
|
|
|
#endif
|
2014-05-18 15:14:24 +00:00
|
|
|
if (PartSize.QuadPart >= 10485760) /* 10 MB */
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1048576);
|
2014-05-04 22:03:00 +00:00
|
|
|
Unit = MUIGetString(STRING_MB);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1024);
|
2014-05-04 22:03:00 +00:00
|
|
|
Unit = MUIGetString(STRING_KB);
|
|
|
|
}
|
|
|
|
|
2015-12-06 20:14:29 +00:00
|
|
|
if (strcmp(PartType, MUIGetString(STRING_FORMATUNKNOWN)) == 0)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
|
|
|
sprintf(LineBuffer,
|
|
|
|
MUIGetString(STRING_HDDINFOUNK5),
|
2014-05-18 15:14:24 +00:00
|
|
|
(PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
|
|
|
|
(PartEntry->DriveLetter == 0) ? '-' : ':',
|
2014-12-07 22:28:12 +00:00
|
|
|
PartEntry->BootIndicator ? '*' : ' ',
|
2014-05-22 14:55:04 +00:00
|
|
|
PartEntry->LogicalPartition ? " " : "",
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry->PartitionType,
|
2014-05-22 14:55:04 +00:00
|
|
|
PartEntry->LogicalPartition ? "" : " ",
|
2014-05-04 22:03:00 +00:00
|
|
|
PartSize.u.LowPart,
|
|
|
|
Unit);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(LineBuffer,
|
2014-12-07 22:28:12 +00:00
|
|
|
"%c%c %c %s%-24s%s %6lu %s",
|
2014-05-18 15:14:24 +00:00
|
|
|
(PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
|
|
|
|
(PartEntry->DriveLetter == 0) ? '-' : ':',
|
2014-12-07 22:28:12 +00:00
|
|
|
PartEntry->BootIndicator ? '*' : ' ',
|
2014-05-22 14:55:04 +00:00
|
|
|
PartEntry->LogicalPartition ? " " : "",
|
2014-05-04 22:03:00 +00:00
|
|
|
PartType,
|
2014-05-22 14:55:04 +00:00
|
|
|
PartEntry->LogicalPartition ? "" : " ",
|
2014-05-04 22:03:00 +00:00
|
|
|
PartSize.u.LowPart,
|
|
|
|
Unit);
|
|
|
|
}
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
2003-08-03 12:20:22 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
Attribute = (List->CurrentDisk == DiskEntry &&
|
2014-05-18 15:14:24 +00:00
|
|
|
List->CurrentPartition == PartEntry) ?
|
2014-05-04 22:03:00 +00:00
|
|
|
FOREGROUND_BLUE | BACKGROUND_WHITE :
|
|
|
|
FOREGROUND_WHITE | BACKGROUND_BLUE;
|
|
|
|
|
|
|
|
if (List->Line >= 0 && List->Line <= Height)
|
|
|
|
{
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
' ',
|
|
|
|
Width,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
}
|
|
|
|
coPos.X += 4;
|
|
|
|
Width -= 8;
|
|
|
|
if (List->Line >= 0 && List->Line <= Height)
|
|
|
|
{
|
|
|
|
FillConsoleOutputAttribute(StdOutput,
|
|
|
|
Attribute,
|
|
|
|
Width,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
}
|
|
|
|
coPos.X++;
|
|
|
|
Width -= 2;
|
|
|
|
if (List->Line >= 0 && List->Line <= Height)
|
|
|
|
{
|
|
|
|
WriteConsoleOutputCharacterA(StdOutput,
|
|
|
|
LineBuffer,
|
|
|
|
min(strlen(LineBuffer), Width),
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
}
|
|
|
|
|
|
|
|
List->Line++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
PrintDiskData(
|
|
|
|
PPARTLIST List,
|
|
|
|
PDISKENTRY DiskEntry)
|
|
|
|
{
|
2014-05-22 14:55:04 +00:00
|
|
|
PPARTENTRY PrimaryPartEntry, LogicalPartEntry;
|
|
|
|
PLIST_ENTRY PrimaryEntry, LogicalEntry;
|
2014-05-04 22:03:00 +00:00
|
|
|
CHAR LineBuffer[128];
|
|
|
|
COORD coPos;
|
|
|
|
DWORD Written;
|
|
|
|
USHORT Width;
|
|
|
|
USHORT Height;
|
|
|
|
ULARGE_INTEGER 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;
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
DiskSize.QuadPart = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
|
|
|
|
if (DiskSize.QuadPart >= 10737418240) /* 10 GB */
|
2007-12-30 21:20:54 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, 1073741824);
|
2014-05-04 22:03:00 +00:00
|
|
|
Unit = MUIGetString(STRING_GB);
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, 1048576);
|
2014-05-04 22:03:00 +00:00
|
|
|
if (DiskSize.QuadPart == 0)
|
|
|
|
DiskSize.QuadPart = 1;
|
|
|
|
Unit = MUIGetString(STRING_MB);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DiskEntry->DriverName.Length > 0)
|
|
|
|
{
|
|
|
|
sprintf(LineBuffer,
|
|
|
|
MUIGetString(STRING_HDINFOPARTSELECT),
|
|
|
|
DiskSize.u.LowPart,
|
|
|
|
Unit,
|
|
|
|
DiskEntry->DiskNumber,
|
|
|
|
DiskEntry->Port,
|
|
|
|
DiskEntry->Bus,
|
|
|
|
DiskEntry->Id,
|
|
|
|
DiskEntry->DriverName.Buffer);
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
sprintf(LineBuffer,
|
|
|
|
MUIGetString(STRING_HDDINFOUNK6),
|
|
|
|
DiskSize.u.LowPart,
|
|
|
|
Unit,
|
|
|
|
DiskEntry->DiskNumber,
|
|
|
|
DiskEntry->Port,
|
|
|
|
DiskEntry->Bus,
|
|
|
|
DiskEntry->Id);
|
2002-11-02 23:17:06 +00:00
|
|
|
}
|
2002-10-29 18:40:02 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
if (List->Line >= 0 && List->Line <= Height)
|
2007-12-30 21:20:54 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
FillConsoleOutputAttribute(StdOutput,
|
|
|
|
FOREGROUND_WHITE | BACKGROUND_BLUE,
|
|
|
|
Width,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
' ',
|
|
|
|
Width,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
coPos.X++;
|
|
|
|
if (List->Line >= 0 && List->Line <= Height)
|
2007-12-30 21:20:54 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
WriteConsoleOutputCharacterA(StdOutput,
|
|
|
|
LineBuffer,
|
|
|
|
min((USHORT)strlen(LineBuffer), Width - 2),
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
}
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
List->Line++;
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Print separator line */
|
|
|
|
PrintEmptyLine(List);
|
2002-10-29 18:40:02 +00:00
|
|
|
|
2016-02-29 20:58:32 +00:00
|
|
|
/* Print partition lines */
|
2014-05-21 20:20:18 +00:00
|
|
|
PrimaryEntry = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (PrimaryEntry != &DiskEntry->PrimaryPartListHead)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-21 20:20:18 +00:00
|
|
|
PrimaryPartEntry = CONTAINING_RECORD(PrimaryEntry, PARTENTRY, ListEntry);
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PrintPartitionData(List,
|
|
|
|
DiskEntry,
|
2014-05-21 20:20:18 +00:00
|
|
|
PrimaryPartEntry);
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2014-05-21 20:20:18 +00:00
|
|
|
if (IsContainerPartition(PrimaryPartEntry->PartitionType))
|
|
|
|
{
|
2014-05-22 14:55:04 +00:00
|
|
|
LogicalEntry = DiskEntry->LogicalPartListHead.Flink;
|
|
|
|
while (LogicalEntry != &DiskEntry->LogicalPartListHead)
|
2014-05-21 20:20:18 +00:00
|
|
|
{
|
2014-05-22 14:55:04 +00:00
|
|
|
LogicalPartEntry = CONTAINING_RECORD(LogicalEntry, PARTENTRY, ListEntry);
|
2014-05-21 20:20:18 +00:00
|
|
|
|
|
|
|
PrintPartitionData(List,
|
|
|
|
DiskEntry,
|
2014-05-22 14:55:04 +00:00
|
|
|
LogicalPartEntry);
|
2014-05-21 20:20:18 +00:00
|
|
|
|
2014-05-22 14:55:04 +00:00
|
|
|
LogicalEntry = LogicalEntry->Flink;
|
2014-05-21 20:20:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PrimaryEntry = PrimaryEntry->Flink;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Print separator line */
|
|
|
|
PrintEmptyLine(List);
|
2002-10-29 18:40:02 +00:00
|
|
|
}
|
2002-10-18 20:04:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
VOID
|
2014-05-04 22:03:00 +00:00
|
|
|
DrawPartitionList(
|
|
|
|
PPARTLIST List)
|
2002-10-18 20:04:00 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PLIST_ENTRY Entry, Entry2;
|
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry = NULL;
|
|
|
|
COORD coPos;
|
|
|
|
DWORD 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;
|
|
|
|
}
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
Entry2 = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->PrimaryPartListHead)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
|
|
|
if (PartEntry == List->CurrentPartition)
|
|
|
|
{
|
|
|
|
CurrentPartLineFound = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
|
|
|
if (CurrentPartLineFound == FALSE)
|
|
|
|
{
|
|
|
|
CurrentPartLine++;
|
|
|
|
}
|
|
|
|
|
|
|
|
LastLine++;
|
|
|
|
}
|
|
|
|
|
2017-02-27 14:32:09 +00:00
|
|
|
if (CurrentPartLineFound == FALSE)
|
|
|
|
{
|
|
|
|
Entry2 = DiskEntry->LogicalPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->LogicalPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
|
|
|
if (PartEntry == List->CurrentPartition)
|
|
|
|
{
|
|
|
|
CurrentPartLineFound = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
|
|
|
if (CurrentPartLineFound == FALSE)
|
|
|
|
{
|
|
|
|
CurrentPartLine++;
|
|
|
|
}
|
|
|
|
|
|
|
|
LastLine++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
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;
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xDA, // '+',
|
|
|
|
1,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
|
|
|
|
/* draw upper edge */
|
|
|
|
coPos.X = List->Left + 1;
|
|
|
|
coPos.Y = List->Top;
|
|
|
|
if (List->Offset == 0)
|
|
|
|
{
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xC4, // '-',
|
|
|
|
List->Right - List->Left - 1,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
2004-08-21 19:30:12 +00:00
|
|
|
}
|
2007-12-30 21:20:54 +00:00
|
|
|
else
|
2004-08-21 19:30:12 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xC4, // '-',
|
|
|
|
List->Right - List->Left - 5,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
coPos.X = List->Right - 5;
|
|
|
|
WriteConsoleOutputCharacterA(StdOutput,
|
|
|
|
"(\x18)", // "(up)"
|
|
|
|
3,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
coPos.X = List->Right - 2;
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xC4, // '-',
|
|
|
|
2,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* draw upper right corner */
|
|
|
|
coPos.X = List->Right;
|
|
|
|
coPos.Y = List->Top;
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
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;
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xB3, // '|',
|
|
|
|
1,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
|
|
|
|
coPos.X = List->Right;
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xB3, //'|',
|
|
|
|
1,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* draw lower left corner */
|
2007-12-30 21:20:54 +00:00
|
|
|
coPos.X = List->Left;
|
2014-05-04 22:03:00 +00:00
|
|
|
coPos.Y = List->Bottom;
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xC0, // '+',
|
|
|
|
1,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
|
|
|
|
/* draw lower edge */
|
|
|
|
coPos.X = List->Left + 1;
|
|
|
|
coPos.Y = List->Bottom;
|
|
|
|
if (LastLine - List->Offset <= List->Bottom - List->Top - 2)
|
|
|
|
{
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xC4, // '-',
|
|
|
|
List->Right - List->Left - 1,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xC4, // '-',
|
|
|
|
List->Right - List->Left - 5,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
coPos.X = List->Right - 5;
|
|
|
|
WriteConsoleOutputCharacterA(StdOutput,
|
|
|
|
"(\x19)", // "(down)"
|
|
|
|
3,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
coPos.X = List->Right - 2;
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xC4, // '-',
|
|
|
|
2,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
}
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* draw lower right corner */
|
2007-12-30 21:20:54 +00:00
|
|
|
coPos.X = List->Right;
|
2014-05-04 22:03:00 +00:00
|
|
|
coPos.Y = List->Bottom;
|
|
|
|
FillConsoleOutputCharacterA(StdOutput,
|
|
|
|
0xD9, // '+',
|
|
|
|
1,
|
|
|
|
coPos,
|
|
|
|
&Written);
|
|
|
|
|
|
|
|
/* print list entries */
|
|
|
|
List->Line = - List->Offset;
|
|
|
|
|
|
|
|
Entry = List->DiskListHead.Flink;
|
|
|
|
while (Entry != &List->DiskListHead)
|
|
|
|
{
|
|
|
|
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
|
|
|
|
|
|
|
|
/* Print disk entry */
|
|
|
|
PrintDiskData(List,
|
|
|
|
DiskEntry);
|
|
|
|
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
}
|
2002-10-18 20:04:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-26 18:19:23 +00:00
|
|
|
DWORD
|
2014-05-04 22:03:00 +00:00
|
|
|
SelectPartition(
|
|
|
|
PPARTLIST List,
|
|
|
|
ULONG DiskNumber,
|
|
|
|
ULONG PartitionNumber)
|
2003-10-06 19:22:42 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
PLIST_ENTRY Entry1;
|
|
|
|
PLIST_ENTRY Entry2;
|
|
|
|
|
|
|
|
/* Check for empty disks */
|
|
|
|
if (IsListEmpty(&List->DiskListHead))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
Entry2 = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->PrimaryPartListHead)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
if (PartEntry->PartitionNumber == PartitionNumber)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
List->CurrentDisk = DiskEntry;
|
|
|
|
List->CurrentPartition = PartEntry;
|
|
|
|
DrawPartitionList(List);
|
|
|
|
return TRUE;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry1 = Entry1->Flink;
|
|
|
|
}
|
|
|
|
|
2007-08-26 18:19:23 +00:00
|
|
|
return FALSE;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
|
2003-10-06 19:22:42 +00:00
|
|
|
|
2014-06-07 20:02:26 +00:00
|
|
|
BOOL
|
2014-05-04 22:03:00 +00:00
|
|
|
ScrollDownPartitionList(
|
|
|
|
PPARTLIST List)
|
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
PLIST_ENTRY DiskListEntry;
|
|
|
|
PLIST_ENTRY PartListEntry;
|
|
|
|
PDISKENTRY DiskEntry;
|
2014-05-04 22:03:00 +00:00
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
|
2014-06-15 12:02:08 +00:00
|
|
|
/* Fail, if no disks are available */
|
2014-05-04 22:03:00 +00:00
|
|
|
if (IsListEmpty(&List->DiskListHead))
|
2014-06-07 20:02:26 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Check for next usable entry on current disk */
|
|
|
|
if (List->CurrentPartition != NULL)
|
2003-10-06 19:22:42 +00:00
|
|
|
{
|
2014-06-07 20:02:26 +00:00
|
|
|
if (List->CurrentPartition->LogicalPartition)
|
2003-10-06 19:22:42 +00:00
|
|
|
{
|
2014-06-07 20:02:26 +00:00
|
|
|
/* Logical partition */
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-06-15 12:02:08 +00:00
|
|
|
PartListEntry = List->CurrentPartition->ListEntry.Flink;
|
|
|
|
if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
|
2014-06-07 20:02:26 +00:00
|
|
|
{
|
|
|
|
/* Next logical partition */
|
2014-06-15 12:02:08 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
|
2014-06-07 20:02:26 +00:00
|
|
|
|
|
|
|
List->CurrentPartition = PartEntry;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
PartListEntry = List->CurrentDisk->ExtendedPartition->ListEntry.Flink;
|
|
|
|
if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
|
2014-06-07 20:02:26 +00:00
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
|
2014-06-07 20:02:26 +00:00
|
|
|
|
|
|
|
List->CurrentPartition = PartEntry;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Primary or extended partition */
|
|
|
|
|
2017-10-01 14:42:04 +00:00
|
|
|
if ((List->CurrentPartition->IsPartitioned != FALSE) &&
|
2014-10-03 09:24:54 +00:00
|
|
|
IsContainerPartition(List->CurrentPartition->PartitionType))
|
2014-06-07 20:02:26 +00:00
|
|
|
{
|
|
|
|
/* First logical partition */
|
2014-06-15 12:02:08 +00:00
|
|
|
PartListEntry = List->CurrentDisk->LogicalPartListHead.Flink;
|
|
|
|
if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
|
2014-06-07 20:02:26 +00:00
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
|
2014-06-07 20:02:26 +00:00
|
|
|
|
|
|
|
List->CurrentPartition = PartEntry;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Next primary partition */
|
2014-06-15 12:02:08 +00:00
|
|
|
PartListEntry = List->CurrentPartition->ListEntry.Flink;
|
|
|
|
if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
|
2014-06-07 20:02:26 +00:00
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
|
2014-06-07 20:02:26 +00:00
|
|
|
|
|
|
|
List->CurrentPartition = PartEntry;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-15 12:02:08 +00:00
|
|
|
/* Search for the first partition entry on the next disk */
|
|
|
|
DiskListEntry = List->CurrentDisk->ListEntry.Flink;
|
|
|
|
while (DiskListEntry != &List->DiskListHead)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-06-15 12:02:08 +00:00
|
|
|
PartListEntry = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
if (PartListEntry != &DiskEntry->PrimaryPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-06-15 12:02:08 +00:00
|
|
|
List->CurrentDisk = DiskEntry;
|
|
|
|
List->CurrentPartition = PartEntry;
|
|
|
|
return TRUE;
|
2003-10-06 19:22:42 +00:00
|
|
|
}
|
2014-06-15 12:02:08 +00:00
|
|
|
|
|
|
|
DiskListEntry = DiskListEntry->Flink;
|
2003-10-06 19:22:42 +00:00
|
|
|
}
|
2014-06-07 20:02:26 +00:00
|
|
|
|
|
|
|
return FALSE;
|
2003-10-06 19:22:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-07 20:02:26 +00:00
|
|
|
BOOL
|
2014-05-04 22:03:00 +00:00
|
|
|
ScrollUpPartitionList(
|
|
|
|
PPARTLIST List)
|
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
PLIST_ENTRY DiskListEntry;
|
|
|
|
PLIST_ENTRY PartListEntry;
|
|
|
|
PDISKENTRY DiskEntry;
|
2014-05-04 22:03:00 +00:00
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
|
2014-06-15 12:02:08 +00:00
|
|
|
/* Fail, if no disks are available */
|
2014-05-04 22:03:00 +00:00
|
|
|
if (IsListEmpty(&List->DiskListHead))
|
2014-06-07 20:02:26 +00:00
|
|
|
return FALSE;
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-06-07 20:02:26 +00:00
|
|
|
/* Check for previous usable entry on current disk */
|
2014-05-04 22:03:00 +00:00
|
|
|
if (List->CurrentPartition != NULL)
|
|
|
|
{
|
2014-06-07 20:02:26 +00:00
|
|
|
if (List->CurrentPartition->LogicalPartition)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-06-07 20:02:26 +00:00
|
|
|
/* Logical partition */
|
2014-06-15 12:02:08 +00:00
|
|
|
PartListEntry = List->CurrentPartition->ListEntry.Blink;
|
|
|
|
if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
|
2014-06-07 20:02:26 +00:00
|
|
|
{
|
|
|
|
/* Previous logical partition */
|
2014-06-15 12:02:08 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
|
2014-06-07 20:02:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Extended partition*/
|
|
|
|
PartEntry = List->CurrentDisk->ExtendedPartition;
|
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
List->CurrentPartition = PartEntry;
|
2014-06-07 20:02:26 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Primary or extended partition */
|
|
|
|
|
2014-06-15 12:02:08 +00:00
|
|
|
PartListEntry = List->CurrentPartition->ListEntry.Blink;
|
|
|
|
if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
|
2014-06-07 20:02:26 +00:00
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
|
2014-06-07 20:02:26 +00:00
|
|
|
|
2017-10-01 14:42:04 +00:00
|
|
|
if ((PartEntry->IsPartitioned != FALSE) &&
|
2014-10-03 09:24:54 +00:00
|
|
|
IsContainerPartition(PartEntry->PartitionType))
|
2014-06-07 20:02:26 +00:00
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
PartListEntry = List->CurrentDisk->LogicalPartListHead.Blink;
|
|
|
|
PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
|
2014-06-07 20:02:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
List->CurrentPartition = PartEntry;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-15 12:02:08 +00:00
|
|
|
/* Search for the last partition entry on the previous disk */
|
|
|
|
DiskListEntry = List->CurrentDisk->ListEntry.Blink;
|
|
|
|
while (DiskListEntry != &List->DiskListHead)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
|
|
|
|
|
|
|
|
PartListEntry = DiskEntry->PrimaryPartListHead.Blink;
|
|
|
|
if (PartListEntry != &DiskEntry->PrimaryPartListHead)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2017-10-01 14:42:04 +00:00
|
|
|
if ((PartEntry->IsPartitioned != FALSE) &&
|
2014-10-03 09:24:54 +00:00
|
|
|
IsContainerPartition(PartEntry->PartitionType))
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-06-15 12:02:08 +00:00
|
|
|
PartListEntry = DiskEntry->LogicalPartListHead.Blink;
|
|
|
|
if (PartListEntry != &DiskEntry->LogicalPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-06-15 12:02:08 +00:00
|
|
|
List->CurrentDisk = DiskEntry;
|
|
|
|
List->CurrentPartition = PartEntry;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
List->CurrentDisk = DiskEntry;
|
|
|
|
List->CurrentPartition = PartEntry;
|
2014-06-15 12:02:08 +00:00
|
|
|
return TRUE;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-15 12:02:08 +00:00
|
|
|
|
|
|
|
DiskListEntry = DiskListEntry->Blink;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
2014-06-07 20:02:26 +00:00
|
|
|
|
|
|
|
return FALSE;
|
2014-05-18 15:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
BOOLEAN
|
|
|
|
IsEmptyLayoutEntry(
|
|
|
|
PPARTITION_INFORMATION PartitionInfo)
|
|
|
|
{
|
|
|
|
if (PartitionInfo->StartingOffset.QuadPart == 0 &&
|
|
|
|
PartitionInfo->PartitionLength.QuadPart == 0)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
BOOLEAN
|
|
|
|
IsSamePrimaryLayoutEntry(
|
|
|
|
IN PPARTITION_INFORMATION PartitionInfo,
|
|
|
|
IN PDISKENTRY DiskEntry,
|
|
|
|
IN PPARTENTRY PartEntry)
|
|
|
|
{
|
|
|
|
if (PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector &&
|
|
|
|
PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector)
|
|
|
|
// PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
|
|
|
|
// PartitionInfo->PartitionType == PartEntry->PartitionType
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-21 20:18:23 +00:00
|
|
|
static
|
|
|
|
ULONG
|
|
|
|
GetPrimaryPartitionCount(
|
|
|
|
IN PDISKENTRY DiskEntry)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
ULONG Count = 0;
|
|
|
|
|
|
|
|
Entry = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (Entry != &DiskEntry->PrimaryPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
|
|
|
|
if (PartEntry->IsPartitioned == TRUE)
|
|
|
|
Count++;
|
|
|
|
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
ULONG
|
|
|
|
GetLogicalPartitionCount(
|
|
|
|
PDISKENTRY DiskEntry)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY ListEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
ULONG Count = 0;
|
|
|
|
|
|
|
|
ListEntry = DiskEntry->LogicalPartListHead.Flink;
|
|
|
|
while (ListEntry != &DiskEntry->LogicalPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
|
|
|
|
if (PartEntry->IsPartitioned)
|
|
|
|
Count++;
|
|
|
|
|
|
|
|
ListEntry = ListEntry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
BOOL
|
|
|
|
ReAllocateLayoutBuffer(
|
|
|
|
PDISKENTRY DiskEntry)
|
|
|
|
{
|
|
|
|
PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
|
|
|
|
ULONG NewPartitionCount;
|
|
|
|
ULONG CurrentPartitionCount = 0;
|
|
|
|
ULONG LayoutBufferSize;
|
2015-06-24 20:06:33 +00:00
|
|
|
ULONG i;
|
2015-06-21 20:18:23 +00:00
|
|
|
|
|
|
|
DPRINT1("ReAllocateLayoutBuffer()\n");
|
|
|
|
|
|
|
|
NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
|
|
|
|
|
|
|
|
if (DiskEntry->LayoutBuffer)
|
|
|
|
CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
|
|
|
|
|
|
|
|
DPRINT1("CurrentPartitionCount: %lu NewPartitionCount: %lu\n",
|
|
|
|
CurrentPartitionCount, NewPartitionCount);
|
|
|
|
|
|
|
|
if (CurrentPartitionCount == NewPartitionCount)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
|
|
|
|
((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
|
|
|
|
NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
DiskEntry->LayoutBuffer,
|
|
|
|
LayoutBufferSize);
|
|
|
|
if (NewLayoutBuffer == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2015-06-24 20:06:33 +00:00
|
|
|
/* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
|
|
|
|
if (NewPartitionCount > CurrentPartitionCount)
|
|
|
|
{
|
|
|
|
for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
|
|
|
|
NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
|
|
|
|
}
|
|
|
|
|
2015-06-21 20:18:23 +00:00
|
|
|
DiskEntry->LayoutBuffer = NewLayoutBuffer;
|
|
|
|
DiskEntry->LayoutBuffer->PartitionCount = NewPartitionCount;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
static
|
2014-05-18 15:14:24 +00:00
|
|
|
VOID
|
|
|
|
UpdateDiskLayout(
|
|
|
|
IN PDISKENTRY DiskEntry)
|
2002-10-18 20:04:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PPARTITION_INFORMATION PartitionInfo;
|
2015-06-24 20:06:33 +00:00
|
|
|
PPARTITION_INFORMATION LinkInfo = NULL;
|
2014-05-18 15:14:24 +00:00
|
|
|
PLIST_ENTRY ListEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
2015-07-04 16:10:50 +00:00
|
|
|
LARGE_INTEGER HiddenSectors64;
|
2015-06-21 20:18:23 +00:00
|
|
|
ULONG Index;
|
2014-05-18 15:14:24 +00:00
|
|
|
ULONG PartitionNumber = 1;
|
2009-04-09 12:42:09 +00:00
|
|
|
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("UpdateDiskLayout()\n");
|
2009-04-09 12:42:09 +00:00
|
|
|
|
2015-06-21 20:18:23 +00:00
|
|
|
/* Resize the layout buffer if necessary */
|
|
|
|
if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
|
|
|
|
{
|
|
|
|
DPRINT("ReAllocateLayoutBuffer() failed.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the primary partition table */
|
|
|
|
Index = 0;
|
2014-05-18 15:14:24 +00:00
|
|
|
ListEntry = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (ListEntry != &DiskEntry->PrimaryPartListHead)
|
2002-10-18 20:04:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
|
2002-10-18 20:04:00 +00:00
|
|
|
|
2017-10-01 14:42:04 +00:00
|
|
|
if (PartEntry->IsPartitioned != FALSE)
|
2014-05-18 15:14:24 +00:00
|
|
|
{
|
|
|
|
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
|
2003-08-03 12:20:22 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
|
|
|
|
{
|
2015-06-21 20:18:23 +00:00
|
|
|
DPRINT1("Updating primary partition entry %lu\n", Index);
|
2015-05-29 14:06:01 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
|
|
|
|
PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
|
2015-07-04 16:10:50 +00:00
|
|
|
PartitionInfo->HiddenSectors = PartEntry->StartSector.LowPart;
|
2014-05-18 15:14:24 +00:00
|
|
|
PartitionInfo->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
|
|
|
|
PartitionInfo->PartitionType = PartEntry->PartitionType;
|
|
|
|
PartitionInfo->BootIndicator = PartEntry->BootIndicator;
|
|
|
|
PartitionInfo->RecognizedPartition = FALSE;
|
|
|
|
PartitionInfo->RewritePartition = TRUE;
|
|
|
|
}
|
2015-06-21 08:55:43 +00:00
|
|
|
|
2015-06-21 20:18:23 +00:00
|
|
|
PartEntry->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
|
|
|
|
PartEntry->PartitionIndex = Index;
|
|
|
|
|
2015-06-21 08:55:43 +00:00
|
|
|
if (!IsContainerPartition(PartEntry->PartitionType))
|
2014-05-18 15:14:24 +00:00
|
|
|
PartitionNumber++;
|
2003-08-03 12:20:22 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
Index++;
|
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
ListEntry = ListEntry->Flink;
|
|
|
|
}
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2015-06-21 20:18:23 +00:00
|
|
|
/* Update the logical partition tables */
|
|
|
|
Index = 4;
|
|
|
|
ListEntry = DiskEntry->LogicalPartListHead.Flink;
|
|
|
|
while (ListEntry != &DiskEntry->LogicalPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
|
|
|
|
|
|
|
|
if (PartEntry->IsPartitioned)
|
|
|
|
{
|
|
|
|
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
|
|
|
|
|
|
|
|
DPRINT1("Updating logical partition entry %lu\n", Index);
|
|
|
|
|
|
|
|
PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
|
|
|
|
PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
|
|
|
|
PartitionInfo->HiddenSectors = DiskEntry->SectorAlignment;
|
|
|
|
PartitionInfo->PartitionNumber = PartitionNumber;
|
|
|
|
PartitionInfo->PartitionType = PartEntry->PartitionType;
|
|
|
|
PartitionInfo->BootIndicator = FALSE;
|
|
|
|
PartitionInfo->RecognizedPartition = FALSE;
|
|
|
|
PartitionInfo->RewritePartition = TRUE;
|
|
|
|
|
|
|
|
PartEntry->PartitionNumber = PartitionNumber;
|
|
|
|
PartEntry->PartitionIndex = Index;
|
|
|
|
|
2015-06-24 20:06:33 +00:00
|
|
|
/* Fill the link entry of the previous partition table */
|
|
|
|
if (LinkInfo != NULL)
|
|
|
|
{
|
|
|
|
LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
|
|
|
|
LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
|
2015-07-04 16:10:50 +00:00
|
|
|
HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart;
|
|
|
|
LinkInfo->HiddenSectors = HiddenSectors64.LowPart;
|
2015-06-24 20:06:33 +00:00
|
|
|
LinkInfo->PartitionNumber = 0;
|
|
|
|
LinkInfo->PartitionType = PARTITION_EXTENDED;
|
|
|
|
LinkInfo->BootIndicator = FALSE;
|
|
|
|
LinkInfo->RecognizedPartition = FALSE;
|
|
|
|
LinkInfo->RewritePartition = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save a pointer to the link entry of the current partition table */
|
|
|
|
LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
|
|
|
|
|
2015-06-21 20:18:23 +00:00
|
|
|
PartitionNumber++;
|
|
|
|
Index += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
ListEntry = ListEntry->Flink;
|
|
|
|
}
|
|
|
|
|
2015-06-24 20:06:33 +00:00
|
|
|
/* Wipe unused primary partition table entries */
|
|
|
|
for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2015-06-24 20:06:33 +00:00
|
|
|
DPRINT1("Primary partition entry %lu\n", Index);
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
if (!IsEmptyLayoutEntry(PartitionInfo))
|
|
|
|
{
|
2015-06-24 20:06:33 +00:00
|
|
|
DPRINT1("Wiping primary partition entry %lu\n", Index);
|
2015-05-29 14:06:01 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PartitionInfo->StartingOffset.QuadPart = 0;
|
|
|
|
PartitionInfo->PartitionLength.QuadPart = 0;
|
|
|
|
PartitionInfo->HiddenSectors = 0;
|
|
|
|
PartitionInfo->PartitionNumber = 0;
|
2015-06-24 20:06:33 +00:00
|
|
|
PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
|
2014-05-18 15:14:24 +00:00
|
|
|
PartitionInfo->BootIndicator = FALSE;
|
|
|
|
PartitionInfo->RecognizedPartition = FALSE;
|
|
|
|
PartitionInfo->RewritePartition = TRUE;
|
|
|
|
}
|
2002-10-18 20:04:00 +00:00
|
|
|
}
|
2015-06-24 20:06:33 +00:00
|
|
|
|
|
|
|
/* Wipe unused logical partition table entries */
|
|
|
|
for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++)
|
|
|
|
{
|
|
|
|
if (Index % 4 >= 2)
|
|
|
|
{
|
|
|
|
DPRINT1("Logical partition entry %lu\n", Index);
|
|
|
|
|
|
|
|
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
|
|
|
|
|
|
|
|
if (!IsEmptyLayoutEntry(PartitionInfo))
|
|
|
|
{
|
|
|
|
DPRINT1("Wiping partition entry %lu\n", Index);
|
|
|
|
|
|
|
|
PartitionInfo->StartingOffset.QuadPart = 0;
|
|
|
|
PartitionInfo->PartitionLength.QuadPart = 0;
|
|
|
|
PartitionInfo->HiddenSectors = 0;
|
|
|
|
PartitionInfo->PartitionNumber = 0;
|
|
|
|
PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
|
|
|
|
PartitionInfo->BootIndicator = FALSE;
|
|
|
|
PartitionInfo->RecognizedPartition = FALSE;
|
|
|
|
PartitionInfo->RewritePartition = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
#ifdef DUMP_PARTITION_TABLE
|
|
|
|
DumpPartitionTable(DiskEntry);
|
|
|
|
#endif
|
2002-10-18 20:04:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
static
|
|
|
|
PPARTENTRY
|
|
|
|
GetPrevUnpartitionedEntry(
|
|
|
|
PDISKENTRY DiskEntry,
|
|
|
|
PPARTENTRY PartEntry)
|
2002-10-18 20:04:00 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PPARTENTRY PrevPartEntry;
|
2015-06-20 13:42:39 +00:00
|
|
|
PLIST_ENTRY ListHead;
|
2009-04-09 12:42:09 +00:00
|
|
|
|
2015-06-20 13:42:39 +00:00
|
|
|
if (PartEntry->LogicalPartition)
|
|
|
|
ListHead = &DiskEntry->LogicalPartListHead;
|
|
|
|
else
|
|
|
|
ListHead = &DiskEntry->PrimaryPartListHead;
|
|
|
|
|
|
|
|
if (PartEntry->ListEntry.Blink != ListHead)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
|
|
|
PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
|
|
|
|
PARTENTRY,
|
|
|
|
ListEntry);
|
2014-05-18 15:14:24 +00:00
|
|
|
if (PrevPartEntry->IsPartitioned == FALSE)
|
2014-05-04 22:03:00 +00:00
|
|
|
return PrevPartEntry;
|
2009-04-09 12:42:09 +00:00
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-04-09 12:42:09 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
static
|
|
|
|
PPARTENTRY
|
|
|
|
GetNextUnpartitionedEntry(
|
|
|
|
PDISKENTRY DiskEntry,
|
|
|
|
PPARTENTRY PartEntry)
|
|
|
|
{
|
|
|
|
PPARTENTRY NextPartEntry;
|
2015-06-20 13:42:39 +00:00
|
|
|
PLIST_ENTRY ListHead;
|
|
|
|
|
|
|
|
if (PartEntry->LogicalPartition)
|
|
|
|
ListHead = &DiskEntry->LogicalPartListHead;
|
|
|
|
else
|
|
|
|
ListHead = &DiskEntry->PrimaryPartListHead;
|
2003-08-03 12:20:22 +00:00
|
|
|
|
2015-06-20 13:42:39 +00:00
|
|
|
if (PartEntry->ListEntry.Flink != ListHead)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
|
|
|
NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
|
|
|
|
PARTENTRY,
|
|
|
|
ListEntry);
|
2014-05-18 15:14:24 +00:00
|
|
|
if (NextPartEntry->IsPartitioned == FALSE)
|
2014-05-04 22:03:00 +00:00
|
|
|
return NextPartEntry;
|
|
|
|
}
|
2009-04-09 12:42:09 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2009-04-09 12:42:09 +00:00
|
|
|
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
VOID
|
2014-05-20 23:48:36 +00:00
|
|
|
CreatePrimaryPartition(
|
2014-05-04 22:03:00 +00:00
|
|
|
PPARTLIST List,
|
2014-05-18 15:14:24 +00:00
|
|
|
ULONGLONG SectorCount,
|
2014-05-04 22:03:00 +00:00
|
|
|
BOOLEAN AutoCreate)
|
|
|
|
{
|
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
PPARTENTRY NewPartEntry;
|
|
|
|
|
2014-05-20 23:48:36 +00:00
|
|
|
DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount);
|
2014-05-18 15:14:24 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
if (List == NULL ||
|
|
|
|
List->CurrentDisk == NULL ||
|
|
|
|
List->CurrentPartition == NULL ||
|
2017-10-01 14:42:04 +00:00
|
|
|
List->CurrentPartition->IsPartitioned != FALSE)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2007-12-30 21:20:54 +00:00
|
|
|
return;
|
2002-10-18 20:04:00 +00:00
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
DiskEntry = List->CurrentDisk;
|
|
|
|
PartEntry = List->CurrentPartition;
|
2003-08-03 12:20:22 +00:00
|
|
|
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
|
2014-05-18 15:14:24 +00:00
|
|
|
|
2017-10-01 14:42:04 +00:00
|
|
|
if ((AutoCreate != FALSE) ||
|
|
|
|
(AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart))
|
2002-10-18 20:04:00 +00:00
|
|
|
{
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("Convert existing partition entry\n");
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Convert current entry to 'new (unformatted)' */
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry->IsPartitioned = TRUE;
|
|
|
|
PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
|
2014-05-04 22:03:00 +00:00
|
|
|
PartEntry->FormatState = Unformatted;
|
|
|
|
PartEntry->AutoCreate = AutoCreate;
|
2015-01-04 13:53:45 +00:00
|
|
|
PartEntry->New = TRUE;
|
2014-12-07 22:28:12 +00:00
|
|
|
PartEntry->BootIndicator = FALSE;
|
2014-05-18 15:14:24 +00:00
|
|
|
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("Add new partition entry\n");
|
2014-05-18 15:14:24 +00:00
|
|
|
|
|
|
|
/* Insert and initialize a new partition entry */
|
|
|
|
NewPartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
2014-05-04 22:03:00 +00:00
|
|
|
if (NewPartEntry == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Insert the new entry into the list */
|
|
|
|
InsertTailList(&PartEntry->ListEntry,
|
|
|
|
&NewPartEntry->ListEntry);
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
NewPartEntry->DiskEntry = DiskEntry;
|
2003-08-12 15:56:21 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
NewPartEntry->IsPartitioned = TRUE;
|
|
|
|
NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
|
2015-08-09 13:14:00 +00:00
|
|
|
NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
|
2014-05-18 15:14:24 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart;
|
|
|
|
NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
|
2003-08-12 15:56:21 +00:00
|
|
|
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
|
2003-08-12 15:56:21 +00:00
|
|
|
|
2015-01-04 13:53:45 +00:00
|
|
|
NewPartEntry->New = TRUE;
|
2014-05-18 15:14:24 +00:00
|
|
|
NewPartEntry->FormatState = Unformatted;
|
2014-12-07 22:28:12 +00:00
|
|
|
NewPartEntry->BootIndicator = FALSE;
|
2003-08-12 15:56:21 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
|
|
|
|
PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
2003-08-12 15:56:21 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
UpdateDiskLayout(DiskEntry);
|
|
|
|
|
|
|
|
DiskEntry->Dirty = TRUE;
|
2003-08-12 15:56:21 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
AssignDriveLetters(List);
|
2003-08-12 15:56:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-22 14:55:04 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
AddLogicalDiskSpace(
|
|
|
|
PDISKENTRY DiskEntry)
|
|
|
|
{
|
|
|
|
PPARTENTRY NewPartEntry;
|
|
|
|
|
|
|
|
DPRINT1("AddLogicalDiskSpace()\n");
|
|
|
|
|
|
|
|
/* Create a partition table entry that represents the empty space in the container partition */
|
|
|
|
NewPartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
|
|
|
if (NewPartEntry == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
NewPartEntry->DiskEntry = DiskEntry;
|
|
|
|
NewPartEntry->LogicalPartition = TRUE;
|
|
|
|
|
|
|
|
NewPartEntry->IsPartitioned = FALSE;
|
2015-05-29 14:06:01 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
|
|
|
|
NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
|
2014-05-22 14:55:04 +00:00
|
|
|
|
|
|
|
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
|
|
|
|
|
|
|
|
NewPartEntry->FormatState = Unformatted;
|
|
|
|
|
|
|
|
InsertTailList(&DiskEntry->LogicalPartListHead,
|
|
|
|
&NewPartEntry->ListEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-20 23:48:36 +00:00
|
|
|
VOID
|
|
|
|
CreateExtendedPartition(
|
|
|
|
PPARTLIST List,
|
|
|
|
ULONGLONG SectorCount)
|
|
|
|
{
|
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
PPARTENTRY NewPartEntry;
|
|
|
|
|
2014-05-22 14:55:04 +00:00
|
|
|
DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount);
|
2014-05-20 23:48:36 +00:00
|
|
|
|
|
|
|
if (List == NULL ||
|
|
|
|
List->CurrentDisk == NULL ||
|
|
|
|
List->CurrentPartition == NULL ||
|
2017-10-01 14:42:04 +00:00
|
|
|
(List->CurrentPartition->IsPartitioned != FALSE))
|
2014-05-20 23:48:36 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DiskEntry = List->CurrentDisk;
|
|
|
|
PartEntry = List->CurrentPartition;
|
|
|
|
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
|
2014-05-20 23:48:36 +00:00
|
|
|
|
2015-08-09 13:14:00 +00:00
|
|
|
if (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
|
2014-05-20 23:48:36 +00:00
|
|
|
{
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("Convert existing partition entry\n");
|
|
|
|
|
2014-05-20 23:48:36 +00:00
|
|
|
/* Convert current entry to 'new (unformatted)' */
|
|
|
|
PartEntry->IsPartitioned = TRUE;
|
|
|
|
PartEntry->FormatState = Formatted;
|
|
|
|
PartEntry->AutoCreate = FALSE;
|
2015-01-04 13:53:45 +00:00
|
|
|
PartEntry->New = FALSE;
|
2014-12-07 22:28:12 +00:00
|
|
|
PartEntry->BootIndicator = FALSE;
|
2014-05-20 23:48:36 +00:00
|
|
|
|
2014-05-22 14:55:04 +00:00
|
|
|
if (PartEntry->StartSector.QuadPart < 1450560)
|
|
|
|
{
|
|
|
|
/* Partition starts below the 8.4GB boundary ==> CHS partition */
|
|
|
|
PartEntry->PartitionType = PARTITION_EXTENDED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Partition starts above the 8.4GB boundary ==> LBA partition */
|
|
|
|
PartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
|
|
|
|
}
|
|
|
|
|
|
|
|
DiskEntry->ExtendedPartition = PartEntry;
|
|
|
|
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
|
2014-05-20 23:48:36 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("Add new partition entry\n");
|
2014-05-20 23:48:36 +00:00
|
|
|
|
|
|
|
/* Insert and initialize a new partition entry */
|
|
|
|
NewPartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
|
|
|
if (NewPartEntry == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Insert the new entry into the list */
|
|
|
|
InsertTailList(&PartEntry->ListEntry,
|
|
|
|
&NewPartEntry->ListEntry);
|
|
|
|
|
|
|
|
NewPartEntry->DiskEntry = DiskEntry;
|
|
|
|
|
|
|
|
NewPartEntry->IsPartitioned = TRUE;
|
|
|
|
NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
|
2015-08-09 13:14:00 +00:00
|
|
|
NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
|
2014-05-20 23:48:36 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart;
|
|
|
|
|
2015-01-04 13:53:45 +00:00
|
|
|
NewPartEntry->New = FALSE;
|
2014-05-20 23:48:36 +00:00
|
|
|
NewPartEntry->FormatState = Formatted;
|
2014-12-07 22:28:12 +00:00
|
|
|
NewPartEntry->BootIndicator = FALSE;
|
2014-05-20 23:48:36 +00:00
|
|
|
|
2014-05-22 14:55:04 +00:00
|
|
|
if (NewPartEntry->StartSector.QuadPart < 1450560)
|
|
|
|
{
|
|
|
|
/* Partition starts below the 8.4GB boundary ==> CHS partition */
|
|
|
|
NewPartEntry->PartitionType = PARTITION_EXTENDED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Partition starts above the 8.4GB boundary ==> LBA partition */
|
|
|
|
NewPartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
|
|
|
|
}
|
|
|
|
|
|
|
|
DiskEntry->ExtendedPartition = NewPartEntry;
|
|
|
|
|
2014-05-20 23:48:36 +00:00
|
|
|
PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
|
|
|
|
PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
|
|
|
|
|
2015-05-29 14:06:01 +00:00
|
|
|
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
|
2014-05-20 23:48:36 +00:00
|
|
|
}
|
|
|
|
|
2014-05-22 14:55:04 +00:00
|
|
|
AddLogicalDiskSpace(DiskEntry);
|
|
|
|
|
2014-05-20 23:48:36 +00:00
|
|
|
UpdateDiskLayout(DiskEntry);
|
|
|
|
|
|
|
|
DiskEntry->Dirty = TRUE;
|
|
|
|
|
|
|
|
AssignDriveLetters(List);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-09 01:49:24 +00:00
|
|
|
VOID
|
|
|
|
CreateLogicalPartition(
|
|
|
|
PPARTLIST List,
|
2015-07-04 16:04:09 +00:00
|
|
|
ULONGLONG SectorCount,
|
|
|
|
BOOLEAN AutoCreate)
|
2014-06-09 01:49:24 +00:00
|
|
|
{
|
2015-06-19 19:01:39 +00:00
|
|
|
PDISKENTRY DiskEntry;
|
2014-06-09 01:49:24 +00:00
|
|
|
PPARTENTRY PartEntry;
|
2015-06-19 19:01:39 +00:00
|
|
|
PPARTENTRY NewPartEntry;
|
2014-06-09 01:49:24 +00:00
|
|
|
|
|
|
|
DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount);
|
|
|
|
|
|
|
|
if (List == NULL ||
|
|
|
|
List->CurrentDisk == NULL ||
|
|
|
|
List->CurrentPartition == NULL ||
|
2017-10-01 14:42:04 +00:00
|
|
|
List->CurrentPartition->IsPartitioned != FALSE)
|
2014-06-09 01:49:24 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-19 19:01:39 +00:00
|
|
|
DiskEntry = List->CurrentDisk;
|
2014-06-09 01:49:24 +00:00
|
|
|
PartEntry = List->CurrentPartition;
|
|
|
|
|
|
|
|
DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
|
2015-06-19 19:01:39 +00:00
|
|
|
|
2015-07-04 16:04:09 +00:00
|
|
|
if (AutoCreate == TRUE ||
|
2015-08-09 13:14:00 +00:00
|
|
|
AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
|
2015-06-19 19:01:39 +00:00
|
|
|
{
|
|
|
|
DPRINT1("Convert existing partition entry\n");
|
|
|
|
|
|
|
|
/* Convert current entry to 'new (unformatted)' */
|
|
|
|
PartEntry->IsPartitioned = TRUE;
|
|
|
|
PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
|
|
|
|
PartEntry->FormatState = Unformatted;
|
|
|
|
PartEntry->AutoCreate = FALSE;
|
|
|
|
PartEntry->New = TRUE;
|
|
|
|
PartEntry->BootIndicator = FALSE;
|
|
|
|
PartEntry->LogicalPartition = TRUE;
|
|
|
|
|
|
|
|
DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Add new partition entry\n");
|
|
|
|
|
|
|
|
/* Insert and initialize a new partition entry */
|
|
|
|
NewPartEntry = RtlAllocateHeap(ProcessHeap,
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(PARTENTRY));
|
|
|
|
if (NewPartEntry == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Insert the new entry into the list */
|
|
|
|
InsertTailList(&PartEntry->ListEntry,
|
|
|
|
&NewPartEntry->ListEntry);
|
|
|
|
|
|
|
|
NewPartEntry->DiskEntry = DiskEntry;
|
|
|
|
|
|
|
|
NewPartEntry->IsPartitioned = TRUE;
|
|
|
|
NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
|
2015-08-09 13:14:00 +00:00
|
|
|
NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
|
2015-06-19 19:01:39 +00:00
|
|
|
NewPartEntry->StartSector.QuadPart;
|
|
|
|
NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
|
|
|
|
|
|
|
|
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
|
|
|
|
DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
|
|
|
|
DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
|
|
|
|
|
|
|
|
NewPartEntry->New = TRUE;
|
|
|
|
NewPartEntry->FormatState = Unformatted;
|
|
|
|
NewPartEntry->BootIndicator = FALSE;
|
|
|
|
NewPartEntry->LogicalPartition = TRUE;
|
|
|
|
|
|
|
|
PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
|
|
|
|
PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateDiskLayout(DiskEntry);
|
|
|
|
|
|
|
|
DiskEntry->Dirty = TRUE;
|
|
|
|
|
|
|
|
AssignDriveLetters(List);
|
2014-06-09 01:49:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
VOID
|
|
|
|
DeleteCurrentPartition(
|
|
|
|
PPARTLIST List)
|
2003-08-12 15:56:21 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
PPARTENTRY PrevPartEntry;
|
|
|
|
PPARTENTRY NextPartEntry;
|
2014-05-22 14:55:04 +00:00
|
|
|
PPARTENTRY LogicalPartEntry;
|
|
|
|
PLIST_ENTRY Entry;
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
if (List == NULL ||
|
|
|
|
List->CurrentDisk == NULL ||
|
|
|
|
List->CurrentPartition == NULL ||
|
2014-05-18 15:14:24 +00:00
|
|
|
List->CurrentPartition->IsPartitioned == FALSE)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2003-08-12 15:56:21 +00:00
|
|
|
|
2017-03-01 20:46:24 +00:00
|
|
|
/* Clear the system disk and partition pointers if the system partition will be deleted */
|
|
|
|
if (List->SystemPartition == List->CurrentPartition)
|
|
|
|
{
|
|
|
|
List->SystemDisk = NULL;
|
|
|
|
List->SystemPartition = NULL;
|
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
DiskEntry = List->CurrentDisk;
|
|
|
|
PartEntry = List->CurrentPartition;
|
2003-08-12 15:56:21 +00:00
|
|
|
|
2016-02-29 01:22:02 +00:00
|
|
|
/* Delete all logical partition entries if an extended partition will be deleted */
|
2014-05-22 14:55:04 +00:00
|
|
|
if (DiskEntry->ExtendedPartition == PartEntry)
|
|
|
|
{
|
|
|
|
while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
|
|
|
|
{
|
|
|
|
Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
|
|
|
|
LogicalPartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
|
|
|
|
|
|
|
|
RtlFreeHeap(ProcessHeap, 0, LogicalPartEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
DiskEntry->ExtendedPartition = NULL;
|
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Adjust unpartitioned disk space entries */
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Get pointer to previous and next unpartitioned entries */
|
2016-02-29 20:58:32 +00:00
|
|
|
PrevPartEntry = GetPrevUnpartitionedEntry(DiskEntry, PartEntry);
|
|
|
|
NextPartEntry = GetNextUnpartitionedEntry(DiskEntry, PartEntry);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
if (PrevPartEntry != NULL && NextPartEntry != NULL)
|
|
|
|
{
|
|
|
|
/* Merge previous, current and next unpartitioned entry */
|
|
|
|
|
|
|
|
/* Adjust the previous entries length */
|
2014-05-18 15:14:24 +00:00
|
|
|
PrevPartEntry->SectorCount.QuadPart += (PartEntry->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
/* Remove the current entry */
|
|
|
|
RemoveEntryList(&PartEntry->ListEntry);
|
2014-05-18 15:14:24 +00:00
|
|
|
RtlFreeHeap(ProcessHeap, 0, PartEntry);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
/* Remove the next entry */
|
|
|
|
RemoveEntryList (&NextPartEntry->ListEntry);
|
2014-05-18 15:14:24 +00:00
|
|
|
RtlFreeHeap(ProcessHeap, 0, NextPartEntry);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
/* Update current partition */
|
|
|
|
List->CurrentPartition = PrevPartEntry;
|
|
|
|
}
|
|
|
|
else if (PrevPartEntry != NULL && NextPartEntry == NULL)
|
|
|
|
{
|
|
|
|
/* Merge current and previous unpartitioned entry */
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Adjust the previous entries length */
|
2014-05-18 15:14:24 +00:00
|
|
|
PrevPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Remove the current entry */
|
|
|
|
RemoveEntryList(&PartEntry->ListEntry);
|
2014-05-18 15:14:24 +00:00
|
|
|
RtlFreeHeap(ProcessHeap, 0, PartEntry);
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Update current partition */
|
|
|
|
List->CurrentPartition = PrevPartEntry;
|
2007-12-30 21:20:54 +00:00
|
|
|
}
|
|
|
|
else if (PrevPartEntry == NULL && NextPartEntry != NULL)
|
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Merge current and next unpartitioned entry */
|
|
|
|
|
|
|
|
/* Adjust the next entries offset and length */
|
2014-05-18 15:14:24 +00:00
|
|
|
NextPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
|
|
|
|
NextPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
/* Remove the current entry */
|
|
|
|
RemoveEntryList(&PartEntry->ListEntry);
|
2014-05-18 15:14:24 +00:00
|
|
|
RtlFreeHeap(ProcessHeap, 0, PartEntry);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
/* Update current partition */
|
|
|
|
List->CurrentPartition = NextPartEntry;
|
2003-04-18 Casper S. Hornstrup <chorns@users.sourceforge.net>
* subsys/system/usetup/partlist.c (AddPartitionList): Create
unpartitioned areas.
(CreatePartitionListNoGUI): Save disk geometry.
(PrintDiskData): Do not print hidden partition list entries.
(ScrollDownPartitionList, ScrollUpPartitionList): Skip hidden partition
list entries.
(GetActiveBootPartition): Use CurrentDisk as index.
(CreateSelectedPartition): New function.
* subsys/system/usetup/partlist.h (PARTDATA): Add field NewPartSize.
(PARTENTRY): Add fields StartingOffset and HidePartEntry.
(DISKENTRY): Add fields Cylinders, TracksPerCylinder, SectorsPerTrack,
and BytesPerSector;
(CreateSelectedPartition): Add Prototype.
* subsys/system/usetup/usetup.c (PAGE_NUMBER): Add CREATE_PARTITION_PAGE
and FORMAT_PARTITION_PAGE
(CurrentPartitionList, CurrentFileSystemList): New globals.
(SelectPartitionPage): Set CurrentPartitionList.
(PARTITION_SIZE_INPUT_FIELD_LENGTH): Define as 6.
(DrawInputField, ShowPartitionSizeInputBox, CreatePartitionPage,
CreateFileSystemList, DestroyFileSystemList, DrawFileSystemList,
ScrollDownFileSystemList, ScrollUpFileSystemList, FormatPartitionPage):
New functions.
(SelectFileSystemPage): Draw partition screen.
(CheckFileSystemPage): Handle CREATE_PARTITION_PAGE and
FORMAT_PARTITION_PAGE.
* subsys/system/usetup/usetup.h (FILE_SYSTEM, FILE_SYSTEM_LIST): Add enums.
svn path=/trunk/; revision=4552
2003-04-18 14:00:17 +00:00
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
else
|
2007-12-30 21:20:54 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Nothing to merge but change current entry */
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry->IsPartitioned = FALSE;
|
2014-10-03 09:24:54 +00:00
|
|
|
PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry->FormatState = Unformatted;
|
|
|
|
PartEntry->DriveLetter = 0;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
2003-04-18 Casper S. Hornstrup <chorns@users.sourceforge.net>
* subsys/system/usetup/partlist.c (AddPartitionList): Create
unpartitioned areas.
(CreatePartitionListNoGUI): Save disk geometry.
(PrintDiskData): Do not print hidden partition list entries.
(ScrollDownPartitionList, ScrollUpPartitionList): Skip hidden partition
list entries.
(GetActiveBootPartition): Use CurrentDisk as index.
(CreateSelectedPartition): New function.
* subsys/system/usetup/partlist.h (PARTDATA): Add field NewPartSize.
(PARTENTRY): Add fields StartingOffset and HidePartEntry.
(DISKENTRY): Add fields Cylinders, TracksPerCylinder, SectorsPerTrack,
and BytesPerSector;
(CreateSelectedPartition): Add Prototype.
* subsys/system/usetup/usetup.c (PAGE_NUMBER): Add CREATE_PARTITION_PAGE
and FORMAT_PARTITION_PAGE
(CurrentPartitionList, CurrentFileSystemList): New globals.
(SelectPartitionPage): Set CurrentPartitionList.
(PARTITION_SIZE_INPUT_FIELD_LENGTH): Define as 6.
(DrawInputField, ShowPartitionSizeInputBox, CreatePartitionPage,
CreateFileSystemList, DestroyFileSystemList, DrawFileSystemList,
ScrollDownFileSystemList, ScrollUpFileSystemList, FormatPartitionPage):
New functions.
(SelectFileSystemPage): Draw partition screen.
(CheckFileSystemPage): Handle CREATE_PARTITION_PAGE and
FORMAT_PARTITION_PAGE.
* subsys/system/usetup/usetup.h (FILE_SYSTEM, FILE_SYSTEM_LIST): Add enums.
svn path=/trunk/; revision=4552
2003-04-18 14:00:17 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
UpdateDiskLayout(DiskEntry);
|
|
|
|
|
|
|
|
DiskEntry->Dirty = TRUE;
|
2003-04-28 19:44:13 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
AssignDriveLetters(List);
|
2003-08-02 16:49:36 +00:00
|
|
|
}
|
|
|
|
|
2003-08-12 15:56:21 +00:00
|
|
|
|
2003-08-19 15:54:47 +00:00
|
|
|
VOID
|
2016-02-28 15:25:22 +00:00
|
|
|
CheckActiveSystemPartition(
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
IN PPARTLIST List,
|
|
|
|
IN PFILE_SYSTEM_LIST FileSystemList /* Needed for checking the FS of the candidate system partition */
|
|
|
|
)
|
2003-08-19 15:54:47 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
PLIST_ENTRY ListEntry;
|
|
|
|
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
PFILE_SYSTEM_ITEM FileSystem;
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Check for empty disk list */
|
2016-02-28 15:25:22 +00:00
|
|
|
if (IsListEmpty(&List->DiskListHead))
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2016-02-28 15:25:22 +00:00
|
|
|
List->SystemDisk = NULL;
|
|
|
|
List->SystemPartition = NULL;
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
List->OriginalSystemDisk = NULL;
|
|
|
|
List->OriginalSystemPartition = NULL;
|
2014-05-04 22:03:00 +00:00
|
|
|
return;
|
|
|
|
}
|
2003-08-19 15:54:47 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Choose the currently selected disk */
|
|
|
|
DiskEntry = List->CurrentDisk;
|
2009-04-09 18:59:28 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
/* Check for empty partition list */
|
2016-02-28 15:25:22 +00:00
|
|
|
if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2016-02-28 15:25:22 +00:00
|
|
|
List->SystemDisk = NULL;
|
|
|
|
List->SystemPartition = NULL;
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
List->OriginalSystemDisk = NULL;
|
|
|
|
List->OriginalSystemPartition = NULL;
|
2014-05-04 22:03:00 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-04-09 18:59:28 +00:00
|
|
|
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
if (List->SystemDisk != NULL && List->SystemPartition != NULL)
|
|
|
|
{
|
|
|
|
/* We already have an active system partition */
|
|
|
|
DPRINT1("Use the current system partition %lu in disk %lu, drive letter %c\n",
|
|
|
|
List->SystemPartition->PartitionNumber,
|
|
|
|
List->SystemDisk->DiskNumber,
|
|
|
|
(List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT1("We are here (1)!\n");
|
|
|
|
|
|
|
|
List->SystemDisk = NULL;
|
|
|
|
List->SystemPartition = NULL;
|
|
|
|
List->OriginalSystemDisk = NULL;
|
|
|
|
List->OriginalSystemPartition = NULL;
|
2016-02-28 15:25:22 +00:00
|
|
|
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
/* Retrieve the first partition of the disk */
|
2014-05-18 15:14:24 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
|
2009-04-09 18:59:28 +00:00
|
|
|
PARTENTRY,
|
|
|
|
ListEntry);
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
List->SystemDisk = DiskEntry;
|
|
|
|
List->SystemPartition = PartEntry;
|
|
|
|
|
|
|
|
//
|
|
|
|
// See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
|
|
|
|
//
|
2009-04-09 18:59:28 +00:00
|
|
|
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
/* Check if the disk is new and if so, use its first partition as the active system partition */
|
|
|
|
if (DiskEntry->NewDisk)
|
2009-04-09 18:59:28 +00:00
|
|
|
{
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator == FALSE)
|
|
|
|
{
|
|
|
|
/* FIXME: Might be incorrect if partitions were created by Linux FDISK */
|
|
|
|
List->SystemDisk = DiskEntry;
|
|
|
|
List->SystemPartition = PartEntry;
|
|
|
|
|
|
|
|
List->OriginalSystemDisk = List->SystemDisk;
|
|
|
|
List->OriginalSystemPartition = List->SystemPartition;
|
|
|
|
|
|
|
|
DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %c\n",
|
|
|
|
List->SystemPartition->PartitionNumber,
|
|
|
|
List->SystemDisk->DiskNumber,
|
|
|
|
(List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
|
|
|
|
|
|
|
|
goto SetSystemPartition;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: What to do??
|
|
|
|
DPRINT1("NewDisk TRUE but first partition is used?\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT1("We are here (2)!\n");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The disk is not new, check if any partition is initialized;
|
|
|
|
* if not, the first one becomes the system partition.
|
|
|
|
*/
|
|
|
|
ListEntry = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (ListEntry != &DiskEntry->PrimaryPartListHead)
|
|
|
|
{
|
|
|
|
/* Retrieve the partition and go to the next one */
|
|
|
|
PartEntry = CONTAINING_RECORD(ListEntry,
|
|
|
|
PARTENTRY,
|
|
|
|
ListEntry);
|
|
|
|
|
|
|
|
/* Check if the partition is partitioned and is used */
|
|
|
|
if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator != FALSE)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Go to the next one */
|
|
|
|
ListEntry = ListEntry->Flink;
|
|
|
|
}
|
|
|
|
if (ListEntry == &DiskEntry->PrimaryPartListHead)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* OK we haven't encountered any used and active partition,
|
|
|
|
* so use the first one as the system partition.
|
|
|
|
*/
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
/* FIXME: Might be incorrect if partitions were created by Linux FDISK */
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
List->OriginalSystemDisk = List->SystemDisk; // DiskEntry
|
|
|
|
List->OriginalSystemPartition = List->SystemPartition; // First PartEntry
|
2014-05-04 22:03:00 +00:00
|
|
|
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
DPRINT1("Use first active system partition %lu in disk %lu, drive letter %c\n",
|
|
|
|
List->SystemPartition->PartitionNumber,
|
|
|
|
List->SystemDisk->DiskNumber,
|
|
|
|
(List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
|
|
|
|
|
|
|
|
goto SetSystemPartition;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
|
2016-02-28 15:25:22 +00:00
|
|
|
List->SystemDisk = NULL;
|
|
|
|
List->SystemPartition = NULL;
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
List->OriginalSystemDisk = NULL;
|
|
|
|
List->OriginalSystemPartition = NULL;
|
2009-04-09 18:59:28 +00:00
|
|
|
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
DPRINT1("We are here (3)!\n");
|
|
|
|
|
|
|
|
/* The disk is not new, scan all partitions to find the (active) system partition */
|
2014-05-18 15:14:24 +00:00
|
|
|
ListEntry = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (ListEntry != &DiskEntry->PrimaryPartListHead)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
/* Retrieve the partition and go to the next one */
|
2014-05-04 22:03:00 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(ListEntry,
|
|
|
|
PARTENTRY,
|
|
|
|
ListEntry);
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
ListEntry = ListEntry->Flink;
|
2009-04-09 18:59:28 +00:00
|
|
|
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
/* Check if the partition is partitioned and used */
|
|
|
|
if (PartEntry->IsPartitioned &&
|
|
|
|
PartEntry->PartitionType != PARTITION_ENTRY_UNUSED)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
/* Check if the partition is active */
|
|
|
|
if (PartEntry->BootIndicator)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
/* Yes, we found it */
|
2016-02-28 15:25:22 +00:00
|
|
|
List->SystemDisk = DiskEntry;
|
|
|
|
List->SystemPartition = PartEntry;
|
2014-05-04 22:03:00 +00:00
|
|
|
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
DPRINT1("Found active system partition %lu in disk %lu, drive letter %c\n",
|
|
|
|
PartEntry->PartitionNumber,
|
|
|
|
DiskEntry->DiskNumber,
|
|
|
|
(PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter);
|
2014-05-18 15:14:24 +00:00
|
|
|
break;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
2009-04-09 18:59:28 +00:00
|
|
|
}
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
/* Check if we have found the system partition */
|
|
|
|
if (List->SystemDisk == NULL || List->SystemPartition == NULL)
|
|
|
|
{
|
|
|
|
/* Nothing, use the alternative system partition */
|
|
|
|
DPRINT1("No system partition found, use the alternative partition!\n");
|
|
|
|
goto UseAlternativeSystemPartition;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save them */
|
|
|
|
List->OriginalSystemDisk = List->SystemDisk;
|
|
|
|
List->OriginalSystemPartition = List->SystemPartition;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ADDITIONAL CHECKS / BIG HACK:
|
|
|
|
*
|
|
|
|
* Retrieve its file system and check whether we have
|
|
|
|
* write support for it. If that is the case we are fine
|
|
|
|
* and we can use it directly. However if we don't have
|
|
|
|
* write support we will need to change the active system
|
|
|
|
* partition.
|
|
|
|
*
|
|
|
|
* NOTE that this is completely useless on architectures
|
|
|
|
* where a real system partition is required, as on these
|
|
|
|
* architectures the partition uses the FAT FS, for which
|
|
|
|
* we do have write support.
|
|
|
|
* NOTE also that for those architectures looking for a
|
|
|
|
* partition boot indicator is insufficient.
|
|
|
|
*/
|
|
|
|
FileSystem = GetFileSystem(FileSystemList, List->OriginalSystemPartition);
|
|
|
|
if (FileSystem == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("System partition %lu in disk %lu with no FS?!\n",
|
|
|
|
List->OriginalSystemPartition->PartitionNumber,
|
|
|
|
List->OriginalSystemDisk->DiskNumber);
|
|
|
|
goto FindAndUseAlternativeSystemPartition;
|
2009-04-09 18:59:28 +00:00
|
|
|
}
|
[USETUP]
- bootsup.c/.h, usetup.c: Save the old MBR sector in the system partition (this makes easier to restore the old one).
- fslist.c/.h, usetup.h: Fix header inclusion order.
- partlist.c/.h, usetup.c: On BIOS-PC architectures, the system partition can be formatted in any FS as long as it is the active partition (on the contrary, on architectures where such system partition is required, it is formatted in FAT). We currently do not have write support for all FSes out there (apart for FAT until now), so do a "clever" "trick" to work around this problem: on initialized disks, find the active partition and check its FS. If we support write access to this FS then we're OK, otherwise we change the (active) system partition for the one on which we are going to install ReactOS (which is, by construction, formatted with a FS on which we support write access).
The MBR (resp. the VBR) of the disk (resp. of the system partition) are always saved into files, making easy for people to boot on them (using FreeLdr) or restoring them.
CORE-10898
svn path=/trunk/; revision=70837
2016-03-01 15:00:56 +00:00
|
|
|
// HACK: WARNING: We cannot write on this FS yet!
|
|
|
|
// See fslist.c:GetFileSystem()
|
|
|
|
if (List->OriginalSystemPartition->PartitionType == PARTITION_EXT2 ||
|
|
|
|
List->OriginalSystemPartition->PartitionType == PARTITION_IFS)
|
|
|
|
{
|
|
|
|
DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
|
|
|
|
FileSystem->FileSystemName);
|
|
|
|
goto FindAndUseAlternativeSystemPartition;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %c\n",
|
|
|
|
List->SystemPartition->PartitionNumber,
|
|
|
|
List->SystemDisk->DiskNumber,
|
|
|
|
(List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
FindAndUseAlternativeSystemPartition:
|
|
|
|
/*
|
|
|
|
* We are here because we have not found any (active) candidate
|
|
|
|
* system partition that we know how to support. What we are going
|
|
|
|
* to do is to change the existing system partition and use the
|
|
|
|
* partition on which we install ReactOS as the new system partition,
|
|
|
|
* and then we will need to add in FreeLdr's entry a boot entry to boot
|
|
|
|
* from the original system partition.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Unset the old system partition */
|
|
|
|
List->SystemPartition->BootIndicator = FALSE;
|
|
|
|
List->SystemDisk->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].BootIndicator = FALSE;
|
|
|
|
List->SystemDisk->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].RewritePartition = TRUE;
|
|
|
|
List->SystemDisk->Dirty = TRUE;
|
|
|
|
|
|
|
|
UseAlternativeSystemPartition:
|
|
|
|
List->SystemDisk = List->CurrentDisk;
|
|
|
|
List->SystemPartition = List->CurrentPartition;
|
|
|
|
|
|
|
|
DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %c\n",
|
|
|
|
List->SystemPartition->PartitionNumber,
|
|
|
|
List->SystemDisk->DiskNumber,
|
|
|
|
(List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
|
|
|
|
|
|
|
|
SetSystemPartition:
|
|
|
|
/* Set the new active system partition */
|
|
|
|
List->SystemPartition->BootIndicator = TRUE;
|
|
|
|
List->SystemDisk->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].BootIndicator = TRUE;
|
|
|
|
List->SystemDisk->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].RewritePartition = TRUE;
|
|
|
|
List->SystemDisk->Dirty = TRUE;
|
2003-08-19 15:54:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
static
|
|
|
|
NTSTATUS
|
2015-06-13 10:08:36 +00:00
|
|
|
WritePartitions(
|
2014-05-18 15:14:24 +00:00
|
|
|
IN PPARTLIST List,
|
|
|
|
IN PDISKENTRY DiskEntry)
|
2003-08-12 15:56:21 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
WCHAR DstPath[MAX_PATH];
|
2014-05-04 22:03:00 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
IO_STATUS_BLOCK Iosb;
|
|
|
|
UNICODE_STRING Name;
|
2014-05-18 15:14:24 +00:00
|
|
|
ULONG BufferSize;
|
|
|
|
HANDLE FileHandle = NULL;
|
2014-05-04 22:03:00 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber);
|
|
|
|
|
|
|
|
swprintf(DstPath,
|
|
|
|
L"\\Device\\Harddisk%d\\Partition0",
|
|
|
|
DiskEntry->DiskNumber);
|
|
|
|
RtlInitUnicodeString(&Name,
|
|
|
|
DstPath);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&Name,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = NtOpenFile(&FileHandle,
|
|
|
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
|
|
|
&ObjectAttributes,
|
|
|
|
&Iosb,
|
|
|
|
0,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
|
|
|
|
return Status;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
#ifdef DUMP_PARTITION_TABLE
|
|
|
|
DumpPartitionTable(DiskEntry);
|
|
|
|
#endif
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
|
|
|
|
((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
|
|
|
|
Status = NtDeviceIoControlFile(FileHandle,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Iosb,
|
|
|
|
IOCTL_DISK_SET_DRIVE_LAYOUT,
|
|
|
|
DiskEntry->LayoutBuffer,
|
|
|
|
BufferSize,
|
|
|
|
NULL,
|
|
|
|
0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
|
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
if (FileHandle != NULL)
|
|
|
|
NtClose(FileHandle);
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2015-01-04 13:53:45 +00:00
|
|
|
BOOLEAN
|
|
|
|
WritePartitionsToDisk(
|
2014-05-18 15:14:24 +00:00
|
|
|
PPARTLIST List)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PDISKENTRY DiskEntry;
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
if (List == NULL)
|
2015-01-04 13:53:45 +00:00
|
|
|
return TRUE;
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
Entry = List->DiskListHead.Flink;
|
|
|
|
while (Entry != &List->DiskListHead)
|
|
|
|
{
|
|
|
|
DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2017-10-01 14:42:04 +00:00
|
|
|
if (DiskEntry->Dirty != FALSE)
|
2014-05-18 15:14:24 +00:00
|
|
|
{
|
2015-06-13 10:08:36 +00:00
|
|
|
WritePartitions(List, DiskEntry);
|
2015-06-12 22:56:36 +00:00
|
|
|
DiskEntry->Dirty = FALSE;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
2007-12-30 21:20:54 +00:00
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
Entry = Entry->Flink;
|
2003-08-12 15:56:21 +00:00
|
|
|
}
|
|
|
|
|
2015-01-04 13:53:45 +00:00
|
|
|
return TRUE;
|
2003-08-12 15:56:21 +00:00
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
BOOL
|
|
|
|
SetMountedDeviceValues(
|
|
|
|
PPARTLIST List)
|
2005-09-15 17:19:31 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PLIST_ENTRY Entry1, Entry2;
|
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
2014-05-18 15:14:24 +00:00
|
|
|
LARGE_INTEGER StartingOffset;
|
2005-09-15 17:19:31 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
if (List == NULL)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry1 = List->DiskListHead.Flink;
|
|
|
|
while (Entry1 != &List->DiskListHead)
|
|
|
|
{
|
|
|
|
DiskEntry = CONTAINING_RECORD(Entry1,
|
|
|
|
DISKENTRY,
|
|
|
|
ListEntry);
|
|
|
|
|
2014-05-18 15:14:24 +00:00
|
|
|
Entry2 = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->PrimaryPartListHead)
|
2005-09-15 17:19:31 +00:00
|
|
|
{
|
2014-05-04 22:03:00 +00:00
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
2014-05-18 15:14:24 +00:00
|
|
|
if (PartEntry->IsPartitioned)
|
2009-04-09 18:59:28 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
if (PartEntry->DriveLetter)
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
|
|
|
|
if (!SetMountedDeviceValue(PartEntry->DriveLetter,
|
|
|
|
DiskEntry->LayoutBuffer->Signature,
|
|
|
|
StartingOffset))
|
2014-05-04 22:03:00 +00:00
|
|
|
{
|
2014-05-18 15:14:24 +00:00
|
|
|
return FALSE;
|
2014-05-04 22:03:00 +00:00
|
|
|
}
|
|
|
|
}
|
2009-04-09 18:59:28 +00:00
|
|
|
}
|
2014-05-04 22:03:00 +00:00
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
2005-09-15 17:19:31 +00:00
|
|
|
}
|
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
Entry1 = Entry1->Flink;
|
|
|
|
}
|
2005-09-15 17:19:31 +00:00
|
|
|
|
2014-05-04 22:03:00 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2005-09-15 17:19:31 +00:00
|
|
|
|
2014-05-20 23:48:36 +00:00
|
|
|
|
|
|
|
ULONG
|
|
|
|
PrimaryPartitionCreationChecks(
|
|
|
|
IN PPARTLIST List)
|
|
|
|
{
|
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
|
|
|
|
DiskEntry = List->CurrentDisk;
|
|
|
|
PartEntry = List->CurrentPartition;
|
|
|
|
|
|
|
|
/* Fail if partition is already in use */
|
2017-10-01 14:42:04 +00:00
|
|
|
if (PartEntry->IsPartitioned != FALSE)
|
2014-05-20 23:48:36 +00:00
|
|
|
return ERROR_NEW_PARTITION;
|
|
|
|
|
2017-05-09 22:09:06 +00:00
|
|
|
/* Fail if there are already 4 primary partitions in the list */
|
|
|
|
if (GetPrimaryPartitionCount(DiskEntry) >= 4)
|
2014-05-20 23:48:36 +00:00
|
|
|
return ERROR_PARTITION_TABLE_FULL;
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
ExtendedPartitionCreationChecks(
|
|
|
|
IN PPARTLIST List)
|
|
|
|
{
|
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
|
|
|
|
DiskEntry = List->CurrentDisk;
|
|
|
|
PartEntry = List->CurrentPartition;
|
|
|
|
|
|
|
|
/* Fail if partition is already in use */
|
2017-10-01 14:42:04 +00:00
|
|
|
if (PartEntry->IsPartitioned != FALSE)
|
2014-05-20 23:48:36 +00:00
|
|
|
return ERROR_NEW_PARTITION;
|
|
|
|
|
2017-05-09 22:09:06 +00:00
|
|
|
/* Fail if there are already 4 primary partitions in the list */
|
|
|
|
if (GetPrimaryPartitionCount(DiskEntry) >= 4)
|
2014-05-20 23:48:36 +00:00
|
|
|
return ERROR_PARTITION_TABLE_FULL;
|
|
|
|
|
|
|
|
/* Fail if there is another extended partition in the list */
|
2014-05-22 14:55:04 +00:00
|
|
|
if (DiskEntry->ExtendedPartition != NULL)
|
2014-05-20 23:48:36 +00:00
|
|
|
return ERROR_ONLY_ONE_EXTENDED;
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2014-06-08 19:05:03 +00:00
|
|
|
|
|
|
|
ULONG
|
|
|
|
LogicalPartitionCreationChecks(
|
|
|
|
IN PPARTLIST List)
|
|
|
|
{
|
|
|
|
// PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
|
|
|
|
// DiskEntry = List->CurrentDisk;
|
|
|
|
PartEntry = List->CurrentPartition;
|
|
|
|
|
|
|
|
/* Fail if partition is already in use */
|
2017-10-01 14:42:04 +00:00
|
|
|
if (PartEntry->IsPartitioned != FALSE)
|
2014-06-08 19:05:03 +00:00
|
|
|
return ERROR_NEW_PARTITION;
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2015-06-12 21:51:57 +00:00
|
|
|
|
|
|
|
BOOL
|
|
|
|
GetNextUnformattedPartition(
|
|
|
|
IN PPARTLIST List,
|
|
|
|
OUT PDISKENTRY *pDiskEntry,
|
|
|
|
OUT PPARTENTRY *pPartEntry)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY Entry1, Entry2;
|
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
|
|
|
|
Entry1 = List->DiskListHead.Flink;
|
|
|
|
while (Entry1 != &List->DiskListHead)
|
|
|
|
{
|
|
|
|
DiskEntry = CONTAINING_RECORD(Entry1,
|
|
|
|
DISKENTRY,
|
|
|
|
ListEntry);
|
|
|
|
|
|
|
|
Entry2 = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->PrimaryPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
|
|
|
if (PartEntry->IsPartitioned && PartEntry->New)
|
|
|
|
{
|
|
|
|
*pDiskEntry = DiskEntry;
|
|
|
|
*pPartEntry = PartEntry;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry2 = DiskEntry->LogicalPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->LogicalPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
|
|
|
if (PartEntry->IsPartitioned && PartEntry->New)
|
|
|
|
{
|
|
|
|
*pDiskEntry = DiskEntry;
|
|
|
|
*pPartEntry = PartEntry;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry1 = Entry1->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pDiskEntry = NULL;
|
|
|
|
*pPartEntry = NULL;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
GetNextUncheckedPartition(
|
|
|
|
IN PPARTLIST List,
|
|
|
|
OUT PDISKENTRY *pDiskEntry,
|
|
|
|
OUT PPARTENTRY *pPartEntry)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY Entry1, Entry2;
|
|
|
|
PDISKENTRY DiskEntry;
|
|
|
|
PPARTENTRY PartEntry;
|
|
|
|
|
|
|
|
Entry1 = List->DiskListHead.Flink;
|
|
|
|
while (Entry1 != &List->DiskListHead)
|
|
|
|
{
|
|
|
|
DiskEntry = CONTAINING_RECORD(Entry1,
|
|
|
|
DISKENTRY,
|
|
|
|
ListEntry);
|
|
|
|
|
|
|
|
Entry2 = DiskEntry->PrimaryPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->PrimaryPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
|
|
|
if (PartEntry->NeedsCheck == TRUE)
|
|
|
|
{
|
|
|
|
*pDiskEntry = DiskEntry;
|
|
|
|
*pPartEntry = PartEntry;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry2 = DiskEntry->LogicalPartListHead.Flink;
|
|
|
|
while (Entry2 != &DiskEntry->LogicalPartListHead)
|
|
|
|
{
|
|
|
|
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
|
|
|
|
if (PartEntry->NeedsCheck == TRUE)
|
|
|
|
{
|
|
|
|
*pDiskEntry = DiskEntry;
|
|
|
|
*pPartEntry = PartEntry;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry2 = Entry2->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entry1 = Entry1->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pDiskEntry = NULL;
|
|
|
|
*pPartEntry = NULL;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2002-10-18 20:04:00 +00:00
|
|
|
/* EOF */
|