📄 cdrom.c
字号:
/*--
Copyright (C) Microsoft Corporation, 1991 - 1999
Module Name:
cdrom.c
Abstract:
The CDROM class driver tranlates IRPs to SRBs with embedded CDBs
and sends them to its devices through the port driver.
Environment:
kernel mode only
Notes:
SCSI Tape, CDRom and Disk class drivers share common routines
that can be found in the CLASS directory (..\ntos\dd\class).
Revision History:
--*/
#include "stddef.h"
#include "string.h"
#include "ntddk.h"
#include "ntddcdvd.h"
#include "classpnp.h"
#include "initguid.h"
#include "ntddstor.h"
#include "cdrom.h"
#include "cdrom.tmh"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, CdRomUnload)
#pragma alloc_text(PAGE, CdRomAddDevice)
#pragma alloc_text(PAGE, CdRomCreateDeviceObject)
#pragma alloc_text(PAGE, CdRomStartDevice)
#pragma alloc_text(PAGE, ScanForSpecial)
#pragma alloc_text(PAGE, ScanForSpecialHandler)
#pragma alloc_text(PAGE, CdRomRemoveDevice)
#pragma alloc_text(PAGE, CdRomGetDeviceType)
#pragma alloc_text(PAGE, CdRomReadWriteVerification)
#pragma alloc_text(PAGE, CdRomGetDeviceParameter)
#pragma alloc_text(PAGE, CdRomSetDeviceParameter)
#pragma alloc_text(PAGE, CdRomPickDvdRegion)
#pragma alloc_text(PAGE, CdRomIsPlayActive)
#pragma alloc_text(PAGEHITA, HitachiProcessError)
#pragma alloc_text(PAGEHIT2, HitachiProcessErrorGD2000)
#pragma alloc_text(PAGETOSH, ToshibaProcessErrorCompletion)
#pragma alloc_text(PAGETOSH, ToshibaProcessError)
#endif
#define IS_WRITE_REQUEST(irpStack) \
(irpStack->MajorFunction == IRP_MJ_WRITE)
#define IS_READ_WRITE_REQUEST(irpStack) \
((irpStack->MajorFunction == IRP_MJ_READ) || \
(irpStack->MajorFunction == IRP_MJ_WRITE) || \
((irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) && \
(irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_RAW_READ)))
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This routine initializes the cdrom class driver.
Arguments:
DriverObject - Pointer to driver object created by system.
RegistryPath - Pointer to the name of the services node for this driver.
Return Value:
The function value is the final status from the initialization operation.
--*/
{
CLASS_INIT_DATA InitializationData = {0};
PCDROM_DRIVER_EXTENSION driverExtension;
NTSTATUS status;
PAGED_CODE();
WPP_INIT_TRACING(DriverObject, RegistryPath);
TraceLog((CdromDebugTrace,
"CDROM.SYS DriverObject %p loading\n", DriverObject));
status = IoAllocateDriverObjectExtension(DriverObject,
CDROM_DRIVER_EXTENSION_ID,
sizeof(CDROM_DRIVER_EXTENSION),
&driverExtension);
if (!NT_SUCCESS(status)) {
TraceLog((CdromDebugWarning,
"DriverEntry !! no DriverObjectExtension %x\n", status));
return status;
}
//
// always zero the memory, since we are now reloading the driver.
//
RtlZeroMemory(driverExtension, sizeof(CDROM_DRIVER_EXTENSION));
//
// Zero InitData
//
RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA));
//
// Set sizes
//
InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
InitializationData.FdoData.DeviceExtensionSize = DEVICE_EXTENSION_SIZE;
InitializationData.FdoData.DeviceType = FILE_DEVICE_CD_ROM;
InitializationData.FdoData.DeviceCharacteristics =
FILE_REMOVABLE_MEDIA | FILE_DEVICE_SECURE_OPEN;
//
// Set entry points
//
InitializationData.FdoData.ClassError = CdRomErrorHandler;
InitializationData.FdoData.ClassInitDevice = CdRomInitDevice;
InitializationData.FdoData.ClassStartDevice = CdRomStartDevice;
InitializationData.FdoData.ClassStopDevice = CdRomStopDevice;
InitializationData.FdoData.ClassRemoveDevice = CdRomRemoveDevice;
InitializationData.FdoData.ClassReadWriteVerification = CdRomReadWriteVerification;
InitializationData.FdoData.ClassDeviceControl = CdRomDeviceControlDispatch;
InitializationData.FdoData.ClassPowerDevice = ClassSpinDownPowerHandler;
InitializationData.FdoData.ClassShutdownFlush = CdRomShutdownFlush;
InitializationData.FdoData.ClassCreateClose = NULL;
InitializationData.ClassStartIo = CdRomStartIo;
InitializationData.ClassAddDevice = CdRomAddDevice;
InitializationData.ClassTick = CdRomTickHandler;
InitializationData.ClassUnload = CdRomUnload;
//
// Call the class init routine
//
return ClassInitialize( DriverObject, RegistryPath, &InitializationData);
} // end DriverEntry()
VOID
CdRomUnload(
IN PDRIVER_OBJECT DriverObject
)
{
PAGED_CODE();
UNREFERENCED_PARAMETER(DriverObject);
TraceLog((CdromDebugTrace,
"CDROM.SYS DriverObject %p unloading\n", DriverObject));
WPP_CLEANUP(DriverObject);
return;
} // end CdRomUnload()
NTSTATUS
CdRomAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
This routine creates and initializes a new FDO for the corresponding
PDO. It may perform property queries on the FDO but cannot do any
media access operations.
Arguments:
DriverObject - CDROM class driver object.
Pdo - the physical device object we are being added to
Return Value:
status
--*/
{
NTSTATUS status;
PAGED_CODE();
//
// Get the address of the count of the number of cdroms already initialized.
//
status = CdRomCreateDeviceObject(DriverObject,
PhysicalDeviceObject);
//
// Note: this always increments driver extension counter
// it will eventually wrap, and fail additions
// if an existing cdrom has the given number.
// so unlikely that we won't even bother considering
// this case, since the cure is quite likely worse
// than the symptoms.
//
if(NT_SUCCESS(status)) {
//
// keep track of the total number of active cdroms in IoGet(),
// as some programs use this to determine when they have found
// all the cdroms in the system.
//
TraceLog((CdromDebugTrace, "CDROM.SYS Add succeeded\n"));
IoGetConfigurationInformation()->CdRomCount++;
} else {
TraceLog((CdromDebugWarning,
"CDROM.SYS Add failed! %x\n", status));
}
return status;
}
NTSTATUS
CdRomCreateDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
This routine creates an object for the device and then calls the
SCSI port driver for media capacity and sector size.
Arguments:
DriverObject - Pointer to driver object created by system.
PortDeviceObject - to connect to SCSI port driver.
DeviceCount - Number of previously installed CDROMs.
PortCapabilities - Pointer to structure returned by SCSI port
driver describing adapter capabilites (and limitations).
LunInfo - Pointer to configuration information for this device.
Return Value:
NTSTATUS
--*/
{
UCHAR ntNameBuffer[64] = {0};
STRING ntNameString = {0};
NTSTATUS status;
PDEVICE_OBJECT lowerDevice = NULL;
PDEVICE_OBJECT deviceObject = NULL;
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;
PCDROM_DATA cdData = NULL;
PCDROM_DRIVER_EXTENSION driverExtension = NULL;
ULONG deviceNumber;
CCHAR dosNameBuffer[64] = {0};
CCHAR deviceNameBuffer[64] = {0};
STRING deviceNameString = {0};
STRING dosString = {0};
UNICODE_STRING dosUnicodeString = {0};
UNICODE_STRING unicodeString = {0};
PAGED_CODE();
//
// Claim the device. Note that any errors after this
// will goto the generic handler, where the device will
// be released.
//
lowerDevice = IoGetAttachedDeviceReference(PhysicalDeviceObject);
status = ClassClaimDevice(lowerDevice, FALSE);
if(!NT_SUCCESS(status)) {
//
// Someone already had this device - we're in trouble
//
ObDereferenceObject(lowerDevice);
return status;
}
//
// Create device object for this device by first getting a unique name
// for the device and then creating it.
//
driverExtension = IoGetDriverObjectExtension(DriverObject,
CDROM_DRIVER_EXTENSION_ID);
ASSERT(driverExtension != NULL);
//
// InterlockedCdRomCounter is biased by 1.
//
deviceNumber = InterlockedIncrement(&driverExtension->InterlockedCdRomCounter) - 1;
sprintf(ntNameBuffer, "\\Device\\CdRom%d", deviceNumber);
status = ClassCreateDeviceObject(DriverObject,
ntNameBuffer,
PhysicalDeviceObject,
TRUE,
&deviceObject);
if (!NT_SUCCESS(status)) {
TraceLog((CdromDebugWarning,
"CreateCdRomDeviceObjects: Can not create device %s\n",
ntNameBuffer));
goto CreateCdRomDeviceObjectExit;
}
//
// Indicate that IRPs should include MDLs.
//
SET_FLAG(deviceObject->Flags, DO_DIRECT_IO);
fdoExtension = deviceObject->DeviceExtension;
//
// Back pointer to device object.
//
fdoExtension->CommonExtension.DeviceObject = deviceObject;
//
// This is the physical device.
//
fdoExtension->CommonExtension.PartitionZeroExtension = fdoExtension;
//
// Initialize lock count to zero. The lock count is used to
// disable the ejection mechanism when media is mounted.
//
fdoExtension->LockCount = 0;
//
// Save system cdrom number
//
fdoExtension->DeviceNumber = deviceNumber;
//
// Set the alignment requirements for the device based on the
// host adapter requirements
//
if (lowerDevice->AlignmentRequirement > deviceObject->AlignmentRequirement) {
deviceObject->AlignmentRequirement = lowerDevice->AlignmentRequirement;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -