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.

1423 lines
36 KiB

  1. #include "regnotif.h"
  2. #include "svcsync.h"
  3. #include "mtpts.h"
  4. #include "vol.h"
  5. #include "namellst.h"
  6. #include "users.h"
  7. #include "sfstr.h"
  8. #include "tfids.h"
  9. #include "dbg.h"
  10. #include <shpriv.h>
  11. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  12. #define MAGICTOKENOFFSET ((DWORD)0x57EF57EF)
  13. LONG CHardwareDevicesImpl::_lAdviseToken = MAGICTOKENOFFSET;
  14. DWORD CHardwareDevicesImpl::_chwdevcb = 0;
  15. #define MAX_ADVISETOKEN 11
  16. #pragma warning(disable: 4700 4701)
  17. HRESULT _VolumeAddedOrUpdatedHelper(IHardwareDeviceCallback* pdevchngcb, CVolume* pvol,
  18. BOOL fAdded)
  19. {
  20. DWORD cchReq;
  21. HRESULT hr;
  22. WCHAR szVolName[MAX_DEVICEID];
  23. WCHAR szVolGUID[50];
  24. WCHAR szLabel[MAX_LABEL];
  25. WCHAR szFileSystem[MAX_FILESYSNAME];
  26. WCHAR szAutorunIconLocation[MAX_ICONLOCATION];
  27. WCHAR szAutorunLabel[MAX_LABEL];
  28. WCHAR szIconLocationFromService[MAX_ICONLOCATION];
  29. WCHAR szNoMediaIconLocationFromService[MAX_ICONLOCATION];
  30. // We can now have a @%SystemRoot%\system32\shell32.dll,-1785 for MUI stuff
  31. WCHAR szLabelFromService[MAX_ICONLOCATION];
  32. VOLUMEINFO volinfo = {0};
  33. ASSERT(pvol);
  34. volinfo.pszDeviceIDVolume = szVolName;
  35. volinfo.pszVolumeGUID = szVolGUID;
  36. volinfo.pszLabel = szLabel;
  37. volinfo.pszFileSystem = szFileSystem;
  38. volinfo.dwState = pvol->_dwState;
  39. hr = pvol->GetName(szVolName, ARRAYSIZE(szVolName), &cchReq);
  40. TRACE(TF_ADVISE,
  41. TEXT("Called _VolumeAddedOrUpdatedHelper for Vol = %s, CB = 0x%08X, Added = %d"),
  42. szVolName, pdevchngcb, fAdded);
  43. if (SUCCEEDED(hr))
  44. {
  45. hr = pvol->GetVolumeConstInfo(szVolGUID,
  46. ARRAYSIZE(szVolGUID), &(volinfo.dwVolumeFlags), &(volinfo.dwDriveType),
  47. &(volinfo.dwDriveCapability));
  48. }
  49. if (SUCCEEDED(hr))
  50. {
  51. hr = pvol->GetVolumeMediaInfo(szLabel, ARRAYSIZE(szLabel),
  52. szFileSystem, ARRAYSIZE(szFileSystem), &(volinfo.dwFileSystemFlags),
  53. &(volinfo.dwMaxFileNameLen), &(volinfo.dwRootAttributes), &(volinfo.dwSerialNumber),
  54. &(volinfo.dwDriveState), &(volinfo.dwMediaState), &(volinfo.dwMediaCap));
  55. }
  56. if (SUCCEEDED(hr))
  57. {
  58. hr = pvol->GetIconAndLabelInfo(szAutorunIconLocation,
  59. ARRAYSIZE(szAutorunIconLocation), szAutorunLabel,
  60. ARRAYSIZE(szAutorunLabel), szIconLocationFromService,
  61. ARRAYSIZE(szIconLocationFromService), szNoMediaIconLocationFromService,
  62. ARRAYSIZE(szNoMediaIconLocationFromService), szLabelFromService,
  63. ARRAYSIZE(szLabelFromService));
  64. if (SUCCEEDED(hr))
  65. {
  66. if (*szAutorunIconLocation)
  67. {
  68. volinfo.pszAutorunIconLocation = szAutorunIconLocation;
  69. }
  70. if (*szAutorunLabel)
  71. {
  72. volinfo.pszAutorunLabel = szAutorunLabel;
  73. }
  74. if (*szIconLocationFromService)
  75. {
  76. volinfo.pszIconLocationFromService = szIconLocationFromService;
  77. }
  78. if (*szNoMediaIconLocationFromService)
  79. {
  80. volinfo.pszNoMediaIconLocationFromService = szNoMediaIconLocationFromService;
  81. }
  82. if (*szLabelFromService)
  83. {
  84. volinfo.pszLabelFromService = szLabelFromService;
  85. }
  86. }
  87. }
  88. if (SUCCEEDED(hr))
  89. {
  90. hr = pdevchngcb->VolumeAddedOrUpdated(fAdded, &volinfo);
  91. }
  92. return hr;
  93. }
  94. #pragma warning(default: 4700 4701)
  95. STDMETHODIMP CHardwareDevicesImpl::EnumVolumes(
  96. DWORD dwFlags, IHardwareDevicesVolumesEnum** ppenum)
  97. {
  98. HRESULT hr;
  99. *ppenum = NULL;
  100. if ((HWDEV_GETCUSTOMPROPERTIES == dwFlags) || (0 == dwFlags))
  101. {
  102. CHardwareDevicesVolumesEnum* phwdve = new CHardwareDevicesVolumesEnum(NULL);
  103. if (phwdve)
  104. {
  105. hr = phwdve->_Init(dwFlags);
  106. if (SUCCEEDED(hr))
  107. {
  108. *ppenum = phwdve;
  109. }
  110. else
  111. {
  112. phwdve->Release();
  113. }
  114. }
  115. else
  116. {
  117. hr = E_OUTOFMEMORY;
  118. }
  119. }
  120. else
  121. {
  122. hr = E_INVALIDARG;
  123. }
  124. ASSERT((*ppenum && SUCCEEDED(hr)) || (!*ppenum && FAILED(hr)));
  125. return hr;
  126. }
  127. STDMETHODIMP CHardwareDevicesImpl::EnumMountPoints(
  128. IHardwareDevicesMountPointsEnum** ppenum)
  129. {
  130. HRESULT hr;
  131. CHardwareDevicesMountPointsEnum* phwdmtpte = new CHardwareDevicesMountPointsEnum(NULL);
  132. *ppenum = NULL;
  133. if (phwdmtpte)
  134. {
  135. hr = phwdmtpte->_Init();
  136. if (SUCCEEDED(hr))
  137. {
  138. *ppenum = phwdmtpte;
  139. }
  140. else
  141. {
  142. phwdmtpte->Release();
  143. }
  144. }
  145. else
  146. {
  147. hr = E_OUTOFMEMORY;
  148. }
  149. ASSERT((*ppenum && SUCCEEDED(hr)) || (!*ppenum && FAILED(hr)));
  150. return hr;
  151. }
  152. STDMETHODIMP CHardwareDevicesImpl::EnumDevices(IHardwareDevicesEnum** /*ppenum*/)
  153. {
  154. return E_NOTIMPL;
  155. }
  156. HRESULT _GetStringAdviseToken(LONG lAdviseToken, LPWSTR szAdviseToken, DWORD cchAdviseToken)
  157. {
  158. HRESULT hr;
  159. if (cchAdviseToken >= MAX_ADVISETOKEN)
  160. {
  161. // 0x12345678
  162. wsprintf(szAdviseToken, TEXT("0x%08X"), lAdviseToken);
  163. hr = S_OK;
  164. }
  165. else
  166. {
  167. hr = E_FAIL;
  168. }
  169. return hr;
  170. }
  171. STDMETHODIMP CHardwareDevicesImpl::Advise(DWORD dwProcessID,
  172. ULONG_PTR hThread, ULONG_PTR pfctCallback, DWORD* pdwToken)
  173. {
  174. HRESULT hr;
  175. TRACE(TF_ADVISE, TEXT(">>>Called ") TEXT(__FUNCTION__) TEXT(", 0x%08X, 0x%08X, 0x%08X"),
  176. dwProcessID, hThread, pfctCallback);
  177. if (dwProcessID && hThread && pfctCallback && pdwToken)
  178. {
  179. LONG lAdviseToken = InterlockedIncrement(&_lAdviseToken);
  180. WCHAR szAdviseToken[MAX_ADVISETOKEN];
  181. hr = _GetStringAdviseToken(lAdviseToken, szAdviseToken,
  182. ARRAYSIZE(szAdviseToken));
  183. if (SUCCEEDED(hr))
  184. {
  185. CNamedElemList* pnel;
  186. hr = CHWEventDetectorHelper::GetList(HWEDLIST_ADVISECLIENT, &pnel);
  187. if (S_OK == hr)
  188. {
  189. CNamedElem* pelem;
  190. hr = pnel->GetOrAdd(szAdviseToken, &pelem);
  191. if (SUCCEEDED(hr))
  192. {
  193. CAdviseClient* pac = (CAdviseClient*)pelem;
  194. hr = pac->_Init(dwProcessID,
  195. hThread, pfctCallback);
  196. if (SUCCEEDED(hr))
  197. {
  198. *pdwToken = lAdviseToken;
  199. }
  200. else
  201. {
  202. pnel->Remove(szAdviseToken);
  203. }
  204. pelem->RCRelease();
  205. }
  206. pnel->RCRelease();
  207. }
  208. }
  209. if (SUCCEEDED(hr))
  210. {
  211. TRACE(TF_ADVISE, TEXT(">>>Advise SUCCEEDED, token = 0x%08X"), lAdviseToken);
  212. }
  213. }
  214. else
  215. {
  216. hr = E_INVALIDARG;
  217. }
  218. if (FAILED(hr))
  219. {
  220. TRACE(TF_ADVISE, TEXT(">>>Advise FAILED"));
  221. }
  222. return hr;
  223. }
  224. STDMETHODIMP CHardwareDevicesImpl::Unadvise(DWORD dwToken)
  225. {
  226. HRESULT hr;
  227. if (dwToken >= (MAGICTOKENOFFSET))
  228. {
  229. WCHAR szAdviseToken[MAX_ADVISETOKEN];
  230. hr = _GetStringAdviseToken(dwToken, szAdviseToken,
  231. ARRAYSIZE(szAdviseToken));
  232. if (SUCCEEDED(hr))
  233. {
  234. CNamedElemList* pnel;
  235. hr = CHWEventDetectorHelper::GetList(HWEDLIST_ADVISECLIENT, &pnel);
  236. if (S_OK == hr)
  237. {
  238. pnel->Remove(szAdviseToken);
  239. pnel->RCRelease();
  240. }
  241. }
  242. }
  243. else
  244. {
  245. hr = E_INVALIDARG;
  246. }
  247. if (SUCCEEDED(hr))
  248. {
  249. TRACE(TF_ADVISE, TEXT(">>>UNAdvise SUCCEEDED, token = 0x%08X"),
  250. dwToken);
  251. }
  252. else
  253. {
  254. TRACE(TF_ADVISE, TEXT(">>>UNAdvise FAILED, token = 0x%08X"),
  255. dwToken);
  256. }
  257. return hr;
  258. }
  259. ///////////////////////////////////////////////////////////////////////////////
  260. //
  261. class CThreadTaskBroadcastEvent : public CThreadTask
  262. {
  263. public:
  264. CThreadTaskBroadcastEvent() : _pshhe(NULL)
  265. {}
  266. virtual ~CThreadTaskBroadcastEvent()
  267. {
  268. if (_pshhe)
  269. {
  270. _FreeMemoryChunk<SHHARDWAREEVENT*>(_pshhe);
  271. }
  272. }
  273. protected:
  274. HRESULT _Broadcast()
  275. {
  276. CNamedElemList* pnel;
  277. HRESULT hr = CHWEventDetectorHelper::GetList(HWEDLIST_ADVISECLIENT, &pnel);
  278. if (S_OK == hr)
  279. {
  280. CNamedElemEnum* penum;
  281. hr = pnel->GetEnum(&penum);
  282. if (SUCCEEDED(hr) && (S_FALSE != hr))
  283. {
  284. CNamedElem* pelem;
  285. while (SUCCEEDED(hr) && SUCCEEDED(hr = penum->Next(&pelem)) &&
  286. (S_FALSE != hr))
  287. {
  288. CAdviseClient* pac = (CAdviseClient*)pelem;
  289. void* pv;
  290. HRESULT hrTmp = pac->WriteMemoryChunkInOtherProcess(_pshhe,
  291. _pshhe->cbSize, &pv);
  292. if (SUCCEEDED(hrTmp))
  293. {
  294. hrTmp = pac->QueueUserAPC(pv);
  295. }
  296. if (FAILED(hrTmp))
  297. {
  298. WCHAR szAdviseToken[MAX_ADVISETOKEN];
  299. DWORD cchReq;
  300. TRACE(TF_ADVISE,
  301. TEXT(__FUNCTION__) TEXT(": Trying to removed token because failed CB, hr = 0x%08X"),
  302. hrTmp);
  303. if (SUCCEEDED(pelem->GetName(szAdviseToken, ARRAYSIZE(szAdviseToken),
  304. &cchReq)))
  305. {
  306. TRACE(TF_ADVISE, TEXT(" ") TEXT(__FUNCTION__) TEXT(": Token = %s"),
  307. szAdviseToken);
  308. pnel->Remove(szAdviseToken);
  309. }
  310. }
  311. pelem->RCRelease();
  312. }
  313. penum->RCRelease();
  314. }
  315. pnel->RCRelease();
  316. }
  317. return hr;
  318. }
  319. protected:
  320. SHHARDWAREEVENT* _pshhe;
  321. };
  322. class CThreadTaskMountPointEvent : public CThreadTaskBroadcastEvent
  323. {
  324. public:
  325. HRESULT InitAdded(LPCWSTR pszMtPt, LPCWSTR pszDeviceIDVolume)
  326. {
  327. ASSERT(!_pshhe);
  328. DWORD cbSize = sizeof(SHHARDWAREEVENT) + sizeof(MTPTADDED);
  329. HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
  330. if (SUCCEEDED(hr))
  331. {
  332. MTPTADDED* pmtptadded = (MTPTADDED*)_pshhe->rgbPayLoad;
  333. _pshhe->cbSize = cbSize;
  334. _pshhe->dwEvent = SHHARDWAREEVENT_MOUNTPOINTARRIVED;
  335. hr = SafeStrCpyN(pmtptadded->szMountPoint, pszMtPt,
  336. ARRAYSIZE(pmtptadded->szMountPoint));
  337. if (SUCCEEDED(hr))
  338. {
  339. hr = SafeStrCpyN(pmtptadded->szDeviceIDVolume, pszDeviceIDVolume,
  340. ARRAYSIZE(pmtptadded->szDeviceIDVolume));
  341. if (SUCCEEDED(hr))
  342. {
  343. // We give the Shell AllowSetForegroundWindow privilege
  344. _GiveAllowForegroundToConsoleShell();
  345. }
  346. }
  347. }
  348. return hr;
  349. }
  350. HRESULT InitRemoved(LPCWSTR pszMtPt)
  351. {
  352. ASSERT(!_pshhe);
  353. DWORD cbSize = sizeof(SHHARDWAREEVENT) + MAX_PATH * sizeof(WCHAR);
  354. HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
  355. if (SUCCEEDED(hr))
  356. {
  357. _pshhe->cbSize = cbSize;
  358. _pshhe->dwEvent = SHHARDWAREEVENT_MOUNTPOINTREMOVED;
  359. hr = SafeStrCpyN((LPWSTR)_pshhe->rgbPayLoad, pszMtPt,
  360. MAX_PATH);
  361. }
  362. return hr;
  363. }
  364. HRESULT _DoStuff()
  365. {
  366. return _Broadcast();
  367. }
  368. };
  369. class CThreadTaskCheckClients : public CThreadTask
  370. {
  371. public:
  372. HRESULT _DoStuff()
  373. {
  374. CNamedElemList* pnel;
  375. //
  376. // Get the list of notify clients.
  377. //
  378. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_ADVISECLIENT, &pnel);
  379. if (S_OK == hres)
  380. {
  381. CNamedElemEnum* penum;
  382. hres = pnel->GetEnum(&penum);
  383. if (SUCCEEDED(hres))
  384. {
  385. CNamedElem* pelem;
  386. //
  387. // Enumerate the advised clients.
  388. //
  389. while (SUCCEEDED(hres = penum->Next(&pelem)) && (S_FALSE != hres))
  390. {
  391. CAdviseClient* pac = (CAdviseClient*)pelem;
  392. //
  393. // Is the process still alive?
  394. //
  395. HRESULT hrTmp = pac->IsProcessStillAlive( );
  396. if (S_OK != hrTmp)
  397. {
  398. WCHAR szAdviseToken[MAX_ADVISETOKEN];
  399. DWORD cchReq;
  400. //
  401. // Nope (or there is some problem with it)... so remove it from the list.
  402. //
  403. TRACE(TF_ADVISE, TEXT(__FUNCTION__) TEXT(": Trying to removed token because process died, pac = %p"), pac);
  404. hrTmp = pelem->GetName(szAdviseToken, ARRAYSIZE(szAdviseToken), &cchReq);
  405. if (SUCCEEDED(hrTmp))
  406. {
  407. TRACE(TF_ADVISE, TEXT(" ") TEXT(__FUNCTION__) TEXT(": Token = %s"), szAdviseToken);
  408. pnel->Remove(szAdviseToken);
  409. }
  410. }
  411. pelem->RCRelease();
  412. }
  413. //
  414. // Reset the HRESULT if it is the expected exit condition.
  415. //
  416. if ( S_FALSE == hres )
  417. {
  418. hres = S_OK;
  419. }
  420. penum->RCRelease();
  421. }
  422. pnel->RCRelease();
  423. }
  424. return hres;
  425. }
  426. };
  427. class CThreadTaskVolumeEvent : public CThreadTaskBroadcastEvent
  428. {
  429. public:
  430. HRESULT InitAdded(VOLUMEINFO2* pvolinfo2, LPCWSTR pszMtPts, DWORD cchMtPts)
  431. {
  432. ASSERT(!_pshhe);
  433. DWORD cbSize = sizeof(SHHARDWAREEVENT) + pvolinfo2->cbSize;
  434. HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
  435. if (SUCCEEDED(hr))
  436. {
  437. _pshhe->cbSize = cbSize;
  438. _pshhe->dwEvent = SHHARDWAREEVENT_VOLUMEARRIVED;
  439. CopyMemory(_pshhe->rgbPayLoad, pvolinfo2, pvolinfo2->cbSize);
  440. _pszDeviceIDVolume = ((VOLUMEINFO2*)_pshhe->rgbPayLoad)->szDeviceIDVolume;
  441. if (SUCCEEDED(hr) && pszMtPts)
  442. {
  443. hr = _DupMemoryChunk<LPCWSTR>(pszMtPts, cchMtPts * sizeof(WCHAR),
  444. &_pszMtPts);
  445. }
  446. }
  447. return hr;
  448. }
  449. HRESULT InitUpdated(VOLUMEINFO2* pvolinfo2)
  450. {
  451. ASSERT(!_pshhe);
  452. DWORD cbSize = sizeof(SHHARDWAREEVENT) + pvolinfo2->cbSize;
  453. HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
  454. if (SUCCEEDED(hr))
  455. {
  456. _pshhe->cbSize = cbSize;
  457. _pshhe->dwEvent = SHHARDWAREEVENT_VOLUMEUPDATED;
  458. CopyMemory(_pshhe->rgbPayLoad, pvolinfo2, pvolinfo2->cbSize);
  459. _pszDeviceIDVolume = ((VOLUMEINFO2*)_pshhe->rgbPayLoad)->szDeviceIDVolume;
  460. // We give the Shell AllowSetForegroundWindow privilege
  461. _GiveAllowForegroundToConsoleShell();
  462. }
  463. return hr;
  464. }
  465. HRESULT InitRemoved(LPCWSTR pszDeviceIDVolume, LPCWSTR pszMtPts, DWORD cchMtPts)
  466. {
  467. ASSERT(!_pshhe);
  468. DWORD cbSize = sizeof(SHHARDWAREEVENT) + MAX_DEVICEID * sizeof(WCHAR);
  469. HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
  470. if (SUCCEEDED(hr))
  471. {
  472. _pshhe->cbSize = cbSize;
  473. _pshhe->dwEvent = SHHARDWAREEVENT_VOLUMEREMOVED;
  474. _pszDeviceIDVolume = ((VOLUMEINFO2*)_pshhe->rgbPayLoad)->szDeviceIDVolume;
  475. hr = SafeStrCpyN((LPWSTR)_pshhe->rgbPayLoad, pszDeviceIDVolume,
  476. MAX_DEVICEID);
  477. if (SUCCEEDED(hr) && pszMtPts)
  478. {
  479. hr = _DupMemoryChunk<LPCWSTR>(pszMtPts, cchMtPts * sizeof(WCHAR),
  480. &_pszMtPts);
  481. }
  482. }
  483. return hr;
  484. }
  485. HRESULT _DoStuff()
  486. {
  487. HRESULT hr;
  488. switch (_pshhe->dwEvent)
  489. {
  490. case SHHARDWAREEVENT_VOLUMEARRIVED:
  491. case SHHARDWAREEVENT_VOLUMEUPDATED:
  492. {
  493. hr = _SendVolumeInfo();
  494. if (SUCCEEDED(hr) && (SHHARDWAREEVENT_VOLUMEARRIVED == _pshhe->dwEvent))
  495. {
  496. // We need to enum the mountpoints too. We were not
  497. // registered to get the notif since this volume was not there
  498. hr = _SendMtPtsInfo();
  499. }
  500. break;
  501. }
  502. case SHHARDWAREEVENT_VOLUMEREMOVED:
  503. {
  504. hr = _SendMtPtsInfo();
  505. if (SUCCEEDED(hr))
  506. {
  507. hr = _SendVolumeInfo();
  508. }
  509. break;
  510. }
  511. default:
  512. {
  513. TRACE(TF_ADVISE, TEXT("DoStuff with unknown SHHARDWAREEVENT_* value"));
  514. hr = E_FAIL;
  515. break;
  516. }
  517. }
  518. return hr;
  519. }
  520. private:
  521. HRESULT _SendMtPtsInfo()
  522. {
  523. if (_pszMtPts)
  524. {
  525. for (LPCWSTR psz = _pszMtPts; *psz; psz += (lstrlen(psz) + 1))
  526. {
  527. CThreadTaskMountPointEvent task;
  528. HRESULT hr;
  529. if (SHHARDWAREEVENT_VOLUMEREMOVED == _pshhe->dwEvent)
  530. {
  531. hr = task.InitRemoved(psz);
  532. }
  533. else
  534. {
  535. hr = task.InitAdded(psz, _pszDeviceIDVolume);
  536. }
  537. if (SUCCEEDED(hr))
  538. {
  539. task.RunSynchronously();
  540. }
  541. }
  542. }
  543. return S_OK;
  544. }
  545. HRESULT _SendVolumeInfo()
  546. {
  547. return _Broadcast();
  548. }
  549. public:
  550. CThreadTaskVolumeEvent() : _pszMtPts(NULL)
  551. {}
  552. ~CThreadTaskVolumeEvent()
  553. {
  554. if (_pszMtPts)
  555. {
  556. _FreeMemoryChunk<LPCWSTR>(_pszMtPts);
  557. }
  558. }
  559. private:
  560. LPCWSTR _pszMtPts;
  561. LPCWSTR _pszDeviceIDVolume;
  562. };
  563. class CThreadTaskGenericEvent : public CThreadTaskBroadcastEvent
  564. {
  565. public:
  566. HRESULT Init(LPCWSTR pszPayload, DWORD dwEvent)
  567. {
  568. ASSERT(!_pshhe);
  569. // maybe use lstrlen()?
  570. DWORD cbSize = (DWORD)(sizeof(SHHARDWAREEVENT) + (pszPayload ? MAX_DEVICEID * sizeof(WCHAR) : 0));
  571. HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
  572. if (SUCCEEDED(hr))
  573. {
  574. LPWSTR pszPayloadLocal = (LPWSTR)_pshhe->rgbPayLoad;
  575. _pshhe->cbSize = cbSize;
  576. _pshhe->dwEvent = dwEvent;
  577. if (pszPayload)
  578. {
  579. hr = SafeStrCpyN(pszPayloadLocal, pszPayload, MAX_DEVICEID);
  580. }
  581. }
  582. return hr;
  583. }
  584. HRESULT _DoStuff()
  585. {
  586. return _Broadcast();
  587. }
  588. };
  589. class CThreadTaskDeviceEvent : public CThreadTaskBroadcastEvent
  590. {
  591. public:
  592. HRESULT Init(LPCWSTR pszDeviceIntfID, GUID* pguidInterface,
  593. DWORD dwDeviceFlags, DWORD dwEvent)
  594. {
  595. ASSERT(!_pshhe);
  596. DWORD cbSize = (DWORD)(sizeof(SHHARDWAREEVENT) + (sizeof(HWDEVICEINFO)));
  597. HRESULT hr = _AllocMemoryChunk<SHHARDWAREEVENT*>(cbSize, &_pshhe);
  598. if (SUCCEEDED(hr))
  599. {
  600. HWDEVICEINFO* phwdevinfo = (HWDEVICEINFO*)_pshhe->rgbPayLoad;
  601. _pshhe->cbSize = cbSize;
  602. _pshhe->dwEvent = dwEvent;
  603. hr = SafeStrCpyN(phwdevinfo->szDeviceIntfID, pszDeviceIntfID,
  604. ARRAYSIZE(phwdevinfo->szDeviceIntfID));
  605. if (SUCCEEDED(hr))
  606. {
  607. phwdevinfo->cbSize = sizeof(*phwdevinfo);
  608. phwdevinfo->guidInterface = *pguidInterface;
  609. phwdevinfo->dwDeviceFlags = dwDeviceFlags;
  610. }
  611. }
  612. return hr;
  613. }
  614. HRESULT _DoStuff()
  615. {
  616. return _Broadcast();
  617. }
  618. };
  619. HRESULT CHardwareDevicesImpl::_AdviseDeviceArrivedOrRemoved(
  620. LPCWSTR pszDeviceIntfID, GUID* pguidInterface, DWORD dwDeviceFlags,
  621. LPCWSTR pszEventType)
  622. {
  623. HRESULT hr;
  624. CThreadTaskDeviceEvent* pTask = new CThreadTaskDeviceEvent();
  625. if (pTask)
  626. {
  627. DWORD dwEvent;
  628. if (!lstrcmpi(pszEventType, TEXT("DeviceArrival")))
  629. {
  630. dwEvent = SHHARDWAREEVENT_DEVICEARRIVED;
  631. }
  632. else
  633. {
  634. dwEvent = SHHARDWAREEVENT_DEVICEREMOVED;
  635. }
  636. hr = pTask->Init(pszDeviceIntfID, pguidInterface, dwDeviceFlags,
  637. dwEvent);
  638. if (SUCCEEDED(hr))
  639. {
  640. pTask->Run();
  641. }
  642. else
  643. {
  644. delete pTask;
  645. }
  646. }
  647. else
  648. {
  649. hr = E_OUTOFMEMORY;
  650. }
  651. return hr;
  652. }
  653. //static
  654. HRESULT CHardwareDevicesImpl::_AdviseVolumeArrivedOrUpdated(
  655. VOLUMEINFO2* pvolinfo2, LPCWSTR pszMtPts, DWORD cchMtPts, BOOL fAdded)
  656. {
  657. HRESULT hr;
  658. TRACE(TF_ADVISE, TEXT(">>>_AdviseVolumeArrivedOrUpdated: fAdded = %d"), fAdded);
  659. CThreadTaskVolumeEvent* pTask = new CThreadTaskVolumeEvent();
  660. if (pTask)
  661. {
  662. if (fAdded)
  663. {
  664. hr = pTask->InitAdded(pvolinfo2, pszMtPts, cchMtPts);
  665. }
  666. else
  667. {
  668. hr = pTask->InitUpdated(pvolinfo2);
  669. }
  670. if (SUCCEEDED(hr))
  671. {
  672. pTask->Run();
  673. }
  674. else
  675. {
  676. delete pTask;
  677. }
  678. }
  679. else
  680. {
  681. hr = E_OUTOFMEMORY;
  682. }
  683. return hr;
  684. }
  685. // static
  686. HRESULT CHardwareDevicesImpl::_AdviseVolumeRemoved(LPCWSTR pszDeviceIDVolume,
  687. LPCWSTR pszMtPts, DWORD cchMtPts)
  688. {
  689. HRESULT hr;
  690. TRACE(TF_ADVISE, TEXT(">>>_AdviseVolumeRemoved"));
  691. CThreadTaskVolumeEvent* pTask = new CThreadTaskVolumeEvent();
  692. if (pTask)
  693. {
  694. hr = pTask->InitRemoved(pszDeviceIDVolume, pszMtPts, cchMtPts);
  695. if (SUCCEEDED(hr))
  696. {
  697. pTask->Run();
  698. }
  699. else
  700. {
  701. delete pTask;
  702. }
  703. }
  704. else
  705. {
  706. hr = E_OUTOFMEMORY;
  707. }
  708. return hr;
  709. }
  710. //static
  711. HRESULT CHardwareDevicesImpl::_AdviseVolumeMountingEvent(
  712. LPCWSTR pszDeviceIDVolume, DWORD dwEvent)
  713. {
  714. TRACE(TF_ADVISE, TEXT(">>>_AdviseVolumeMountingEvent: %s, dwEvent = 0x%08X"),
  715. pszDeviceIDVolume, dwEvent);
  716. HRESULT hr;
  717. CThreadTaskGenericEvent* pTask = new CThreadTaskGenericEvent();
  718. if (pTask)
  719. {
  720. hr = pTask->Init(pszDeviceIDVolume, dwEvent);
  721. if (SUCCEEDED(hr))
  722. {
  723. pTask->Run();
  724. }
  725. else
  726. {
  727. delete pTask;
  728. }
  729. }
  730. else
  731. {
  732. hr = E_OUTOFMEMORY;
  733. }
  734. return hr;
  735. }
  736. //static
  737. HRESULT CHardwareDevicesImpl::_AdviseMountPointHelper(LPCWSTR pszMtPt,
  738. LPCWSTR pszDeviceIDVolume, BOOL fAdded)
  739. {
  740. TRACE(TF_ADVISE, TEXT(">>>_AdviseMountPointHelper: %s, fAdded = %d"),
  741. pszMtPt, fAdded);
  742. HRESULT hr;
  743. CThreadTaskMountPointEvent* pTask = new CThreadTaskMountPointEvent();
  744. if (pTask)
  745. {
  746. if (fAdded)
  747. {
  748. hr = pTask->InitAdded(pszMtPt, pszDeviceIDVolume);
  749. }
  750. else
  751. {
  752. hr = pTask->InitRemoved(pszMtPt);
  753. }
  754. if (SUCCEEDED(hr))
  755. {
  756. pTask->Run();
  757. }
  758. else
  759. {
  760. delete pTask;
  761. }
  762. }
  763. else
  764. {
  765. hr = E_OUTOFMEMORY;
  766. }
  767. return hr;
  768. }
  769. //static
  770. HRESULT CHardwareDevicesImpl::_AdviseCheckClients(void)
  771. {
  772. HRESULT hr;
  773. CThreadTaskCheckClients* pTask = new CThreadTaskCheckClients();
  774. if (pTask)
  775. {
  776. pTask->Run( );
  777. hr = S_OK;
  778. }
  779. else
  780. {
  781. hr = E_OUTOFMEMORY;
  782. }
  783. return hr;
  784. }
  785. ///////////////////////////////////////////////////////////////////////////////
  786. // Impl
  787. CHardwareDevicesImpl::CHardwareDevicesImpl()
  788. {
  789. _CompleteShellHWDetectionInitialization();
  790. }
  791. CHardwareDevicesImpl::~CHardwareDevicesImpl()
  792. {}
  793. ///////////////////////////////////////////////////////////////////////////////
  794. ///////////////////////////////////////////////////////////////////////////////
  795. ///////////////////////////////////////////////////////////////////////////////
  796. //
  797. STDMETHODIMP CHardwareDevicesEnumImpl::Next(
  798. LPWSTR* /*ppszDeviceID*/,
  799. GUID* /*pguidDeviceID*/)
  800. {
  801. return E_NOTIMPL;
  802. }
  803. CHardwareDevicesEnumImpl::CHardwareDevicesEnumImpl()
  804. {}
  805. CHardwareDevicesEnumImpl::~CHardwareDevicesEnumImpl()
  806. {}
  807. ///////////////////////////////////////////////////////////////////////////////
  808. ///////////////////////////////////////////////////////////////////////////////
  809. ///////////////////////////////////////////////////////////////////////////////
  810. //
  811. HRESULT CHardwareDevicesVolumesEnumImpl::_Init(DWORD dwFlags)
  812. {
  813. CNamedElemList* pnel;
  814. HRESULT hr = CHWEventDetectorHelper::GetList(HWEDLIST_VOLUME, &pnel);
  815. _dwFlags = dwFlags;
  816. if (S_OK == hr)
  817. {
  818. hr = pnel->GetEnum(&_penum);
  819. pnel->RCRelease();
  820. }
  821. return hr;
  822. }
  823. STDMETHODIMP CHardwareDevicesVolumesEnumImpl::Next(VOLUMEINFO* pvolinfo)
  824. {
  825. HRESULT hr;
  826. if (pvolinfo)
  827. {
  828. if (_penum)
  829. {
  830. CNamedElem* pelem;
  831. hr = _penum->Next(&pelem);
  832. if (SUCCEEDED(hr) && (S_FALSE != hr))
  833. {
  834. // Const Info
  835. WCHAR szVolName[MAX_DEVICEID];
  836. WCHAR szVolGUID[50];
  837. WCHAR szLabel[MAX_LABEL];
  838. WCHAR szFileSystem[MAX_FILESYSNAME];
  839. WCHAR szAutorunIconLocation[MAX_ICONLOCATION];
  840. WCHAR szAutorunLabel[MAX_LABEL];
  841. WCHAR szIconLocationFromService[MAX_ICONLOCATION];
  842. WCHAR szNoMediaIconLocationFromService[MAX_ICONLOCATION];
  843. // We can now have a @%SystemRoot%\system32\shell32.dll,-1785 for MUI stuff
  844. WCHAR szLabelFromService[MAX_ICONLOCATION];
  845. CVolume* pvol = (CVolume*)pelem;
  846. // Misc
  847. DWORD cchReq;
  848. ZeroMemory(pvolinfo, sizeof(VOLUMEINFO));
  849. hr = pvol->GetName(szVolName, ARRAYSIZE(szVolName), &cchReq);
  850. if (SUCCEEDED(hr))
  851. {
  852. hr = pvol->GetVolumeConstInfo(szVolGUID,
  853. ARRAYSIZE(szVolGUID), &(pvolinfo->dwVolumeFlags),
  854. &(pvolinfo->dwDriveType),
  855. &(pvolinfo->dwDriveCapability));
  856. }
  857. if (SUCCEEDED(hr))
  858. {
  859. hr = pvol->GetVolumeMediaInfo(szLabel, ARRAYSIZE(szLabel),
  860. szFileSystem, ARRAYSIZE(szFileSystem),
  861. &(pvolinfo->dwFileSystemFlags),
  862. &(pvolinfo->dwMaxFileNameLen),
  863. &(pvolinfo->dwRootAttributes),
  864. &(pvolinfo->dwSerialNumber), &(pvolinfo->dwDriveState),
  865. &(pvolinfo->dwMediaState), &(pvolinfo->dwMediaCap));
  866. }
  867. if (SUCCEEDED(hr))
  868. {
  869. if (HWDEV_GETCUSTOMPROPERTIES & _dwFlags)
  870. {
  871. szAutorunIconLocation[0] = 0;
  872. szAutorunLabel[0] = 0;
  873. szIconLocationFromService[0] = 0;
  874. szNoMediaIconLocationFromService[0] = 0;
  875. szLabelFromService[0] = 0;
  876. hr = pvol->GetIconAndLabelInfo(szAutorunIconLocation,
  877. ARRAYSIZE(szAutorunIconLocation), szAutorunLabel,
  878. ARRAYSIZE(szAutorunLabel),
  879. szIconLocationFromService,
  880. ARRAYSIZE(szIconLocationFromService),
  881. szNoMediaIconLocationFromService,
  882. ARRAYSIZE(szNoMediaIconLocationFromService),
  883. szLabelFromService,
  884. ARRAYSIZE(szLabelFromService));
  885. if (SUCCEEDED(hr))
  886. {
  887. if (*szAutorunIconLocation)
  888. {
  889. hr = _CoTaskMemCopy(szAutorunIconLocation,
  890. &(pvolinfo->pszAutorunIconLocation));
  891. }
  892. if (SUCCEEDED(hr) && *szAutorunLabel)
  893. {
  894. hr = _CoTaskMemCopy(szAutorunLabel,
  895. &(pvolinfo->pszAutorunLabel));
  896. }
  897. if (SUCCEEDED(hr) && *szIconLocationFromService)
  898. {
  899. hr = _CoTaskMemCopy(szIconLocationFromService,
  900. &(pvolinfo->pszIconLocationFromService));
  901. }
  902. if (SUCCEEDED(hr) && *szNoMediaIconLocationFromService)
  903. {
  904. hr = _CoTaskMemCopy(szNoMediaIconLocationFromService,
  905. &(pvolinfo->pszNoMediaIconLocationFromService));
  906. }
  907. if (SUCCEEDED(hr) && *szLabelFromService)
  908. {
  909. hr = _CoTaskMemCopy(szLabelFromService,
  910. &(pvolinfo->pszLabelFromService));
  911. }
  912. }
  913. }
  914. }
  915. if (SUCCEEDED(hr))
  916. {
  917. hr = _CoTaskMemCopy(szVolName, &(pvolinfo->pszDeviceIDVolume));
  918. if (SUCCEEDED(hr))
  919. {
  920. hr = _CoTaskMemCopy(szVolGUID, &(pvolinfo->pszVolumeGUID));
  921. }
  922. if (SUCCEEDED(hr))
  923. {
  924. hr = _CoTaskMemCopy(szLabel, &(pvolinfo->pszLabel));
  925. }
  926. if (SUCCEEDED(hr))
  927. {
  928. hr = _CoTaskMemCopy(szFileSystem, &(pvolinfo->pszFileSystem));
  929. }
  930. }
  931. if (FAILED(hr))
  932. {
  933. _CoTaskMemFree(pvolinfo->pszDeviceIDVolume);
  934. _CoTaskMemFree(pvolinfo->pszVolumeGUID);
  935. _CoTaskMemFree(pvolinfo->pszLabel);
  936. _CoTaskMemFree(pvolinfo->pszFileSystem);
  937. _CoTaskMemFree(pvolinfo->pszAutorunIconLocation);
  938. _CoTaskMemFree(pvolinfo->pszAutorunLabel);
  939. _CoTaskMemFree(pvolinfo->pszIconLocationFromService);
  940. _CoTaskMemFree(pvolinfo->pszNoMediaIconLocationFromService);
  941. _CoTaskMemFree(pvolinfo->pszLabelFromService);
  942. ZeroMemory(pvolinfo, sizeof(VOLUMEINFO));
  943. }
  944. pelem->RCRelease();
  945. }
  946. }
  947. else
  948. {
  949. hr = S_FALSE;
  950. }
  951. }
  952. else
  953. {
  954. hr = E_INVALIDARG;
  955. }
  956. return hr;
  957. }
  958. CHardwareDevicesVolumesEnumImpl::CHardwareDevicesVolumesEnumImpl() :
  959. _penum(NULL)
  960. {}
  961. CHardwareDevicesVolumesEnumImpl::~CHardwareDevicesVolumesEnumImpl()
  962. {
  963. if (_penum)
  964. {
  965. _penum->RCRelease();
  966. }
  967. }
  968. ///////////////////////////////////////////////////////////////////////////////
  969. ///////////////////////////////////////////////////////////////////////////////
  970. ///////////////////////////////////////////////////////////////////////////////
  971. //
  972. HRESULT CHardwareDevicesMountPointsEnumImpl::_Init()
  973. {
  974. CNamedElemList* pnel;
  975. HRESULT hr = CHWEventDetectorHelper::GetList(HWEDLIST_MTPT, &pnel);
  976. if (S_OK == hr)
  977. {
  978. hr = pnel->GetEnum(&_penum);
  979. pnel->RCRelease();
  980. }
  981. return hr;
  982. }
  983. STDMETHODIMP CHardwareDevicesMountPointsEnumImpl::Next(
  984. LPWSTR* ppszMountPoint, // "c:\", or "d:\MountFolder\"
  985. LPWSTR* ppszDeviceIDVolume) // \\?\STORAGE#Volume#...{...GUID...}
  986. {
  987. HRESULT hr;
  988. *ppszMountPoint = NULL;
  989. *ppszDeviceIDVolume = NULL;
  990. if (_penum)
  991. {
  992. CNamedElem* pelem;
  993. hr = _penum->Next(&pelem);
  994. if (SUCCEEDED(hr) && (S_FALSE != hr))
  995. {
  996. // Const Info
  997. WCHAR szMtPtName[MAX_PATH];
  998. WCHAR szVolName[MAX_DEVICEID];
  999. CMtPt* pmtpt = (CMtPt*)pelem;
  1000. // Misc
  1001. DWORD cchReq;
  1002. hr = pmtpt->GetName(szMtPtName, ARRAYSIZE(szMtPtName), &cchReq);
  1003. if (SUCCEEDED(hr))
  1004. {
  1005. hr = pmtpt->GetVolumeName(szVolName, ARRAYSIZE(szVolName));
  1006. }
  1007. if (SUCCEEDED(hr))
  1008. {
  1009. hr = _CoTaskMemCopy(szMtPtName, ppszMountPoint);
  1010. if (SUCCEEDED(hr))
  1011. {
  1012. hr = _CoTaskMemCopy(szVolName, ppszDeviceIDVolume);
  1013. }
  1014. else
  1015. {
  1016. CoTaskMemFree(*ppszMountPoint);
  1017. *ppszMountPoint = NULL;
  1018. }
  1019. }
  1020. pelem->RCRelease();
  1021. }
  1022. }
  1023. else
  1024. {
  1025. hr = S_FALSE;
  1026. }
  1027. return hr;
  1028. }
  1029. CHardwareDevicesMountPointsEnumImpl::CHardwareDevicesMountPointsEnumImpl() :
  1030. _penum(NULL)
  1031. {}
  1032. CHardwareDevicesMountPointsEnumImpl::~CHardwareDevicesMountPointsEnumImpl()
  1033. {
  1034. if (_penum)
  1035. {
  1036. _penum->RCRelease();
  1037. }
  1038. }
  1039. ///////////////////////////////////////////////////////////////////////////////
  1040. ///////////////////////////////////////////////////////////////////////////////
  1041. ///////////////////////////////////////////////////////////////////////////////
  1042. HRESULT CAdviseClient::Init(LPCWSTR pszElemName)
  1043. {
  1044. ASSERT(pszElemName);
  1045. return _SetName(pszElemName);
  1046. }
  1047. HRESULT CAdviseClient::_Cleanup()
  1048. {
  1049. if (_hProcess)
  1050. {
  1051. CloseHandle(_hProcess);
  1052. _hProcess = NULL;
  1053. }
  1054. if (_hThread)
  1055. {
  1056. CloseHandle(_hThread);
  1057. _hThread = NULL;
  1058. }
  1059. return S_OK;
  1060. }
  1061. HRESULT CAdviseClient::_Init(DWORD dwProcessID, ULONG_PTR hThread,
  1062. ULONG_PTR pfctCallback)
  1063. {
  1064. HRESULT hr = E_FAIL;
  1065. _Cleanup();
  1066. _pfct = (PAPCFUNC)pfctCallback;
  1067. // rename hProcess!
  1068. _hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | SYNCHRONIZE |
  1069. PROCESS_DUP_HANDLE, FALSE, dwProcessID);
  1070. if (_hProcess)
  1071. {
  1072. if (DuplicateHandle(_hProcess, (HANDLE)hThread,
  1073. GetCurrentProcess(), &_hThread, THREAD_ALL_ACCESS, FALSE, 0))
  1074. {
  1075. hr = S_OK;
  1076. }
  1077. }
  1078. return hr;
  1079. }
  1080. HRESULT CAdviseClient::WriteMemoryChunkInOtherProcess(SHHARDWAREEVENT* pshhe,
  1081. DWORD cbSize, void** ppv)
  1082. {
  1083. HRESULT hr = E_FAIL;
  1084. void* pv = VirtualAllocEx(_hProcess, NULL, cbSize,
  1085. MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
  1086. PAGE_READWRITE);
  1087. *ppv = NULL;
  1088. if (pv)
  1089. {
  1090. SIZE_T cbWritten;
  1091. if (WriteProcessMemory(_hProcess, pv, pshhe, cbSize, &cbWritten)
  1092. && (cbWritten == cbSize))
  1093. {
  1094. *ppv = pv;
  1095. hr = S_OK;
  1096. }
  1097. else
  1098. {
  1099. VirtualFreeEx(_hProcess, pv, 0, MEM_RELEASE);
  1100. }
  1101. }
  1102. else
  1103. {
  1104. // Out of mem, but in the other process...
  1105. hr = E_OUTOFMEMORY;
  1106. }
  1107. return hr;
  1108. }
  1109. HRESULT CAdviseClient::QueueUserAPC(void* pv)
  1110. {
  1111. HRESULT hr;
  1112. if (::QueueUserAPC(_pfct, _hThread, (ULONG_PTR)pv))
  1113. {
  1114. hr = S_OK;
  1115. }
  1116. else
  1117. {
  1118. hr = E_FAIL;
  1119. }
  1120. return hr;
  1121. }
  1122. HRESULT CAdviseClient::IsProcessStillAlive(void)
  1123. {
  1124. HRESULT hr;
  1125. DWORD dwResult = WaitForSingleObject( _hProcess, 0 );
  1126. switch (dwResult)
  1127. {
  1128. case WAIT_OBJECT_0:
  1129. hr = S_FALSE; // process has died.
  1130. break;
  1131. case WAIT_TIMEOUT:
  1132. hr = S_OK; // process is still alive
  1133. break;
  1134. default:
  1135. {
  1136. // problem with handle
  1137. DWORD dwErr = GetLastError( );
  1138. hr = HRESULT_FROM_WIN32( dwErr );
  1139. }
  1140. break;
  1141. }
  1142. return hr;
  1143. }
  1144. CAdviseClient::CAdviseClient() : _hProcess(NULL), _hThread(NULL), _pfct(NULL)
  1145. {}
  1146. CAdviseClient::~CAdviseClient()
  1147. {
  1148. _Cleanup();
  1149. }
  1150. // static
  1151. HRESULT CAdviseClient::Create(CNamedElem** ppelem)
  1152. {
  1153. HRESULT hr = S_OK;
  1154. *ppelem = new CAdviseClient();
  1155. if (!(*ppelem))
  1156. {
  1157. hr = E_OUTOFMEMORY;
  1158. }
  1159. return hr;
  1160. }