📄 geometry.c
字号:
/*++
Copyright (C) Microsoft Corporation, 1991 - 1999
Module Name:
geometry.c
Abstract:
SCSI disk class driver - this module contains all the code for generating
disk geometries.
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include "disk.h"
#include "ntddstor.h"
#if defined (_X86_)
DISK_GEOMETRY_SOURCE
DiskUpdateGeometry(
IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension
);
NTSTATUS
DiskUpdateRemovableGeometry (
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
);
VOID
DiskScanBusDetectInfo(
IN PDRIVER_OBJECT DriverObject,
IN HANDLE BusKey
);
NTSTATUS
DiskSaveBusDetectInfo(
IN PDRIVER_OBJECT DriverObject,
IN HANDLE TargetKey,
IN ULONG DiskNumber
);
NTSTATUS
DiskSaveGeometryDetectInfo(
IN PDRIVER_OBJECT DriverObject,
IN HANDLE HardwareKey
);
NTSTATUS
DiskGetPortGeometry(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
OUT PDISK_GEOMETRY Geometry
);
typedef struct _DISK_DETECT_INFO {
BOOLEAN Initialized;
ULONG Style;
ULONG Signature;
ULONG MbrCheckSum;
PDEVICE_OBJECT Device;
CM_INT13_DRIVE_PARAMETER DriveParameters;
} DISK_DETECT_INFO, *PDISK_DETECT_INFO;
//
// Information about the disk geometries collected and saved into the registry
// by NTDETECT.COM or the system firmware.
//
PDISK_DETECT_INFO DetectInfoList = NULL;
ULONG DetectInfoCount = 0;
ULONG DetectInfoUsedCount = 0;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DiskSaveDetectInfo)
#pragma alloc_text(INIT, DiskScanBusDetectInfo)
#pragma alloc_text(INIT, DiskSaveBusDetectInfo)
#pragma alloc_text(INIT, DiskSaveGeometryDetectInfo)
#pragma alloc_text(PAGE, DiskUpdateGeometry)
#pragma alloc_text(PAGE, DiskUpdateRemovableGeometry)
#pragma alloc_text(PAGE, DiskGetPortGeometry)
#pragma alloc_text(PAGE, DiskGetDetectInfo)
#pragma alloc_text(PAGE, DiskReadSignature)
#endif
NTSTATUS
DiskSaveDetectInfo(
PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
This routine saves away the firmware information about the disks which has
been saved in the registry. It generates a list (DetectInfoList) which
contains the disk geometries, signatures & checksums of all drives which
were examined by NtDetect. This list is later used to assign geometries
to disks as they are initialized.
Arguments:
DriverObject - the driver being initialized. This is used to get to the
hardware database.
Return Value:
status.
--*/
{
OBJECT_ATTRIBUTES objectAttributes;
HANDLE hardwareKey;
UNICODE_STRING unicodeString;
HANDLE busKey;
NTSTATUS status;
PAGED_CODE();
InitializeObjectAttributes(
&objectAttributes,
DriverObject->HardwareDatabase,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
//
// Create the hardware base key.
//
status = ZwOpenKey(&hardwareKey, KEY_READ, &objectAttributes);
if(!NT_SUCCESS(status)) {
DebugPrint((1, "DiskSaveDetectInfo: Cannot open hardware data. "
"Name: %wZ\n",
DriverObject->HardwareDatabase));
return status;
}
status = DiskSaveGeometryDetectInfo(DriverObject, hardwareKey);
if(!NT_SUCCESS(status)) {
DebugPrint((1, "DiskSaveDetectInfo: Can't query configuration data "
"(%#08lx)\n",
status));
ZwClose(hardwareKey);
return status;
}
//
// Open EISA bus key.
//
RtlInitUnicodeString(&unicodeString, L"EisaAdapter");
InitializeObjectAttributes(&objectAttributes,
&unicodeString,
OBJ_CASE_INSENSITIVE,
hardwareKey,
NULL);
status = ZwOpenKey(&busKey,
KEY_READ,
&objectAttributes);
if(NT_SUCCESS(status)) {
DebugPrint((1, "DiskSaveDetectInfo: Opened EisaAdapter key\n"));
DiskScanBusDetectInfo(DriverObject, busKey);
ZwClose(busKey);
}
//
// Open MultiFunction bus key.
//
RtlInitUnicodeString(&unicodeString, L"MultifunctionAdapter");
InitializeObjectAttributes(&objectAttributes,
&unicodeString,
OBJ_CASE_INSENSITIVE,
hardwareKey,
NULL);
status = ZwOpenKey(&busKey,
KEY_READ,
&objectAttributes);
if(NT_SUCCESS(status)) {
DebugPrint((1, "DiskSaveDetectInfo: Opened MultifunctionAdapter key\n"));
DiskScanBusDetectInfo(DriverObject, busKey);
ZwClose(busKey);
}
ZwClose(hardwareKey);
return STATUS_SUCCESS;
}
VOID
DiskCleanupDetectInfo(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
This routine will cleanup the data structure built by DiskSaveDetectInfo.
Arguments:
DriverObject - a pointer to the kernel object for this driver.
Return Value:
none
--*/
{
if(DetectInfoList != NULL) {
ExFreePool(DetectInfoList);
DetectInfoList = NULL;
}
return;
}
NTSTATUS
DiskSaveGeometryDetectInfo(
IN PDRIVER_OBJECT DriverObject,
IN HANDLE HardwareKey
)
{
UNICODE_STRING unicodeString;
PKEY_VALUE_FULL_INFORMATION keyData;
ULONG length;
PCM_FULL_RESOURCE_DESCRIPTOR fullDescriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor;
PCM_INT13_DRIVE_PARAMETER driveParameters;
ULONG numberOfDrives;
ULONG i;
NTSTATUS status;
PAGED_CODE();
//
// Get disk BIOS geometry information.
//
RtlInitUnicodeString(&unicodeString, L"Configuration Data");
keyData = ExAllocatePoolWithTag(PagedPool,
VALUE_BUFFER_SIZE,
DISK_TAG_UPDATE_GEOM);
if(keyData == NULL) {
DebugPrint((1, "DiskSaveGeometryDetectInfo: Can't allocate config "
"data buffer\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
status = ZwQueryValueKey(HardwareKey,
&unicodeString,
KeyValueFullInformation,
keyData,
VALUE_BUFFER_SIZE,
&length);
if(!NT_SUCCESS(status)) {
DebugPrint((1, "DiskSaveGeometryDetectInfo: Can't query configuration "
"data (%#08lx)\n",
status));
ExFreePool(keyData);
return status;
}
//
// Extract the resource list out of the key data.
//
fullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
(((PUCHAR) keyData) + keyData->DataOffset);
partialDescriptor =
fullDescriptor->PartialResourceList.PartialDescriptors;
length = partialDescriptor->u.DeviceSpecificData.DataSize;
if((keyData->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) ||
(fullDescriptor->PartialResourceList.Count == 0) ||
(partialDescriptor->Type != CmResourceTypeDeviceSpecific) ||
(length < sizeof(ULONG))) {
DebugPrint((1, "DiskSaveGeometryDetectInfo: BIOS header data too small "
"or invalid\n"));
ExFreePool(keyData);
return STATUS_INVALID_PARAMETER;
}
//
// Point to the BIOS data. THe BIOS data is located after the first
// partial Resource list which should be device specific data.
//
{
PUCHAR buffer = (PUCHAR) keyData;
buffer += keyData->DataOffset;
buffer += sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
driveParameters = (PCM_INT13_DRIVE_PARAMETER) buffer;
}
numberOfDrives = length / sizeof(CM_INT13_DRIVE_PARAMETER);
//
// Allocate our detect info list now that we know how many entries there
// are going to be. No other routine allocates detect info and this is
// done out of DriverEntry so we don't need to synchronize it's creation.
//
length = sizeof(DISK_DETECT_INFO) * numberOfDrives;
DetectInfoList = ExAllocatePoolWithTag(PagedPool,
length,
DISK_TAG_UPDATE_GEOM);
if(DetectInfoList == NULL) {
DebugPrint((1, "DiskSaveGeometryDetectInfo: Couldn't allocate %x bytes "
"for DetectInfoList\n",
length));
ExFreePool(keyData);
return STATUS_INSUFFICIENT_RESOURCES;
}
DetectInfoCount = numberOfDrives;
RtlZeroMemory(DetectInfoList, length);
//
// Copy the information out of the key data and into the list we've
// allocated.
//
for(i = 0; i < numberOfDrives; i++) {
DetectInfoList[i].DriveParameters = driveParameters[i];
}
ExFreePool(keyData);
return STATUS_SUCCESS;
}
VOID
DiskScanBusDetectInfo(
IN PDRIVER_OBJECT DriverObject,
IN HANDLE BusKey
)
/*++
Routine Description:
The routine queries the registry to determine which disks are visible to
the BIOS. If a disk is visable to the BIOS then the geometry information
is updated with the disk's signature and MBR checksum.
Arguments:
DriverObject - the object for this driver.
BusKey - handle to the bus key to be enumerated.
Return Value:
status
--*/
{
ULONG busNumber;
NTSTATUS status;
for(busNumber = 0; ; busNumber++) {
WCHAR buffer[32];
UNICODE_STRING unicodeString;
OBJECT_ATTRIBUTES objectAttributes;
HANDLE spareKey;
HANDLE adapterKey;
ULONG adapterNumber;
DebugPrint((1, "DiskScanBusDetectInfo: Scanning bus %d\n", busNumber));
//
// Open controller name key.
//
swprintf(buffer, L"%d", busNumber);
RtlInitUnicodeString(&unicodeString, buffer);
InitializeObjectAttributes(&objectAttributes,
&unicodeString,
OBJ_CASE_INSENSITIVE,
BusKey,
NULL);
status = ZwOpenKey(&spareKey, KEY_READ, &objectAttributes);
if(!NT_SUCCESS(status)) {
DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening bus "
"key %#x\n",
status, busNumber));
break;
}
//
// Open up a controller ordinal key.
//
RtlInitUnicodeString(&unicodeString, L"DiskController");
InitializeObjectAttributes(&objectAttributes,
&unicodeString,
OBJ_CASE_INSENSITIVE,
spareKey,
NULL);
status = ZwOpenKey(&adapterKey, KEY_READ, &objectAttributes);
ZwClose(spareKey);
if(!NT_SUCCESS(status)) {
DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening "
"DiskController key\n",
status));
continue;
}
for(adapterNumber = 0; ; adapterNumber++) {
HANDLE diskKey;
ULONG diskNumber;
//
// Open disk key.
//
DebugPrint((1, "DiskScanBusDetectInfo: Scanning disk key "
"%d\\DiskController\\%d\\DiskPeripheral\n",
busNumber, adapterNumber));
swprintf(buffer, L"%d\\DiskPeripheral", adapterNumber);
RtlInitUnicodeString(&unicodeString, buffer);
InitializeObjectAttributes(&objectAttributes,
&unicodeString,
OBJ_CASE_INSENSITIVE,
adapterKey,
NULL);
status = ZwOpenKey(&diskKey, KEY_READ, &objectAttributes);
if(!NT_SUCCESS(status)) {
DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening "
"disk key\n",
status));
break;
}
for(diskNumber = 0; ; diskNumber++) {
HANDLE targetKey;
DebugPrint((1, "DiskScanBusDetectInfo: Scanning target key "
"%d\\DiskController\\%d\\DiskPeripheral\\%d\n",
busNumber, adapterNumber, diskNumber));
swprintf(buffer, L"%d", diskNumber);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -