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.

414 lines
11 KiB

  1. /*++
  2. Copyright (c) 1996-1998 Microsoft Corporation
  3. Module Name:
  4. cldskwmi.c
  5. Abstract:
  6. km wmi tracing code.
  7. Will be shared between our drivers.
  8. Authors:
  9. GorN 10-Aug-1999
  10. Environment:
  11. kernel mode only
  12. Notes:
  13. Revision History:
  14. Comments:
  15. This code is a quick hack to enable WMI tracing in cluster drivers.
  16. It should eventually go away.
  17. WmlTinySystemControl will be replaced with WmilibSystemControl from wmilib.sys .
  18. WmlTrace or equivalent will be added to the kernel in addition to IoWMIWriteEvent(&TraceBuffer);
  19. --*/
  20. #include <ntos.h>
  21. #include <ntrtl.h>
  22. #include <nturtl.h>
  23. #include "stdio.h"
  24. #include <wmistr.h>
  25. #include <evntrace.h>
  26. #include "wmlkm.h"
  27. BOOLEAN
  28. WmlpFindGuid(
  29. IN PWML_CONTROL_GUID_REG GuidList,
  30. IN ULONG GuidCount,
  31. IN LPGUID Guid,
  32. OUT PULONG GuidIndex
  33. )
  34. /*++
  35. Routine Description:
  36. This routine will search the list of guids registered and return
  37. the index for the one that was registered.
  38. Arguments:
  39. GuidList is the list of guids to search
  40. GuidCount is the count of guids in the list
  41. Guid is the guid being searched for
  42. *GuidIndex returns the index to the guid
  43. Return Value:
  44. TRUE if guid is found else FALSE
  45. --*/
  46. {
  47. ULONG i;
  48. for (i = 0; i < GuidCount; i++)
  49. {
  50. if (IsEqualGUID(Guid, &GuidList[i].Guid))
  51. {
  52. *GuidIndex = i;
  53. return(TRUE);
  54. }
  55. }
  56. return(FALSE);
  57. }
  58. NTSTATUS
  59. WmlTinySystemControl(
  60. IN OUT PWML_TINY_INFO WmiLibInfo,
  61. IN PDEVICE_OBJECT DeviceObject,
  62. IN PIRP Irp
  63. )
  64. /*++
  65. Routine Description:
  66. Dispatch routine for IRP_MJ_SYSTEM_CONTROL. This routine will process
  67. all wmi requests received, forwarding them if they are not for this
  68. driver or determining if the guid is valid and if so passing it to
  69. the driver specific function for handing wmi requests.
  70. Arguments:
  71. WmiLibInfo has the WMI information control block
  72. DeviceObject - Supplies a pointer to the device object for this request.
  73. Irp - Supplies the Irp making the request.
  74. Return Value:
  75. status
  76. --*/
  77. {
  78. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  79. ULONG bufferSize;
  80. PUCHAR buffer;
  81. NTSTATUS status;
  82. ULONG retSize;
  83. UCHAR minorFunction;
  84. ULONG guidIndex;
  85. ULONG instanceCount;
  86. ULONG instanceIndex;
  87. //
  88. // If the irp is not a WMI irp or it is not targetted at this device
  89. // or this device has not regstered with WMI then just forward it on.
  90. minorFunction = irpStack->MinorFunction;
  91. if ((minorFunction > IRP_MN_EXECUTE_METHOD) ||
  92. (irpStack->Parameters.WMI.ProviderId != (ULONG_PTR)DeviceObject) ||
  93. ((minorFunction != IRP_MN_REGINFO) &&
  94. (WmiLibInfo->GuidCount == 0) || (WmiLibInfo->ControlGuids == NULL) ))
  95. {
  96. //
  97. // IRP is not for us so forward if there is a lower device object
  98. if (WmiLibInfo->LowerDeviceObject != NULL)
  99. {
  100. IoSkipCurrentIrpStackLocation(Irp);
  101. return(IoCallDriver(WmiLibInfo->LowerDeviceObject, Irp));
  102. } else {
  103. status = STATUS_INVALID_DEVICE_REQUEST;
  104. Irp->IoStatus.Status = status;
  105. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  106. return(status);
  107. }
  108. }
  109. buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
  110. bufferSize = irpStack->Parameters.WMI.BufferSize;
  111. if (minorFunction != IRP_MN_REGINFO)
  112. {
  113. //
  114. // For all requests other than query registration info we are passed
  115. // a guid. Determine if the guid is one that is supported by the
  116. // device.
  117. if (WmlpFindGuid(WmiLibInfo->ControlGuids,
  118. WmiLibInfo->GuidCount,
  119. (LPGUID)irpStack->Parameters.WMI.DataPath,
  120. &guidIndex) )
  121. {
  122. status = STATUS_SUCCESS;
  123. } else {
  124. status = STATUS_WMI_GUID_NOT_FOUND;
  125. }
  126. if (!NT_SUCCESS(status))
  127. {
  128. Irp->IoStatus.Status = status;
  129. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  130. return(status);
  131. }
  132. }
  133. switch(minorFunction)
  134. {
  135. case IRP_MN_REGINFO:
  136. {
  137. ULONG guidCount;
  138. PWML_CONTROL_GUID_REG guidList;
  139. PWMIREGINFOW wmiRegInfo;
  140. PWMIREGGUIDW wmiRegGuid;
  141. PDEVICE_OBJECT pdo;
  142. PUNICODE_STRING regPath;
  143. PWCHAR stringPtr;
  144. ULONG registryPathOffset;
  145. ULONG bufferNeeded;
  146. ULONG i;
  147. UNICODE_STRING nullRegistryPath;
  148. regPath = WmiLibInfo->DriverRegPath;
  149. guidList = WmiLibInfo->ControlGuids;
  150. guidCount = WmiLibInfo->GuidCount;
  151. if (regPath == NULL)
  152. {
  153. // No registry path specified. This is a bad thing for
  154. // the device to do, but is not fatal
  155. nullRegistryPath.Buffer = NULL;
  156. nullRegistryPath.Length = 0;
  157. nullRegistryPath.MaximumLength = 0;
  158. regPath = &nullRegistryPath;
  159. }
  160. registryPathOffset = FIELD_OFFSET(WMIREGINFOW, WmiRegGuid) +
  161. guidCount * sizeof(WMIREGGUIDW);
  162. bufferNeeded = registryPathOffset +
  163. regPath->Length + sizeof(USHORT);
  164. if (bufferNeeded <= bufferSize)
  165. {
  166. retSize = bufferNeeded;
  167. RtlZeroMemory(buffer, bufferNeeded);
  168. wmiRegInfo = (PWMIREGINFO)buffer;
  169. wmiRegInfo->BufferSize = bufferNeeded;
  170. // wmiRegInfo->NextWmiRegInfo = 0;
  171. // wmiRegInfo->MofResourceName = 0;
  172. wmiRegInfo->RegistryPath = registryPathOffset;
  173. wmiRegInfo->GuidCount = guidCount;
  174. for (i = 0; i < guidCount; i++)
  175. {
  176. wmiRegGuid = &wmiRegInfo->WmiRegGuid[i];
  177. wmiRegGuid->Guid = guidList[i].Guid;
  178. wmiRegGuid->Flags = WMIREG_FLAG_TRACED_GUID | WMIREG_FLAG_TRACE_CONTROL_GUID;
  179. // wmiRegGuid->InstanceInfo = 0;
  180. // wmiRegGuid->InstanceCount = 0;
  181. }
  182. stringPtr = (PWCHAR)((PUCHAR)buffer + registryPathOffset);
  183. *stringPtr++ = regPath->Length;
  184. RtlCopyMemory(stringPtr,
  185. regPath->Buffer,
  186. regPath->Length);
  187. status = STATUS_SUCCESS;
  188. } else {
  189. status = STATUS_BUFFER_TOO_SMALL;
  190. *((PULONG)buffer) = bufferNeeded;
  191. retSize = sizeof(ULONG);
  192. }
  193. Irp->IoStatus.Status = status;
  194. Irp->IoStatus.Information = retSize;
  195. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  196. return(status);
  197. }
  198. case IRP_MN_ENABLE_EVENTS:
  199. case IRP_MN_DISABLE_EVENTS:
  200. {
  201. PWNODE_HEADER Wnode = irpStack->Parameters.WMI.Buffer;
  202. PWML_CONTROL_GUID_REG Ctx = WmiLibInfo->ControlGuids + guidIndex;
  203. if (irpStack->Parameters.WMI.BufferSize >= sizeof(WNODE_HEADER)) {
  204. status = STATUS_SUCCESS;
  205. if (minorFunction == IRP_MN_DISABLE_EVENTS) {
  206. //DbgPrint("WMI disable\n");
  207. Ctx->EnableLevel = 0;
  208. Ctx->EnableFlags = 0;
  209. Ctx->LoggerHandle = 0;
  210. } else {
  211. Ctx->LoggerHandle = (TRACEHANDLE)( Wnode->HistoricalContext );
  212. Ctx->EnableLevel = WmiGetLoggerEnableLevel(Ctx->LoggerHandle); // UCHAR
  213. Ctx->EnableFlags = WmiGetLoggerEnableFlags(Ctx->LoggerHandle); // ULONG
  214. //DbgPrint("WMI enable: %lx %lx\n",Ctx->EnableLevel,Ctx->EnableFlags);
  215. }
  216. } else {
  217. status = STATUS_INVALID_PARAMETER;
  218. }
  219. break;
  220. }
  221. case IRP_MN_ENABLE_COLLECTION:
  222. case IRP_MN_DISABLE_COLLECTION:
  223. {
  224. status = STATUS_SUCCESS;
  225. break;
  226. }
  227. case IRP_MN_QUERY_ALL_DATA:
  228. case IRP_MN_QUERY_SINGLE_INSTANCE:
  229. case IRP_MN_CHANGE_SINGLE_INSTANCE:
  230. case IRP_MN_CHANGE_SINGLE_ITEM:
  231. case IRP_MN_EXECUTE_METHOD:
  232. {
  233. status = STATUS_INVALID_DEVICE_REQUEST;
  234. break;
  235. }
  236. default:
  237. {
  238. status = STATUS_INVALID_DEVICE_REQUEST;
  239. break;
  240. }
  241. }
  242. Irp->IoStatus.Status = status;
  243. Irp->IoStatus.Information = 0;
  244. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  245. return(status);
  246. }
  247. #define MAX_SCRATCH_LOG 256
  248. typedef struct _TRACE_BUFFER {
  249. union {
  250. EVENT_TRACE_HEADER Trace;
  251. WNODE_HEADER Wnode;
  252. };
  253. union {
  254. MOF_FIELD MofFields[MAX_MOF_FIELDS + 1];
  255. UCHAR ScratchPad[MAX_SCRATCH_LOG];
  256. };
  257. } TRACE_BUFFER, *PTRACE_BUFFER;
  258. //////////////////////////////////////////////////////////////////////
  259. // 0 | Size | ProviderId | 0 |Size.HT.Mk | Typ.Lev.Version|
  260. // 2 | L o g g e r H a n d l e | 2 | T h r e a d I d |
  261. // 4 | T i m e S t a m p | 4 | T i m e S t a m p |
  262. // 6 | G U I D L o w | 6 | GUID Ptr / Guid L o w |
  263. // 8 | G U I D H I g h | 8 | G U I D H i g h |
  264. // 10 | ClientCtx | Flags | 10 |KernelTime | UserTime |
  265. //////////////////////////////////////////////////////////////////////
  266. ULONG
  267. WmlTrace(
  268. IN ULONG Type,
  269. IN LPCGUID TraceGuid,
  270. IN TRACEHANDLE LoggerHandle,
  271. ... // Pairs: Address, Length
  272. )
  273. {
  274. TRACE_BUFFER TraceBuffer;
  275. TraceBuffer.Trace.Version = Type;
  276. TraceBuffer.Wnode.HistoricalContext = LoggerHandle; // [KM]
  277. TraceBuffer.Trace.Guid = *TraceGuid;
  278. TraceBuffer.Wnode.Flags =
  279. WNODE_FLAG_USE_MOF_PTR | // MOF data are dereferenced
  280. WNODE_FLAG_TRACED_GUID; // Trace Event, not a WMI event
  281. {
  282. PMOF_FIELD ptr = TraceBuffer.MofFields;
  283. va_list ap;
  284. va_start(ap, LoggerHandle);
  285. do {
  286. if ( 0 == (ptr->Length = (ULONG)va_arg (ap, size_t)) ) {
  287. break;
  288. }
  289. ptr->DataPtr = (ULONGLONG)va_arg(ap, PVOID);
  290. } while ( ++ptr < &TraceBuffer.MofFields[MAX_MOF_FIELDS] );
  291. va_end(ap);
  292. TraceBuffer.Wnode.BufferSize = (ULONG) ((ULONG_PTR)ptr - (ULONG_PTR)&TraceBuffer);
  293. }
  294. IoWMIWriteEvent(&TraceBuffer); // [KM]
  295. return STATUS_SUCCESS;
  296. }
  297. ULONG
  298. WmlPrintf(
  299. IN ULONG Type,
  300. IN LPCGUID TraceGuid,
  301. IN TRACEHANDLE LoggerHandle,
  302. IN PCHAR FormatString,
  303. ... // printf var args
  304. )
  305. {
  306. TRACE_BUFFER TraceBuffer;
  307. va_list ArgList;
  308. ULONG Length;
  309. TraceBuffer.Trace.Version = Type;
  310. TraceBuffer.Wnode.HistoricalContext = LoggerHandle; // [KM]
  311. TraceBuffer.Trace.Guid = *TraceGuid;
  312. TraceBuffer.Wnode.Flags =
  313. WNODE_FLAG_TRACED_GUID; // Trace Event, not a WMI event
  314. va_start(ArgList, FormatString);
  315. Length = _vsnprintf(TraceBuffer.ScratchPad, MAX_SCRATCH_LOG, FormatString, ArgList);
  316. TraceBuffer.ScratchPad[Length] = 0;
  317. va_end(ArgList);
  318. TraceBuffer.Wnode.BufferSize =
  319. (ULONG) ((ULONG_PTR)(TraceBuffer.ScratchPad + Length) - (ULONG_PTR)&TraceBuffer);
  320. IoWMIWriteEvent(&TraceBuffer); // [KM]
  321. return STATUS_SUCCESS;
  322. }