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.
334 lines
8.3 KiB
334 lines
8.3 KiB
|
|
//+----------------------------------------------------------------------------//+----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 2001, Microsoft Corporation
|
|
//
|
|
// File: rxcontx.c
|
|
//
|
|
// Contents: Contains functions for allocating contexts and Cancel Routines
|
|
//
|
|
//
|
|
// Functions:
|
|
//
|
|
// Author - Rohan Phillips (Rohanp)
|
|
//-----------------------------------------------------------------------------
|
|
#include "ntifs.h"
|
|
#include <rxcontx.h>
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, RxInitializeContext)
|
|
#pragma alloc_text(PAGE, DfsInitializeContextResources)
|
|
#pragma alloc_text(PAGE, DfsDeInitializeContextResources)
|
|
#endif
|
|
|
|
#define RX_IRPC_POOLTAG ('rsfd')
|
|
|
|
KSPIN_LOCK RxStrucSupSpinLock = {0};
|
|
LIST_ENTRY RxActiveContexts;
|
|
ULONG NumberOfActiveContexts = 0;
|
|
NPAGED_LOOKASIDE_LIST RxContextLookasideList;
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsInitializeContextResources
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Status
|
|
// ERROR_SUCCESS on success
|
|
// ERROR status code otherwise
|
|
//
|
|
//
|
|
// Description: Initializes all resources needed for allocating contexts
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
NTSTATUS DfsInitializeContextResources(void)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
KeInitializeSpinLock( &RxStrucSupSpinLock );
|
|
|
|
// Initialize the look aside list for RxContext allocation
|
|
ExInitializeNPagedLookasideList(
|
|
&RxContextLookasideList,
|
|
ExAllocatePoolWithTag,
|
|
ExFreePool,
|
|
0,
|
|
sizeof(RX_CONTEXT),
|
|
RX_IRPC_POOLTAG,
|
|
32);
|
|
|
|
InitializeListHead(&RxActiveContexts);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsDeInitializeContextResources
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Status
|
|
// ERROR_SUCCESS on success
|
|
// ERROR status code otherwise
|
|
//
|
|
//
|
|
// Description: DeInitializes all resources needed for allocating contexts
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
NTSTATUS DfsDeInitializeContextResources(void)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
ExDeleteNPagedLookasideList(&RxContextLookasideList);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: RxInitializeContext
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
// Description: initializes a context
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
VOID
|
|
RxInitializeContext(
|
|
IN PIRP Irp,
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
RxContext->ReferenceCount = 1;
|
|
|
|
// Initialize the Sync Event.
|
|
KeInitializeEvent(
|
|
&RxContext->SyncEvent,
|
|
SynchronizationEvent,
|
|
FALSE);
|
|
|
|
if(Irp)
|
|
{
|
|
if (!IoIsOperationSynchronous(Irp))
|
|
{
|
|
SetFlag( RxContext->Flags, DFS_CONTEXT_FLAG_ASYNC_OPERATION );
|
|
}
|
|
}
|
|
|
|
// Set the Irp fields.
|
|
RxContext->CurrentIrp = Irp;
|
|
RxContext->OriginalThread = RxContext->LastExecutionThread = PsGetCurrentThread();
|
|
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: RxCreateRxContext
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Pointer to context information
|
|
//
|
|
//
|
|
// Description: allocates a context
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
PRX_CONTEXT
|
|
RxCreateRxContext (
|
|
IN PIRP Irp,
|
|
IN ULONG InitialContextFlags
|
|
)
|
|
{
|
|
PRX_CONTEXT RxContext = NULL;
|
|
ULONG RxContextFlags = 0;
|
|
KIRQL SavedIrql;
|
|
|
|
RxContext = ExAllocateFromNPagedLookasideList(
|
|
&RxContextLookasideList);
|
|
if(RxContext == NULL)
|
|
{
|
|
return(NULL);
|
|
}
|
|
|
|
InterlockedIncrement(&NumberOfActiveContexts);
|
|
|
|
RtlZeroMemory( RxContext, sizeof(RX_CONTEXT) );
|
|
|
|
RxContext->Flags = RxContextFlags;
|
|
|
|
RxInitializeContext(Irp,RxContext);
|
|
|
|
KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
|
|
|
|
InsertTailList(&RxActiveContexts,&RxContext->ContextListEntry);
|
|
|
|
KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
|
|
|
|
return RxContext;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: RxDereferenceAndDeleteRxContext_Real
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
// Description: Deallocates a context
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
VOID
|
|
RxDereferenceAndDeleteRxContext_Real (
|
|
IN PRX_CONTEXT RxContext
|
|
)
|
|
{
|
|
PRX_CONTEXT pStopContext = NULL;
|
|
LONG FinalRefCount = 0;
|
|
KIRQL SavedIrql;
|
|
|
|
KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
|
|
|
|
FinalRefCount = InterlockedDecrement(&RxContext->ReferenceCount);
|
|
|
|
if (FinalRefCount == 0)
|
|
{
|
|
RemoveEntryList(&RxContext->ContextListEntry);
|
|
|
|
InterlockedDecrement(&NumberOfActiveContexts);
|
|
|
|
RtlZeroMemory( RxContext, sizeof(RX_CONTEXT) );
|
|
|
|
ExFreeToNPagedLookasideList(
|
|
&RxContextLookasideList,
|
|
RxContext );
|
|
}
|
|
|
|
KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: RxSetMinirdrCancelRoutine
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
// Description: Sets up a cancel routine
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
NTSTATUS
|
|
RxSetMinirdrCancelRoutine(
|
|
IN OUT PRX_CONTEXT RxContext,
|
|
IN DFS_CALLDOWN_ROUTINE DfsCancelRoutine)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
KIRQL SavedIrql;
|
|
|
|
KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
|
|
|
|
if (!FlagOn(RxContext->Flags, DFS_CONTEXT_FLAG_CANCELLED))
|
|
{
|
|
RxContext->CancelRoutine = DfsCancelRoutine;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_CANCELLED;
|
|
}
|
|
|
|
KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: RxCancelRoutine
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
// Description: The main cancel routine
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
VOID
|
|
RxCancelRoutine(
|
|
PDEVICE_OBJECT pDeviceObject,
|
|
PIRP pIrp)
|
|
{
|
|
PRX_CONTEXT pRxContext = NULL;
|
|
PLIST_ENTRY pListEntry = NULL;
|
|
DFS_CALLDOWN_ROUTINE DfsCancelRoutine = NULL;
|
|
KIRQL SavedIrql;
|
|
|
|
// Locate the context corresponding to the given Irp.
|
|
KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
|
|
|
|
pListEntry = RxActiveContexts.Flink;
|
|
|
|
while (pListEntry != &RxActiveContexts)
|
|
{
|
|
pRxContext = CONTAINING_RECORD(pListEntry,RX_CONTEXT,ContextListEntry);
|
|
|
|
if (pRxContext->CurrentIrp == pIrp)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
pListEntry = pListEntry->Flink;
|
|
}
|
|
}
|
|
|
|
if (pListEntry != &RxActiveContexts)
|
|
{
|
|
SetFlag( pRxContext->Flags, DFS_CONTEXT_FLAG_CANCELLED );
|
|
DfsCancelRoutine = pRxContext->CancelRoutine;
|
|
pRxContext->CancelRoutine = NULL;
|
|
InterlockedIncrement(&pRxContext->ReferenceCount);
|
|
}
|
|
else
|
|
{
|
|
pRxContext = NULL;
|
|
DfsCancelRoutine = NULL;
|
|
}
|
|
|
|
KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
|
|
|
|
IoReleaseCancelSpinLock(pIrp->CancelIrql);
|
|
|
|
if (pRxContext != NULL)
|
|
{
|
|
if (DfsCancelRoutine != NULL)
|
|
{
|
|
(DfsCancelRoutine)(pRxContext);
|
|
}
|
|
|
|
RxDereferenceAndDeleteRxContext(pRxContext);
|
|
}
|
|
}
|
|
|