windows-nt/Source/XPSP1/NT/printscan/wia/kernel/qv2kux/qv2kux.c
2020-09-26 16:20:57 +08:00

522 lines
14 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//----------------- Original Sig ------------------------
/*++
Copyright (c) 1991-1999 Microsoft Corporation
Module Name:
fpfilter.c
--*/
#define INITGUID
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "usbdi.h"
#include "usbdlib.h"
//
// Bit Flag Macros
//
#define SET_FLAG(Flags, Bit) ((Flags) |= (Bit))
#define CLEAR_FLAG(Flags, Bit) ((Flags) &= ~(Bit))
#define TEST_FLAG(Flags, Bit) (((Flags) & (Bit)) != 0)
//
// Remove lock
//
#define REMLOCK_TAG 'QV2K'
#define REMLOCK_MAXIMUM 1 // Max minutes system allows lock to be held
#define REMLOCK_HIGHWATER 250 // Max number of irps holding lock at one time
//
// Device Extension
//
typedef struct _FDO_EXTENSION {
ULONG Signature;
PDEVICE_OBJECT Fdo; // Back pointer to Fdo
PDEVICE_OBJECT Pdo; // Not Used
PDEVICE_OBJECT Ldo; // Lower Device Object
PDEVICE_OBJECT PhysicalDeviceObject; // Not Used
KEVENT SyncEvent; // for ForwardIrpSynchronous
} FDO_EXTENSION, *PFDO_EXTENSION;
#define FDO_EXTENSION_SIZE sizeof(FDO_EXTENSION)
//
// Function declarations
//
NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS QV2KUX_AddDevice ( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
VOID QV2KUX_Unload ( IN PDRIVER_OBJECT DriverObject );
NTSTATUS QV2KUX_ForwardIrpSynchronous( IN PDEVICE_OBJECT Fdo, IN PIRP Irp);
NTSTATUS QV2KUX_DispatchPnp ( IN PDEVICE_OBJECT Fdo, IN PIRP Irp);
NTSTATUS QV2KUX_DispatchPower ( IN PDEVICE_OBJECT Fdo, IN PIRP Irp);
NTSTATUS QV2KUX_StartDevice ( IN PDEVICE_OBJECT Fdo, IN PIRP Irp);
NTSTATUS QV2KUX_RemoveDevice ( IN PDEVICE_OBJECT Fdo, IN PIRP Irp);
NTSTATUS QV2KUX_SendToNextDriver ( IN PDEVICE_OBJECT Fdo, IN PIRP Irp);
NTSTATUS QV2KUX_Internal_IOCTL ( IN PDEVICE_OBJECT Fdo, IN PIRP Irp);
NTSTATUS QV2KUX_IrpCompletion ( IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN PVOID Context);
VOID QV2KUX_SyncFilterWithLdo ( IN PDEVICE_OBJECT Fdo, IN PDEVICE_OBJECT Ldo);
#if DBG
#define DEBUG_BUFFER_LENGTH 256
ULONG QV2KUX_Debug = 0;
UCHAR QV2KUX_DebugBuffer[DEBUG_BUFFER_LENGTH];
VOID QV2KUX_DebugPrint( ULONG DebugPrintLevel, PCCHAR DebugMessage, ...);
#define DebugPrint(x) QV2KUX_DebugPrint x
#else
#define DebugPrint(x)
#endif
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
/*++
Routine Description:
<20><><EFBFBD><EFBFBD><EFBFBD>ł̓G<CD83><47><EFBFBD>g<EFBFBD><67><EFBFBD>[<5B>|<7C>C<EFBFBD><43><EFBFBD>g<EFBFBD>̐ݒ肾<DD92><E882BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Arguments:
DriverObject - The disk performance driver object.
RegistryPath - pointer to a unicode string representing the path,
to driver-specific key in the registry.
Return Value:
STATUS_SUCCESS
--*/
{
ULONG ulIndex;
PDRIVER_DISPATCH * dispatch;
// <20>Ƃ肠<C682><E882A0><EFBFBD><EFBFBD><EFBFBD>S<EFBFBD>ăo<C483>C<EFBFBD>p<EFBFBD>X<EFBFBD><58><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɐݒ<C990>
for (ulIndex = 0, dispatch = DriverObject->MajorFunction;
ulIndex <= IRP_MJ_MAXIMUM_FUNCTION;
ulIndex++, dispatch++) {
*dispatch = QV2KUX_SendToNextDriver;
}
// <20><><EFBFBD>L<EFBFBD>̐ݒ<CC90><DD92>ł͂܂<CD82><DC82><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̕ύX
DriverObject->MajorFunction[IRP_MJ_POWER] = QV2KUX_DispatchPower;
DriverObject->DriverUnload = QV2KUX_Unload;
//<2F>Œ<EFBFBD><C592><EFBFBD><EFBFBD>K<EFBFBD>v<EFBFBD>Ȃ<EFBFBD><C882><EFBFBD>
DriverObject->MajorFunction[IRP_MJ_PNP] = QV2KUX_DispatchPnp;
DriverObject->DriverExtension->AddDevice = QV2KUX_AddDevice;
// <20><><EFBFBD><EFBFBD><EFBFBD>I<EFBFBD>ɂ<EFBFBD><C982><EFBFBD><E882BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = QV2KUX_Internal_IOCTL;
return(STATUS_SUCCESS);
} // end DriverEntry()
#define FILTER_DEVICE_PROPOGATE_FLAGS 0
#define FILTER_DEVICE_PROPOGATE_CHARACTERISTICS (FILE_REMOVABLE_MEDIA | \
FILE_READ_ONLY_DEVICE | \
FILE_FLOPPY_DISKETTE \
)
VOID QV2KUX_SyncFilterWithLdo( IN PDEVICE_OBJECT Fdo, IN PDEVICE_OBJECT Ldo)
{
ULONG propFlags;
//
// Propogate all useful flags from target to QV2KUX_. MountMgr will look
// at the QV2KUX_ object capabilities to figure out if the disk is
// a removable and perhaps other things.
//
propFlags = Ldo->Flags & FILTER_DEVICE_PROPOGATE_FLAGS;
SET_FLAG(Fdo->Flags, propFlags);
propFlags = Ldo->Characteristics & FILTER_DEVICE_PROPOGATE_CHARACTERISTICS;
SET_FLAG(Fdo->Characteristics, propFlags);
}
NTSTATUS QV2KUX_AddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)
/*++
Routine Description:
DeviceObject<63>̍쐻<CC8D>Ƃ<EFBFBD><C682><EFBFBD>DeviceExtension<6F>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD>
<20><><EFBFBD>̃v<CC83><76><EFBFBD>O<EFBFBD><4F><EFBFBD><EFBFBD><EFBFBD>ł́APDO<44>͍쐻<CD8D><EC90BB><EFBFBD>Ȃ<EFBFBD><C882><EFBFBD>FDO<44>̂ݎg<DD8E>p<EFBFBD><70><EFBFBD><EFBFBD>
Arguments:
DriverObject - Disk performance driver object.
PhysicalDeviceObject - Physical Device Object from the underlying layered driver
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
PDEVICE_OBJECT Fdo;
PFDO_EXTENSION fdoExtension;
PIRP irp;
// Create a filter device object for this device (partition).
DebugPrint((2, "QV2KUX_AddDevice: Driver %p Device %p\n", DriverObject, PhysicalDeviceObject));
status = IoCreateDevice(DriverObject, FDO_EXTENSION_SIZE, NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &Fdo);
if (!NT_SUCCESS(status)) {
DebugPrint((1, "QV2KUX_AddDevice: Cannot create Fdo\n"));
return status;
}
SET_FLAG(Fdo->Flags, DO_DIRECT_IO);
fdoExtension = Fdo->DeviceExtension;
RtlZeroMemory(fdoExtension, FDO_EXTENSION_SIZE);
fdoExtension->Signature = 'QV2K';
fdoExtension->Fdo = Fdo;
fdoExtension->PhysicalDeviceObject = PhysicalDeviceObject;
// <20><><EFBFBD>ʃh<CA83><68><EFBFBD>C<EFBFBD>o<EFBFBD>ɐڑ<C990>
fdoExtension->Ldo = IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);
if (fdoExtension->Ldo == NULL) {
IoDeleteDevice(Fdo);
DebugPrint((1, "QV2KUX_AddDevice: Unable to attach %X to target %X\n", Fdo, PhysicalDeviceObject));
return STATUS_NO_SUCH_DEVICE;
}
// ForwardIrpSynchronous<75>Ŏg<C58E>p<EFBFBD><70><EFBFBD><EFBFBD>
KeInitializeEvent(&fdoExtension->SyncEvent, NotificationEvent, FALSE);
// default to DO_POWER_PAGABLE
SET_FLAG(Fdo->Flags, DO_POWER_PAGABLE);
// Clear the DO_DEVICE_INITIALIZING flag
CLEAR_FLAG(Fdo->Flags, DO_DEVICE_INITIALIZING);
return STATUS_SUCCESS;
} // end QV2KUX_AddDevice()
NTSTATUS QV2KUX_DispatchPnp(IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
/*++
Routine Description:
Dispatch for PNP
Arguments:
Fdo - Supplies the device object.
Irp - Supplies the I/O request packet.
Return Value:
NTSTATUS
--*/
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status;
PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
BOOLEAN lockHeld;
BOOLEAN irpCompleted;
DebugPrint((2, "QV2KUX_DispatchPnp: Device %X Irp %X\n", Fdo, Irp));
irpCompleted = FALSE;
switch(irpSp->MinorFunction) {
case IRP_MN_START_DEVICE: status = QV2KUX_StartDevice(Fdo, Irp); break;
case IRP_MN_REMOVE_DEVICE: status = QV2KUX_RemoveDevice(Fdo, Irp); break;
default: status = QV2KUX_SendToNextDriver(Fdo, Irp); irpCompleted = TRUE; break;
}
if (! irpCompleted) {
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return status;
} // end QV2KUX_DispatchPnp()
NTSTATUS QV2KUX_IrpCompletion( IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN PVOID Context)
/*++
Routine Description:
Forwarded IRP completion routine. Set an event and return
STATUS_MORE_PROCESSING_REQUIRED. Irp forwarder will wait on this
event and then re-complete the irp after cleaning up.
Arguments:
Fdo is the device object of the WMI driver
Irp is the WMI irp that was just completed
Context is a PKEVENT that forwarder will wait on
Return Value:
STATUS_MORE_PORCESSING_REQUIRED
--*/
{
PKEVENT Event = (PKEVENT) Context;
UNREFERENCED_PARAMETER(Fdo);
UNREFERENCED_PARAMETER(Irp);
KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
// Irp<72><70><EFBFBD>܂<EFBFBD><DC82>g<EFBFBD><67><EFBFBD>A<EFBFBD><41><EFBFBD>ɂ<EFBFBD>Completion<6F><6E><EFBFBD>܂<EFBFBD><DC82>m<EFBFBD><EFBFBD>Ȃ<EFBFBD>
return(STATUS_MORE_PROCESSING_REQUIRED);
} // end QV2KUX_IrpCompletion()
NTSTATUS QV2KUX_StartDevice( IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
/*++
Routine Description:
This routine is called when a Pnp Start Irp is received.
It will schedule a completion routine to initialize and register with WMI.
Arguments:
Fdo - a pointer to the device object
Irp - a pointer to the irp
Return Value:
Status of processing the Start Irp
--*/
{
PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
KEVENT event;
NTSTATUS status;
status = QV2KUX_ForwardIrpSynchronous(Fdo, Irp);
QV2KUX_SyncFilterWithLdo(Fdo, fdoExtension->Ldo);
return status;
}
NTSTATUS QV2KUX_RemoveDevice( IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
/*++
Routine Description:
This routine is called when the device is to be removed.
It will de-register itself from WMI first, detach itself from the
stack before deleting itself.
Arguments:
Fdo - a pointer to the device object
Irp - a pointer to the irp
Return Value:
Status of removing the device
--*/
{
NTSTATUS status;
PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
status = QV2KUX_ForwardIrpSynchronous(Fdo, Irp);
IoDetachDevice(fdoExtension->Ldo);
IoDeleteDevice(Fdo);
return status;
}
NTSTATUS QV2KUX_SendToNextDriver( IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
/*++
Routine Description:
This routine sends the Irp to the next driver in line
when the Irp is not processed by this driver.
Arguments:
Fdo
Irp
Return Value:
NTSTATUS
--*/
{
PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(fdoExtension->Ldo, Irp);
} // end QV2KUX_SendToNextDriver()
NTSTATUS QV2KUX_DispatchPower( IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
{
PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(fdoExtension->Ldo, Irp);
} // end QV2KUX_DispatchPower
NTSTATUS QV2KUX_ForwardIrpSynchronous( IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
/*++
Routine Description:
This routine sends the Irp to the next driver in line
when the Irp needs to be processed by the lower drivers
prior to being processed by this one.
Arguments:
Fdo
Irp
Return Value:
NTSTATUS
--*/
{
PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
NTSTATUS status;
//<2F>C<EFBFBD>x<EFBFBD><78><EFBFBD>g<EFBFBD>̃N<CC83><4E><EFBFBD>A
KeClearEvent(&fdoExtension->SyncEvent);
//IrpStack<63>̃R<CC83>s<EFBFBD>[
IoCopyCurrentIrpStackLocationToNext(Irp);
// IrpCompletion<6F>̐ݒ<CC90>
IoSetCompletionRoutine(Irp, QV2KUX_IrpCompletion, &fdoExtension->SyncEvent, TRUE, TRUE, TRUE);
// call the next lower device
status = IoCallDriver(fdoExtension->Ldo, Irp);
// wait for the actual completion
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&fdoExtension->SyncEvent, Executive, KernelMode, FALSE, NULL);
status = Irp->IoStatus.Status;
}
return status;
} // end QV2KUX_ForwardIrpSynchronous()
VOID QV2KUX_Unload( IN PDRIVER_OBJECT DriverObject)
/*++
Routine Description:
Free all the allocated resources, etc.
Arguments:
DriverObject - pointer to a driver object.
Return Value:
VOID.
--*/
{
return;
}
NTSTATUS QV2KUX_Internal_IOCTL(IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
{
PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
NTSTATUS ntStatus;
PIO_STACK_LOCATION IrpSp;
PURB urb;
PUCHAR IoBuffer;
USHORT length;
UCHAR subclass;
if (fdoExtension->Signature != 'QV2K') return QV2KUX_SendToNextDriver(Fdo,Irp);
IrpSp = IoGetCurrentIrpStackLocation(Irp);
urb = IrpSp->Parameters.Others.Argument1;
if (!urb) return QV2KUX_SendToNextDriver(Fdo,Irp);
if (urb->UrbHeader.Function != URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
return QV2KUX_SendToNextDriver(Fdo,Irp);
// <20>P<EFBFBD><50><EFBFBD>ڂ<EFBFBD> USB_DEVICE_DESCRIPTOR_TYPE Length = 0x12;
// <20>Q<EFBFBD><51><EFBFBD>ڂ<EFBFBD> USB_CONFIGURATION_DESCRIPTOR_TYPE LENGHT = 0x9
// <20>R<EFBFBD><52><EFBFBD>ڂ<EFBFBD> USB_CONFIGURATION_DESCRIPTOR_TYPE LENGHT = interface,endpoint descriptor<6F><72><EFBFBD>܂߂<DC82><DF82><EFBFBD><EFBFBD><EFBFBD>
if (urb->UrbControlDescriptorRequest.TransferBufferLength <= 0x12)
return QV2KUX_SendToNextDriver(Fdo,Irp);
// <20>R<EFBFBD><52><EFBFBD>ڂ<EFBFBD><DA82><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʉ߂<CA89><DF82><EFBFBD>
DebugPrint((0,"URB Get All of Configuration Descriptor \n"));
ntStatus = QV2KUX_ForwardIrpSynchronous(Fdo,Irp);
if (NT_SUCCESS(ntStatus)) {
IoBuffer = (UCHAR *)urb->UrbControlDescriptorRequest.TransferBuffer;
length = (USHORT)urb->UrbControlDescriptorRequest.TransferBufferLength;
while(length >= 9) {
//InterfaceDescriptor<6F><72><EFBFBD>؂蕪<D882><E895AA><EFBFBD><EFBFBD>
if (*(IoBuffer+1) == 4) {
subclass = *(IoBuffer+6);
DebugPrint((0,"QV2K_IntIoctl: SubCrass = %d \n",subclass));
if (*(IoBuffer+6) == 6) *(IoBuffer+6) = 5;
}
length -= *IoBuffer;
IoBuffer += *IoBuffer;
}
}
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return ntStatus;
}
#if DBG
VOID
QV2KUX_DebugPrint(
ULONG DebugPrintLevel,
PCCHAR DebugMessage,
...
)
/*++
Routine Description:
Debug print for all QV2KUX_
Arguments:
Debug print level between 0 and 3, with 3 being the most verbose.
Return Value:
None
--*/
{
va_list ap;
va_start(ap, DebugMessage);
if ((DebugPrintLevel <= (QV2KUX_Debug & 0x0000ffff)) ||
((1 << (DebugPrintLevel + 15)) & QV2KUX_Debug)) {
_vsnprintf(QV2KUX_DebugBuffer, DEBUG_BUFFER_LENGTH, DebugMessage, ap);
DbgPrint(QV2KUX_DebugBuffer);
}
va_end(ap);
}
#endif