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.

546 lines
19 KiB

  1. /*****************************************************************************
  2. * (C) COPYRIGHT MICROSOFT CORPORATION, 2002
  3. *
  4. * AUTHOR: ByronC
  5. *
  6. * DATE: 3/24/2002
  7. *
  8. * @doc INTERNAL
  9. *
  10. * @module WiaEventClient.cpp - Implementation of the <c WiaEventClient> class |
  11. *
  12. * This file contains the implementation for the <c WiaEventClient> base class.
  13. *
  14. *****************************************************************************/
  15. #include "precomp.h"
  16. #include "wia.h"
  17. /*****************************************************************************
  18. * @doc INTERNAL
  19. *
  20. * @mfunc | WiaEventClient | WiaEventClient |
  21. *
  22. * We initialize all member variables. In general, this sets the values to 0,
  23. * except:
  24. * <nl><md WiaEventClient::m_ulSig> is set to be WiaEventClient_UNINIT_SIG.
  25. * <nl><md WiaEventClient::m_cRef> is set to be 1.
  26. * <nl><md WiaEventClient::m_ClientContext> is set to be ClientContext.
  27. *
  28. *****************************************************************************/
  29. WiaEventClient::WiaEventClient(STI_CLIENT_CONTEXT ClientContext) :
  30. m_ulSig(WiaEventClient_UNINIT_SIG),
  31. m_cRef(1),
  32. m_ClientContext(ClientContext),
  33. m_bRemove(FALSE)
  34. {
  35. DBG_FN(WiaEventClient);
  36. }
  37. /*****************************************************************************
  38. * @doc INTERNAL
  39. *
  40. * @mfunc | WiaEventClient | ~WiaEventClient |
  41. *
  42. * Do any cleanup that is not already done. We call:
  43. * <nl><mf WiaEventClient::DestroyRegistrationList>
  44. * <nl><mf WiaEventClient::DestroyPendingEventList>
  45. *
  46. * Also:
  47. * <nl><md WiaEventClient::m_ulSig> is set to be WiaEventClient_DEL_SIG.
  48. *
  49. *****************************************************************************/
  50. WiaEventClient::~WiaEventClient()
  51. {
  52. DBG_FN(~WiaEventClient destructor);
  53. m_ulSig = WiaEventClient_DEL_SIG;
  54. m_cRef = 0;
  55. m_ClientContext = NULL;
  56. DestroyRegistrationList();
  57. DestroyPendingEventList();
  58. }
  59. /*****************************************************************************
  60. * @doc INTERNAL
  61. *
  62. * @mfunc ULONG | WiaEventClient | AddRef |
  63. *
  64. * Increments this object's ref count. We should always AddRef when handing
  65. * out a pointer to this object.
  66. *
  67. * @rvalue Count |
  68. * The reference count after the count has been incremented.
  69. *****************************************************************************/
  70. ULONG __stdcall WiaEventClient::AddRef()
  71. {
  72. InterlockedIncrement((long*) &m_cRef);
  73. return m_cRef;
  74. }
  75. /*****************************************************************************
  76. * @doc INTERNAL
  77. *
  78. * @mfunc ULONG | WiaEventClient | Release |
  79. *
  80. * Decrement this object's ref count. We should always Release when finished
  81. * with a pointer to this object.
  82. *
  83. * @rvalue Count |
  84. * The reference count after the count has been decremented.
  85. *****************************************************************************/
  86. ULONG __stdcall WiaEventClient::Release()
  87. {
  88. ULONG ulRefCount = m_cRef - 1;
  89. if (InterlockedDecrement((long*) &m_cRef) == 0) {
  90. delete this;
  91. return 0;
  92. }
  93. return ulRefCount;
  94. }
  95. /*****************************************************************************
  96. * @doc INTERNAL
  97. *
  98. * @mfunc HRESULT | WiaEventClient | Initialize |
  99. *
  100. * Create and initialize any dependant objects/resources. Specifically:
  101. * <nl>- Check that <md WiaEventClient::m_csClientSync> is initialized
  102. * correctly.
  103. *
  104. * If this method fails, the object should not be used - it should be
  105. * destroyed immediately.
  106. *
  107. * @rvalue S_OK |
  108. * The method succeeded.
  109. * @rvalue E_UNEXPECTED |
  110. * The object could not be intialized sucessfully.
  111. *****************************************************************************/
  112. HRESULT WiaEventClient::Initialize()
  113. {
  114. HRESULT hr = S_OK;
  115. if (!m_csClientSync.IsInitialized())
  116. {
  117. DBG_ERR(("Runtime event Error: WiaEventClient's sync primitive could not be created"));
  118. hr = E_UNEXPECTED;
  119. }
  120. if (SUCCEEDED(hr))
  121. {
  122. m_ulSig = WiaEventNotifier_INIT_SIG;
  123. }
  124. return hr;
  125. }
  126. /*****************************************************************************
  127. * @doc INTERNAL
  128. *
  129. * @mfunc BOOL | WiaEventClient | IsRegisteredForEvent |
  130. *
  131. * Checks whether the client has at least one event registration that matches
  132. * this event.
  133. *
  134. * @parm WiaEventInfo* | pWiaEventInfo |
  135. * Indicates WIA Device event
  136. *
  137. * @rvalue TRUE |
  138. * The client is registered to receive this event.
  139. * @rvalue FALSE |
  140. * The client is not registered.
  141. *****************************************************************************/
  142. BOOL WiaEventClient::IsRegisteredForEvent(
  143. WiaEventInfo *pWiaEventInfo)
  144. {
  145. BOOL bRegistered = FALSE;
  146. if (pWiaEventInfo)
  147. {
  148. BSTR bstrDeviceID = pWiaEventInfo->getDeviceID();
  149. GUID guidEvent = pWiaEventInfo->getEventGuid();
  150. TAKE_CRIT_SECT t(m_csClientSync);
  151. //
  152. // We put an exception handler around our code to ensure that the
  153. // crtitical section is exited properly.
  154. //
  155. _try
  156. {
  157. //
  158. // Walk the list and see if we can find it
  159. //
  160. EventRegistrationInfo *pEventRegistrationInfo = NULL;
  161. CSimpleLinkedList<EventRegistrationInfo*>::Iterator iter;
  162. for (iter = m_ListOfEventRegistrations.Begin(); iter != m_ListOfEventRegistrations.End(); ++iter)
  163. {
  164. pEventRegistrationInfo = *iter;
  165. if (pEventRegistrationInfo)
  166. {
  167. if (pEventRegistrationInfo->MatchesDeviceEvent(bstrDeviceID, guidEvent))
  168. {
  169. //
  170. // We found a registration matching this event, set the return and break from the loop
  171. //
  172. bRegistered = TRUE;
  173. break;
  174. }
  175. }
  176. else
  177. {
  178. //
  179. // Log Error
  180. // pEventRegistrationInfo should never be NULL
  181. DBG_ERR(("Runtime event Error: While searching for an equal registration, we hit a NULL pEventRegistrationInfo!"));
  182. }
  183. }
  184. }
  185. _except(EXCEPTION_EXECUTE_HANDLER)
  186. {
  187. DBG_ERR(("Runtime event Error: The WiaEventClient caught an exception (0x%08X) trying to check for an event registration", GetExceptionCode()));
  188. // TBD: Should we re-throw the exception?
  189. }
  190. }
  191. else
  192. {
  193. DBG_ERR(("Runtime event Error: The WiaEventClient cannot check whether the client is registered for a NULL WIA Event"));
  194. }
  195. return bRegistered;
  196. }
  197. /*****************************************************************************
  198. * @doc INTERNAL
  199. *
  200. * @mfunc HRESULT | WiaEventClient | RegisterUnregisterForEventNotification |
  201. *
  202. * Description goes here
  203. *
  204. * @parm EventRegistrationInfo | pEventRegistrationInfo |
  205. * Pointer to a class containing the registration data to add.
  206. * This method will make a copy of the structure and insert it into the
  207. * relevant list.
  208. *
  209. * @rvalue S_OK |
  210. * The method succeeded.
  211. * @rvalue S_FALSE |
  212. * We are already registered for this.
  213. * @rvalue E_XXXXXXXX |
  214. * Could not update event registration.
  215. *****************************************************************************/
  216. HRESULT WiaEventClient::RegisterUnregisterForEventNotification(
  217. EventRegistrationInfo *pEventRegistrationInfo)
  218. {
  219. HRESULT hr = S_OK;
  220. if (pEventRegistrationInfo)
  221. {
  222. //
  223. // We always have to walk through the list. This is because when we add, we need
  224. // to check whether it already exists. When we remove, we need to find the
  225. // element to remove.
  226. // So, try and find the element here.
  227. //
  228. EventRegistrationInfo *pExistingReg = FindEqualEventRegistration(pEventRegistrationInfo);
  229. //
  230. // Check whether this is registration or unregistration.
  231. // NOTE: Since unregistration is typically done via the RegistrationCookie,
  232. // our hueristic for this is that if it is not specifically an UnRegistration,
  233. // then it is considered a registration.
  234. //
  235. if (pEventRegistrationInfo->getFlags() & WIA_UNREGISTER_EVENT_CALLBACK)
  236. {
  237. if (pExistingReg != NULL)
  238. {
  239. //
  240. // Release it and remove it from our list.
  241. //
  242. m_ListOfEventRegistrations.Remove(pExistingReg);
  243. pExistingReg->Release();
  244. DBG_TRC(("Removed registration:"));
  245. pExistingReg->Dump();
  246. }
  247. else
  248. {
  249. DBG_ERR(("Runtime event Error: Attempting to unregister when you have not first registered"));
  250. hr = E_INVALIDARG;
  251. }
  252. }
  253. else // This is considered a registration
  254. {
  255. if (pExistingReg == NULL)
  256. {
  257. //
  258. // Add it to our list. We AddRef it here since we're keeping a reference to it.
  259. //
  260. m_ListOfEventRegistrations.Prepend(pEventRegistrationInfo);
  261. pEventRegistrationInfo->AddRef();
  262. DBG_TRC(("Added new registration:"));
  263. pEventRegistrationInfo->Dump();
  264. hr = S_OK;
  265. }
  266. else
  267. {
  268. DBG_WRN(("Runtime event client Error: Registration already exists in the list"));
  269. hr = S_FALSE;
  270. }
  271. }
  272. //
  273. // We need to release pExistingReg due to the AddRef from the lookup.
  274. //
  275. if (pExistingReg)
  276. {
  277. pExistingReg->Release();
  278. pExistingReg = NULL;
  279. }
  280. }
  281. else
  282. {
  283. DBG_ERR(("Runtime event Error: Cannot handle a NULL registration"));
  284. hr = E_POINTER;
  285. }
  286. return hr;
  287. }
  288. /*****************************************************************************
  289. * @doc INTERNAL
  290. *
  291. * @mfunc HRESULT | WiaEventClient | AddPendingEventNotification |
  292. *
  293. * Description goes here
  294. *
  295. * @parm WiaEventInfo* | pWiaEventInfo |
  296. * Pointer to a <c WiaEventInfo> object which contains event info that
  297. * must be sent to the client. This class is AddRef'd when added to the
  298. * list.
  299. *
  300. * @rvalue S_OK |
  301. * The method succeeded.
  302. * @rvalue E_UNEXPECTED |
  303. * The object could not be added sucessfully.
  304. *****************************************************************************/
  305. HRESULT WiaEventClient::AddPendingEventNotification(
  306. WiaEventInfo *pWiaEventInfo)
  307. {
  308. HRESULT hr = S_OK;
  309. TAKE_CRIT_SECT t(m_csClientSync);
  310. //
  311. // We put an exception handler around our code to ensure that the
  312. // crtitical section is exited properly.
  313. //
  314. _try
  315. {
  316. DBG_TRC(("Added another pending event to %p", m_ClientContext));
  317. m_ListOfEventsPending.Enqueue(pWiaEventInfo);
  318. pWiaEventInfo->AddRef();
  319. }
  320. _except(EXCEPTION_EXECUTE_HANDLER)
  321. {
  322. DBG_ERR(("Runtime event Error: The WiaEventClient caught an exception (0x%08X) trying to add a pending event", GetExceptionCode()));
  323. // TBD: Should we re-throw the exception?
  324. hr = E_UNEXPECTED;
  325. }
  326. return hr;
  327. }
  328. /*****************************************************************************
  329. * @doc INTERNAL
  330. *
  331. * @mfunc STI_CLIENT_CONTEXT | WiaEventClient | getClientContext |
  332. *
  333. * Returns the context which uniquely identifies the client.
  334. *
  335. * @rvalue STI_CLIENT_CONTEXT |
  336. * The context identifyin this client.
  337. *****************************************************************************/
  338. STI_CLIENT_CONTEXT WiaEventClient::getClientContext()
  339. {
  340. return m_ClientContext;
  341. }
  342. /*****************************************************************************
  343. * @doc INTERNAL
  344. *
  345. * @mfunc EventRegistrationInfo* | WiaEventClient | FindEqualEventRegistration |
  346. *
  347. * Checks whether a semantically equal <c EventRegistrationInfo> is in the list.
  348. * If it is, we retrieve it. Note that caller must Release it.
  349. *
  350. * @parm EventRegistrationInfo | pEventRegistrationInfo |
  351. * Specifies a <c EventRegistrationInfo> we're looking for in our list.
  352. *
  353. * @rvalue NULL |
  354. * We could not find it.
  355. * @rvalue non-NULL |
  356. * The equivalent <c EventRegistrationInfo> exists. Caller must Release.
  357. *****************************************************************************/
  358. EventRegistrationInfo* WiaEventClient::FindEqualEventRegistration(
  359. EventRegistrationInfo *pEventRegistrationInfo)
  360. {
  361. EventRegistrationInfo *pRet = NULL;
  362. if (pEventRegistrationInfo)
  363. {
  364. TAKE_CRIT_SECT t(m_csClientSync);
  365. //
  366. // We put an exception handler around our code to ensure that the
  367. // crtitical section is exited properly.
  368. //
  369. _try
  370. {
  371. //
  372. // Walk the list and see if we can find it
  373. //
  374. EventRegistrationInfo *pElem = NULL;
  375. CSimpleLinkedList<EventRegistrationInfo*>::Iterator iter;
  376. for (iter = m_ListOfEventRegistrations.Begin(); iter != m_ListOfEventRegistrations.End(); ++iter)
  377. {
  378. pElem = *iter;
  379. if (pElem)
  380. {
  381. if (pElem->Equals(pEventRegistrationInfo))
  382. {
  383. //
  384. // We found it, so AddRef it and set the return
  385. //
  386. pElem->AddRef();
  387. pRet = pElem;
  388. break;
  389. }
  390. }
  391. else
  392. {
  393. //
  394. // Log Error
  395. // pEventRegistrationInfo should never be NULL
  396. DBG_ERR(("Runtime event Error: While searching for an equal registration, we hit a NULL pEventRegistrationInfo!"));
  397. }
  398. }
  399. }
  400. _except(EXCEPTION_EXECUTE_HANDLER)
  401. {
  402. DBG_ERR(("Runtime event Error: The WiaEventClient caught an exception (0x%08X) trying to find an equal event registration", GetExceptionCode()));
  403. // TBD: Should we re-throw the exception?
  404. }
  405. }
  406. return pRet;
  407. }
  408. /*****************************************************************************
  409. * @doc INTERNAL
  410. *
  411. * @mfunc VOID | WiaEventClient | DestroyRegistrationList |
  412. *
  413. * Frees all resources associated with the registration list by releasing all elements
  414. * in it, and then destroying the links in the list.
  415. *****************************************************************************/
  416. VOID WiaEventClient::DestroyRegistrationList()
  417. {
  418. TAKE_CRIT_SECT t(m_csClientSync);
  419. //
  420. // We put an exception handler around our code to ensure that the
  421. // crtitical section is exited properly.
  422. //
  423. _try
  424. {
  425. //
  426. // Walk the list of registrations release all elements. Then destroy the list.
  427. //
  428. EventRegistrationInfo *pElem = NULL;
  429. CSimpleLinkedList<EventRegistrationInfo*>::Iterator iter;
  430. for (iter = m_ListOfEventRegistrations.Begin(); iter != m_ListOfEventRegistrations.End(); ++iter)
  431. {
  432. pElem = *iter;
  433. if (pElem)
  434. {
  435. pElem->Release();
  436. }
  437. }
  438. m_ListOfEventRegistrations.Destroy();
  439. }
  440. _except(EXCEPTION_EXECUTE_HANDLER)
  441. {
  442. DBG_ERR(("Runtime event Error: The WiaEventClient caught an exception (0x%08X) trying to destroy the registration list", GetExceptionCode()));
  443. // TBD: Should we re-throw the exception?
  444. }
  445. }
  446. /*****************************************************************************
  447. * @doc INTERNAL
  448. *
  449. * @mfunc VOID | WiaEventClient | DestroyPendingEventList |
  450. *
  451. * Frees all resources associated with the pending event list by releasing all elements
  452. * in it, and then destroying the links in the list.
  453. *****************************************************************************/
  454. VOID WiaEventClient::DestroyPendingEventList()
  455. {
  456. TAKE_CRIT_SECT t(m_csClientSync);
  457. //
  458. // We put an exception handler around our code to ensure that the
  459. // crtitical section is exited properly.
  460. //
  461. _try
  462. {
  463. //
  464. // Walk the list of registrations release all elements. Then destroy the list.
  465. //
  466. WiaEventInfo *pElem = NULL;
  467. CSimpleLinkedList<WiaEventInfo*>::Iterator iter;
  468. for (iter = m_ListOfEventsPending.Begin(); iter != m_ListOfEventsPending.End(); ++iter)
  469. {
  470. pElem = *iter;
  471. if (pElem)
  472. {
  473. pElem->Release();
  474. }
  475. }
  476. m_ListOfEventsPending.Destroy();
  477. }
  478. _except(EXCEPTION_EXECUTE_HANDLER)
  479. {
  480. DBG_ERR(("Runtime event Error: The WiaEventClient caught an exception (0x%08X) trying to destroy the registration list", GetExceptionCode()));
  481. // TBD: Should we re-throw the exception?
  482. }
  483. }
  484. /*****************************************************************************
  485. * @doc INTERNAL
  486. *
  487. * @mfunc VOID | WiaEventClient | MarkForRemoval |
  488. *
  489. * Sets the mark to indicate that this object should be removed at the next
  490. * possible convenience (i.e. we use lazy deletion).
  491. *
  492. *****************************************************************************/
  493. VOID WiaEventClient::MarkForRemoval()
  494. {
  495. DBG_TRC(("Client %p marked for removal", m_ClientContext));
  496. m_bRemove = TRUE;
  497. }
  498. /*****************************************************************************
  499. * @doc INTERNAL
  500. *
  501. * @mfunc BOOL | WiaEventClient | isMarkedForRemoval |
  502. *
  503. * Check the mark to indicate whether this object should be removed.
  504. *
  505. * @rvalue TRUE |
  506. * This object can/should be removed.
  507. * @rvalue FALSE |
  508. * This object is not marked for removal.
  509. *****************************************************************************/
  510. BOOL WiaEventClient::isMarkedForRemoval()
  511. {
  512. return m_bRemove;
  513. }