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.
 
 
 
 
 
 

388 lines
9.7 KiB

/*++
Copyright (c) 2000-2000 Microsoft Corporation
Module Name:
Utils.c
Abstract:
This module implements various Utility routines used by
the PGM Transport
Author:
Mohammad Shabbir Alam (MAlam) 3-30-2000
Revision History:
--*/
#include "precomp.h"
//******************* Pageable Routine Declarations ****************
#ifdef ALLOC_PRAGMA
#endif
//******************* Pageable Routine Declarations ****************
//----------------------------------------------------------------------------
VOID
GetRandomData(
IN PUCHAR pBuffer,
IN ULONG BufferSize
)
/*++
Routine Description:
This routine returns a random integer calculated using the help of SystemTime
Arguments:
IN StartRange -- Lower bound for range
IN EndRange -- upper bound for range
Return Value:
Random integer between StartRange and EndRange (inclusive)
If StartRange >= EndRange, then StartRange is returned
--*/
{
LARGE_INTEGER TimeValue;
ULONG i;
UCHAR *pRandom = (PUCHAR) &TimeValue.LowPart;
if ((PgmGetCurrentIrql()) ||
(!PgmFipsInitialize ()) ||
(!PgmStaticConfig.FipsFunctionTable.FIPSGenRandom (pBuffer, BufferSize)))
{
//
// We were unable to use the Fips routine, so fallback to a quick'n'dirty mechanism
//
while (BufferSize)
{
KeQuerySystemTime (&TimeValue);
// the lower 4 bits appear to be zero always...!!
TimeValue.QuadPart = TimeValue.QuadPart >> 4;
for (i = 0; i <sizeof(TimeValue.LowPart); i++)
{
pBuffer[BufferSize-1] = pRandom[i];
if (!--BufferSize)
{
break;
}
}
}
}
}
ULONG
GetRandomInteger(
IN ULONG StartRange,
IN ULONG EndRange
)
/*++
Routine Description:
This routine returns a random integer calculated using the help of SystemTime
Arguments:
IN StartRange -- Lower bound for range
IN EndRange -- upper bound for range
Return Value:
Random integer between StartRange and EndRange (inclusive)
If StartRange >= EndRange, then StartRange is returned
--*/
{
ULONG RandomNumber;
ULONG Range = (EndRange - StartRange) + 1;
if (StartRange >= EndRange)
{
return (StartRange);
}
GetRandomData ((PUCHAR) &RandomNumber, sizeof (RandomNumber));
return (StartRange + (RandomNumber % Range));
}
//----------------------------------------------------------------------------
VOID
PgmExecuteWorker(
IN PVOID pContextInfo
)
/*++
Routine Description:
This routine handles executing delayed requests at non-Dpc level. If
the Driver is currently being unloaded, we let the Unload Handler
complete the request.
Arguments:
pContext - the Context data for this Worker thread
Return Value:
none
--*/
{
PGM_WORKER_CONTEXT *pContext = (PGM_WORKER_CONTEXT *) pContextInfo;
PPGM_WORKER_ROUTINE pDelayedWorkerRoutine = (PPGM_WORKER_ROUTINE) pContext->WorkerRoutine;
PGMLockHandle OldIrq;
(*pDelayedWorkerRoutine) (pContext->Context1,
pContext->Context2,
pContext->Context3);
PgmFreeMem ((PVOID) pContext);
PgmLock (&PgmDynamicConfig, OldIrq);
if ((!--PgmDynamicConfig.NumWorkerThreadsQueued) &&
(PgmDynamicConfig.GlobalFlags & PGM_CONFIG_FLAG_UNLOADING))
{
PgmUnlock (&PgmDynamicConfig, OldIrq);
KeSetEvent(&PgmDynamicConfig.LastWorkerItemEvent, 0, FALSE);
}
else
{
PgmUnlock (&PgmDynamicConfig, OldIrq);
}
}
//----------------------------------------------------------------------------
NTSTATUS
PgmQueueForDelayedExecution(
IN PVOID DelayedWorkerRoutine,
IN PVOID Context1,
IN PVOID Context2,
IN PVOID Context3,
IN BOOLEAN fConfigLockHeld
)
/*++
Routine Description:
This routine simply queues a request on an excutive worker thread
for later execution.
Arguments:
DelayedWorkerRoutine- the routine for the Workerthread to call
Context1 - Context
Context2
Context3
Return Value:
NTSTATUS -- Final status of the Queue request
--*/
{
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
PGM_WORKER_CONTEXT *pContext;
PGMLockHandle OldIrq;
if (!fConfigLockHeld)
{
PgmLock (&PgmDynamicConfig, OldIrq);
}
if (pContext = (PGM_WORKER_CONTEXT *) PgmAllocMem (sizeof(PGM_WORKER_CONTEXT), PGM_TAG('2')))
{
PgmZeroMemory (pContext, sizeof(PGM_WORKER_CONTEXT));
InitializeListHead(&pContext->PgmConfigLinkage);
pContext->Context1 = Context1;
pContext->Context2 = Context2;
pContext->Context3 = Context3;
pContext->WorkerRoutine = DelayedWorkerRoutine;
//
// Don't Queue this request onto the Worker Queue if we have
// already started unloading
//
if (PgmDynamicConfig.GlobalFlags & PGM_CONFIG_FLAG_UNLOADING)
{
InsertTailList (&PgmDynamicConfig.WorkerQList, &pContext->PgmConfigLinkage);
}
else
{
++PgmDynamicConfig.NumWorkerThreadsQueued;
ExInitializeWorkItem (&pContext->Item, PgmExecuteWorker, pContext);
ExQueueWorkItem (&pContext->Item, DelayedWorkQueue);
}
status = STATUS_SUCCESS;
}
if (!fConfigLockHeld)
{
PgmUnlock (&PgmDynamicConfig, OldIrq);
}
return (status);
}
//----------------------------------------------------------------------------
//
// The following routines are temporary and will be replaced by WMI logging
// in the near future
//
//----------------------------------------------------------------------------
#ifdef OLD_LOGGING
// ULONG PgmDebugFlags = DBG_ENABLE_DBGPRINT;
// ULONG PgmDebugFlags = 0xffffffff;
#if DBG
enum eSEVERITY_LEVEL PgmDebuggerSeverity = PGM_LOG_INFORM_STATUS;
#else
enum eSEVERITY_LEVEL PgmDebuggerSeverity = PGM_LOG_DISABLED;
#endif // DBG
ULONG PgmDebuggerPath = 0xffffffff;
enum eSEVERITY_LEVEL PgmLogFileSeverity = PGM_LOG_DISABLED;
ULONG PgmLogFilePath = 0x0;
NTSTATUS
_PgmLog(
IN enum eSEVERITY_LEVEL Severity,
IN ULONG Path,
IN PUCHAR pszFunctionName,
IN PUCHAR Format,
IN va_list Marker
)
/*++
Routine Description:
This routine
Arguments:
IN
Return Value:
NTSTATUS - Final status of the set event operation
--*/
{
PUCHAR pLogBuffer = NULL;
if ((Path & PgmLogFilePath) && (Severity <= PgmLogFileSeverity))
{
ASSERT (0); // Not implemented yet!
}
if ((Path & PgmDebuggerPath) && (Severity <= PgmDebuggerSeverity))
{
if (MAX_DEBUG_MESSAGE_LENGTH <= (sizeof ("RMCast.") +
sizeof (": ") +
sizeof ("ERROR -- ") +
strlen (pszFunctionName) + 1))
{
DbgPrint ("PgmLog: FunctionName=<%s> too big to print!\n", pszFunctionName);
return (STATUS_UNSUCCESSFUL);
}
if (!(pLogBuffer = ExAllocateFromNPagedLookasideList (&PgmStaticConfig.DebugMessagesLookasideList)))
{
DbgPrint ("PgmLog: STATUS_INSUFFICIENT_RESOURCES Logging %sMessage from Function=<%s>\n",
((Severity == PGM_LOG_ERROR || Severity == PGM_LOG_CRITICAL_ERROR) ? "ERROR " : ""), pszFunctionName);
return (STATUS_INSUFFICIENT_RESOURCES);
}
strcpy(pLogBuffer, "RMCast.");
strcat(pLogBuffer, pszFunctionName);
strcat(pLogBuffer, ": ");
if ((Severity == PGM_LOG_ERROR) ||
(Severity == PGM_LOG_CRITICAL_ERROR))
{
strcat(pLogBuffer, "ERROR -- ");
}
_vsnprintf (pLogBuffer+strlen(pLogBuffer), MAX_DEBUG_MESSAGE_LENGTH-strlen(pLogBuffer), Format, Marker);
pLogBuffer[MAX_DEBUG_MESSAGE_LENGTH] = '\0';
DbgPrint ("%s", pLogBuffer);
ExFreeToNPagedLookasideList (&PgmStaticConfig.DebugMessagesLookasideList, pLogBuffer);
}
return (STATUS_SUCCESS);
}
//----------------------------------------------------------------------------
NTSTATUS
PgmLog(
IN enum eSEVERITY_LEVEL Severity,
IN ULONG Path,
IN PUCHAR pszFunctionName,
IN PUCHAR Format,
...
)
/*++
Routine Description:
This routine
Arguments:
IN
Return Value:
NTSTATUS - Final status of the set event operation
--*/
{
NTSTATUS status = STATUS_SUCCESS;
va_list Marker;
//
// Based on our Path and the Flags, see if this Event qualifies
// for being logged
//
if (((Path & PgmDebuggerPath) && (Severity <= PgmDebuggerSeverity)) ||
((Path & PgmLogFilePath) && (Severity <= PgmLogFileSeverity)))
{
va_start (Marker, Format);
status =_PgmLog (Severity, Path, pszFunctionName, Format, Marker);
va_end (Marker);
}
return (status);
}
//----------------------------------------------------------------------------
#endif // OLD_LOGGING