|
|
//----------------- 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: �����ł̓G���g���[�|�C���g�̐ݒ肾��������
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;
// �Ƃ肠�����S�ăo�C�p�X�����悤�ɐݒ�
for (ulIndex = 0, dispatch = DriverObject->MajorFunction; ulIndex <= IRP_MJ_MAXIMUM_FUNCTION; ulIndex++, dispatch++) {
*dispatch = QV2KUX_SendToNextDriver; }
// ���L�̐ݒ��ł͂܂��������̕ύX
DriverObject->MajorFunction[IRP_MJ_POWER] = QV2KUX_DispatchPower; DriverObject->DriverUnload = QV2KUX_Unload;
//�Œ����K�v�Ȃ���
DriverObject->MajorFunction[IRP_MJ_PNP] = QV2KUX_DispatchPnp; DriverObject->DriverExtension->AddDevice = QV2KUX_AddDevice;
// �����I�ɂ��肽����������
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�̍쐻�Ƃ���DeviceExtension�̏����� ���̃v���O�����ł́APDO�͍쐻���Ȃ���FDO�̂ݎg�p����
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;
// ���ʃh���C�o�ɐڑ�
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�Ŏg�p����
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���܂��g���A���ɂ�Completion���܂��m�点�Ȃ�
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;
//�C�x���g�̃N���A
KeClearEvent(&fdoExtension->SyncEvent); //IrpStack�̃R�s�[
IoCopyCurrentIrpStackLocationToNext(Irp); // IrpCompletion�̐ݒ�
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); // �P���ڂ� USB_DEVICE_DESCRIPTOR_TYPE Length = 0x12;
// �Q���ڂ� USB_CONFIGURATION_DESCRIPTOR_TYPE LENGHT = 0x9
// �R���ڂ� USB_CONFIGURATION_DESCRIPTOR_TYPE LENGHT = interface,endpoint descriptor���܂߂�����
if (urb->UrbControlDescriptorRequest.TransferBufferLength <= 0x12) return QV2KUX_SendToNextDriver(Fdo,Irp); // �R���ڂ������ʉ߂���
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���蕪����
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
|