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.

624 lines
23 KiB

  1. /*****************************************************************************
  2. * (C) COPYRIGHT MICROSOFT CORPORATION, 2002
  3. *
  4. * AUTHOR: ByronC
  5. *
  6. * DATE: 4/10/2002
  7. *
  8. * @doc INTERNAL
  9. *
  10. * @module WiaEventHandlerLookup.cpp - Implementation for <c WiaEventHandlerLookup> |
  11. *
  12. * This file contains the implementation for the <c WiaEventHandlerLookup> class.
  13. *
  14. *****************************************************************************/
  15. #include "precomp.h"
  16. /*****************************************************************************
  17. * @doc INTERNAL
  18. *
  19. * @mfunc | WiaEventHandlerLookup | WiaEventHandlerLookup |
  20. *
  21. * We initialize all member variables. In general, this sets the values to 0,
  22. * except:
  23. * <nl><md WiaEventHandlerLookup::m_ulSig> is set to be WiaEventHandlerLookup_INIT_SIG.
  24. * <nl><md WiaEventHandlerLookup::m_cRef> is set to be 1.
  25. *
  26. *****************************************************************************/
  27. WiaEventHandlerLookup::WiaEventHandlerLookup(
  28. const CSimpleStringWide &cswEventKeyRoot) :
  29. m_ulSig(WiaEventHandlerLookup_INIT_SIG),
  30. m_cRef(1),
  31. m_cswEventKeyRoot(cswEventKeyRoot),
  32. m_pEventHandlerInfo(NULL)
  33. {
  34. }
  35. /*****************************************************************************
  36. * @doc INTERNAL
  37. *
  38. * @mfunc | WiaEventHandlerLookup | WiaEventHandlerLookup |
  39. *
  40. * We initialize all member variables. In general, this sets the values to 0,
  41. * except:
  42. * <nl><md WiaEventHandlerLookup::m_ulSig> is set to be WiaEventHandlerLookup_INIT_SIG.
  43. * <nl><md WiaEventHandlerLookup::m_cRef> is set to be 1.
  44. *
  45. *****************************************************************************/
  46. WiaEventHandlerLookup::WiaEventHandlerLookup() :
  47. m_ulSig(WiaEventHandlerLookup_INIT_SIG),
  48. m_cRef(1),
  49. m_pEventHandlerInfo(NULL)
  50. {
  51. }
  52. /*****************************************************************************
  53. * @doc INTERNAL
  54. *
  55. * @mfunc | WiaEventHandlerLookup | ~WiaEventHandlerLookup |
  56. *
  57. * Do any cleanup that is not already done.
  58. *
  59. * Also:
  60. * <nl><md WiaEventHandlerLookup::m_ulSig> is set to be WiaEventHandlerLookup_DEL_SIG.
  61. *
  62. *****************************************************************************/
  63. WiaEventHandlerLookup::~WiaEventHandlerLookup()
  64. {
  65. m_ulSig = WiaEventHandlerLookup_DEL_SIG;
  66. m_cRef = 0;
  67. }
  68. /*****************************************************************************
  69. * @doc INTERNAL
  70. *
  71. * @mfunc ULONG | WiaEventHandlerLookup | AddRef |
  72. *
  73. * Increments this object's ref count. We should always AddRef when handing
  74. * out a pointer to this object.
  75. *
  76. * @rvalue Count |
  77. * The reference count after the count has been incremented.
  78. *****************************************************************************/
  79. ULONG __stdcall WiaEventHandlerLookup::AddRef()
  80. {
  81. InterlockedIncrement((long*) &m_cRef);
  82. return m_cRef;
  83. }
  84. /*****************************************************************************
  85. * @doc INTERNAL
  86. *
  87. * @mfunc ULONG | WiaEventHandlerLookup | Release |
  88. *
  89. * Decrement this object's ref count. We should always Release when finished
  90. * with a pointer to this object.
  91. *
  92. * @rvalue Count |
  93. * The reference count after the count has been decremented.
  94. *****************************************************************************/
  95. ULONG __stdcall WiaEventHandlerLookup::Release()
  96. {
  97. ULONG ulRefCount = m_cRef - 1;
  98. if (InterlockedDecrement((long*) &m_cRef) == 0)
  99. {
  100. delete this;
  101. return 0;
  102. }
  103. if (m_pEventHandlerInfo)
  104. {
  105. m_pEventHandlerInfo->Release();
  106. m_pEventHandlerInfo = NULL;
  107. }
  108. return ulRefCount;
  109. }
  110. /*****************************************************************************
  111. * @doc INTERNAL
  112. *
  113. * @mfunc EventHandlerInfo* | WiaEventHandlerLookup | getPersistentHandlerForDeviceEvent |
  114. *
  115. * This static method is used to find the WIA persistent event handler
  116. * registered for a particular device event.
  117. *
  118. * The heuristics used is as follows:
  119. *
  120. * <nl> 1. First, let's look for the prompt registered for this event.
  121. * <nl> 2. If one doesn't exist, try and grab the prompt for the STI_PROXY_EVENT.
  122. * <nl> 3. If we cannot find it, grab the first event handler for this event we can find.
  123. * <nl> 4. If that doesn't exist, just find the first handler for the STI_PROXY_EVENT.
  124. * <nl> 5. If none was found, we have no handlers for this event.
  125. *
  126. * Note: This method clears <md WiaEventHandlerLookup::m_cswEventKeyRoot>
  127. *
  128. * @parm CSimpleString& | cswDeviceID |
  129. * The WIA DeviceID on which this event occured
  130. * @parm GUID& | guidEvent |
  131. * The WIA event guid indicating which event occured
  132. *
  133. * @rvalue NULL |
  134. * There is no handler registered which can accept this device event.
  135. * @rvalue non-NULL |
  136. * A pointer to a <c WiaHandlerInfo> describing the registered
  137. * handler. Caller must Release.
  138. *****************************************************************************/
  139. EventHandlerInfo* WiaEventHandlerLookup::getPersistentHandlerForDeviceEvent(
  140. const CSimpleStringWide &cswDeviceID,
  141. const GUID &guidEvent)
  142. {
  143. EventHandlerInfo *pEventHandlerInfo = NULL;
  144. m_cswEventKeyRoot = L"";
  145. //
  146. // Get the device key for this device id. We can then do a lookup on the device's event
  147. // subkey to look for a default handler.
  148. // We will skip this lookup if we cannot find the Device key path
  149. //
  150. WiaDeviceKey wiaDeviceKey(cswDeviceID);
  151. if (wiaDeviceKey.getDeviceKeyPath().Length() > 0)
  152. {
  153. CSimpleString cswDeviceEventKey = wiaDeviceKey.getDeviceKeyPath() + EVENT_STR;
  154. setEventKeyRoot(cswDeviceEventKey);
  155. pEventHandlerInfo = getHandlerRegisteredForEvent(guidEvent);
  156. }
  157. //
  158. // If we haven't found it yet, let's check for global handlers
  159. //
  160. if (!pEventHandlerInfo)
  161. {
  162. //
  163. // 1. First, let's look for the prompt registered for this event.
  164. // 2. If one doesn't exist, try and grab the prompt for the STI_PROXY_EVENT.
  165. // 3. If we cannot find it, grab the first event handler for this event we can find.
  166. // 4. If that doesn't exist, just find the first handler for the STI_PROXY_EVENT.
  167. // 5. If none was found, we have no handlers for this event.
  168. //
  169. setEventKeyRoot(GLOBAL_HANDLER_REGPATH);
  170. pEventHandlerInfo = getHandlerFromCLSID(guidEvent, WIA_EVENT_HANDLER_PROMPT);
  171. if (!pEventHandlerInfo)
  172. {
  173. //
  174. // 2. Try and grab the prompt for the STI_PROXY_EVENT.
  175. //
  176. pEventHandlerInfo = getHandlerFromCLSID(WIA_EVENT_STI_PROXY, WIA_EVENT_HANDLER_PROMPT);
  177. }
  178. if (!pEventHandlerInfo)
  179. {
  180. //
  181. // 3. Grab the first event handler for this event we can find.
  182. //
  183. pEventHandlerInfo = getHandlerRegisteredForEvent(guidEvent);
  184. }
  185. if (!pEventHandlerInfo)
  186. {
  187. //
  188. // 4. Just find the first handler for the STI_PROXY_EVENT..
  189. //
  190. pEventHandlerInfo = getHandlerRegisteredForEvent(WIA_EVENT_STI_PROXY);
  191. }
  192. }
  193. return pEventHandlerInfo;
  194. }
  195. /*****************************************************************************
  196. * @doc INTERNAL
  197. *
  198. * @mfunc VOID | WiaEventHandlerLookup | setEventKeyRoot |
  199. *
  200. * Description goes here
  201. *
  202. * @parm CSimpleString& | cswNewEventKeyPath |
  203. * The new event key path to use as root for our lookups.
  204. *
  205. *****************************************************************************/
  206. VOID WiaEventHandlerLookup::setEventKeyRoot(
  207. const CSimpleString& cswNewEventKeyPath)
  208. {
  209. m_cswEventKeyRoot = cswNewEventKeyPath;
  210. }
  211. /*****************************************************************************
  212. * @doc INTERNAL
  213. *
  214. * @mfunc EventHandlerInfo* | WiaEventHandlerLookup | getHandlerRegisteredForDeviceEvent |
  215. *
  216. * In WIA, a handler registers for Device/Event pairs. When an event occurs,
  217. * a handler registered for that event needs to be found.
  218. * Note that by the time we use this class to look for an event handler, we already
  219. * know that we have a match on Device ID (WIA events are always matched by
  220. * Event and Device pairs). This is quitre easily explained with an example:
  221. * <nl>When searching for a handler, we might use logic like:
  222. * <nl> EventHandlerInfo *pInfo = NULL;
  223. * <nl> WiaEventHandlerLookup deviceSpecificLookup(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Class\\{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}\\0003\\Events");
  224. * <nl> pInfo = deviceSpecificLookup.getHandlerRegisteredForEvent(guidEvent);
  225. * <nl> if (!pInfo)
  226. * <nl> {
  227. * <nl> //
  228. * <nl> // Didn't find a handler registered for that device so let's try the globals
  229. * <nl> //
  230. * <nl> WiaEventHandlerLookup globalLookup(L"SYSTEM\\CurrentControlSet\\Control\\StillImage\\Events");
  231. * <nl> pInfo.globalLookup.getHandlerRegisteredForEvent(guidEvent);
  232. * <nl> .
  233. * <nl> .
  234. * <nl> . and so on
  235. * <nl> .
  236. * <nl> };
  237. *
  238. * This method walks the registry, starting from <md WiaEventHandlerLookup::m_cswEventKeyRoot>,
  239. * and returns a pointer to a <c EventHandlerInfo> describing the registered
  240. * handler for this device event.
  241. *
  242. * @parm GUID | guidEvent |
  243. * A guid indicating the WIA event.
  244. *
  245. * @rvalue NULL |
  246. * There is no handler registered which can accept this device event.
  247. * @rvalue non-NULL |
  248. * A pointer to a <c WiaHandlerInfo> describing the registered
  249. * handler. Caller must Release.
  250. *****************************************************************************/
  251. EventHandlerInfo* WiaEventHandlerLookup::getHandlerRegisteredForEvent(
  252. const GUID &guidEvent)
  253. {
  254. EventHandlerInfo *pEventHandlerInfo = NULL;
  255. //
  256. // Ensure we do not have any event info left lying around.
  257. //
  258. if (m_pEventHandlerInfo)
  259. {
  260. m_pEventHandlerInfo->Release();
  261. m_pEventHandlerInfo = NULL;
  262. }
  263. //
  264. // Save the parameters in member fields so we can search on them during
  265. // reg key enumeration. Enumeration is done via procedure callbacks,
  266. // in which we pass (this) as a parameter.
  267. //
  268. WCHAR wszGuid[40];
  269. if (StringFromGUID2(guidEvent, wszGuid, sizeof(wszGuid)/sizeof(wszGuid[0])))
  270. {
  271. wszGuid[(sizeof(wszGuid)/sizeof(wszGuid[0])) - 1] = L'\0';
  272. m_cswEventGuidString = wszGuid;
  273. }
  274. //
  275. // Open the registery at the desired place. We only require READ access and
  276. // we do not want to create it if it doesn't exist.
  277. //
  278. CSimpleReg csrEventRoot(HKEY_LOCAL_MACHINE, m_cswEventKeyRoot, false, KEY_READ, NULL);
  279. //
  280. // Enumerate the sub-keys looking for the sub-key corresponding to guidEvent.
  281. //
  282. bool bKeyNotFound = csrEventRoot.EnumKeys(WiaEventHandlerLookup::ProcessEventSubKey, (LPARAM)this);
  283. if (bKeyNotFound)
  284. {
  285. DBG_TRC(("Key was not found!"));
  286. }
  287. else
  288. {
  289. DBG_TRC(("We found key %ws, looking for default handler...", m_cswEventKey.String()));
  290. //
  291. // First, check whether we have a specific entry for the default handler.
  292. //
  293. CSimpleReg csrEventKey(csrEventRoot.GetKey(), m_cswEventKey.String());
  294. CSimpleStringWide cswDefault = csrEventKey.Query(DEFAULT_HANDLER_VALUE_NAME, L"");
  295. if (cswDefault.Length() > 0)
  296. {
  297. //
  298. // Try and open the key specified by the default handler entry.
  299. //
  300. CSimpleReg csrDefautHandler(csrEventKey.GetKey(), cswDefault);
  301. if (csrEventKey.OK())
  302. {
  303. //
  304. // Fill in the handler info from the handler entry
  305. //
  306. pEventHandlerInfo = CreateHandlerInfoFromKey(csrDefautHandler);
  307. }
  308. }
  309. //
  310. // If we could not find the default, we will just take the first one we find.
  311. // TBD: Should we enumerate and return the last one registered instead? WinXP bits
  312. // did not do this...
  313. //
  314. if (!pEventHandlerInfo)
  315. {
  316. //
  317. // Set the Handler CLSID to the empty string, since we're not looking for a specific handler,
  318. // any one while do.
  319. //
  320. m_cswHandlerCLSID = L"";
  321. csrEventKey.EnumKeys(WiaEventHandlerLookup::ProcessHandlerSubKey, (LPARAM)this);
  322. //
  323. // Swap pEventHandlerInfo with m_pEventHandlerInfo. m_pEventHandlerInfo will
  324. // be non-NULL if we were successfull.
  325. // Be sure to set it to NULL so we don't release it if this function is called again
  326. // - only the caller should release this object.
  327. //
  328. pEventHandlerInfo = m_pEventHandlerInfo;
  329. m_pEventHandlerInfo = NULL;
  330. }
  331. // Diagnostic only
  332. if (pEventHandlerInfo)
  333. {
  334. DBG_TRC(("Found handler:"));
  335. pEventHandlerInfo->Dump();
  336. }
  337. else
  338. {
  339. DBG_TRC(("No handler could be found"));
  340. }
  341. }
  342. return pEventHandlerInfo;
  343. }
  344. /*****************************************************************************
  345. * @doc INTERNAL
  346. *
  347. * @mfunc EventHandlerInfo* | WiaEventHandlerLookup | getHandlerRegisteredForDeviceEvent |
  348. *
  349. * This method walks the registry, starting from <md WiaEventHandlerLookup::m_cswEventKeyRoot>,
  350. * searches for the event subkey matching <p guidEvent>. It enumerates all handlers
  351. * under that key and finds the one whose CLSID matches <p guidHandlerCLSID> and
  352. * returns a pointer to a <c EventHandlerInfo>.
  353. *
  354. * @parm GUID | guidEvent |
  355. * A guid indicating the WIA event.
  356. * @parm GUID& | guidHandlerCLSID |
  357. * A guid indicating the CLSID of the registered handler.
  358. *
  359. * @rvalue NULL |
  360. * There is no handler registered with this CLSID.
  361. * @rvalue non-NULL |
  362. * A pointer to a <c WiaHandlerInfo> describing the registered
  363. * handler. Caller must Release.
  364. *****************************************************************************/
  365. EventHandlerInfo* WiaEventHandlerLookup::getHandlerFromCLSID(
  366. const GUID &guidEvent,
  367. const GUID &guidHandlerCLSID)
  368. {
  369. EventHandlerInfo *pEventHandlerInfo = NULL;
  370. //
  371. // Ensure we do not have any event info left lying around.
  372. //
  373. if (m_pEventHandlerInfo)
  374. {
  375. m_pEventHandlerInfo->Release();
  376. m_pEventHandlerInfo = NULL;
  377. }
  378. //
  379. // Save the parameters in member fields so we can search on them during
  380. // reg key enumeration. Enumeration is done via procedure callbacks,
  381. // in which we pass (this) as a parameter.
  382. //
  383. WCHAR wszGuid[40];
  384. if (StringFromGUID2(guidHandlerCLSID, wszGuid, sizeof(wszGuid)/sizeof(wszGuid[0])))
  385. {
  386. wszGuid[(sizeof(wszGuid)/sizeof(wszGuid[0])) - 1] = L'\0';
  387. m_cswHandlerCLSID = wszGuid;
  388. }
  389. if (StringFromGUID2(guidEvent, wszGuid, sizeof(wszGuid)/sizeof(wszGuid[0])))
  390. {
  391. wszGuid[(sizeof(wszGuid)/sizeof(wszGuid[0])) - 1] = L'\0';
  392. m_cswEventGuidString = wszGuid;
  393. }
  394. DBG_TRC(("Looking for event %ws and CLSID %ws", m_cswEventGuidString.String(), m_cswHandlerCLSID.String()));
  395. //
  396. // Open the registery at the desired place. We only require READ access and
  397. // we do not want to create it if it doesn't exist.
  398. //
  399. CSimpleReg csrEventRoot(HKEY_LOCAL_MACHINE, m_cswEventKeyRoot, false, KEY_READ, NULL);
  400. //
  401. // Enumerate the sub-keys looking for the sub-key corresponding to guidEvent.
  402. //
  403. bool bKeyNotFound = csrEventRoot.EnumKeys(WiaEventHandlerLookup::ProcessEventSubKey, (LPARAM)this);
  404. if (bKeyNotFound)
  405. {
  406. DBG_TRC(("Key was not found!"));
  407. }
  408. else
  409. {
  410. DBG_TRC(("We found key %ws, looking for specific handler...", m_cswEventKey.String()));
  411. CSimpleReg csrEventKey(csrEventRoot.GetKey(), m_cswEventKey.String());
  412. //
  413. // Search for the specific handler. m_cswHandlerCLSID has been primed with the
  414. // CLSID we're looking for.
  415. //
  416. csrEventKey.EnumKeys(WiaEventHandlerLookup::ProcessHandlerSubKey, (LPARAM)this);
  417. //
  418. // Swap pEventHandlerInfo with m_pEventHandlerInfo. m_pEventHandlerInfo will
  419. // be non-NULL if we were successfull.
  420. // Be sure to set it to NULL so we don't release it if this function is called again
  421. // - only the caller should release this object.
  422. //
  423. pEventHandlerInfo = m_pEventHandlerInfo;
  424. m_pEventHandlerInfo = NULL;
  425. // Diagnostic only
  426. if (pEventHandlerInfo)
  427. {
  428. DBG_TRC(("Found specific handler:"));
  429. pEventHandlerInfo->Dump();
  430. }
  431. else
  432. {
  433. DBG_TRC(("No specific handler could be found"));
  434. }
  435. }
  436. return pEventHandlerInfo;
  437. }
  438. /*****************************************************************************
  439. * @doc INTERNAL
  440. *
  441. * @mfunc EventHandlerInfo* | WiaEventHandlerLookup | CreateHandlerInfoFromKey |
  442. *
  443. * Creates a <c EventHandlerInfo> object for the specified handler registry key.
  444. *
  445. * @parm CSimpleReg | csrHandlerKey |
  446. * Reg key of the handler entry
  447. *
  448. * @rvalue NULL |
  449. * We could not create the event handler info object.
  450. * @rvalue non-NULL |
  451. * We created the event handler info object. Caller must Release.
  452. *****************************************************************************/
  453. EventHandlerInfo* WiaEventHandlerLookup::CreateHandlerInfoFromKey(
  454. CSimpleReg &csrHandlerKey)
  455. {
  456. EventHandlerInfo *pEventHandlerInfo = NULL;
  457. if (csrHandlerKey.OK())
  458. {
  459. CSimpleString cswCLSID = csrHandlerKey.GetSubKeyName();
  460. CSimpleString cswName = csrHandlerKey.Query(NAME_VALUE, L"");
  461. CSimpleString cswDescription = csrHandlerKey.Query(DESC_VALUE_NAME, L"");
  462. CSimpleString cswIcon = csrHandlerKey.Query(ICON_VALUE_NAME, L"");;
  463. CSimpleString cswCommandline = csrHandlerKey.Query(CMDLINE_VALUE_NAME, L"");
  464. GUID guidCLSID = GUID_NULL;
  465. CLSIDFromString((LPOLESTR)cswCLSID.String(), &guidCLSID);
  466. pEventHandlerInfo = new EventHandlerInfo(cswName,
  467. cswDescription,
  468. cswIcon,
  469. cswCommandline,
  470. guidCLSID);
  471. }
  472. return pEventHandlerInfo;
  473. }
  474. /*****************************************************************************
  475. * @doc INTERNAL
  476. *
  477. * @mfunc bool | WiaEventHandlerLookup | ProcessEventSubKey |
  478. *
  479. * This method is called on each sub-key as part of an enumeration of all
  480. * the event sub-keys. The enumeration will stop if we return false from
  481. * this method.
  482. *
  483. * @parm CKeyEnumInfo& | enumInfo |
  484. * Indicates the current sub-key we're on.
  485. *
  486. * @rvalue false |
  487. * Indicates we can stop with the enumeration. We found the correct
  488. * event key.
  489. * @rvalue true |
  490. * Indicates we should continue with the enumeration.
  491. *****************************************************************************/
  492. bool WiaEventHandlerLookup::ProcessEventSubKey(
  493. CSimpleReg::CKeyEnumInfo &enumInfo)
  494. {
  495. bool bContinueEnumeration = TRUE;
  496. //
  497. // Check that we have a This pointer
  498. //
  499. WiaEventHandlerLookup *This = (WiaEventHandlerLookup*)enumInfo.lParam;
  500. if (This)
  501. {
  502. //
  503. // Open this sub-key. We're looking for a sub-key which contains a GUID entry
  504. // matching m_cswEventGuidString.
  505. //
  506. CSimpleReg csrEventSubKey(enumInfo.hkRoot, enumInfo.strName);
  507. CSimpleStringWide cswGuidValue = csrEventSubKey.Query(GUID_VALUE_NAME, L"{00000000-0000-0000-0000-000000000000}");
  508. if (cswGuidValue.CompareNoCase(This->m_cswEventGuidString) == 0)
  509. {
  510. //
  511. // We found the key we're looking for. All we need to store is the name.
  512. //
  513. This->m_cswEventKey = enumInfo.strName;
  514. bContinueEnumeration = FALSE;
  515. }
  516. }
  517. return bContinueEnumeration;
  518. }
  519. /*****************************************************************************
  520. * @doc INTERNAL
  521. *
  522. * @mfunc bool | WiaEventHandlerLookup | ProcessHandlerSubKey |
  523. *
  524. * This method is called on each sub-key as part of an enumeration of
  525. * the handler sub-keys. Our current behavior is one of two options:
  526. * <nl> If <md WiaEventHandlerLookup::m_cswHandlerCLSID> is empty, stop enumeration after the
  527. * first one.
  528. * <nl> If <md WiaEventHandlerLookup::m_cswHandlerCLSID> is not empty, stop enumeration
  529. * only after finding the handler corresponding to that CLSID.
  530. *
  531. * On return, we set the <md WiaEventHandlerLookup::m_pEventHandlerInfo>
  532. * member.
  533. *
  534. * @parm CKeyEnumInfo& | enumInfo |
  535. * Indicates the current sub-key we're on.
  536. *
  537. * @rvalue false |
  538. * Indicates we can stop with the enumeration. We found the correct
  539. * handler.
  540. * @rvalue true |
  541. * Indicates we should continue with the enumeration.
  542. *****************************************************************************/
  543. bool WiaEventHandlerLookup::ProcessHandlerSubKey(
  544. CSimpleReg::CKeyEnumInfo &enumInfo)
  545. {
  546. bool bContinueEnumeration = TRUE;
  547. //
  548. // Check that we have a This pointer
  549. //
  550. WiaEventHandlerLookup *This = (WiaEventHandlerLookup*)enumInfo.lParam;
  551. if (This)
  552. {
  553. //
  554. // Open this sub-key.
  555. //
  556. CSimpleReg csrHandlerSubKey(enumInfo.hkRoot, enumInfo.strName);
  557. if (csrHandlerSubKey.OK())
  558. {
  559. //
  560. // Check whether we have to find a specific handler or just the first one.
  561. //
  562. if (This->m_cswHandlerCLSID.Length() > 0)
  563. {
  564. if (enumInfo.strName.CompareNoCase(This->m_cswHandlerCLSID) == 0)
  565. {
  566. //
  567. // This is the specific handler we're looking for.
  568. //
  569. This->m_pEventHandlerInfo = This->CreateHandlerInfoFromKey(csrHandlerSubKey);
  570. bContinueEnumeration = FALSE;
  571. }
  572. }
  573. else
  574. {
  575. //
  576. // We only want the first one, so this one will do
  577. //
  578. This->m_pEventHandlerInfo = This->CreateHandlerInfoFromKey(csrHandlerSubKey);
  579. bContinueEnumeration = FALSE;
  580. }
  581. }
  582. }
  583. return bContinueEnumeration;
  584. }