// @doc /********************************************************************** * * @module FLTR.c | * * Implementation of basic IRP handlers for Filter Device Objects * * History * ---------------------------------------------------------- * Mitchell S. Dernis Original * * (c) 1986-1998 Microsoft Corporation. All right reserved. * * @topic FLTR | * The non-Power and PnP IRP handler routines are handled in this module * for all Device Objects created as filters for the raw HID-Pdos. * **********************************************************************/ #define __DEBUG_MODULE_IN_USE__ GCK_FLTR_C #include #include "Debug.h" #include "GckShell.h" DECLARE_MODULE_DEBUG_LEVEL((DBG_WARN|DBG_ERROR|DBG_CRITICAL)); // // Mark the pageable routines as such // #ifdef ALLOC_PRAGMA #pragma alloc_text (INIT, GCK_FLTR_DriverEntry) #pragma alloc_text (PAGE, GCK_FLTR_Create) #pragma alloc_text (PAGE, GCK_FLTR_Close) #pragma alloc_text (PAGE, GCK_FLTR_Ioctl) #pragma alloc_text (PAGE, GCK_FLTR_Unload) #endif /*********************************************************************************** ** ** NTSTATUS GCK_FLTR_DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath ) ** ** @func Initializing the portions of the driver related to the filter devices. ** ** @rdesc STATUS_SUCCESS ** *************************************************************************************/ NTSTATUS GCK_FLTR_DriverEntry ( IN PDRIVER_OBJECT pDriverObject, // @parm Driver Object IN PUNICODE_STRING puniRegistryPath // @parm Path to driver specific registry section. ) { UNREFERENCED_PARAMETER(pDriverObject); UNREFERENCED_PARAMETER(puniRegistryPath); // // Initialize Globals related to filter devices // GCK_DBG_TRACE_PRINT(("Initializing globals\n")); Globals.ulFilteredDeviceCount = 0; Globals.pFilterObjectList = NULL; Globals.pSWVB_FilterExt=NULL; // Nobody owns the virtual bus yet. Globals.pVirtualKeyboardPdo = NULL; // No keyboard object Globals.ulVirtualKeyboardRefCount = 0; // No keyboard users ExInitializeFastMutex(&Globals.FilterObjectListFMutex); return STATUS_SUCCESS; } /*********************************************************************************** ** ** NTSTATUS GCK_FLTR_Create ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) ** ** @func Handles the IRP_MJ_CREATE for filter devices ** - Called generated by Win32 API CreateFile or OpenFile ** ** @rdesc STATUS_SUCCESS, or various error codes ** *************************************************************************************/ NTSTATUS GCK_FLTR_Create ( IN PDEVICE_OBJECT pDeviceObject, // @parm DO target for IRP IN PIRP pIrp // @parm IRP ) { NTSTATUS NtStatus = STATUS_SUCCESS; PGCK_FILTER_EXT pFilterExt; PDEVICE_OBJECT pCurDeviceObject; PIO_STACK_LOCATION pIrpStack; KEVENT SyncEvent; USHORT usShareAccess; PAGED_CODE (); GCK_DBG_ENTRY_PRINT (("Entering GCK_FLTR\n")); //cast device extension to proper type pFilterExt = (PGCK_FILTER_EXT) pDeviceObject->DeviceExtension; // Just an extra sanity check ASSERT( GCK_DO_TYPE_FILTER == pFilterExt->ulGckDevObjType); // // Increment IRP count, ASAP, note we couldn't do this until now, as we // knew not whether the device extension was really a GCK_FILTER_EXT // GCK_IncRemoveLock(&pFilterExt->RemoveLock); // Make sure we are not in the process of going away if( GCK_STATE_STARTED != pFilterExt->eDeviceState && GCK_STATE_STOP_PENDING != pFilterExt->eDeviceState ) { GCK_DBG_WARN_PRINT(("Create while remove pending\n")); NtStatus = STATUS_DELETE_PENDING; pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = NtStatus; IoCompleteRequest (pIrp, IO_NO_INCREMENT); } else // process this { GCK_DBG_TRACE_PRINT(("GCK_Create calling lower driver\n")); pIrpStack = IoGetCurrentIrpStackLocation(pIrp); // //We lie to hidclass about the desired share access, //because it doesn't know not to count us. //Notice below that we restore this before passing to our //internal poll routines, so that we can track it there. // usShareAccess=pIrpStack->Parameters.Create.ShareAccess; pIrpStack->Parameters.Create.ShareAccess = FILE_READ_DATA|FILE_WRITE_DATA; //This is our internal poll trying to create a file object, just call down if( pFilterExt->InternalPoll.InternalCreateThread == KeGetCurrentThread()) { IoSkipCurrentIrpStackLocation(pIrp); NtStatus = IoCallDriver (pFilterExt->pTopOfStack, pIrp); } //This is a request from above, capture on the way up else { GCK_IP_AddFileObject( pFilterExt, pIrpStack->FileObject, pIrpStack->Parameters.Create.ShareAccess, pIrpStack->Parameters.Create.SecurityContext->DesiredAccess ); GCKF_KickDeviceForData(pFilterExt); // Call create synchronously KeInitializeEvent(&SyncEvent, SynchronizationEvent, FALSE); IoCopyCurrentIrpStackLocationToNext(pIrp); IoSetCompletionRoutine( pIrp, GCK_FLTR_CreateComplete, (PVOID)&SyncEvent, TRUE, TRUE, TRUE ); IoCallDriver (pFilterExt->pTopOfStack, pIrp); KeWaitForSingleObject(&SyncEvent, Executive, KernelMode, FALSE, NULL); NtStatus = pIrp->IoStatus.Status; // If create succeeded, we need to remember the FileObject GCK_IP_ConfirmFileObject(pFilterExt, pIrpStack->FileObject, (BOOLEAN)(NT_SUCCESS(pIrp->IoStatus.Status) ? TRUE : FALSE) ); IoCompleteRequest(pIrp, IO_NO_INCREMENT); // This was misssing!!! } } // // We are done with this IRP, so decrement the outstanding count // and signal remove if this was the last outstanding IRP // GCK_DecRemoveLock(&pFilterExt->RemoveLock); GCK_DBG_EXIT_PRINT(("Exiting GCK_Create(2). Status: 0x%0.8x\n", NtStatus)); return NtStatus; } /*********************************************************************************** ** ** NTSTATUS GCK_FLTR_CreateComplete(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext) ** ** @mfunc Completion Routine for IRP_MJ_CREATE ** ** @rdesc STATUS_SUCCESS ** *************************************************************************************/ NTSTATUS GCK_FLTR_CreateComplete ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext ) { PKEVENT pSyncEvent; UNREFERENCED_PARAMETER(pDeviceObject); UNREFERENCED_PARAMETER(pIrp); // Cast context to device extension pSyncEvent = (PKEVENT) pContext; KeSetEvent(pSyncEvent, IO_NO_INCREMENT, FALSE); //Done with this IRP, never need to see it again return STATUS_MORE_PROCESSING_REQUIRED; } /*********************************************************************************** ** ** NTSTATUS GCK_FLTR_Close ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) ** ** @func Handles IRP_MJ_CLOSE for filter device objects - Call generated by Win32 API CloseFile ** ** @rdesc STATUS_SUCCESS or various errors ** *************************************************************************************/ NTSTATUS GCK_FLTR_Close ( IN PDEVICE_OBJECT pDeviceObject, // @parm DO target for IRP IN PIRP pIrp // @parm IRP ) { NTSTATUS NtStatus = STATUS_SUCCESS; PGCK_FILTER_EXT pFilterExt; PIO_STACK_LOCATION pIrpStack; PAGED_CODE (); GCK_DBG_ENTRY_PRINT (("GCK_Close, pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp)); //cast device extension to proper type pFilterExt = (PGCK_FILTER_EXT) pDeviceObject->DeviceExtension; // Just an extra sanity check ASSERT( GCK_DO_TYPE_FILTER == pFilterExt->ulGckDevObjType); // // Increment IRP count, ASAP, note we couldn't do this until now, as we // knew not whether the device extension was really a GCK_FILTER_EXT // GCK_IncRemoveLock(&pFilterExt->RemoveLock); pIrpStack = IoGetCurrentIrpStackLocation(pIrp); //cleanup pending IO and our tracking of the FileObject - //however not applicable if it is our internal polling open, that is being close if(pIrpStack->FileObject != pFilterExt->InternalPoll.pInternalFileObject) { //Complete pending I\O on FileObject if( GCK_STATE_STARTED == pFilterExt->eDeviceState || GCK_STATE_STOP_PENDING == pFilterExt->eDeviceState ) { //There is no pending I\O if the device is not started yet GCKF_CompleteReadRequestsForFileObject(pFilterExt, pIrpStack->FileObject); } //forget file object GCK_IP_RemoveFileObject(pFilterExt, pIrpStack->FileObject); } //send the Irp along IoSkipCurrentIrpStackLocation (pIrp); NtStatus = IoCallDriver(pFilterExt->pTopOfStack, pIrp); // Decrement outstanding IO and signal if went to zero GCK_DecRemoveLock(&pFilterExt->RemoveLock); GCK_DBG_EXIT_PRINT(("Exiting GCK_Close(2). Status: 0x%0.8x\n", NtStatus)); return NtStatus; } /*********************************************************************************** ** ** NTSTATUS GCK_FLTR_Read (IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) ** ** @func Handles IRP_MJ_READ for filter device objects - Generated by Win32 ReadFile ** ** @rdesc STATUS_SUCCESS, or various errors ** *************************************************************************************/ NTSTATUS GCK_FLTR_Read ( IN PDEVICE_OBJECT pDeviceObject, // @parm Target of IRP IN PIRP pIrp // @parm IRP to handle ) { NTSTATUS NtStatus; LARGE_INTEGER lgiWaitTime; PGCK_FILTER_EXT pFilterExt; PIO_STACK_LOCATION pIrpStack; PIO_STACK_LOCATION pPrivateIrpStack; PVOID pvIrpBuffer; PFILE_OBJECT pIrpsFileObject; static int iEnterCount=0; unsigned int i=0; GCK_DBG_RT_ENTRY_PRINT(("Entering GCK_Read. pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp)); //cast device extension to proper type pFilterExt = (PGCK_FILTER_EXT) pDeviceObject->DeviceExtension; // Just an extra sanity check ASSERT( GCK_DO_TYPE_FILTER == pFilterExt->ulGckDevObjType); // Increment IRP count while we handle this one GCK_IncRemoveLock(&pFilterExt->RemoveLock); // If we have been removed, we shouldn't be getting read IRPs if( GCK_STATE_STARTED != pFilterExt->eDeviceState && GCK_STATE_STOP_PENDING != pFilterExt->eDeviceState ) { GCK_DBG_WARN_PRINT(( "GCK_Read called with delete pending\n")); NtStatus = STATUS_DELETE_PENDING; pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = NtStatus; IoCompleteRequest(pIrp, IO_NO_INCREMENT); // Decrement outstanding IRP count, and signal if it want to zero GCK_DecRemoveLock(&pFilterExt->RemoveLock); } else { // // Send Reqeust to filter, the filterhooks module is responsible // for all the necessary Asynchronous IRP handling steps, we just // return status pending. // NtStatus = GCKF_IncomingReadRequests(pFilterExt, pIrp); // Poll the lower driver, if one is not yet pending. GCK_IP_OneTimePoll(pFilterExt); } GCK_DBG_RT_EXIT_PRINT(("Exiting GCK_Read(2). Status: 0x%0.8x\n", NtStatus)); return NtStatus; } /*********************************************************************************** ** ** NTSTATUS GCK_FLTR_Ioctl (IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) ** ** @mfunc Handles all IOCTLs for the filter devices - this is just a straight pass through ** ** @rdesc STATUS_SUCCESS, various errors ** *************************************************************************************/ NTSTATUS GCK_FLTR_Ioctl ( IN PDEVICE_OBJECT pDeviceObject, // @parm pointer to Device Object IN PIRP pIrp // @parm pointer to IRP ) { PGCK_FILTER_EXT pFilterExt; NTSTATUS NtStatus; PAGED_CODE (); GCK_DBG_ENTRY_PRINT(("Entering GCK_FLTR_Ioctl, pDeviceObject = 0x%0.8x, pIRP = 0x%0.8x\n", pDeviceObject, pIrp)); //cast device extension to proper type pFilterExt = (PGCK_FILTER_EXT) pDeviceObject->DeviceExtension; // // If we have been removed we need to refuse this IRP // if (GCK_STATE_REMOVED == pFilterExt->eDeviceState) { GCK_DBG_TRACE_PRINT(("GCK_FLTR_Ioctl called while delete pending\n")); ASSERT(FALSE); NtStatus = STATUS_DELETE_PENDING; pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = NtStatus; IoCompleteRequest (pIrp, IO_NO_INCREMENT); } else { // Send the IRP on unchanged. IoSkipCurrentIrpStackLocation (pIrp); NtStatus = IoCallDriver (pFilterExt->pTopOfStack, pIrp); } GCK_DBG_EXIT_PRINT(("Exiting GCK_FLTR_Ioctl, Status: 0x%0.8x\n", NtStatus)); return NtStatus; }