class2.c
来自「一个类似windows」· C语言 代码 · 共 2,461 行 · 第 1/5 页
C
2,461 行
return(STATUS_BUFFER_TOO_SMALL);
}
DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
/* Initialize next stack location for call to the port driver */
NextStack = IoGetNextIrpStackLocation(Irp);
NextStack->Parameters = Stack->Parameters;
NextStack->MajorFunction = Stack->MajorFunction;
NextStack->MinorFunction = Stack->MinorFunction;
/* Call port driver */
return(IoCallDriver(DeviceExtension->PortDeviceObject,
Irp));
}
if (IoControlCode == IOCTL_SCSI_GET_ADDRESS)
{
PSCSI_ADDRESS ScsiAddress;
if (OutputBufferLength < sizeof(SCSI_ADDRESS))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_BUFFER_TOO_SMALL);
}
ScsiAddress = Irp->AssociatedIrp.SystemBuffer;
ScsiAddress->Length = sizeof(SCSI_ADDRESS);
ScsiAddress->PortNumber = DeviceExtension->PortNumber;
ScsiAddress->PathId = DeviceExtension->PathId;
ScsiAddress->TargetId = DeviceExtension->TargetId;
ScsiAddress->Lun = DeviceExtension->Lun;
Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
if (IoControlCode == IOCTL_SCSI_PASS_THROUGH ||
IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
{
PSCSI_PASS_THROUGH ScsiPassThrough;
DPRINT("IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
/* Check input size */
if (InputBufferLength < sizeof(SCSI_PASS_THROUGH))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_INVALID_PARAMETER);
}
/* Initialize next stack location for call to the port driver */
NextStack = IoGetNextIrpStackLocation(Irp);
ScsiPassThrough = Irp->AssociatedIrp.SystemBuffer;
ScsiPassThrough->PathId = DeviceExtension->PathId;
ScsiPassThrough->TargetId = DeviceExtension->TargetId;
ScsiPassThrough->Lun = DeviceExtension->Lun;
ScsiPassThrough->Cdb[1] |= DeviceExtension->Lun << 5;
NextStack->Parameters = Stack->Parameters;
NextStack->MajorFunction = Stack->MajorFunction;
NextStack->MinorFunction = Stack->MinorFunction;
/* Call port driver */
return(IoCallDriver(DeviceExtension->PortDeviceObject,
Irp));
}
/* Allocate and initialize an SRB */
Srb = ExAllocateFromNPagedLookasideList(&DeviceExtension->SrbLookasideListHead);
if (Srb == NULL)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return(STATUS_INSUFFICIENT_RESOURCES);
}
/* Initialize the SRB */
RtlZeroMemory(Srb,
sizeof(SCSI_REQUEST_BLOCK));
Cdb = (PCDB)Srb->Cdb;
ModifiedControlCode = (IoControlCode & 0x0000FFFF) | (IOCTL_DISK_BASE << 16);
switch (ModifiedControlCode)
{
case IOCTL_DISK_CHECK_VERIFY:
DPRINT ("ScsiClassDeviceControl: IOCTL_DISK_CHECK_VERIFY\n");
if (OutputBufferLength != 0)
{
if (OutputBufferLength < sizeof(ULONG))
{
DPRINT ("ScsiClassDeviceControl: IOCTL_DISK_CHECK_VERIFY SMALL\n");
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
/* Free the SRB */
ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
Srb);
IoCompleteRequest (Irp,
IO_NO_INCREMENT);
return STATUS_BUFFER_TOO_SMALL;
}
/* Allocate new IRP for TEST UNIT READY scsi command */
SubIrp = IoAllocateIrp ((CCHAR)DeviceObject->StackSize + 3,
FALSE);
if (SubIrp == NULL)
{
DPRINT ("ScsiClassDeviceControl: IOCTL_DISK_CHECK_VERIFY NotEnuf\n");
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
/* Free the SRB */
ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
Srb);
IoCompleteRequest (Irp,
IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
SubIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
IoSetNextIrpStackLocation (SubIrp);
NextStack = IoGetCurrentIrpStackLocation (SubIrp);
NextStack->Parameters.Others.Argument1 = Irp;
NextStack->DeviceObject = DeviceObject;
IoSetCompletionRoutine (SubIrp,
ScsiClassCheckVerifyCompletion,
NULL,
TRUE,
TRUE,
TRUE);
DPRINT ("ScsiClassDeviceControl: IOCTL_DISK_CHECK_VERIFY IoSet\n");
IoSetNextIrpStackLocation (SubIrp);
NextStack = IoGetCurrentIrpStackLocation (SubIrp);
NextStack->DeviceObject = DeviceObject;
IoMarkIrpPending (Irp);
Irp = SubIrp;
}
/* Initialize SRB operation */
Srb->CdbLength = 6;
Srb->TimeOutValue = DeviceExtension->TimeOutValue;
Cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
DPRINT ("ScsiClassDeviceControl: IOCTL_DISK_CHECK_VERIFY SrbAsync\n");
return(ScsiClassSendSrbAsynchronous(DeviceObject,
Srb,
Irp,
NULL,
0,
FALSE));
default:
DPRINT("Unknown device io control code %lx\n",
ModifiedControlCode);
/* Free the SRB */
ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
Srb);
/* Pass the IOCTL down to the port driver */
NextStack = IoGetNextIrpStackLocation(Irp);
NextStack->Parameters = Stack->Parameters;
NextStack->MajorFunction = Stack->MajorFunction;
NextStack->MinorFunction = Stack->MinorFunction;
/* Call port driver */
return(IoCallDriver(DeviceExtension->PortDeviceObject,
Irp));
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_UNSUCCESSFUL);
}
/*
* @implemented
*/
PVOID STDCALL
ScsiClassFindModePage(IN PCHAR ModeSenseBuffer,
IN ULONG Length,
IN UCHAR PageMode,
IN BOOLEAN Use6Byte)
{
ULONG DescriptorLength;
ULONG HeaderLength;
PCHAR End;
PCHAR Ptr;
DPRINT("ScsiClassFindModePage() called\n");
/* Get header length */
HeaderLength = (Use6Byte) ? sizeof(MODE_PARAMETER_HEADER) : sizeof(MODE_PARAMETER_HEADER10);
/* Check header length */
if (Length < HeaderLength)
return NULL;
/* Get descriptor length */
if (Use6Byte == TRUE)
{
DescriptorLength = ((PMODE_PARAMETER_HEADER)ModeSenseBuffer)->BlockDescriptorLength;
}
else
{
DescriptorLength = ((PMODE_PARAMETER_HEADER10)ModeSenseBuffer)->BlockDescriptorLength[1];
}
/* Set page pointers */
Ptr = ModeSenseBuffer + HeaderLength + DescriptorLength;
End = ModeSenseBuffer + Length;
/* Search for page */
while (Ptr < End)
{
/* Check page code */
if (((PMODE_DISCONNECT_PAGE)Ptr)->PageCode == PageMode)
return Ptr;
/* Skip to next page */
Ptr += ((PMODE_DISCONNECT_PAGE)Ptr)->PageLength;
}
return NULL;
}
/*
* @implemented
*/
ULONG STDCALL
ScsiClassFindUnclaimedDevices(IN PCLASS_INIT_DATA InitializationData,
IN PSCSI_ADAPTER_BUS_INFO AdapterInformation)
{
PSCSI_INQUIRY_DATA UnitInfo;
PINQUIRYDATA InquiryData;
PUCHAR Buffer;
ULONG Bus;
ULONG UnclaimedDevices = 0;
DPRINT("ScsiClassFindUnclaimedDevices() called\n");
DPRINT("NumberOfBuses: %lu\n",AdapterInformation->NumberOfBuses);
Buffer = (PUCHAR)AdapterInformation;
for (Bus = 0; Bus < (ULONG)AdapterInformation->NumberOfBuses; Bus++)
{
DPRINT("Searching bus %lu\n", Bus);
UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterInformation->BusData[Bus].InquiryDataOffset);
while (AdapterInformation->BusData[Bus].InquiryDataOffset)
{
InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
DPRINT("Device: '%.8s'\n", InquiryData->VendorId);
if ((InitializationData->ClassFindDeviceCallBack(InquiryData) == TRUE) &&
(UnitInfo->DeviceClaimed == FALSE))
{
UnclaimedDevices++;
}
if (UnitInfo->NextInquiryDataOffset == 0)
break;
UnitInfo = (PSCSI_INQUIRY_DATA) (Buffer + UnitInfo->NextInquiryDataOffset);
}
}
return(UnclaimedDevices);
}
/*
* @implemented
*/
NTSTATUS STDCALL
ScsiClassGetCapabilities(IN PDEVICE_OBJECT PortDeviceObject,
OUT PIO_SCSI_CAPABILITIES *PortCapabilities)
{
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
KEVENT Event;
PIRP Irp;
KeInitializeEvent(&Event,
NotificationEvent,
FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES,
PortDeviceObject,
NULL,
0,
PortCapabilities,
sizeof(PVOID),
FALSE,
&Event,
&IoStatusBlock);
if (Irp == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
Status = IoCallDriver(PortDeviceObject,
Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,
Suspended,
KernelMode,
FALSE,
NULL);
Status = IoStatusBlock.Status;
}
DPRINT("PortCapabilities at %p\n", *PortCapabilities);
return(Status);
}
/*
* @implemented
*/
NTSTATUS STDCALL
ScsiClassGetInquiryData(IN PDEVICE_OBJECT PortDeviceObject,
IN PSCSI_ADAPTER_BUS_INFO *ConfigInfo)
{
PSCSI_ADAPTER_BUS_INFO Buffer;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
KEVENT Event;
PIRP Irp;
DPRINT("ScsiClassGetInquiryData() called\n");
*ConfigInfo = NULL;
Buffer = ExAllocatePool(NonPagedPool,
INQUIRY_DATA_SIZE);
if (Buffer == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
KeInitializeEvent(&Event,
NotificationEvent,
FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA,
PortDeviceObject,
NULL,
0,
Buffer,
INQUIRY_DATA_SIZE,
FALSE,
&Event,
&IoStatusBlock);
if (Irp == NULL)
{
ExFreePool(Buffer);
return(STATUS_INSUFFICIENT_RESOURCES);
}
Status = IoCallDriver(PortDeviceObject,
Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,
Suspended,
KernelMode,
FALSE,
NULL);
Status = IoStatusBlock.Status;
}
if (!NT_SUCCESS(Status))
{
ExFreePool(Buffer);
}
else
{
*ConfigInfo = Buffer;
}
DPRINT("ScsiClassGetInquiryData() done\n");
return(Status);
}
/*
* @implemented
*/
ULONG STDCALL
ScsiClassInitialize(IN PVOID Argument1,
IN PVOID Argument2,
IN PCLASS_INIT_DATA InitializationData)
{
PCONFIGURATION_INFORMATION ConfigInfo;
PDRIVER_OBJECT DriverObject = Argument1;
WCHAR NameBuffer[80];
UNICODE_STRING PortName;
ULONG PortNumber;
PDEVICE_OBJECT PortDeviceObject;
PFILE_OBJECT FileObject;
BOOLEAN DiskFound = FALSE;
NTSTATUS Status;
DPRINT("ScsiClassInitialize() called!\n");
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite;
DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassInternalIoControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceDispatch;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush;
if (InitializationData->ClassStartIo)
{
DriverObject->DriverStartIo = InitializationData->ClassStartIo;
}
ConfigInfo = IoGetConfigurationInformation();
DPRINT("ScsiPorts: %lu\n", ConfigInfo->ScsiPortCount);
/* look for ScsiPortX scsi port devices */
for (PortNumber = 0; PortNumber < ConfigInfo->ScsiPortCount; PortNumber++)
{
swprintf(NameBuffer,
L"\\Device\\ScsiPort%lu",
PortNumber);
RtlInitUnicodeString(&PortName,
NameBuffer);
DPRINT("Checking scsi port %ld\n", PortNumber);
Status = IoGetDeviceObjectPointer(&PortName,
FILE_READ_ATTRIBUTES,
&FileObject,
&PortDeviceObject);
DPRINT("Status 0x%08lX\n", Status);
if (NT_SUCCESS(Status))
{
DPRINT("ScsiPort%lu found.\n", PortNumber);
/* check scsi port for attached disk drives */
if (InitializationData->ClassFindDevices(DriverObject,
Argument2,
InitializationData,
PortDeviceObject,
PortNumber))
{
DiskFound = TRUE;
}
}
else
{
DbgPrint("Couldn't find ScsiPort%lu (Status %lx)\n", PortNumber, Status);
}
}
DPRINT("ScsiClassInitialize() done!\n");
return((DiskFound == TRUE) ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE);
}
/**********************************************************************
* NAME EXPORTED
* ScsiClassInitializeSrbLookasideList
*
* DESCRIPTION
* Initializes a lookaside list for SRBs.
*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?