windows-nt/Source/XPSP1/NT/drivers/storage/kdext/scsikd/partition.c
2020-09-26 16:20:57 +08:00

608 lines
14 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
partition.c
Abstract:
Debugger extension for dumping partition structures:
DRIVE_LAYOUT_INFORMATION
DRIVE_LAYOUT_INFORMATION_EX
PARTITION_INFORMATION
PARTITION_INFORMATION_EX
Author:
Matthew D Hendel (math) 19-Jan-2000
Revision History:
--*/
#include "pch.h"
#include <ntdddisk.h>
VOID
DumpPartition(
IN ULONG64 Address,
IN ULONG Detail,
IN ULONG Depth,
IN ULONG PartitionCount
)
/*++
Routine Description:
Dump a PARTITION_INFORMATION structure.
Arguments:
Address - The address of the partition information structure to dump.
Detail - The detail level. Currently unused.
Depth - The depth to indent to.
PartitionCount - The number of partitions. This is used to determine
whether a particular partition ordinal is valid or not.
Return Value:
None.
--*/
{
BOOL Succ;
ULONG Size;
ULONG64 StartingOffset;
ULONG64 PartitionLength;
ULONG PartitionNumber;
UCHAR PartitionType;
BOOLEAN BootIndicator;
BOOLEAN RecognizedPartition;
BOOLEAN RewritePartition;
InitTypeRead(Address, nt!PARTITION_INFORMATION);
StartingOffset = ReadField(StartingOffset.QuadPart);
PartitionLength = ReadField(PartitionLength.QuadPart);
PartitionType = (UCHAR) ReadField(PartitionType);
BootIndicator = (BOOLEAN) ReadField(BootIndicator);
RecognizedPartition = (BOOLEAN) ReadField(RecognizedPartition);
RewritePartition = (BOOLEAN) ReadField(RewritePartition);
PartitionNumber = (ULONG) ReadField(PartitionNumber);
//
// Sanity check the data.
//
if ( (BootIndicator != TRUE && BootIndicator != FALSE) ||
(RecognizedPartition != TRUE && RecognizedPartition != FALSE) ||
(RewritePartition != TRUE && RewritePartition != FALSE) ) {
xdprintfEx (Depth, ("Invalid partition information at %p\n", Address));
}
if (PartitionNumber > PartitionCount) {
PartitionNumber = (ULONG)-1;
}
xdprintfEx (Depth, ("[%-2d] %-16I64x %-16I64x %2.2x %c %c %c\n",
PartitionNumber,
StartingOffset,
PartitionLength,
PartitionType,
BootIndicator ? 'x' : ' ',
RecognizedPartition ? 'x' : ' ',
RewritePartition ? 'x' : ' '
));
}
VOID
DumpDriveLayout(
IN ULONG64 Address,
IN ULONG Detail,
IN ULONG Depth
)
{
BOOL Succ;
ULONG Size;
ULONG i;
ULONG64 PartAddress;
ULONG result;
ULONG offset;
ULONG PartitionCount;
ULONG Signature;
ULONG OffsetOfFirstPartitionInfo;
ULONG SizeOfPartitionInfo;
InitTypeRead(Address, nt!_DRIVE_LAYOUT_INFORMATION);
PartitionCount = (ULONG) ReadField(PartitionCount);
Signature = (ULONG) ReadField(Signature);
xdprintfEx (Depth, ("\nDRIVE_LAYOUT %p\n", Address));
//
// Warn if the partition count is not a factor of 4. This is probably a
// bad partition information structure, but we'll continue on anyway.
//
if (PartitionCount % 4 != 0) {
xdprintfEx (Depth, ("WARNING: Partition count should be a factor of 4.\n"));
}
xdprintfEx (Depth, ("PartitionCount: %d\n", PartitionCount));
xdprintfEx (Depth, ("Signature: %8.8x\n\n", Signature));
xdprintfEx (Depth+1, (" ORD Offset Length Type BI RP RW\n"));
xdprintfEx (Depth+1, ("------------------------------------------------------------\n"));
result = GetFieldOffset("nt!_DRIVE_LAYOUT_INFORMATION",
"PartitionEntry[0]",
&offset);
if (result) {
SCSIKD_PRINT_ERROR(result);
return;
}
OffsetOfFirstPartitionInfo = offset;
result = GetFieldOffset("nt!_DRIVE_LAYOUT_INFORMATION",
"PartitionEntry[1]",
&offset);
if (result) {
SCSIKD_PRINT_ERROR(result);
return;
}
SizeOfPartitionInfo = offset - OffsetOfFirstPartitionInfo;
PartAddress = Address + OffsetOfFirstPartitionInfo;
for (i = 0; i < PartitionCount; i++) {
if (CheckControlC()) {
return;
}
DumpPartition(PartAddress, Detail, Depth+1, PartitionCount);
PartAddress += SizeOfPartitionInfo;
}
}
VOID
DumpPartitionEx(
IN ULONG64 Address,
IN ULONG Detail,
IN ULONG Depth,
IN ULONG PartitionCount
)
/*++
Routine Description:
Dump a PARTITION_INFORMATION_EX structure.
Arguments:
Address - The address of the partition information structure to dump.
Detail - The detail level. Currently unused.
Depth - The depth to indent to.
PartitionCount - The number of partitions. This is used to determine
whether a particular partition ordinal is valid or not.
Return Value:
None.
--*/
{
BOOL Succ;
ULONG Size;
ULONG result;
ULONG offset;
ULONG PartitionStyle;
ULONG PartitionNumber;
ULONG64 StartingOffset;
ULONG64 PartitionLength;
BOOLEAN RewritePartition;
UCHAR MbrPartitionType;
BOOLEAN MbrBootIndicator;
BOOLEAN MbrRecognizedPartition;
ULONG64 GptAttributes;
GUID GptPartitionType;
GUID GptPartitionId;
ULONG64 AddrOfGuid;
WCHAR GptName[36];
InitTypeRead (Address, nt!_PARTITION_INFORMATION_EX);
PartitionStyle = (ULONG) ReadField(PartitionStyle);
if (PartitionStyle != PARTITION_STYLE_MBR &&
PartitionStyle != PARTITION_STYLE_GPT) {
SCSIKD_PRINT_ERROR(0);
return;
}
PartitionNumber = (ULONG) ReadField(PartitionNumber);
StartingOffset = ReadField(StartingOffset.QuadPart);
PartitionLength = ReadField(PartitionLength.QuadPart);
RewritePartition = (BOOLEAN) ReadField(RewritePartition);
//
// We use -1 to denote an invalid partition ordinal.
//
if (PartitionNumber >= PartitionCount) {
PartitionNumber = (ULONG)-1;
}
InitTypeRead (Address, nt!_PARTITION_INFORMATION_EX);
if (PartitionStyle == PARTITION_STYLE_MBR) {
MbrPartitionType = (UCHAR) ReadField(Mbr.PartitionType);
MbrBootIndicator = (BOOLEAN) ReadField(Mbr.BootIndicator);
MbrRecognizedPartition = (BOOLEAN) ReadField(Mbr.RecognizedPartition);
xdprintfEx (Depth, ("[%-2d] %-16I64x %-16I64x %2.2x %c %c %c\n",
PartitionNumber,
StartingOffset,
PartitionLength,
MbrPartitionType,
MbrBootIndicator ? 'x' : ' ',
MbrRecognizedPartition ? 'x' : ' ',
RewritePartition ? 'x' : ' '
));
} else {
GptAttributes = ReadField(Gpt.Attributes);
result = GetFieldOffset("nt!_PARTITION_INFORMATION_EX",
"Gpt.PartitionType",
&offset);
if (result) {
SCSIKD_PRINT_ERROR(result);
return;
}
AddrOfGuid = Address + offset;
Succ = ReadMemory (
AddrOfGuid,
&GptPartitionType,
sizeof (GUID),
&Size
);
if (!Succ || Size != sizeof (GUID)) {
SCSIKD_PRINT_ERROR(0);
return;
}
//
// PartitionId immediately follows the PartitionType. So all we have to do
// is add sizeof(GUID) to the address and read PartitionId.
//
AddrOfGuid += sizeof(GUID);
Succ = ReadMemory (
AddrOfGuid,
&GptPartitionId,
sizeof (GUID),
&Size
);
if (!Succ || Size != sizeof (GUID)) {
SCSIKD_PRINT_ERROR(0);
return;
}
//
// Read in the Gpt.Name.
//
result = GetFieldOffset("nt!_PARTITION_INFORMATION_EX",
"Gpt.Name",
&offset);
if (result) {
SCSIKD_PRINT_ERROR(result);
return;
}
Succ = ReadMemory (
Address + offset,
&GptName,
sizeof (WCHAR) * 36,
&Size
);
if (!Succ || Size != sizeof (GUID)) {
SCSIKD_PRINT_ERROR(0);
return;
}
xdprintfEx (Depth, ("[%-2d] %S\n",
PartitionNumber, GptName));
xdprintfEx (Depth, ("OFF %-16I64x LEN %-16I64x ATTR %-16I64x R/W %c\n",
StartingOffset,
PartitionLength,
GptAttributes,
RewritePartition ? 'T' : 'F'));
xdprintfEx (Depth, ("TYPE %s\n",
GuidToString (&GptPartitionType)));
xdprintfEx (Depth, ("ID %s\n",
GuidToString (&GptPartitionId)));
xdprintfEx (Depth, ("\n"));
}
}
VOID
DumpDriveLayoutEx(
IN ULONG64 Address,
IN ULONG Detail,
IN ULONG Depth
)
{
ULONG result;
BOOL Succ;
ULONG Size;
ULONG i;
ULONG offset;
ULONG64 AddrOfDiskId;
ULONG PartitionStyle;
ULONG PartitionCount;
ULONG MbrSignature;
GUID GptDiskId;
ULONG64 GptStartingUsableOffset;
ULONG64 GptUsableLength;
ULONG GptMaxPartitionCount;
ULONG SizeOfPartitionEntry;
ULONG OffsetOfFirstPartitionEntry;
InitTypeRead(Address, nt!_DRIVE_LAYOUT_INFORMATION_EX);
PartitionStyle = (ULONG)ReadField(PartitionStyle);
PartitionCount = (ULONG)ReadField(PartitionCount);
MbrSignature = (ULONG)ReadField(Mbr.Signature);
GptStartingUsableOffset = ReadField(Gpt.StartingUsableOffset.QuadPart);
GptUsableLength = ReadField(Gpt.UsableLength.QuadPart);
GptMaxPartitionCount = (ULONG)ReadField(Gpt.MaxPartitionCount);
result = GetFieldOffset("nt!_DRIVE_LAYOUT_INFORMATION_EX",
"Gpt.DiskId",
&offset);
if (result) {
SCSIKD_PRINT_ERROR(result);
return;
}
AddrOfDiskId = Address + offset;
Succ = ReadMemory(
AddrOfDiskId,
&GptDiskId,
sizeof(GUID),
&Size);
if (!Succ || Size != sizeof(GUID)) {
SCSIKD_PRINT_ERROR(result);
return;
}
xdprintfEx (Depth, ("\nDRIVE_LAYOUT_EX %p\n", Address));
if (PartitionStyle != PARTITION_STYLE_MBR &&
PartitionStyle != PARTITION_STYLE_GPT) {
xdprintfEx (Depth, ("ERROR: invalid partition style %d\n", PartitionStyle));
return;
}
if (PartitionStyle == PARTITION_STYLE_MBR &&
PartitionCount % 4 != 0) {
xdprintfEx (Depth, ("WARNING: Partition count is not a factor of 4, (%d)\n",
PartitionCount));
}
if (PartitionStyle == PARTITION_STYLE_MBR) {
xdprintfEx (Depth, ("Signature: %8.8x\n", MbrSignature));
xdprintfEx (Depth, ("PartitionCount %d\n\n", PartitionCount));
xdprintfEx (Depth+1, (" ORD Offset Length Type BI RP RW\n"));
xdprintfEx (Depth+1, ("------------------------------------------------------------\n"));
} else {
xdprintfEx (Depth, ("DiskId: %s\n", GuidToString (&GptDiskId)));
xdprintfEx (Depth, ("StartingUsableOffset: %I64x\n", GptStartingUsableOffset));
xdprintfEx (Depth, ("UsableLength: %I64x\n", GptUsableLength));
xdprintfEx (Depth, ("MaxPartitionCount: %d\n", GptMaxPartitionCount));
xdprintfEx (Depth, ("PartitionCount %d\n\n", PartitionCount));
}
result = GetFieldOffset("nt!_DRIVE_LAYOUT_INFORMATION_EX",
"PartitionEntry[i]",
&offset);
if (result) {
SCSIKD_PRINT_ERROR(result);
return;
}
OffsetOfFirstPartitionEntry = offset;
Address += offset;
result = GetFieldOffset("nt!_DRIVE_LAYOUT_INFORMATION_EX",
"PartitionEntry[1]",
&offset);
if (result) {
SCSIKD_PRINT_ERROR(result);
return;
}
SizeOfPartitionEntry = offset - OffsetOfFirstPartitionEntry;
for (i = 0; i < PartitionCount; i++) {
if (CheckControlC()) {
return;
}
DumpPartitionEx(Address, Detail, Depth+1, PartitionCount);
Address += SizeOfPartitionEntry;
}
}
DECLARE_API (layout)
/*++
Routine Description:
Dump a DRIVE_LAYOUT structure with all it's partitions.
Arguments:
args - A string containing the address of the DRIVE_LAYOUT structure to
be dumped.
Return Value:
None.
--*/
{
ULONG64 Address;
ULONG Detail = 0;
GetAddressAndDetailLevel64 (args, &Address, &Detail);
DumpDriveLayout (Address, Detail, 0);
return S_OK;
}
DECLARE_API (layoutex)
/*++
Routine Description:
Dump a DRIVE_LAYOUT_EX structure and it's partitions.
Usage:
layoutex <address>
Arguments:
args - A string containing the address of the DRIVE_LAYOUT_EX structure
to be dumped.
Return Value:
None.
--*/
{
ULONG64 Address;
ULONG Detail = 0;
GetAddressAndDetailLevel64 (args, &Address, &Detail);
DumpDriveLayoutEx (Address, Detail, 0);
return S_OK;
}
DECLARE_API (part)
/*++
Routine Description:
Dump a PARTITION_INFORMATION structure.
Usage:
part <address>
Arguments:
args - A string containing the address of the PARTITION_INFORMATION
structure to be dumped.
Return Value:
None.
--*/
{
ULONG64 Address;
ULONG Detail = 0;
GetAddressAndDetailLevel64 (args, &Address, &Detail);
DumpPartition (Address, Detail, 0, 0);
return S_OK;
}
DECLARE_API (partex)
/*++
Routine Description:
Dump a PARTITION_INFORMATION_EX structure.
Usage:
partex <address>
Arguments:
args - A string containing the address of the PARTITION_INFORMATION_EX
structure to be dumped.
Return Value:
None.
--*/
{
ULONG64 Address;
ULONG Detail = 0;
GetAddressAndDetailLevel64 (args, &Address, &Detail);
DumpPartitionEx (Address, Detail, 0, 0);
return S_OK;
}