disk.c
来自「一个类似windows」· C语言 代码 · 共 2,090 行 · 第 1/5 页
C
2,090 行
/*
* ReactOS kernel
* Copyright (C) 2001, 2002, 2003, 2004 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.
*/
/* $Id: disk.c 21534 2006-04-09 17:58:43Z peterw $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/storage/disk/disk.c
* PURPOSE: disk class driver
* PROGRAMMER: Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include <ntddk.h>
#include <ntdddisk.h>
#include <scsi.h>
#include <ntddscsi.h>
#include <include/class2.h>
#include <stdio.h>
#define NDEBUG
#include <debug.h>
#define VERSION "0.0.1"
#define SCSI_DISK_TIMEOUT 10 /* Default timeout: 10 seconds */
#define MODE_DATA_SIZE 192
#define MAX_PATH 260
typedef struct _DISK_DATA
{
PDEVICE_EXTENSION NextPartition;
ULONG Signature;
ULONG MbrCheckSum;
ULONG HiddenSectors;
ULONG PartitionNumber;
ULONG PartitionOrdinal;
UCHAR PartitionType;
BOOLEAN BootIndicator;
BOOLEAN DriveNotReady;
} DISK_DATA, *PDISK_DATA;
BOOLEAN STDCALL
DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath,
PCLASS_INIT_DATA InitializationData,
PDEVICE_OBJECT PortDeviceObject,
ULONG PortNumber);
BOOLEAN STDCALL
DiskClassCheckDevice(IN PINQUIRYDATA InquiryData);
NTSTATUS STDCALL
DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static VOID
DiskClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension,
IN ULONG DeviceNumber);
static NTSTATUS
DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath, /* what's this used for? */
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber,
IN ULONG DiskNumber,
IN PIO_SCSI_CAPABILITIES Capabilities,
IN PSCSI_INQUIRY_DATA InquiryData,
IN PCLASS_INIT_DATA InitializationData);
NTSTATUS STDCALL
DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS STDCALL
DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static BOOLEAN
ScsiDiskSearchForDisk(IN PDEVICE_EXTENSION DeviceExtension,
IN HANDLE BusKey,
OUT PULONG DetectedDiskNumber);
static VOID
DiskClassUpdatePartitionDeviceObjects (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static VOID
ScsiDiskUpdateFixedDiskGeometry(IN PDEVICE_EXTENSION DeviceExtension);
static BOOLEAN
ScsiDiskCalcMbrCheckSum(IN PDEVICE_EXTENSION DeviceExtension,
OUT PULONG Checksum);
static NTSTATUS
DiskBuildPartitionTable(IN PDEVICE_OBJECT DiskDeviceObject,
IN PIRP Irp);
/* FUNCTIONS ****************************************************************/
/**********************************************************************
* NAME EXPORTED
* DriverEntry
*
* DESCRIPTION
* This function initializes the driver, locates and claims
* hardware resources, and creates various NT objects needed
* to process I/O requests.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* DriverObject
* System allocated Driver Object for this driver
*
* RegistryPath
* Name of registry driver service key
*
* RETURN VALUE
* Status
*/
NTSTATUS STDCALL
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
CLASS_INIT_DATA InitData;
DPRINT("Disk Class Driver %s\n",
VERSION);
DPRINT("RegistryPath '%wZ'\n",
RegistryPath);
RtlZeroMemory(&InitData,
sizeof(CLASS_INIT_DATA));
InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA);
InitData.DeviceType = FILE_DEVICE_DISK;
InitData.DeviceCharacteristics = 0;
InitData.ClassError = NULL; // DiskClassProcessError;
InitData.ClassReadWriteVerification = DiskClassCheckReadWrite;
InitData.ClassFindDeviceCallBack = DiskClassCheckDevice;
InitData.ClassFindDevices = DiskClassFindDevices;
InitData.ClassDeviceControl = DiskClassDeviceControl;
InitData.ClassShutdownFlush = DiskClassShutdownFlush;
InitData.ClassCreateClose = NULL;
InitData.ClassStartIo = NULL;
return(ScsiClassInitialize(DriverObject,
RegistryPath,
&InitData));
}
/**********************************************************************
* NAME EXPORTED
* DiskClassFindDevices
*
* DESCRIPTION
* This function searches for device that are attached to the
* given scsi port.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* DriverObject
* System allocated Driver Object for this driver
*
* RegistryPath
* Name of registry driver service key
*
* InitializationData
* Pointer to the main initialization data
*
* PortDeviceObject
* Pointer to the port Device Object
*
* PortNumber
* Port number
*
* RETURN VALUE
* TRUE: At least one disk drive was found
* FALSE: No disk drive found
*/
BOOLEAN STDCALL
DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath,
PCLASS_INIT_DATA InitializationData,
PDEVICE_OBJECT PortDeviceObject,
ULONG PortNumber)
{
PCONFIGURATION_INFORMATION ConfigInfo;
PIO_SCSI_CAPABILITIES PortCapabilities;
PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
PSCSI_INQUIRY_DATA UnitInfo;
PINQUIRYDATA InquiryData;
PCHAR Buffer;
ULONG Bus;
ULONG DeviceCount;
BOOLEAN FoundDevice = FALSE;
NTSTATUS Status;
DPRINT("DiskClassFindDevices() called.\n");
/* Get port capabilities */
Status = ScsiClassGetCapabilities(PortDeviceObject,
&PortCapabilities);
if (!NT_SUCCESS(Status))
{
DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status);
return(FALSE);
}
DPRINT("PortCapabilities: %p\n", PortCapabilities);
DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength);
DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities->MaximumPhysicalPages);
/* Get inquiry data */
Status = ScsiClassGetInquiryData(PortDeviceObject,
(PSCSI_ADAPTER_BUS_INFO *)&Buffer);
if (!NT_SUCCESS(Status))
{
DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status);
return(FALSE);
}
/* Check whether there are unclaimed devices */
AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData,
AdapterBusInfo);
if (DeviceCount == 0)
{
DPRINT("No unclaimed devices!\n");
return(FALSE);
}
DPRINT("Found %lu unclaimed devices!\n", DeviceCount);
ConfigInfo = IoGetConfigurationInformation();
/* Search each bus of this adapter */
for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++)
{
DPRINT("Searching bus %lu\n", Bus);
UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset);
while (AdapterBusInfo->BusData[Bus].InquiryDataOffset)
{
InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
DPRINT("Device type %u\n", InquiryData->DeviceType);
if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
(InquiryData->DeviceType == OPTICAL_DEVICE)) &&
(InquiryData->DeviceTypeQualifier == 0) &&
(UnitInfo->DeviceClaimed == FALSE))
{
DPRINT("Vendor: '%.24s'\n",
InquiryData->VendorId);
/* Create device objects for disk */
Status = DiskClassCreateDeviceObject(DriverObject,
RegistryPath,
PortDeviceObject,
PortNumber,
ConfigInfo->DiskCount,
PortCapabilities,
UnitInfo,
InitializationData);
if (NT_SUCCESS(Status))
{
ConfigInfo->DiskCount++;
FoundDevice = TRUE;
}
}
if (UnitInfo->NextInquiryDataOffset == 0)
break;
UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset);
}
}
ExFreePool(Buffer);
DPRINT("DiskClassFindDevices() done\n");
return(FoundDevice);
}
static VOID
DiskClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension,
IN ULONG DeviceNumber)
{
DeviceExtension->MediaChangeEvent =
IoCreateSynchronizationEvent (NULL,
&DeviceExtension->MediaChangeEventHandle);
KeClearEvent (DeviceExtension->MediaChangeEvent);
}
/**********************************************************************
* NAME EXPORTED
* DiskClassCheckDevice
*
* DESCRIPTION
* This function checks the InquiryData for the correct device
* type and qualifier.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* InquiryData
* Pointer to the inquiry data for the device in question.
*
* RETURN VALUE
* TRUE: A disk device was found.
* FALSE: Otherwise.
*/
BOOLEAN STDCALL
DiskClassCheckDevice(IN PINQUIRYDATA InquiryData)
{
return((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE ||
InquiryData->DeviceType == OPTICAL_DEVICE) &&
InquiryData->DeviceTypeQualifier == 0);
}
/**********************************************************************
* NAME EXPORTED
* DiskClassCheckReadWrite
*
* DESCRIPTION
* This function checks the given IRP for correct data.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* DeviceObject
* Pointer to the device.
*
* Irp
* Irp to check.
*
* RETURN VALUE
* STATUS_SUCCESS: The IRP matches the requirements of the given device.
* Others: Failure.
*/
NTSTATUS STDCALL
DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
PDISK_DATA DiskData;
PIO_STACK_LOCATION IrpStack;
LARGE_INTEGER EndingOffset;
DPRINT("DiskClassCheckReadWrite() called\n");
DeviceExtension = DeviceObject->DeviceExtension;
DiskData = (PDISK_DATA)(DeviceExtension + 1);
if (DiskData->DriveNotReady == TRUE)
{
Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
IoSetHardErrorOrVerifyDevice(Irp,
DeviceObject);
return(STATUS_INVALID_PARAMETER);
}
IrpStack = IoGetCurrentIrpStackLocation(Irp);
EndingOffset.QuadPart = IrpStack->Parameters.Read.ByteOffset.QuadPart +
IrpStack->Parameters.Read.Length;
DPRINT("Ending %I64d, and RealEnding %I64d! PartSize %I64d\n",EndingOffset.QuadPart,
DeviceExtension->PartitionLength.QuadPart,
DeviceExtension->PartitionLength.QuadPart /
DeviceExtension->DiskGeometry->BytesPerSector);
if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
(DeviceExtension->DiskGeometry->MediaType == RemovableMedia))
{
/* Assume if removable media and if Partition length is 0, Partition not built yet! */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?