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.

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