|
|
// @doc
/**********************************************************************
* * @module InternalPolling.c | * * Implementation of routines for internal polling * * History * ---------------------------------------------------------- * Mitchell S. Dernis Original * * (c) 1986-1999 Microsoft Corporation. All right reserved. * * @topic Internal Polling | * All polling to get data is via this internal polling mechanism. * However, for security and access checks, the first poll from * a new file handle is sent straight down, and comes up via * different completion. To keep track of this we keep a linked * list of GCK_FILE_OPEN_ITEMs representing each of the FILE_OBJECTS * that we need.<nl> * To Poll internally we need to have a valid FILE_OBJECT otherwise * hidclass.sys will reject the poll request. This is done * via GCK_IP_CreateFileObject which internally calls IoGetDeviceObjectPointer. * Somewhat unfortunately, this takes circular path through, so is not * really distinguishable from opens done up top. (Ken Ray tells me that * this is guaranteed to be synchronous, so we can compare thread IDs and * figure out that a given open is from our driver, but this code is written * assuming that we don't really need to distinguish.) * **********************************************************************/ #define __DEBUG_MODULE_IN_USE__ GCK_INTERNALPOLL_C
#include <wdm.h>
#include "Debug.h"
#include "GckShell.h"
DECLARE_MODULE_DEBUG_LEVEL((DBG_WARN|DBG_ERROR|DBG_CRITICAL));
/***********************************************************************************
** ** NTSTATUS GCK_IP_AddFileObject(IN PGCK_FILTER_EXT pFilterExt, IN PFILE_OBJECT pFileObject) ** ** @func Called to add a GCK_FILE_OPEN_ITEM entry corresponding to pFileObject to ** our list of file handles that we know about. Allocate and initializes the structure. ** ** @rdesc STATUS_SUCCESS, or STATUS_UNSUCCESSFUL if pFileObject is not found. ** *************************************************************************************/ NTSTATUS GCK_IP_AddFileObject ( IN PGCK_FILTER_EXT pFilterExt, IN PFILE_OBJECT pFileObject, IN USHORT usDesiredShareAccess, IN ULONG ulDesiredAccess ) { PGCK_FILE_OPEN_ITEM pNewFileOpenItem; KIRQL OldIrql;
GCK_DBG_ENTRY_PRINT(("Entering GCK_IP_AddFileObject pFilterExt = 0x%0.8x, pFileObject = 0x%0.8x\n", pFilterExt, pFileObject)); //We need a spin lock to access this list
KeAcquireSpinLock(&pFilterExt->InternalPoll.InternalPollLock, &OldIrql);
//Check for sharing violation
if( !GCK_IP_CheckSharing(pFilterExt->InternalPoll.ShareStatus, usDesiredShareAccess, ulDesiredAccess) ) { KeReleaseSpinLock(&pFilterExt->InternalPoll.InternalPollLock, OldIrql); GCK_DBG_EXIT_PRINT(("Exiting GCK_IP_AddFileObject: Sharing Violation\n")); return STATUS_SHARING_VIOLATION; }
//Allocate Space for NewFileOpenItem;
pNewFileOpenItem = (PGCK_FILE_OPEN_ITEM)EX_ALLOCATE_POOL(NonPagedPool, sizeof(GCK_FILE_OPEN_ITEM)); if(!pNewFileOpenItem) { GCK_DBG_CRITICAL_PRINT(("Failed to allocate space for GCK_FILE_OPEN_ITEM\n")); GCK_DBG_EXIT_PRINT(("Exiting GCK_IP_AddFileObject(1) STATUS_NO_MEMORY\n")); return STATUS_NO_MEMORY; } //Initialize FileOpenItem
pNewFileOpenItem->fReadPending = FALSE; pNewFileOpenItem->pFileObject = pFileObject; pNewFileOpenItem->pNextOpenItem = NULL; pNewFileOpenItem->ulAccess = ulDesiredAccess; pNewFileOpenItem->usSharing = usDesiredShareAccess; pNewFileOpenItem->fConfirmed = FALSE;
//Add New Item to head of list
pNewFileOpenItem->pNextOpenItem = pFilterExt->InternalPoll.pFirstOpenItem; pFilterExt->InternalPoll.pFirstOpenItem = pNewFileOpenItem; //Update SHARE_ACCESS
GCK_IP_AddSharing(&pFilterExt->InternalPoll.ShareStatus, usDesiredShareAccess, ulDesiredAccess);
//Release Spinlock
KeReleaseSpinLock(&pFilterExt->InternalPoll.InternalPollLock, OldIrql);
GCK_DBG_EXIT_PRINT(("Exiting GCK_IP_AddFileObject(2) STATUS_SUCCESS\n")); return STATUS_SUCCESS; }
/***********************************************************************************
** ** NTSTATUS GCK_IP_RemoveFileObject(IN PGCK_FILTER_EXT pFilterExt, IN PFILE_OBJECT pFileObject) ** ** @func Called to remove a GCK_FILE_OPEN_ITEM entry corresponding to pFileObject from ** our list of file handles that we know about. Deallocates structure. ** ** @rdesc STATUS_SUCCESS, or STATUS_UNSUCCESSFUL if pFileObject is not found. ** *************************************************************************************/ NTSTATUS GCK_IP_RemoveFileObject ( IN PGCK_FILTER_EXT pFilterExt, IN PFILE_OBJECT pFileObject ) { //Remove is just a negative confirmation
return GCK_IP_ConfirmFileObject(pFilterExt, pFileObject, FALSE); }
NTSTATUS GCK_IP_ConfirmFileObject ( IN PGCK_FILTER_EXT pFilterExt, IN PFILE_OBJECT pFileObject, IN BOOLEAN fConfirm ) { //Find FileOpenItem and remove it.
PGCK_FILE_OPEN_ITEM pCurrentFileItem = pFilterExt->InternalPoll.pFirstOpenItem; PGCK_FILE_OPEN_ITEM pPreviousFileItem = NULL;
GCK_DBG_ENTRY_PRINT(("Entering GCK_IP_ConfirmFileObject pFilterExt = 0x%0.8x, pFileObject = 0x%0.8x, fConfirm = %d\n", pFilterExt, pFileObject, fConfirm)); while(pCurrentFileItem) { //Check for File Object Match
if(pCurrentFileItem->pFileObject == pFileObject) { //If this is a confirmation, flag
if( fConfirm ) { pCurrentFileItem->fConfirmed = TRUE; } //Otherwise, it is a negative confirmation, and we must remove it
else { //Remove from list
if( NULL == pPreviousFileItem) { pFilterExt->InternalPoll.pFirstOpenItem = pCurrentFileItem->pNextOpenItem; } else { pPreviousFileItem->pNextOpenItem = pCurrentFileItem->pNextOpenItem; } //Decrement number of open file objects
GCK_IP_RemoveSharing(&pFilterExt->InternalPoll.ShareStatus, pCurrentFileItem->usSharing, pCurrentFileItem->ulAccess);
//Free memory allocate for FileOpenItem
ExFreePool(pCurrentFileItem); } //Return Successfully
GCK_DBG_EXIT_PRINT(("Exiting GCK_IP_RemoveFileObject(1) STATUS_SUCCESS\n")); return STATUS_SUCCESS; } pPreviousFileItem = pCurrentFileItem; pCurrentFileItem = pCurrentFileItem->pNextOpenItem; } //If we are here the file object is not in our list. Either it was never added
//or is was removed
ASSERT(FALSE); GCK_DBG_EXIT_PRINT(("Exiting GCK_IP_ConfirmFileObject(2) STATUS_UNSUCCESSFUL\n")); return STATUS_UNSUCCESSFUL; }
BOOLEAN GCK_IP_CheckSharing ( IN SHARE_STATUS ShareStatus, IN USHORT usDesiredShareAccess, IN ULONG ulDesiredAccess ) { //Check that no-one has exclusive access to the desire access
if( ( (ulDesiredAccess & FILE_WRITE_DATA) && (ShareStatus.SharedWrite < ShareStatus.OpenCount) ) || ( (ulDesiredAccess & FILE_READ_DATA) && (ShareStatus.SharedRead < ShareStatus.OpenCount) ) ) { return FALSE; } //Check that not requesting exclusive access, if already open
if( ( !(usDesiredShareAccess & FILE_SHARE_READ) && ShareStatus.Readers) || ( !(usDesiredShareAccess & FILE_SHARE_WRITE) && ShareStatus.Writers) || (!usDesiredShareAccess && ShareStatus.OpenCount) ) { return FALSE; }
//This would be approved
return TRUE; }
BOOLEAN GCK_IP_AddSharing ( IN OUT SHARE_STATUS *pShareStatus, IN USHORT usDesiredShareAccess, IN ULONG ulDesiredAccess ) { //We assume this was checked before requested
ASSERT(GCK_IP_CheckSharing(*pShareStatus, usDesiredShareAccess, ulDesiredAccess)); pShareStatus->OpenCount++; if(usDesiredShareAccess & FILE_SHARE_READ) pShareStatus->SharedRead++; if(usDesiredShareAccess & FILE_SHARE_WRITE) pShareStatus->SharedWrite++; if(ulDesiredAccess & FILE_WRITE_DATA) pShareStatus->Writers++; if(ulDesiredAccess & FILE_READ_DATA) pShareStatus->Readers++; return TRUE; }
BOOLEAN GCK_IP_RemoveSharing ( IN OUT SHARE_STATUS *pShareStatus, IN USHORT usDesiredShareAccess, IN ULONG ulDesiredAccess ) { pShareStatus->OpenCount--; if(usDesiredShareAccess & FILE_SHARE_READ) pShareStatus->SharedRead--; if(usDesiredShareAccess & FILE_SHARE_WRITE) pShareStatus->SharedWrite--; if(ulDesiredAccess & FILE_WRITE_DATA) pShareStatus->Writers--; if(ulDesiredAccess & FILE_READ_DATA) pShareStatus->Readers--; return TRUE; }
typedef struct _GCK_INTERNEL_WorkItemExtension { WORK_QUEUE_ITEM WorkItem; PGCK_FILTER_EXT pFilterExt; } GCK_INTERNEL_WorkItemExtension;
VOID GCK_IP_WorkItem ( IN PVOID pvContext ) { GCK_INTERNEL_WorkItemExtension* pWIExtension = (GCK_INTERNEL_WorkItemExtension*)pvContext;
if (pWIExtension != NULL) { GCKF_IncomingReadRequests(pWIExtension->pFilterExt, NULL); ExFreePool(pWIExtension); } }
/***********************************************************************************
** ** NTSTATUS GCK_IP_OneTimePoll(IN PGCK_FILTER_EXT pFilterExt) ** ** @func If a private poll is not pending, it forces one. ** ** @rdesc STATUS_SUCCESS, or various errors ** *************************************************************************************/ NTSTATUS GCK_IP_OneTimePoll ( IN PGCK_FILTER_EXT pFilterExt ) { PIO_STACK_LOCATION pPrivateIrpStack; GCK_INTERNEL_WorkItemExtension* pWIExtension; //
// Create a polling FileObject if necessary
//
if(!pFilterExt->InternalPoll.fReady) { NTSTATUS NtStatus; if(GCK_STATE_STARTED == pFilterExt->eDeviceState) { pFilterExt->InternalPoll.InternalCreateThread=KeGetCurrentThread(); NtStatus = GCK_IP_CreateFileObject( &pFilterExt->InternalPoll.pInternalFileObject, pFilterExt->pPDO); pFilterExt->InternalPoll.InternalCreateThread=NULL; if( NT_SUCCESS(NtStatus) ) { pFilterExt->InternalPoll.fReady = TRUE; } else { return STATUS_DEVICE_NOT_CONNECTED; } } else { return STATUS_DEVICE_NOT_CONNECTED; } }
// If an read IRP is not pending, post one
/* if( pFilterExt->InternalPoll.fReadPending )
{ //If an IRP is pending, we're done
return STATUS_SUCCESS; }
// Mark a read pending
pFilterExt->InternalPoll.fReadPending = TRUE; */ if (InterlockedExchange(&pFilterExt->InternalPoll.fReadPending, TRUE) == TRUE) { return STATUS_SUCCESS; }
//Otherwise Post an IRP
GCK_DBG_RT_WARN_PRINT(("No IRP Pending, posting one.\n"));
// Give a change for the LEDs to update (we fake an incoming request)
pWIExtension = (GCK_INTERNEL_WorkItemExtension*)(EX_ALLOCATE_POOL(NonPagedPool, sizeof(GCK_INTERNEL_WorkItemExtension))); if (pWIExtension != NULL) { pWIExtension->pFilterExt = pFilterExt; ExInitializeWorkItem(&pWIExtension->WorkItem, GCK_IP_WorkItem, (void*)(pWIExtension));
// Need to callback at IRQL PASSIVE_LEVEL
ExQueueWorkItem(&pWIExtension->WorkItem, DelayedWorkQueue); pWIExtension = NULL; // Will be deleted by the work item routine
} //Setup the file object for out internal IRP
GCK_DBG_RT_WARN_PRINT(("Copying File object.\n")); pPrivateIrpStack = IoGetNextIrpStackLocation(pFilterExt->InternalPoll.pPrivateIrp); pPrivateIrpStack->FileObject = pFilterExt->InternalPoll.pInternalFileObject; // Reset status
pFilterExt->InternalPoll.pPrivateIrp->IoStatus.Information = 0; pFilterExt->InternalPoll.pPrivateIrp->IoStatus.Status = STATUS_SUCCESS;
// Reset the ByteOffset, Length
pPrivateIrpStack->Parameters.Read.ByteOffset.QuadPart = 0; pPrivateIrpStack->Parameters.Read.Key = 0; pPrivateIrpStack->Parameters.Read.Length = (ULONG)pFilterExt->HidInfo.HidPCaps.InputReportByteLength;
// Set Completion routine to process poll after it is complete.
GCK_DBG_RT_WARN_PRINT(("Setting completion routine.\n")); ASSERT(pFilterExt->InternalPoll.pPrivateIrp);
IoSetCompletionRoutine( pFilterExt->InternalPoll.pPrivateIrp, GCK_IP_ReadComplete, (PVOID)pFilterExt, TRUE, TRUE, TRUE ); // We are about to generate another IRP so increment outstanding IO count
GCK_IncRemoveLock(&pFilterExt->RemoveLock);
// Send IRP down to driver
GCK_DBG_RT_WARN_PRINT(("Calling down to next driver.\n")); return IoCallDriver (pFilterExt->pTopOfStack, pFilterExt->InternalPoll.pPrivateIrp); }
/***********************************************************************************
** ** NTSTATUS GCK_IP_FullTimePoll(IN PGCK_FILTER_EXT pFilterExt, IN BOOLEAN fStart) ** ** @func Turns FullTime internal polling on or off. Actually changes a refcount. ** When the refcount goes to zero, polling is off, otherwise it is on. Calls ** GCK_IP_OneTimePoll which may be necessary to get ball rolling. ** ** @rdesc STATUS_SUCCESS, or various errors ** *************************************************************************************/ NTSTATUS GCK_IP_FullTimePoll ( IN PGCK_FILTER_EXT pFilterExt, IN BOOLEAN fStart ) { //Change number of requests for continuous background polling.
if(fStart) { pFilterExt->InternalPoll.ulInternalPollRef++; ASSERT( 0!= pFilterExt->InternalPoll.ulInternalPollRef); //There is no thread, the completion routine recycles the IRP
//and polls again if pFilterExt->InternalPoll.ulInternalPollRef > 0
//we need to hit GCK_IP_OneTimePoll just to get the ball rolling though.
if(GCK_STATE_STARTED == pFilterExt->eDeviceState ) { return GCK_IP_OneTimePoll(pFilterExt); } return STATUS_SUCCESS; } //We need to decrment the refcount.
ASSERT( 0 != pFilterExt->InternalPoll.ulInternalPollRef); if(0 != pFilterExt->InternalPoll.ulInternalPollRef) { pFilterExt->InternalPoll.ulInternalPollRef--; } return STATUS_SUCCESS; }
/***********************************************************************************
** ** NTSTATUS GCK_IP_ReadComplete (IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext) ** ** @func When a Private IRP is completed handles processing the data. Also ** important is that it repolls internall if pFilterExt->InternalPoll.ulInternalPollRef ** is greater than zero. ** ** @rdesc STATUS_SUCCESS, or various errors ** *************************************************************************************/ NTSTATUS GCK_IP_ReadComplete ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext ) { PGCK_FILTER_EXT pFilterExt; PVOID pvReportBuffer; UNREFERENCED_PARAMETER(pDeviceObject); GCK_DBG_RT_ENTRY_PRINT(("Entering GCK_ReadComplete. pDO = 0x%0.8x, pIrp = 0x%0.8x, pContext = 0x%0.8x\n", pDeviceObject, pIrp, pContext));
// Cast context to device extension
pFilterExt = (PGCK_FILTER_EXT) pContext; // Just an extra sanity check
ASSERT( GCK_DO_TYPE_FILTER == pFilterExt->ulGckDevObjType);
// Get Pointer to data
ASSERT(pIrp);
pvReportBuffer = GCK_GetSystemAddressForMdlSafe(pIrp->MdlAddress); if(pvReportBuffer) { // Tell filter we have new data
GCKF_IncomingInputReports(pFilterExt, pvReportBuffer, pIrp->IoStatus); } //**
//** At this point we are done with the IRP
//** Need not complete it, it will be recycled.
//**
// Decrement outstanding IRP count
GCK_DecRemoveLock(&pFilterExt->RemoveLock);
// Read is no longer pending
pFilterExt->InternalPoll.fReadPending = FALSE; //If the InternalPollRef is greater than zero,
//we need to be polling ourselves continuously
//but don't carry on if some catestrophic failure
//occured which lead to a MDL mapping failure
if( pvReportBuffer && (pFilterExt->InternalPoll.ulInternalPollRef) ) { GCK_IP_OneTimePoll(pFilterExt); }
//We don't want any cleanup to happen
return STATUS_MORE_PROCESSING_REQUIRED; }
void GCK_IP_AddDevice(PGCK_FILTER_EXT pFilterExt) { KeInitializeSpinLock(&pFilterExt->InternalPoll.InternalPollLock); pFilterExt->InternalPoll.ShareStatus.OpenCount = 0; pFilterExt->InternalPoll.ShareStatus.Readers = 0; pFilterExt->InternalPoll.ShareStatus.Writers = 0; pFilterExt->InternalPoll.ShareStatus.SharedRead = 0; pFilterExt->InternalPoll.ShareStatus.SharedWrite = 0; pFilterExt->InternalPoll.fReadPending = FALSE; pFilterExt->InternalPoll.ulInternalPollRef = 0; pFilterExt->InternalPoll.pFirstOpenItem = NULL; pFilterExt->InternalPoll.fReady = FALSE; } /***********************************************************************************
** ** NTSTATUS GCK_IP_Init (IN OUT PGCK_FILTER_EXT pFilterExt); ** ** @func As part of the initialization that occurs at the end of Start device on ** a filtered device, the filter must be prepared for internal polling. ** All data polling is internal. (IRP_MJ_READ are sent down directly once ** so that hidclass.sys can perform its security check, but the data from ** that poll is discarded.) Initialize InternalPoll Data in Device Extension ** including creating a pInternalFileObject, a pPrivateIRP and an associtated ** Buffer. ** ** @rdesc STATUS_SUCCESS, or various errors ** *************************************************************************************/ NTSTATUS GCK_IP_Init ( IN OUT PGCK_FILTER_EXT pFilterExt ) { //NTSTATUS NtStatus;
LARGE_INTEGER lgiBufferOffset;
//Initialize the Internal Poll Structure
pFilterExt->InternalPoll.pInternalFileObject = NULL; pFilterExt->InternalPoll.pPrivateIrp = NULL; pFilterExt->InternalPoll.pucReportBuffer = NULL;
// Allocate a Buffer for the private IRP_MJ_READ
pFilterExt->InternalPoll.pucReportBuffer = (PUCHAR) EX_ALLOCATE_POOL ( NonPagedPool, pFilterExt->HidInfo.HidPCaps.InputReportByteLength ); if(!pFilterExt->InternalPoll.pucReportBuffer) { GCK_DBG_CRITICAL_PRINT(("Failed to allocate Report Buffer for private IRPs\n")); return STATUS_INSUFFICIENT_RESOURCES; } // Allocate private recyclable IRPs for internal polling
lgiBufferOffset.QuadPart = 0; pFilterExt->InternalPoll.pPrivateIrp = IoBuildAsynchronousFsdRequest ( IRP_MJ_READ, pFilterExt->pTopOfStack, pFilterExt->InternalPoll.pucReportBuffer, (ULONG)pFilterExt->HidInfo.HidPCaps.InputReportByteLength, &lgiBufferOffset, NULL );
if(!pFilterExt->InternalPoll.pPrivateIrp) { GCK_DBG_CRITICAL_PRINT(("Failed to allocate private Ping-Pong IRP\n")); return STATUS_INSUFFICIENT_RESOURCES; } // Initialize status for very first IRP
pFilterExt->ioLastReportStatus.Information = (ULONG)pFilterExt->HidInfo.HidPCaps.InputReportByteLength; pFilterExt->ioLastReportStatus.Status = STATUS_SUCCESS;
/**
** Cannot do this here since build 2006 or so, ** so defer until the first time we need it. ** ** ** //Open ourselves with a file object
** pFilterExt->InternalPoll.InternalCreateThread=KeGetCurrentThread(); ** NtStatus = GCK_IP_CreateFileObject( &pFilterExt->InternalPoll.pInternalFileObject, pFilterExt->pTopOfStack); ** pFilterExt->InternalPoll.InternalCreateThread=NULL; ** if( NT_SUCCESS(NtStatus) ) ** { ** pFilterExt->InternalPoll.fReady = TRUE; ** } **/ return STATUS_SUCCESS; }
/***********************************************************************************
** ** NTSTATUS GCK_IP_Cleanup (IN OUT PGCK_FILTER_EXT pFilterExt); ** ** @func Reverses Init, cancels outstanding internal polls, release pFileObject for ** internal polls, release private IRP and buffer. Does not release open file handles ** ** @rdesc STATUS_SUCCESS, STATUS_UNSUCCESSFUL if we could not cancel a pending poll ** *************************************************************************************/ NTSTATUS GCK_IP_Cleanup ( IN OUT PGCK_FILTER_EXT pFilterExt ) { NTSTATUS NtStatus = STATUS_SUCCESS; if( pFilterExt->InternalPoll.fReady) { NtStatus = GCK_IP_CloseFileObject(pFilterExt); } if(NT_SUCCESS(NtStatus)) { //Cleanup private IRP - and buffer, safely they may never had been allocated
if(pFilterExt->InternalPoll.pPrivateIrp) { IoFreeIrp(pFilterExt->InternalPoll.pPrivateIrp); pFilterExt->InternalPoll.pPrivateIrp = NULL; } if(pFilterExt->InternalPoll.pucReportBuffer) { ExFreePool(pFilterExt->InternalPoll.pucReportBuffer); pFilterExt->InternalPoll.pucReportBuffer = NULL; } } return NtStatus; }
/***********************************************************************************
** ** NTSTATUS GCK_IP_CreateFileObject (OUT PFILE_OBJECT *ppFileObject, IN PDEVICE_OBJECT pPDO); ** ** @func Calls IoGetDeviceObjectPointer, even though we already attached to the ** and have a pointer to the device object, the caller wants to create a ** new file object for internal calls down the stack that may require one. ** ** @rdesc STATUS_SUCCESS, or various errors ** *************************************************************************************/ NTSTATUS GCK_IP_CreateFileObject ( OUT PFILE_OBJECT *ppFileObject, IN PDEVICE_OBJECT pPDO ) { NTSTATUS NtStatus; ULONG ulBufferLength = 0; PVOID pPDONameBuffer = NULL; UNICODE_STRING uniPDOName; PDEVICE_OBJECT pDeviceObject;
//Get the size required for the PDO Name Buffer
NtStatus = IoGetDeviceProperty( pPDO, DevicePropertyPhysicalDeviceObjectName, ulBufferLength, pPDONameBuffer, &ulBufferLength ); ASSERT(STATUS_BUFFER_TOO_SMALL==NtStatus);
//Allocate space
pPDONameBuffer = EX_ALLOCATE_POOL(NonPagedPool, ulBufferLength); if(!pPDONameBuffer) { return STATUS_NO_MEMORY; }
//Get PDO Name
NtStatus = IoGetDeviceProperty( pPDO, DevicePropertyPhysicalDeviceObjectName, ulBufferLength, pPDONameBuffer, &ulBufferLength ); ASSERT(NT_SUCCESS(NtStatus)); if( NT_ERROR(NtStatus) ) { return NtStatus; }
//Make PDO Name into UNICODE string
RtlInitUnicodeString(&uniPDOName, pPDONameBuffer);
//Call IoGetDeviceObjectPointer to create a FILE_OBJECT
NtStatus = IoGetDeviceObjectPointer( &uniPDOName, FILE_READ_DATA, ppFileObject, &pDeviceObject ); ASSERT(NT_SUCCESS(NtStatus));
//Release the space for Name
ExFreePool(pPDONameBuffer); return NtStatus; }
/***********************************************************************************
** ** NTSTATUS GCK_IP_CloseFileObject (OUT PFILE_OBJECT *ppFileObject, IN PDEVICE_OBJECT pPDO); ** ** @func Stops outstanding IO to hidclass.sys and closes handle ** @rdesc STATUS_SUCCESS, or STATUS_UNSUCCESSFUL ** *************************************************************************************/ NTSTATUS GCK_IP_CloseFileObject ( IN OUT PGCK_FILTER_EXT pFilterExt ) { NTSTATUS NtStatus; BOOLEAN fResult = TRUE; //Turn off internal polling
pFilterExt->InternalPoll.fReady = FALSE; //Cancel pending internal polls
if(pFilterExt->InternalPoll.fReadPending) { ASSERT(pFilterExt->InternalPoll.pPrivateIrp); fResult = IoCancelIrp(pFilterExt->InternalPoll.pPrivateIrp); }
if(!fResult) { return STATUS_UNSUCCESSFUL; } //***
//***If we are here, there are no pending polls, and there shall be no pending polls.
//***
//Release internal file object - if it had been created successfully
if(pFilterExt->InternalPoll.pInternalFileObject) { ObDereferenceObject((PVOID)pFilterExt->InternalPoll.pInternalFileObject); pFilterExt->InternalPoll.pInternalFileObject=NULL; }
return STATUS_SUCCESS; }
|