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.

1652 lines
43 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include "mtpt.h"
  4. #include "mtptl.h"
  5. #include "mtptr.h"
  6. #include "hwcmmn.h"
  7. #include "clsobj.h"
  8. #include <cfgmgr32.h>
  9. HDPA CMountPoint::_hdpaMountPoints = NULL;
  10. HDPA CMountPoint::_hdpaVolumes = NULL;
  11. HDPA CMountPoint::_hdpaShares = NULL;
  12. CMtPtLocal* CMountPoint::_rgMtPtDriveLetterLocal[26] = {0};
  13. CMtPtRemote* CMountPoint::_rgMtPtDriveLetterNet[26] = {0};
  14. CCriticalSection CMountPoint::_csLocalMtPtHDPA;
  15. CCriticalSection CMountPoint::_csDL;
  16. BOOL CMountPoint::_fShuttingDown = FALSE;
  17. BOOL CMountPoint::_fNetDrivesInited = FALSE;
  18. BOOL CMountPoint::_fLocalDrivesInited = FALSE;
  19. BOOL CMountPoint::_fNoVolLocalDrivesInited = FALSE;
  20. DWORD CMountPoint::_dwTickCountTriedAndFailed = 0;
  21. DWORD CMountPoint::_dwAdviseToken = -1;
  22. BOOL CMountPoint::_fCanRegisterWithShellService = FALSE;
  23. CRegSupport CMountPoint::_rsMtPtsLocalDL;
  24. CRegSupport CMountPoint::_rsMtPtsLocalMOF;
  25. CRegSupport CMountPoint::_rsMtPtsRemote;
  26. DWORD CMountPoint::_dwRemoteDriveAutorun = 0;
  27. static WCHAR g_szCrossProcessCacheMtPtsLocalDLKey[] = TEXT("CPC\\LocalDL");
  28. static WCHAR g_szCrossProcessCacheMtPtsRemoteKey[] = TEXT("CPC\\Remote");
  29. static WCHAR g_szCrossProcessCacheMtPtsLocalMOFKey[] = TEXT("CPC\\LocalMOF");
  30. HANDLE CMountPoint::_hThreadSCN = NULL;
  31. DWORD CMountPoint::_dwRememberedNetDrivesMask = 0;
  32. ///////////////////////////////////////////////////////////////////////////////
  33. // Public
  34. ///////////////////////////////////////////////////////////////////////////////
  35. //static
  36. CMountPoint* CMountPoint::GetMountPoint(int iDrive, BOOL fCreateNew,
  37. BOOL fOKToHitNet)
  38. {
  39. CMountPoint* pMtPt = NULL;
  40. if (iDrive >= 0 && iDrive < 26)
  41. {
  42. _csDL.Enter();
  43. if (!_fShuttingDown)
  44. {
  45. pMtPt = _GetMountPointDL(iDrive, fCreateNew);
  46. }
  47. _csDL.Leave();
  48. }
  49. else
  50. {
  51. TraceMsg(TF_MOUNTPOINT,
  52. "CMountPoint::GetMountPoint: Requested invalid mtpt '%d'",
  53. iDrive);
  54. }
  55. return pMtPt;
  56. }
  57. //static
  58. CMountPoint* CMountPoint::GetMountPoint(LPCTSTR pszName, BOOL fCreateNew)
  59. {
  60. CMountPoint* pMtPt = NULL;
  61. // Sometimes we receive an empty string (go figure)
  62. // Check '\' for UNC and \\?\VolumeGUID which we do not support
  63. // (they're not mountpoints)
  64. if (pszName && *pszName && (TEXT('\\') != *pszName))
  65. {
  66. if (InRange(*pszName , TEXT('a'), TEXT('z')) ||
  67. InRange(*pszName , TEXT('A'), TEXT('Z')))
  68. {
  69. _csDL.Enter();
  70. if (!_fShuttingDown)
  71. {
  72. if (!_IsDriveLetter(pszName))
  73. {
  74. BOOL fNetDrive = _IsNetDriveLazyLoadNetDLLs(DRIVEID(pszName));
  75. if (!fNetDrive)
  76. {
  77. TCHAR szClosestMtPt[MAX_PATH];
  78. if (_StripToClosestMountPoint(pszName, szClosestMtPt,
  79. ARRAYSIZE(szClosestMtPt)))
  80. {
  81. if (!_IsDriveLetter(szClosestMtPt))
  82. {
  83. pMtPt = _GetStoredMtPtMOF(szClosestMtPt);
  84. }
  85. else
  86. {
  87. pMtPt = _GetMountPointDL(DRIVEID(pszName), fCreateNew);
  88. }
  89. }
  90. }
  91. else
  92. {
  93. // Net drives can only be mounted on drive letter
  94. pMtPt = _GetMountPointDL(DRIVEID(pszName), fCreateNew);
  95. }
  96. }
  97. else
  98. {
  99. pMtPt = _GetMountPointDL(DRIVEID(pszName), fCreateNew);
  100. }
  101. }
  102. _csDL.Leave();
  103. }
  104. else
  105. {
  106. TraceMsg(TF_MOUNTPOINT,
  107. "CMountPoint::GetMountPoint: Requested invalid mtpt '%s'",
  108. pszName);
  109. }
  110. }
  111. else
  112. {
  113. TraceMsg(TF_MOUNTPOINT, "CMountPoint::GetMountPoint: Requested invalid mtpt '%s'",
  114. pszName);
  115. }
  116. return pMtPt;
  117. }
  118. //static
  119. CMountPoint* CMountPoint::GetSimulatedMountPointFromVolumeGuid(LPCTSTR pszVolumeGuid)
  120. {
  121. CMountPoint* pMtPt = NULL;
  122. static const TCHAR szWackWackVolume[] = TEXT("\\\\?\\Volume");
  123. // Check for "\\?\Volume"
  124. if (pszVolumeGuid && 0 == lstrncmp( pszVolumeGuid, szWackWackVolume, ARRAYSIZE(szWackWackVolume) - sizeof("") ) )
  125. {
  126. _csDL.Enter();
  127. CMtPtLocal::_CreateMtPtLocalFromVolumeGuid( pszVolumeGuid, &pMtPt );
  128. if ( !pMtPt )
  129. {
  130. TraceMsg(TF_MOUNTPOINT, "CMountPoint::GetMountPoint: Out of memory" );
  131. }
  132. _csDL.Leave();
  133. }
  134. else
  135. {
  136. TraceMsg(TF_MOUNTPOINT, "CMountPoint::GetSimulatedMountPointFromVolumeGuid: Request is not a volume guid '%ws'",
  137. pszVolumeGuid);
  138. }
  139. return pMtPt;
  140. }
  141. // static
  142. BOOL CMountPoint::_LocalDriveIsCoveredByNetDrive(LPCWSTR pszDriveLetter)
  143. {
  144. BOOL fCovered = FALSE;
  145. CMountPoint* pmtpt = GetMountPoint(DRIVEID(pszDriveLetter), FALSE, FALSE);
  146. if (pmtpt)
  147. {
  148. if (pmtpt->_IsRemote())
  149. {
  150. fCovered = TRUE;
  151. }
  152. pmtpt->Release();
  153. }
  154. return fCovered;
  155. }
  156. ///////////////////////////////////////////////////////////////////////////////
  157. // Private
  158. ///////////////////////////////////////////////////////////////////////////////
  159. // pszSource must be a path including a trailing backslash
  160. // if returns TRUE, then pszDest contains the path to the closest MountPoint
  161. //static
  162. BOOL CMountPoint::_StripToClosestMountPoint(LPCTSTR pszSource, LPTSTR pszDest,
  163. DWORD cchDest)
  164. {
  165. BOOL fFound = GetVolumePathName(pszSource, pszDest, cchDest);
  166. if (fFound)
  167. {
  168. PathAddBackslash(pszDest);
  169. }
  170. return fFound;
  171. }
  172. ///////////////////////////////////////////////////////////////////////////////
  173. // Drive letter: DL
  174. ///////////////////////////////////////////////////////////////////////////////
  175. //static
  176. CMountPoint* CMountPoint::_GetMountPointDL(int iDrive, BOOL fCreateNew)
  177. {
  178. ASSERT(_csDL.IsInside());
  179. CMountPoint* pmtpt = NULL;
  180. // Determine if it's a net drive
  181. BOOL fNetDrive = _IsNetDriveLazyLoadNetDLLs(iDrive);
  182. if (fNetDrive)
  183. {
  184. if (!_fNetDrivesInited)
  185. {
  186. _InitNetDrives();
  187. }
  188. pmtpt = _rgMtPtDriveLetterNet[iDrive];
  189. }
  190. else
  191. {
  192. if (!_fLocalDrivesInited)
  193. {
  194. _InitLocalDrives();
  195. }
  196. pmtpt = _rgMtPtDriveLetterLocal[iDrive];
  197. if (!_Shell32LoadedInDesktop())
  198. {
  199. DWORD dwAllDrives = GetLogicalDrives();
  200. if (pmtpt)
  201. {
  202. // make sure it still exist
  203. if (!(dwAllDrives & (1 << iDrive)))
  204. {
  205. // its' gone!
  206. _rgMtPtDriveLetterLocal[iDrive]->Release();
  207. _rgMtPtDriveLetterLocal[iDrive] = NULL;
  208. pmtpt = NULL;
  209. }
  210. if (pmtpt && (pmtpt->_NeedToRefresh()))
  211. {
  212. CVolume* pvol;
  213. HRESULT hr;
  214. WCHAR szMountPoint[4];
  215. _rgMtPtDriveLetterLocal[iDrive]->Release();
  216. _rgMtPtDriveLetterLocal[iDrive] = NULL;
  217. PathBuildRoot(szMountPoint, iDrive);
  218. pvol = CMtPtLocal::_GetVolumeByMtPt(szMountPoint);
  219. if (pvol)
  220. {
  221. hr = CMtPtLocal::_CreateMtPtLocalWithVolume(szMountPoint,
  222. pvol);
  223. pvol->Release();
  224. }
  225. else
  226. {
  227. hr = CMtPtLocal::_CreateMtPtLocal(szMountPoint);
  228. }
  229. if (SUCCEEDED(hr))
  230. {
  231. pmtpt = _rgMtPtDriveLetterLocal[iDrive];
  232. }
  233. else
  234. {
  235. pmtpt = NULL;
  236. }
  237. }
  238. }
  239. else
  240. {
  241. // maybe it arrived after we enumerated
  242. if (dwAllDrives & (1 << iDrive))
  243. {
  244. WCHAR szMtPt[4];
  245. // Is it a non-net drive?
  246. UINT uDriveType = GetDriveType(PathBuildRoot(szMtPt, iDrive));
  247. if ((DRIVE_FIXED == uDriveType) || (DRIVE_CDROM == uDriveType) ||
  248. (DRIVE_REMOVABLE == uDriveType) || (DRIVE_RAMDISK == uDriveType))
  249. {
  250. // indeed
  251. CVolume* pvolNew;
  252. HRESULT hrTmp = CMtPtLocal::_CreateVolumeFromReg(szMtPt, &pvolNew);
  253. if (SUCCEEDED(hrTmp))
  254. {
  255. CMtPtLocal::_CreateMtPtLocalWithVolume(szMtPt, pvolNew);
  256. pvolNew->Release();
  257. }
  258. else
  259. {
  260. CMtPtLocal::_CreateMtPtLocal(szMtPt);
  261. }
  262. pmtpt = _rgMtPtDriveLetterNet[iDrive];
  263. }
  264. }
  265. }
  266. }
  267. }
  268. if (pmtpt)
  269. {
  270. pmtpt->AddRef();
  271. }
  272. return pmtpt;
  273. }
  274. ///////////////////////////////////////////////////////////////////////////////
  275. // Mounted On Folder: MOF
  276. ///////////////////////////////////////////////////////////////////////////////
  277. //static
  278. CMtPtLocal* CMountPoint::_GetStoredMtPtMOFFromHDPA(LPTSTR pszPathWithBackslash)
  279. {
  280. CMtPtLocal* pmtptl = NULL;
  281. if (_hdpaMountPoints)
  282. {
  283. int n = DPA_GetPtrCount(_hdpaMountPoints);
  284. for (int i = 0; i < n; ++i)
  285. {
  286. pmtptl = (CMtPtLocal*)DPA_GetPtr(_hdpaMountPoints, i);
  287. if (pmtptl)
  288. {
  289. if (!lstrcmpi(pmtptl->_GetName(), pszPathWithBackslash))
  290. {
  291. break;
  292. }
  293. else
  294. {
  295. pmtptl = NULL;
  296. }
  297. }
  298. }
  299. }
  300. return pmtptl;
  301. }
  302. //static
  303. CMtPtLocal* CMountPoint::_GetStoredMtPtMOF(LPTSTR pszPathWithBackslash)
  304. {
  305. ASSERT(_csDL.IsInside());
  306. _csLocalMtPtHDPA.Enter();
  307. if (!_fLocalDrivesInited)
  308. {
  309. _InitLocalDrives();
  310. }
  311. CMtPtLocal* pmtptl = _GetStoredMtPtMOFFromHDPA(pszPathWithBackslash);
  312. if (!_Shell32LoadedInDesktop())
  313. {
  314. BOOL fExist = _CheckLocalMtPtsMOF(pszPathWithBackslash);
  315. if (pmtptl)
  316. {
  317. if (fExist)
  318. {
  319. if (pmtptl->_NeedToRefresh())
  320. {
  321. CVolume* pvol = CMtPtLocal::_GetVolumeByMtPt(pszPathWithBackslash);
  322. pmtptl = NULL;
  323. if (pvol)
  324. {
  325. HRESULT hr = CMtPtLocal::_CreateMtPtLocalWithVolume(
  326. pszPathWithBackslash, pvol);
  327. if (SUCCEEDED(hr))
  328. {
  329. pmtptl = _GetStoredMtPtMOFFromHDPA(pszPathWithBackslash);
  330. }
  331. pvol->Release();
  332. }
  333. else
  334. {
  335. // if we can't get a volume, we don't care about drive mounted on folder
  336. }
  337. }
  338. }
  339. else
  340. {
  341. // its' gone!
  342. _RemoveLocalMountPoint(pszPathWithBackslash);
  343. pmtptl = NULL;
  344. }
  345. }
  346. else
  347. {
  348. // maybe it arrived after we enumerated
  349. if (fExist)
  350. {
  351. CVolume* pvolNew;
  352. HRESULT hrTmp = CMtPtLocal::_CreateVolumeFromReg(pszPathWithBackslash,
  353. &pvolNew);
  354. if (SUCCEEDED(hrTmp))
  355. {
  356. hrTmp = CMtPtLocal::_CreateMtPtLocalWithVolume(pszPathWithBackslash, pvolNew);
  357. if (SUCCEEDED(hrTmp))
  358. {
  359. pmtptl = _GetStoredMtPtMOFFromHDPA(pszPathWithBackslash);
  360. }
  361. pvolNew->Release();
  362. }
  363. else
  364. {
  365. // if we can't get a volume, we don't care about drive mounted on folder
  366. }
  367. }
  368. }
  369. }
  370. if (pmtptl)
  371. {
  372. pmtptl->AddRef();
  373. }
  374. _csLocalMtPtHDPA.Leave();
  375. return pmtptl;
  376. }
  377. //static
  378. BOOL CMountPoint::_StoreMtPtMOF(CMtPtLocal* pmtptl)
  379. {
  380. HRESULT hr;
  381. _csLocalMtPtHDPA.Enter();
  382. if (!_hdpaMountPoints && !_fShuttingDown)
  383. {
  384. _hdpaMountPoints = DPA_Create(2);
  385. }
  386. if (_hdpaMountPoints)
  387. {
  388. if (-1 == DPA_AppendPtr(_hdpaMountPoints, pmtptl))
  389. {
  390. hr = E_OUTOFMEMORY;
  391. }
  392. else
  393. {
  394. hr = S_OK;
  395. }
  396. }
  397. else
  398. {
  399. hr = E_OUTOFMEMORY;
  400. }
  401. _csLocalMtPtHDPA.Leave();
  402. return hr;
  403. }
  404. //static
  405. BOOL CMountPoint::_IsDriveLetter(LPCTSTR pszName)
  406. {
  407. // Is this a drive mounted on a drive letter only (e.g. 'a:' or 'a:\')?
  408. return (!pszName[2] || !pszName[3]);
  409. }
  410. ///////////////////////////////////////////////////////////////////////////////
  411. //
  412. ///////////////////////////////////////////////////////////////////////////////
  413. //static
  414. HRESULT CMountPoint::_InitNetDrivesHelper(DWORD dwScope)
  415. {
  416. HRESULT hr = S_FALSE;
  417. HANDLE hEnum;
  418. DWORD dwErr = WNetOpenEnum(dwScope, RESOURCETYPE_DISK, 0, NULL, &hEnum);
  419. if (WN_SUCCESS == dwErr)
  420. {
  421. DWORD cbBuf = 4096 * 4; // Recommended size from docs
  422. PBYTE pbBuf = (PBYTE)LocalAlloc(LPTR, cbBuf);
  423. if (pbBuf)
  424. {
  425. // return as many entries as possible
  426. DWORD dwEntries = (DWORD)-1;
  427. dwErr = WNetEnumResource(hEnum, &dwEntries, pbBuf, &cbBuf);
  428. if (dwErr == ERROR_MORE_DATA)
  429. {
  430. if (pbBuf)
  431. {
  432. LocalFree(pbBuf);
  433. }
  434. // cbBuf contains required size
  435. pbBuf = (PBYTE)LocalAlloc(LPTR, cbBuf);
  436. if (pbBuf)
  437. {
  438. dwErr = WNetEnumResource(hEnum, &dwEntries, pbBuf, &cbBuf);
  439. }
  440. else
  441. {
  442. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  443. }
  444. }
  445. if (dwErr == WN_SUCCESS)
  446. {
  447. UINT i;
  448. NETRESOURCE* pnr = (NETRESOURCE*)pbBuf;
  449. for (i = 0; SUCCEEDED(hr) && (i < dwEntries); ++i)
  450. {
  451. // Is it mapped or just net used
  452. if (pnr->lpLocalName)
  453. {
  454. // Remembered drives and connected drives list overlaps
  455. if (!_rgMtPtDriveLetterNet[DRIVEID(pnr->lpLocalName)])
  456. {
  457. hr = CMtPtRemote::_CreateMtPtRemote(pnr->lpLocalName,
  458. pnr->lpRemoteName,
  459. (dwScope == RESOURCE_CONNECTED));
  460. if (RESOURCE_REMEMBERED == dwScope)
  461. {
  462. _dwRememberedNetDrivesMask |= (1 << DRIVEID(pnr->lpLocalName));
  463. }
  464. }
  465. }
  466. pnr++;
  467. }
  468. }
  469. if (pbBuf)
  470. {
  471. LocalFree(pbBuf);
  472. }
  473. }
  474. WNetCloseEnum(hEnum);
  475. }
  476. return hr;
  477. }
  478. //static
  479. HRESULT CMountPoint::_ReInitNetDrives()
  480. {
  481. ASSERT(_csDL.IsInside());
  482. CMtPtRemote::_DeleteAllMtPtsAndShares();
  483. _fNetDrivesInited = FALSE;
  484. CMountPoint::_InitNetDrives();
  485. return S_OK;
  486. }
  487. //static
  488. HRESULT CMountPoint::_InitNetDrives()
  489. {
  490. ASSERT(_csDL.IsInside());
  491. HRESULT hr;
  492. if (!_fNetDrivesInited)
  493. {
  494. if (!_fShuttingDown)
  495. {
  496. if (!_hdpaShares)
  497. {
  498. _hdpaShares = DPA_Create(3);
  499. }
  500. }
  501. if (_hdpaShares)
  502. {
  503. hr = _InitNetDrivesHelper(RESOURCE_CONNECTED);
  504. if (SUCCEEDED(hr))
  505. {
  506. hr = _InitNetDrivesHelper(RESOURCE_REMEMBERED);
  507. }
  508. if (SUCCEEDED(hr))
  509. {
  510. DWORD dwLogicalDrives = GetLogicalDrives();
  511. for (DWORD dw = 0; dw < 26; ++dw)
  512. {
  513. if (dwLogicalDrives & (1 << dw))
  514. {
  515. if (!(_rgMtPtDriveLetterNet[dw]))
  516. {
  517. WCHAR szDrive[4];
  518. PathBuildRoot(szDrive, dw);
  519. if (DRIVE_REMOTE == GetDriveType(szDrive))
  520. {
  521. // This must be a weird System mapped drive
  522. // which is not enumerated by the per-user
  523. // WNetEnumResource...
  524. hr = CMtPtRemote::_CreateMtPtRemoteWithoutShareName(szDrive);
  525. }
  526. }
  527. }
  528. }
  529. _fNetDrivesInited = TRUE;
  530. }
  531. }
  532. else
  533. {
  534. hr = E_OUTOFMEMORY;
  535. }
  536. }
  537. else
  538. {
  539. hr = S_FALSE;
  540. }
  541. if (_Shell32LoadedInDesktop())
  542. {
  543. DWORD dwRemoteDrives = 0;
  544. for (DWORD dw = 0; dw < 26; ++dw)
  545. {
  546. if (_rgMtPtDriveLetterNet[dw])
  547. {
  548. dwRemoteDrives |= (1 << dw);
  549. }
  550. }
  551. }
  552. return hr;
  553. }
  554. inline void _CoTaskMemFree(void* pv)
  555. {
  556. if (pv)
  557. {
  558. CoTaskMemFree(pv);
  559. }
  560. }
  561. const GUID guidVolumeClass =
  562. {0x53f5630d, 0xb6bf, 0x11d0,
  563. {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  564. //static
  565. HRESULT CMountPoint::_EnumVolumes(IHardwareDevices* pihwdevs)
  566. {
  567. ASSERT(_csDL.IsInside());
  568. HRESULT hr;
  569. if (_Shell32LoadedInDesktop())
  570. {
  571. // Synchro
  572. IHardwareDevicesVolumesEnum* penum;
  573. hr = pihwdevs->EnumVolumes(HWDEV_GETCUSTOMPROPERTIES, &penum);
  574. ASSERTMSG(NULL != _hdpaVolumes, "_hdpaVolumes should not be NULL at this point, some code found its way here without calling InitLocalDrives");
  575. if (SUCCEEDED(hr))
  576. {
  577. do
  578. {
  579. VOLUMEINFO volinfo;
  580. hr = penum->Next(&volinfo);
  581. if (SUCCEEDED(hr) && (S_FALSE != hr))
  582. {
  583. CVolume* pvolNew;
  584. if (SUCCEEDED(CMtPtLocal::_CreateVolume(&volinfo, &pvolNew)))
  585. {
  586. CMtPtLocal::_UpdateVolumeRegInfo(&volinfo);
  587. pvolNew->Release();
  588. }
  589. CoTaskMemFree(volinfo.pszDeviceIDVolume);
  590. CoTaskMemFree(volinfo.pszVolumeGUID);
  591. CoTaskMemFree(volinfo.pszLabel);
  592. CoTaskMemFree(volinfo.pszFileSystem);
  593. CoTaskMemFree(volinfo.pszAutorunIconLocation);
  594. CoTaskMemFree(volinfo.pszAutorunLabel);
  595. CoTaskMemFree(volinfo.pszIconLocationFromService);
  596. CoTaskMemFree(volinfo.pszNoMediaIconLocationFromService);
  597. CoTaskMemFree(volinfo.pszLabelFromService);
  598. }
  599. }
  600. while (SUCCEEDED(hr) && (S_FALSE != hr));
  601. penum->Release();
  602. }
  603. }
  604. else
  605. {
  606. ULONG ulSize;
  607. ULONG ulFlags = CM_GET_DEVICE_INTERFACE_LIST_PRESENT;
  608. CONFIGRET cr = CM_Get_Device_Interface_List_Size_Ex(&ulSize,
  609. (GUID*)&guidVolumeClass, NULL, ulFlags, NULL);
  610. if ((CR_SUCCESS == cr) && (ulSize > 1))
  611. {
  612. LPWSTR pszVolumes = (LPWSTR)LocalAlloc(LPTR, ulSize * sizeof(WCHAR));
  613. if (pszVolumes)
  614. {
  615. cr = CM_Get_Device_Interface_List_Ex((GUID*)&guidVolumeClass,
  616. NULL, pszVolumes, ulSize, ulFlags, NULL);
  617. if (CR_SUCCESS == cr)
  618. {
  619. for (LPWSTR psz = pszVolumes; *psz; psz += lstrlen(psz) + 1)
  620. {
  621. CVolume* pvolNew;
  622. HRESULT hrTmp = CMtPtLocal::_CreateVolumeFromReg(psz,
  623. &pvolNew);
  624. if (SUCCEEDED(hrTmp))
  625. {
  626. pvolNew->Release();
  627. }
  628. }
  629. hr = S_OK;
  630. }
  631. else
  632. {
  633. hr = S_FALSE;
  634. }
  635. LocalFree(pszVolumes);
  636. }
  637. else
  638. {
  639. hr = E_OUTOFMEMORY;
  640. }
  641. }
  642. else
  643. {
  644. hr = S_FALSE;
  645. }
  646. }
  647. return hr;
  648. }
  649. //static
  650. HRESULT CMountPoint::_EnumMountPoints(IHardwareDevices* pihwdevs)
  651. {
  652. ASSERT(_csDL.IsInside());
  653. HRESULT hr;
  654. if (_Shell32LoadedInDesktop())
  655. {
  656. IHardwareDevicesMountPointsEnum* penum;
  657. hr = pihwdevs->EnumMountPoints(&penum);
  658. if (SUCCEEDED(hr))
  659. {
  660. LPWSTR pszMountPoint;
  661. LPWSTR pszDeviceIDVolume;
  662. while (SUCCEEDED(hr = penum->Next(&pszMountPoint, &pszDeviceIDVolume)) &&
  663. (S_FALSE != hr))
  664. {
  665. CVolume* pvol = CMtPtLocal::_GetVolumeByID(pszDeviceIDVolume);
  666. if (pvol)
  667. {
  668. CMtPtLocal::_CreateMtPtLocalWithVolume(pszMountPoint, pvol);
  669. pvol->Release();
  670. }
  671. if (!_IsDriveLetter(pszMountPoint))
  672. {
  673. _rsMtPtsLocalMOF.RSSetTextValue(NULL, pszMountPoint, TEXT(""));
  674. }
  675. CoTaskMemFree(pszMountPoint);
  676. CoTaskMemFree(pszDeviceIDVolume);
  677. }
  678. penum->Release();
  679. }
  680. }
  681. else
  682. {
  683. hr = S_OK;
  684. if (_hdpaVolumes)
  685. {
  686. DWORD c = DPA_GetPtrCount(_hdpaVolumes);
  687. for (int i = c - 1; i >= 0; --i)
  688. {
  689. CVolume* pvol = (CVolume*)DPA_GetPtr(_hdpaVolumes, i);
  690. if (pvol)
  691. {
  692. DWORD cch;
  693. if (GetVolumePathNamesForVolumeName(pvol->pszVolumeGUID,
  694. NULL, 0, &cch))
  695. {
  696. // no mountpoint, we're done
  697. }
  698. else
  699. {
  700. // Expected, even wanted...
  701. if (ERROR_MORE_DATA == GetLastError())
  702. {
  703. LPWSTR pszMtPts = (LPWSTR)LocalAlloc(LPTR,
  704. cch * sizeof(WCHAR));
  705. if (pszMtPts)
  706. {
  707. if (GetVolumePathNamesForVolumeName(
  708. pvol->pszVolumeGUID, pszMtPts, cch, &cch))
  709. {
  710. for (LPWSTR psz = pszMtPts; *psz;
  711. psz += lstrlen(psz) + 1)
  712. {
  713. CMtPtLocal::_CreateMtPtLocalWithVolume(
  714. psz, pvol);
  715. }
  716. }
  717. LocalFree(pszMtPts);
  718. }
  719. else
  720. {
  721. hr = E_OUTOFMEMORY;
  722. }
  723. }
  724. else
  725. {
  726. hr = S_FALSE;
  727. }
  728. }
  729. }
  730. }
  731. }
  732. }
  733. // We don't care about the prev hr. I'll clean this up when moving the
  734. // volume information from the Shell Service. (stephstm, 2001/03/13)
  735. DWORD dwLogicalDrives = GetLogicalDrives();
  736. DWORD dwLocalDrives = 0;
  737. for (DWORD dw = 0; dw < 26; ++dw)
  738. {
  739. if (dwLogicalDrives & (1 << dw))
  740. {
  741. if (_rgMtPtDriveLetterLocal[dw])
  742. {
  743. dwLocalDrives |= (1 << dw);
  744. }
  745. else
  746. {
  747. WCHAR szDrive[4];
  748. PathBuildRoot(szDrive, dw);
  749. if (DRIVE_REMOTE != GetDriveType(szDrive))
  750. {
  751. // This is a "subst" drive or something like this.
  752. // It only appears in the per-user drive map, not the
  753. // per-machine. Let's create a mountpoint for it.
  754. CMtPtLocal::_CreateMtPtLocal(szDrive);
  755. dwLocalDrives |= (1 << dw);
  756. }
  757. }
  758. }
  759. }
  760. return hr;
  761. }
  762. //static
  763. HRESULT CMountPoint::_DeleteVolumeInfo()
  764. {
  765. ASSERT(_csDL.IsInside());
  766. if (_hdpaVolumes)
  767. {
  768. DWORD c = DPA_GetPtrCount(_hdpaVolumes);
  769. for (int i = c - 1; i >= 0; --i)
  770. {
  771. CVolume* pvol = (CVolume*)DPA_GetPtr(_hdpaVolumes, i);
  772. if (pvol)
  773. {
  774. pvol->Release();
  775. }
  776. DPA_DeletePtr(_hdpaVolumes, i);
  777. }
  778. DPA_Destroy(_hdpaVolumes);
  779. _hdpaVolumes = NULL;
  780. }
  781. return S_OK;
  782. }
  783. //static
  784. HRESULT CMountPoint::_DeleteLocalMtPts()
  785. {
  786. ASSERT(_csDL.IsInside());
  787. for (DWORD dw = 0; dw < 26; ++dw)
  788. {
  789. CMtPtLocal* pmtptl = (CMtPtLocal*)_rgMtPtDriveLetterLocal[dw];
  790. if (pmtptl)
  791. {
  792. pmtptl->Release();
  793. _rgMtPtDriveLetterLocal[dw] = 0;
  794. }
  795. }
  796. _csLocalMtPtHDPA.Enter();
  797. if (_hdpaMountPoints)
  798. {
  799. int n = DPA_GetPtrCount(_hdpaMountPoints);
  800. for (int i = n - 1; i >= 0; --i)
  801. {
  802. CMtPtLocal* pmtptl = (CMtPtLocal*)DPA_GetPtr(_hdpaMountPoints, i);
  803. if (pmtptl)
  804. {
  805. pmtptl->Release();
  806. DPA_DeletePtr(_hdpaMountPoints, i);
  807. }
  808. }
  809. DPA_Destroy(_hdpaMountPoints);
  810. }
  811. _csLocalMtPtHDPA.Leave();
  812. return S_OK;
  813. }
  814. // static
  815. HRESULT CMountPoint::_GetMountPointsForVolume(LPCWSTR pszDeviceIDVolume,
  816. HDPA hdpaMtPts)
  817. {
  818. ASSERT(!_csDL.IsInside());
  819. _csDL.Enter();
  820. for (DWORD dw = 0; dw < 26; ++dw)
  821. {
  822. CMtPtLocal* pmtptl = (CMtPtLocal*)_rgMtPtDriveLetterLocal[dw];
  823. if (pmtptl && pmtptl->_pvol)
  824. {
  825. if (!lstrcmpi(pmtptl->_pvol->pszDeviceIDVolume, pszDeviceIDVolume))
  826. {
  827. LPCWSTR pszMtPt = StrDup(pmtptl->_szName);
  828. if (pszMtPt)
  829. {
  830. if (-1 == DPA_AppendPtr(hdpaMtPts, (void*)pszMtPt))
  831. {
  832. LocalFree((HLOCAL)pszMtPt);
  833. }
  834. }
  835. // Volumes can be mounted on only one drive letter
  836. break;
  837. }
  838. }
  839. }
  840. _csDL.Leave();
  841. _csLocalMtPtHDPA.Enter();
  842. if (_hdpaMountPoints)
  843. {
  844. int n = DPA_GetPtrCount(_hdpaMountPoints);
  845. for (int i = n - 1; i >= 0; --i)
  846. {
  847. CMtPtLocal* pmtptl = (CMtPtLocal*)DPA_GetPtr(_hdpaMountPoints, i);
  848. if (pmtptl && pmtptl->_pvol)
  849. {
  850. if (!lstrcmpi(pmtptl->_pvol->pszDeviceIDVolume, pszDeviceIDVolume))
  851. {
  852. LPCWSTR pszMtPt = StrDup(pmtptl->_szName);
  853. if (pszMtPt)
  854. {
  855. if (-1 == DPA_AppendPtr(hdpaMtPts, (void*)pszMtPt))
  856. {
  857. LocalFree((HLOCAL)pszMtPt);
  858. }
  859. }
  860. }
  861. }
  862. }
  863. }
  864. _csLocalMtPtHDPA.Leave();
  865. return S_OK;
  866. }
  867. // static
  868. HRESULT CMountPoint::_InitLocalDriveHelper()
  869. {
  870. #ifdef DEBUG
  871. // We should not try to enter the Drive Letter critical section on this thread.
  872. // We've already entered it on the thread that launched us, and
  873. // we should still be in there. The thread that launched us is waiting for
  874. // this thread to finish before going on. Trying to re-enter this critical
  875. // section from this thread will deadlock.
  876. DWORD dwThreadID = GetCurrentThreadId();
  877. _csDL.SetThreadIDToCheckForEntrance(dwThreadID);
  878. _csDL.FakeEnter();
  879. #endif
  880. IHardwareDevices* pihwdevs;
  881. HRESULT hr;
  882. BOOL fLoadedInDesktop = _Shell32LoadedInDesktop();
  883. if (fLoadedInDesktop)
  884. {
  885. hr = _GetHardwareDevices(&pihwdevs);
  886. }
  887. else
  888. {
  889. hr = S_FALSE;
  890. }
  891. if (SUCCEEDED(hr))
  892. {
  893. if (!_hdpaVolumes && !_fShuttingDown)
  894. {
  895. _hdpaVolumes = DPA_Create(3);
  896. }
  897. if (_hdpaVolumes)
  898. {
  899. if (SUCCEEDED(hr))
  900. {
  901. hr = _EnumVolumes(pihwdevs);
  902. if (SUCCEEDED(hr))
  903. {
  904. hr = _EnumMountPoints(pihwdevs);
  905. if (SUCCEEDED(hr))
  906. {
  907. _fLocalDrivesInited = TRUE;
  908. }
  909. else
  910. {
  911. _DeleteVolumeInfo();
  912. }
  913. }
  914. }
  915. }
  916. else
  917. {
  918. hr = E_OUTOFMEMORY;
  919. }
  920. if (fLoadedInDesktop)
  921. {
  922. pihwdevs->Release();
  923. }
  924. }
  925. #ifdef DEBUG
  926. _csDL.FakeLeave();
  927. _csDL.SetThreadIDToCheckForEntrance(0);
  928. #endif
  929. return hr;
  930. }
  931. DWORD WINAPI _FirstHardwareEnumThreadProc(void* pv)
  932. {
  933. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
  934. if (SUCCEEDED(hr))
  935. {
  936. hr = CMountPoint::_InitLocalDriveHelper();
  937. CoUninitialize();
  938. }
  939. return (DWORD)hr;
  940. }
  941. //static
  942. BOOL CMountPoint::_CanRegister()
  943. {
  944. if (!CMountPoint::_fCanRegisterWithShellService)
  945. {
  946. HANDLE hCanRegister = OpenEvent(SYNCHRONIZE, FALSE, TEXT("_fCanRegisterWithShellService"));
  947. if (hCanRegister)
  948. {
  949. CloseHandle(hCanRegister);
  950. }
  951. else
  952. {
  953. CMountPoint::_fCanRegisterWithShellService = TRUE;
  954. }
  955. }
  956. return CMountPoint::_fCanRegisterWithShellService;
  957. }
  958. //static
  959. HRESULT CMountPoint::_InitLocalDrives()
  960. {
  961. ASSERT(_csDL.IsInside());
  962. HRESULT hr = E_FAIL;
  963. BOOL fTryFullInit = FALSE;
  964. if (CMountPoint::_CanRegister())
  965. {
  966. if (!_dwTickCountTriedAndFailed)
  967. {
  968. // We didn't try full init yet
  969. fTryFullInit = TRUE;
  970. }
  971. else
  972. {
  973. // We already tried and failed doing a full init. Try again only if
  974. // it's been more than 5 seconds.
  975. if ((GetTickCount() - _dwTickCountTriedAndFailed) >
  976. (5 * 1000))
  977. {
  978. fTryFullInit = TRUE;
  979. }
  980. }
  981. if (fTryFullInit)
  982. {
  983. if (_Shell32LoadedInDesktop())
  984. {
  985. HANDLE hThread = CreateThread(NULL, 0, _FirstHardwareEnumThreadProc, NULL, 0, NULL);
  986. if (hThread)
  987. {
  988. DWORD dwWait = WaitForSingleObject(hThread, INFINITE);
  989. if (WAIT_FAILED != dwWait)
  990. {
  991. DWORD dwExitCode;
  992. if (GetExitCodeThread(hThread, &dwExitCode))
  993. {
  994. hr = (HRESULT)dwExitCode;
  995. }
  996. }
  997. CloseHandle(hThread);
  998. }
  999. if (SUCCEEDED(hr))
  1000. {
  1001. _dwTickCountTriedAndFailed = 0;
  1002. }
  1003. else
  1004. {
  1005. _dwTickCountTriedAndFailed = GetTickCount();
  1006. }
  1007. }
  1008. else
  1009. {
  1010. hr = _InitLocalDriveHelper();
  1011. _dwTickCountTriedAndFailed = 0;
  1012. }
  1013. }
  1014. }
  1015. if (FAILED(hr))
  1016. {
  1017. if (!_fNoVolLocalDrivesInited)
  1018. {
  1019. DWORD dwLogicalDrives = GetLogicalDrives();
  1020. for (DWORD dw = 0; dw < 26; ++dw)
  1021. {
  1022. if (dwLogicalDrives & (1 << dw))
  1023. {
  1024. WCHAR szDrive[4];
  1025. int iDriveType = GetDriveType(PathBuildRoot(szDrive, dw));
  1026. if ((DRIVE_REMOTE != iDriveType) && (DRIVE_UNKNOWN != iDriveType) &&
  1027. (DRIVE_NO_ROOT_DIR != iDriveType))
  1028. {
  1029. hr = CMtPtLocal::_CreateMtPtLocal(szDrive);
  1030. }
  1031. }
  1032. }
  1033. _fNoVolLocalDrivesInited = TRUE;
  1034. }
  1035. else
  1036. {
  1037. hr = S_FALSE;
  1038. }
  1039. }
  1040. return hr;
  1041. }
  1042. //static
  1043. DWORD CMountPoint::GetDrivesMask()
  1044. {
  1045. HRESULT hr = S_FALSE;
  1046. DWORD dwMask = 0;
  1047. _csDL.Enter();
  1048. if (!_fNetDrivesInited)
  1049. {
  1050. hr = _InitNetDrives();
  1051. }
  1052. if (!_fLocalDrivesInited)
  1053. {
  1054. hr = _InitLocalDrives();
  1055. }
  1056. if (SUCCEEDED(hr))
  1057. {
  1058. if (_Shell32LoadedInDesktop())
  1059. {
  1060. for (DWORD dw = 0; dw < 26; ++dw)
  1061. {
  1062. if (_rgMtPtDriveLetterLocal[dw] || _rgMtPtDriveLetterNet[dw])
  1063. {
  1064. dwMask |= (1 << dw);
  1065. }
  1066. }
  1067. }
  1068. else
  1069. {
  1070. dwMask = GetLogicalDrives() | _dwRememberedNetDrivesMask;
  1071. }
  1072. }
  1073. _csDL.Leave();
  1074. return dwMask;
  1075. }
  1076. //static
  1077. BOOL CMountPoint::Initialize()
  1078. {
  1079. BOOL bRet = TRUE;
  1080. if (!_csLocalMtPtHDPA.Init() ||
  1081. !_csDL.Init())
  1082. {
  1083. bRet = FALSE;
  1084. }
  1085. _rsMtPtsLocalDL.RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2,
  1086. g_szCrossProcessCacheMtPtsLocalDLKey, REG_OPTION_VOLATILE);
  1087. _rsMtPtsRemote.RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2,
  1088. g_szCrossProcessCacheMtPtsRemoteKey, REG_OPTION_VOLATILE);
  1089. _rsMtPtsLocalMOF.RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2,
  1090. g_szCrossProcessCacheMtPtsLocalMOFKey, REG_OPTION_VOLATILE);
  1091. return bRet;
  1092. }
  1093. ///////////////////////////////////////////////////////////////////////////////
  1094. // For C caller
  1095. ///////////////////////////////////////////////////////////////////////////////
  1096. STDAPI_(void) CMtPt_FinalCleanUp()
  1097. {
  1098. CMountPoint::FinalCleanUp();
  1099. CMtPtLocal::FinalCleanUp();
  1100. }
  1101. STDAPI_(BOOL) CMtPt_Initialize()
  1102. {
  1103. BOOL bRet = TRUE;
  1104. if (!CMountPoint::Initialize() ||
  1105. !CMtPtLocal::Initialize())
  1106. {
  1107. bRet = FALSE;
  1108. }
  1109. return bRet;
  1110. }
  1111. //static
  1112. void CMountPoint::FinalCleanUp()
  1113. {
  1114. if (_csDL.IsInitialized() && _csLocalMtPtHDPA.IsInitialized())
  1115. {
  1116. _csDL.Enter();
  1117. _fShuttingDown = TRUE;
  1118. _csLocalMtPtHDPA.Enter();
  1119. _DeleteLocalMtPts();
  1120. _DeleteVolumeInfo();
  1121. CMtPtRemote::_DeleteAllMtPtsAndShares();
  1122. _fNetDrivesInited = FALSE;
  1123. _csLocalMtPtHDPA._fShuttingDown = TRUE;
  1124. _csDL._fShuttingDown = TRUE;
  1125. _csLocalMtPtHDPA.Leave();
  1126. _csDL.Leave();
  1127. _csLocalMtPtHDPA.Delete();
  1128. _csDL.Delete();
  1129. CSniffDrive::CleanUp();
  1130. if (_hThreadSCN)
  1131. {
  1132. CloseHandle(_hThreadSCN);
  1133. _hThreadSCN = NULL;
  1134. }
  1135. }
  1136. if (_Shell32LoadedInDesktop())
  1137. {
  1138. _rsMtPtsLocalDL.RSDeleteKey();
  1139. _rsMtPtsLocalMOF.RSDeleteKey();
  1140. _rsMtPtsRemote.RSDeleteKey();
  1141. }
  1142. }
  1143. //static
  1144. BOOL CMountPoint::_IsNetDriveLazyLoadNetDLLs(int iDrive)
  1145. {
  1146. ASSERT(_csDL.IsInside());
  1147. BOOL fNetDrive = FALSE;
  1148. if (!_fNetDrivesInited)
  1149. {
  1150. HRESULT hr = S_FALSE;
  1151. WCHAR szPath[4];
  1152. // Try to avoid loading the net dlls
  1153. UINT uDriveType = GetDriveType(PathBuildRoot(szPath, iDrive));
  1154. if (DRIVE_NO_ROOT_DIR == uDriveType)
  1155. {
  1156. // This happens for Remembered drives
  1157. hr = _InitNetDrives();
  1158. if (SUCCEEDED(hr))
  1159. {
  1160. fNetDrive = BOOLFROMPTR(_rgMtPtDriveLetterNet[iDrive]);
  1161. }
  1162. }
  1163. else
  1164. {
  1165. if (DRIVE_REMOTE == uDriveType)
  1166. {
  1167. fNetDrive = TRUE;
  1168. }
  1169. }
  1170. }
  1171. else
  1172. {
  1173. fNetDrive = BOOLFROMPTR(_rgMtPtDriveLetterNet[iDrive]);
  1174. if (!_Shell32LoadedInDesktop())
  1175. {
  1176. DWORD dwAllDrives = GetLogicalDrives() | _dwRememberedNetDrivesMask;
  1177. if (fNetDrive)
  1178. {
  1179. // make sure it still exist
  1180. if (!(dwAllDrives & (1 << iDrive)))
  1181. {
  1182. // its' gone!
  1183. fNetDrive = FALSE;
  1184. }
  1185. else
  1186. {
  1187. WCHAR szPath[4];
  1188. // There's still a drive there, make sure it's not a local one
  1189. if (!(_dwRememberedNetDrivesMask & (1 << iDrive)) &&
  1190. !(GetDriveType(PathBuildRoot(szPath, iDrive)) == DRIVE_REMOTE))
  1191. {
  1192. fNetDrive = FALSE;
  1193. }
  1194. }
  1195. if (!fNetDrive && (_rgMtPtDriveLetterNet[iDrive]))
  1196. {
  1197. _rgMtPtDriveLetterNet[iDrive]->Release();
  1198. _rgMtPtDriveLetterNet[iDrive] = NULL;
  1199. }
  1200. }
  1201. else
  1202. {
  1203. // maybe it arrived after we enumerated
  1204. if (dwAllDrives & (1 << iDrive))
  1205. {
  1206. WCHAR szPath[4];
  1207. // Is it a remote drive?
  1208. if ((_dwRememberedNetDrivesMask & (1 << iDrive)) ||
  1209. (GetDriveType(PathBuildRoot(szPath, iDrive)) == DRIVE_REMOTE))
  1210. {
  1211. // indeed
  1212. _ReInitNetDrives();
  1213. fNetDrive = TRUE;
  1214. }
  1215. }
  1216. }
  1217. }
  1218. }
  1219. return fNetDrive;
  1220. }
  1221. // static
  1222. HRESULT CMountPoint::_RemoveLocalMountPoint(LPCWSTR pszMountPoint)
  1223. {
  1224. if (_IsDriveLetter(pszMountPoint))
  1225. {
  1226. _csDL.Enter();
  1227. int iDrive = DRIVEID(pszMountPoint);
  1228. CMtPtLocal* pmtptl = (CMtPtLocal*)_rgMtPtDriveLetterLocal[iDrive];
  1229. if (pmtptl)
  1230. {
  1231. _rgMtPtDriveLetterLocal[iDrive] = 0;
  1232. pmtptl->Release();
  1233. }
  1234. _csDL.Leave();
  1235. }
  1236. else
  1237. {
  1238. _csLocalMtPtHDPA.Enter();
  1239. if (_hdpaMountPoints)
  1240. {
  1241. DWORD c = DPA_GetPtrCount(_hdpaMountPoints);
  1242. for (int i = c - 1; i >= 0; --i)
  1243. {
  1244. CMtPtLocal* pmtptl = (CMtPtLocal*)DPA_GetPtr(_hdpaMountPoints, i);
  1245. if (pmtptl)
  1246. {
  1247. if (!lstrcmpi(pmtptl->_szName, pszMountPoint))
  1248. {
  1249. DPA_DeletePtr(_hdpaMountPoints, i);
  1250. pmtptl->Release();
  1251. break;
  1252. }
  1253. }
  1254. }
  1255. }
  1256. if (_Shell32LoadedInDesktop())
  1257. {
  1258. _rsMtPtsLocalMOF.RSDeleteValue(NULL, pszMountPoint);
  1259. }
  1260. _csLocalMtPtHDPA.Leave();
  1261. }
  1262. return S_OK;
  1263. }
  1264. // static
  1265. HRESULT CMountPoint::_RemoveNetMountPoint(LPCWSTR pszMountPoint)
  1266. {
  1267. _csDL.Enter();
  1268. int iDrive = DRIVEID(pszMountPoint);
  1269. if (_rgMtPtDriveLetterNet[iDrive])
  1270. {
  1271. _rgMtPtDriveLetterNet[iDrive]->Release();
  1272. _rgMtPtDriveLetterNet[iDrive] = 0;
  1273. }
  1274. _csDL.Leave();
  1275. return S_OK;
  1276. }
  1277. // static
  1278. BOOL CMountPoint::_CheckLocalMtPtsMOF(LPCWSTR pszMountPoint)
  1279. {
  1280. ASSERT(!_Shell32LoadedInDesktop());
  1281. return _rsMtPtsLocalMOF.RSValueExist(NULL, pszMountPoint);
  1282. }
  1283. //
  1284. // This needs to be called from the thread that will be used for APCs callbacks
  1285. // (stephstm: 2001/03/31)
  1286. // static
  1287. DWORD WINAPI CMountPoint::_RegisterThreadProc(void* pv)
  1288. {
  1289. ASSERT(_Shell32LoadedInDesktop());
  1290. HANDLE hThread = (HANDLE)pv;
  1291. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
  1292. if (SUCCEEDED(hr))
  1293. {
  1294. IHardwareDevices* pihwdevs;
  1295. hr = _GetHardwareDevices(&pihwdevs);
  1296. if (SUCCEEDED(hr))
  1297. {
  1298. hr = pihwdevs->Advise(GetCurrentProcessId(), (ULONG_PTR)hThread,
  1299. (ULONG_PTR)CMountPoint::_EventAPCProc, &_dwAdviseToken);
  1300. pihwdevs->Release();
  1301. }
  1302. CoUninitialize();
  1303. }
  1304. return (DWORD)hr;
  1305. }
  1306. // static
  1307. HRESULT CMountPoint::RegisterForHardwareNotifications()
  1308. {
  1309. HRESULT hr;
  1310. if (_Shell32LoadedInDesktop() && (-1 == _dwAdviseToken))
  1311. {
  1312. HANDLE hPseudoProcess = GetCurrentProcess();
  1313. // See comment above!
  1314. HANDLE hPseudoThread = GetCurrentThread();
  1315. hr = E_FAIL;
  1316. if (DuplicateHandle(hPseudoProcess, hPseudoThread, hPseudoProcess,
  1317. &_hThreadSCN, DUPLICATE_SAME_ACCESS, FALSE, 0))
  1318. {
  1319. HANDLE hThread = CreateThread(NULL, 0, _RegisterThreadProc, (void*)_hThreadSCN, 0, NULL);
  1320. CSniffDrive::Init(_hThreadSCN);
  1321. if (hThread)
  1322. {
  1323. DWORD dwWait = WaitForSingleObject(hThread, INFINITE);
  1324. if (WAIT_FAILED != dwWait)
  1325. {
  1326. DWORD dwExitCode;
  1327. if (GetExitCodeThread(hThread, &dwExitCode))
  1328. {
  1329. hr = (HRESULT)dwExitCode;
  1330. }
  1331. }
  1332. CloseHandle(hThread);
  1333. }
  1334. else
  1335. {
  1336. // We want to keep the handle around we'll uise it for something else.
  1337. }
  1338. }
  1339. }
  1340. else
  1341. {
  1342. hr = S_FALSE;
  1343. }
  1344. return hr;
  1345. }