|
|
/*++
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+1] = {0};
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(GptName)-sizeof(WCHAR), &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;
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[0]", &offset);
if (result) { SCSIKD_PRINT_ERROR(result); return; }
Address += offset;
for (i = 0; i < PartitionCount; i++) { if (CheckControlC()) { return; }
DumpPartitionEx(Address, Detail, Depth + 1, PartitionCount);
Address += sizeof(PARTITION_INFORMATION_EX); } }
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 = 0; ULONG64 detail = 0;
if (GetExpressionEx(args, &Address, &args)) { GetExpressionEx(args, &detail, &args); }
DumpDriveLayout (Address, (ULONG)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 = 0; ULONG64 detail = 0;
if (GetExpressionEx(args, &Address, &args)) { GetExpressionEx(args, &detail, &args); }
DumpDriveLayoutEx (Address, (ULONG)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 = 0; ULONG64 detail = 0;
if (GetExpressionEx(args, &Address, &args)) { GetExpressionEx(args, &detail, &args); }
DumpPartition (Address, (ULONG)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 = 0; ULONG64 detail = 0;
if (GetExpressionEx(args, &Address, &args)) { GetExpressionEx(args, &detail, &args); }
DumpPartitionEx (Address, (ULONG)detail, 0, 0);
return S_OK; }
|