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.
 
 
 
 
 
 

547 lines
12 KiB

//+----------------------------------------------------------------------------//+----------------------------------------------------------------------------
//
// Copyright (C) 2001, Microsoft Corporation
//
// File: dfsumr.c
//
// Contents:
//
//
// Functions:
//
// Author - Rohan Phillips (Rohanp)
//-----------------------------------------------------------------------------
#include "ntifs.h"
#include <windef.h>
#include <DfsReferralData.h>
#include <midatlax.h>
#include <rxcontx.h>
#include <dfsumr.h>
#include <umrx.h>
#include <dfsumrctrl.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, DfsInitializeUmrResources)
#pragma alloc_text(PAGE, DfsDeInitializeUmrResources)
#pragma alloc_text(PAGE, DfsWaitForPendingClients)
#pragma alloc_text(PAGE, DfsStartupUMRx)
#pragma alloc_text(PAGE, DfsTeardownUMRx)
#pragma alloc_text(PAGE, DfsProcessUMRxPacket)
#pragma alloc_text(PAGE, AddUmrRef)
#pragma alloc_text(PAGE, ReleaseUmrRef)
#pragma alloc_text(PAGE, IsUmrEnabled)
#pragma alloc_text(PAGE, LockUmrShared)
#pragma alloc_text(PAGE, GetUMRxEngineFromRxContext)
#endif
#define DFS_INIT_REFLOCK 0x00000001
#define DFS_INIT_UMRXENG 0x00000002
#define DFS_INIT_CONTEXT 0x00000004
//
// Number of usecs that the thread disabling the reflection should wait
// between checks. negative value for relative time.
// 1,000,000 usecs => 1 sec
//
#define DFS_UMR_DISABLE_DELAY -100000
BOOL ReflectionEngineInitialized = FALSE;
ULONG cUserModeReflectionsInProgress = 0;
NTSTATUS g_CheckStatus = 0xFFFFFFFF;
DWORD InitilizationStatus = 0;
PERESOURCE gReflectionLock = NULL;
PUMRX_ENGINE g_pUMRxEngine = NULL;
PERESOURCE
CreateResource(void ) ;
void
ReleaseResource(PERESOURCE pResource ) ;
//+-------------------------------------------------------------------------
//
// Function: DfsInitializeUmrResources
//
// Arguments:
//
// Returns: Status
// ERROR_SUCCESS on success
// ERROR status code otherwise
//
//
// Description: Initializes all resources neder for the usermode reflector
//
//--------------------------------------------------------------------------
NTSTATUS
DfsInitializeUmrResources(void)
{
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
gReflectionLock = CreateResource();
if(gReflectionLock != NULL)
{
InitilizationStatus |= DFS_INIT_REFLOCK;
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
g_pUMRxEngine = CreateUMRxEngine();
if(g_pUMRxEngine != NULL)
{
InitilizationStatus |= DFS_INIT_UMRXENG;
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
Status = DfsInitializeContextResources();
if(Status == STATUS_SUCCESS)
{
InitilizationStatus |= DFS_INIT_CONTEXT;
}
Exit:
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: DfsDeInitializeUmrResources
//
// Arguments:
//
// Returns: Status
// ERROR_SUCCESS on success
// ERROR status code otherwise
//
//
// Description: Releases all resources neder for the usermode reflector
//
//--------------------------------------------------------------------------
void
DfsDeInitializeUmrResources(void)
{
PAGED_CODE();
if(InitilizationStatus & DFS_INIT_REFLOCK)
{
ReleaseResource(gReflectionLock);
gReflectionLock = NULL;
}
if(InitilizationStatus & DFS_INIT_UMRXENG)
{
if(g_pUMRxEngine != NULL)
{
FinalizeUMRxEngine (g_pUMRxEngine);
g_pUMRxEngine = NULL;
}
}
if(InitilizationStatus & DFS_INIT_CONTEXT)
{
DfsDeInitializeContextResources();
}
}
PERESOURCE
CreateResource(void )
{
PERESOURCE pResource = NULL;
PAGED_CODE();
pResource = ExAllocatePoolWithTag( NonPagedPool,
sizeof( ERESOURCE ),
'DfsR');
if( pResource )
{
if( !NT_SUCCESS( ExInitializeResourceLite( pResource ) ) )
{
ExFreePool( pResource ) ;
pResource = NULL ;
}
}
return pResource ;
}
void
ReleaseResource(PERESOURCE pResource )
{
PAGED_CODE();
ASSERT( pResource != 0 ) ;
if( pResource )
{
ExDeleteResourceLite( pResource ) ;
ExFreePool( pResource ) ;
}
}
//+-------------------------------------------------------------------------
//
// Function: DfsEnableReflectionEngine
//
// Arguments:
//
// Returns: Status
// ERROR_SUCCESS on success
// ERROR status code otherwise
//
//
// Description: Changes the reflector state to stopped
//
//--------------------------------------------------------------------------
NTSTATUS
DfsEnableReflectionEngine(void)
{
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
ReflectionEngineInitialized = TRUE;
if(g_pUMRxEngine)
{
InterlockedExchange(&g_pUMRxEngine->Q.State,
UMRX_ENGINE_STATE_STOPPED);
}
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: DfsWaitForPendingClients
//
// Arguments:
//
// Returns: Status
// ERROR_SUCCESS on success
// ERROR status code otherwise
//
//
// Description: Waits for all clients to exit relector before returning
//
//--------------------------------------------------------------------------
NTSTATUS
DfsWaitForPendingClients(void)
{
BOOLEAN fDone = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
LARGE_INTEGER liDelay;
liDelay.QuadPart = DFS_UMR_DISABLE_DELAY;
PAGED_CODE();
while (!fDone)
{
ExAcquireResourceExclusiveLite(&g_pUMRxEngine->Q.Lock,TRUE);
if (ReflectionEngineInitialized)
{
if (0 == g_pUMRxEngine->cUserModeReflectionsInProgress)
{
fDone = TRUE;
}
else
{
}
}
else
{
fDone = TRUE;
}
ExReleaseResourceForThreadLite(&g_pUMRxEngine->Q.Lock,ExGetCurrentResourceThread());
if (!fDone)
{
KeDelayExecutionThread(UserMode, FALSE, &liDelay);
}
}
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: DfsStartupUMRx
//
// Arguments:
//
// Returns: Status
// ERROR_SUCCESS on success
// ERROR status code otherwise
//
//
// Description: Starts the reflector engine
//
//--------------------------------------------------------------------------
NTSTATUS
DfsStartupUMRx(void)
{
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
ExAcquireResourceExclusiveLite(gReflectionLock,TRUE);
Status = UMRxEngineRestart(g_pUMRxEngine);
if(Status == STATUS_SUCCESS)
{
ReflectionEngineInitialized = TRUE;
}
ExReleaseResourceForThreadLite(gReflectionLock,ExGetCurrentResourceThread());
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: DfsTeardownUMRx
//
// Arguments:
//
// Returns: Status
// ERROR_SUCCESS on success
// ERROR status code otherwise
//
//
// Description: Stops the reflector engine
//
//--------------------------------------------------------------------------
NTSTATUS
DfsTeardownUMRx(void)
{
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
if(g_pUMRxEngine)
{
Status = UMRxEngineReleaseThreads(g_pUMRxEngine);
}
ReflectionEngineInitialized = FALSE;
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: DfsProcessUMRxPacket
//
// Arguments:
//
// Returns: Status
// ERROR_SUCCESS on success
// ERROR status code otherwise
//
//
// Description: Processes a packet from usermode
//
//--------------------------------------------------------------------------
NTSTATUS
DfsProcessUMRxPacket(
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN OUT PIO_STATUS_BLOCK pIoStatusBlock)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
BOOLEAN fReturnImmediately = FALSE;
IO_STATUS_BLOCK Iosb;
PAGED_CODE();
if ((InputBuffer == NULL) && (OutputBuffer == NULL))
{
UMRxEngineCompleteQueuedRequests(
g_pUMRxEngine,
STATUS_INSUFFICIENT_RESOURCES,
FALSE);
Status = STATUS_SUCCESS;
goto Exit;
}
//
// Recd a response packet from umode - process it
//
Status = UMRxCompleteUserModeRequest(
g_pUMRxEngine,
(PUMRX_USERMODE_WORKITEM) InputBuffer,
InputBufferLength,
TRUE,
&Iosb,
&fReturnImmediately
);
if( !NT_SUCCESS(Iosb.Status) )
{
}
if (fReturnImmediately)
{
pIoStatusBlock->Status = STATUS_SUCCESS;
pIoStatusBlock->Information = 0;
goto Exit;
}
//
// Remove a request from the Engine and process it
//
Status = UMRxEngineProcessRequest(
g_pUMRxEngine,
(PUMRX_USERMODE_WORKITEM) OutputBuffer,
OutputBufferLength,
&OutputBufferLength
);
if( !NT_SUCCESS(Status) )
{
//
// error processing request
//
}
pIoStatusBlock->Information = OutputBufferLength;
Exit:
pIoStatusBlock->Status = Status;
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: AddUmrRef
//
// Arguments:
//
// Returns: Number of clients using reflector
//
//
// Description: Increments the number of clients using the reflector
//
//--------------------------------------------------------------------------
LONG
AddUmrRef(void)
{
LONG cRefs = 0;
PAGED_CODE();
cRefs = InterlockedIncrement(&g_pUMRxEngine->cUserModeReflectionsInProgress);
//DFS_TRACE_HIGH (KUMR_DETAIL, "AddUmrRef %d\n", cRefs);
ASSERT(cRefs > 0);
return cRefs;
}
//+-------------------------------------------------------------------------
//
// Function: ReleaseUmrRef
//
// Arguments:
//
// Returns: Number of clients using reflector
//
//
// Description: Deccrements the number of clients using the reflector
//
//--------------------------------------------------------------------------
LONG
ReleaseUmrRef(void)
{
LONG cRefs = 0;
PAGED_CODE();
cRefs = InterlockedDecrement(&g_pUMRxEngine->cUserModeReflectionsInProgress);
//DFS_TRACE_HIGH (KUMR_DETAIL, "ReleaseUmrRef %d\n", cRefs);
//ASSERT(cRefs >= 0); //this is a harmless assert. It's removed for now.
return cRefs;
}
//+-------------------------------------------------------------------------
//
// Function: GetUMRxEngineFromRxContext
//
// Arguments:
//
// Returns: A pointer to the reflector engine
//
//
// Description: returns a pointer to the reflector engine
//
//--------------------------------------------------------------------------
PUMRX_ENGINE
GetUMRxEngineFromRxContext(void)
{
PAGED_CODE();
return g_pUMRxEngine;
}
BOOL IsUmrEnabled(void)
{
PAGED_CODE();
return ReflectionEngineInitialized;
}
BOOLEAN LockUmrShared(void)
{
BOOLEAN fAcquired = FALSE;
PAGED_CODE();
fAcquired = ExAcquireResourceSharedLite(&g_pUMRxEngine->Q.Lock, FALSE);
return fAcquired;
}
void UnLockUmrShared(void)
{
PAGED_CODE();
ExReleaseResourceForThreadLite (&g_pUMRxEngine->Q.Lock,ExGetCurrentResourceThread());
}