321 lines
7.7 KiB
C
321 lines
7.7 KiB
C
|
/*++
|
|||
|
|
|||
|
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"
|
|||
|
#include <stdio.h>
|
|||
|
|
|||
|
|
|||
|
//******************* Pageable Routine Declarations ****************
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#endif
|
|||
|
//******************* Pageable Routine Declarations ****************
|
|||
|
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
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 Range = (EndRange - StartRange) + 1;
|
|||
|
LARGE_INTEGER TimeValue;
|
|||
|
|
|||
|
if (StartRange >= EndRange)
|
|||
|
{
|
|||
|
return (StartRange);
|
|||
|
}
|
|||
|
|
|||
|
KeQuerySystemTime (&TimeValue);
|
|||
|
// the lower 4 bits appear to be zero always...!!
|
|||
|
return (StartRange + ((TimeValue.LowTime >> 8) % 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
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
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);
|
|||
|
}
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|