📄 partlist.c
字号:
/*
* ReactOS kernel
* Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: subsys/system/usetup/partlist.c
* PURPOSE: Partition list functions
* PROGRAMMER: Eric Kohl
* Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
#include "usetup.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
static VOID
GetDriverName (PDISKENTRY DiskEntry)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
WCHAR KeyName[32];
NTSTATUS Status;
RtlInitUnicodeString (&DiskEntry->DriverName,
NULL);
swprintf (KeyName,
L"\\Scsi\\Scsi Port %lu",
DiskEntry->Port);
RtlZeroMemory (&QueryTable,
sizeof(QueryTable));
QueryTable[0].Name = L"Driver";
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
QueryTable[0].EntryContext = &DiskEntry->DriverName;
Status = RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP,
KeyName,
QueryTable,
NULL,
NULL);
if (!NT_SUCCESS (Status))
{
DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
}
}
static VOID
AssignDriverLetters (PPARTLIST List)
{
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
PLIST_ENTRY Entry1;
PLIST_ENTRY Entry2;
CHAR Letter;
Letter = 'C';
/* Assign drive letters to primary partitions */
Entry1 = List->DiskListHead.Flink;
while (Entry1 != &List->DiskListHead)
{
DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
if (!IsListEmpty (&DiskEntry->PartListHead))
{
PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink,
PARTENTRY,
ListEntry);
PartEntry->DriveLetter = 0;
if (PartEntry->Unpartitioned == FALSE &&
!IsContainerPartition (PartEntry->PartInfo[0].PartitionType))
{
if (IsRecognizedPartition (PartEntry->PartInfo[0].PartitionType) ||
(PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED &&
PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL))
{
if (Letter <= 'Z')
{
PartEntry->DriveLetter = Letter;
Letter++;
}
}
}
}
Entry1 = Entry1->Flink;
}
/* Assign drive letters to logical drives */
Entry1 = List->DiskListHead.Flink;
while (Entry1 != &List->DiskListHead)
{
DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
Entry2 = DiskEntry->PartListHead.Flink;
if (Entry2 != &DiskEntry->PartListHead)
{
Entry2 = Entry2->Flink;
while (Entry2 != &DiskEntry->PartListHead)
{
PartEntry = CONTAINING_RECORD (Entry2,
PARTENTRY,
ListEntry);
PartEntry->DriveLetter = 0;
if (PartEntry->Unpartitioned == FALSE &&
!IsContainerPartition (PartEntry->PartInfo[0].PartitionType))
{
if (IsRecognizedPartition (PartEntry->PartInfo[0].PartitionType) ||
(PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED &&
PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL))
{
if (Letter <= 'Z')
{
PartEntry->DriveLetter = Letter;
Letter++;
}
}
}
Entry2 = Entry2->Flink;
}
}
Entry1 = Entry1->Flink;
}
}
static VOID
UpdatePartitionNumbers (PDISKENTRY DiskEntry)
{
PPARTENTRY PartEntry;
PLIST_ENTRY Entry;
ULONG PartNumber;
ULONG i;
PartNumber = 1;
Entry = DiskEntry->PartListHead.Flink;
while (Entry != &DiskEntry->PartListHead)
{
PartEntry = CONTAINING_RECORD (Entry,
PARTENTRY,
ListEntry);
if (PartEntry->Unpartitioned == TRUE)
{
for (i = 0; i < 4; i++)
{
PartEntry->PartInfo[i].PartitionNumber = 0;
}
}
else
{
for (i = 0; i < 4; i++)
{
if (IsContainerPartition (PartEntry->PartInfo[i].PartitionType))
{
PartEntry->PartInfo[i].PartitionNumber = 0;
}
else if (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED &&
PartEntry->PartInfo[i].PartitionLength.QuadPart == 0ULL)
{
PartEntry->PartInfo[i].PartitionNumber = 0;
}
else
{
PartEntry->PartInfo[i].PartitionNumber = PartNumber;
PartNumber++;
}
}
}
Entry = Entry->Flink;
}
}
static VOID
AddPartitionToList (ULONG DiskNumber,
PDISKENTRY DiskEntry,
DRIVE_LAYOUT_INFORMATION *LayoutBuffer)
{
PPARTENTRY PartEntry;
ULONG i;
ULONG j;
for (i = 0; i < LayoutBuffer->PartitionCount; i += 4)
{
for (j = 0; j < 4; j++)
{
if (LayoutBuffer->PartitionEntry[i+j].PartitionType != PARTITION_ENTRY_UNUSED ||
LayoutBuffer->PartitionEntry[i+j].PartitionLength.QuadPart != 0ULL)
{
break;
}
}
if (j >= 4)
{
continue;
}
PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
0,
sizeof(PARTENTRY));
if (PartEntry == NULL)
{
return;
}
RtlZeroMemory (PartEntry,
sizeof(PARTENTRY));
PartEntry->Unpartitioned = FALSE;
for (j = 0; j < 4; j++)
{
RtlCopyMemory (&PartEntry->PartInfo[j],
&LayoutBuffer->PartitionEntry[i+j],
sizeof(PARTITION_INFORMATION));
}
if (IsContainerPartition(PartEntry->PartInfo[0].PartitionType))
{
PartEntry->FormatState = Unformatted;
}
else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
(PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
(PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
(PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13) ||
(PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
(PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
{
#if 0
if (CheckFatFormat())
{
PartEntry->FormatState = Preformatted;
}
else
{
PartEntry->FormatState = Unformatted;
}
#endif
PartEntry->FormatState = Preformatted;
}
else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
{
#if 0
if (CheckNtfsFormat())
{
PartEntry->FormatState = Preformatted;
}
else if (CheckHpfsFormat())
{
PartEntry->FormatState = Preformatted;
}
else
{
PartEntry->FormatState = Unformatted;
}
#endif
PartEntry->FormatState = Preformatted;
}
else
{
PartEntry->FormatState = UnknownFormat;
}
InsertTailList (&DiskEntry->PartListHead,
&PartEntry->ListEntry);
}
}
static VOID
ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry)
{
ULONGLONG LastStartingOffset;
ULONGLONG LastPartitionLength;
ULONGLONG LastUnusedPartitionLength;
PPARTENTRY PartEntry;
PPARTENTRY NewPartEntry;
PLIST_ENTRY Entry;
ULONG i;
ULONG j;
if (IsListEmpty (&DiskEntry->PartListHead))
{
/* Create a partition table that represents the empty disk */
PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
0,
sizeof(PARTENTRY));
if (PartEntry == NULL)
return;
RtlZeroMemory (PartEntry,
sizeof(PARTENTRY));
PartEntry->Unpartitioned = TRUE;
PartEntry->UnpartitionedOffset = 0ULL;
PartEntry->UnpartitionedLength = DiskEntry->DiskSize;
PartEntry->FormatState = Unformatted;
InsertTailList (&DiskEntry->PartListHead,
&PartEntry->ListEntry);
}
else
{
/* Start partition at head 1, cylinder 0 */
LastStartingOffset = DiskEntry->TrackSize;
LastPartitionLength = 0ULL;
LastUnusedPartitionLength = 0ULL;
i = 0;
Entry = DiskEntry->PartListHead.Flink;
while (Entry != &DiskEntry->PartListHead)
{
PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);
for (j = 0; j < 4; j++)
{
if ((!IsContainerPartition (PartEntry->PartInfo[j].PartitionType)) &&
(PartEntry->PartInfo[j].PartitionType != PARTITION_ENTRY_UNUSED ||
PartEntry->PartInfo[j].PartitionLength.QuadPart != 0LL))
{
LastUnusedPartitionLength =
PartEntry->PartInfo[j].StartingOffset.QuadPart -
(LastStartingOffset + LastPartitionLength);
if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
{
DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);
NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
0,
sizeof(PARTENTRY));
if (NewPartEntry == NULL)
return;
RtlZeroMemory (NewPartEntry,
sizeof(PARTENTRY));
NewPartEntry->Unpartitioned = TRUE;
NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
if (j == 0)
NewPartEntry->UnpartitionedLength -= DiskEntry->TrackSize;
NewPartEntry->FormatState = Unformatted;
/* Insert the table into the list */
InsertTailList (&PartEntry->ListEntry,
&NewPartEntry->ListEntry);
}
LastStartingOffset = PartEntry->PartInfo[j].StartingOffset.QuadPart;
LastPartitionLength = PartEntry->PartInfo[j].PartitionLength.QuadPart;
}
}
i += 4;
Entry = Entry->Flink;
}
/* Check for trailing unpartitioned disk space */
if (DiskEntry->DiskSize > (LastStartingOffset + LastPartitionLength))
{
/* Round-down to cylinder size */
LastUnusedPartitionLength =
ROUND_DOWN (DiskEntry->DiskSize - (LastStartingOffset + LastPartitionLength),
DiskEntry->CylinderSize);
if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
{
DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);
NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
0,
sizeof(PARTENTRY));
if (NewPartEntry == NULL)
return;
RtlZeroMemory (NewPartEntry,
sizeof(PARTENTRY));
NewPartEntry->Unpartitioned = TRUE;
NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
/* Append the table to the list */
InsertTailList (&DiskEntry->PartListHead,
&NewPartEntry->ListEntry);
}
}
}
}
NTSTATUS
NTAPI
DiskIdentifierQueryRoutine(PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext)
{
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;
}
NTSTATUS
NTAPI
DiskConfigurationDataQueryRoutine(PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext)
{
PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
ULONG i;
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 (FullResourceDescriptor->PartialResourceList.Version != 1 ||
FullResourceDescriptor->PartialResourceList.Revision != 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -