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.

866 lines
24 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #undef ASSERT
  5. #include "dtct.h"
  6. #include "hwdev.h"
  7. #include "dtctreg.h"
  8. #include "users.h"
  9. #include "cmmn.h"
  10. #include "sfstr.h"
  11. #include "reg.h"
  12. #include "misc.h"
  13. #include "dbg.h"
  14. #include "tfids.h"
  15. #include <shpriv.h>
  16. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  17. // {C1FB73D0-EC3A-4ba2-B512-8CDB9187B6D1}
  18. const CLSID IID_IHWEventHandler =
  19. {0xC1FB73D0, 0xEC3A, 0x4ba2,
  20. {0xB5, 0x12, 0x8C, 0xDB, 0x91, 0x87, 0xB6, 0xD1}};
  21. ///////////////////////////////////////////////////////////////////////////////
  22. //
  23. HRESULT _CreateAndInitEventHandler(LPCWSTR pszHandler, CLSID* pclsid,
  24. IHWEventHandler** ppihweh)
  25. {
  26. IHWEventHandler* pihweh;
  27. HRESULT hres = _CoCreateInstanceInConsoleSession(*pclsid, NULL,
  28. CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IHWEventHandler, &pihweh));
  29. *ppihweh = NULL;
  30. if (SUCCEEDED(hres))
  31. {
  32. LPWSTR pszInitCmdLine;
  33. hres = _GetInitCmdLine(pszHandler, &pszInitCmdLine);
  34. if (SUCCEEDED(hres))
  35. {
  36. if (S_FALSE == hres)
  37. {
  38. ASSERT(!pszInitCmdLine);
  39. hres = pihweh->Initialize(TEXT(""));
  40. }
  41. else
  42. {
  43. hres = pihweh->Initialize(pszInitCmdLine);
  44. }
  45. if (SUCCEEDED(hres))
  46. {
  47. *ppihweh = pihweh;
  48. }
  49. if (pszInitCmdLine)
  50. {
  51. LocalFree((HLOCAL)pszInitCmdLine);
  52. }
  53. }
  54. if (FAILED(hres))
  55. {
  56. pihweh->Release();
  57. *ppihweh = NULL;
  58. }
  59. }
  60. return hres;
  61. }
  62. struct EXECUTEHANDLERDATA
  63. {
  64. CLSID clsidHandler;
  65. LPWSTR pszDeviceIDForAutoplay;
  66. LPWSTR pszEventType;
  67. union
  68. {
  69. LPWSTR pszHandler;
  70. LPWSTR pszInitCmdLine;
  71. };
  72. };
  73. HRESULT _CreateExecuteHandlerData(EXECUTEHANDLERDATA** ppehd)
  74. {
  75. HRESULT hres;
  76. *ppehd = (EXECUTEHANDLERDATA*)LocalAlloc(LPTR, sizeof(EXECUTEHANDLERDATA));
  77. if (*ppehd)
  78. {
  79. hres = S_OK;
  80. }
  81. else
  82. {
  83. hres = E_OUTOFMEMORY;
  84. }
  85. return hres;
  86. }
  87. HRESULT _FreeEHDStrings(EXECUTEHANDLERDATA* pehd)
  88. {
  89. if (pehd->pszHandler)
  90. {
  91. LocalFree((HLOCAL)pehd->pszHandler);
  92. pehd->pszHandler = NULL;
  93. }
  94. if (pehd->pszDeviceIDForAutoplay)
  95. {
  96. LocalFree((HLOCAL)pehd->pszDeviceIDForAutoplay);
  97. pehd->pszDeviceIDForAutoplay = NULL;
  98. }
  99. if (pehd->pszEventType)
  100. {
  101. LocalFree((HLOCAL)pehd->pszEventType);
  102. pehd->pszEventType = NULL;
  103. }
  104. return S_OK;
  105. }
  106. HRESULT _FreeExecuteHandlerData(EXECUTEHANDLERDATA* pehd)
  107. {
  108. _FreeEHDStrings(pehd);
  109. LocalFree((HLOCAL)pehd);
  110. return S_OK;
  111. }
  112. HRESULT _SetExecuteHandlerData(EXECUTEHANDLERDATA* pehd,
  113. LPCWSTR pszDeviceIDForAutoplay, LPCWSTR pszEventType,
  114. LPCWSTR pszHandlerOrInitCmdLine, const CLSID* pclsidHandler)
  115. {
  116. HRESULT hres = DupString(pszHandlerOrInitCmdLine, &(pehd->pszHandler));
  117. if (SUCCEEDED(hres))
  118. {
  119. hres = DupString(pszDeviceIDForAutoplay,
  120. &(pehd->pszDeviceIDForAutoplay));
  121. if (SUCCEEDED(hres))
  122. {
  123. hres = DupString(pszEventType, &(pehd->pszEventType));
  124. if (SUCCEEDED(hres))
  125. {
  126. pehd->clsidHandler = *pclsidHandler;
  127. }
  128. }
  129. }
  130. if (FAILED(hres))
  131. {
  132. // Free everything
  133. _FreeEHDStrings(pehd);
  134. }
  135. return hres;
  136. }
  137. DWORD WINAPI _ExecuteHandlerThreadProc(void* pv)
  138. {
  139. EXECUTEHANDLERDATA* pehd = (EXECUTEHANDLERDATA*)pv;
  140. IHWEventHandler* pihweh;
  141. DIAGNOSTIC((TEXT("[0100]Attempting to execute handler for: %s %s %s"),
  142. pehd->pszDeviceIDForAutoplay, pehd->pszEventType,
  143. pehd->pszHandler));
  144. TRACE(TF_SHHWDTCTDTCT,
  145. TEXT("_ExecuteHandlerThreadProc for: %s %s %s"),
  146. pehd->pszDeviceIDForAutoplay, pehd->pszEventType,
  147. pehd->pszHandler);
  148. HRESULT hres = _CreateAndInitEventHandler(pehd->pszHandler,
  149. &(pehd->clsidHandler), &pihweh);
  150. if (SUCCEEDED(hres) && (S_FALSE != hres))
  151. {
  152. WCHAR szDeviceIDAlt[MAX_PATH];
  153. DIAGNOSTIC((TEXT("[0101]Got Handler Interface")));
  154. TRACE(TF_SHHWDTCTDTCT, TEXT("Got Handler Interface"));
  155. hres = _GetAltDeviceID(pehd->pszDeviceIDForAutoplay, szDeviceIDAlt,
  156. ARRAYSIZE(szDeviceIDAlt));
  157. if (S_FALSE == hres)
  158. {
  159. szDeviceIDAlt[0] = 0;
  160. }
  161. if (SUCCEEDED(hres))
  162. {
  163. hres = pihweh->HandleEvent(pehd->pszDeviceIDForAutoplay,
  164. szDeviceIDAlt, pehd->pszEventType);
  165. DIAGNOSTIC((TEXT("[0103]IHWEventHandler::HandleEvent returned: hr = 0x%08X"), hres));
  166. TRACE(TF_SHHWDTCTDTCT,
  167. TEXT("pIEventHandler->HandleEvent result: 0x%08X"), hres);
  168. }
  169. pihweh->Release();
  170. }
  171. else
  172. {
  173. DIAGNOSTIC((TEXT("[0102]Did not get Handler Interface: hr = 0x%08X"), hres));
  174. TRACE(TF_SHHWDTCTDTCT,
  175. TEXT("Did not get Handler Interface: 0x%08X"), hres);
  176. }
  177. _FreeExecuteHandlerData(pehd);
  178. TRACE(TF_SHHWDTCTDTCT, TEXT("Exiting _ExecuteHandlerThreadProc"));
  179. return (DWORD)hres;
  180. }
  181. HRESULT _DelegateToExecuteHandlerThread(EXECUTEHANDLERDATA* pehd,
  182. LPTHREAD_START_ROUTINE pThreadProc, HANDLE* phThread)
  183. {
  184. HRESULT hres;
  185. // set thread stack size?
  186. *phThread = CreateThread(NULL, 0, pThreadProc, pehd, 0, NULL);
  187. if (*phThread)
  188. {
  189. hres = S_OK;
  190. }
  191. else
  192. {
  193. hres = E_FAIL;
  194. }
  195. return hres;
  196. }
  197. HRESULT _ExecuteHandlerHelper(LPCWSTR pszDeviceIDForAutoplay,
  198. LPCWSTR pszEventType,
  199. LPCWSTR pszHandlerOrInitCmdLine, LPTHREAD_START_ROUTINE pThreadProc,
  200. const CLSID* pclsidHandler, HANDLE* phThread)
  201. {
  202. // Let's prepare to delegate to other thread
  203. EXECUTEHANDLERDATA* pehd;
  204. HRESULT hres = _CreateExecuteHandlerData(&pehd);
  205. *phThread = NULL;
  206. if (SUCCEEDED(hres))
  207. {
  208. hres = _SetExecuteHandlerData(pehd, pszDeviceIDForAutoplay,
  209. pszEventType, pszHandlerOrInitCmdLine,
  210. pclsidHandler);
  211. if (SUCCEEDED(hres))
  212. {
  213. hres = _DelegateToExecuteHandlerThread(pehd,
  214. pThreadProc, phThread);
  215. }
  216. if (FAILED(hres))
  217. {
  218. _FreeExecuteHandlerData(pehd);
  219. }
  220. }
  221. return hres;
  222. }
  223. HRESULT _ExecuteHandler(LPCWSTR pszDeviceIDForAutoplay, LPCWSTR pszEventType,
  224. LPCWSTR pszHandler)
  225. {
  226. CLSID clsidHandler;
  227. HRESULT hres = _GetHandlerCLSID(pszHandler, &clsidHandler);
  228. if (SUCCEEDED(hres) && (S_FALSE != hres))
  229. {
  230. HANDLE hThread;
  231. hres = _ExecuteHandlerHelper(pszDeviceIDForAutoplay, pszEventType,
  232. pszHandler, _ExecuteHandlerThreadProc,
  233. &clsidHandler, &hThread);
  234. if (SUCCEEDED(hres))
  235. {
  236. CloseHandle(hThread);
  237. }
  238. }
  239. return hres;
  240. }
  241. ///////////////////////////////////////////////////////////////////////////////
  242. //
  243. DWORD WINAPI _PromptUserThreadProc(void* pv)
  244. {
  245. IHWEventHandler* pihweh;
  246. EXECUTEHANDLERDATA* pehd = (EXECUTEHANDLERDATA*)pv;
  247. DIAGNOSTIC((TEXT("[0110]Will prompt user for preferences")));
  248. TRACE(TF_SHHWDTCTDTCT, TEXT("Entered _PromptUserThreadProc"));
  249. HRESULT hr = _CoCreateInstanceInConsoleSession(pehd->clsidHandler, NULL,
  250. CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IHWEventHandler, &pihweh));
  251. if (SUCCEEDED(hr))
  252. {
  253. hr = pihweh->Initialize(pehd->pszInitCmdLine);
  254. if (SUCCEEDED(hr))
  255. {
  256. WCHAR szDeviceIDAlt[MAX_PATH];
  257. TRACE(TF_SHHWDTCTDTCT, TEXT("Got Handler Interface"));
  258. hr = _GetAltDeviceID(pehd->pszDeviceIDForAutoplay, szDeviceIDAlt,
  259. ARRAYSIZE(szDeviceIDAlt));
  260. if (S_FALSE == hr)
  261. {
  262. szDeviceIDAlt[0] = 0;
  263. }
  264. if (SUCCEEDED(hr))
  265. {
  266. hr = pihweh->HandleEvent(pehd->pszDeviceIDForAutoplay,
  267. szDeviceIDAlt, pehd->pszEventType);
  268. }
  269. }
  270. pihweh->Release();
  271. }
  272. _FreeExecuteHandlerData(pehd);
  273. TRACE(TF_SHHWDTCTDTCT, TEXT("Exiting _PromptUserThreadProc"));
  274. return (DWORD)hr;
  275. }
  276. HRESULT _PromptUser(LPCWSTR pszDeviceIDForAutoplay, LPCWSTR pszEventType,
  277. LPCWSTR pszInitCmdLine)
  278. {
  279. HANDLE hThread;
  280. HRESULT hr = _ExecuteHandlerHelper(pszDeviceIDForAutoplay, pszEventType,
  281. pszInitCmdLine, _PromptUserThreadProc,
  282. &CLSID_ShellAutoplay, &hThread);
  283. if (SUCCEEDED(hr))
  284. {
  285. CloseHandle(hThread);
  286. }
  287. return hr;
  288. }
  289. ///////////////////////////////////////////////////////////////////////////////
  290. //
  291. struct QUERYRUNNINGOBJECTSTRUCT
  292. {
  293. IHWEventHandler* phweh;
  294. WCHAR szDeviceIntfID[MAX_DEVICEID];
  295. WCHAR szEventType[MAX_EVENTTYPE];
  296. };
  297. DWORD WINAPI _QueryRunningObjectThreadProc(void* pv)
  298. {
  299. QUERYRUNNINGOBJECTSTRUCT* pqro = (QUERYRUNNINGOBJECTSTRUCT*)pv;
  300. HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
  301. if (SUCCEEDED(hr))
  302. {
  303. hr = pqro->phweh->HandleEvent(pqro->szDeviceIntfID, TEXT(""), pqro->szEventType);
  304. CoUninitialize();
  305. }
  306. pqro->phweh->Release();
  307. LocalFree((HLOCAL)pqro);
  308. return (DWORD)hr;
  309. }
  310. HRESULT _QueryRunningObject(IHWEventHandler* phweh, LPCWSTR pszDeviceIntfID,
  311. LPCWSTR pszEventType, LPCWSTR pszHandler, BOOL* pfHandlesEvent)
  312. {
  313. HRESULT hr;
  314. QUERYRUNNINGOBJECTSTRUCT* pqro = (QUERYRUNNINGOBJECTSTRUCT*)LocalAlloc(LPTR,
  315. sizeof(QUERYRUNNINGOBJECTSTRUCT));
  316. *pfHandlesEvent = FALSE;
  317. if (pqro)
  318. {
  319. phweh->AddRef();
  320. pqro->phweh = phweh;
  321. hr = SafeStrCpyN(pqro->szDeviceIntfID, pszDeviceIntfID,
  322. ARRAYSIZE(pqro->szDeviceIntfID));
  323. if (SUCCEEDED(hr))
  324. {
  325. hr = SafeStrCpyN(pqro->szEventType, pszEventType,
  326. ARRAYSIZE(pqro->szEventType));
  327. }
  328. if (SUCCEEDED(hr))
  329. {
  330. HANDLE hThread = CreateThread(NULL, 0, _QueryRunningObjectThreadProc, pqro,
  331. 0, NULL);
  332. if (hThread)
  333. {
  334. // Wait 3 sec to see if wants to process it. If not, it's
  335. // fair play for us.
  336. DWORD dwWait = WaitForSingleObject(hThread, 3000);
  337. if (WAIT_OBJECT_0 == dwWait)
  338. {
  339. // Return within time and did not failed
  340. DWORD dwExitCode;
  341. if (GetExitCodeThread(hThread, &dwExitCode))
  342. {
  343. HRESULT hrHandlesEvent = (HRESULT)dwExitCode;
  344. // WIA will return S_FALSE if they do NOT want to process
  345. // the event
  346. if (SUCCEEDED(hrHandlesEvent) && (S_FALSE != hrHandlesEvent))
  347. {
  348. DIAGNOSTIC((TEXT("[0124]Already running handler will handle event (%s)"), pszHandler));
  349. TRACE(TF_WIA,
  350. TEXT("Already running handler will handle event"));
  351. *pfHandlesEvent = TRUE;
  352. }
  353. else
  354. {
  355. DIAGNOSTIC((TEXT("[0125]Already running handler will *NOT* handle event(%s)"), pszHandler));
  356. TRACE(TF_WIA,
  357. TEXT("WIA.HandleEventOverride will NOT Handle Event"));
  358. }
  359. hr = S_OK;
  360. }
  361. else
  362. {
  363. hr = S_FALSE;
  364. }
  365. }
  366. else
  367. {
  368. if (WAIT_TIMEOUT == dwWait)
  369. {
  370. DIAGNOSTIC((TEXT("[0126]Timed out on already running handler ( > 3 sec)")));
  371. TRACE(TF_WIA,
  372. TEXT("Timed out waiting on already running object (%s)"), pszHandler);
  373. }
  374. hr = S_FALSE;
  375. }
  376. CloseHandle(hThread);
  377. }
  378. else
  379. {
  380. hr = E_OUTOFMEMORY;
  381. }
  382. }
  383. if (FAILED(hr))
  384. {
  385. pqro->phweh->Release();
  386. LocalFree((HLOCAL)pqro);
  387. }
  388. }
  389. else
  390. {
  391. hr = E_OUTOFMEMORY;
  392. }
  393. return hr;
  394. }
  395. HRESULT _FindAlreadyRunningHandler(LPCWSTR pszDeviceIntfID,
  396. LPCWSTR pszEventType, LPCWSTR pszEventHandler, BOOL* pfHandlesEvent)
  397. {
  398. CImpersonateConsoleSessionUser icsu;
  399. HRESULT hr = icsu.Impersonate();
  400. if (SUCCEEDED(hr) && (S_FALSE != hr))
  401. {
  402. IBindCtx* pbindctx;
  403. hr = CreateBindCtx(0, &pbindctx);
  404. *pfHandlesEvent = FALSE;
  405. if (SUCCEEDED(hr))
  406. {
  407. IRunningObjectTable* prot;
  408. hr = pbindctx->GetRunningObjectTable(&prot);
  409. if (SUCCEEDED(hr))
  410. {
  411. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("EventHandlers\\"));
  412. hr = SafeStrCatN(szKeyName, pszEventHandler, ARRAYSIZE(szKeyName));
  413. if (SUCCEEDED(hr))
  414. {
  415. HKEY hkey;
  416. hr = _RegOpenKey(HKEY_LOCAL_MACHINE, szKeyName, &hkey);
  417. if (SUCCEEDED(hr) && (S_FALSE != hr))
  418. {
  419. WCHAR szHandler[MAX_HANDLER];
  420. DWORD dwIndex = 0;
  421. while (!*pfHandlesEvent && SUCCEEDED(hr) &&
  422. SUCCEEDED(hr = _RegEnumStringValue(hkey, dwIndex,
  423. szHandler, ARRAYSIZE(szHandler))) &&
  424. (S_FALSE != hr))
  425. {
  426. CLSID clsid;
  427. hr = _GetHandlerCancelCLSID(szHandler, &clsid);
  428. if (SUCCEEDED(hr) && (S_FALSE != hr))
  429. {
  430. IMoniker* pmoniker;
  431. hr = _BuildMoniker(pszEventHandler, clsid,
  432. (USER_SHARED_DATA->ActiveConsoleId), &pmoniker);
  433. if (SUCCEEDED(hr))
  434. {
  435. IUnknown* punk;
  436. hr = prot->GetObject(pmoniker, &punk);
  437. if (SUCCEEDED(hr) && (S_FALSE != hr))
  438. {
  439. IHWEventHandler* phweh;
  440. hr = punk->QueryInterface(
  441. IID_IHWEventHandler, (void**)&phweh);
  442. if (SUCCEEDED(hr))
  443. {
  444. hr = _QueryRunningObject(phweh,
  445. pszDeviceIntfID, pszEventType,
  446. szHandler, pfHandlesEvent);
  447. phweh->Release();
  448. }
  449. punk->Release();
  450. }
  451. else
  452. {
  453. // if it can't find it, it return s failure
  454. hr = S_FALSE;
  455. }
  456. pmoniker->Release();
  457. }
  458. }
  459. ++dwIndex;
  460. }
  461. _RegCloseKey(hkey);
  462. }
  463. }
  464. prot->Release();
  465. }
  466. pbindctx->Release();
  467. }
  468. icsu.RevertToSelf();
  469. }
  470. return hr;
  471. }
  472. HRESULT _FinalDispatch(LPCWSTR pszDeviceIntfID, LPCWSTR pszEventType,
  473. LPCWSTR pszEventHandler)
  474. {
  475. DIAGNOSTIC((TEXT("[0111]Looking for already running handler for: %s, %s, %s"),
  476. pszDeviceIntfID, pszEventType, pszEventHandler));
  477. BOOL fHandlesEvent;
  478. HRESULT hres = _FindAlreadyRunningHandler(pszDeviceIntfID, pszEventType,
  479. pszEventHandler, &fHandlesEvent);
  480. if (SUCCEEDED(hres) && !fHandlesEvent)
  481. {
  482. WCHAR szHandler[MAX_HANDLER];
  483. hres = _GetUserDefaultHandler(pszDeviceIntfID, pszEventHandler,
  484. szHandler, ARRAYSIZE(szHandler), GUH_USEWINSTA0USER);
  485. if (SUCCEEDED(hres) && (S_FALSE != hres))
  486. {
  487. // We have a handler
  488. TRACE(TF_SHHWDTCTDTCT, TEXT("Found Handler: %s"), szHandler);
  489. BOOL fPrompt = FALSE;
  490. BOOL fCheckAlwaysDoThis = FALSE;
  491. BOOL fExecuteHandler = FALSE;
  492. if (HANDLERDEFAULT_GETFLAGS(hres) &
  493. HANDLERDEFAULT_USERCHOSENDEFAULT)
  494. {
  495. // We have a user chosen default...
  496. if (HANDLERDEFAULT_GETFLAGS(hres) &
  497. HANDLERDEFAULT_MORERECENTHANDLERSINSTALLED)
  498. {
  499. // ... but we have more recent apps that were installed
  500. fPrompt = TRUE;
  501. }
  502. else
  503. {
  504. if (lstrcmp(szHandler, TEXT("MSTakeNoAction")))
  505. {
  506. // The handler is *not* "Take no action"
  507. if (!lstrcmp(szHandler, TEXT("MSPromptEachTime")))
  508. {
  509. // The handler is "Prompt each time"
  510. fPrompt = TRUE;
  511. }
  512. else
  513. {
  514. fExecuteHandler = TRUE;
  515. }
  516. }
  517. }
  518. }
  519. else
  520. {
  521. // If we do not have a user chosen handler, then we always
  522. // prompt
  523. fPrompt = TRUE;
  524. }
  525. if (fPrompt)
  526. {
  527. if (HANDLERDEFAULT_GETFLAGS(hres) &
  528. HANDLERDEFAULT_MORERECENTHANDLERSINSTALLED)
  529. {
  530. // There are more recent handlers
  531. if (HANDLERDEFAULT_GETFLAGS(hres) &
  532. HANDLERDEFAULT_USERCHOSENDEFAULT)
  533. {
  534. // The user chose a default handler
  535. if (!(HANDLERDEFAULT_GETFLAGS(hres) &
  536. HANDLERDEFAULT_DEFAULTSAREDIFFERENT))
  537. {
  538. // The handlers are the same, check the checkbox
  539. fCheckAlwaysDoThis = TRUE;
  540. }
  541. }
  542. }
  543. _GiveAllowForegroundToConsoleShell();
  544. if (fCheckAlwaysDoThis)
  545. {
  546. // Notice the '*' at the end of the string
  547. hres = _PromptUser(pszDeviceIntfID, pszEventType,
  548. TEXT("PromptEachTimeNoContent*"));
  549. }
  550. else
  551. {
  552. hres = _PromptUser(pszDeviceIntfID, pszEventType,
  553. TEXT("PromptEachTimeNoContent"));
  554. }
  555. }
  556. else
  557. {
  558. if (fExecuteHandler)
  559. {
  560. hres = _ExecuteHandler(pszDeviceIntfID, pszEventType,
  561. szHandler);
  562. }
  563. }
  564. }
  565. }
  566. return hres;
  567. }
  568. ///////////////////////////////////////////////////////////////////////////////
  569. //
  570. HRESULT _IsWIAHandlingEvent(LPCWSTR pszDeviceIDForAutoplay,
  571. LPCWSTR pszEventType, BOOL* pfWIAHandlingEvent)
  572. {
  573. CLSID clsid = {0};
  574. HRESULT hr = CLSIDFromProgID(TEXT("WIA.HandleEventOverride"), &clsid);
  575. *pfWIAHandlingEvent = FALSE;
  576. if (SUCCEEDED(hr))
  577. {
  578. HANDLE hThread;
  579. hr = _ExecuteHandlerHelper(pszDeviceIDForAutoplay, pszEventType,
  580. TEXT(""), _ExecuteHandlerThreadProc, &clsid, &hThread);
  581. if (SUCCEEDED(hr))
  582. {
  583. // Wait 3 sec to see if WIA wants to process it. If not, it's
  584. // fair play for us.
  585. DWORD dwWait = WaitForSingleObject(hThread, 3000);
  586. if (WAIT_OBJECT_0 == dwWait)
  587. {
  588. // Return within time and did not failed
  589. DWORD dwExitCode;
  590. if (GetExitCodeThread(hThread, &dwExitCode))
  591. {
  592. HRESULT hrWIA = (HRESULT)dwExitCode;
  593. // WIA will return S_FALSE if they do NOT want to process
  594. // the event
  595. if (SUCCEEDED(hrWIA) && (S_FALSE != hrWIA))
  596. {
  597. DIAGNOSTIC((TEXT("[0114]WIA will handle event")));
  598. TRACE(TF_WIA,
  599. TEXT("WIA.HandleEventOverride will Handle Event"));
  600. *pfWIAHandlingEvent = TRUE;
  601. }
  602. else
  603. {
  604. TRACE(TF_WIA,
  605. TEXT("WIA.HandleEventOverride will NOT Handle Event"));
  606. }
  607. }
  608. }
  609. else
  610. {
  611. if (WAIT_TIMEOUT == dwWait)
  612. {
  613. TRACE(TF_WIA,
  614. TEXT("Timed out waiting on WIA.HandleEventOverride"));
  615. }
  616. }
  617. CloseHandle(hThread);
  618. }
  619. else
  620. {
  621. TRACE(TF_WIA,
  622. TEXT("_ExecuteHandlerHelper failed for WIA.HandleEventOverride"));
  623. }
  624. }
  625. else
  626. {
  627. TRACE(TF_WIA,
  628. TEXT("Could not get CLSID for WIA.HandleEventOverride"));
  629. }
  630. return hr;
  631. }
  632. HRESULT _DispatchToHandler(LPCWSTR pszDeviceIntfID, CHWDeviceInst* phwdevinst,
  633. LPCWSTR pszEventType, BOOL* pfHasHandler)
  634. {
  635. WCHAR szDeviceHandler[MAX_DEVICEHANDLER];
  636. HRESULT hres = _GetDeviceHandler(phwdevinst, szDeviceHandler,
  637. ARRAYSIZE(szDeviceHandler));
  638. *pfHasHandler = FALSE;
  639. if (SUCCEEDED(hres) && (S_FALSE != hres))
  640. {
  641. WCHAR szEventHandler[MAX_EVENTHANDLER];
  642. DIAGNOSTIC((TEXT("[0115]Found DeviceHandler: %s"), szDeviceHandler));
  643. TRACE(TF_SHHWDTCTDTCT,
  644. TEXT("Found Device Handler: %s"), szDeviceHandler);
  645. if (SUCCEEDED(hres))
  646. {
  647. DIAGNOSTIC((TEXT("[0117]Device does NOT Support Content")));
  648. TRACE(TF_SHHWDTCTDTCT, TEXT("Device does NOT Support Content"));
  649. BOOL fWIAHandlingEvent = FALSE;
  650. GUID guidInterface;
  651. HRESULT hres2 = phwdevinst->GetInterfaceGUID(&guidInterface);
  652. if (SUCCEEDED(hres2))
  653. {
  654. if ((guidInterface == guidImagingDeviceClass) ||
  655. (guidInterface == guidVideoCameraClass))
  656. {
  657. _IsWIAHandlingEvent(pszDeviceIntfID, pszEventType,
  658. &fWIAHandlingEvent);
  659. }
  660. }
  661. if (!fWIAHandlingEvent)
  662. {
  663. hres = _GetEventHandlerFromDeviceHandler(szDeviceHandler,
  664. pszEventType, szEventHandler, ARRAYSIZE(szEventHandler));
  665. if (SUCCEEDED(hres))
  666. {
  667. if (S_FALSE != hres)
  668. {
  669. *pfHasHandler = TRUE;
  670. hres = _FinalDispatch(pszDeviceIntfID, pszEventType,
  671. szEventHandler);
  672. TRACE(TF_SHHWDTCTDTCTDETAILED,
  673. TEXT(" _GetEventHandlerFromDeviceHandler returned: %s"),
  674. szEventHandler);
  675. }
  676. }
  677. }
  678. else
  679. {
  680. DIAGNOSTIC((TEXT("[0123]WIA will handle event")));
  681. TRACE(TF_SHHWDTCTDTCTDETAILED, TEXT(" WIA will handle event"));
  682. }
  683. }
  684. }
  685. else
  686. {
  687. DIAGNOSTIC((TEXT("[0112]Did NOT find DeviceHandler: 0x%08X"), hres));
  688. TRACE(TF_SHHWDTCTDTCT, TEXT("Did not find Device Handler: 0x%08X"),
  689. hres);
  690. }
  691. return hres;
  692. }