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.

1668 lines
42 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. //
  470. // BUGBUG (stephstm) - do we really want to return S_FALSE if WNetEnumResource fails?!?
  471. //
  472. if (pbBuf)
  473. {
  474. LocalFree(pbBuf);
  475. }
  476. }
  477. WNetCloseEnum(hEnum);
  478. }
  479. //
  480. // BUGBUG (stephstm) - do we really want to return S_FALSE if WNetOpenEnum fails?!?
  481. //
  482. // else if (ERROR_NO_NETWORK == dwErr)
  483. return hr;
  484. }
  485. //static
  486. HRESULT CMountPoint::_ReInitNetDrives()
  487. {
  488. ASSERT(_csDL.IsInside());
  489. CMtPtRemote::_DeleteAllMtPtsAndShares();
  490. _fNetDrivesInited = FALSE;
  491. CMountPoint::_InitNetDrives();
  492. return S_OK;
  493. }
  494. //static
  495. HRESULT CMountPoint::_InitNetDrives()
  496. {
  497. ASSERT(_csDL.IsInside());
  498. HRESULT hr;
  499. if (!_fNetDrivesInited)
  500. {
  501. if (!_fShuttingDown)
  502. {
  503. if (!_hdpaShares)
  504. {
  505. _hdpaShares = DPA_Create(3);
  506. }
  507. }
  508. if (_hdpaShares)
  509. {
  510. hr = _InitNetDrivesHelper(RESOURCE_CONNECTED);
  511. if (SUCCEEDED(hr))
  512. {
  513. hr = _InitNetDrivesHelper(RESOURCE_REMEMBERED);
  514. }
  515. if (SUCCEEDED(hr))
  516. {
  517. DWORD dwLogicalDrives = GetLogicalDrives();
  518. for (DWORD dw = 0; dw < 26; ++dw)
  519. {
  520. if (dwLogicalDrives & (1 << dw))
  521. {
  522. if (!(_rgMtPtDriveLetterNet[dw]))
  523. {
  524. WCHAR szDrive[4];
  525. PathBuildRoot(szDrive, dw);
  526. if (DRIVE_REMOTE == GetDriveType(szDrive))
  527. {
  528. // This must be a weird System mapped drive
  529. // which is not enumerated by the per-user
  530. // WNetEnumResource...
  531. hr = CMtPtRemote::_CreateMtPtRemoteWithoutShareName(szDrive);
  532. }
  533. }
  534. }
  535. }
  536. _fNetDrivesInited = TRUE;
  537. }
  538. }
  539. else
  540. {
  541. hr = E_OUTOFMEMORY;
  542. }
  543. }
  544. else
  545. {
  546. hr = S_FALSE;
  547. }
  548. if (_Shell32LoadedInDesktop())
  549. {
  550. DWORD dwRemoteDrives = 0;
  551. for (DWORD dw = 0; dw < 26; ++dw)
  552. {
  553. if (_rgMtPtDriveLetterNet[dw])
  554. {
  555. dwRemoteDrives |= (1 << dw);
  556. }
  557. }
  558. }
  559. return hr;
  560. }
  561. inline void _CoTaskMemFree(void* pv)
  562. {
  563. if (pv)
  564. {
  565. CoTaskMemFree(pv);
  566. }
  567. }
  568. const GUID guidVolumeClass =
  569. {0x53f5630d, 0xb6bf, 0x11d0,
  570. {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
  571. //static
  572. HRESULT CMountPoint::_EnumVolumes(IHardwareDevices* pihwdevs)
  573. {
  574. ASSERT(_csDL.IsInside());
  575. HRESULT hr;
  576. if (_Shell32LoadedInDesktop())
  577. {
  578. // Synchro
  579. IHardwareDevicesVolumesEnum* penum;
  580. hr = pihwdevs->EnumVolumes(HWDEV_GETCUSTOMPROPERTIES, &penum);
  581. ASSERTMSG(NULL != _hdpaVolumes, "_hdpaVolumes should not be NULL at this point, some code found its way here without calling InitLocalDrives");
  582. if (SUCCEEDED(hr))
  583. {
  584. do
  585. {
  586. VOLUMEINFO volinfo;
  587. hr = penum->Next(&volinfo);
  588. if (SUCCEEDED(hr) && (S_FALSE != hr))
  589. {
  590. CVolume* pvolNew;
  591. if (SUCCEEDED(CMtPtLocal::_CreateVolume(&volinfo, &pvolNew)))
  592. {
  593. CMtPtLocal::_UpdateVolumeRegInfo(&volinfo);
  594. pvolNew->Release();
  595. }
  596. CoTaskMemFree(volinfo.pszDeviceIDVolume);
  597. CoTaskMemFree(volinfo.pszVolumeGUID);
  598. CoTaskMemFree(volinfo.pszLabel);
  599. CoTaskMemFree(volinfo.pszFileSystem);
  600. CoTaskMemFree(volinfo.pszAutorunIconLocation);
  601. CoTaskMemFree(volinfo.pszAutorunLabel);
  602. CoTaskMemFree(volinfo.pszIconLocationFromService);
  603. CoTaskMemFree(volinfo.pszNoMediaIconLocationFromService);
  604. CoTaskMemFree(volinfo.pszLabelFromService);
  605. }
  606. }
  607. while (SUCCEEDED(hr) && (S_FALSE != hr));
  608. penum->Release();
  609. }
  610. }
  611. else
  612. {
  613. ULONG ulSize;
  614. ULONG ulFlags = CM_GET_DEVICE_INTERFACE_LIST_PRESENT;
  615. CONFIGRET cr = CM_Get_Device_Interface_List_Size_Ex(&ulSize,
  616. (GUID*)&guidVolumeClass, NULL, ulFlags, NULL);
  617. if ((CR_SUCCESS == cr) && (ulSize > 1))
  618. {
  619. LPWSTR pszVolumes = (LPWSTR)LocalAlloc(LPTR, ulSize * sizeof(WCHAR));
  620. if (pszVolumes)
  621. {
  622. cr = CM_Get_Device_Interface_List_Ex((GUID*)&guidVolumeClass,
  623. NULL, pszVolumes, ulSize, ulFlags, NULL);
  624. if (CR_SUCCESS == cr)
  625. {
  626. for (LPWSTR psz = pszVolumes; *psz; psz += lstrlen(psz) + 1)
  627. {
  628. CVolume* pvolNew;
  629. HRESULT hrTmp = CMtPtLocal::_CreateVolumeFromReg(psz,
  630. &pvolNew);
  631. if (SUCCEEDED(hrTmp))
  632. {
  633. pvolNew->Release();
  634. }
  635. }
  636. hr = S_OK;
  637. }
  638. else
  639. {
  640. hr = S_FALSE;
  641. }
  642. LocalFree(pszVolumes);
  643. }
  644. else
  645. {
  646. hr = E_OUTOFMEMORY;
  647. }
  648. }
  649. else
  650. {
  651. hr = S_FALSE;
  652. }
  653. }
  654. return hr;
  655. }
  656. //static
  657. HRESULT CMountPoint::_EnumMountPoints(IHardwareDevices* pihwdevs)
  658. {
  659. ASSERT(_csDL.IsInside());
  660. HRESULT hr;
  661. if (_Shell32LoadedInDesktop())
  662. {
  663. IHardwareDevicesMountPointsEnum* penum;
  664. hr = pihwdevs->EnumMountPoints(&penum);
  665. if (SUCCEEDED(hr))
  666. {
  667. LPWSTR pszMountPoint;
  668. LPWSTR pszDeviceIDVolume;
  669. while (SUCCEEDED(hr = penum->Next(&pszMountPoint, &pszDeviceIDVolume)) &&
  670. (S_FALSE != hr))
  671. {
  672. CVolume* pvol = CMtPtLocal::_GetVolumeByID(pszDeviceIDVolume);
  673. if (pvol)
  674. {
  675. CMtPtLocal::_CreateMtPtLocalWithVolume(pszMountPoint, pvol);
  676. pvol->Release();
  677. }
  678. if (!_IsDriveLetter(pszMountPoint))
  679. {
  680. _rsMtPtsLocalMOF.RSSetTextValue(NULL, pszMountPoint, TEXT(""));
  681. }
  682. CoTaskMemFree(pszMountPoint);
  683. CoTaskMemFree(pszDeviceIDVolume);
  684. }
  685. penum->Release();
  686. }
  687. }
  688. else
  689. {
  690. hr = S_OK;
  691. if (_hdpaVolumes)
  692. {
  693. DWORD c = DPA_GetPtrCount(_hdpaVolumes);
  694. for (int i = c - 1; i >= 0; --i)
  695. {
  696. CVolume* pvol = (CVolume*)DPA_GetPtr(_hdpaVolumes, i);
  697. if (pvol)
  698. {
  699. DWORD cch;
  700. if (GetVolumePathNamesForVolumeName(pvol->pszVolumeGUID,
  701. NULL, 0, &cch))
  702. {
  703. // no mountpoint, we're done
  704. }
  705. else
  706. {
  707. // Expected, even wanted...
  708. if (ERROR_MORE_DATA == GetLastError())
  709. {
  710. LPWSTR pszMtPts = (LPWSTR)LocalAlloc(LPTR,
  711. cch * sizeof(WCHAR));
  712. if (pszMtPts)
  713. {
  714. if (GetVolumePathNamesForVolumeName(
  715. pvol->pszVolumeGUID, pszMtPts, cch, &cch))
  716. {
  717. for (LPWSTR psz = pszMtPts; *psz;
  718. psz += lstrlen(psz) + 1)
  719. {
  720. CMtPtLocal::_CreateMtPtLocalWithVolume(
  721. psz, pvol);
  722. }
  723. }
  724. LocalFree(pszMtPts);
  725. }
  726. else
  727. {
  728. hr = E_OUTOFMEMORY;
  729. }
  730. }
  731. else
  732. {
  733. hr = S_FALSE;
  734. }
  735. }
  736. }
  737. }
  738. }
  739. }
  740. // We don't care about the prev hr. I'll clean this up when moving the
  741. // volume information from the Shell Service. (stephstm, 2001/03/13)
  742. DWORD dwLogicalDrives = GetLogicalDrives();
  743. DWORD dwLocalDrives = 0;
  744. for (DWORD dw = 0; dw < 26; ++dw)
  745. {
  746. if (dwLogicalDrives & (1 << dw))
  747. {
  748. if (_rgMtPtDriveLetterLocal[dw])
  749. {
  750. dwLocalDrives |= (1 << dw);
  751. }
  752. else
  753. {
  754. WCHAR szDrive[4];
  755. PathBuildRoot(szDrive, dw);
  756. if (DRIVE_REMOTE != GetDriveType(szDrive))
  757. {
  758. // This is a "subst" drive or something like this.
  759. // It only appears in the per-user drive map, not the
  760. // per-machine. Let's create a mountpoint for it.
  761. CMtPtLocal::_CreateMtPtLocal(szDrive);
  762. dwLocalDrives |= (1 << dw);
  763. }
  764. }
  765. }
  766. }
  767. return hr;
  768. }
  769. //static
  770. HRESULT CMountPoint::_DeleteVolumeInfo()
  771. {
  772. ASSERT(_csDL.IsInside());
  773. if (_hdpaVolumes)
  774. {
  775. DWORD c = DPA_GetPtrCount(_hdpaVolumes);
  776. for (int i = c - 1; i >= 0; --i)
  777. {
  778. CVolume* pvol = (CVolume*)DPA_GetPtr(_hdpaVolumes, i);
  779. if (pvol)
  780. {
  781. pvol->Release();
  782. }
  783. DPA_DeletePtr(_hdpaVolumes, i);
  784. }
  785. DPA_Destroy(_hdpaVolumes);
  786. _hdpaVolumes = NULL;
  787. }
  788. return S_OK;
  789. }
  790. //static
  791. HRESULT CMountPoint::_DeleteLocalMtPts()
  792. {
  793. ASSERT(_csDL.IsInside());
  794. for (DWORD dw = 0; dw < 26; ++dw)
  795. {
  796. CMtPtLocal* pmtptl = (CMtPtLocal*)_rgMtPtDriveLetterLocal[dw];
  797. if (pmtptl)
  798. {
  799. pmtptl->Release();
  800. _rgMtPtDriveLetterLocal[dw] = 0;
  801. }
  802. }
  803. _csLocalMtPtHDPA.Enter();
  804. if (_hdpaMountPoints)
  805. {
  806. int n = DPA_GetPtrCount(_hdpaMountPoints);
  807. for (int i = n - 1; i >= 0; --i)
  808. {
  809. CMtPtLocal* pmtptl = (CMtPtLocal*)DPA_GetPtr(_hdpaMountPoints, i);
  810. if (pmtptl)
  811. {
  812. pmtptl->Release();
  813. DPA_DeletePtr(_hdpaMountPoints, i);
  814. }
  815. }
  816. DPA_Destroy(_hdpaMountPoints);
  817. }
  818. _csLocalMtPtHDPA.Leave();
  819. return S_OK;
  820. }
  821. // static
  822. HRESULT CMountPoint::_GetMountPointsForVolume(LPCWSTR pszDeviceIDVolume,
  823. HDPA hdpaMtPts)
  824. {
  825. ASSERT(!_csDL.IsInside());
  826. _csDL.Enter();
  827. for (DWORD dw = 0; dw < 26; ++dw)
  828. {
  829. CMtPtLocal* pmtptl = (CMtPtLocal*)_rgMtPtDriveLetterLocal[dw];
  830. if (pmtptl && pmtptl->_pvol)
  831. {
  832. if (!lstrcmpi(pmtptl->_pvol->pszDeviceIDVolume, pszDeviceIDVolume))
  833. {
  834. LPCWSTR pszMtPt = StrDup(pmtptl->_szName);
  835. if (pszMtPt)
  836. {
  837. if (-1 == DPA_AppendPtr(hdpaMtPts, (void*)pszMtPt))
  838. {
  839. LocalFree((HLOCAL)pszMtPt);
  840. }
  841. }
  842. // Volumes can be mounted on only one drive letter
  843. break;
  844. }
  845. }
  846. }
  847. _csDL.Leave();
  848. _csLocalMtPtHDPA.Enter();
  849. if (_hdpaMountPoints)
  850. {
  851. int n = DPA_GetPtrCount(_hdpaMountPoints);
  852. for (int i = n - 1; i >= 0; --i)
  853. {
  854. CMtPtLocal* pmtptl = (CMtPtLocal*)DPA_GetPtr(_hdpaMountPoints, i);
  855. if (pmtptl && pmtptl->_pvol)
  856. {
  857. if (!lstrcmpi(pmtptl->_pvol->pszDeviceIDVolume, pszDeviceIDVolume))
  858. {
  859. LPCWSTR pszMtPt = StrDup(pmtptl->_szName);
  860. if (pszMtPt)
  861. {
  862. if (-1 == DPA_AppendPtr(hdpaMtPts, (void*)pszMtPt))
  863. {
  864. LocalFree((HLOCAL)pszMtPt);
  865. }
  866. }
  867. }
  868. }
  869. }
  870. }
  871. _csLocalMtPtHDPA.Leave();
  872. return S_OK;
  873. }
  874. //static
  875. HRESULT CMountPoint::_CleanupLocalMtPtInfo()
  876. {
  877. _csDL.Enter();
  878. // We should Unadvise here but there's two problems: the ref counting
  879. // and we are probably here because CoUninitialize has been called, so
  880. // creating the IHardwareDevices interface'c component would probably fail
  881. _DeleteLocalMtPts();
  882. _DeleteVolumeInfo();
  883. _csDL.Leave();
  884. return S_OK;
  885. }
  886. // static
  887. HRESULT CMountPoint::_InitLocalDriveHelper()
  888. {
  889. #ifdef DEBUG
  890. // We should not try to enter the Drive Letter critical section on this thread.
  891. // We've already entered it on the thread that launched us, and
  892. // we should still be in there. The thread that launched us is waiting for
  893. // this thread to finish before going on. Trying to re-enter this critical
  894. // section from this thread will deadlock.
  895. DWORD dwThreadID = GetCurrentThreadId();
  896. _csDL.SetThreadIDToCheckForEntrance(dwThreadID);
  897. _csDL.FakeEnter();
  898. #endif
  899. IHardwareDevices* pihwdevs;
  900. HRESULT hr;
  901. BOOL fLoadedInDesktop = _Shell32LoadedInDesktop();
  902. if (fLoadedInDesktop)
  903. {
  904. hr = _GetHardwareDevices(&pihwdevs);
  905. }
  906. else
  907. {
  908. hr = S_FALSE;
  909. }
  910. if (SUCCEEDED(hr))
  911. {
  912. if (!_hdpaVolumes && !_fShuttingDown)
  913. {
  914. _hdpaVolumes = DPA_Create(3);
  915. }
  916. if (_hdpaVolumes)
  917. {
  918. if (SUCCEEDED(hr))
  919. {
  920. hr = _EnumVolumes(pihwdevs);
  921. if (SUCCEEDED(hr))
  922. {
  923. hr = _EnumMountPoints(pihwdevs);
  924. if (SUCCEEDED(hr))
  925. {
  926. _fLocalDrivesInited = TRUE;
  927. }
  928. else
  929. {
  930. _DeleteVolumeInfo();
  931. }
  932. }
  933. }
  934. }
  935. else
  936. {
  937. hr = E_OUTOFMEMORY;
  938. }
  939. if (fLoadedInDesktop)
  940. {
  941. pihwdevs->Release();
  942. }
  943. }
  944. #ifdef DEBUG
  945. _csDL.FakeLeave();
  946. _csDL.SetThreadIDToCheckForEntrance(0);
  947. #endif
  948. return hr;
  949. }
  950. DWORD WINAPI _FirstHardwareEnumThreadProc(void* pv)
  951. {
  952. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
  953. if (SUCCEEDED(hr))
  954. {
  955. hr = CMountPoint::_InitLocalDriveHelper();
  956. CoUninitialize();
  957. }
  958. return (DWORD)hr;
  959. }
  960. BOOL _InsideLoaderLock()
  961. {
  962. return (NtCurrentTeb()->ClientId.UniqueThread ==
  963. ((PRTL_CRITICAL_SECTION)(NtCurrentPeb()->LoaderLock))->OwningThread);
  964. }
  965. //static
  966. BOOL CMountPoint::_CanRegister()
  967. {
  968. if (!CMountPoint::_fCanRegisterWithShellService)
  969. {
  970. HANDLE hCanRegister = OpenEvent(SYNCHRONIZE, FALSE, TEXT("_fCanRegisterWithShellService"));
  971. if (hCanRegister)
  972. {
  973. CloseHandle(hCanRegister);
  974. }
  975. else
  976. {
  977. CMountPoint::_fCanRegisterWithShellService = TRUE;
  978. }
  979. }
  980. return CMountPoint::_fCanRegisterWithShellService;
  981. }
  982. //static
  983. HRESULT CMountPoint::_InitLocalDrives()
  984. {
  985. ASSERT(_csDL.IsInside());
  986. HRESULT hr = E_FAIL;
  987. BOOL fTryFullInit = FALSE;
  988. if (CMountPoint::_CanRegister())
  989. {
  990. if (!_dwTickCountTriedAndFailed)
  991. {
  992. // We didn't try full init yet
  993. fTryFullInit = TRUE;
  994. }
  995. else
  996. {
  997. // We already tried and failed doing a full init. Try again only if
  998. // it's been more than 5 seconds.
  999. if ((GetTickCount() - _dwTickCountTriedAndFailed) >
  1000. (5 * 1000))
  1001. {
  1002. fTryFullInit = TRUE;
  1003. }
  1004. }
  1005. if (fTryFullInit)
  1006. {
  1007. if (_Shell32LoadedInDesktop())
  1008. {
  1009. HANDLE hThread = CreateThread(NULL, 0, _FirstHardwareEnumThreadProc, NULL, 0, NULL);
  1010. if (hThread)
  1011. {
  1012. DWORD dwWait = WaitForSingleObject(hThread, INFINITE);
  1013. if (WAIT_FAILED != dwWait)
  1014. {
  1015. DWORD dwExitCode;
  1016. if (GetExitCodeThread(hThread, &dwExitCode))
  1017. {
  1018. hr = (HRESULT)dwExitCode;
  1019. }
  1020. }
  1021. CloseHandle(hThread);
  1022. }
  1023. if (SUCCEEDED(hr))
  1024. {
  1025. _dwTickCountTriedAndFailed = 0;
  1026. }
  1027. else
  1028. {
  1029. _dwTickCountTriedAndFailed = GetTickCount();
  1030. }
  1031. }
  1032. else
  1033. {
  1034. hr = _InitLocalDriveHelper();
  1035. _dwTickCountTriedAndFailed = 0;
  1036. }
  1037. }
  1038. }
  1039. if (FAILED(hr))
  1040. {
  1041. if (!_fNoVolLocalDrivesInited)
  1042. {
  1043. DWORD dwLogicalDrives = GetLogicalDrives();
  1044. for (DWORD dw = 0; dw < 26; ++dw)
  1045. {
  1046. if (dwLogicalDrives & (1 << dw))
  1047. {
  1048. WCHAR szDrive[4];
  1049. int iDriveType = GetDriveType(PathBuildRoot(szDrive, dw));
  1050. if ((DRIVE_REMOTE != iDriveType) && (DRIVE_UNKNOWN != iDriveType) &&
  1051. (DRIVE_NO_ROOT_DIR != iDriveType))
  1052. {
  1053. hr = CMtPtLocal::_CreateMtPtLocal(szDrive);
  1054. }
  1055. }
  1056. }
  1057. _fNoVolLocalDrivesInited = TRUE;
  1058. }
  1059. else
  1060. {
  1061. hr = S_FALSE;
  1062. }
  1063. }
  1064. return hr;
  1065. }
  1066. //static
  1067. DWORD CMountPoint::GetDrivesMask()
  1068. {
  1069. HRESULT hr = S_FALSE;
  1070. DWORD dwMask = 0;
  1071. _csDL.Enter();
  1072. if (!_fNetDrivesInited)
  1073. {
  1074. hr = _InitNetDrives();
  1075. }
  1076. if (!_fLocalDrivesInited)
  1077. {
  1078. hr = _InitLocalDrives();
  1079. }
  1080. if (SUCCEEDED(hr))
  1081. {
  1082. if (_Shell32LoadedInDesktop())
  1083. {
  1084. for (DWORD dw = 0; dw < 26; ++dw)
  1085. {
  1086. if (_rgMtPtDriveLetterLocal[dw] || _rgMtPtDriveLetterNet[dw])
  1087. {
  1088. dwMask |= (1 << dw);
  1089. }
  1090. }
  1091. }
  1092. else
  1093. {
  1094. dwMask = GetLogicalDrives() | _dwRememberedNetDrivesMask;
  1095. }
  1096. }
  1097. _csDL.Leave();
  1098. return dwMask;
  1099. }
  1100. //static
  1101. void CMountPoint::Initialize()
  1102. {
  1103. _csLocalMtPtHDPA.Init();
  1104. _csDL.Init();
  1105. _rsMtPtsLocalDL.RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2,
  1106. g_szCrossProcessCacheMtPtsLocalDLKey, REG_OPTION_VOLATILE);
  1107. _rsMtPtsRemote.RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2,
  1108. g_szCrossProcessCacheMtPtsRemoteKey, REG_OPTION_VOLATILE);
  1109. _rsMtPtsLocalMOF.RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2,
  1110. g_szCrossProcessCacheMtPtsLocalMOFKey, REG_OPTION_VOLATILE);
  1111. }
  1112. ///////////////////////////////////////////////////////////////////////////////
  1113. // For C caller
  1114. ///////////////////////////////////////////////////////////////////////////////
  1115. STDAPI_(void) CMtPt_FinalCleanUp()
  1116. {
  1117. CMountPoint::FinalCleanUp();
  1118. CMtPtLocal::FinalCleanUp();
  1119. }
  1120. STDAPI_(void) CMtPt_Initialize()
  1121. {
  1122. CMountPoint::Initialize();
  1123. CMtPtLocal::Initialize();
  1124. }
  1125. //static
  1126. void CMountPoint::FinalCleanUp()
  1127. {
  1128. if (_csDL.IsInitialized() && _csLocalMtPtHDPA.IsInitialized())
  1129. {
  1130. _csDL.Enter();
  1131. _fShuttingDown = TRUE;
  1132. _csLocalMtPtHDPA.Enter();
  1133. _DeleteLocalMtPts();
  1134. _DeleteVolumeInfo();
  1135. CMtPtRemote::_DeleteAllMtPtsAndShares();
  1136. _fNetDrivesInited = FALSE;
  1137. _csLocalMtPtHDPA._fShuttingDown = TRUE;
  1138. _csDL._fShuttingDown = TRUE;
  1139. _csLocalMtPtHDPA.Leave();
  1140. _csDL.Leave();
  1141. _csLocalMtPtHDPA.Delete();
  1142. _csDL.Delete();
  1143. CSniffDrive::CleanUp();
  1144. if (_hThreadSCN)
  1145. {
  1146. CloseHandle(_hThreadSCN);
  1147. _hThreadSCN = NULL;
  1148. }
  1149. }
  1150. if (_Shell32LoadedInDesktop())
  1151. {
  1152. _rsMtPtsLocalDL.RSDeleteKey();
  1153. _rsMtPtsLocalMOF.RSDeleteKey();
  1154. _rsMtPtsRemote.RSDeleteKey();
  1155. }
  1156. }
  1157. //static
  1158. BOOL CMountPoint::_IsNetDriveLazyLoadNetDLLs(int iDrive)
  1159. {
  1160. ASSERT(_csDL.IsInside());
  1161. BOOL fNetDrive = FALSE;
  1162. if (!_fNetDrivesInited)
  1163. {
  1164. HRESULT hr = S_FALSE;
  1165. WCHAR szPath[4];
  1166. // Try to avoid loading the net dlls
  1167. UINT uDriveType = GetDriveType(PathBuildRoot(szPath, iDrive));
  1168. if (DRIVE_NO_ROOT_DIR == uDriveType)
  1169. {
  1170. // This happens for Remembered drives
  1171. hr = _InitNetDrives();
  1172. if (SUCCEEDED(hr))
  1173. {
  1174. fNetDrive = BOOLFROMPTR(_rgMtPtDriveLetterNet[iDrive]);
  1175. }
  1176. }
  1177. else
  1178. {
  1179. if (DRIVE_REMOTE == uDriveType)
  1180. {
  1181. fNetDrive = TRUE;
  1182. }
  1183. }
  1184. }
  1185. else
  1186. {
  1187. fNetDrive = BOOLFROMPTR(_rgMtPtDriveLetterNet[iDrive]);
  1188. if (!_Shell32LoadedInDesktop())
  1189. {
  1190. DWORD dwAllDrives = GetLogicalDrives() | _dwRememberedNetDrivesMask;
  1191. if (fNetDrive)
  1192. {
  1193. // make sure it still exist
  1194. if (!(dwAllDrives & (1 << iDrive)))
  1195. {
  1196. // its' gone!
  1197. fNetDrive = FALSE;
  1198. }
  1199. else
  1200. {
  1201. WCHAR szPath[4];
  1202. // There's still a drive there, make sure it's not a local one
  1203. if (!(_dwRememberedNetDrivesMask & (1 << iDrive)) &&
  1204. !(GetDriveType(PathBuildRoot(szPath, iDrive)) == DRIVE_REMOTE))
  1205. {
  1206. fNetDrive = FALSE;
  1207. }
  1208. }
  1209. if (!fNetDrive && (_rgMtPtDriveLetterNet[iDrive]))
  1210. {
  1211. _rgMtPtDriveLetterNet[iDrive]->Release();
  1212. _rgMtPtDriveLetterNet[iDrive] = NULL;
  1213. }
  1214. }
  1215. else
  1216. {
  1217. // maybe it arrived after we enumerated
  1218. if (dwAllDrives & (1 << iDrive))
  1219. {
  1220. WCHAR szPath[4];
  1221. // Is it a remote drive?
  1222. if ((_dwRememberedNetDrivesMask & (1 << iDrive)) ||
  1223. (GetDriveType(PathBuildRoot(szPath, iDrive)) == DRIVE_REMOTE))
  1224. {
  1225. // indeed
  1226. _ReInitNetDrives();
  1227. fNetDrive = TRUE;
  1228. }
  1229. }
  1230. }
  1231. }
  1232. }
  1233. return fNetDrive;
  1234. }
  1235. // static
  1236. HRESULT CMountPoint::_RemoveLocalMountPoint(LPCWSTR pszMountPoint)
  1237. {
  1238. if (_IsDriveLetter(pszMountPoint))
  1239. {
  1240. _csDL.Enter();
  1241. int iDrive = DRIVEID(pszMountPoint);
  1242. CMtPtLocal* pmtptl = (CMtPtLocal*)_rgMtPtDriveLetterLocal[iDrive];
  1243. if (pmtptl)
  1244. {
  1245. _rgMtPtDriveLetterLocal[iDrive] = 0;
  1246. pmtptl->Release();
  1247. }
  1248. _csDL.Leave();
  1249. }
  1250. else
  1251. {
  1252. _csLocalMtPtHDPA.Enter();
  1253. if (_hdpaMountPoints)
  1254. {
  1255. DWORD c = DPA_GetPtrCount(_hdpaMountPoints);
  1256. for (int i = c - 1; i >= 0; --i)
  1257. {
  1258. CMtPtLocal* pmtptl = (CMtPtLocal*)DPA_GetPtr(_hdpaMountPoints, i);
  1259. if (pmtptl)
  1260. {
  1261. if (!lstrcmpi(pmtptl->_szName, pszMountPoint))
  1262. {
  1263. DPA_DeletePtr(_hdpaMountPoints, i);
  1264. pmtptl->Release();
  1265. break;
  1266. }
  1267. }
  1268. }
  1269. }
  1270. if (_Shell32LoadedInDesktop())
  1271. {
  1272. _rsMtPtsLocalMOF.RSDeleteValue(NULL, pszMountPoint);
  1273. }
  1274. _csLocalMtPtHDPA.Leave();
  1275. }
  1276. return S_OK;
  1277. }
  1278. // static
  1279. HRESULT CMountPoint::_RemoveNetMountPoint(LPCWSTR pszMountPoint)
  1280. {
  1281. _csDL.Enter();
  1282. int iDrive = DRIVEID(pszMountPoint);
  1283. if (_rgMtPtDriveLetterNet[iDrive])
  1284. {
  1285. _rgMtPtDriveLetterNet[iDrive]->Release();
  1286. _rgMtPtDriveLetterNet[iDrive] = 0;
  1287. }
  1288. _csDL.Leave();
  1289. return S_OK;
  1290. }
  1291. // static
  1292. BOOL CMountPoint::_CheckLocalMtPtsMOF(LPCWSTR pszMountPoint)
  1293. {
  1294. ASSERT(!_Shell32LoadedInDesktop());
  1295. return _rsMtPtsLocalMOF.RSValueExist(NULL, pszMountPoint);
  1296. }
  1297. //
  1298. // This needs to be called from the thread that will be used for APCs callbacks
  1299. // (stephstm: 2001/03/31)
  1300. // static
  1301. DWORD WINAPI CMountPoint::_RegisterThreadProc(void* pv)
  1302. {
  1303. ASSERT(_Shell32LoadedInDesktop());
  1304. HANDLE hThread = (HANDLE)pv;
  1305. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
  1306. if (SUCCEEDED(hr))
  1307. {
  1308. IHardwareDevices* pihwdevs;
  1309. hr = _GetHardwareDevices(&pihwdevs);
  1310. if (SUCCEEDED(hr))
  1311. {
  1312. hr = pihwdevs->Advise(GetCurrentProcessId(), (ULONG_PTR)hThread,
  1313. (ULONG_PTR)CMountPoint::_EventAPCProc, &_dwAdviseToken);
  1314. pihwdevs->Release();
  1315. }
  1316. CoUninitialize();
  1317. }
  1318. return (DWORD)hr;
  1319. }
  1320. // static
  1321. HRESULT CMountPoint::RegisterForHardwareNotifications()
  1322. {
  1323. HRESULT hr;
  1324. if (_Shell32LoadedInDesktop() && (-1 == _dwAdviseToken))
  1325. {
  1326. HANDLE hPseudoProcess = GetCurrentProcess();
  1327. // See comment above!
  1328. HANDLE hPseudoThread = GetCurrentThread();
  1329. hr = E_FAIL;
  1330. if (DuplicateHandle(hPseudoProcess, hPseudoThread, hPseudoProcess,
  1331. &_hThreadSCN, DUPLICATE_SAME_ACCESS, FALSE, 0))
  1332. {
  1333. HANDLE hThread = CreateThread(NULL, 0, _RegisterThreadProc, (void*)_hThreadSCN, 0, NULL);
  1334. CSniffDrive::Init(_hThreadSCN);
  1335. if (hThread)
  1336. {
  1337. DWORD dwWait = WaitForSingleObject(hThread, INFINITE);
  1338. if (WAIT_FAILED != dwWait)
  1339. {
  1340. DWORD dwExitCode;
  1341. if (GetExitCodeThread(hThread, &dwExitCode))
  1342. {
  1343. hr = (HRESULT)dwExitCode;
  1344. }
  1345. }
  1346. CloseHandle(hThread);
  1347. }
  1348. else
  1349. {
  1350. // We want to keep the handle around we'll uise it for something else.
  1351. }
  1352. }
  1353. }
  1354. else
  1355. {
  1356. hr = S_FALSE;
  1357. }
  1358. return hr;
  1359. }