Source code of Windows XP (NT5)
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.

320 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 2000-2000 Microsoft Corporation
  3. Module Name:
  4. Utils.c
  5. Abstract:
  6. This module implements various Utility routines used by
  7. the PGM Transport
  8. Author:
  9. Mohammad Shabbir Alam (MAlam) 3-30-2000
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include <stdio.h>
  14. //******************* Pageable Routine Declarations ****************
  15. #ifdef ALLOC_PRAGMA
  16. #endif
  17. //******************* Pageable Routine Declarations ****************
  18. //----------------------------------------------------------------------------
  19. ULONG
  20. GetRandomInteger(
  21. IN ULONG StartRange,
  22. IN ULONG EndRange
  23. )
  24. /*++
  25. Routine Description:
  26. This routine returns a random integer calculated using the help of SystemTime
  27. Arguments:
  28. IN StartRange -- Lower bound for range
  29. IN EndRange -- upper bound for range
  30. Return Value:
  31. Random integer between StartRange and EndRange (inclusive)
  32. If StartRange >= EndRange, then StartRange is returned
  33. --*/
  34. {
  35. ULONG Range = (EndRange - StartRange) + 1;
  36. LARGE_INTEGER TimeValue;
  37. if (StartRange >= EndRange)
  38. {
  39. return (StartRange);
  40. }
  41. KeQuerySystemTime (&TimeValue);
  42. // the lower 4 bits appear to be zero always...!!
  43. return (StartRange + ((TimeValue.LowTime >> 8) % Range));
  44. }
  45. //----------------------------------------------------------------------------
  46. VOID
  47. PgmExecuteWorker(
  48. IN PVOID pContextInfo
  49. )
  50. /*++
  51. Routine Description:
  52. This routine handles executing delayed requests at non-Dpc level. If
  53. the Driver is currently being unloaded, we let the Unload Handler
  54. complete the request.
  55. Arguments:
  56. pContext - the Context data for this Worker thread
  57. Return Value:
  58. none
  59. --*/
  60. {
  61. PGM_WORKER_CONTEXT *pContext = (PGM_WORKER_CONTEXT *) pContextInfo;
  62. PPGM_WORKER_ROUTINE pDelayedWorkerRoutine = (PPGM_WORKER_ROUTINE) pContext->WorkerRoutine;
  63. PGMLockHandle OldIrq;
  64. (*pDelayedWorkerRoutine) (pContext->Context1,
  65. pContext->Context2,
  66. pContext->Context3);
  67. PgmFreeMem ((PVOID) pContext);
  68. PgmLock (&PgmDynamicConfig, OldIrq);
  69. if ((!--PgmDynamicConfig.NumWorkerThreadsQueued) &&
  70. (PgmDynamicConfig.GlobalFlags & PGM_CONFIG_FLAG_UNLOADING))
  71. {
  72. PgmUnlock (&PgmDynamicConfig, OldIrq);
  73. KeSetEvent(&PgmDynamicConfig.LastWorkerItemEvent, 0, FALSE);
  74. }
  75. else
  76. {
  77. PgmUnlock (&PgmDynamicConfig, OldIrq);
  78. }
  79. }
  80. //----------------------------------------------------------------------------
  81. NTSTATUS
  82. PgmQueueForDelayedExecution(
  83. IN PVOID DelayedWorkerRoutine,
  84. IN PVOID Context1,
  85. IN PVOID Context2,
  86. IN PVOID Context3,
  87. IN BOOLEAN fConfigLockHeld
  88. )
  89. /*++
  90. Routine Description:
  91. This routine simply queues a request on an excutive worker thread
  92. for later execution.
  93. Arguments:
  94. DelayedWorkerRoutine- the routine for the Workerthread to call
  95. Context1 - Context
  96. Context2
  97. Context3
  98. Return Value:
  99. NTSTATUS -- Final status of the Queue request
  100. --*/
  101. {
  102. NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
  103. PGM_WORKER_CONTEXT *pContext;
  104. PGMLockHandle OldIrq;
  105. if (!fConfigLockHeld)
  106. {
  107. PgmLock (&PgmDynamicConfig, OldIrq);
  108. }
  109. if (pContext = (PGM_WORKER_CONTEXT *) PgmAllocMem (sizeof(PGM_WORKER_CONTEXT), PGM_TAG('2')))
  110. {
  111. PgmZeroMemory (pContext, sizeof(PGM_WORKER_CONTEXT));
  112. InitializeListHead(&pContext->PgmConfigLinkage);
  113. pContext->Context1 = Context1;
  114. pContext->Context2 = Context2;
  115. pContext->Context3 = Context3;
  116. pContext->WorkerRoutine = DelayedWorkerRoutine;
  117. //
  118. // Don't Queue this request onto the Worker Queue if we have
  119. // already started unloading
  120. //
  121. if (PgmDynamicConfig.GlobalFlags & PGM_CONFIG_FLAG_UNLOADING)
  122. {
  123. InsertTailList (&PgmDynamicConfig.WorkerQList, &pContext->PgmConfigLinkage);
  124. }
  125. else
  126. {
  127. ++PgmDynamicConfig.NumWorkerThreadsQueued;
  128. ExInitializeWorkItem (&pContext->Item, PgmExecuteWorker, pContext);
  129. ExQueueWorkItem (&pContext->Item, DelayedWorkQueue);
  130. }
  131. status = STATUS_SUCCESS;
  132. }
  133. if (!fConfigLockHeld)
  134. {
  135. PgmUnlock (&PgmDynamicConfig, OldIrq);
  136. }
  137. return (status);
  138. }
  139. //----------------------------------------------------------------------------
  140. //
  141. // The following routines are temporary and will be replaced by WMI logging
  142. // in the near future
  143. //
  144. //----------------------------------------------------------------------------
  145. NTSTATUS
  146. _PgmLog(
  147. IN enum eSEVERITY_LEVEL Severity,
  148. IN ULONG Path,
  149. IN PUCHAR pszFunctionName,
  150. IN PUCHAR Format,
  151. IN va_list Marker
  152. )
  153. /*++
  154. Routine Description:
  155. This routine
  156. Arguments:
  157. IN
  158. Return Value:
  159. NTSTATUS - Final status of the set event operation
  160. --*/
  161. {
  162. PUCHAR pLogBuffer = NULL;
  163. if ((Path & PgmLogFilePath) && (Severity <= PgmLogFileSeverity))
  164. {
  165. ASSERT (0); // Not implemented yet!
  166. }
  167. if ((Path & PgmDebuggerPath) && (Severity <= PgmDebuggerSeverity))
  168. {
  169. if (MAX_DEBUG_MESSAGE_LENGTH <= (sizeof ("RMCast.") +
  170. sizeof (": ") +
  171. sizeof ("ERROR -- ") +
  172. strlen (pszFunctionName) + 1))
  173. {
  174. DbgPrint ("PgmLog: FunctionName=<%s> too big to print!\n", pszFunctionName);
  175. return (STATUS_UNSUCCESSFUL);
  176. }
  177. if (!(pLogBuffer = ExAllocateFromNPagedLookasideList (&PgmStaticConfig.DebugMessagesLookasideList)))
  178. {
  179. DbgPrint ("PgmLog: STATUS_INSUFFICIENT_RESOURCES Logging %sMessage from Function=<%s>\n",
  180. ((Severity == PGM_LOG_ERROR || Severity == PGM_LOG_CRITICAL_ERROR) ? "ERROR " : ""), pszFunctionName);
  181. return (STATUS_INSUFFICIENT_RESOURCES);
  182. }
  183. strcpy(pLogBuffer, "RMCast.");
  184. strcat(pLogBuffer, pszFunctionName);
  185. strcat(pLogBuffer, ": ");
  186. if ((Severity == PGM_LOG_ERROR) ||
  187. (Severity == PGM_LOG_CRITICAL_ERROR))
  188. {
  189. strcat(pLogBuffer, "ERROR -- ");
  190. }
  191. _vsnprintf (pLogBuffer+strlen(pLogBuffer), MAX_DEBUG_MESSAGE_LENGTH-strlen(pLogBuffer), Format, Marker);
  192. pLogBuffer[MAX_DEBUG_MESSAGE_LENGTH] = '\0';
  193. DbgPrint ("%s", pLogBuffer);
  194. ExFreeToNPagedLookasideList (&PgmStaticConfig.DebugMessagesLookasideList, pLogBuffer);
  195. }
  196. return (STATUS_SUCCESS);
  197. }
  198. //----------------------------------------------------------------------------
  199. NTSTATUS
  200. PgmLog(
  201. IN enum eSEVERITY_LEVEL Severity,
  202. IN ULONG Path,
  203. IN PUCHAR pszFunctionName,
  204. IN PUCHAR Format,
  205. ...
  206. )
  207. /*++
  208. Routine Description:
  209. This routine
  210. Arguments:
  211. IN
  212. Return Value:
  213. NTSTATUS - Final status of the set event operation
  214. --*/
  215. {
  216. NTSTATUS status = STATUS_SUCCESS;
  217. va_list Marker;
  218. //
  219. // Based on our Path and the Flags, see if this Event qualifies
  220. // for being logged
  221. //
  222. if (((Path & PgmDebuggerPath) && (Severity <= PgmDebuggerSeverity)) ||
  223. ((Path & PgmLogFilePath) && (Severity <= PgmLogFileSeverity)))
  224. {
  225. va_start (Marker, Format);
  226. status =_PgmLog (Severity, Path, pszFunctionName, Format, Marker);
  227. va_end (Marker);
  228. }
  229. return (status);
  230. }
  231. //----------------------------------------------------------------------------