You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
4.0 KiB
123 lines
4.0 KiB
// @doc
|
|
/**********************************************************************
|
|
*
|
|
* @module RemLock.c |
|
|
*
|
|
* Implements Remove Lock utilities for keeping track of the driver.
|
|
*
|
|
* History
|
|
* ----------------------------------------------------------
|
|
* Mitchell S. Dernis Original
|
|
*
|
|
* (c) 1986-1998 Microsoft Corporation. All right reserved.
|
|
*
|
|
* @topic RemLock |
|
|
* This module was written to make the numerous increments and
|
|
* and decrements of Outstanding IO easier to manage.
|
|
* An increment and a decrment (even the final one), is reduced
|
|
* to a one line function everywhere. Furthermore, this module
|
|
* can have traceouts turned on independently just for testing
|
|
* this aspect of the driver.<nl>
|
|
* This is similar to the IoAcquireRemoveLock, except that
|
|
* to the best of my knowledge is not available on Win98.
|
|
*
|
|
**********************************************************************/
|
|
#define __DEBUG_MODULE_IN_USE__ GCK_REMLOCK_C
|
|
|
|
#include <wdm.h>
|
|
#include "debug.h"
|
|
#include "RemLock.h"
|
|
|
|
DECLARE_MODULE_DEBUG_LEVEL((DBG_WARN|DBG_ERROR|DBG_CRITICAL));
|
|
//DECLARE_MODULE_DEBUG_LEVEL((DBG_ALL));
|
|
|
|
#if (DBG==1)
|
|
void GCK_InitRemoveLockChecked(PGCK_REMOVE_LOCK pRemoveLock, PCHAR pcInstanceID)
|
|
{
|
|
pRemoveLock->pcInstanceID = pcInstanceID;
|
|
GCK_DBG_TRACE_PRINT(("Initializing remove lock \'%s\' to one.\n", pRemoveLock->pcInstanceID));
|
|
pRemoveLock->lRemoveLock = 1;
|
|
KeInitializeEvent(&pRemoveLock->RemoveLockEvent, SynchronizationEvent, FALSE);
|
|
}
|
|
#else
|
|
void GCK_InitRemoveLockFree(PGCK_REMOVE_LOCK pRemoveLock)
|
|
{
|
|
pRemoveLock->lRemoveLock = 1;
|
|
KeInitializeEvent(&pRemoveLock->RemoveLockEvent, SynchronizationEvent, FALSE);
|
|
}
|
|
#endif
|
|
|
|
void GCK_IncRemoveLock(PGCK_REMOVE_LOCK pRemoveLock)
|
|
{
|
|
LONG lNewCount = InterlockedIncrement(&pRemoveLock->lRemoveLock);
|
|
GCK_DBG_TRACE_PRINT(("\'%s\', Incremented Remove Lock to %d.\n", pRemoveLock->pcInstanceID, lNewCount));
|
|
}
|
|
|
|
void GCK_DecRemoveLock(PGCK_REMOVE_LOCK pRemoveLock)
|
|
{
|
|
LONG lNewCount = InterlockedDecrement(&pRemoveLock->lRemoveLock);
|
|
if (0 >= lNewCount)
|
|
{
|
|
GCK_DBG_TRACE_PRINT(("\'%s\', Last IRP completed.\n", pRemoveLock->pcInstanceID));
|
|
KeSetEvent (&pRemoveLock->RemoveLockEvent, IO_NO_INCREMENT, FALSE);
|
|
}
|
|
GCK_DBG_TRACE_PRINT(("\'%s\', Decremented Remove Lock to %d\n", pRemoveLock->pcInstanceID, lNewCount));
|
|
|
|
}
|
|
|
|
NTSTATUS GCK_DecRemoveLockAndWait(PGCK_REMOVE_LOCK pRemoveLock, PLARGE_INTEGER plgiWaitTime)
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
LONG lNewCount = InterlockedDecrement(&pRemoveLock->lRemoveLock);
|
|
if (0 < lNewCount)
|
|
{
|
|
GCK_DBG_TRACE_PRINT(("\'%s\', Decremented Remove Lock to %d, waiting for final unlock.\n",
|
|
pRemoveLock->pcInstanceID,
|
|
lNewCount));
|
|
NtStatus = KeWaitForSingleObject (
|
|
&pRemoveLock->RemoveLockEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
plgiWaitTime
|
|
);
|
|
}
|
|
|
|
#if (DBG==1)
|
|
if(STATUS_SUCCESS == NtStatus)
|
|
{
|
|
GCK_DBG_EXIT_PRINT(("\'%s\', GCK_DecRemoveLockAndWait exiting - Remove Lock went to zero.\n", pRemoveLock->pcInstanceID));
|
|
}
|
|
else
|
|
{
|
|
GCK_DBG_CRITICAL_PRINT(("\'%s\', Remove Lock is still %d, should be zero.\n", pRemoveLock->lRemoveLock));
|
|
GCK_DBG_EXIT_PRINT(("\'%s\', GCK_DecRemoveLockAndWait exiting - timed out.\n", pRemoveLock->pcInstanceID));
|
|
}
|
|
#endif
|
|
return NtStatus;
|
|
}
|
|
|
|
/*
|
|
* Avoid bugchecks by requesting a failable mapping.
|
|
* Error check that was added to calling functions is limited to
|
|
* only avoiding partying on a NULL pointer. Correct functioning
|
|
* is not expected.
|
|
*/
|
|
PVOID GCK_GetSystemAddressForMdlSafe(PMDL MdlAddress)
|
|
{
|
|
PVOID buf = NULL;
|
|
/*
|
|
* Can't call MmGetSystemAddressForMdlSafe in a WDM driver,
|
|
* so set the MDL_MAPPING_CAN_FAIL bit and check the result
|
|
* of the mapping.
|
|
*/
|
|
if (MdlAddress) {
|
|
MdlAddress->MdlFlags |= MDL_MAPPING_CAN_FAIL;
|
|
buf = MmGetSystemAddressForMdl(MdlAddress);
|
|
MdlAddress->MdlFlags &= (~MDL_MAPPING_CAN_FAIL);
|
|
}
|
|
else {
|
|
GCK_DBG_CRITICAL_PRINT(("MdlAddress passed into GetSystemAddress is NULL\n"));
|
|
}
|
|
return buf;
|
|
}
|