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.

343 lines
9.4 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. request.h
  5. Abstract:
  6. This file contains structures and functions definitions used in Ntdll.dll
  7. and advapi32.dll.
  8. --*/
  9. HANDLE EtwpKMHandle;
  10. extern
  11. HANDLE EtwpWin32Event;
  12. __inline HANDLE EtwpAllocEvent(
  13. void
  14. )
  15. {
  16. HANDLE EventHandle;
  17. EventHandle = (HANDLE)InterlockedExchangePointer((PVOID *)(&EtwpWin32Event),
  18. NULL);
  19. if (EventHandle == NULL)
  20. {
  21. //
  22. // If event in queue is in use then create a new one
  23. #if defined (_NTDLLBUILD_)
  24. EventHandle = EtwpCreateEventW(NULL, FALSE, FALSE, NULL);
  25. #else
  26. EventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
  27. #endif
  28. }
  29. return(EventHandle);
  30. }
  31. __inline void EtwpFreeEvent(
  32. HANDLE EventHandle
  33. )
  34. {
  35. if (InterlockedCompareExchangePointer(&EtwpWin32Event,
  36. EventHandle,
  37. NULL) != NULL)
  38. {
  39. //
  40. // If there is already a handle in the event queue then free this
  41. // handle
  42. #if defined (_NTDLLBUILD_)
  43. EtwpCloseHandle(EventHandle);
  44. #else
  45. CloseHandle(EventHandle);
  46. #endif
  47. }
  48. }
  49. ULONG IoctlActionCode[WmiExecuteMethodCall+1] =
  50. {
  51. IOCTL_WMI_QUERY_ALL_DATA,
  52. IOCTL_WMI_QUERY_SINGLE_INSTANCE,
  53. IOCTL_WMI_SET_SINGLE_INSTANCE,
  54. IOCTL_WMI_SET_SINGLE_ITEM,
  55. IOCTL_WMI_ENABLE_EVENT,
  56. IOCTL_WMI_DISABLE_EVENT,
  57. IOCTL_WMI_ENABLE_COLLECTION,
  58. IOCTL_WMI_DISABLE_COLLECTION,
  59. IOCTL_WMI_GET_REGINFO,
  60. IOCTL_WMI_EXECUTE_METHOD
  61. };
  62. ULONG EtwpSendWmiKMRequest(
  63. HANDLE DeviceHandle,
  64. ULONG Ioctl,
  65. PVOID InBuffer,
  66. ULONG InBufferSize,
  67. PVOID OutBuffer,
  68. ULONG MaxBufferSize,
  69. ULONG *ReturnSize,
  70. LPOVERLAPPED Overlapped
  71. )
  72. /*+++
  73. Routine Description:
  74. This routine does the work of sending WMI requests to the WMI kernel
  75. mode device. Any retry errors returned by the WMI device are handled
  76. in this routine.
  77. Arguments:
  78. Ioctl is the IOCTL code to send to the WMI device
  79. Buffer is the input buffer for the call to the WMI device
  80. InBufferSize is the size of the buffer passed to the device
  81. OutBuffer is the output buffer for the call to the WMI device
  82. MaxBufferSize is the maximum number of bytes that can be written
  83. into the buffer
  84. *ReturnSize on return has the actual number of bytes written in buffer
  85. Overlapped is an option OVERLAPPED struct that is used to make the
  86. call async
  87. Return Value:
  88. ERROR_SUCCESS or an error code
  89. ---*/
  90. {
  91. OVERLAPPED StaticOverlapped;
  92. ULONG Status;
  93. BOOL IoctlSuccess;
  94. EtwpEnterPMCritSection();
  95. #if defined (_NTDLLBUILD_)
  96. if (EtwpKMHandle == NULL)
  97. {
  98. //
  99. // If device is not open for then open it now. The
  100. // handle is closed in the process detach dll callout (DlllMain)
  101. EtwpKMHandle = EtwpCreateFileW(WMIDataDeviceName_W,
  102. GENERIC_READ | GENERIC_WRITE,
  103. 0,
  104. NULL,
  105. OPEN_EXISTING,
  106. FILE_ATTRIBUTE_NORMAL |
  107. FILE_FLAG_OVERLAPPED,
  108. NULL);
  109. if (EtwpKMHandle == INVALID_HANDLE_VALUE)
  110. {
  111. EtwpKMHandle = NULL;
  112. EtwpLeavePMCritSection();
  113. return(EtwpGetLastError());
  114. }
  115. }
  116. EtwpLeavePMCritSection();
  117. if (Overlapped == NULL)
  118. {
  119. //
  120. // if caller didn't pass an overlapped structure then supply
  121. // our own and make the call synchronous
  122. //
  123. Overlapped = &StaticOverlapped;
  124. Overlapped->hEvent = EtwpAllocEvent();
  125. if (Overlapped->hEvent == NULL)
  126. {
  127. return(ERROR_NOT_ENOUGH_MEMORY);
  128. }
  129. }
  130. if (DeviceHandle == NULL)
  131. {
  132. DeviceHandle = EtwpKMHandle;
  133. }
  134. do
  135. {
  136. IoctlSuccess = EtwpDeviceIoControl(DeviceHandle,
  137. Ioctl,
  138. InBuffer,
  139. InBufferSize,
  140. OutBuffer,
  141. MaxBufferSize,
  142. ReturnSize,
  143. Overlapped);
  144. if (!IoctlSuccess)
  145. {
  146. if (Overlapped == &StaticOverlapped)
  147. {
  148. //
  149. // if the call was successful and we are synchronous then
  150. // block until the call completes
  151. //
  152. if (EtwpGetLastError() == ERROR_IO_PENDING)
  153. {
  154. IoctlSuccess = EtwpGetOverlappedResult(DeviceHandle,
  155. Overlapped,
  156. ReturnSize,
  157. TRUE);
  158. }
  159. if (! IoctlSuccess)
  160. {
  161. Status = EtwpGetLastError();
  162. } else {
  163. Status = ERROR_SUCCESS;
  164. }
  165. } else {
  166. Status = EtwpGetLastError();
  167. }
  168. } else {
  169. Status = ERROR_SUCCESS;
  170. }
  171. } while (Status == ERROR_WMI_TRY_AGAIN);
  172. if (Overlapped == &StaticOverlapped)
  173. {
  174. EtwpFreeEvent(Overlapped->hEvent);
  175. }
  176. #else // _NTDLLBUILD_
  177. if (EtwpKMHandle == NULL)
  178. {
  179. //
  180. // If device is not open for then open it now. The
  181. // handle is closed in the process detach dll callout (DlllMain)
  182. EtwpKMHandle = CreateFile(WMIDataDeviceName,
  183. GENERIC_READ | GENERIC_WRITE,
  184. 0,
  185. NULL,
  186. OPEN_EXISTING,
  187. FILE_ATTRIBUTE_NORMAL |
  188. FILE_FLAG_OVERLAPPED,
  189. NULL);
  190. if (EtwpKMHandle == INVALID_HANDLE_VALUE)
  191. {
  192. EtwpKMHandle = NULL;
  193. EtwpLeavePMCritSection();
  194. return(GetLastError());
  195. }
  196. }
  197. EtwpLeavePMCritSection();
  198. if (Overlapped == NULL)
  199. {
  200. //
  201. // if caller didn't pass an overlapped structure then supply
  202. // our own and make the call synchronous
  203. //
  204. Overlapped = &StaticOverlapped;
  205. Overlapped->hEvent = EtwpAllocEvent();
  206. if (Overlapped->hEvent == NULL)
  207. {
  208. return(ERROR_NOT_ENOUGH_MEMORY);
  209. }
  210. }
  211. if (DeviceHandle == NULL)
  212. {
  213. DeviceHandle = EtwpKMHandle;
  214. }
  215. do
  216. {
  217. IoctlSuccess = DeviceIoControl(DeviceHandle,
  218. Ioctl,
  219. InBuffer,
  220. InBufferSize,
  221. OutBuffer,
  222. MaxBufferSize,
  223. ReturnSize,
  224. Overlapped);
  225. if (!IoctlSuccess)
  226. {
  227. if (Overlapped == &StaticOverlapped)
  228. {
  229. //
  230. // if the call was successful and we are synchronous then
  231. // block until the call completes
  232. //
  233. if (GetLastError() == ERROR_IO_PENDING)
  234. {
  235. IoctlSuccess = GetOverlappedResult(DeviceHandle,
  236. Overlapped,
  237. ReturnSize,
  238. TRUE);
  239. }
  240. if (! IoctlSuccess)
  241. {
  242. Status = GetLastError();
  243. } else {
  244. Status = ERROR_SUCCESS;
  245. }
  246. } else {
  247. Status = GetLastError();
  248. }
  249. } else {
  250. Status = ERROR_SUCCESS;
  251. }
  252. } while (Status == ERROR_WMI_TRY_AGAIN);
  253. if (Overlapped == &StaticOverlapped)
  254. {
  255. EtwpFreeEvent(Overlapped->hEvent);
  256. }
  257. #endif
  258. return(Status);
  259. }
  260. ULONG EtwpSendWmiRequest(
  261. ULONG ActionCode,
  262. PWNODE_HEADER Wnode,
  263. ULONG WnodeSize,
  264. PVOID OutBuffer,
  265. ULONG MaxWnodeSize,
  266. ULONG *RetSize
  267. )
  268. /*+++
  269. Routine Description:
  270. This routine does the work of sending WMI requests to the appropriate
  271. data provider. Note that this routine is called while the GuidHandle's
  272. critical section is held.
  273. Arguments:
  274. Return Value:
  275. ---*/
  276. {
  277. ULONG Status = ERROR_SUCCESS;
  278. ULONG Ioctl;
  279. ULONG BusyRetries;
  280. //
  281. // Send the query down to kernel mode for execution
  282. //
  283. EtwpAssert(ActionCode <= WmiExecuteMethodCall);
  284. Ioctl = IoctlActionCode[ActionCode];
  285. Status = EtwpSendWmiKMRequest(NULL,
  286. Ioctl,
  287. Wnode,
  288. WnodeSize,
  289. OutBuffer,
  290. MaxWnodeSize,
  291. RetSize,
  292. NULL);
  293. return(Status);
  294. }