Leaked source code of windows server 2003
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

//+----------------------------------------------------------------------------//+----------------------------------------------------------------------------
//
// 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);
}
}