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.

411 lines
9.9 KiB

  1. /*++
  2. Copyright (c) 2001-2002 Microsoft Corporation
  3. Module Name:
  4. uletw.c
  5. Abstract:
  6. This module contains code for WDM WMI Irps and wrapper functions
  7. to send trace events to ETW.
  8. Author:
  9. Melur Raghuraman (mraghu) 14-Feb-2001
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include "uletwp.h"
  14. //
  15. // Private globals.
  16. //
  17. LONG g_UlEtwTraceEnable = 0;
  18. TRACEHANDLE g_UlEtwLoggerHandle = 0;
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text( PAGE, UlEtwInitLog )
  21. #pragma alloc_text( PAGE, UlEtwUnRegisterLog )
  22. #pragma alloc_text( PAGE, UlEtwRegisterGuids )
  23. #pragma alloc_text( PAGE, UlEtwEnableLog )
  24. #pragma alloc_text( PAGE, UlEtwDisableLog )
  25. #pragma alloc_text( PAGE, UlEtwDispatch )
  26. #endif // ALLOC_PRAGMA
  27. #if 0
  28. NOT PAGEABLE -- UlEtwTraceEvent
  29. NOT PAGEABLE -- UlEtwGetTraceEnableFlags
  30. #endif
  31. //
  32. // Public functions.
  33. //
  34. //
  35. // Private functions.
  36. //
  37. //
  38. // Public functions.
  39. //
  40. /***************************************************************************++
  41. Routine Description:
  42. This is the routine in which we call IoWMIRegistrationControl to
  43. register for ETW logging.
  44. Arguments:
  45. pDeviceObject - Supplies a pointer to the target device object.
  46. Return Value:
  47. NTSTATUS - Completion status.
  48. --***************************************************************************/
  49. NTSTATUS
  50. UlEtwInitLog(
  51. IN PDEVICE_OBJECT pDeviceObject
  52. )
  53. {
  54. NTSTATUS status;
  55. //
  56. // Register wtih ETW
  57. //
  58. status = IoWMIRegistrationControl(pDeviceObject, WMIREG_ACTION_REGISTER);
  59. if (!NT_SUCCESS(status))
  60. {
  61. UlTrace(ETW, (
  62. "UlEtwInitLog: IoWMIRegistrationControl failed with %x\n",
  63. status
  64. ));
  65. }
  66. return status;
  67. }
  68. /***************************************************************************++
  69. Routine Description:
  70. This is the routine in which we call IoWMIRegistrationControl to
  71. Unregister from ETW logging.
  72. Arguments:
  73. pDeviceObject - Supplies a pointer to the target device object.
  74. Return Value:
  75. NTSTATUS - Completion status.
  76. --***************************************************************************/
  77. NTSTATUS
  78. UlEtwUnRegisterLog(
  79. IN PDEVICE_OBJECT pDeviceObject
  80. )
  81. {
  82. NTSTATUS status;
  83. //
  84. // Register with ETW.
  85. //
  86. status = IoWMIRegistrationControl(pDeviceObject,
  87. WMIREG_ACTION_DEREGISTER);
  88. if (!NT_SUCCESS(status))
  89. {
  90. UlTrace(ETW, (
  91. "UlEtwUnRegisterLog: Failed to unregister for ETW support\n"
  92. ));
  93. }
  94. return status;
  95. }
  96. /***************************************************************************++
  97. Routine Description:
  98. This function handles ETW GUID registration.
  99. Arguments:
  100. EtwRegInfo
  101. etwRegInfoSize,
  102. pReturnSize
  103. Return Value:
  104. NTSTATUS - Completion status.
  105. --***************************************************************************/
  106. NTSTATUS
  107. UlEtwRegisterGuids(
  108. IN PWMIREGINFO EtwRegInfo,
  109. IN ULONG etwRegInfoSize,
  110. IN PULONG pReturnSize
  111. )
  112. {
  113. //
  114. // Register a Control Guid as a Trace Guid.
  115. //
  116. ULONG SizeNeeded;
  117. PWMIREGGUIDW EtwRegGuidPtr;
  118. ULONG GuidCount;
  119. ULONG RegistryPathSize;
  120. ULONG MofResourceSize;
  121. PUCHAR ptmp;
  122. #if DBG
  123. GUID UlTestGuid = {0xdd5ef90a, 0x6398, 0x47a4, 0xad, 0x34, 0x4d, 0xce, 0xcd, 0xef, 0x79, 0x5f};
  124. ASSERT(IsEqualGUID(&UlControlGuid, &UlTestGuid));
  125. #endif
  126. *pReturnSize = 0;
  127. GuidCount = 1;
  128. //
  129. // Allocate WMIREGINFO for controlGuid + GuidCount.
  130. //
  131. RegistryPathSize = sizeof(REGISTRY_UL_INFORMATION) - sizeof(WCHAR) + sizeof(USHORT);
  132. MofResourceSize = sizeof(UL_TRACE_MOF_FILE) - sizeof(WCHAR) + sizeof(USHORT);
  133. SizeNeeded = sizeof(WMIREGINFOW) + GuidCount * sizeof(WMIREGGUIDW) +
  134. RegistryPathSize +
  135. MofResourceSize;
  136. if (SizeNeeded > etwRegInfoSize) {
  137. *((PULONG)EtwRegInfo) = SizeNeeded;
  138. *pReturnSize = sizeof(ULONG);
  139. return STATUS_BUFFER_TOO_SMALL;
  140. }
  141. RtlZeroMemory(EtwRegInfo, SizeNeeded);
  142. EtwRegInfo->BufferSize = SizeNeeded;
  143. EtwRegInfo->GuidCount = GuidCount;
  144. EtwRegInfo->RegistryPath = sizeof(WMIREGINFOW) + GuidCount * sizeof(WMIREGGUIDW);
  145. EtwRegInfo->MofResourceName = EtwRegInfo->RegistryPath + RegistryPathSize;
  146. EtwRegGuidPtr = &EtwRegInfo->WmiRegGuid[0];
  147. EtwRegGuidPtr->Guid = UlControlGuid;
  148. EtwRegGuidPtr->Flags |= WMIREG_FLAG_TRACED_GUID;
  149. EtwRegGuidPtr->Flags |= WMIREG_FLAG_TRACE_CONTROL_GUID;
  150. EtwRegGuidPtr->InstanceCount = 0;
  151. EtwRegGuidPtr->InstanceInfo = 0;
  152. ptmp = (PUCHAR)&EtwRegInfo->WmiRegGuid[1];
  153. *((PUSHORT)ptmp) = sizeof(REGISTRY_UL_INFORMATION) - sizeof(WCHAR);
  154. ptmp += sizeof(USHORT);
  155. RtlCopyMemory(ptmp,
  156. REGISTRY_UL_INFORMATION,
  157. sizeof(REGISTRY_UL_INFORMATION) - sizeof(WCHAR)
  158. );
  159. ptmp = (PUCHAR)EtwRegInfo + EtwRegInfo->MofResourceName;
  160. *((PUSHORT)ptmp) = sizeof(UL_TRACE_MOF_FILE) - sizeof(WCHAR);
  161. ptmp += sizeof(USHORT);
  162. RtlCopyMemory(ptmp,
  163. UL_TRACE_MOF_FILE,
  164. sizeof(UL_TRACE_MOF_FILE) - sizeof(WCHAR)
  165. );
  166. *pReturnSize = SizeNeeded;
  167. return(STATUS_SUCCESS);
  168. }
  169. NTSTATUS
  170. UlEtwEnableLog(
  171. IN PVOID Buffer,
  172. IN ULONG BufferSize
  173. )
  174. {
  175. PWNODE_HEADER Wnode=NULL;
  176. ASSERT(Buffer);
  177. ASSERT(BufferSize >= sizeof(WNODE_HEADER));
  178. Wnode = (PWNODE_HEADER)Buffer;
  179. if (BufferSize >= sizeof(WNODE_HEADER)) {
  180. ULONG Level;
  181. g_UlEtwLoggerHandle = Wnode->HistoricalContext;
  182. Level = (ULONG) WmiGetLoggerEnableLevel ( g_UlEtwLoggerHandle );
  183. if (Level > ULMAX_TRACE_LEVEL) {
  184. Level = ULMAX_TRACE_LEVEL;
  185. }
  186. g_UlEtwTraceEnable = (1 << Level);
  187. }
  188. return STATUS_SUCCESS;
  189. }
  190. NTSTATUS
  191. UlEtwDisableLog(
  192. )
  193. {
  194. g_UlEtwTraceEnable = 0;
  195. g_UlEtwLoggerHandle = 0;
  196. return(STATUS_SUCCESS);
  197. }
  198. NTSTATUS
  199. UlEtwDispatch(
  200. IN PDEVICE_OBJECT pDO,
  201. IN PIRP Irp
  202. )
  203. {
  204. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  205. ULONG BufferSize = irpSp->Parameters.WMI.BufferSize;
  206. PVOID Buffer = irpSp->Parameters.WMI.Buffer;
  207. ULONG ReturnSize = 0;
  208. NTSTATUS status = STATUS_SUCCESS;
  209. UNREFERENCED_PARAMETER(pDO);
  210. switch (irpSp->MinorFunction) {
  211. case IRP_MN_REGINFO:
  212. {
  213. status = UlEtwRegisterGuids( (PWMIREGINFO) Buffer,
  214. BufferSize,
  215. &ReturnSize);
  216. Irp->IoStatus.Information = ReturnSize;
  217. Irp->IoStatus.Status = status;
  218. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  219. break;
  220. }
  221. case IRP_MN_ENABLE_EVENTS:
  222. {
  223. status = UlEtwEnableLog(
  224. Buffer,
  225. BufferSize
  226. );
  227. Irp->IoStatus.Status = status;
  228. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  229. break;
  230. }
  231. case IRP_MN_DISABLE_EVENTS:
  232. {
  233. status = UlEtwDisableLog();
  234. Irp->IoStatus.Status = status;
  235. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  236. break;
  237. }
  238. default:
  239. {
  240. status = STATUS_INVALID_DEVICE_REQUEST;
  241. Irp->IoStatus.Status = status;
  242. Irp->IoStatus.Information = 0;
  243. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  244. break;
  245. }
  246. }
  247. return status;
  248. }
  249. /***************************************************************************++
  250. Routine Description:
  251. This is the routine that is called to log a trace event with ETW
  252. logger.
  253. Arguments:
  254. pGuid - Supplies a pointer to the Guid of the event
  255. EventType - Type of the event being logged.
  256. ... - List of arguments to be logged with this event
  257. These are in pairs of
  258. PVOID - ptr to argument
  259. ULONG - size of argument
  260. and terminated by a pointer to NULL, length of zero pair
  261. Return Value:
  262. NTSTATUS - Completion status.
  263. --***************************************************************************/
  264. NTSTATUS
  265. UlEtwTraceEvent(
  266. IN LPCGUID pGuid,
  267. IN ULONG EventType,
  268. ...
  269. )
  270. {
  271. NTSTATUS status;
  272. UL_ETW_TRACE_EVENT UlEvent;
  273. ULONG i;
  274. va_list ArgList;
  275. PVOID source;
  276. SIZE_T len;
  277. RtlZeroMemory(& UlEvent, sizeof(EVENT_TRACE_HEADER));
  278. va_start(ArgList, EventType);
  279. for (i = 0; i < MAX_MOF_FIELDS; i ++) {
  280. source = va_arg(ArgList, PVOID);
  281. if (source == NULL)
  282. break;
  283. len = va_arg(ArgList, SIZE_T);
  284. if (len == 0)
  285. break;
  286. UlEvent.MofField[i].DataPtr = (ULONGLONG) source;
  287. UlEvent.MofField[i].Length = (ULONG) len;
  288. }
  289. va_end(ArgList);
  290. UlEvent.Header.Flags = WNODE_FLAG_TRACED_GUID |
  291. WNODE_FLAG_USE_MOF_PTR |
  292. WNODE_FLAG_USE_GUID_PTR;
  293. UlEvent.Header.Size = (USHORT) (sizeof(EVENT_TRACE_HEADER) + (i * sizeof(MOF_FIELD)));
  294. UlEvent.Header.Class.Type = (UCHAR) EventType;
  295. UlEvent.Header.GuidPtr = (ULONGLONG)pGuid;
  296. ((PWNODE_HEADER)&UlEvent)->HistoricalContext = g_UlEtwLoggerHandle;
  297. status = IoWMIWriteEvent((PVOID)&UlEvent);
  298. #if DBG
  299. if (!NT_SUCCESS(status) ) {
  300. UlTrace(ETW, ("UL: TraceEvent ErrorCode %x EventType %x\n",
  301. status, EventType));
  302. }
  303. #endif // DBG
  304. return status;
  305. }
  306. ULONG
  307. UlEtwGetTraceEnableFlags(
  308. VOID
  309. )
  310. {
  311. return WmiGetLoggerEnableFlags ( g_UlEtwLoggerHandle );
  312. }