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.

450 lines
12 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. request.c
  5. Abstract:
  6. Implements WMI requests to different data providers
  7. Author:
  8. 16-Jan-1997 AlanWar
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h> // for ntutrl.h
  13. #include <nturtl.h> // for RTL_CRITICAL_SECTION in winbase.h/wtypes.h
  14. #include "wmiump.h"
  15. #include "evntrace.h"
  16. #include "trcapi.h"
  17. //
  18. // This is the handle to the WMI kernel mode device
  19. HANDLE WmipKMHandle;
  20. //
  21. // This is the one-deep Win32 event queue used to supply events for
  22. // overlapped I/O to the WMI device.
  23. HANDLE WmipWin32Event;
  24. __inline HANDLE WmipAllocEvent(
  25. void
  26. )
  27. {
  28. HANDLE EventHandle;
  29. EventHandle = (HANDLE)InterlockedExchangePointer((PVOID *)(&WmipWin32Event),
  30. NULL);
  31. if (EventHandle == NULL)
  32. {
  33. //
  34. // If event in queue is in use then create a new one
  35. EventHandle = WmipCreateEventA(NULL, FALSE, FALSE, NULL);
  36. }
  37. return(EventHandle);
  38. }
  39. __inline void WmipFreeEvent(
  40. HANDLE EventHandle
  41. )
  42. {
  43. if (InterlockedCompareExchangePointer(&WmipWin32Event,
  44. EventHandle,
  45. NULL) != NULL)
  46. {
  47. //
  48. // If there is already a handle in the event queue then free this
  49. // handle
  50. WmipCloseHandle(EventHandle);
  51. }
  52. }
  53. ULONG WmipSendWmiKMRequest(
  54. HANDLE DeviceHandle,
  55. ULONG Ioctl,
  56. PVOID InBuffer,
  57. ULONG InBufferSize,
  58. PVOID OutBuffer,
  59. ULONG MaxBufferSize,
  60. ULONG *ReturnSize,
  61. LPOVERLAPPED Overlapped
  62. )
  63. /*+++
  64. Routine Description:
  65. This routine does the work of sending WMI requests to the WMI kernel
  66. mode device. Any retry errors returned by the WMI device are handled
  67. in this routine.
  68. Arguments:
  69. Ioctl is the IOCTL code to send to the WMI device
  70. Buffer is the input buffer for the call to the WMI device
  71. InBufferSize is the size of the buffer passed to the device
  72. OutBuffer is the output buffer for the call to the WMI device
  73. MaxBufferSize is the maximum number of bytes that can be written
  74. into the buffer
  75. *ReturnSize on return has the actual number of bytes written in buffer
  76. Overlapped is an option OVERLAPPED struct that is used to make the
  77. call async
  78. Return Value:
  79. ERROR_SUCCESS or an error code
  80. ---*/
  81. {
  82. OVERLAPPED StaticOverlapped;
  83. ULONG Status;
  84. BOOL IoctlSuccess;
  85. WmipEnterPMCritSection();
  86. if (WmipKMHandle == NULL)
  87. {
  88. //
  89. // If device is not open for then open it now. The
  90. // handle is closed in the process detach dll callout (DlllMain)
  91. WmipKMHandle = WmipCreateFileA(WMIDataDeviceName,
  92. GENERIC_READ | GENERIC_WRITE,
  93. 0,
  94. NULL,
  95. OPEN_EXISTING,
  96. FILE_ATTRIBUTE_NORMAL |
  97. FILE_FLAG_OVERLAPPED,
  98. NULL);
  99. if (WmipKMHandle == (HANDLE)-1)
  100. {
  101. WmipKMHandle = NULL;
  102. WmipLeavePMCritSection();
  103. return(WmipGetLastError());
  104. }
  105. }
  106. WmipLeavePMCritSection();
  107. if (Overlapped == NULL)
  108. {
  109. //
  110. // if caller didn't pass an overlapped structure then supply
  111. // our own and make the call synchronous
  112. //
  113. Overlapped = &StaticOverlapped;
  114. Overlapped->hEvent = WmipAllocEvent();
  115. if (Overlapped->hEvent == NULL)
  116. {
  117. return(ERROR_NOT_ENOUGH_MEMORY);
  118. }
  119. }
  120. if (DeviceHandle == NULL)
  121. {
  122. DeviceHandle = WmipKMHandle;
  123. }
  124. do
  125. {
  126. IoctlSuccess = WmipDeviceIoControl(DeviceHandle,
  127. Ioctl,
  128. InBuffer,
  129. InBufferSize,
  130. OutBuffer,
  131. MaxBufferSize,
  132. ReturnSize,
  133. Overlapped);
  134. if (!IoctlSuccess)
  135. {
  136. if (Overlapped == &StaticOverlapped)
  137. {
  138. //
  139. // if the call was successful and we are synchronous then
  140. // block until the call completes
  141. //
  142. if (WmipGetLastError() == ERROR_IO_PENDING)
  143. {
  144. IoctlSuccess = WmipGetOverlappedResult(DeviceHandle,
  145. Overlapped,
  146. ReturnSize,
  147. TRUE);
  148. }
  149. if (! IoctlSuccess)
  150. {
  151. Status = WmipGetLastError();
  152. } else {
  153. Status = ERROR_SUCCESS;
  154. }
  155. } else {
  156. Status = WmipGetLastError();
  157. }
  158. } else {
  159. Status = ERROR_SUCCESS;
  160. }
  161. } while (Status == ERROR_WMI_TRY_AGAIN);
  162. if (Overlapped == &StaticOverlapped)
  163. {
  164. WmipFreeEvent(Overlapped->hEvent);
  165. }
  166. return(Status);
  167. }
  168. ULONG IoctlActionCode[WmiExecuteMethodCall+1] =
  169. {
  170. IOCTL_WMI_QUERY_ALL_DATA,
  171. IOCTL_WMI_QUERY_SINGLE_INSTANCE,
  172. IOCTL_WMI_SET_SINGLE_INSTANCE,
  173. IOCTL_WMI_SET_SINGLE_ITEM,
  174. IOCTL_WMI_ENABLE_EVENT,
  175. IOCTL_WMI_DISABLE_EVENT,
  176. IOCTL_WMI_ENABLE_COLLECTION,
  177. IOCTL_WMI_DISABLE_COLLECTION,
  178. IOCTL_WMI_GET_REGINFO,
  179. IOCTL_WMI_EXECUTE_METHOD
  180. };
  181. ULONG WmipSendWmiRequest(
  182. ULONG ActionCode,
  183. PWNODE_HEADER Wnode,
  184. ULONG WnodeSize,
  185. PVOID OutBuffer,
  186. ULONG MaxWnodeSize,
  187. ULONG *RetSize
  188. )
  189. /*+++
  190. Routine Description:
  191. This routine does the work of sending WMI requests to the appropriate
  192. data provider. Note that this routine is called while the GuidHandle's
  193. critical section is held.
  194. Arguments:
  195. Return Value:
  196. ---*/
  197. {
  198. ULONG Status = ERROR_SUCCESS;
  199. ULONG Ioctl;
  200. ULONG BusyRetries;
  201. //
  202. // Send the query down to kernel mode for execution
  203. //
  204. WmipAssert(ActionCode <= WmiExecuteMethodCall);
  205. Ioctl = IoctlActionCode[ActionCode];
  206. Status = WmipSendWmiKMRequest(NULL,
  207. Ioctl,
  208. Wnode,
  209. WnodeSize,
  210. OutBuffer,
  211. MaxWnodeSize,
  212. RetSize,
  213. NULL);
  214. return(Status);
  215. }
  216. ULONG WmipConvertWADToAnsi(
  217. PWNODE_ALL_DATA Wnode
  218. )
  219. /*+++
  220. Routine Description:
  221. This routine will convert the instance names in a WNODE_ALL_DATA to
  222. ansi. The conversion is done in place since we can assume that ansi
  223. strings are no longer than unicode strings.
  224. Arguments:
  225. Wnode is the WNODE_ALL_DATA whose instance names are to be converted to
  226. ANSI
  227. Return Value:
  228. Returns ERROR_SUCCESS or an error code.
  229. ---*/
  230. {
  231. ULONG i;
  232. ULONG Linkage;
  233. ULONG InstanceCount;
  234. PULONG InstanceNameOffsets;
  235. PWCHAR Ptr;
  236. ULONG Status = ERROR_SUCCESS;
  237. WmipAssert(!(Wnode->WnodeHeader.Flags & WNODE_FLAG_ANSI_INSTANCENAMES));
  238. do
  239. {
  240. Wnode->WnodeHeader.Flags |= WNODE_FLAG_ANSI_INSTANCENAMES;
  241. InstanceCount = Wnode->InstanceCount;
  242. InstanceNameOffsets = (PULONG)(((PUCHAR)Wnode) +
  243. Wnode->OffsetInstanceNameOffsets);
  244. for (i = 0; i < InstanceCount; i++)
  245. {
  246. Ptr = (PWCHAR)(((PUCHAR)Wnode) + InstanceNameOffsets[i]);
  247. try
  248. {
  249. Status = WmipCountedUnicodeToCountedAnsi(Ptr, (PCHAR)Ptr);
  250. } except(EXCEPTION_EXECUTE_HANDLER) {
  251. // Wnode->WnodeHeader.Flags |= WNODE_FLAG_INVALID;
  252. return(ERROR_SUCCESS);
  253. }
  254. if (Status != ERROR_SUCCESS)
  255. {
  256. WmipSetLastError(Status);
  257. goto Done;
  258. }
  259. }
  260. Linkage = Wnode->WnodeHeader.Linkage;
  261. Wnode = (PWNODE_ALL_DATA)(((PUCHAR)Wnode) + Linkage);
  262. } while (Linkage != 0);
  263. Done:
  264. return(Status);
  265. }
  266. /*ULONG WmipQueryPidEntry(
  267. IN GUID Guid,
  268. IN ULONG Pid,
  269. OUT BOOLEAN *PidEntry
  270. )
  271. {
  272. ULONG Status;
  273. ULONG ReturnSize;
  274. ULONG Size = sizeof(QUERYPIDENTRY);
  275. PQUERYPIDENTRY QueryPidEntry = NULL;
  276. WmipInitProcessHeap();
  277. QueryPidEntry = WmipAlloc(Size);
  278. if(!QueryPidEntry)
  279. return STATUS_NO_MEMORY;
  280. QueryPidEntry->Guid = Guid;
  281. QueryPidEntry->Pid = Pid;
  282. QueryPidEntry->PidEntry = FALSE;
  283. Status = WmipSendWmiKMRequest(NULL,
  284. IOCTL_WMI_QUERY_PIDENTRY,
  285. QueryPidEntry,
  286. Size,
  287. QueryPidEntry,
  288. Size,
  289. &ReturnSize,
  290. NULL);
  291. if (Status == ERROR_SUCCESS){
  292. *PidEntry = QueryPidEntry->PidEntry;
  293. }
  294. WmipFree(QueryPidEntry);
  295. return Status;
  296. }*/
  297. ULONG WmipRegisterGuids(
  298. IN LPGUID MasterGuid,
  299. IN ULONG RegistrationCookie,
  300. IN PWMIREGINFOW RegInfo,
  301. IN ULONG GuidCount,
  302. OUT PTRACEGUIDMAP *GuidMapHandle,
  303. OUT ULONG64 *LoggerContext,
  304. OUT HANDLE *RegistrationHandle
  305. )
  306. {
  307. ULONG Status;
  308. ULONG SizeNeeded, InSizeNeeded, OutSizeNeeded;
  309. WCHAR GuidObjectName[WmiGuidObjectNameLength+1];
  310. OBJECT_ATTRIBUTES ObjectAttributes;
  311. UNICODE_STRING GuidString;
  312. PWMIREGREQUEST WmiRegRequest;
  313. PTRACEGUIDMAP TraceGuidMap;
  314. PUCHAR Buffer;
  315. PUCHAR RegInfoBuffer;
  316. PWMIREGRESULTS WmiRegResults;
  317. ULONG ReturnSize;
  318. ULONG TraceGuidMapSize;
  319. //
  320. // Allocate a buffer large enough for all in and out parameters
  321. //
  322. TraceGuidMapSize = GuidCount * sizeof(TRACEGUIDMAP);
  323. InSizeNeeded = sizeof(WMIREGREQUEST) + RegInfo->BufferSize;
  324. OutSizeNeeded = TraceGuidMapSize + sizeof(WMIREGRESULTS);
  325. if (InSizeNeeded > OutSizeNeeded)
  326. {
  327. SizeNeeded = InSizeNeeded;
  328. } else {
  329. SizeNeeded = OutSizeNeeded;
  330. }
  331. Buffer = WmipAlloc(SizeNeeded);
  332. if (Buffer != NULL)
  333. {
  334. //
  335. // Build the object attributes
  336. //
  337. WmiRegRequest = (PWMIREGREQUEST)Buffer;
  338. WmiRegRequest->ObjectAttributes = &ObjectAttributes;
  339. WmiRegRequest->GuidCount = GuidCount;
  340. RegInfoBuffer = Buffer + sizeof(WMIREGREQUEST);
  341. Status = WmipBuildGuidObjectAttributes(MasterGuid,
  342. &ObjectAttributes,
  343. &GuidString,
  344. GuidObjectName);
  345. if (Status == ERROR_SUCCESS)
  346. {
  347. WmiRegRequest->Cookie = RegistrationCookie;
  348. memcpy(RegInfoBuffer, RegInfo, RegInfo->BufferSize);
  349. Status = WmipSendWmiKMRequest(NULL,
  350. IOCTL_WMI_REGISTER_GUIDS,
  351. Buffer,
  352. InSizeNeeded,
  353. Buffer,
  354. OutSizeNeeded,
  355. &ReturnSize,
  356. NULL);
  357. if (Status == ERROR_SUCCESS)
  358. {
  359. //
  360. // Successful call, return the out parameters
  361. //
  362. WmiRegResults = (PWMIREGRESULTS)((PUCHAR)Buffer + TraceGuidMapSize);
  363. *RegistrationHandle = WmiRegResults->RequestHandle.Handle;
  364. *LoggerContext = WmiRegResults->LoggerContext;
  365. *GuidMapHandle = (PTRACEGUIDMAP)Buffer;
  366. }
  367. //
  368. // Note that we do not free Buffer in this call. This will be
  369. // freed by the caller since it is returned in *GuidMapHandle
  370. //
  371. }
  372. } else {
  373. Status = ERROR_NOT_ENOUGH_MEMORY;
  374. }
  375. return(Status);
  376. }