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

  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. //******************* Pageable Routine Declarations ****************
  14. #ifdef ALLOC_PRAGMA
  15. #endif
  16. //******************* Pageable Routine Declarations ****************
  17. //----------------------------------------------------------------------------
  18. VOID
  19. GetRandomData(
  20. IN PUCHAR pBuffer,
  21. IN ULONG BufferSize
  22. )
  23. /*++
  24. Routine Description:
  25. This routine returns a random integer calculated using the help of SystemTime
  26. Arguments:
  27. IN StartRange -- Lower bound for range
  28. IN EndRange -- upper bound for range
  29. Return Value:
  30. Random integer between StartRange and EndRange (inclusive)
  31. If StartRange >= EndRange, then StartRange is returned
  32. --*/
  33. {
  34. LARGE_INTEGER TimeValue;
  35. ULONG i;
  36. UCHAR *pRandom = (PUCHAR) &TimeValue.LowPart;
  37. if ((PgmGetCurrentIrql()) ||
  38. (!PgmFipsInitialize ()) ||
  39. (!PgmStaticConfig.FipsFunctionTable.FIPSGenRandom (pBuffer, BufferSize)))
  40. {
  41. //
  42. // We were unable to use the Fips routine, so fallback to a quick'n'dirty mechanism
  43. //
  44. while (BufferSize)
  45. {
  46. KeQuerySystemTime (&TimeValue);
  47. // the lower 4 bits appear to be zero always...!!
  48. TimeValue.QuadPart = TimeValue.QuadPart >> 4;
  49. for (i = 0; i <sizeof(TimeValue.LowPart); i++)
  50. {
  51. pBuffer[BufferSize-1] = pRandom[i];
  52. if (!--BufferSize)
  53. {
  54. break;
  55. }
  56. }
  57. }
  58. }
  59. }
  60. ULONG
  61. GetRandomInteger(
  62. IN ULONG StartRange,
  63. IN ULONG EndRange
  64. )
  65. /*++
  66. Routine Description:
  67. This routine returns a random integer calculated using the help of SystemTime
  68. Arguments:
  69. IN StartRange -- Lower bound for range
  70. IN EndRange -- upper bound for range
  71. Return Value:
  72. Random integer between StartRange and EndRange (inclusive)
  73. If StartRange >= EndRange, then StartRange is returned
  74. --*/
  75. {
  76. ULONG RandomNumber;
  77. ULONG Range = (EndRange - StartRange) + 1;
  78. if (StartRange >= EndRange)
  79. {
  80. return (StartRange);
  81. }
  82. GetRandomData ((PUCHAR) &RandomNumber, sizeof (RandomNumber));
  83. return (StartRange + (RandomNumber % Range));
  84. }
  85. //----------------------------------------------------------------------------
  86. VOID
  87. PgmExecuteWorker(
  88. IN PVOID pContextInfo
  89. )
  90. /*++
  91. Routine Description:
  92. This routine handles executing delayed requests at non-Dpc level. If
  93. the Driver is currently being unloaded, we let the Unload Handler
  94. complete the request.
  95. Arguments:
  96. pContext - the Context data for this Worker thread
  97. Return Value:
  98. none
  99. --*/
  100. {
  101. PGM_WORKER_CONTEXT *pContext = (PGM_WORKER_CONTEXT *) pContextInfo;
  102. PPGM_WORKER_ROUTINE pDelayedWorkerRoutine = (PPGM_WORKER_ROUTINE) pContext->WorkerRoutine;
  103. PGMLockHandle OldIrq;
  104. (*pDelayedWorkerRoutine) (pContext->Context1,
  105. pContext->Context2,
  106. pContext->Context3);
  107. PgmFreeMem ((PVOID) pContext);
  108. PgmLock (&PgmDynamicConfig, OldIrq);
  109. if ((!--PgmDynamicConfig.NumWorkerThreadsQueued) &&
  110. (PgmDynamicConfig.GlobalFlags & PGM_CONFIG_FLAG_UNLOADING))
  111. {
  112. PgmUnlock (&PgmDynamicConfig, OldIrq);
  113. KeSetEvent(&PgmDynamicConfig.LastWorkerItemEvent, 0, FALSE);
  114. }
  115. else
  116. {
  117. PgmUnlock (&PgmDynamicConfig, OldIrq);
  118. }
  119. }
  120. //----------------------------------------------------------------------------
  121. NTSTATUS
  122. PgmQueueForDelayedExecution(
  123. IN PVOID DelayedWorkerRoutine,
  124. IN PVOID Context1,
  125. IN PVOID Context2,
  126. IN PVOID Context3,
  127. IN BOOLEAN fConfigLockHeld
  128. )
  129. /*++
  130. Routine Description:
  131. This routine simply queues a request on an excutive worker thread
  132. for later execution.
  133. Arguments:
  134. DelayedWorkerRoutine- the routine for the Workerthread to call
  135. Context1 - Context
  136. Context2
  137. Context3
  138. Return Value:
  139. NTSTATUS -- Final status of the Queue request
  140. --*/
  141. {
  142. NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
  143. PGM_WORKER_CONTEXT *pContext;
  144. PGMLockHandle OldIrq;
  145. if (!fConfigLockHeld)
  146. {
  147. PgmLock (&PgmDynamicConfig, OldIrq);
  148. }
  149. if (pContext = (PGM_WORKER_CONTEXT *) PgmAllocMem (sizeof(PGM_WORKER_CONTEXT), PGM_TAG('2')))
  150. {
  151. PgmZeroMemory (pContext, sizeof(PGM_WORKER_CONTEXT));
  152. InitializeListHead(&pContext->PgmConfigLinkage);
  153. pContext->Context1 = Context1;
  154. pContext->Context2 = Context2;
  155. pContext->Context3 = Context3;
  156. pContext->WorkerRoutine = DelayedWorkerRoutine;
  157. //
  158. // Don't Queue this request onto the Worker Queue if we have
  159. // already started unloading
  160. //
  161. if (PgmDynamicConfig.GlobalFlags & PGM_CONFIG_FLAG_UNLOADING)
  162. {
  163. InsertTailList (&PgmDynamicConfig.WorkerQList, &pContext->PgmConfigLinkage);
  164. }
  165. else
  166. {
  167. ++PgmDynamicConfig.NumWorkerThreadsQueued;
  168. ExInitializeWorkItem (&pContext->Item, PgmExecuteWorker, pContext);
  169. ExQueueWorkItem (&pContext->Item, DelayedWorkQueue);
  170. }
  171. status = STATUS_SUCCESS;
  172. }
  173. if (!fConfigLockHeld)
  174. {
  175. PgmUnlock (&PgmDynamicConfig, OldIrq);
  176. }
  177. return (status);
  178. }
  179. //----------------------------------------------------------------------------
  180. //
  181. // The following routines are temporary and will be replaced by WMI logging
  182. // in the near future
  183. //
  184. //----------------------------------------------------------------------------
  185. #ifdef OLD_LOGGING
  186. // ULONG PgmDebugFlags = DBG_ENABLE_DBGPRINT;
  187. // ULONG PgmDebugFlags = 0xffffffff;
  188. #if DBG
  189. enum eSEVERITY_LEVEL PgmDebuggerSeverity = PGM_LOG_INFORM_STATUS;
  190. #else
  191. enum eSEVERITY_LEVEL PgmDebuggerSeverity = PGM_LOG_DISABLED;
  192. #endif // DBG
  193. ULONG PgmDebuggerPath = 0xffffffff;
  194. enum eSEVERITY_LEVEL PgmLogFileSeverity = PGM_LOG_DISABLED;
  195. ULONG PgmLogFilePath = 0x0;
  196. NTSTATUS
  197. _PgmLog(
  198. IN enum eSEVERITY_LEVEL Severity,
  199. IN ULONG Path,
  200. IN PUCHAR pszFunctionName,
  201. IN PUCHAR Format,
  202. IN va_list Marker
  203. )
  204. /*++
  205. Routine Description:
  206. This routine
  207. Arguments:
  208. IN
  209. Return Value:
  210. NTSTATUS - Final status of the set event operation
  211. --*/
  212. {
  213. PUCHAR pLogBuffer = NULL;
  214. if ((Path & PgmLogFilePath) && (Severity <= PgmLogFileSeverity))
  215. {
  216. ASSERT (0); // Not implemented yet!
  217. }
  218. if ((Path & PgmDebuggerPath) && (Severity <= PgmDebuggerSeverity))
  219. {
  220. if (MAX_DEBUG_MESSAGE_LENGTH <= (sizeof ("RMCast.") +
  221. sizeof (": ") +
  222. sizeof ("ERROR -- ") +
  223. strlen (pszFunctionName) + 1))
  224. {
  225. DbgPrint ("PgmLog: FunctionName=<%s> too big to print!\n", pszFunctionName);
  226. return (STATUS_UNSUCCESSFUL);
  227. }
  228. if (!(pLogBuffer = ExAllocateFromNPagedLookasideList (&PgmStaticConfig.DebugMessagesLookasideList)))
  229. {
  230. DbgPrint ("PgmLog: STATUS_INSUFFICIENT_RESOURCES Logging %sMessage from Function=<%s>\n",
  231. ((Severity == PGM_LOG_ERROR || Severity == PGM_LOG_CRITICAL_ERROR) ? "ERROR " : ""), pszFunctionName);
  232. return (STATUS_INSUFFICIENT_RESOURCES);
  233. }
  234. strcpy(pLogBuffer, "RMCast.");
  235. strcat(pLogBuffer, pszFunctionName);
  236. strcat(pLogBuffer, ": ");
  237. if ((Severity == PGM_LOG_ERROR) ||
  238. (Severity == PGM_LOG_CRITICAL_ERROR))
  239. {
  240. strcat(pLogBuffer, "ERROR -- ");
  241. }
  242. _vsnprintf (pLogBuffer+strlen(pLogBuffer), MAX_DEBUG_MESSAGE_LENGTH-strlen(pLogBuffer), Format, Marker);
  243. pLogBuffer[MAX_DEBUG_MESSAGE_LENGTH] = '\0';
  244. DbgPrint ("%s", pLogBuffer);
  245. ExFreeToNPagedLookasideList (&PgmStaticConfig.DebugMessagesLookasideList, pLogBuffer);
  246. }
  247. return (STATUS_SUCCESS);
  248. }
  249. //----------------------------------------------------------------------------
  250. NTSTATUS
  251. PgmLog(
  252. IN enum eSEVERITY_LEVEL Severity,
  253. IN ULONG Path,
  254. IN PUCHAR pszFunctionName,
  255. IN PUCHAR Format,
  256. ...
  257. )
  258. /*++
  259. Routine Description:
  260. This routine
  261. Arguments:
  262. IN
  263. Return Value:
  264. NTSTATUS - Final status of the set event operation
  265. --*/
  266. {
  267. NTSTATUS status = STATUS_SUCCESS;
  268. va_list Marker;
  269. //
  270. // Based on our Path and the Flags, see if this Event qualifies
  271. // for being logged
  272. //
  273. if (((Path & PgmDebuggerPath) && (Severity <= PgmDebuggerSeverity)) ||
  274. ((Path & PgmLogFilePath) && (Severity <= PgmLogFileSeverity)))
  275. {
  276. va_start (Marker, Format);
  277. status =_PgmLog (Severity, Path, pszFunctionName, Format, Marker);
  278. va_end (Marker);
  279. }
  280. return (status);
  281. }
  282. //----------------------------------------------------------------------------
  283. #endif // OLD_LOGGING