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.

2786 lines
73 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include "shitemid.h"
  4. #include "ids.h"
  5. #include <ntddcdrm.h>
  6. #include "shpriv.h"
  7. #include "hwcmmn.h"
  8. #include "mtptl.h"
  9. #include "cdburn.h"
  10. #ifdef DEBUG
  11. DWORD CMtPtLocal::_cMtPtLocal = 0;
  12. DWORD CVolume::_cVolume = 0;
  13. #endif
  14. const static WCHAR g_szCrossProcessCacheVolumeKey[] = TEXT("CPC\\Volume");
  15. CRegSupport CMtPtLocal::_rsVolumes;
  16. HRESULT CMtPtLocal::SetLabel(HWND hwnd, LPCTSTR pszLabel)
  17. {
  18. HRESULT hr = E_FAIL;
  19. TraceMsg(TF_MOUNTPOINT, "CMtPtLocal::SetLabel: for '%s'", _GetNameDebug());
  20. if (SetVolumeLabel(_GetNameForFctCall(), pszLabel))
  21. {
  22. TraceMsg(TF_MOUNTPOINT, " 'SetVolumeLabel' succeeded");
  23. if ( !_fVolumePoint )
  24. {
  25. RSSetTextValue(NULL, TEXT("_LabelFromReg"), pszLabel,
  26. REG_OPTION_NON_VOLATILE);
  27. }
  28. if (!_CanUseVolume())
  29. {
  30. // we notify for only the current drive (no folder mounted drive)
  31. SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_PATH, _GetName(),
  32. _GetName());
  33. }
  34. hr = S_OK;
  35. }
  36. else
  37. {
  38. DWORD dwErr = GetLastError();
  39. switch (dwErr)
  40. {
  41. case ERROR_SUCCESS:
  42. break;
  43. case ERROR_ACCESS_DENIED:
  44. hr = S_FALSE; // don't have permission, shouldn't put them back into editing mode
  45. ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_ACCESSDENIED ),
  46. MAKEINTRESOURCE( IDS_TITLE_VOLUMELABELBAD ),
  47. MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
  48. break;
  49. case ERROR_WRITE_PROTECT:
  50. hr = S_FALSE; // can't write, shouldn't put them back into editing mode
  51. ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_WRITEPROTECTED ),
  52. MAKEINTRESOURCE( IDS_TITLE_VOLUMELABELBAD ),
  53. MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
  54. break;
  55. case ERROR_LABEL_TOO_LONG:
  56. ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_ERR_VOLUMELABELBAD ),
  57. MAKEINTRESOURCE( IDS_TITLE_VOLUMELABELBAD ),
  58. MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
  59. break;
  60. case ERROR_UNRECOGNIZED_VOLUME:
  61. hr = S_FALSE; // can't write, shouldn't put them back into editing mode
  62. ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_ERR_VOLUMEUNFORMATTED ),
  63. MAKEINTRESOURCE( IDS_TITLE_VOLUMELABELBAD ),
  64. MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
  65. break;
  66. default:
  67. ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_BADLABEL ),
  68. MAKEINTRESOURCE( IDS_TITLE_VOLUMELABELBAD ),
  69. MB_OK | MB_ICONSTOP | MB_SETFOREGROUND);
  70. break;
  71. }
  72. TraceMsg(TF_MOUNTPOINT, " 'SetVolumeLabel' failed");
  73. }
  74. return hr;
  75. }
  76. HRESULT CMtPtLocal::SetDriveLabel(HWND hwnd, LPCTSTR pszLabel)
  77. {
  78. HRESULT hr = E_FAIL;
  79. if ((_IsFloppy() || !_IsMediaPresent()) && _IsMountedOnDriveLetter())
  80. {
  81. // we rename the drive not the media
  82. TCHAR szSubKey[MAX_PATH];
  83. wnsprintf(szSubKey, ARRAYSIZE(szSubKey),
  84. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%c\\DefaultLabel"),
  85. _GetNameFirstCharUCase());
  86. hr = RegSetValueString(HKEY_LOCAL_MACHINE, szSubKey, NULL, pszLabel) ? S_OK : E_FAIL;
  87. if (SUCCEEDED(hr))
  88. {
  89. LocalFree(_pszLegacyRegLabel); // may be NULL
  90. _pszLegacyRegLabel = *pszLabel ? StrDup(pszLabel) : NULL; // empty string resets
  91. SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_PATH, _GetName(), _GetName());
  92. }
  93. }
  94. else
  95. {
  96. hr = SetLabel(hwnd, pszLabel);
  97. }
  98. return hr;
  99. }
  100. HRESULT CMtPtLocal::GetLabelNoFancy(LPTSTR pszLabel, DWORD cchLabel)
  101. {
  102. HRESULT hr = S_OK;
  103. if (!_GetGVILabelOrMixedCaseFromReg(pszLabel, cchLabel))
  104. {
  105. *pszLabel = 0;
  106. // Propagate failure code out for caller
  107. hr = E_FAIL;
  108. }
  109. return hr;
  110. }
  111. BOOL _ShowUglyDriveNames()
  112. {
  113. static BOOL s_fShowUglyDriveNames = (BOOL)42; // Preload some value to say lets calculate...
  114. if (s_fShowUglyDriveNames == (BOOL)42)
  115. {
  116. int iACP;
  117. TCHAR szTemp[MAX_PATH]; // Nice large buffer
  118. if (GetLocaleInfo(GetUserDefaultLCID(), LOCALE_IDEFAULTANSICODEPAGE, szTemp, ARRAYSIZE(szTemp)))
  119. {
  120. iACP = StrToInt(szTemp);
  121. // per Samer Arafeh, show ugly name for 1256 (Arabic ACP)
  122. if (iACP == 1252 || iACP == 1254 || iACP == 1255 || iACP == 1257 || iACP == 1258)
  123. goto TryLoadString;
  124. else
  125. s_fShowUglyDriveNames = TRUE;
  126. }
  127. else
  128. {
  129. TryLoadString:
  130. // All indications are that we can use pretty drive names.
  131. // Double-check that the localizers didn't corrupt the chars.
  132. LoadString(HINST_THISDLL, IDS_DRIVES_UGLY_TEST, szTemp, ARRAYSIZE(szTemp));
  133. // If the characters did not come through properly set ugly mode...
  134. s_fShowUglyDriveNames = (szTemp[0] != 0x00BC || szTemp[1] != 0x00BD);
  135. }
  136. }
  137. return s_fShowUglyDriveNames;
  138. }
  139. BOOL CMtPtLocal::_HasAutorunLabel()
  140. {
  141. BOOL fRet = FALSE;
  142. if (_CanUseVolume())
  143. {
  144. fRet = BOOLFROMPTR(_pvol->pszAutorunLabel) &&
  145. *(_pvol->pszAutorunLabel);
  146. }
  147. return fRet;
  148. }
  149. BOOL CMtPtLocal::_HasAutorunIcon()
  150. {
  151. BOOL fRet = FALSE;
  152. if (_CanUseVolume())
  153. {
  154. fRet = BOOLFROMPTR(_pvol->pszAutorunIconLocation) &&
  155. *(_pvol->pszAutorunIconLocation);
  156. }
  157. return fRet;
  158. }
  159. void CMtPtLocal::_GetAutorunLabel(LPWSTR pszLabel, DWORD cchLabel)
  160. {
  161. ASSERT(_CanUseVolume());
  162. lstrcpyn(pszLabel, _pvol->pszAutorunLabel, cchLabel);
  163. }
  164. HRESULT CMtPtLocal::GetLabel(LPTSTR pszLabel, DWORD cchLabel)
  165. {
  166. HRESULT hr = S_OK;
  167. BOOL fFoundIt = FALSE;
  168. // Autorun first
  169. // Fancy icon (Autoplay) second
  170. // True label from drive for non-removable
  171. // Legacy drive icons third
  172. // Regular last
  173. if (_HasAutorunLabel())
  174. {
  175. _GetAutorunLabel(pszLabel, cchLabel);
  176. fFoundIt = TRUE;
  177. }
  178. if (!fFoundIt)
  179. {
  180. if (!_IsFloppy())
  181. {
  182. if (!_GetGVILabelOrMixedCaseFromReg(pszLabel, cchLabel))
  183. {
  184. *pszLabel = 0;
  185. }
  186. else
  187. {
  188. if (*pszLabel)
  189. {
  190. fFoundIt = TRUE;
  191. }
  192. }
  193. }
  194. }
  195. if (!fFoundIt)
  196. {
  197. fFoundIt = _GetLegacyRegLabel(pszLabel, cchLabel);
  198. }
  199. if (!fFoundIt)
  200. {
  201. if (!_IsFloppy())
  202. {
  203. if (_CanUseVolume())
  204. {
  205. if (_pvol->pszLabelFromService)
  206. {
  207. if (SUCCEEDED(SHLoadIndirectString(_pvol->pszLabelFromService, pszLabel,
  208. cchLabel, NULL)))
  209. {
  210. fFoundIt = TRUE;
  211. }
  212. else
  213. {
  214. *pszLabel = 0;
  215. }
  216. }
  217. }
  218. }
  219. }
  220. if (!fFoundIt)
  221. {
  222. if (_CanUseVolume() && (HWDTS_CDROM == _pvol->dwDriveType))
  223. {
  224. fFoundIt = _GetCDROMName(pszLabel, cchLabel);
  225. }
  226. }
  227. if (!fFoundIt)
  228. {
  229. if (_IsFloppy())
  230. {
  231. // For some weird reason we have wo sets of "ugly" name for floppies,
  232. // the other is in GetTypeString
  233. UINT id;
  234. if (_IsFloppy35())
  235. {
  236. id = _ShowUglyDriveNames() ? IDS_35_FLOPPY_DRIVE_UGLY : IDS_35_FLOPPY_DRIVE;
  237. }
  238. else
  239. {
  240. id = _ShowUglyDriveNames() ? IDS_525_FLOPPY_DRIVE_UGLY : IDS_525_FLOPPY_DRIVE;
  241. }
  242. LoadString(HINST_THISDLL, id, pszLabel, cchLabel);
  243. }
  244. else
  245. {
  246. // Cook up a default name
  247. GetTypeString(pszLabel, cchLabel);
  248. }
  249. }
  250. return hr;
  251. }
  252. HRESULT CMtPtLocal::Eject(HWND hwnd)
  253. {
  254. TCHAR szNameForError[MAX_DISPLAYNAME];
  255. GetDisplayName(szNameForError, ARRAYSIZE(szNameForError));
  256. return _Eject(hwnd, szNameForError);
  257. }
  258. BOOL CMtPtLocal::HasMedia()
  259. {
  260. return _IsMediaPresent();
  261. }
  262. BOOL CMtPtLocal::IsFormatted()
  263. {
  264. return _IsFormatted();
  265. }
  266. BOOL CMtPtLocal::IsEjectable()
  267. {
  268. BOOL fIsEjectable = FALSE;
  269. if (_IsCDROM())
  270. {
  271. fIsEjectable = TRUE;
  272. }
  273. else
  274. {
  275. // Floppies are not Software ejectable
  276. if (_IsStrictRemovable())
  277. {
  278. fIsEjectable = TRUE;
  279. }
  280. else
  281. {
  282. if (_IsFloppy())
  283. {
  284. if (_CanUseVolume() && (HWDDC_FLOPPYSOFTEJECT & _pvol->dwDriveCapability))
  285. {
  286. if (_IsMediaPresent())
  287. {
  288. fIsEjectable = TRUE;
  289. }
  290. }
  291. }
  292. }
  293. }
  294. if (fIsEjectable)
  295. {
  296. if (_CanUseVolume())
  297. {
  298. if (HWDDC_NOSOFTEJECT & _pvol->dwDriveCapability)
  299. {
  300. fIsEjectable = FALSE;
  301. }
  302. }
  303. }
  304. return fIsEjectable;
  305. }
  306. HRESULT CMtPtLocal::GetCDInfo(DWORD* pdwDriveCapabilities, DWORD* pdwMediaCapabilities)
  307. {
  308. HRESULT hr;
  309. *pdwDriveCapabilities = 0;
  310. *pdwMediaCapabilities = 0;
  311. if (_IsCDROM())
  312. {
  313. if (_CanUseVolume())
  314. {
  315. if (HWDDC_CAPABILITY_SUPPORTDETECTION & _pvol->dwDriveCapability)
  316. {
  317. *pdwDriveCapabilities = (_pvol->dwDriveCapability & HWDDC_CDTYPEMASK);
  318. if (HWDMC_WRITECAPABILITY_SUPPORTDETECTION & _pvol->dwMediaCap)
  319. {
  320. *pdwMediaCapabilities = (_pvol->dwMediaCap & HWDMC_CDTYPEMASK);
  321. }
  322. hr = S_OK;
  323. }
  324. else
  325. {
  326. // in the case where we really dont know, see if the IMAPI info cached in the
  327. // registry has what we want.
  328. hr = CDBurn_GetCDInfo(_pvol->pszVolumeGUID, pdwDriveCapabilities, pdwMediaCapabilities);
  329. }
  330. }
  331. else
  332. {
  333. hr = S_FALSE;
  334. }
  335. }
  336. else
  337. {
  338. hr = E_FAIL;
  339. }
  340. return hr;
  341. }
  342. // Put all these together
  343. BOOL CMtPtLocal::_IsDVDDisc()
  344. {
  345. BOOL fRet = FALSE;
  346. if (_CanUseVolume())
  347. {
  348. if (HWDMC_HASDVDMOVIE & _pvol->dwMediaCap)
  349. {
  350. fRet = TRUE;
  351. }
  352. }
  353. // else In safe boot we don't care about Audio Disc
  354. return fRet;
  355. }
  356. BOOL CMtPtLocal::_IsWritableDisc()
  357. {
  358. BOOL fRet = FALSE;
  359. DWORD dwDriveCaps, dwMediaCaps;
  360. if ((S_OK == GetCDInfo(&dwDriveCaps, &dwMediaCaps)) &&
  361. ((HWDMC_CDRECORDABLE | HWDMC_CDREWRITABLE) & dwMediaCaps))
  362. {
  363. fRet = TRUE;
  364. }
  365. return fRet;
  366. }
  367. BOOL CMtPtLocal::_IsRemovableDevice()
  368. {
  369. BOOL fRet = FALSE;
  370. if (_CanUseVolume())
  371. {
  372. if (HWDDC_REMOVABLEDEVICE & _pvol->dwDriveCapability)
  373. {
  374. fRet = TRUE;
  375. }
  376. }
  377. return fRet;
  378. }
  379. // We keep the functionality we had before: a drive is Autorun only if it has
  380. // a Autorun.inf in the root when inserted. If it acquires one after, too bad.
  381. BOOL CMtPtLocal::_IsAutorun()
  382. {
  383. BOOL fRet = FALSE;
  384. if (_CanUseVolume())
  385. {
  386. if ((HWDMC_HASAUTORUNINF & _pvol->dwMediaCap) &&
  387. (HWDMC_HASAUTORUNCOMMAND & _pvol->dwMediaCap) &&
  388. !(HWDMC_HASUSEAUTOPLAY & _pvol->dwMediaCap))
  389. {
  390. fRet = TRUE;
  391. }
  392. }
  393. else
  394. {
  395. WCHAR szAutorun[MAX_PATH];
  396. DWORD dwErrMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  397. lstrcpyn(szAutorun, _GetNameForFctCall(), ARRAYSIZE(szAutorun));
  398. StrCatBuff(szAutorun, TEXT("autorun.inf"), ARRAYSIZE(szAutorun));
  399. if (-1 != GetFileAttributes(szAutorun))
  400. {
  401. fRet = TRUE;
  402. }
  403. SetErrorMode(dwErrMode);
  404. }
  405. return fRet;
  406. }
  407. // try to rename it
  408. BOOL CMtPtLocal::_IsAudioDisc()
  409. {
  410. BOOL fRet = FALSE;
  411. if (_CanUseVolume())
  412. {
  413. if (HWDMC_HASAUDIOTRACKS & _pvol->dwMediaCap)
  414. {
  415. fRet = TRUE;
  416. }
  417. }
  418. // else In safe boot we don't care about Audio Disc
  419. return fRet;
  420. }
  421. LPCTSTR CMtPtLocal::_GetNameForFctCall()
  422. {
  423. LPCTSTR psz;
  424. if (_CanUseVolume())
  425. {
  426. psz = _pvol->pszVolumeGUID;
  427. }
  428. else
  429. {
  430. psz = _szName;
  431. }
  432. return psz;
  433. }
  434. HRESULT CMtPtLocal::_Eject(HWND hwnd, LPTSTR pszMountPointNameForError)
  435. {
  436. HRESULT hr = E_FAIL;
  437. #ifndef _WIN64
  438. // NTRAID#NTBUG9-093957-2000/09/08-StephStm Code temporarily disabled for Win64
  439. // MCI is not 64bit ready. It crashes.
  440. // We do this check to see if the CD will accept an IOCTL to eject it.
  441. // Old CD drives do not. On W2K ssince the IOCTL was not implemented they use
  442. // to all say 'no'. I assumne that on ia64 machine they will have recent CD
  443. // drives. I call the IOCTL for them. It works now, and it's certainly better
  444. // than the crash we get using MCI, worst come to worst it will silently fail.
  445. if (IsEjectable())
  446. {
  447. #endif //_WIN64
  448. // it is a protect mode drive that we can tell directly...
  449. if (_IsCDROM())
  450. {
  451. HANDLE h = _GetHandleReadRead();
  452. if (INVALID_HANDLE_VALUE != h)
  453. {
  454. DWORD dwReturned;
  455. DeviceIoControl(h, IOCTL_DISK_EJECT_MEDIA, NULL, 0, NULL, 0,
  456. &dwReturned, NULL);
  457. CloseHandle(h);
  458. }
  459. hr = S_OK;
  460. }
  461. else
  462. {
  463. // For removable drives, we want to do all the calls on a single
  464. // handle, thus we can't do lots of calls to DeviceIoControl.
  465. // Instead, use the helper routines to do our work...
  466. // Don't bring up any error message if the user already chose to abort.
  467. BOOL fAborted = FALSE;
  468. BOOL fFailed = TRUE;
  469. HANDLE h = _GetHandleWithAccessAndShareMode(GENERIC_READ,
  470. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE);
  471. if (INVALID_HANDLE_VALUE != h)
  472. {
  473. DWORD dwReturned;
  474. _RETRY_LOCK_VOLUME_:
  475. // Now try to lock the drive...
  476. //
  477. // In theory, if no filesystem was mounted, the IOCtl command could go
  478. // to the device, which would fail with ERROR_INVALID_FUNCTION. If that
  479. // occured, we would still want to proceed, since the device might still
  480. // be able to handle the IOCTL_DISK_EJECT_MEDIA command below.
  481. //
  482. if (!DeviceIoControl(h, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0,
  483. &dwReturned, NULL) && (GetLastError() != ERROR_INVALID_FUNCTION))
  484. {
  485. // So we can't lock the drive, bring up a message box to see if user
  486. // wants to
  487. // 1. Abort.
  488. // 2. Retry to lock the drive.
  489. // 3. Dismount anyway.
  490. WCHAR szLabelForMessage[MAX_LABEL];
  491. szLabelForMessage[0] = 0;
  492. if (_CanUseVolume() && (_pvol->pszLabelFromService))
  493. {
  494. lstrcpyn(szLabelForMessage, _pvol->pszLabelFromService, ARRAYSIZE(szLabelForMessage));
  495. }
  496. if (!(szLabelForMessage[0]))
  497. {
  498. GetTypeString(szLabelForMessage, ARRAYSIZE(szLabelForMessage));
  499. LPTSTR psz = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_VOL_FORMAT),
  500. szLabelForMessage, _GetNameFirstCharUCase());
  501. if (psz)
  502. {
  503. StrCpyN(szLabelForMessage, psz, ARRAYSIZE(szLabelForMessage));
  504. LocalFree(psz);
  505. }
  506. else
  507. {
  508. StrCpyN(szLabelForMessage, pszMountPointNameForError, ARRAYSIZE(szLabelForMessage));
  509. }
  510. }
  511. int iRet = ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_UNMOUNT_TEXT ),
  512. pszMountPointNameForError, MB_CANCELTRYCONTINUE | MB_ICONWARNING | MB_SETFOREGROUND,
  513. szLabelForMessage);
  514. switch (iRet)
  515. {
  516. case IDCANCEL:
  517. // we did not fail, we aborted the format
  518. fFailed = FALSE;
  519. fAborted = TRUE;
  520. break;
  521. case IDCONTINUE:
  522. // send FSCTL_DISMOUNT_VOLUME
  523. if (!DeviceIoControl(h, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwReturned, NULL))
  524. {
  525. TraceMsg(TF_WARNING, "FSCTL_DISMOUNT_VOLUME failed with error %d.", GetLastError());
  526. fFailed = TRUE;
  527. break;
  528. }
  529. // We sucessfully dismounted the volume, so the h we have is not valid anymore. We
  530. // therefore close it and start the process all over again, hoping to lock the volume before
  531. // anyone re-opens a handle to it
  532. //
  533. // (fall through)
  534. case IDTRYAGAIN:
  535. goto _RETRY_LOCK_VOLUME_;
  536. }
  537. }
  538. else
  539. {
  540. ASSERT(!fAborted); // should not have aborted if we got this far...
  541. fFailed = FALSE;
  542. }
  543. if (!fFailed && !fAborted)
  544. {
  545. PREVENT_MEDIA_REMOVAL pmr;
  546. pmr.PreventMediaRemoval = FALSE;
  547. // tell the drive to allow removal, then eject
  548. if (!DeviceIoControl(h, IOCTL_STORAGE_MEDIA_REMOVAL, &pmr, sizeof(pmr), NULL, 0, &dwReturned, NULL) ||
  549. !DeviceIoControl(h, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &dwReturned, NULL))
  550. {
  551. ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_EJECT_TEXT ),
  552. MAKEINTRESOURCE( IDS_EJECT_TITLE ),
  553. MB_OK | MB_ICONSTOP | MB_SETFOREGROUND, pszMountPointNameForError);
  554. }
  555. else
  556. {
  557. hr = S_OK;
  558. }
  559. }
  560. CloseHandle(h);
  561. }
  562. if (fFailed)
  563. {
  564. ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE( IDS_UNMOUNT_TEXT ),
  565. MAKEINTRESOURCE( IDS_UNMOUNT_TITLE ),
  566. MB_OK | MB_ICONSTOP | MB_SETFOREGROUND, pszMountPointNameForError);
  567. }
  568. }
  569. #ifndef _WIN64
  570. }
  571. else
  572. {
  573. // Is this needed anymore?
  574. // See comment above for why this is ifdef'ed out on Win64
  575. // (stephstm) only works for drive mounted on letter
  576. TCHAR szMCI[128];
  577. wsprintf(szMCI, TEXT("Open %c: type cdaudio alias foo shareable"),
  578. _GetNameFirstCharUCase());
  579. if (mciSendString(szMCI, NULL, 0, 0L) == MMSYSERR_NOERROR)
  580. {
  581. mciSendString(TEXT("set foo door open"), NULL, 0, 0L);
  582. mciSendString(TEXT("close foo"), NULL, 0, 0L);
  583. hr = S_OK;
  584. }
  585. }
  586. #endif //_WIN64
  587. return hr;
  588. }
  589. ///////////////////////////////////////////////////////////////////////////////
  590. // New //////////////////////////////////////////////////////////////////////
  591. ///////////////////////////////////////////////////////////////////////////////
  592. BOOL CMtPtLocal::_GetFileAttributes(DWORD* pdwAttrib)
  593. {
  594. BOOL fRet = FALSE;
  595. BOOL fDoRead = FALSE;
  596. *pdwAttrib = -1;
  597. if (_CanUseVolume() && !_IsFloppy())
  598. {
  599. if (_IsMediaPresent() && _IsFormatted())
  600. {
  601. if (_IsReadOnly())
  602. {
  603. // The file attrib we received at the begginning should be
  604. // valid, do not touch the drive for nothing
  605. *pdwAttrib = _pvol->dwRootAttributes;
  606. fRet = TRUE;
  607. }
  608. else
  609. {
  610. fDoRead = TRUE;
  611. }
  612. }
  613. }
  614. else
  615. {
  616. fDoRead = TRUE;
  617. }
  618. if (fDoRead)
  619. {
  620. DWORD dw = GetFileAttributes(_GetNameForFctCall());
  621. if (-1 != dw)
  622. {
  623. *pdwAttrib = dw;
  624. fRet = TRUE;
  625. }
  626. }
  627. return fRet;
  628. }
  629. // { DRIVE_ISCOMPRESSIBLE | DRIVE_LFN | DRIVE_SECURITY }
  630. int CMtPtLocal::_GetGVIDriveFlags()
  631. {
  632. int iFlags = 0;
  633. DWORD dwFileSystemFlags = 0;
  634. DWORD dwMaxFileNameLen = 13;
  635. if (_CanUseVolume() && (_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION))
  636. {
  637. if (_IsMediaPresent() && _IsFormatted())
  638. {
  639. // No check for _IsReadOnly, we'll be notified if there's a format
  640. dwFileSystemFlags = _pvol->dwFileSystemFlags;
  641. dwMaxFileNameLen = _pvol->dwMaxFileNameLen;
  642. }
  643. }
  644. else
  645. {
  646. if (!GetVolumeInformation(_GetNameForFctCall(), NULL, 0, NULL,
  647. &dwMaxFileNameLen, &dwFileSystemFlags, NULL, NULL))
  648. {
  649. // Just make sure
  650. dwMaxFileNameLen = 13;
  651. }
  652. }
  653. // The file attrib we received at the begginning should be
  654. // valid, do not touch the drive for nothing
  655. if (dwFileSystemFlags & FS_FILE_COMPRESSION)
  656. {
  657. iFlags |= DRIVE_ISCOMPRESSIBLE;
  658. }
  659. // Volume supports long filename (greater than 8.3)?
  660. if (dwMaxFileNameLen > 12)
  661. {
  662. iFlags |= DRIVE_LFN;
  663. }
  664. // Volume supports security?
  665. if (dwFileSystemFlags & FS_PERSISTENT_ACLS)
  666. {
  667. iFlags |= DRIVE_SECURITY;
  668. }
  669. return iFlags;
  670. }
  671. BOOL CMtPtLocal::_GetGVILabel(LPTSTR pszLabel, DWORD cchLabel)
  672. {
  673. BOOL fRet = FALSE;
  674. *pszLabel = 0;
  675. if (_CanUseVolume() && (_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION))
  676. {
  677. if (_IsMediaPresent() && _IsFormatted())
  678. {
  679. // No check for _IsReadOnly, we'll be notified if there's a change
  680. // of label
  681. lstrcpyn(pszLabel, _pvol->pszLabel, cchLabel);
  682. fRet = TRUE;
  683. }
  684. }
  685. else
  686. {
  687. fRet = GetVolumeInformation(_GetNameForFctCall(), pszLabel, cchLabel,
  688. NULL, NULL, NULL, NULL, NULL);
  689. }
  690. return fRet;
  691. }
  692. BOOL CMtPtLocal::_GetSerialNumber(DWORD* pdwSerialNumber)
  693. {
  694. BOOL fRet = FALSE;
  695. if (_CanUseVolume() && (_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION))
  696. {
  697. if (_IsMediaPresent() && _IsFormatted())
  698. {
  699. *pdwSerialNumber = _pvol->dwSerialNumber;
  700. fRet = TRUE;
  701. }
  702. }
  703. else
  704. {
  705. fRet = GetVolumeInformation(_GetNameForFctCall(), NULL, 0,
  706. pdwSerialNumber, NULL, NULL, NULL, NULL);
  707. }
  708. return fRet;
  709. }
  710. BOOL CMtPtLocal::_GetGVILabelOrMixedCaseFromReg(LPTSTR pszLabel, DWORD cchLabel)
  711. {
  712. BOOL fRet = FALSE;
  713. *pszLabel = 0;
  714. fRet = _GetGVILabel(pszLabel, cchLabel);
  715. if (fRet)
  716. {
  717. WCHAR szLabelFromReg[MAX_LABEL];
  718. // Do we already have a label from the registry for this volume?
  719. // (the user may have renamed this drive)
  720. if (_GetLabelFromReg(szLabelFromReg, ARRAYSIZE(szLabelFromReg)) &&
  721. szLabelFromReg[0])
  722. {
  723. // Yes
  724. // Do they match (only diff in case)
  725. if (lstrcmpi(szLabelFromReg, pszLabel) == 0)
  726. {
  727. // Yes
  728. lstrcpyn(pszLabel, szLabelFromReg, cchLabel);
  729. }
  730. }
  731. }
  732. return fRet;
  733. }
  734. BOOL CMtPtLocal::_GetFileSystemFlags(DWORD* pdwFlags)
  735. {
  736. BOOL fRet = FALSE;
  737. DWORD dwFileSystemFlags = 0;
  738. *pdwFlags = 0;
  739. if (_CanUseVolume() && (_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION))
  740. {
  741. if (_IsMediaPresent() && _IsFormatted())
  742. {
  743. // No check for _IsReadOnly, we'll be notified if there's a
  744. // format oper.
  745. *pdwFlags = _pvol->dwFileSystemFlags;
  746. fRet = TRUE;
  747. }
  748. }
  749. else
  750. {
  751. if (GetVolumeInformation(_GetNameForFctCall(), NULL, 0, NULL,
  752. NULL, pdwFlags, NULL, NULL))
  753. {
  754. fRet = TRUE;
  755. }
  756. }
  757. return fRet;
  758. }
  759. BOOL CMtPtLocal::_GetFileSystemName(LPTSTR pszFileSysName, DWORD cchFileSysName)
  760. {
  761. BOOL fRet = FALSE;
  762. *pszFileSysName = 0;
  763. if (_CanUseVolume() && (_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION))
  764. {
  765. if (_IsMediaPresent() && _IsFormatted())
  766. {
  767. StrCpyN(pszFileSysName, _pvol->pszFileSystem, cchFileSysName);
  768. fRet = TRUE;
  769. }
  770. }
  771. else
  772. {
  773. if (GetVolumeInformation(_GetNameForFctCall(),
  774. NULL,
  775. 0,
  776. NULL,
  777. NULL,
  778. NULL,
  779. pszFileSysName,
  780. cchFileSysName))
  781. {
  782. fRet = TRUE;
  783. }
  784. }
  785. return fRet;
  786. }
  787. struct CDROMICONS
  788. {
  789. DWORD dwCap;
  790. UINT iIcon;
  791. UINT iName;
  792. };
  793. // Go from most wonderful caps to less wonderful (according to stepshtm)
  794. // Keep in order, it is verrrrry important
  795. const CDROMICONS rgMediaPresent[] =
  796. {
  797. // Specfic content
  798. { HWDMC_HASDVDMOVIE, -IDI_AP_VIDEO, 0}, // we display the DVD media icon,
  799. // since it will most likely be
  800. // replaced by an icon from the DVD itself
  801. { HWDMC_HASAUDIOTRACKS | HWDMC_HASDATATRACKS, -IDI_MEDIACDAUDIOPLUS, 0},
  802. { HWDMC_HASAUDIOTRACKS, -IDI_CDAUDIO, 0 },
  803. { HWDMC_HASAUTORUNINF, -IDI_DRIVECD, 0 },
  804. // Specific media
  805. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_DVDRAM, -IDI_MEDIADVDRAM, 0 },
  806. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_DVDRECORDABLE, -IDI_MEDIADVDR, 0 },
  807. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_DVDREWRITABLE, -IDI_MEDIADVDRW, 0 },
  808. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_DVDROM, -IDI_MEDIADVDROM, 0 },
  809. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_CDREWRITABLE, -IDI_MEDIACDRW, 0 },
  810. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_CDRECORDABLE, -IDI_MEDIACDR, 0 },
  811. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDMC_CDROM, -IDI_MEDIACDROM, 0 },
  812. };
  813. // Keep in order, it is verrrrry important
  814. const CDROMICONS rgNoMedia[] =
  815. {
  816. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDRAM, -IDI_DRIVECD, IDS_DRIVES_DVDRAM },
  817. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDRECORDABLE, -IDI_DRIVECD, IDS_DRIVES_DVDR },
  818. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDREWRITABLE, -IDI_DRIVECD, IDS_DRIVES_DVDRW },
  819. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDROM | HWDDC_CDREWRITABLE, -IDI_DRIVECD, IDS_DRIVES_DVDCDRW },
  820. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDROM | HWDDC_CDRECORDABLE, -IDI_DRIVECD, IDS_DRIVES_DVDCDR },
  821. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_DVDROM, -IDI_DVDDRIVE, IDS_DRIVES_DVD },
  822. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_CDREWRITABLE, -IDI_DRIVECD, IDS_DRIVES_CDRW },
  823. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_CDRECORDABLE, -IDI_DRIVECD, IDS_DRIVES_CDR },
  824. { HWDMC_WRITECAPABILITY_SUPPORTDETECTION | HWDDC_CDROM, -IDI_DRIVECD, IDS_DRIVES_CDROM },
  825. };
  826. UINT _GetCDROMIconFromArray(DWORD dwCap, const CDROMICONS* prgcdromicons,
  827. DWORD ccdromicons)
  828. {
  829. UINT iIcon = 0;
  830. for (DWORD dw = 0; dw < ccdromicons; ++dw)
  831. {
  832. if ((prgcdromicons[dw].dwCap & dwCap) == prgcdromicons[dw].dwCap)
  833. {
  834. iIcon = prgcdromicons[dw].iIcon;
  835. break;
  836. }
  837. }
  838. return iIcon;
  839. }
  840. UINT _GetCDROMNameFromArray(DWORD dwCap)
  841. {
  842. UINT iName = 0;
  843. for (DWORD dw = 0; dw < ARRAYSIZE(rgNoMedia); ++dw)
  844. {
  845. if ((rgNoMedia[dw].dwCap & dwCap) == rgNoMedia[dw].dwCap)
  846. {
  847. iName = rgNoMedia[dw].iName;
  848. break;
  849. }
  850. }
  851. return iName;
  852. }
  853. UINT CMtPtLocal::_GetCDROMIcon()
  854. {
  855. int iIcon;
  856. if (_IsMediaPresent())
  857. {
  858. ASSERT(_CanUseVolume());
  859. iIcon = _GetCDROMIconFromArray(_pvol->dwMediaCap, rgMediaPresent,
  860. ARRAYSIZE(rgMediaPresent));
  861. if (!iIcon)
  862. {
  863. iIcon = -IDI_DRIVECD;
  864. }
  865. }
  866. else
  867. {
  868. ASSERT(_CanUseVolume());
  869. iIcon = _GetCDROMIconFromArray(_pvol->dwDriveCapability, rgNoMedia,
  870. ARRAYSIZE(rgNoMedia));
  871. if (!iIcon)
  872. {
  873. // No media generic CD icon
  874. iIcon = -IDI_DRIVECD;
  875. }
  876. }
  877. return iIcon;
  878. }
  879. BOOL CMtPtLocal::_GetCDROMName(LPWSTR pszName, DWORD cchName)
  880. {
  881. BOOL fRet = FALSE;
  882. *pszName = 0;
  883. if (!_IsMediaPresent())
  884. {
  885. ASSERT(_CanUseVolume());
  886. UINT iName = _GetCDROMNameFromArray(_pvol->dwDriveCapability);
  887. if (iName)
  888. {
  889. fRet = LoadString(HINST_THISDLL, iName, pszName, cchName);
  890. }
  891. }
  892. return fRet;
  893. }
  894. UINT CMtPtLocal::_GetAutorunIcon(LPTSTR pszModule, DWORD cchModule)
  895. {
  896. int iIcon = -1;
  897. ASSERT(_CanUseVolume());
  898. if (_pvol->pszAutorunIconLocation)
  899. {
  900. lstrcpyn(pszModule, _GetName(), cchModule);
  901. StrCatBuff(pszModule, _pvol->pszAutorunIconLocation, cchModule);
  902. iIcon = PathParseIconLocation(pszModule);
  903. }
  904. return iIcon;
  905. }
  906. UINT CMtPtLocal::GetIcon(LPTSTR pszModule, DWORD cchModule)
  907. {
  908. UINT iIcon = -IDI_DRIVEUNKNOWN;
  909. *pszModule = 0;
  910. if (_CanUseVolume())
  911. {
  912. // Autorun first
  913. // Fancy icon (Autoplay) second
  914. // Legacy drive icons last
  915. if (_HasAutorunIcon())
  916. {
  917. iIcon = _GetAutorunIcon(pszModule, cchModule);
  918. }
  919. if (-IDI_DRIVEUNKNOWN == iIcon)
  920. {
  921. // Try fancy icon
  922. if (!_IsFloppy())
  923. {
  924. if (_IsMediaPresent())
  925. {
  926. if (_pvol->pszIconFromService)
  927. {
  928. lstrcpyn(pszModule, _pvol->pszIconFromService, cchModule);
  929. }
  930. }
  931. else
  932. {
  933. if (_pvol->pszNoMediaIconFromService)
  934. {
  935. lstrcpyn(pszModule, _pvol->pszNoMediaIconFromService, cchModule);
  936. }
  937. else
  938. {
  939. if (_pvol->pszIconFromService)
  940. {
  941. lstrcpyn(pszModule, _pvol->pszIconFromService, cchModule);
  942. }
  943. }
  944. }
  945. if (*pszModule)
  946. {
  947. iIcon = PathParseIconLocation(pszModule);
  948. }
  949. }
  950. if (-IDI_DRIVEUNKNOWN == iIcon)
  951. {
  952. if (_pszLegacyRegIcon)
  953. {
  954. if (*_pszLegacyRegIcon)
  955. {
  956. if (lstrcpyn(pszModule, _pszLegacyRegIcon, cchModule))
  957. {
  958. iIcon = PathParseIconLocation(pszModule);
  959. }
  960. }
  961. }
  962. else
  963. {
  964. if (_CanUseVolume() && (HWDTS_CDROM == _pvol->dwDriveType))
  965. {
  966. iIcon = _GetCDROMIcon();
  967. *pszModule = 0;
  968. }
  969. }
  970. }
  971. if (-IDI_DRIVEUNKNOWN == iIcon)
  972. {
  973. switch (_pvol->dwDriveType)
  974. {
  975. case HWDTS_FLOPPY35:
  976. {
  977. iIcon = II_DRIVE35;
  978. break;
  979. }
  980. case HWDTS_FIXEDDISK:
  981. {
  982. iIcon = II_DRIVEFIXED;
  983. break;
  984. }
  985. case HWDTS_CDROM:
  986. {
  987. iIcon = II_DRIVECD;
  988. break;
  989. }
  990. case HWDTS_REMOVABLEDISK:
  991. {
  992. iIcon = II_DRIVEREMOVE;
  993. break;
  994. }
  995. case HWDTS_FLOPPY525:
  996. {
  997. iIcon = II_DRIVE525;
  998. break;
  999. }
  1000. default:
  1001. {
  1002. iIcon = -IDI_DRIVEUNKNOWN;
  1003. break;
  1004. }
  1005. }
  1006. }
  1007. }
  1008. }
  1009. else
  1010. {
  1011. iIcon = CMountPoint::GetSuperPlainDriveIcon(_szName, GetDriveType(_GetName()));
  1012. }
  1013. if (*pszModule)
  1014. TraceMsg(TF_MOUNTPOINT, "CMtPtLocal::GetIcon: for '%s', chose '%s', '%d'", _GetNameDebug(), pszModule, iIcon);
  1015. else
  1016. TraceMsg(TF_MOUNTPOINT, "CMtPtLocal::GetIcon: for '%s', chose '%d'", _GetNameDebug(), iIcon);
  1017. return iIcon;
  1018. }
  1019. HRESULT CMtPtLocal::GetAssocSystemElement(IAssociationElement **ppae)
  1020. {
  1021. PCWSTR psz = NULL;
  1022. if (_IsFixedDisk())
  1023. psz = L"Drive.Fixed";
  1024. else if (_IsFloppy())
  1025. psz = L"Drive.Floppy";
  1026. else if (_IsCDROM())
  1027. psz = L"Drive.CDROM";
  1028. else if (_IsStrictRemovable())
  1029. psz = L"Drive.Removable";
  1030. if (psz)
  1031. return AssocElemCreateForClass(&CLSID_AssocSystemElement, psz, ppae);
  1032. return E_FAIL;
  1033. }
  1034. int CMtPtLocal::GetDriveFlags()
  1035. {
  1036. UINT uDriveFlags = 0;
  1037. // Is this a CD/DVD of some sort?
  1038. if (_IsCDROM())
  1039. {
  1040. // Yes
  1041. LPCTSTR pszSubKey = NULL;
  1042. if (_IsAudioDisc())
  1043. {
  1044. uDriveFlags |= DRIVE_AUDIOCD;
  1045. pszSubKey = TEXT("AudioCD\\shell");
  1046. }
  1047. else if (_IsDVDDisc())
  1048. {
  1049. uDriveFlags |= DRIVE_DVD;
  1050. pszSubKey = TEXT("DVD\\shell");
  1051. }
  1052. // Set the AutoOpen stuff, if applicable
  1053. if (pszSubKey)
  1054. {
  1055. TCHAR ach[80];
  1056. LONG cb = sizeof(ach);
  1057. ach[0] = 0;
  1058. // get the default verb for Audio CD/DVD
  1059. SHRegQueryValue(HKEY_CLASSES_ROOT, pszSubKey, ach, &cb);
  1060. // we should only set AUTOOPEN if there is a default verb on Audio CD/DVD
  1061. if (ach[0])
  1062. uDriveFlags |= DRIVE_AUTOOPEN;
  1063. }
  1064. }
  1065. else
  1066. {
  1067. // No, by default every drive type is ShellOpen, except CD-ROMs
  1068. uDriveFlags |= DRIVE_SHELLOPEN;
  1069. }
  1070. if (_IsAutorun())
  1071. {
  1072. uDriveFlags |= DRIVE_AUTORUN;
  1073. //FEATURE should we set AUTOOPEN based on a flag in the AutoRun.inf???
  1074. uDriveFlags |= DRIVE_AUTOOPEN;
  1075. }
  1076. return uDriveFlags;
  1077. }
  1078. void CMtPtLocal::GetTypeString(LPTSTR pszType, DWORD cchType)
  1079. {
  1080. int iID;
  1081. *pszType = 0;
  1082. if (_CanUseVolume())
  1083. {
  1084. switch (_pvol->dwDriveType)
  1085. {
  1086. case HWDTS_FLOPPY35:
  1087. if (_ShowUglyDriveNames())
  1088. {
  1089. iID = IDS_DRIVES_DRIVE35_UGLY;
  1090. }
  1091. else
  1092. {
  1093. iID = IDS_DRIVES_DRIVE35;
  1094. }
  1095. break;
  1096. case HWDTS_FLOPPY525:
  1097. if (_ShowUglyDriveNames())
  1098. {
  1099. iID = IDS_DRIVES_DRIVE525_UGLY;
  1100. }
  1101. else
  1102. {
  1103. iID = IDS_DRIVES_DRIVE525;
  1104. }
  1105. break;
  1106. case HWDTS_REMOVABLEDISK:
  1107. iID = IDS_DRIVES_REMOVABLE;
  1108. break;
  1109. case HWDTS_FIXEDDISK:
  1110. iID = IDS_DRIVES_FIXED;
  1111. break;
  1112. case HWDTS_CDROM:
  1113. iID = IDS_DRIVES_CDROM;
  1114. break;
  1115. }
  1116. }
  1117. else
  1118. {
  1119. UINT uDriveType = GetDriveType(_GetNameForFctCall());
  1120. switch (uDriveType)
  1121. {
  1122. case DRIVE_REMOVABLE:
  1123. iID = IDS_DRIVES_REMOVABLE;
  1124. break;
  1125. case DRIVE_REMOTE:
  1126. iID = IDS_DRIVES_NETDRIVE;
  1127. break;
  1128. case DRIVE_CDROM:
  1129. iID = IDS_DRIVES_CDROM;
  1130. break;
  1131. case DRIVE_RAMDISK:
  1132. iID = IDS_DRIVES_RAMDISK;
  1133. break;
  1134. case DRIVE_FIXED:
  1135. default:
  1136. iID = IDS_DRIVES_FIXED;
  1137. break;
  1138. }
  1139. }
  1140. LoadString(HINST_THISDLL, iID, pszType, cchType);
  1141. }
  1142. DWORD CMtPtLocal::GetShellDescriptionID()
  1143. {
  1144. DWORD dwShellDescrID;
  1145. if (_CanUseVolume())
  1146. {
  1147. switch (_pvol->dwDriveType)
  1148. {
  1149. case HWDTS_FLOPPY35:
  1150. dwShellDescrID = SHDID_COMPUTER_DRIVE35;
  1151. break;
  1152. case HWDTS_FLOPPY525:
  1153. dwShellDescrID = SHDID_COMPUTER_DRIVE525;
  1154. break;
  1155. case HWDTS_REMOVABLEDISK:
  1156. dwShellDescrID = SHDID_COMPUTER_REMOVABLE;
  1157. break;
  1158. case HWDTS_FIXEDDISK:
  1159. dwShellDescrID = SHDID_COMPUTER_FIXED;
  1160. break;
  1161. case HWDTS_CDROM:
  1162. dwShellDescrID = SHDID_COMPUTER_CDROM;
  1163. break;
  1164. default:
  1165. dwShellDescrID = SHDID_COMPUTER_OTHER;
  1166. break;
  1167. }
  1168. }
  1169. else
  1170. {
  1171. UINT uDriveType = GetDriveType(_GetNameForFctCall());
  1172. switch (uDriveType)
  1173. {
  1174. case DRIVE_REMOVABLE:
  1175. dwShellDescrID = SHDID_COMPUTER_REMOVABLE;
  1176. break;
  1177. case DRIVE_CDROM:
  1178. dwShellDescrID = SHDID_COMPUTER_CDROM;
  1179. break;
  1180. case DRIVE_FIXED:
  1181. dwShellDescrID = SHDID_COMPUTER_FIXED;
  1182. break;
  1183. case DRIVE_RAMDISK:
  1184. dwShellDescrID = SHDID_COMPUTER_RAMDISK;
  1185. break;
  1186. case DRIVE_NO_ROOT_DIR:
  1187. case DRIVE_UNKNOWN:
  1188. default:
  1189. dwShellDescrID = SHDID_COMPUTER_OTHER;
  1190. break;
  1191. }
  1192. }
  1193. return dwShellDescrID;
  1194. }
  1195. ///////////////////////////////////////////////////////////////////////////////
  1196. // DeviceIoControl stuff
  1197. ///////////////////////////////////////////////////////////////////////////////
  1198. HANDLE CMtPtLocal::_GetHandleWithAccessAndShareMode(DWORD dwDesiredAccess, DWORD dwShareMode)
  1199. {
  1200. HANDLE handle = INVALID_HANDLE_VALUE;
  1201. WCHAR szVolumeGUIDWOSlash[50];
  1202. DWORD dwFileAttributes = 0;
  1203. if (_CanUseVolume())
  1204. {
  1205. StrCpyN(szVolumeGUIDWOSlash, _pvol->pszVolumeGUID,
  1206. ARRAYSIZE(szVolumeGUIDWOSlash));
  1207. PathRemoveBackslash(szVolumeGUIDWOSlash);
  1208. }
  1209. else
  1210. {
  1211. // Go for VolumeGUID first
  1212. if (GetVolumeNameForVolumeMountPoint(_GetName(), szVolumeGUIDWOSlash,
  1213. ARRAYSIZE(szVolumeGUIDWOSlash)))
  1214. {
  1215. PathRemoveBackslash(szVolumeGUIDWOSlash);
  1216. }
  1217. else
  1218. {
  1219. // Probably a floppy, which cannot be mounted on a folder
  1220. lstrcpy(szVolumeGUIDWOSlash, TEXT("\\\\.\\A:"));
  1221. szVolumeGUIDWOSlash[4] = _GetNameFirstCharUCase();
  1222. }
  1223. }
  1224. return CreateFile(szVolumeGUIDWOSlash, dwDesiredAccess, dwShareMode, NULL, OPEN_EXISTING, dwFileAttributes, NULL);
  1225. }
  1226. // On NT, when use GENERIC_READ (as opposed to 0) in the CreateFile call, we
  1227. // get a handle to the filesystem (CDFS), not the device itself. But we can't
  1228. // change DriveIOCTL to do this, since that causes the floppy disks to spin
  1229. // up, and we don't want to do that.
  1230. HANDLE CMtPtLocal::_GetHandleReadRead()
  1231. {
  1232. return _GetHandleWithAccessAndShareMode(GENERIC_READ, FILE_SHARE_READ);
  1233. }
  1234. BOOL CMtPtLocal::_CanUseVolume()
  1235. {
  1236. // This is used in ASSERTs, do not add code that would introduce a side
  1237. // effect in debug only (stephstm)
  1238. // For Dismounted volumes, we want the code to take the alternate code
  1239. // path. The volume, when ready to be re-mounted, will be remounted
  1240. // until some code tries to access it. So using the alternate code path
  1241. // will try to remount it, if it's ready it will get remounted, the Shell
  1242. // Service will get an event, and we'll remove the DISMOUNTED bit.
  1243. return (_pvol && !(_pvol->dwVolumeFlags & HWDVF_STATE_ACCESSDENIED) &&
  1244. !(_pvol->dwVolumeFlags & HWDVF_STATE_DISMOUNTED));
  1245. }
  1246. HRESULT CMtPtLocal::_InitWithVolume(LPCWSTR pszMtPt, CVolume* pvol)
  1247. {
  1248. pvol->AddRef();
  1249. _pvol = pvol;
  1250. lstrcpyn(_szName, pszMtPt, ARRAYSIZE(_szName));
  1251. PathAddBackslash(_szName);
  1252. _fMountedOnDriveLetter = _IsDriveLetter(pszMtPt);
  1253. RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2, _pvol->pszKeyName,
  1254. REG_OPTION_NON_VOLATILE);
  1255. RSSetTextValue(NULL, TEXT("BaseClass"), TEXT("Drive"));
  1256. _InitAutorunInfo();
  1257. if (_CanUseVolume())
  1258. {
  1259. if (HWDMC_HASDESKTOPINI & _pvol->dwMediaCap)
  1260. {
  1261. // we need to listen to change notify to know when this guys will change
  1262. _UpdateCommentFromDesktopINI();
  1263. }
  1264. }
  1265. _InitLegacyRegIconAndLabelHelper();
  1266. return S_OK;
  1267. }
  1268. // These can only be mounted on drive letter
  1269. HRESULT CMtPtLocal::_Init(LPCWSTR pszMtPt)
  1270. {
  1271. HRESULT hr;
  1272. ASSERT(_IsDriveLetter(pszMtPt));
  1273. if (GetLogicalDrives() & (1 << DRIVEID(pszMtPt)))
  1274. {
  1275. _fMountedOnDriveLetter = TRUE;
  1276. lstrcpyn(_szName, pszMtPt, ARRAYSIZE(_szName));
  1277. PathAddBackslash(_szName);
  1278. _GetNameFirstXChar(_szNameNoVolume, ARRAYSIZE(_szNameNoVolume));
  1279. RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2, _szNameNoVolume,
  1280. REG_OPTION_NON_VOLATILE);
  1281. RSSetTextValue(NULL, TEXT("BaseClass"), TEXT("Drive"));
  1282. _InitAutorunInfo();
  1283. hr = S_OK;
  1284. }
  1285. else
  1286. {
  1287. hr = E_FAIL;
  1288. }
  1289. return hr;
  1290. }
  1291. void CMtPtLocal::_InitLegacyRegIconAndLabelHelper()
  1292. {
  1293. CMountPoint::_InitLegacyRegIconAndLabel(_HasAutorunIcon(),
  1294. _HasAutorunLabel());
  1295. }
  1296. void CMtPtLocal::StoreIconForUpdateImage(int iImage)
  1297. {
  1298. if (_CanUseVolume())
  1299. {
  1300. _pvol->iShellImageForUpdateImage = iImage;
  1301. }
  1302. }
  1303. void CMtPtLocal::_InitAutorunInfo()
  1304. {
  1305. if (_Shell32LoadedInDesktop())
  1306. {
  1307. BOOL fAutorun = FALSE;
  1308. if (!_CanUseVolume())
  1309. {
  1310. if (_IsAutorun())
  1311. {
  1312. fAutorun = TRUE;
  1313. }
  1314. }
  1315. if (!fAutorun && !_fVolumePoint)
  1316. {
  1317. // Make sure to delete the shell key
  1318. RSDeleteSubKey(TEXT("Shell"));
  1319. }
  1320. }
  1321. }
  1322. // Equivalent of GetDriveType API
  1323. int CMtPtLocal::_GetDriveType()
  1324. {
  1325. int iDriveType = DRIVE_NO_ROOT_DIR;
  1326. if (_CanUseVolume())
  1327. {
  1328. switch (_pvol->dwDriveType)
  1329. {
  1330. case HWDTS_FLOPPY35:
  1331. case HWDTS_FLOPPY525:
  1332. case HWDTS_REMOVABLEDISK:
  1333. iDriveType = DRIVE_REMOVABLE;
  1334. break;
  1335. case HWDTS_FIXEDDISK:
  1336. iDriveType = DRIVE_FIXED;
  1337. break;
  1338. case HWDTS_CDROM:
  1339. iDriveType = DRIVE_CDROM;
  1340. break;
  1341. }
  1342. }
  1343. else
  1344. {
  1345. iDriveType = GetDriveType(_GetNameForFctCall());
  1346. }
  1347. return iDriveType;
  1348. }
  1349. inline HLOCAL _LocalFree(HLOCAL hMem)
  1350. {
  1351. if (hMem)
  1352. {
  1353. LocalFree(hMem);
  1354. }
  1355. return NULL;
  1356. }
  1357. #define VALID_VOLUME_PREFIX TEXT("\\\\?\\Volume")
  1358. // static
  1359. HRESULT CMtPtLocal::_CreateVolume(VOLUMEINFO* pvolinfo, CVolume** ppvolNew)
  1360. {
  1361. ASSERT(_csDL.IsInside());
  1362. HRESULT hr;
  1363. if (!StrCmpN(pvolinfo->pszVolumeGUID, VALID_VOLUME_PREFIX, ARRAYSIZE(VALID_VOLUME_PREFIX) - 1))
  1364. {
  1365. CVolume* pvol = new CVolume();
  1366. *ppvolNew = NULL;
  1367. if (pvol)
  1368. {
  1369. // The next four strings shouyld always be set to something
  1370. pvol->pszDeviceIDVolume = StrDup(pvolinfo->pszDeviceIDVolume);
  1371. pvol->pszVolumeGUID = StrDup(pvolinfo->pszVolumeGUID);
  1372. pvol->pszLabel = StrDup(pvolinfo->pszLabel);
  1373. pvol->pszFileSystem = StrDup(pvolinfo->pszFileSystem);
  1374. // The following five strings are optional
  1375. if (pvolinfo->pszAutorunIconLocation)
  1376. {
  1377. pvol->pszAutorunIconLocation = StrDup(pvolinfo->pszAutorunIconLocation);
  1378. }
  1379. if (pvolinfo->pszAutorunLabel)
  1380. {
  1381. pvol->pszAutorunLabel = StrDup(pvolinfo->pszAutorunLabel);
  1382. }
  1383. if (pvolinfo->pszIconLocationFromService)
  1384. {
  1385. pvol->pszIconFromService = StrDup(pvolinfo->pszIconLocationFromService);
  1386. }
  1387. if (pvolinfo->pszNoMediaIconLocationFromService)
  1388. {
  1389. pvol->pszNoMediaIconFromService = StrDup(pvolinfo->pszNoMediaIconLocationFromService);
  1390. }
  1391. if (pvolinfo->pszLabelFromService)
  1392. {
  1393. pvol->pszLabelFromService = StrDup(pvolinfo->pszLabelFromService);
  1394. }
  1395. if (pvol->pszDeviceIDVolume && pvol->pszVolumeGUID && pvol->pszLabel &&
  1396. pvol->pszFileSystem)
  1397. {
  1398. pvol->dwState = pvolinfo->dwState;
  1399. pvol->dwVolumeFlags = pvolinfo->dwVolumeFlags;
  1400. pvol->dwDriveType = pvolinfo->dwDriveType;
  1401. pvol->dwDriveCapability = pvolinfo->dwDriveCapability;
  1402. pvol->dwFileSystemFlags = pvolinfo->dwFileSystemFlags;
  1403. pvol->dwMaxFileNameLen = pvolinfo->dwMaxFileNameLen;
  1404. pvol->dwRootAttributes = pvolinfo->dwRootAttributes;
  1405. pvol->dwSerialNumber = pvolinfo->dwSerialNumber;
  1406. pvol->dwDriveState = pvolinfo->dwDriveState;
  1407. pvol->dwMediaState = pvolinfo->dwMediaState;
  1408. pvol->dwMediaCap = pvolinfo->dwMediaCap;
  1409. if (_hdpaVolumes && (-1 != DPA_AppendPtr(_hdpaVolumes, pvol)))
  1410. {
  1411. pvol->pszKeyName = pvol->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID;
  1412. pvol->AddRef();
  1413. *ppvolNew = pvol;
  1414. hr = S_OK;
  1415. }
  1416. else
  1417. {
  1418. hr = E_OUTOFMEMORY;
  1419. }
  1420. }
  1421. else
  1422. {
  1423. hr = E_OUTOFMEMORY;
  1424. }
  1425. if (FAILED(hr))
  1426. {
  1427. _LocalFree(pvol->pszDeviceIDVolume);
  1428. _LocalFree(pvol->pszVolumeGUID);
  1429. _LocalFree(pvol->pszLabel);
  1430. _LocalFree(pvol->pszFileSystem);
  1431. _LocalFree(pvol->pszAutorunIconLocation);
  1432. _LocalFree(pvol->pszAutorunLabel);
  1433. _LocalFree(pvol->pszIconFromService);
  1434. _LocalFree(pvol->pszNoMediaIconFromService);
  1435. _LocalFree(pvol->pszLabelFromService);
  1436. delete pvol;
  1437. }
  1438. }
  1439. else
  1440. {
  1441. hr = E_OUTOFMEMORY;
  1442. }
  1443. }
  1444. else
  1445. {
  1446. hr = E_FAIL;
  1447. }
  1448. return hr;
  1449. }
  1450. // this helper function will hit the drive to see if media is present.
  1451. // should only be used for drives that don't support the HWDVF_STATE_SUPPORTNOTIFICATION
  1452. BOOL CMtPtLocal::_ForceCheckMediaPresent()
  1453. {
  1454. BOOL bRet = FALSE; // assume no media present
  1455. HANDLE hDevice = _GetHandleWithAccessAndShareMode(GENERIC_READ,
  1456. FILE_SHARE_READ | FILE_SHARE_WRITE);
  1457. if (hDevice != INVALID_HANDLE_VALUE)
  1458. {
  1459. DWORD dwDummy;
  1460. // call the ioctl to verify media presence
  1461. if (DeviceIoControl(hDevice,
  1462. IOCTL_STORAGE_CHECK_VERIFY,
  1463. NULL,
  1464. 0,
  1465. NULL,
  1466. 0,
  1467. &dwDummy,
  1468. NULL))
  1469. {
  1470. bRet = TRUE;
  1471. }
  1472. CloseHandle(hDevice);
  1473. }
  1474. return bRet;
  1475. }
  1476. BOOL CMtPtLocal::_IsMediaPresent()
  1477. {
  1478. BOOL bRet;
  1479. if (!_CanUseVolume() || !(_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION))
  1480. {
  1481. // if the drive dosen't support notification, we need to ping it now
  1482. bRet = _ForceCheckMediaPresent();
  1483. }
  1484. else
  1485. {
  1486. bRet = (HWDMS_PRESENT & _pvol->dwMediaState);
  1487. }
  1488. return bRet;
  1489. }
  1490. BOOL CMtPtLocal::_IsFormatted()
  1491. {
  1492. BOOL bRet = FALSE;
  1493. if (!_CanUseVolume() || !(_pvol->dwVolumeFlags & HWDVF_STATE_SUPPORTNOTIFICATION))
  1494. {
  1495. // if the drive dosen't support notification, we need to ping it now
  1496. bRet = GetVolumeInformation(_GetNameForFctCall(),
  1497. NULL,
  1498. 0,
  1499. NULL,
  1500. NULL,
  1501. NULL,
  1502. NULL,
  1503. NULL);
  1504. }
  1505. else
  1506. {
  1507. bRet = (_IsMediaPresent() && (HWDMS_FORMATTED & _pvol->dwMediaState));
  1508. }
  1509. return bRet;
  1510. }
  1511. BOOL CMtPtLocal::_IsReadOnly()
  1512. {
  1513. ASSERT(_CanUseVolume());
  1514. ASSERT(_IsMediaPresent()); // does not make sense otherwise
  1515. BOOL fRet = FALSE;
  1516. if (_IsCDROM() &&
  1517. (
  1518. (HWDMC_WRITECAPABILITY_SUPPORTDETECTION & _pvol->dwMediaState) &&
  1519. (
  1520. (HWDMC_CDROM & _pvol->dwMediaCap) ||
  1521. (HWDMC_DVDROM & _pvol->dwMediaCap)
  1522. )
  1523. )
  1524. )
  1525. {
  1526. fRet = TRUE;
  1527. }
  1528. else
  1529. {
  1530. // We could optimize by checking if the floppy is write protected. But
  1531. // it might not be worth it.
  1532. fRet = FALSE;
  1533. }
  1534. return fRet;
  1535. }
  1536. BOOL CMtPtLocal::_IsMountedOnDriveLetter()
  1537. {
  1538. return _fMountedOnDriveLetter;
  1539. }
  1540. CMtPtLocal::CMtPtLocal()
  1541. {
  1542. #ifdef DEBUG
  1543. ++_cMtPtLocal;
  1544. #endif
  1545. }
  1546. CMtPtLocal::~CMtPtLocal()
  1547. {
  1548. if (_pvol)
  1549. {
  1550. _pvol->Release();
  1551. }
  1552. #ifdef DEBUG
  1553. --_cMtPtLocal;
  1554. #endif
  1555. }
  1556. // static
  1557. HRESULT CMtPtLocal::_CreateMtPtLocal(LPCWSTR pszMountPoint)
  1558. {
  1559. ASSERT(_csDL.IsInside());
  1560. HRESULT hr;
  1561. CMtPtLocal* pmtptl = new CMtPtLocal();
  1562. if (pmtptl)
  1563. {
  1564. int iDrive = DRIVEID(pszMountPoint);
  1565. if (_rgMtPtDriveLetterLocal[iDrive])
  1566. {
  1567. _rgMtPtDriveLetterLocal[iDrive]->Release();
  1568. _rgMtPtDriveLetterLocal[iDrive] = NULL;
  1569. }
  1570. hr = pmtptl->_Init(pszMountPoint);
  1571. if (SUCCEEDED(hr))
  1572. {
  1573. // Yes
  1574. _rgMtPtDriveLetterLocal[iDrive] = pmtptl;
  1575. }
  1576. else
  1577. {
  1578. delete pmtptl;
  1579. }
  1580. }
  1581. else
  1582. {
  1583. hr = E_OUTOFMEMORY;
  1584. }
  1585. return hr;
  1586. }
  1587. HRESULT CMtPtLocal::GetMountPointName(LPWSTR pszMountPoint, DWORD cchMountPoint)
  1588. {
  1589. lstrcpyn(pszMountPoint, _GetName(), cchMountPoint);
  1590. return S_OK;
  1591. }
  1592. // static
  1593. HRESULT CMtPtLocal::_CreateMtPtLocalWithVolume(LPCWSTR pszMountPoint,
  1594. CVolume* pvol)
  1595. {
  1596. ASSERT(_csDL.IsInside());
  1597. HRESULT hr;
  1598. CMtPtLocal* pmtptlNew = new CMtPtLocal();
  1599. if (pmtptlNew)
  1600. {
  1601. // Is it a drive letter only?
  1602. if (_IsDriveLetter(pszMountPoint))
  1603. {
  1604. // Yes
  1605. int iDrive = DRIVEID(pszMountPoint);
  1606. if (_rgMtPtDriveLetterLocal[iDrive])
  1607. {
  1608. _rgMtPtDriveLetterLocal[iDrive]->Release();
  1609. _rgMtPtDriveLetterLocal[iDrive] = NULL;
  1610. }
  1611. }
  1612. else
  1613. {
  1614. _RemoveLocalMountPoint(pszMountPoint);
  1615. }
  1616. hr = pmtptlNew->_InitWithVolume(pszMountPoint, pvol);
  1617. if (SUCCEEDED(hr))
  1618. {
  1619. // Is it a drive letter only?
  1620. if (_IsDriveLetter(pszMountPoint))
  1621. {
  1622. // Yes
  1623. int iDrive = DRIVEID(pszMountPoint);
  1624. _rgMtPtDriveLetterLocal[iDrive] = pmtptlNew;
  1625. }
  1626. else
  1627. {
  1628. hr = _StoreMtPtMOF(pmtptlNew);
  1629. }
  1630. }
  1631. if (FAILED(hr))
  1632. {
  1633. delete pmtptlNew;
  1634. }
  1635. }
  1636. else
  1637. {
  1638. hr = E_OUTOFMEMORY;
  1639. }
  1640. return hr;
  1641. }
  1642. // static
  1643. HRESULT CMtPtLocal::_CreateMtPtLocalFromVolumeGuid(LPCWSTR pszVolumeGuid, CMountPoint ** ppmtpt )
  1644. {
  1645. ASSERT(_csDL.IsInside());
  1646. HRESULT hr;
  1647. CMtPtLocal* pmtptlNew = new CMtPtLocal();
  1648. Assert( NULL != ppmtpt );
  1649. *ppmtpt = (CMountPoint *) pmtptlNew;
  1650. if (pmtptlNew)
  1651. {
  1652. ASSERT(NULL == pmtptlNew->_pvol);
  1653. lstrcpyn(pmtptlNew->_szName, pszVolumeGuid, ARRAYSIZE(pmtptlNew->_szName));
  1654. PathAddBackslash(pmtptlNew->_szName);
  1655. pmtptlNew->_fMountedOnDriveLetter = FALSE;
  1656. pmtptlNew->_fVolumePoint = TRUE;
  1657. pmtptlNew->_InitAutorunInfo();
  1658. hr = S_OK;
  1659. }
  1660. else
  1661. {
  1662. hr = E_OUTOFMEMORY;
  1663. }
  1664. return hr;
  1665. }
  1666. // static
  1667. CVolume* CMtPtLocal::_GetVolumeByMtPt(LPCWSTR pszMountPoint)
  1668. {
  1669. ASSERT(_csDL.IsInside());
  1670. CVolume* pvol = NULL;
  1671. WCHAR szVolumeGUID[50];
  1672. if (_fLocalDrivesInited)
  1673. {
  1674. if (GetVolumeNameForVolumeMountPoint(pszMountPoint, szVolumeGUID,
  1675. ARRAYSIZE(szVolumeGUID)))
  1676. {
  1677. DWORD c = DPA_GetPtrCount(_hdpaVolumes);
  1678. for (DWORD dw = 0; dw < c; ++dw)
  1679. {
  1680. pvol = (CVolume*)DPA_GetPtr(_hdpaVolumes, dw);
  1681. if (pvol)
  1682. {
  1683. if (!lstrcmpi(pvol->pszVolumeGUID, szVolumeGUID))
  1684. {
  1685. pvol->AddRef();
  1686. break;
  1687. }
  1688. else
  1689. {
  1690. pvol = NULL;
  1691. }
  1692. }
  1693. }
  1694. }
  1695. }
  1696. return pvol;
  1697. }
  1698. // static
  1699. CVolume* CMtPtLocal::_GetVolumeByID(LPCWSTR pszDeviceIDVolume)
  1700. {
  1701. ASSERT(_csDL.IsInside());
  1702. CVolume* pvol = NULL;
  1703. if (_hdpaVolumes)
  1704. {
  1705. DWORD c = DPA_GetPtrCount(_hdpaVolumes);
  1706. for (DWORD dw = 0; dw < c; ++dw)
  1707. {
  1708. pvol = (CVolume*)DPA_GetPtr(_hdpaVolumes, dw);
  1709. if (pvol)
  1710. {
  1711. if (!lstrcmpi(pvol->pszDeviceIDVolume, pszDeviceIDVolume))
  1712. {
  1713. pvol->AddRef();
  1714. break;
  1715. }
  1716. else
  1717. {
  1718. pvol = NULL;
  1719. }
  1720. }
  1721. }
  1722. }
  1723. return pvol;
  1724. }
  1725. // static
  1726. CVolume* CMtPtLocal::_GetAndRemoveVolumeByID(LPCWSTR pszDeviceIDVolume)
  1727. {
  1728. CVolume* pvol = NULL;
  1729. _csDL.Enter();
  1730. if (_hdpaVolumes)
  1731. {
  1732. DWORD c = DPA_GetPtrCount(_hdpaVolumes);
  1733. for (int i = c - 1; i >= 0; --i)
  1734. {
  1735. pvol = (CVolume*)DPA_GetPtr(_hdpaVolumes, i);
  1736. if (pvol)
  1737. {
  1738. if (!lstrcmpi(pvol->pszDeviceIDVolume, pszDeviceIDVolume))
  1739. {
  1740. // Do not AddRef
  1741. DPA_DeletePtr(_hdpaVolumes, i);
  1742. break;
  1743. }
  1744. else
  1745. {
  1746. pvol = NULL;
  1747. }
  1748. }
  1749. }
  1750. }
  1751. _csDL.Leave();
  1752. return pvol;
  1753. }
  1754. // static
  1755. HRESULT CMtPtLocal::_GetAndRemoveVolumeAndItsMtPts(LPCWSTR pszDeviceIDVolume,
  1756. CVolume** ppvol, HDPA hdpaMtPts)
  1757. {
  1758. _csDL.Enter();
  1759. CVolume* pvol = _GetAndRemoveVolumeByID(pszDeviceIDVolume);
  1760. if (pvol)
  1761. {
  1762. for (DWORD dw = 0; dw < 26; ++dw)
  1763. {
  1764. CMtPtLocal* pmtptl = (CMtPtLocal*)_rgMtPtDriveLetterLocal[dw];
  1765. if (pmtptl && pmtptl->_pvol)
  1766. {
  1767. if (pmtptl->_pvol == pvol)
  1768. {
  1769. _rgMtPtDriveLetterLocal[dw] = 0;
  1770. DPA_AppendPtr(hdpaMtPts, pmtptl);
  1771. break;
  1772. }
  1773. }
  1774. }
  1775. _csLocalMtPtHDPA.Enter();
  1776. if (_hdpaMountPoints)
  1777. {
  1778. DWORD c = DPA_GetPtrCount(_hdpaMountPoints);
  1779. for (int i = c - 1; i >= 0; --i)
  1780. {
  1781. CMtPtLocal* pmtptl = (CMtPtLocal*)DPA_GetPtr(_hdpaMountPoints, i);
  1782. if (pmtptl && pmtptl->_pvol)
  1783. {
  1784. if (pmtptl->_pvol == pvol)
  1785. {
  1786. DPA_DeletePtr(_hdpaMountPoints, i);
  1787. DPA_AppendPtr(hdpaMtPts, pmtptl);
  1788. }
  1789. }
  1790. }
  1791. }
  1792. _csLocalMtPtHDPA.Leave();
  1793. }
  1794. *ppvol = pvol;
  1795. _csDL.Leave();
  1796. return S_OK;
  1797. }
  1798. BOOL CMtPtLocal::_IsMiniMtPt()
  1799. {
  1800. return !_CanUseVolume();
  1801. }
  1802. HKEY CMtPtLocal::GetRegKey()
  1803. {
  1804. TraceMsg(TF_MOUNTPOINT, "CMtPtLocal::GetRegKey: for '%s'", _GetNameDebug());
  1805. if (_IsAutoRunDrive())
  1806. {
  1807. _ProcessAutoRunFile();
  1808. }
  1809. return RSDuplicateRootKey();
  1810. }
  1811. DWORD CMtPtLocal::_GetRegVolumeGen()
  1812. {
  1813. ASSERT(_CanUseVolume());
  1814. DWORD dwGen;
  1815. if (!_rsVolumes.RSGetDWORDValue(_pvol->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID, TEXT("Generation"), &dwGen))
  1816. {
  1817. dwGen = 0;
  1818. }
  1819. return dwGen;
  1820. }
  1821. BOOL CMtPtLocal::_NeedToRefresh()
  1822. {
  1823. ASSERT(_csDL.IsInside());
  1824. ASSERT(!_Shell32LoadedInDesktop());
  1825. BOOL fNeedToRefresh = FALSE;
  1826. if (_CanUseVolume())
  1827. {
  1828. DWORD dwRegVolumeGeneration = _GetRegVolumeGen();
  1829. if (dwRegVolumeGeneration != _pvol->dwGeneration)
  1830. {
  1831. // Remove it so that new mtpts do not get it.
  1832. CVolume* pvolnew;
  1833. CVolume* pvol = _GetAndRemoveVolumeByID(_pvol->pszDeviceIDVolume);
  1834. if (pvol)
  1835. {
  1836. // Release our cache ref count
  1837. pvol->Release();
  1838. }
  1839. // Replace the volume
  1840. if (SUCCEEDED(CMtPtLocal::_CreateVolumeFromReg(_pvol->pszDeviceIDVolume,
  1841. &pvolnew)))
  1842. {
  1843. pvolnew->Release();
  1844. }
  1845. fNeedToRefresh = TRUE;
  1846. }
  1847. }
  1848. return fNeedToRefresh;
  1849. }
  1850. // static
  1851. HRESULT CMtPtLocal::_CreateVolumeFromVOLUMEINFO2(VOLUMEINFO2* pvolinfo2, CVolume** ppvolNew)
  1852. {
  1853. VOLUMEINFO volinfo = {0};
  1854. volinfo.pszDeviceIDVolume = pvolinfo2->szDeviceIDVolume;
  1855. volinfo.pszVolumeGUID = pvolinfo2->szVolumeGUID;
  1856. volinfo.pszLabel = pvolinfo2->szLabel;
  1857. volinfo.pszFileSystem = pvolinfo2->szFileSystem;
  1858. volinfo.dwState = pvolinfo2->dwState;
  1859. volinfo.dwVolumeFlags = pvolinfo2->dwVolumeFlags;
  1860. volinfo.dwDriveType = pvolinfo2->dwDriveType;
  1861. volinfo.dwDriveCapability = pvolinfo2->dwDriveCapability;
  1862. volinfo.dwFileSystemFlags = pvolinfo2->dwFileSystemFlags;
  1863. volinfo.dwMaxFileNameLen = pvolinfo2->dwMaxFileNameLen;
  1864. volinfo.dwRootAttributes = pvolinfo2->dwRootAttributes;
  1865. volinfo.dwSerialNumber = pvolinfo2->dwSerialNumber;
  1866. volinfo.dwDriveState = pvolinfo2->dwDriveState;
  1867. volinfo.dwMediaState = pvolinfo2->dwMediaState;
  1868. volinfo.dwMediaCap = pvolinfo2->dwMediaCap;
  1869. if (-1 != pvolinfo2->oAutorunIconLocation)
  1870. {
  1871. volinfo.pszAutorunIconLocation = pvolinfo2->szOptionalStrings +
  1872. pvolinfo2->oAutorunIconLocation;
  1873. }
  1874. if (-1 != pvolinfo2->oAutorunLabel)
  1875. {
  1876. volinfo.pszAutorunLabel = pvolinfo2->szOptionalStrings +
  1877. pvolinfo2->oAutorunLabel;
  1878. }
  1879. if (-1 != pvolinfo2->oIconLocationFromService)
  1880. {
  1881. volinfo.pszIconLocationFromService = pvolinfo2->szOptionalStrings +
  1882. pvolinfo2->oIconLocationFromService;
  1883. }
  1884. if (-1 != pvolinfo2->oNoMediaIconLocationFromService)
  1885. {
  1886. volinfo.pszNoMediaIconLocationFromService = pvolinfo2->szOptionalStrings +
  1887. pvolinfo2->oNoMediaIconLocationFromService;
  1888. }
  1889. if (-1 != pvolinfo2->oLabelFromService)
  1890. {
  1891. volinfo.pszLabelFromService = pvolinfo2->szOptionalStrings +
  1892. pvolinfo2->oLabelFromService;
  1893. }
  1894. return _CreateVolume(&volinfo, ppvolNew);
  1895. }
  1896. // static
  1897. HRESULT CMtPtLocal::_CreateVolumeFromRegHelper(LPCWSTR pszGUID, CVolume** ppvolNew)
  1898. {
  1899. ASSERT(!_Shell32LoadedInDesktop());
  1900. ASSERT(_csDL.IsInside());
  1901. HRESULT hr;
  1902. DWORD cbSize = MAX_VOLUMEINFO2;
  1903. PBYTE pb = (PBYTE)LocalAlloc(LPTR, cbSize);
  1904. if (pb)
  1905. {
  1906. if (_rsVolumes.RSGetBinaryValue(pszGUID, TEXT("Data"), pb, &cbSize))
  1907. {
  1908. DWORD dwGen;
  1909. if (_rsVolumes.RSGetDWORDValue(pszGUID, TEXT("Generation"), &dwGen))
  1910. {
  1911. VOLUMEINFO2* pvolinfo2 = (VOLUMEINFO2*)pb;
  1912. hr = _CreateVolumeFromVOLUMEINFO2(pvolinfo2, ppvolNew);
  1913. if (SUCCEEDED(hr))
  1914. {
  1915. (*ppvolNew)->dwGeneration = dwGen;
  1916. }
  1917. }
  1918. else
  1919. {
  1920. hr = E_FAIL;
  1921. }
  1922. }
  1923. else
  1924. {
  1925. hr = E_FAIL;
  1926. }
  1927. LocalFree(pb);
  1928. }
  1929. else
  1930. {
  1931. hr = E_OUTOFMEMORY;
  1932. }
  1933. return hr;
  1934. }
  1935. // static
  1936. HRESULT CMtPtLocal::_CreateVolumeFromReg(LPCWSTR pszDeviceIDVolume, CVolume** ppvolNew)
  1937. {
  1938. ASSERT(!_Shell32LoadedInDesktop());
  1939. ASSERT(_csDL.IsInside());
  1940. HRESULT hr;
  1941. WCHAR szDeviceIDWithSlash[200];
  1942. WCHAR szVolumeGUID[50];
  1943. lstrcpyn(szDeviceIDWithSlash, pszDeviceIDVolume,
  1944. ARRAYSIZE(szDeviceIDWithSlash));
  1945. PathAddBackslash(szDeviceIDWithSlash);
  1946. if (GetVolumeNameForVolumeMountPoint(szDeviceIDWithSlash,
  1947. szVolumeGUID, ARRAYSIZE(szVolumeGUID)))
  1948. {
  1949. LPWSTR pszGUID = &(szVolumeGUID[OFFSET_GUIDWITHINVOLUMEGUID]);
  1950. hr = _CreateVolumeFromRegHelper(pszGUID, ppvolNew);
  1951. }
  1952. else
  1953. {
  1954. hr = E_FAIL;
  1955. }
  1956. return hr;
  1957. }
  1958. // static
  1959. HRESULT CMtPtLocal::_UpdateVolumeRegInfo(VOLUMEINFO* pvolinfo)
  1960. {
  1961. ASSERT(_Shell32LoadedInDesktop());
  1962. ASSERT(_csDL.IsInside());
  1963. HRESULT hr;
  1964. DWORD cbSize = MAX_VOLUMEINFO2;
  1965. PBYTE pb = (PBYTE)LocalAlloc(LPTR, cbSize);
  1966. if (pb)
  1967. {
  1968. DWORD dwGen;
  1969. DWORD offset = 0;
  1970. VOLUMEINFO2* pvolinfo2 = (VOLUMEINFO2*)pb;
  1971. // Get the Generation
  1972. if (!_rsVolumes.RSGetDWORDValue(
  1973. pvolinfo->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID, TEXT("Generation"),
  1974. &dwGen))
  1975. {
  1976. dwGen = 0;
  1977. }
  1978. ++dwGen;
  1979. ASSERT(pvolinfo->pszDeviceIDVolume);
  1980. ASSERT(pvolinfo->pszVolumeGUID);
  1981. ASSERT(pvolinfo->pszLabel);
  1982. ASSERT(pvolinfo->pszFileSystem);
  1983. lstrcpyn(pvolinfo2->szDeviceIDVolume, pvolinfo->pszDeviceIDVolume,
  1984. ARRAYSIZE(pvolinfo2->szDeviceIDVolume));
  1985. lstrcpyn(pvolinfo2->szVolumeGUID, pvolinfo->pszVolumeGUID,
  1986. ARRAYSIZE(pvolinfo2->szVolumeGUID));
  1987. lstrcpyn(pvolinfo2->szLabel, pvolinfo->pszLabel,
  1988. ARRAYSIZE(pvolinfo2->szLabel));
  1989. lstrcpyn(pvolinfo2->szFileSystem, pvolinfo->pszFileSystem,
  1990. ARRAYSIZE(pvolinfo2->szFileSystem));
  1991. pvolinfo2->dwState = pvolinfo->dwState;
  1992. pvolinfo2->dwVolumeFlags = pvolinfo->dwVolumeFlags;
  1993. pvolinfo2->dwDriveType = pvolinfo->dwDriveType;
  1994. pvolinfo2->dwDriveCapability = pvolinfo->dwDriveCapability;
  1995. pvolinfo2->dwFileSystemFlags = pvolinfo->dwFileSystemFlags;
  1996. pvolinfo2->dwMaxFileNameLen = pvolinfo->dwMaxFileNameLen;
  1997. pvolinfo2->dwRootAttributes = pvolinfo->dwRootAttributes;
  1998. pvolinfo2->dwSerialNumber = pvolinfo->dwSerialNumber;
  1999. pvolinfo2->dwDriveState = pvolinfo->dwDriveState;
  2000. pvolinfo2->dwMediaState = pvolinfo->dwMediaState;
  2001. pvolinfo2->dwMediaCap = pvolinfo->dwMediaCap;
  2002. pvolinfo2->oAutorunIconLocation = -1;
  2003. pvolinfo2->oAutorunLabel = -1;
  2004. pvolinfo2->oIconLocationFromService = -1;
  2005. pvolinfo2->oNoMediaIconLocationFromService = -1;
  2006. pvolinfo2->oLabelFromService = -1;
  2007. // The following five strings are optional
  2008. if (pvolinfo->pszAutorunIconLocation)
  2009. {
  2010. pvolinfo2->oAutorunIconLocation = offset;
  2011. offset += lstrlen(pvolinfo->pszAutorunIconLocation) + 1;
  2012. lstrcpy(pvolinfo2->szOptionalStrings + pvolinfo2->oAutorunIconLocation,
  2013. pvolinfo->pszAutorunIconLocation);
  2014. }
  2015. if (pvolinfo->pszAutorunLabel)
  2016. {
  2017. pvolinfo2->oAutorunIconLocation = offset;
  2018. offset += lstrlen(pvolinfo->pszAutorunLabel) + 1;
  2019. lstrcpy(pvolinfo2->szOptionalStrings + pvolinfo2->oAutorunIconLocation,
  2020. pvolinfo->pszAutorunLabel);
  2021. }
  2022. if (pvolinfo->pszIconLocationFromService)
  2023. {
  2024. pvolinfo2->oIconLocationFromService = offset;
  2025. offset += lstrlen(pvolinfo->pszIconLocationFromService) + 1;
  2026. lstrcpy(pvolinfo2->szOptionalStrings + pvolinfo2->oIconLocationFromService,
  2027. pvolinfo->pszIconLocationFromService);
  2028. }
  2029. if (pvolinfo->pszNoMediaIconLocationFromService)
  2030. {
  2031. pvolinfo2->oNoMediaIconLocationFromService = offset;
  2032. offset += lstrlen(pvolinfo->pszNoMediaIconLocationFromService) + 1;
  2033. lstrcpy(pvolinfo2->szOptionalStrings + pvolinfo2->oNoMediaIconLocationFromService,
  2034. pvolinfo->pszNoMediaIconLocationFromService);
  2035. }
  2036. if (pvolinfo->pszLabelFromService)
  2037. {
  2038. pvolinfo2->oLabelFromService = offset;
  2039. offset += lstrlen(pvolinfo->pszLabelFromService) + 1;
  2040. lstrcpy(pvolinfo2->szOptionalStrings + pvolinfo2->oLabelFromService,
  2041. pvolinfo->pszLabelFromService);
  2042. }
  2043. if (_rsVolumes.RSSetBinaryValue(pvolinfo->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID,
  2044. TEXT("Data"), pb, sizeof(VOLUMEINFO2) + (offset * sizeof(WCHAR)), REG_OPTION_VOLATILE))
  2045. {
  2046. if (_rsVolumes.RSSetDWORDValue(pvolinfo->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID,
  2047. TEXT("Generation"), dwGen))
  2048. {
  2049. hr = S_OK;
  2050. }
  2051. else
  2052. {
  2053. hr = E_FAIL;
  2054. }
  2055. }
  2056. else
  2057. {
  2058. hr = E_FAIL;
  2059. }
  2060. if (FAILED(hr))
  2061. {
  2062. _rsVolumes.RSDeleteSubKey(pvolinfo->pszVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID);
  2063. }
  2064. LocalFree(pb);
  2065. }
  2066. else
  2067. {
  2068. hr = E_OUTOFMEMORY;
  2069. }
  2070. return hr;
  2071. }
  2072. // static
  2073. HRESULT CMtPtLocal::_UpdateVolumeRegInfo2(VOLUMEINFO2* pvolinfo2)
  2074. {
  2075. ASSERT(_Shell32LoadedInDesktop());
  2076. ASSERT(_csDL.IsInside());
  2077. HRESULT hr;
  2078. DWORD dwGen;
  2079. // Get the Generation
  2080. if (!_rsVolumes.RSGetDWORDValue(
  2081. pvolinfo2->szVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID, TEXT("Generation"),
  2082. &dwGen))
  2083. {
  2084. dwGen = 0;
  2085. }
  2086. ++dwGen;
  2087. if (_rsVolumes.RSSetBinaryValue(pvolinfo2->szVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID,
  2088. TEXT("Data"), (PBYTE)pvolinfo2, pvolinfo2->cbSize, REG_OPTION_VOLATILE))
  2089. {
  2090. if (_rsVolumes.RSSetDWORDValue(pvolinfo2->szVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID,
  2091. TEXT("Generation"), dwGen))
  2092. {
  2093. hr = S_OK;
  2094. }
  2095. else
  2096. {
  2097. hr = E_FAIL;
  2098. }
  2099. }
  2100. else
  2101. {
  2102. hr = E_FAIL;
  2103. }
  2104. if (FAILED(hr))
  2105. {
  2106. _rsVolumes.RSDeleteSubKey(pvolinfo2->szVolumeGUID + OFFSET_GUIDWITHINVOLUMEGUID);
  2107. }
  2108. return hr;
  2109. }
  2110. //static
  2111. void CMtPtLocal::Initialize()
  2112. {
  2113. _rsVolumes.RSInitRoot(HKEY_CURRENT_USER, REGSTR_MTPT_ROOTKEY2,
  2114. g_szCrossProcessCacheVolumeKey, REG_OPTION_VOLATILE);
  2115. }
  2116. void CMtPtLocal::FinalCleanUp()
  2117. {
  2118. if (_Shell32LoadedInDesktop())
  2119. {
  2120. _rsVolumes.RSDeleteKey();
  2121. }
  2122. }
  2123. static const TWODWORDS arcontenttypemappings[] =
  2124. {
  2125. { HWDMC_HASAUTORUNINF, ARCONTENT_AUTORUNINF },
  2126. { HWDMC_HASAUDIOTRACKS, ARCONTENT_AUDIOCD },
  2127. { HWDMC_HASDVDMOVIE, ARCONTENT_DVDMOVIE },
  2128. };
  2129. static const TWODWORDS arblankmediamappings[] =
  2130. {
  2131. { HWDMC_CDRECORDABLE, ARCONTENT_BLANKCD },
  2132. { HWDMC_CDREWRITABLE, ARCONTENT_BLANKCD },
  2133. { HWDMC_DVDRECORDABLE, ARCONTENT_BLANKDVD },
  2134. { HWDMC_DVDREWRITABLE, ARCONTENT_BLANKDVD },
  2135. };
  2136. DWORD CMtPtLocal::_GetAutorunContentType()
  2137. {
  2138. DWORD dwRet = 0;
  2139. if (_CanUseVolume())
  2140. {
  2141. dwRet = _DoDWORDMapping(_pvol->dwMediaCap, arcontenttypemappings,
  2142. ARRAYSIZE(arcontenttypemappings), TRUE);
  2143. if (_pvol->dwMediaState & HWDMS_FORMATTED)
  2144. {
  2145. dwRet |= ARCONTENT_UNKNOWNCONTENT;
  2146. }
  2147. else
  2148. {
  2149. ASSERT(!dwRet);
  2150. DWORD dwDriveCapabilities;
  2151. DWORD dwMediaCapabilities;
  2152. if (_IsCDROM())
  2153. {
  2154. if (SUCCEEDED(CDBurn_GetCDInfo(_pvol->pszVolumeGUID, &dwDriveCapabilities, &dwMediaCapabilities)))
  2155. {
  2156. dwRet = _DoDWORDMapping(dwMediaCapabilities, arblankmediamappings,
  2157. ARRAYSIZE(arblankmediamappings), TRUE);
  2158. }
  2159. }
  2160. }
  2161. }
  2162. else
  2163. {
  2164. // If there's no _pvol, we care only about autorun.inf
  2165. if (_IsAutorun())
  2166. {
  2167. dwRet = ARCONTENT_AUTORUNINF;
  2168. }
  2169. if (_IsFormatted())
  2170. {
  2171. dwRet |= ARCONTENT_UNKNOWNCONTENT;
  2172. }
  2173. }
  2174. return dwRet;
  2175. }
  2176. // static
  2177. BOOL CMtPtLocal::IsVolume(LPCWSTR pszDeviceID)
  2178. {
  2179. BOOL fRet = FALSE;
  2180. _csDL.Enter();
  2181. CVolume* pvol = _GetVolumeByID(pszDeviceID);
  2182. if (pvol)
  2183. {
  2184. fRet = TRUE;
  2185. pvol->Release();
  2186. }
  2187. _csDL.Leave();
  2188. return fRet;
  2189. }
  2190. // static
  2191. HRESULT CMtPtLocal::GetMountPointFromDeviceID(LPCWSTR pszDeviceID,
  2192. LPWSTR pszMountPoint, DWORD cchMountPoint)
  2193. {
  2194. HRESULT hr = E_FAIL;
  2195. CMtPtLocal* pmtptl = NULL;
  2196. _csDL.Enter();
  2197. for (DWORD dw = 0; dw < 26; ++dw)
  2198. {
  2199. pmtptl = (CMtPtLocal*)_rgMtPtDriveLetterLocal[dw];
  2200. if (pmtptl && pmtptl->_pvol)
  2201. {
  2202. if (!lstrcmpi(pmtptl->_pvol->pszDeviceIDVolume, pszDeviceID))
  2203. {
  2204. lstrcpyn(pszMountPoint, pmtptl->_szName, cchMountPoint);
  2205. hr = S_OK;
  2206. break;
  2207. }
  2208. }
  2209. }
  2210. _csDL.Leave();
  2211. if (FAILED(hr))
  2212. {
  2213. _csLocalMtPtHDPA.Enter();
  2214. if (_hdpaMountPoints)
  2215. {
  2216. DWORD c = DPA_GetPtrCount(_hdpaMountPoints);
  2217. for (int i = c - 1; i >= 0; --i)
  2218. {
  2219. pmtptl = (CMtPtLocal*)DPA_GetPtr(_hdpaMountPoints, i);
  2220. if (pmtptl && pmtptl->_pvol)
  2221. {
  2222. if (!lstrcmpi(pmtptl->_pvol->pszDeviceIDVolume, pszDeviceID))
  2223. {
  2224. lstrcpyn(pszMountPoint, pmtptl->_szName, cchMountPoint);
  2225. hr = S_OK;
  2226. break;
  2227. }
  2228. }
  2229. }
  2230. }
  2231. _csLocalMtPtHDPA.Leave();
  2232. }
  2233. return hr;
  2234. }
  2235. static const TWODWORDS drivetypemappings[] =
  2236. {
  2237. { HWDTS_FLOPPY35 , DT_FLOPPY35 },
  2238. { HWDTS_FLOPPY525 , DT_FLOPPY525 },
  2239. { HWDTS_REMOVABLEDISK, DT_REMOVABLEDISK },
  2240. { HWDTS_FIXEDDISK , DT_FIXEDDISK },
  2241. { HWDTS_CDROM , DT_CDROM },
  2242. };
  2243. static const TWODWORDS drivetypemappingusingGDT[] =
  2244. {
  2245. { DRIVE_REMOVABLE , DT_REMOVABLEDISK },
  2246. { DRIVE_FIXED , DT_FIXEDDISK },
  2247. { DRIVE_RAMDISK , DT_FIXEDDISK },
  2248. { DRIVE_CDROM , DT_CDROM },
  2249. };
  2250. static const TWODWORDS cdtypemappings[] =
  2251. {
  2252. { HWDDC_CDROM , DT_CDROM },
  2253. { HWDDC_CDRECORDABLE , DT_CDR },
  2254. { HWDDC_CDREWRITABLE , DT_CDRW },
  2255. { HWDDC_DVDROM , DT_DVDROM },
  2256. { HWDDC_DVDRECORDABLE, DT_DVDR },
  2257. { HWDDC_DVDREWRITABLE, DT_DVDRW },
  2258. { HWDDC_DVDRAM , DT_DVDRAM },
  2259. };
  2260. DWORD CMtPtLocal::_GetMTPTDriveType()
  2261. {
  2262. DWORD dwRet = 0;
  2263. if (_CanUseVolume())
  2264. {
  2265. dwRet = _DoDWORDMapping(_pvol->dwDriveType, drivetypemappings,
  2266. ARRAYSIZE(drivetypemappings), TRUE);
  2267. if (DT_CDROM == dwRet)
  2268. {
  2269. DWORD dwDriveCapabilities;
  2270. DWORD dwMediaCapabilities;
  2271. if (SUCCEEDED(CDBurn_GetCDInfo(_pvol->pszVolumeGUID, &dwDriveCapabilities, &dwMediaCapabilities)))
  2272. {
  2273. dwRet |= _DoDWORDMapping(dwDriveCapabilities, cdtypemappings,
  2274. ARRAYSIZE(cdtypemappings), TRUE);
  2275. }
  2276. }
  2277. }
  2278. else
  2279. {
  2280. dwRet = _DoDWORDMapping(GetDriveType(_GetNameForFctCall()), drivetypemappingusingGDT,
  2281. ARRAYSIZE(drivetypemappingusingGDT), FALSE);
  2282. }
  2283. return dwRet;
  2284. }
  2285. /* TBD
  2286. CT_UNKNOWNCONTENT 0x00000008
  2287. CT_AUTOPLAYMUSIC 0x00000100
  2288. CT_AUTOPLAYPIX 0x00000200
  2289. CT_AUTOPLAYMOVIE 0x00000400*/
  2290. static const TWODWORDS contenttypemappings[] =
  2291. {
  2292. { HWDMC_HASAUTORUNINF, CT_AUTORUNINF },
  2293. { HWDMC_HASAUDIOTRACKS, CT_CDAUDIO },
  2294. { HWDMC_HASDVDMOVIE, CT_DVDMOVIE },
  2295. };
  2296. static const TWODWORDS blankmediamappings[] =
  2297. {
  2298. { HWDMC_CDRECORDABLE, CT_BLANKCDR },
  2299. { HWDMC_CDREWRITABLE, CT_BLANKCDRW },
  2300. { HWDMC_DVDRECORDABLE, CT_BLANKDVDR },
  2301. { HWDMC_DVDREWRITABLE, CT_BLANKDVDRW },
  2302. };
  2303. DWORD CMtPtLocal::_GetMTPTContentType()
  2304. {
  2305. DWORD dwRet = 0;
  2306. if (_CanUseVolume())
  2307. {
  2308. dwRet = _DoDWORDMapping(_pvol->dwMediaCap, contenttypemappings,
  2309. ARRAYSIZE(contenttypemappings), TRUE);
  2310. if (!(_pvol->dwMediaState & HWDMS_FORMATTED))
  2311. {
  2312. ASSERT(!dwRet);
  2313. DWORD dwDriveCapabilities;
  2314. DWORD dwMediaCapabilities;
  2315. if (_IsCDROM())
  2316. {
  2317. if (SUCCEEDED(CDBurn_GetCDInfo(_pvol->pszVolumeGUID, &dwDriveCapabilities, &dwMediaCapabilities)))
  2318. {
  2319. dwRet = _DoDWORDMapping(dwMediaCapabilities, blankmediamappings,
  2320. ARRAYSIZE(blankmediamappings), TRUE);
  2321. }
  2322. }
  2323. }
  2324. else
  2325. {
  2326. dwRet |= CT_UNKNOWNCONTENT;
  2327. }
  2328. }
  2329. else
  2330. {
  2331. // If there's no _pvol, we care only about autorun.inf
  2332. if (_IsAutorun())
  2333. {
  2334. dwRet = CT_AUTORUNINF;
  2335. }
  2336. if (_IsFormatted())
  2337. {
  2338. dwRet |= CT_UNKNOWNCONTENT;
  2339. }
  2340. }
  2341. return dwRet;
  2342. }