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.

315 lines
11 KiB

  1. /*****************************************************************************
  2. * (C) COPYRIGHT MICROSOFT CORPORATION, 2002
  3. *
  4. * AUTHOR: ByronC
  5. *
  6. * DATE: 3/25/2002
  7. *
  8. * @doc INTERNAL
  9. *
  10. * @module AsyncRPCEventClient.cpp - Declaration for <c AsyncRPCEventClient> |
  11. *
  12. * This file contains the implmentation for the <c AsyncRPCEventClient> class.
  13. *
  14. *****************************************************************************/
  15. #include "precomp.h"
  16. /*****************************************************************************
  17. * @doc INTERNAL
  18. *
  19. * @mfunc | AsyncRPCEventClient | AsyncRPCEventClient |
  20. *
  21. * This constructor simply calls the base class <c WiaEventClient> constructor.
  22. *
  23. *****************************************************************************/
  24. AsyncRPCEventClient::AsyncRPCEventClient(
  25. STI_CLIENT_CONTEXT SyncClientContext) :
  26. WiaEventClient(SyncClientContext)
  27. {
  28. DBG_FN(AsyncRPCEventClient);
  29. m_pAsyncState = NULL;
  30. m_pAsyncEventData = NULL;
  31. }
  32. /*****************************************************************************
  33. * @doc INTERNAL
  34. *
  35. * @mfunc | AsyncRPCEventClient | ~AsyncRPCEventClient |
  36. *
  37. * This destructor aborts any outstanding AsyncRPC calls.
  38. * Remember: The base classes's destructor will also be called.
  39. *
  40. *****************************************************************************/
  41. AsyncRPCEventClient::~AsyncRPCEventClient()
  42. {
  43. DBG_FN(~AsyncRPCEventClient);
  44. //
  45. // Abort any outstanding Async RPC calls
  46. //
  47. if (m_pAsyncState)
  48. {
  49. RPC_STATUS rpcStatus = RpcAsyncAbortCall(m_pAsyncState, RPC_S_CALL_CANCELLED);
  50. m_pAsyncState = NULL;
  51. }
  52. }
  53. /*****************************************************************************
  54. * @doc INTERNAL
  55. *
  56. * @mfunc HRESULT | AsyncRPCEventClient | setAsyncState |
  57. *
  58. * Saves the async rpc params for this client
  59. *
  60. * @parm RPC_ASYNC_STATE | pAsyncState |
  61. * Pointer to the async rpc state structure used to keep track of a
  62. * specific Async call.
  63. * @parm WIA_ASYNC_EVENT_NOTIFY_DATA | pAsyncEventData |
  64. * Pointer to the out parameter used to store event notification data.
  65. *
  66. *****************************************************************************/
  67. HRESULT AsyncRPCEventClient::saveAsyncParams(
  68. RPC_ASYNC_STATE *pAsyncState,
  69. WIA_ASYNC_EVENT_NOTIFY_DATA *pAsyncEventData)
  70. {
  71. HRESULT hr = S_OK;
  72. if (pAsyncState)
  73. {
  74. TAKE_CRIT_SECT t(m_csClientSync);
  75. //
  76. // We put an exception handler around our code to ensure that the
  77. // crtitical section is exited properly.
  78. //
  79. _try
  80. {
  81. //
  82. // Abort any outstanding Async RPC calls
  83. //
  84. if (m_pAsyncState)
  85. {
  86. RPC_STATUS rpcStatus = RpcAsyncAbortCall(m_pAsyncState, RPC_S_CALL_CANCELLED);
  87. m_pAsyncState = NULL;
  88. m_pAsyncEventData = NULL;
  89. }
  90. m_pAsyncState = pAsyncState;
  91. m_pAsyncEventData = pAsyncEventData;
  92. //
  93. // Now that we have an outstanding AsyncRPC call, send the next event
  94. // notification.
  95. // The return value for that call should not affect the return value for
  96. // here, so we use a new variable: hres.
  97. //
  98. HRESULT hres = SendNextEventNotification();
  99. }
  100. _except(EXCEPTION_EXECUTE_HANDLER)
  101. {
  102. DBG_ERR(("We caught exception 0x%08X trying to update client's async state", GetExceptionCode()));
  103. hr = E_UNEXPECTED;
  104. // TBD: Rethrow the exception?
  105. }
  106. }
  107. else
  108. {
  109. hr = E_POINTER;
  110. }
  111. return hr;
  112. }
  113. /*****************************************************************************
  114. * @doc INTERNAL
  115. *
  116. * @mfunc HRESULT | AsyncRPCEventClient | AddPendingEventNotification |
  117. *
  118. * This method call's the base class <mf WiaEventClient::AddPendingEventNotification>
  119. * first.
  120. *
  121. * Then, if we have an outstanding Async RPC call, we complete it to signify
  122. * the event notification.
  123. *
  124. * @rvalue S_OK |
  125. * The method succeeded.
  126. * @rvalue E_XXXXXXX |
  127. * The method failed. It is not given whether the adding of the
  128. * event failed, or the actual notification
  129. *****************************************************************************/
  130. HRESULT AsyncRPCEventClient::AddPendingEventNotification(
  131. WiaEventInfo *pWiaEventInfo)
  132. {
  133. HRESULT hr = S_OK;
  134. hr = WiaEventClient::AddPendingEventNotification(pWiaEventInfo);
  135. if (SUCCEEDED(hr))
  136. {
  137. //
  138. // Send this event notification if possible.
  139. hr = SendNextEventNotification();
  140. }
  141. else
  142. {
  143. DBG_ERR(("Runtime event client Error: Failed to add pending notification to AsyncRPCWiaEventClient"));
  144. }
  145. return hr;
  146. }
  147. /*****************************************************************************
  148. * @doc INTERNAL
  149. *
  150. * @mfunc BOOL | AsyncRPCEventClient | IsRegisteredForEvent |
  151. *
  152. * Checks whether the client has at least one event registration that matches
  153. * this event.
  154. *
  155. * This method first checks whether we have an outstanding AsyncRPC call - if
  156. * we do, it checks whether the client has died. If it has, it returns false.
  157. * Otherwise, it calls the base class method <mf WiaEventClient::IsRegisteredForEvent>.
  158. *
  159. * @parm WiaEventInfo* | pWiaEventInfo |
  160. * Indicates WIA Device event
  161. *
  162. * @rvalue TRUE |
  163. * The client is registered to receive this event.
  164. * @rvalue FALSE |
  165. * The client is not registered.
  166. *****************************************************************************/
  167. BOOL AsyncRPCEventClient::IsRegisteredForEvent(
  168. WiaEventInfo *pWiaEventInfo)
  169. {
  170. BOOL bRet = FALSE;
  171. RPC_STATUS rpcStatus = RPC_S_OK;
  172. TAKE_CRIT_SECT t(m_csClientSync);
  173. //
  174. // We put an exception handler around our code to ensure that the
  175. // crtitical section is exited properly.
  176. //
  177. _try
  178. {
  179. //
  180. // Check whether we have an outstanding AsyncRPC call.
  181. // If we do, check the status. Is the status is abnormal,
  182. // abort the call (a normal status is RPC_S_CALL_IN_PROGRESS indicating that
  183. // the call is still in progress).
  184. //
  185. if (m_pAsyncState)
  186. {
  187. rpcStatus = RpcServerTestCancel(RpcAsyncGetCallHandle (m_pAsyncState));
  188. if ((rpcStatus == RPC_S_CALL_IN_PROGRESS) || (rpcStatus == RPC_S_OK))
  189. {
  190. rpcStatus = RPC_S_OK;
  191. }
  192. else
  193. {
  194. rpcStatus = RpcAsyncAbortCall(m_pAsyncState, RPC_S_CALL_CANCELLED);
  195. m_pAsyncState = NULL;
  196. MarkForRemoval();
  197. }
  198. }
  199. if (rpcStatus == RPC_S_OK)
  200. {
  201. bRet = WiaEventClient::IsRegisteredForEvent(pWiaEventInfo);
  202. }
  203. }
  204. _except(EXCEPTION_EXECUTE_HANDLER)
  205. {
  206. DBG_ERR(("Runtime event client error: We caught exception 0x%08X trying to check client's registration", GetExceptionCode()));
  207. // TBD: Rethrow the exception?
  208. }
  209. return bRet;
  210. }
  211. /*****************************************************************************
  212. * @doc INTERNAL
  213. *
  214. * @mfunc HRESULT | AsyncRPCEventClient | SendNextEventNotification |
  215. *
  216. * The operation of this method is as follows:
  217. * <nl>1. Checks whether client can receive notifications.
  218. * A client can receive notification if we have a valid Async RPC state.
  219. * <nl>2. If it can, we check whether there are any pending events in the queue.
  220. * <nl>3. If the client can receive notifications, and there are events pending,
  221. * we pop the next pending event and send it.
  222. *
  223. * If any condition is not met, it is not an error - we report back S_OK.
  224. *
  225. * @rvalue S_OK |
  226. * There were no errors.
  227. * @rvalue E_XXXXXXXX |
  228. * We could not send the notification.
  229. *****************************************************************************/
  230. HRESULT AsyncRPCEventClient::SendNextEventNotification()
  231. {
  232. HRESULT hr = S_OK;
  233. WiaEventInfo *pWiaEventInfo = NULL;
  234. TAKE_CRIT_SECT t(m_csClientSync);
  235. //
  236. // We put an exception handler around our code to ensure that the
  237. // crtitical section is exited properly.
  238. //
  239. _try
  240. {
  241. //
  242. // Check whether the client is ready to receive events yet
  243. //
  244. if (m_pAsyncState && m_pAsyncEventData)
  245. {
  246. RPC_STATUS rpcStatus = RPC_S_OK;
  247. DWORD dwClientRet = RPC_S_OK;
  248. if (m_ListOfEventsPending.Dequeue(pWiaEventInfo))
  249. {
  250. if (pWiaEventInfo)
  251. {
  252. //
  253. // We have the event - let's prepare the data.
  254. //
  255. m_pAsyncEventData->EventGuid = pWiaEventInfo->getEventGuid();
  256. m_pAsyncEventData->bstrEventDescription = SysAllocString(pWiaEventInfo->getEventDescription());
  257. m_pAsyncEventData->bstrDeviceID = SysAllocString(pWiaEventInfo->getDeviceID());
  258. m_pAsyncEventData->bstrDeviceDescription = SysAllocString(pWiaEventInfo->getDeviceDescription());
  259. m_pAsyncEventData->bstrFullItemName = SysAllocString(pWiaEventInfo->getFullItemName());
  260. m_pAsyncEventData->dwDeviceType = pWiaEventInfo->getDeviceType();
  261. m_pAsyncEventData->ulEventType = pWiaEventInfo->getEventType();
  262. //
  263. // We're done with pWiaEventInfo, so we can release it here
  264. //
  265. pWiaEventInfo->Release();
  266. pWiaEventInfo = NULL;
  267. //
  268. // Let's send the event notification
  269. //
  270. rpcStatus = RpcAsyncCompleteCall(m_pAsyncState, &dwClientRet);
  271. if (rpcStatus != RPC_S_OK)
  272. {
  273. hr = HRESULT_FROM_WIN32(rpcStatus);
  274. }
  275. //
  276. // Since we've sent the notification, our async params are invalid.
  277. // Clear them now.
  278. //
  279. m_pAsyncState = NULL;
  280. m_pAsyncEventData = NULL;
  281. }
  282. }
  283. }
  284. }
  285. _except(EXCEPTION_EXECUTE_HANDLER)
  286. {
  287. DBG_ERR(("Runtime event client error: We caught exception 0x%08X trying to send pending event", GetExceptionCode()));
  288. hr = E_UNEXPECTED;
  289. // TBD: Rethrow the exception?
  290. }
  291. return hr;
  292. }