📄 cdrom.c
字号:
#ifdef _PPC_
NTSTATUS
FindScsiAdapter (
IN HANDLE KeyHandle,
IN UNICODE_STRING ScsiUnicodeString[],
OUT PUCHAR IntermediateController
);
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, DriverEntry)
#pragma alloc_text(PAGE, ScsiCdRomFindDevices)
#pragma alloc_text(PAGE, CreateCdRomDeviceObject)
#pragma alloc_text(PAGE, ScanForSpecial)
//#pragma alloc_text(PAGE, CdRomDeviceControl)
#pragma alloc_text(PAGE, HitachProcessError)
#pragma alloc_text(PAGE, CdRomIsPlayActive)
#pragma alloc_text(PAGE, ScsiCdRomReadVerification)
#pragma alloc_text(INIT, CdRomCheckRegistryForMediaChangeValue)
#pragma alloc_text(INIT, IsThisAnAtapiChanger)
#pragma alloc_text(INIT, IsThisASanyo)
#pragma alloc_text(INIT, IsThisAMultiLunDevice)
#pragma alloc_text(INIT, CdRomCreateNamedEvent)
#ifdef _PPC_
#pragma alloc_text(PAGE, FindScsiAdapter)
#endif
#endif
ULONG NoLoad = 0;
NTSTATUS
STDCALL
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;
if(NoLoad) {
return STATUS_NO_SUCH_DEVICE;
}
//
// Zero InitData
//
RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA));
//
// Set sizes
//
InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
InitializationData.DeviceExtensionSize = DEVICE_EXTENSION_SIZE;
InitializationData.DeviceType = FILE_DEVICE_CD_ROM;
InitializationData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_READ_ONLY_DEVICE;
//
// Set entry points
//
InitializationData.ClassReadWriteVerification = ScsiCdRomReadVerification;
InitializationData.ClassDeviceControl = CdRomDeviceControl;
InitializationData.ClassFindDevices = ScsiCdRomFindDevices;
InitializationData.ClassShutdownFlush = NULL;
InitializationData.ClassCreateClose = NULL;
InitializationData.ClassStartIo = ScsiCdRomStartIo;
//
// Call the class init routine
//
return ScsiClassInitialize( DriverObject, RegistryPath, &InitializationData);
} // end DriverEntry()
BOOLEAN
STDCALL
ScsiCdRomFindDevices(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PCLASS_INIT_DATA InitializationData,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber
)
/*++
Routine Description:
Connect to SCSI port driver. Get adapter capabilities and
SCSI bus configuration information. Search inquiry data
for CDROM devices to process.
Arguments:
DriverObject - CDROM class driver object.
PortDeviceObject - SCSI port driver device object.
PortNumber - The system ordinal for this scsi adapter.
Return Value:
TRUE if CDROM device present on this SCSI adapter.
--*/
{
PIO_SCSI_CAPABILITIES portCapabilities;
PULONG cdRomCount;
PCHAR buffer;
PSCSI_INQUIRY_DATA lunInfo;
PSCSI_ADAPTER_BUS_INFO adapterInfo;
PINQUIRYDATA inquiryData;
ULONG scsiBus;
NTSTATUS status;
BOOLEAN foundDevice = FALSE;
//
// Call port driver to get adapter capabilities.
//
status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities);
if (!NT_SUCCESS(status)) {
DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n"));
return foundDevice;
}
//
// Call port driver to get inquiry information to find cdroms.
//
status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer);
if (!NT_SUCCESS(status)) {
DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n"));
return foundDevice;
}
//
// Get the address of the count of the number of cdroms already initialized.
//
cdRomCount = &IoGetConfigurationInformation()->CdRomCount;
adapterInfo = (PVOID) buffer;
//
// For each SCSI bus this adapter supports ...
//
for (scsiBus=0; scsiBus < adapterInfo->NumberOfBuses; scsiBus++) {
//
// Get the SCSI bus scan data for this bus.
//
lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);
//
// Search list for unclaimed disk devices.
//
while (adapterInfo->BusData[scsiBus].InquiryDataOffset) {
inquiryData = (PVOID)lunInfo->InquiryData;
if ((inquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) &&
(inquiryData->DeviceTypeQualifier == 0) &&
(!lunInfo->DeviceClaimed)) {
DebugPrint((1,"FindScsiDevices: Vendor string is %.24s\n",
inquiryData->VendorId));
//
// Create device objects for cdrom
//
status = CreateCdRomDeviceObject(DriverObject,
PortDeviceObject,
PortNumber,
cdRomCount,
portCapabilities,
lunInfo,
InitializationData,
RegistryPath);
if (NT_SUCCESS(status)) {
//
// Increment system cdrom device count.
//
(*cdRomCount)++;
//
// Indicate that a cdrom device was found.
//
foundDevice = TRUE;
}
}
//
// Get next LunInfo.
//
if (lunInfo->NextInquiryDataOffset == 0) {
break;
}
lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
}
}
ExFreePool(buffer);
return foundDevice;
} // end FindScsiCdRoms()
VOID
STDCALL
CdRomCreateNamedEvent(
IN PDEVICE_EXTENSION DeviceExtension,
IN ULONG DeviceNumber
)
/*++
Routine Description:
Create the named synchronization event for notification of media change
events to the system. The event is reset before this function returns.
Arguments:
DeviceExtension - the device extension pointer for storage of the event pointer.
Return Value:
None.
--*/
{
UNICODE_STRING unicodeString;
OBJECT_ATTRIBUTES objectAttributes;
CCHAR eventNameBuffer[MAXIMUM_FILENAME_LENGTH];
STRING eventNameString;
HANDLE handle;
NTSTATUS status;
sprintf(eventNameBuffer,"\\Device\\MediaChangeEvent%d",
DeviceNumber);
RtlInitString(&eventNameString,
eventNameBuffer);
status = RtlAnsiStringToUnicodeString(&unicodeString,
&eventNameString,
TRUE);
if (!NT_SUCCESS(status)) {
return;
}
InitializeObjectAttributes(&objectAttributes,
&unicodeString,
OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
NULL,
NULL);
DeviceExtension->MediaChangeEvent = IoCreateSynchronizationEvent(&unicodeString,
&handle);
DeviceExtension->MediaChangeEventHandle = handle;
KeClearEvent(DeviceExtension->MediaChangeEvent);
RtlFreeUnicodeString(&unicodeString);
}
NTSTATUS
STDCALL
CreateCdRomDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber,
IN PULONG DeviceCount,
IN PIO_SCSI_CAPABILITIES PortCapabilities,
IN PSCSI_INQUIRY_DATA LunInfo,
IN PCLASS_INIT_DATA InitializationData,
IN PUNICODE_STRING RegistryPath
)
/*++
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];
STRING ntNameString;
UNICODE_STRING ntUnicodeString;
NTSTATUS status;
BOOLEAN changerDevice;
SCSI_REQUEST_BLOCK srb;
ULONG length;
PCDROM_DATA cddata;
PCDB cdb;
PVOID senseData = NULL;
PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_EXTENSION deviceExtension = NULL;
PUCHAR buffer;
ULONG bps;
ULONG lastBit;
ULONG timeOut;
BOOLEAN srbListInitialized = FALSE;
//
// Claim the device. Note that any errors after this
// will goto the generic handler, where the device will
// be released.
//
status = ScsiClassClaimDevice(PortDeviceObject,
LunInfo,
FALSE,
&PortDeviceObject);
if (!NT_SUCCESS(status)) {
return(status);
}
//
// Create device object for this device.
//
sprintf(ntNameBuffer,
"\\Device\\CdRom%d",
*DeviceCount);
status = ScsiClassCreateDeviceObject(DriverObject,
ntNameBuffer,
NULL,
&deviceObject,
InitializationData);
if (!NT_SUCCESS(status)) {
DebugPrint((1,"CreateCdRomDeviceObjects: Can not create device %s\n",
ntNameBuffer));
RtlFreeUnicodeString(&ntUnicodeString);
goto CreateCdRomDeviceObjectExit;
}
//
// Indicate that IRPs should include MDLs.
//
deviceObject->Flags |= DO_DIRECT_IO;
//
// Set up required stack size in device object.
//
deviceObject->StackSize = PortDeviceObject->StackSize + 2;
deviceExtension = deviceObject->DeviceExtension;
//
// Allocate spinlock for split request completion.
//
KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
//
// This is the physical device.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -