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.

542 lines
15 KiB

  1. #include "dtct.h"
  2. #include "fact.h"
  3. #include "vol.h"
  4. #include "hnotif.h"
  5. #include "miscdev.h"
  6. #include "dtctreg.h"
  7. #include "regnotif.h"
  8. #include "cmmn.h"
  9. #include "sfstr.h"
  10. #include "misc.h"
  11. #include "str.h"
  12. #include "dbg.h"
  13. #include "tfids.h"
  14. #include <ioevent.h>
  15. #include <dbt.h>
  16. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  17. ///////////////////////////////////////////////////////////////////////////////
  18. //
  19. HRESULT _HandleDeviceEvent(LPCWSTR pszDeviceIntfID, CHWDeviceInst* phwdevinst,
  20. LPCWSTR pszEventType, BOOL* pfHasHandler)
  21. {
  22. HRESULT hres = _DispatchToHandler(pszDeviceIntfID, phwdevinst,
  23. pszEventType, pfHasHandler);
  24. if (SUCCEEDED(hres))
  25. {
  26. TRACE(TF_SHHWDTCTDTCT, TEXT("_DispatchToHandler SUCCEEDED"));
  27. }
  28. else
  29. {
  30. TRACE(TF_SHHWDTCTDTCT, TEXT("_DispatchToHandler FAILED: 0x%08X"),
  31. hres);
  32. hres = S_FALSE;
  33. }
  34. return hres;
  35. }
  36. // {A5DCBF10-6530-11D2-901F-00C04FB951ED}
  37. const CLSID guidInterfaceUSB =
  38. {0xA5DCBF10, 0x6530, 0x11D2,
  39. {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}};
  40. // {53F5630A-B6BF-11D0-94F2-00A0C91EFB8B}
  41. const CLSID guidInterfacePartition =
  42. {0x53F5630A, 0xB6BF, 0x11D0,
  43. {0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B}};
  44. HRESULT _IsInterfaceInList(const GUID* pguidInterface, const CLSID* rgList[], DWORD cList,
  45. BOOL* pfPresent)
  46. {
  47. *pfPresent = FALSE;
  48. for (DWORD dw = 0; !(*pfPresent) && (dw < cList); ++dw)
  49. {
  50. if (*(rgList[dw]) == *pguidInterface)
  51. {
  52. *pfPresent = TRUE;
  53. }
  54. }
  55. return S_OK;
  56. }
  57. const CLSID* _rgpguidRejectedInterface[] =
  58. {
  59. &guidInterfacePartition,
  60. };
  61. HRESULT _IsInterfaceRejected(GUID* pguidInterface, BOOL* pfRejected)
  62. {
  63. return _IsInterfaceInList(pguidInterface, _rgpguidRejectedInterface,
  64. ARRAYSIZE(_rgpguidRejectedInterface), pfRejected);
  65. }
  66. const CLSID* _rgpguidSpecialInterface[] =
  67. {
  68. &guidInterfaceUSB,
  69. };
  70. HRESULT _IsInterfaceSpecial(GUID* pguidInterface, BOOL* pfSpecial)
  71. {
  72. return _IsInterfaceInList(pguidInterface, _rgpguidSpecialInterface,
  73. ARRAYSIZE(_rgpguidRejectedInterface), pfSpecial);
  74. }
  75. HRESULT _TryAutoplay(LPCWSTR pszDeviceIntfID, CHWDeviceInst* phwdevinst,
  76. DWORD dwEventType)
  77. {
  78. LPCWSTR pszEventType = NULL;
  79. HRESULT hres;
  80. if (DBT_DEVICEARRIVAL == dwEventType)
  81. {
  82. pszEventType = TEXT("DeviceArrival");
  83. }
  84. else
  85. {
  86. if (DBT_DEVICEREMOVECOMPLETE == dwEventType)
  87. {
  88. pszEventType = TEXT("DeviceRemoval");
  89. }
  90. else
  91. {
  92. ASSERT(FALSE);
  93. }
  94. }
  95. if (pszEventType)
  96. {
  97. // Useless in this case
  98. BOOL fHasHandler;
  99. hres = _HandleDeviceEvent(pszDeviceIntfID, phwdevinst,
  100. pszEventType, &fHasHandler);
  101. }
  102. else
  103. {
  104. hres = S_FALSE;
  105. }
  106. return hres;
  107. }
  108. const CLSID* _rgpguidRequiringAdviseInterface[] =
  109. {
  110. &guidInterfaceUSB,
  111. &guidVideoCameraClass,
  112. &guidImagingDeviceClass,
  113. };
  114. HRESULT _IsInterfaceRequiringAdvise(GUID* pguidInterface, BOOL* pfRequiringAdvise)
  115. {
  116. return _IsInterfaceInList(pguidInterface, _rgpguidRequiringAdviseInterface,
  117. ARRAYSIZE(_rgpguidRequiringAdviseInterface), pfRequiringAdvise);
  118. }
  119. // If it's one of the few interfaces requiring advise, or if the device has a
  120. // DeviceHandler we send notifications
  121. HRESULT _AdviseDeviceArrivedOrRemovedHelper(GUID* pguidInterface,
  122. LPCWSTR pszDeviceIntfID, CHWDeviceInst* phwdevinst, DWORD dwEventType)
  123. {
  124. BOOL fAdvise;
  125. HRESULT hr = _IsInterfaceRequiringAdvise(pguidInterface, &fAdvise);
  126. // This should never get here
  127. ASSERT(guidVolumeClass != *pguidInterface);
  128. if (SUCCEEDED(hr))
  129. {
  130. DWORD dwDeviceFlags = HWDDF_HASDEVICEHANDLER_UNDETERMINED;
  131. if (phwdevinst)
  132. {
  133. WCHAR szDeviceHandler[MAX_DEVICEHANDLER];
  134. HRESULT hrTmp = _GetDeviceHandler(phwdevinst, szDeviceHandler,
  135. ARRAYSIZE(szDeviceHandler));
  136. if (SUCCEEDED(hrTmp) && (S_FALSE != hrTmp))
  137. {
  138. fAdvise = TRUE;
  139. dwDeviceFlags &= ~HWDDF_HASDEVICEHANDLER_UNDETERMINED;
  140. dwDeviceFlags |= HWDDF_HASDEVICEHANDLER;
  141. }
  142. }
  143. if (fAdvise)
  144. {
  145. BOOL fRemovableDevice;
  146. LPCWSTR pszDeviceEvent;
  147. if (DBT_DEVICEARRIVAL == dwEventType)
  148. {
  149. pszDeviceEvent = TEXT("DeviceArrival");
  150. }
  151. else
  152. {
  153. ASSERT(DBT_DEVICEREMOVECOMPLETE == dwEventType);
  154. pszDeviceEvent = TEXT("DeviceRemoval");
  155. }
  156. dwDeviceFlags |= HWDDF_REMOVABLEDEVICE_UNDETERMINED;
  157. if (phwdevinst)
  158. {
  159. hr = phwdevinst->IsRemovableDevice(&fRemovableDevice);
  160. if (SUCCEEDED(hr))
  161. {
  162. if (fRemovableDevice)
  163. {
  164. dwDeviceFlags &= ~HWDDF_REMOVABLEDEVICE_UNDETERMINED;
  165. dwDeviceFlags |= HWDDF_REMOVABLEDEVICE;
  166. }
  167. }
  168. }
  169. if (SUCCEEDED(hr))
  170. {
  171. hr = CHardwareDevicesImpl::_AdviseDeviceArrivedOrRemoved(
  172. pszDeviceIntfID, pguidInterface, dwDeviceFlags,
  173. pszDeviceEvent);
  174. }
  175. }
  176. else
  177. {
  178. hr = S_FALSE;
  179. }
  180. }
  181. return hr;
  182. }
  183. HRESULT _ProcessInterface(GUID* pguidInterface, LPCWSTR pszDeviceIntfID,
  184. DWORD dwEventType)
  185. {
  186. CNamedElemList* pnel;
  187. HRESULT hr = CHWEventDetectorHelper::GetList(HWEDLIST_MISCDEVINTF, &pnel);
  188. if (SUCCEEDED(hr))
  189. {
  190. if (DBT_DEVICEARRIVAL == dwEventType)
  191. {
  192. CNamedElem* pelem;
  193. hr = pnel->GetOrAdd(pszDeviceIntfID, &pelem);
  194. if (SUCCEEDED(hr))
  195. {
  196. BOOL fRemoveFromList = TRUE;
  197. CMiscDeviceInterface* pmdi = (CMiscDeviceInterface*)pelem;
  198. // If we're adding it, let's finish its initialization
  199. hr = pmdi->InitInterfaceGUID(pguidInterface);
  200. if (SUCCEEDED(hr))
  201. {
  202. CHWDeviceInst* phwdevinst;
  203. hr = pmdi->GetHWDeviceInst(&phwdevinst);
  204. if (SUCCEEDED(hr) && (S_FALSE != hr))
  205. {
  206. BOOL f;
  207. _AdviseDeviceArrivedOrRemovedHelper(pguidInterface,
  208. pszDeviceIntfID, phwdevinst, dwEventType);
  209. hr = phwdevinst->IsRemovableDevice(&f);
  210. if (SUCCEEDED(hr) & f)
  211. {
  212. hr = _IsInterfaceSpecial(pguidInterface, &f);
  213. if (SUCCEEDED(hr) & f)
  214. {
  215. hr = phwdevinst->ShouldAutoplayOnSpecialInterface(
  216. pguidInterface, &f);
  217. if (FAILED(hr) || (S_FALSE == hr))
  218. {
  219. f = FALSE;
  220. }
  221. }
  222. else
  223. {
  224. f = TRUE;
  225. }
  226. if (f)
  227. {
  228. hr = _TryAutoplay(pszDeviceIntfID, phwdevinst,
  229. dwEventType);
  230. fRemoveFromList = FALSE;
  231. }
  232. }
  233. }
  234. }
  235. if (fRemoveFromList)
  236. {
  237. hr = pnel->Remove(pszDeviceIntfID);
  238. }
  239. pelem->RCRelease();
  240. }
  241. }
  242. else
  243. {
  244. CNamedElem* pelem;
  245. hr = pnel->Get(pszDeviceIntfID, &pelem);
  246. if (SUCCEEDED(hr) && (S_FALSE != hr))
  247. {
  248. CHWDeviceInst* phwdevinst;
  249. CMiscDeviceInterface* pmdi = (CMiscDeviceInterface*)pelem;
  250. hr = pmdi->GetHWDeviceInst(&phwdevinst);
  251. if (SUCCEEDED(hr) && (S_FALSE != hr))
  252. {
  253. _AdviseDeviceArrivedOrRemovedHelper(pguidInterface,
  254. pszDeviceIntfID, phwdevinst, dwEventType);
  255. hr = _TryAutoplay(pszDeviceIntfID, phwdevinst,
  256. dwEventType);
  257. // If we're removing it, let's remove it from the list
  258. HRESULT hr2 = pnel->Remove(pszDeviceIntfID);
  259. hr = FAILED(hr2) ? hr2 : hr;
  260. }
  261. pelem->RCRelease();
  262. }
  263. else
  264. {
  265. _AdviseDeviceArrivedOrRemovedHelper(pguidInterface,
  266. pszDeviceIntfID, NULL, dwEventType);
  267. }
  268. }
  269. pnel->RCRelease();
  270. }
  271. return hr;
  272. }
  273. HRESULT CHWEventDetectorImpl::_HandleInterfaceEvent(
  274. DEV_BROADCAST_DEVICEINTERFACE* pdbdi, DWORD dwEventType)
  275. {
  276. HRESULT hres = S_FALSE;
  277. if (pdbdi->dbcc_name[0])
  278. {
  279. BOOL fSpecialCased;
  280. hres = _IsInterfaceSpecialCased(&(pdbdi->dbcc_classguid),
  281. &fSpecialCased);
  282. if (SUCCEEDED(hres))
  283. {
  284. if (fSpecialCased)
  285. {
  286. TRACE(TF_SHHWDTCTDTCT, TEXT("---> Special case"));
  287. hres = _ProcessInterfaceSpecialCased(&(pdbdi->dbcc_classguid),
  288. pdbdi->dbcc_name, dwEventType);
  289. }
  290. else
  291. {
  292. if ((DBT_DEVICEARRIVAL == dwEventType) ||
  293. (DBT_DEVICEREMOVECOMPLETE == dwEventType))
  294. {
  295. BOOL fRejected;
  296. hres = _IsInterfaceRejected(&(pdbdi->dbcc_classguid),
  297. &fRejected);
  298. if (SUCCEEDED(hres))
  299. {
  300. if (!fRejected)
  301. {
  302. TRACE(TF_SHHWDTCTDTCT, TEXT("---> Regular processing"));
  303. hres = _ProcessInterface(&(pdbdi->dbcc_classguid),
  304. pdbdi->dbcc_name, dwEventType);
  305. }
  306. else
  307. {
  308. TRACE(TF_SHHWDTCTDTCT, TEXT("---> Rejected"));
  309. }
  310. }
  311. }
  312. else
  313. {
  314. TRACE(TF_SHHWDTCTDTCT, TEXT("---> Not deviceArrival/Removal"));
  315. }
  316. }
  317. }
  318. }
  319. else
  320. {
  321. // why do we get this?
  322. }
  323. return hres;
  324. }
  325. // This is for volumes only
  326. // static
  327. HRESULT CHWEventDetectorImpl::HandleVolumeMediaEvent(LPCWSTR pszDeviceIDVolume,
  328. CHWDeviceInst* phwdevinst, LPCWSTR pszEventType,
  329. BOOL* pfHasHandler)
  330. {
  331. return _HandleDeviceEvent(pszDeviceIDVolume, phwdevinst, pszEventType,
  332. pfHasHandler);
  333. }
  334. // This is for volumes only
  335. HRESULT CHWEventDetectorImpl::_HandleBroadcastHandleEvent(
  336. DEV_BROADCAST_HANDLE* pdbh, DWORD dwEventType)
  337. {
  338. HRESULT hres = S_OK;
  339. if (DBT_CUSTOMEVENT == dwEventType)
  340. {
  341. if ((GUID_IO_VOLUME_MOUNT == pdbh->dbch_eventguid) ||
  342. (GUID_IO_VOLUME_DISMOUNT == pdbh->dbch_eventguid) ||
  343. (GUID_IO_VOLUME_DISMOUNT_FAILED == pdbh->dbch_eventguid) ||
  344. (GUID_IO_VOLUME_LOCK == pdbh->dbch_eventguid) ||
  345. (GUID_IO_VOLUME_UNLOCK == pdbh->dbch_eventguid) ||
  346. (GUID_IO_VOLUME_LOCK_FAILED == pdbh->dbch_eventguid) ||
  347. (GUID_IO_MEDIA_ARRIVAL == pdbh->dbch_eventguid) ||
  348. (GUID_IO_MEDIA_REMOVAL == pdbh->dbch_eventguid) ||
  349. (GUID_IO_VOLUME_CHANGE == pdbh->dbch_eventguid) ||
  350. (GUID_IO_VOLUME_NAME_CHANGE == pdbh->dbch_eventguid))
  351. {
  352. hres = CHandleNotif::HandleBroadcastHandleEvent(pdbh, dwEventType);
  353. }
  354. else
  355. {
  356. #ifdef DEBUG
  357. WCHAR szGUID[MAX_GUIDSTRING];
  358. if (SUCCEEDED(_StringFromGUID(&(pdbh->dbch_eventguid), szGUID,
  359. ARRAYSIZE(szGUID))))
  360. {
  361. TRACE(TF_SHHWDTCTDTCT,
  362. TEXT("UNHANDLED! DBT_CUSTOMEVENT + %s for '0x%08X'"),
  363. szGUID, pdbh->dbch_handle);
  364. }
  365. #endif
  366. }
  367. }
  368. else
  369. {
  370. if ((DBT_DEVICEQUERYREMOVE == dwEventType) ||
  371. (DBT_DEVICEREMOVEPENDING == dwEventType) ||
  372. (DBT_DEVICEQUERYREMOVEFAILED == dwEventType) ||
  373. (DBT_DEVICEREMOVECOMPLETE == dwEventType))
  374. {
  375. hres = CHandleNotif::HandleBroadcastHandleEvent(pdbh, dwEventType);
  376. }
  377. }
  378. return hres;
  379. }
  380. ///////////////////////////////////////////////////////////////////////////////
  381. //
  382. HRESULT CHWEventDetectorImpl::_RegisterForNotif()
  383. {
  384. HRESULT hres = CHWEventDetectorHelper::CreateLists();
  385. if (SUCCEEDED(hres))
  386. {
  387. hres = CHWEventDetectorHelper::FillLists();
  388. if (SUCCEEDED(hres))
  389. {
  390. // Register for all Device Interface Events
  391. DEV_BROADCAST_DEVICEINTERFACE dbdNotifFilter = {0};
  392. dbdNotifFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
  393. dbdNotifFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  394. dbdNotifFilter.dbcc_classguid = guidInvalid;
  395. hres = CHWEventDetectorHelper::RegisterDeviceNotification(
  396. &dbdNotifFilter, &_hdevnotifyAllInterfaces, TRUE);
  397. }
  398. }
  399. return hres;
  400. }
  401. HRESULT CHWEventDetectorImpl::_UnregisterForNotif()
  402. {
  403. CHWEventDetectorHelper::EmptyLists();
  404. UnregisterDeviceNotification(_hdevnotifyAllInterfaces);
  405. return S_OK;
  406. }
  407. ///////////////////////////////////////////////////////////////////////////////
  408. //
  409. HRESULT CHWEventDetectorImpl::_RegisterFactories()
  410. {
  411. // TRUE: we want it to stay around
  412. HRESULT hres = (CCOMBaseFactory::_RegisterFactories(TRUE) ? S_OK : E_FAIL);
  413. TRACE(TF_COMSERVER, TEXT("CHWEventDetectorImpl::_RegisterFactories returns: 0x%08X"), hres);
  414. return hres;
  415. }
  416. HRESULT CHWEventDetectorImpl::_UnregisterFactories()
  417. {
  418. // TRUE: we wanted it to stay around
  419. HRESULT hres = (CCOMBaseFactory::_UnregisterFactories(TRUE) ? S_OK : E_FAIL);
  420. TRACE(TF_COMSERVER, TEXT("CHWEventDetectorImpl::_UnregisterFactories returns: 0x%08X"), hres);
  421. return hres;
  422. }
  423. HRESULT CHWEventDetectorImpl::_SuspendFactories()
  424. {
  425. HRESULT hres = (CCOMBaseFactory::_SuspendFactories() ? S_OK : E_FAIL);
  426. TRACE(TF_COMSERVER, TEXT("CHWEventDetectorImpl::_SuspendFactories returns: 0x%08X"), hres);
  427. return hres;
  428. }
  429. HRESULT CHWEventDetectorImpl::_ResumeFactories()
  430. {
  431. HRESULT hres = (CCOMBaseFactory::_ResumeFactories() ? S_OK : E_FAIL);
  432. TRACE(TF_COMSERVER, TEXT("CHWEventDetectorImpl::_ResumeFactories returns: 0x%08X"), hres);
  433. return hres;
  434. }
  435. ///////////////////////////////////////////////////////////////////////////////
  436. //
  437. CHWEventDetectorImpl::CHWEventDetectorImpl() : _hEventRelinquishControl(NULL),
  438. _hdevnotifyAllInterfaces(NULL), _hEventInitCompleted(NULL)
  439. {}
  440. CHWEventDetectorImpl::~CHWEventDetectorImpl()
  441. {}