Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3139 lines
92 KiB

  1. #include "vol.h"
  2. #include "hwdev.h"
  3. #include "hnotif.h"
  4. #include "mtpts.h"
  5. #include "regnotif.h"
  6. #include "drvbase.h"
  7. #include "dtctreg.h"
  8. #include "users.h"
  9. //
  10. // ISSUE-2001/01/08-StephStm that's bad, vol should not depend on dtct...
  11. //
  12. #include "dtct.h"
  13. #include "reg.h"
  14. #include "sfstr.h"
  15. #include "misc.h"
  16. #pragma warning(disable: 4201)
  17. #include <winioctl.h>
  18. #pragma warning(default: 4201)
  19. #include <ntddcdrm.h>
  20. #include <ntddmmc.h>
  21. #include <ioevent.h>
  22. #include <shpriv.h>
  23. #include <setupapi.h>
  24. #include "mischlpr.h"
  25. #include "dbg.h"
  26. #include <strsafe.h>
  27. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  28. #define STATE_DRIVETYPE 0x00000001
  29. #define STATE_UPDATECONSTINFO 0x00000002
  30. #define STATE_DEVICENUMBERINFO 0x00000004
  31. #define STATE_DEVICEINST 0x00000008
  32. #define STATE_HWDEVICEINST 0x00000010
  33. #define STATE_MEDIAINFO 0x00000020
  34. #define STATE_GVIFAILED 0x10000000
  35. #define STATE_GFAFAILED 0x20000000
  36. #define STATE_UPDATEHASMEDIAFAILED 0x40000000
  37. #define INVALID_DWORD ((DWORD)-1)
  38. #define MPFE_UNDETERMINED ((DWORD)0x0DEF0DEF)
  39. #define MPFE_FALSE ((DWORD)0)
  40. #define MPFE_TRUE ((DWORD)1)
  41. ///////////////////////////////////////////////////////////////////////////////
  42. // Public
  43. // No need for the critical section, since it will not be added to the
  44. // NamedList until init is finsihed and has succeeded. Until it's in the
  45. // namedlist, no code can grab a pointer to this object and call it.
  46. HRESULT CVolume::Init(LPCWSTR pszElemName)
  47. {
  48. HRESULT hres = _cs.Init();
  49. if (SUCCEEDED(hres))
  50. {
  51. hres = _SetName(pszElemName);
  52. if (SUCCEEDED(hres))
  53. {
  54. CImpersonateEveryone* pieo;
  55. hres = CHWEventDetectorHelper::GetImpersonateEveryone(&pieo);
  56. if (SUCCEEDED(hres) && (S_FALSE != hres))
  57. {
  58. hres = pieo->Impersonate();
  59. if (SUCCEEDED(hres) && (S_FALSE != hres))
  60. {
  61. hres = _InitHelper(pszElemName);
  62. pieo->RevertToSelf();
  63. }
  64. pieo->RCRelease();
  65. }
  66. }
  67. }
  68. return hres;
  69. }
  70. HRESULT _IsDeviceFullyInstalled(LPCWSTR pszDeviceIntfID, BOOL* pfDeviceFullyInstalled)
  71. {
  72. HRESULT hr = E_FAIL;
  73. HDEVINFO hdevinfo = SetupDiCreateDeviceInfoList(NULL, NULL);
  74. *pfDeviceFullyInstalled = FALSE;
  75. if (INVALID_HANDLE_VALUE != hdevinfo)
  76. {
  77. SP_DEVICE_INTERFACE_DATA sdid = {0};
  78. sdid.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  79. if (SetupDiOpenDeviceInterface(hdevinfo, pszDeviceIntfID, 0, &sdid))
  80. {
  81. DWORD cbsdidd = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) +
  82. (MAX_DEVICE_ID_LEN * sizeof(WCHAR));
  83. SP_DEVINFO_DATA sdd = {0};
  84. SP_DEVICE_INTERFACE_DETAIL_DATA* psdidd =
  85. (SP_DEVICE_INTERFACE_DETAIL_DATA*)LocalAlloc(LPTR, cbsdidd);
  86. if (psdidd)
  87. {
  88. psdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  89. sdd.cbSize = sizeof(SP_DEVINFO_DATA);
  90. // SetupDiGetDeviceInterfaceDetail (below) requires that the
  91. // cbSize member of SP_DEVICE_INTERFACE_DETAIL_DATA be set
  92. // to the size of the fixed part of the structure, and to pass
  93. // the size of the full thing as the 4th param.
  94. if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &sdid, psdidd,
  95. cbsdidd, NULL, &sdd))
  96. {
  97. DWORD dw;
  98. if (SetupDiGetDeviceRegistryProperty(hdevinfo, &sdd,
  99. SPDRP_INSTALL_STATE, 0, (PBYTE)&dw, sizeof(dw), NULL))
  100. {
  101. TRACE(TF_VOLUME, TEXT(">>>> Got SPDRP_INSTALL_STATE property: 0x%08X"), dw);
  102. if (CM_INSTALL_STATE_INSTALLED == dw)
  103. {
  104. *pfDeviceFullyInstalled = TRUE;
  105. }
  106. hr = S_OK;
  107. }
  108. }
  109. LocalFree((HLOCAL)psdidd);
  110. }
  111. SetupDiDeleteDeviceInterfaceData(hdevinfo, &sdid);
  112. }
  113. SetupDiDestroyDeviceInfoList(hdevinfo);
  114. }
  115. return hr;
  116. }
  117. HRESULT CVolume::_InitHelper(LPCWSTR pszElemName)
  118. {
  119. BOOL fDeviceFullyInstalled;
  120. HRESULT hres = _IsDeviceFullyInstalled(_pszElemName, &fDeviceFullyInstalled);
  121. if (SUCCEEDED(hres))
  122. {
  123. if (!fDeviceFullyInstalled)
  124. {
  125. TRACE(TF_VOLUME,
  126. TEXT("!!!!!!!!!!!! Device not fully installed!\n %s"),
  127. pszElemName);
  128. hres = E_FAIL;
  129. }
  130. else
  131. {
  132. HANDLE hDevice;
  133. BOOL fCloseHandle = TRUE;
  134. hres = _GetDeviceHandleSafe(&hDevice, FALSE);
  135. if (SUCCEEDED(hres) && (S_FALSE != hres))
  136. {
  137. hres = _InitDriveType(hDevice);
  138. if (SUCCEEDED(hres))
  139. {
  140. _dwState |= STATE_DRIVETYPE;
  141. hres = S_OK;
  142. if ((HWDTS_FIXEDDISK != _dwDriveType) &&
  143. (HWDTS_FLOPPY35 != _dwDriveType) &&
  144. (HWDTS_FLOPPY525 != _dwDriveType))
  145. {
  146. _CloseDeviceHandleSafe(hDevice);
  147. fCloseHandle = FALSE;
  148. // Removable disk drives + CD require access to
  149. // the media to query all the required info
  150. hres = _GetDeviceHandleSafe(&hDevice, TRUE);
  151. }
  152. if (SUCCEEDED(hres) && (S_FALSE != hres))
  153. {
  154. hres = _UpdateConstInfo(hDevice);
  155. if (SUCCEEDED(hres))
  156. {
  157. _dwState |= STATE_UPDATECONSTINFO;
  158. }
  159. if ((HWDTS_FLOPPY35 != _dwDriveType) &&
  160. (HWDTS_FLOPPY525 != _dwDriveType))
  161. {
  162. if (SUCCEEDED(hres))
  163. {
  164. fCloseHandle = TRUE;
  165. hres = _GetDeviceNumberInfoFromHandle(hDevice,
  166. &_devtype, &_ulDeviceNumber,
  167. &_ulPartitionNumber);
  168. if (SUCCEEDED(hres))
  169. {
  170. if (S_FALSE != hres)
  171. {
  172. _dwState |= STATE_DEVICENUMBERINFO;
  173. }
  174. GUID guidDummy;
  175. hres = _GetDeviceInstance(pszElemName,
  176. &_devinst, &guidDummy);
  177. if (SUCCEEDED(hres) && (S_FALSE != hres))
  178. {
  179. _dwState |= STATE_DEVICEINST;
  180. hres = _InitHWDeviceInst();
  181. if (SUCCEEDED(hres) && (S_FALSE != hres))
  182. {
  183. hres = _UpdateSoftEjectCaps();
  184. if (SUCCEEDED(hres))
  185. {
  186. hres = _UpdateRemovableDevice();
  187. }
  188. }
  189. }
  190. }
  191. // We need to do this anyway, even if the
  192. // DeviceNumber stuff and/or the deviceInst stuff
  193. // fails. Otherwise we'll have a very sorry volume.
  194. if (SUCCEEDED(hres))
  195. {
  196. hres = _UpdateMediaInfo(hDevice, FALSE);
  197. if (SUCCEEDED(hres))
  198. {
  199. if (S_FALSE != hres)
  200. {
  201. _dwState |= STATE_MEDIAINFO;
  202. }
  203. hres = _RegisterNotif();
  204. }
  205. }
  206. }
  207. }
  208. if (SUCCEEDED(hres))
  209. {
  210. hres = _CreateMountPoints();
  211. }
  212. }
  213. else
  214. {
  215. _HandleAccessDenied();
  216. }
  217. }
  218. if (fCloseHandle)
  219. {
  220. _CloseDeviceHandleSafe(hDevice);
  221. }
  222. }
  223. else
  224. {
  225. _HandleAccessDenied();
  226. }
  227. }
  228. }
  229. return hres;
  230. }
  231. void CVolume::_HandleAccessDenied()
  232. {
  233. if (ERROR_ACCESS_DENIED == GetLastError())
  234. {
  235. _dwVolumeFlags |= HWDVF_STATE_ACCESSDENIED;
  236. }
  237. }
  238. // *pdwFloppy
  239. // 0: not a floppy
  240. // 35: 3.5" flopy
  241. // 525: 5.25" floppy
  242. HRESULT _DeviceIsFloppy(HANDLE hDevice, DWORD* pdwFloppy, BOOL* pfFloppySupportsSoftEject)
  243. {
  244. HRESULT hres = S_FALSE;
  245. DISK_GEOMETRY dg[12] = {0};
  246. DWORD cbBuf = sizeof(dg);
  247. DWORD dwReturned;
  248. *pdwFloppy = 0;
  249. *pfFloppySupportsSoftEject = FALSE;
  250. // Should be IOCTL_..._DISK_GEOMETRY...
  251. if (DeviceIoControl(hDevice, IOCTL_DISK_GET_MEDIA_TYPES,
  252. NULL, 0, dg, cbBuf, &dwReturned, NULL))
  253. {
  254. DWORD cMediaInfo = dwReturned / sizeof(DISK_GEOMETRY);
  255. for (DWORD dw = 0; !(*pdwFloppy) && (dw < cMediaInfo); ++dw)
  256. {
  257. switch (dg[dw].MediaType)
  258. {
  259. case F5_1Pt2_512: // Cap: 1200
  260. case F5_360_512: // Cap: 360
  261. case F5_320_512: // Cap: 360
  262. case F5_320_1024: // Cap: 360
  263. case F5_180_512: // Cap: 360
  264. case F5_160_512: // Cap: 360
  265. *pdwFloppy = 525;
  266. break;
  267. case F3_120M_512: // Cap: 120MB
  268. *pfFloppySupportsSoftEject = TRUE;
  269. case F3_1Pt44_512: // Cap: 1440
  270. case F3_2Pt88_512: // Cap: 2880
  271. case F3_20Pt8_512: // Cap: 2880
  272. case F3_720_512: // Cap: 720
  273. *pdwFloppy = 35;
  274. break;
  275. //
  276. // Japanese specific device types from here.
  277. //
  278. case F5_1Pt23_1024: // Cap: 1200
  279. case F5_640_512: // Cap: 260
  280. case F5_720_512: // Cap: 360
  281. *pdwFloppy = 525;
  282. break;
  283. case F3_640_512: // Cap: 720
  284. case F3_1Pt2_512: // Cap: 1440
  285. case F3_1Pt23_1024: // Cap: 1440
  286. *pdwFloppy = 35;
  287. break;
  288. case F3_128Mb_512: // Cap: ?
  289. case F3_230Mb_512: // Cap: ?
  290. case F3_200Mb_512:
  291. *pdwFloppy = 35;
  292. break;
  293. }
  294. if (*pdwFloppy)
  295. {
  296. hres = S_OK;
  297. }
  298. }
  299. }
  300. return hres;
  301. }
  302. HRESULT _GetDriveTypeInfo(HANDLE hDevice, DWORD* pdwDriveType, BOOL* pfFloppy);
  303. HRESULT CVolume::_InitDriveType(HANDLE hDevice)
  304. {
  305. BOOL fFloppy = FALSE;
  306. HRESULT hr = _GetDriveTypeInfo(hDevice, &_dwDriveType, &fFloppy);
  307. if (SUCCEEDED(hr))
  308. {
  309. if (fFloppy)
  310. {
  311. DWORD dwFloppy;
  312. BOOL fFloppySupportsSoftEject;
  313. hr = _DeviceIsFloppy(hDevice, &dwFloppy, &fFloppySupportsSoftEject);
  314. if (SUCCEEDED(hr) && (S_FALSE != hr))
  315. {
  316. if (fFloppySupportsSoftEject)
  317. {
  318. _dwDriveCap |= HWDDC_FLOPPYSOFTEJECT;
  319. }
  320. switch (dwFloppy)
  321. {
  322. case 35:
  323. _dwDriveType = HWDTS_FLOPPY35;
  324. break;
  325. case 525:
  326. _dwDriveType = HWDTS_FLOPPY525;
  327. }
  328. }
  329. }
  330. }
  331. return hr;
  332. }
  333. HRESULT _GetRemovableDeviceInstRecurs(DEVINST devinst,
  334. DEVINST* pdevinst)
  335. {
  336. BOOL fRemovable;
  337. HRESULT hres = _DeviceInstIsRemovable(devinst, &fRemovable);
  338. if (SUCCEEDED(hres))
  339. {
  340. if (fRemovable)
  341. {
  342. // Found it!
  343. *pdevinst = devinst;
  344. }
  345. else
  346. {
  347. // Recurse
  348. DEVINST devinstParent;
  349. CONFIGRET cr = CM_Get_Parent_Ex(&devinstParent, devinst, 0,
  350. NULL);
  351. if (CR_SUCCESS == cr)
  352. {
  353. hres = _GetRemovableDeviceInstRecurs(devinstParent, pdevinst);
  354. }
  355. else
  356. {
  357. hres = S_FALSE;
  358. }
  359. }
  360. }
  361. return hres;
  362. }
  363. HRESULT CVolume::_GetDeviceIDDisk(LPWSTR pszDeviceIDDisk,
  364. DWORD cchDeviceIDDisk)
  365. {
  366. HRESULT hr;
  367. _cs.Enter();
  368. if (_szDeviceIDDisk[0])
  369. {
  370. hr = SafeStrCpyN(pszDeviceIDDisk, _szDeviceIDDisk, cchDeviceIDDisk);
  371. }
  372. else
  373. {
  374. if (((ULONG)-1) != _ulDeviceNumber)
  375. {
  376. CNamedElemList* pnel;
  377. hr = CHWEventDetectorHelper::GetList(HWEDLIST_DISK, &pnel);
  378. if (S_OK == hr)
  379. {
  380. CNamedElemEnum* penum;
  381. hr = pnel->GetEnum(&penum);
  382. if (SUCCEEDED(hr))
  383. {
  384. CNamedElem* pelem;
  385. BOOL fFoundIt = FALSE;
  386. while (!fFoundIt && SUCCEEDED(hr = penum->Next(&pelem)) &&
  387. (S_FALSE != hr))
  388. {
  389. CDisk* pdisk = (CDisk*)pelem;
  390. ULONG ulDeviceNumber;
  391. hr = pdisk->GetDeviceNumber(&ulDeviceNumber);
  392. if (SUCCEEDED(hr) && (S_FALSE != hr))
  393. {
  394. if (_ulDeviceNumber == ulDeviceNumber)
  395. {
  396. DEVICE_TYPE devtype;
  397. hr = pdisk->GetDeviceType(&devtype);
  398. if (SUCCEEDED(hr) && (S_FALSE != hr))
  399. {
  400. if (_devtype == devtype)
  401. {
  402. // Use me!
  403. DWORD cchReq;
  404. hr = pelem->GetName(pszDeviceIDDisk,
  405. cchDeviceIDDisk, &cchReq);
  406. fFoundIt = TRUE;
  407. }
  408. }
  409. }
  410. }
  411. pelem->RCRelease();
  412. }
  413. penum->RCRelease();
  414. }
  415. pnel->RCRelease();
  416. }
  417. }
  418. else
  419. {
  420. hr = S_FALSE;
  421. }
  422. if (SUCCEEDED(hr) && (S_FALSE != hr))
  423. {
  424. if (FAILED(SafeStrCpyN(_szDeviceIDDisk, pszDeviceIDDisk,
  425. ARRAYSIZE(_szDeviceIDDisk))))
  426. {
  427. _szDeviceIDDisk[0] = 0;
  428. }
  429. }
  430. }
  431. _cs.Leave();
  432. return hr;
  433. }
  434. HRESULT CVolume::_InitHWDeviceInst()
  435. {
  436. WCHAR szDeviceIDDisk[MAX_DEVICEID];
  437. HRESULT hr = _GetDeviceIDDisk(szDeviceIDDisk, ARRAYSIZE(szDeviceIDDisk));
  438. if (SUCCEEDED(hr))
  439. {
  440. DEVINST devinstFinal = 0;
  441. GUID guidDummy;
  442. if (S_FALSE != hr)
  443. {
  444. DEVINST devinstDisk;
  445. hr = _GetDeviceInstance(szDeviceIDDisk, &devinstDisk, &guidDummy);
  446. if (SUCCEEDED(hr) && (S_FALSE != hr))
  447. {
  448. hr = _GetRemovableDeviceInstRecurs(devinstDisk, &devinstFinal);
  449. if (SUCCEEDED(hr))
  450. {
  451. if (S_FALSE == hr)
  452. {
  453. // Maybe this is not a removable device (not talking
  454. // about removable disk).
  455. BOOL fFoundProp;
  456. WCHAR szProp[1];
  457. ULONG ulData = sizeof(szProp);
  458. // First check if the disk interface has customn properties associated with it.
  459. CONFIGRET cr = CM_Get_DevNode_Custom_Property(devinstDisk, TEXT("DeviceGroup"),
  460. NULL, (PBYTE)szProp, &ulData, 0);
  461. if ((CR_SUCCESS == cr) || (CR_BUFFER_SMALL == cr))
  462. {
  463. fFoundProp = TRUE;
  464. }
  465. else
  466. {
  467. ulData = sizeof(szProp);
  468. cr = CM_Get_DevNode_Custom_Property(devinstDisk, TEXT("Icons"),
  469. NULL, (PBYTE)szProp, &ulData, 0);
  470. if ((CR_SUCCESS == cr) || (CR_BUFFER_SMALL == cr))
  471. {
  472. fFoundProp = TRUE;
  473. }
  474. else
  475. {
  476. fFoundProp = FALSE;
  477. }
  478. }
  479. if (fFoundProp)
  480. {
  481. devinstFinal = devinstDisk;
  482. hr = S_OK;
  483. }
  484. else
  485. {
  486. // Let's get the parent devinst of this devinst.
  487. if (CR_SUCCESS == CM_Get_Parent_Ex(&devinstFinal,
  488. devinstDisk, 0, NULL))
  489. {
  490. hr = S_OK;
  491. DIAGNOSTIC((TEXT("[0303]Got DeviceInst from parent of disk")));
  492. TRACE(TF_VOLUME,
  493. TEXT("HWDevInst: Got devinst from parent of Disk for Disk\n %s"),
  494. _pszElemName);
  495. }
  496. }
  497. }
  498. else
  499. {
  500. DIAGNOSTIC((TEXT("[0302]Got DeviceInst from Removable Device")));
  501. TRACE(TF_VOLUME,
  502. TEXT("HWDevInst: Got devinst from Removable Device for Volume\n %s"),
  503. _pszElemName);
  504. }
  505. }
  506. }
  507. else
  508. {
  509. DIAGNOSTIC((TEXT("[0304]Did NOT get DeviceInst from the disk")));
  510. TRACE(TF_VOLUME,
  511. TEXT("HWDevInst: Did not get a devinst from the Disk for Volume\n %s"),
  512. _pszElemName);
  513. }
  514. }
  515. else
  516. {
  517. DIAGNOSTIC((TEXT("[0305]Got DeviceInst from Volume itself")));
  518. TRACE(TF_VOLUME,
  519. TEXT("HWDevInst: Did not get a Disk, get devinst from Volume itself for Volume\n (%s)"),
  520. _pszElemName);
  521. // We did not get a device number for the volume
  522. // Let's get the device instance from the volume then, maybe there's no
  523. // volume-disk-device hierarchy
  524. hr = _GetDeviceInstance(_pszElemName, &devinstFinal, &guidDummy);
  525. }
  526. if (SUCCEEDED(hr) && (S_FALSE != hr))
  527. {
  528. hr = _hwdevinst.Init(devinstFinal);
  529. if (SUCCEEDED(hr) && (S_FALSE != hr))
  530. {
  531. hr = _hwdevinst.InitInterfaceGUID(&guidVolumeClass);
  532. if (SUCCEEDED(hr) && (S_FALSE != hr))
  533. {
  534. _fHWDevInstInited = TRUE;
  535. }
  536. }
  537. }
  538. }
  539. return hr;
  540. }
  541. HRESULT CVolume::GetHWDeviceInst(CHWDeviceInst** pphwdevinst)
  542. {
  543. HRESULT hr;
  544. if (_fHWDevInstInited)
  545. {
  546. *pphwdevinst = &_hwdevinst;
  547. hr = S_OK;
  548. }
  549. else
  550. {
  551. *pphwdevinst = NULL;
  552. hr = S_FALSE;
  553. }
  554. return hr;
  555. }
  556. HRESULT CVolume::_ShouldTryAutoplay(BOOL* pfTry)
  557. {
  558. HRESULT hr;
  559. if (_dwMediaState & HWDMS_PRESENT)
  560. {
  561. if (_dwMediaState & HWDMS_FORMATTED)
  562. {
  563. if (!(_dwMediaCap & HWDMC_HASDVDMOVIE))
  564. {
  565. if (!(_dwMediaCap & HWDMC_HASAUTORUNINF) ||
  566. (_dwMediaCap & HWDMC_HASUSEAUTOPLAY))
  567. {
  568. WCHAR szVolumeGUID[MAX_PATH + 50];
  569. LPWSTR pszFile;
  570. if (_dwMediaCap & HWDMC_HASUSEAUTOPLAY)
  571. {
  572. DIAGNOSTIC((TEXT("[0316]Autorun.inf, BUT as a UseAutoPLAY entry -> try Autoplay!")));
  573. }
  574. hr = SafeStrCpyN(szVolumeGUID, _szVolumeGUID,
  575. ARRAYSIZE(szVolumeGUID));
  576. *pfTry = TRUE;
  577. if (SUCCEEDED(hr))
  578. {
  579. HKEY hkey;
  580. pszFile = szVolumeGUID + lstrlen(szVolumeGUID);
  581. TRACE(TF_LEAK, TEXT("Special files - BEGIN"));
  582. hr = _RegOpenKey(HKEY_LOCAL_MACHINE,
  583. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoplayHandlers\\CancelAutoplay\\Files"),
  584. &hkey);
  585. if (SUCCEEDED(hr) && (S_FALSE != hr))
  586. {
  587. DWORD dwIndex = 0;
  588. while ((*pfTry) && SUCCEEDED(hr = _RegEnumStringValue(hkey, dwIndex, pszFile,
  589. (DWORD)(ARRAYSIZE(szVolumeGUID) - (pszFile - szVolumeGUID)))) &&
  590. (S_FALSE != hr))
  591. {
  592. WIN32_FIND_DATA w32fd;
  593. HANDLE h;
  594. h = FindFirstFile(szVolumeGUID, &w32fd);
  595. if (INVALID_HANDLE_VALUE != h)
  596. {
  597. FindClose(h);
  598. *pfTry = FALSE;
  599. DIAGNOSTIC((TEXT("[0307]Detected special file : '%s' (%s) -> No Autoplay!"),
  600. w32fd.cFileName, pszFile));
  601. TRACE(TF_VOLUME,
  602. TEXT("Detected %s (%s) -> No Autoplay!"),
  603. w32fd.cFileName , pszFile);
  604. }
  605. ++dwIndex;
  606. }
  607. _RegCloseKey(hkey);
  608. }
  609. TRACE(TF_LEAK, TEXT("Special files - END"));
  610. }
  611. }
  612. else
  613. {
  614. DIAGNOSTIC((TEXT("[0313]Autorun.inf -> No Content Autoplay!")));
  615. hr = S_OK;
  616. *pfTry = FALSE;
  617. }
  618. }
  619. else
  620. {
  621. DIAGNOSTIC((TEXT("[0312]DVD Movie -> No Content Autoplay!")));
  622. hr = S_OK;
  623. *pfTry = FALSE;
  624. }
  625. }
  626. else
  627. {
  628. DIAGNOSTIC((TEXT("[0317]Media *NOT* formatted -> No Content Autoplay!")));
  629. hr = S_OK;
  630. *pfTry = FALSE;
  631. }
  632. }
  633. else
  634. {
  635. DIAGNOSTIC((TEXT("[0306]NO media -> No Content Autoplay!")));
  636. hr = S_OK;
  637. *pfTry = FALSE;
  638. }
  639. return hr;
  640. }
  641. HRESULT CVolume::_HandleMediaArrival()
  642. {
  643. DIAGNOSTIC((TEXT("[0002]Processing Media Arrival Event: %s"), _pszElemName));
  644. _dwMediaPresentFromEvent = MPFE_TRUE;
  645. _cs.Enter();
  646. HRESULT hr = _UpdateMediaInfo(INVALID_HANDLE_VALUE, TRUE);
  647. _cs.Leave();
  648. if (SUCCEEDED(hr))
  649. {
  650. if (_fHWDevInstInited)
  651. {
  652. // Try Autoplay?
  653. BOOL fTryAutoplay;
  654. hr = _ShouldTryAutoplay(&fTryAutoplay);
  655. if (SUCCEEDED(hr))
  656. {
  657. if (fTryAutoplay)
  658. {
  659. BOOL fHasHandler;
  660. hr = CHWEventDetectorImpl::HandleVolumeMediaEvent(
  661. _pszElemName, &_hwdevinst, TEXT("MediaArrival"),
  662. &fHasHandler);
  663. if (SUCCEEDED(hr) && fHasHandler)
  664. {
  665. _dwVolumeFlags |= HWDVF_STATE_HASAUTOPLAYHANDLER;
  666. }
  667. }
  668. else
  669. {
  670. _dwVolumeFlags |= HWDVF_STATE_DONOTSNIFFCONTENT;
  671. }
  672. }
  673. }
  674. else
  675. {
  676. DIAGNOSTIC((TEXT("[0308]Cannot find hardware device for this volume -> No Autoplay!")));
  677. }
  678. if (SUCCEEDED(hr))
  679. {
  680. _AdviseVolumeChangeHelper(FALSE);
  681. }
  682. }
  683. else
  684. {
  685. hr = S_FALSE;
  686. }
  687. return hr;
  688. }
  689. HRESULT CVolume::_AdviseVolumeMountingEvent(DWORD dwEvent)
  690. {
  691. return CHardwareDevicesImpl::_AdviseVolumeMountingEvent(_pszElemName,
  692. dwEvent);
  693. }
  694. HRESULT CVolume::_AdviseVolumeChangeHelper(BOOL fAdded)
  695. {
  696. HRESULT hr;
  697. VOLUMEINFO2* pvolinfo2;
  698. _cs.Enter();
  699. hr = _GetVOLUMEINFO2(&pvolinfo2);
  700. _cs.Leave();
  701. if (SUCCEEDED(hr))
  702. {
  703. LPWSTR pszMtPts;
  704. DWORD cchMtPts;
  705. hr = _GetMountPoints(&pszMtPts, &cchMtPts);
  706. if (SUCCEEDED(hr))
  707. {
  708. CHardwareDevicesImpl::_AdviseVolumeArrivedOrUpdated(pvolinfo2,
  709. pszMtPts, cchMtPts, fAdded);
  710. if (S_FALSE != hr)
  711. {
  712. LocalFree((HLOCAL)pszMtPts);
  713. }
  714. }
  715. _FreeMemoryChunk<VOLUMEINFO2*>(pvolinfo2);
  716. }
  717. return hr;
  718. }
  719. HRESULT CVolume::_HandleMediaRemoval()
  720. {
  721. HRESULT hr;
  722. DIAGNOSTIC((TEXT("[0003]Processing Media Removal Event: %s"), _pszElemName));
  723. _dwMediaPresentFromEvent = MPFE_FALSE;
  724. _cs.Enter();
  725. hr = _UpdateMediaInfoOnRemove();
  726. _cs.Leave();
  727. if (SUCCEEDED(hr))
  728. {
  729. _AdviseVolumeChangeHelper(FALSE);
  730. if (_fHWDevInstInited)
  731. {
  732. // Useless in this case, since there's no content, so we won't sniff
  733. BOOL fHasHandler;
  734. hr = CHWEventDetectorImpl::HandleVolumeMediaEvent(_pszElemName,
  735. &_hwdevinst, TEXT("MediaRemoval"), &fHasHandler);
  736. }
  737. else
  738. {
  739. DIAGNOSTIC((TEXT("[0309]Cannot find hardware device for this volume -> No Autoplay!")));
  740. }
  741. }
  742. return hr;
  743. }
  744. HRESULT CVolume::_HandleVolumeChange()
  745. {
  746. HRESULT hr;
  747. _cs.Enter();
  748. hr = _UpdateMediaInfo(INVALID_HANDLE_VALUE, TRUE);
  749. _cs.Leave();
  750. if (SUCCEEDED(hr))
  751. {
  752. _AdviseVolumeChangeHelper(FALSE);
  753. }
  754. else
  755. {
  756. hr = S_FALSE;
  757. }
  758. return hr;
  759. }
  760. HRESULT CVolume::HNTHandleEvent(DEV_BROADCAST_HANDLE* pdbh,
  761. DWORD dwEventType)
  762. {
  763. HRESULT hres = S_OK;
  764. if (DBT_CUSTOMEVENT == dwEventType)
  765. {
  766. if (GUID_IO_MEDIA_ARRIVAL == pdbh->dbch_eventguid)
  767. {
  768. // This notification arrive very soon when the media is inserted
  769. // in the device. Often the Volume driver has not been loaded on
  770. // the drive and calls like GetVolumeInformation will fail.
  771. // Instead of doing something right now, flag the event, and
  772. // process on the first GUID_IO_VOLUME_MOUNT below.
  773. TRACE(TF_SHHWDTCTDTCT,
  774. TEXT("****CVolume GUID_IO_MEDIA_ARRIVAL"));
  775. hres = _HandleMediaArrival();
  776. }
  777. else if (GUID_IO_MEDIA_REMOVAL == pdbh->dbch_eventguid)
  778. {
  779. TRACE(TF_SHHWDTCTDTCT,
  780. TEXT("****CVolume GUID_IO_MEDIA_REMOVAL"));
  781. hres = _HandleMediaRemoval();
  782. }
  783. else if (GUID_IO_VOLUME_MOUNT == pdbh->dbch_eventguid)
  784. {
  785. TRACE(TF_SHHWDTCTDTCT,
  786. TEXT("****CVolume GUID_IO_VOLUME_MOUNT"));
  787. if (_dwVolumeFlags & HWDVF_STATE_DISMOUNTED)
  788. {
  789. _dwVolumeFlags &= ~HWDVF_STATE_DISMOUNTED;
  790. hres = _AdviseVolumeMountingEvent(
  791. SHHARDWAREEVENT_VOLUMEMOUNTED);
  792. _HandleVolumeChange();
  793. }
  794. }
  795. else if (GUID_IO_VOLUME_NAME_CHANGE == pdbh->dbch_eventguid)
  796. {
  797. TRACE(TF_SHHWDTCTDTCT,
  798. TEXT("****CVolume GUID_IO_VOLUME_NAME_CHANGE"));
  799. _cs.Enter();
  800. hres = _UpdateMountPoints();
  801. _cs.Leave();
  802. }
  803. else if (GUID_IO_VOLUME_CHANGE == pdbh->dbch_eventguid)
  804. {
  805. TRACE(TF_SHHWDTCTDTCT,
  806. TEXT("****CVolume GUID_IO_VOLUME_CHANGE"));
  807. _cs.Enter();
  808. // This is for bug 645878. Basically, it's to cover the case of a
  809. // volume mounted on another volume's folder and then transfered
  810. // to another clustered machine. We use to miss the volume
  811. // mounted on the folder. Even thought the right event to send
  812. // would have been GUID_IO_VOLUME_NAME_CHANGE, it swas not
  813. // possible unless the cluster guys would have unmounted the volume
  814. // from the folder and remounted it, which is overkill just for an
  815. // icon.
  816. hres = _UpdateMountPoints();
  817. _cs.Leave();
  818. hres = _HandleVolumeChange();
  819. }
  820. else if (GUID_IO_VOLUME_DISMOUNT == pdbh->dbch_eventguid)
  821. {
  822. _dwVolumeFlags |= HWDVF_STATE_DISMOUNTED;
  823. hres = _AdviseVolumeMountingEvent(
  824. SHHARDWAREEVENT_VOLUMEDISMOUNTED);
  825. }
  826. else if (GUID_IO_VOLUME_DISMOUNT_FAILED == pdbh->dbch_eventguid)
  827. {
  828. _dwVolumeFlags &= ~HWDVF_STATE_DISMOUNTED;
  829. hres = _AdviseVolumeMountingEvent(
  830. SHHARDWAREEVENT_VOLUMEMOUNTED);
  831. }
  832. }
  833. return hres;
  834. }
  835. HRESULT CVolume::_GetDeviceHandleSafe(HANDLE* phDevice,
  836. BOOL fGenericReadRequired)
  837. {
  838. ASSERT(!_hdevnotify);
  839. HRESULT hr;
  840. HANDLE hDevice = _GetDeviceHandle(_pszElemName,
  841. fGenericReadRequired ? GENERIC_READ : FILE_READ_ATTRIBUTES);
  842. *phDevice = INVALID_HANDLE_VALUE;
  843. if (INVALID_HANDLE_VALUE != hDevice)
  844. {
  845. DEV_BROADCAST_HANDLE dbhNotifFilter = {0};
  846. dbhNotifFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
  847. dbhNotifFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
  848. dbhNotifFilter.dbch_handle = hDevice;
  849. hr = CHWEventDetectorHelper::RegisterDeviceNotification(
  850. &dbhNotifFilter, &_hdevnotify, FALSE);
  851. if (SUCCEEDED(hr) && (S_FALSE != hr))
  852. {
  853. *phDevice = hDevice;
  854. #ifdef DEBUG
  855. _fGenericReadRequired = fGenericReadRequired;
  856. #endif
  857. }
  858. else
  859. {
  860. _CloseDeviceHandle(hDevice);
  861. }
  862. }
  863. else
  864. {
  865. hr = S_FALSE;
  866. }
  867. return hr;
  868. }
  869. HRESULT CVolume::_CloseDeviceHandleSafe(HANDLE hDevice)
  870. {
  871. ASSERT(_hdevnotify);
  872. _CloseDeviceHandle(hDevice);
  873. UnregisterDeviceNotification(_hdevnotify);
  874. _hdevnotify = NULL;
  875. return S_OK;
  876. }
  877. HRESULT CVolume::_UnregisterNotif()
  878. {
  879. CNamedElemList* pnel;
  880. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_HANDLENOTIF,
  881. &pnel);
  882. if (S_OK == hres)
  883. {
  884. hres = pnel->Remove(_pszElemName);
  885. if (_szDeviceIDDisk[0])
  886. {
  887. hres = pnel->Remove(_szDeviceIDDisk);
  888. }
  889. pnel->RCRelease();
  890. }
  891. return hres;
  892. }
  893. HRESULT CVolume::_RegisterNotif()
  894. {
  895. CNamedElemList* pnel;
  896. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_HANDLENOTIF,
  897. &pnel);
  898. if (S_OK == hres)
  899. {
  900. CNamedElem* pelem;
  901. // register for handle notification
  902. hres = pnel->GetOrAdd(_pszElemName, &pelem);
  903. // Was it already there or added?
  904. if (SUCCEEDED(hres) && (S_FALSE == hres))
  905. {
  906. // Added. Initialize it.
  907. CHandleNotif* phnotif = (CHandleNotif*)pelem;
  908. hres = phnotif->InitNotif(this);
  909. if (SUCCEEDED(hres))
  910. {
  911. if (HWDTS_REMOVABLEDISK == _dwDriveType)
  912. {
  913. // Removable disk drives receive their notifications for
  914. // media arrival/removal on the disk interface, not the
  915. // volume one, so register for this too.
  916. WCHAR szDeviceIDDisk[MAX_DEVICEID];
  917. hres = _GetDeviceIDDisk(szDeviceIDDisk,
  918. ARRAYSIZE(szDeviceIDDisk));
  919. if (SUCCEEDED(hres) && (S_FALSE != hres))
  920. {
  921. CNamedElem* pelem2;
  922. // register for handle notification
  923. hres = pnel->GetOrAdd(szDeviceIDDisk, &pelem2);
  924. // Was it already there or added?
  925. if (SUCCEEDED(hres) && (S_FALSE == hres))
  926. {
  927. // Added. Initialize it.
  928. CHandleNotif* phnotif2 = (CHandleNotif*)pelem2;
  929. hres = phnotif2->InitNotif(this);
  930. if (FAILED(hres))
  931. {
  932. pnel->Remove(szDeviceIDDisk);
  933. }
  934. pelem2->RCRelease();
  935. }
  936. }
  937. }
  938. }
  939. if (FAILED(hres))
  940. {
  941. pnel->Remove(_pszElemName);
  942. }
  943. pelem->RCRelease();
  944. }
  945. pnel->RCRelease();
  946. }
  947. return hres;
  948. }
  949. HRESULT CVolume::_RemoveMtPt(LPWSTR pszMtPt)
  950. {
  951. CNamedElemList* pnel;
  952. HRESULT hr = CHWEventDetectorHelper::GetList(HWEDLIST_MTPT, &pnel);
  953. if (S_OK == hr)
  954. {
  955. hr = pnel->Remove(pszMtPt);
  956. pnel->RCRelease();
  957. }
  958. return hr;
  959. }
  960. HRESULT CVolume::_CreateMtPt(LPWSTR pszMtPt)
  961. {
  962. CNamedElemList* pnel;
  963. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_MTPT, &pnel);
  964. if (S_OK == hres)
  965. {
  966. CNamedElem* pelem;
  967. hres = pnel->GetOrAdd(pszMtPt, &pelem);
  968. if (SUCCEEDED(hres))
  969. {
  970. // Init one way or the other
  971. CMtPt* pmtpt = (CMtPt*)pelem;
  972. hres = pmtpt->InitVolume(_pszElemName);
  973. if (FAILED(hres))
  974. {
  975. pnel->Remove(pszMtPt);
  976. }
  977. pelem->RCRelease();
  978. }
  979. pnel->RCRelease();
  980. }
  981. return hres;
  982. }
  983. HRESULT CVolume::_AdviseMountPointHelper(LPCWSTR pszMountPoint, BOOL fAdded)
  984. {
  985. // I'd like to not call this from outside the crit sect
  986. ASSERT(_cs.IsInside());
  987. WCHAR szDeviceIDVolume[MAX_DEVICEID];
  988. DWORD cchReq;
  989. HRESULT hr = GetName(szDeviceIDVolume, ARRAYSIZE(szDeviceIDVolume), &cchReq);
  990. if (SUCCEEDED(hr))
  991. {
  992. CHardwareDevicesImpl::_AdviseMountPointHelper(pszMountPoint,
  993. szDeviceIDVolume, fAdded);
  994. }
  995. return hr;
  996. }
  997. HRESULT CVolume::_UpdateMountPoints()
  998. {
  999. LPWSTR pszMtPtNew;
  1000. DWORD cchMtPtNew;
  1001. HRESULT hr = _GetMountPoints(&pszMtPtNew, &cchMtPtNew);
  1002. #ifdef DEBUG
  1003. if (_pszMountPoints)
  1004. {
  1005. TRACE(TF_VOLUME, TEXT("_UpdateMountPoints: OLD mountPoints for %s:"), _pszElemName);
  1006. for (LPWSTR psz = _pszMountPoints; *psz; psz += lstrlen(psz) + 1)
  1007. {
  1008. TRACE(TF_VOLUME, TEXT(" %s"), psz);
  1009. }
  1010. }
  1011. #endif
  1012. if (SUCCEEDED(hr))
  1013. {
  1014. if (S_FALSE != hr)
  1015. {
  1016. #ifdef DEBUG
  1017. TRACE(TF_VOLUME, TEXT("_UpdateMountPoints: NEW mountPoints:"));
  1018. for (LPWSTR psz = pszMtPtNew; *psz; psz += lstrlen(psz) + 1)
  1019. {
  1020. TRACE(TF_VOLUME, TEXT(" %s"), psz);
  1021. }
  1022. #endif
  1023. // Was there at least one?
  1024. if (_pszMountPoints)
  1025. {
  1026. // Yep, find the removed ones
  1027. for (LPWSTR pszOld = _pszMountPoints; *pszOld;
  1028. pszOld += lstrlen(pszOld) + 1)
  1029. {
  1030. BOOL fFoundInNew = FALSE;
  1031. for (LPWSTR pszNew = pszMtPtNew; !fFoundInNew && *pszNew;
  1032. pszNew += lstrlen(pszNew) + 1)
  1033. {
  1034. if (!lstrcmpi(pszNew, pszOld))
  1035. {
  1036. fFoundInNew = TRUE;
  1037. }
  1038. }
  1039. if (!fFoundInNew)
  1040. {
  1041. TRACE(TF_VOLUME, TEXT("_UpdateMountPoints: Found DELETED one: %s"), pszOld);
  1042. // That's a deleted one
  1043. _RemoveMtPt(pszOld);
  1044. _AdviseMountPointHelper(pszOld, FALSE);
  1045. }
  1046. }
  1047. }
  1048. else
  1049. {
  1050. TRACE(TF_VOLUME, TEXT("_UpdateMountPoints: There was NO mountpoints before"));
  1051. }
  1052. // Find the new ones
  1053. for (LPWSTR pszNew = pszMtPtNew; *pszNew;
  1054. pszNew += lstrlen(pszNew) + 1)
  1055. {
  1056. BOOL fFoundInOld = FALSE;
  1057. if (_pszMountPoints)
  1058. {
  1059. for (LPWSTR pszOld = _pszMountPoints;
  1060. !fFoundInOld && *pszOld; pszOld += lstrlen(pszOld) + 1)
  1061. {
  1062. if (!lstrcmpi(pszNew, pszOld))
  1063. {
  1064. fFoundInOld = TRUE;
  1065. }
  1066. }
  1067. }
  1068. if (!fFoundInOld)
  1069. {
  1070. TRACE(TF_VOLUME, TEXT("_UpdateMountPoints: Found ADDED one: %s"), pszNew);
  1071. // That's a new one
  1072. _CreateMtPt(pszNew);
  1073. _AdviseMountPointHelper(pszNew, TRUE);
  1074. }
  1075. }
  1076. LocalFree(_pszMountPoints);
  1077. _pszMountPoints = pszMtPtNew;
  1078. _cchMountPoints = cchMtPtNew;
  1079. }
  1080. else
  1081. {
  1082. TRACE(TF_VOLUME, TEXT("_UpdateMountPoints: NO MountPoints left, remove all old ones"));
  1083. if (_pszMountPoints && *_pszMountPoints)
  1084. {
  1085. for (LPWSTR pszOld = _pszMountPoints; *pszOld;
  1086. pszOld += lstrlen(pszOld) + 1)
  1087. {
  1088. _RemoveMtPt(pszOld);
  1089. _AdviseMountPointHelper(pszOld, FALSE);
  1090. }
  1091. LocalFree(_pszMountPoints);
  1092. _pszMountPoints = NULL;
  1093. _cchMountPoints = 0;
  1094. }
  1095. }
  1096. }
  1097. return hr;
  1098. }
  1099. HRESULT CVolume::_CreateMountPoints()
  1100. {
  1101. HRESULT hr = _GetMountPoints(&_pszMountPoints, &_cchMountPoints);
  1102. if (SUCCEEDED(hr))
  1103. {
  1104. if (S_FALSE != hr)
  1105. {
  1106. for (LPWSTR psz = _pszMountPoints; *psz;
  1107. psz += lstrlen(psz) + 1)
  1108. {
  1109. _CreateMtPt(psz);
  1110. // go on even if error
  1111. }
  1112. }
  1113. else
  1114. {
  1115. hr = S_OK;
  1116. }
  1117. }
  1118. return hr;
  1119. }
  1120. // Caller must free returned data using LocalFree
  1121. HRESULT CVolume::_GetMountPoints(LPWSTR* ppsz, DWORD* pcch)
  1122. {
  1123. HRESULT hr;
  1124. LPWSTR psz = NULL;
  1125. DWORD cch;
  1126. *ppsz = NULL;
  1127. *pcch = 0;
  1128. if (GetVolumePathNamesForVolumeName(_szVolumeGUID, NULL, 0, &cch))
  1129. {
  1130. // no mountpoint, we're done
  1131. hr = S_FALSE;
  1132. }
  1133. else
  1134. {
  1135. // Expected, even wanted...
  1136. if (ERROR_MORE_DATA == GetLastError())
  1137. {
  1138. psz = (LPWSTR)LocalAlloc(LPTR, cch * sizeof(WCHAR));
  1139. if (psz)
  1140. {
  1141. if (GetVolumePathNamesForVolumeName(_szVolumeGUID,
  1142. psz, cch, &cch))
  1143. {
  1144. *ppsz = psz;
  1145. *pcch = cch;
  1146. hr = S_OK;
  1147. }
  1148. else
  1149. {
  1150. LocalFree(psz);
  1151. hr = S_FALSE;
  1152. }
  1153. }
  1154. else
  1155. {
  1156. hr = E_OUTOFMEMORY;
  1157. }
  1158. }
  1159. else
  1160. {
  1161. hr = S_FALSE;
  1162. }
  1163. }
  1164. return hr;
  1165. }
  1166. HRESULT _DeviceMediaIsAccessible(HANDLE hDevice, BOOL* pfAccessible)
  1167. {
  1168. HRESULT hres = S_FALSE;
  1169. DWORD dwDummy;
  1170. *pfAccessible = FALSE;
  1171. // requires GENERIC_READ access on the handle
  1172. BOOL b = DeviceIoControl(hDevice, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0, &dwDummy, NULL);
  1173. if (ERROR_MEDIA_CHANGED == GetLastError())
  1174. {
  1175. // try one more time, ERROR_MEDIA_CHANGED means it's still pending for a little bit.
  1176. b = DeviceIoControl(hDevice, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0, &dwDummy, NULL);
  1177. }
  1178. if (b)
  1179. {
  1180. *pfAccessible = TRUE;
  1181. hres = S_OK;
  1182. }
  1183. else
  1184. {
  1185. // ERROR_NOT_READY == GetLastError() means no media
  1186. if (ERROR_NOT_READY == GetLastError())
  1187. {
  1188. hres = S_OK;
  1189. }
  1190. else
  1191. {
  1192. hres = S_FALSE;
  1193. }
  1194. }
  1195. return hres;
  1196. }
  1197. HRESULT CVolume::_UpdateHasMedia(HANDLE hDevice)
  1198. {
  1199. HRESULT hr = S_FALSE;
  1200. switch (_dwDriveType)
  1201. {
  1202. case HWDTS_FIXEDDISK:
  1203. _dwMediaState |= HWDMS_PRESENT;
  1204. hr = S_OK;
  1205. break;
  1206. case HWDTS_REMOVABLEDISK:
  1207. case HWDTS_CDROM:
  1208. {
  1209. #if 0
  1210. This does not work on my laptop
  1211. if (_dwDriveCap & HWDDC_CAPABILITY_SUPPORTDETECTION)
  1212. {
  1213. // It's MMC2
  1214. if (_dwMediaCap & (HWDMC_CDROM | HWDMC_CDRECORDABLE |
  1215. HWDMC_CDREWRITABLE | HWDMC_DVDROM | HWDMC_DVDRECORDABLE |
  1216. HWDMC_DVDRAM))
  1217. {
  1218. _dwMediaState |= HWDMS_PRESENT;
  1219. }
  1220. else
  1221. {
  1222. _dwMediaState &= ~HWDMS_PRESENT;
  1223. }
  1224. }
  1225. else
  1226. #endif
  1227. if (MPFE_UNDETERMINED != _dwMediaPresentFromEvent)
  1228. {
  1229. hr = S_OK;
  1230. if (MPFE_TRUE == _dwMediaPresentFromEvent)
  1231. {
  1232. _dwMediaState |= HWDMS_PRESENT;
  1233. }
  1234. else
  1235. {
  1236. _dwMediaState &= ~HWDMS_PRESENT;
  1237. }
  1238. }
  1239. else
  1240. {
  1241. BOOL fAccessible;
  1242. ASSERT(_fGenericReadRequired);
  1243. hr = _DeviceMediaIsAccessible(hDevice, &fAccessible);
  1244. if (SUCCEEDED(hr) && (S_FALSE != hr))
  1245. {
  1246. if (fAccessible)
  1247. {
  1248. _dwMediaState |= HWDMS_PRESENT;
  1249. }
  1250. else
  1251. {
  1252. _dwMediaState &= ~HWDMS_PRESENT;
  1253. }
  1254. }
  1255. else
  1256. {
  1257. _dwMediaState &= ~HWDMS_PRESENT;
  1258. }
  1259. }
  1260. break;
  1261. }
  1262. default:
  1263. // ISSUE-2000/10/23-StephStm: We do not handle CD Changer, maybe we should
  1264. //
  1265. // case HWDTS_CDCHANGER:
  1266. case HWDTS_FLOPPY35:
  1267. case HWDTS_FLOPPY525:
  1268. _dwMediaState &= ~HWDMS_PRESENT;
  1269. break;
  1270. }
  1271. return hr;
  1272. }
  1273. HRESULT CVolume::_ExtractAutorunIconAndLabel()
  1274. {
  1275. WCHAR szInfFile[MAX_PATH + 50];
  1276. LPWSTR pszNext;
  1277. DWORD cchLeft;
  1278. HRESULT hr = SafeStrCpyNEx(szInfFile, _szVolumeGUID, ARRAYSIZE(szInfFile),
  1279. &pszNext, &cchLeft);
  1280. if (SUCCEEDED(hr))
  1281. {
  1282. hr = SafeStrCpyN(pszNext, TEXT("Autorun.inf"), cchLeft);
  1283. if (SUCCEEDED(hr))
  1284. {
  1285. WCHAR szDummy[4];
  1286. #if defined(_X86_)
  1287. LPWSTR pszSection = TEXT("AutoRun.x86");
  1288. #elif defined(_AMD64_)
  1289. LPWSTR pszSection = TEXT("AutoRun.Amd64");
  1290. #elif defined(_IA64_)
  1291. LPWSTR pszSection = TEXT("AutoRun.Ia64");
  1292. #else
  1293. #error "No Target Architecture"
  1294. #endif
  1295. // Flush some buffer somewhere
  1296. WritePrivateProfileString(NULL, NULL, NULL, szInfFile);
  1297. if (!GetPrivateProfileString(pszSection, TEXT("Icon"), TEXT(""),
  1298. _szAutorunIconLocation, ARRAYSIZE(_szAutorunIconLocation),
  1299. szInfFile))
  1300. {
  1301. pszSection = TEXT("AutoRun");
  1302. _HandleAccessDenied();
  1303. if (!GetPrivateProfileString(pszSection, TEXT("Icon"),
  1304. TEXT(""), _szAutorunIconLocation,
  1305. ARRAYSIZE(_szAutorunIconLocation), szInfFile))
  1306. {
  1307. _szAutorunIconLocation[0] = 0;
  1308. _HandleAccessDenied();
  1309. }
  1310. }
  1311. if (!GetPrivateProfileString(pszSection, TEXT("Label"), TEXT(""),
  1312. _szAutorunLabel, ARRAYSIZE(_szAutorunLabel), szInfFile))
  1313. {
  1314. _szAutorunLabel[0] = 0;
  1315. _HandleAccessDenied();
  1316. }
  1317. if (GetPrivateProfileString(pszSection, TEXT("Open"), TEXT(""),
  1318. szDummy, ARRAYSIZE(szDummy), szInfFile) ||
  1319. GetPrivateProfileString(pszSection, TEXT("ShellExecute"), TEXT(""),
  1320. szDummy, ARRAYSIZE(szDummy), szInfFile))
  1321. {
  1322. _dwMediaCap |= HWDMC_HASAUTORUNCOMMAND;
  1323. }
  1324. else
  1325. {
  1326. _HandleAccessDenied();
  1327. }
  1328. if (GetPrivateProfileString(pszSection, TEXT("UseAutoPLAY"), TEXT(""),
  1329. szDummy, ARRAYSIZE(szDummy), szInfFile))
  1330. {
  1331. _dwMediaCap |= HWDMC_HASUSEAUTOPLAY;
  1332. }
  1333. else
  1334. {
  1335. _HandleAccessDenied();
  1336. }
  1337. }
  1338. }
  1339. return hr;
  1340. }
  1341. HRESULT CVolume::_UpdateSpecialFilePresence()
  1342. {
  1343. struct SPECIALFILEINFO
  1344. {
  1345. LPCWSTR pszFile;
  1346. DWORD dwCapBit;
  1347. };
  1348. HRESULT hr;
  1349. WCHAR szPath[50 + 1 + ARRAYSIZE(TEXT("video_ts\\video_ts.ifo"))];
  1350. static const SPECIALFILEINFO rgsfi[] =
  1351. {
  1352. { TEXT("autorun.inf"), HWDMC_HASAUTORUNINF },
  1353. { TEXT("desktop.ini"), HWDMC_HASDESKTOPINI },
  1354. { TEXT("video_ts\\video_ts.ifo"), HWDMC_HASDVDMOVIE },
  1355. };
  1356. LPWSTR pszNext;
  1357. DWORD cchLeft;
  1358. hr = SafeStrCpyNEx(szPath, _szVolumeGUID,
  1359. ARRAYSIZE(szPath), &pszNext, &cchLeft);
  1360. if (SUCCEEDED(hr))
  1361. {
  1362. for (DWORD dw = 0; dw < ARRAYSIZE(rgsfi); ++dw)
  1363. {
  1364. hr = SafeStrCpyN(pszNext, rgsfi[dw].pszFile, cchLeft);
  1365. if (SUCCEEDED(hr))
  1366. {
  1367. DWORD dwGFA = GetFileAttributes(szPath);
  1368. if (-1 != dwGFA)
  1369. {
  1370. _dwMediaCap |= (rgsfi[dw].dwCapBit);
  1371. }
  1372. else
  1373. {
  1374. _HandleAccessDenied();
  1375. }
  1376. }
  1377. }
  1378. }
  1379. // To fix bug 425431
  1380. if (HWDMC_HASDVDMOVIE & _dwMediaCap)
  1381. {
  1382. // This better be a CD/DVD drive.
  1383. if (HWDTS_CDROM != _dwDriveType)
  1384. {
  1385. // No. Remove the flag otherwise, Hard Disks get a Play verb
  1386. // when they have the ts_video\video_ts.ifo file in their root.
  1387. _dwMediaCap &= ~HWDMC_HASDVDMOVIE;
  1388. }
  1389. }
  1390. return hr;
  1391. }
  1392. #define TRACK_TYPE_MASK 0x04
  1393. #define AUDIO_TRACK 0x00
  1394. #define DATA_TRACK 0x04
  1395. HRESULT CVolume::_UpdateTrackInfo(HANDLE hDevice)
  1396. {
  1397. HRESULT hr;
  1398. ASSERT(!(_dwMediaCap & (HWDMC_HASDATATRACKS | HWDMC_HASAUDIOTRACKS)));
  1399. hr = S_OK;
  1400. // To be compatible with Win95, we'll only return TRUE from this
  1401. // function if the disc has ONLY audio tracks (and NO data tracks).
  1402. // FEATURE: Post NT-SUR beta 1, we should consider adding a new
  1403. // DriveType flag for "contains data tracks" and revamp the commands
  1404. // available on a CD-ROM drive. The current code doesn't handle
  1405. // mixed audio/data and audio/autorun discs very usefully. --JonBe
  1406. // First try the new IOCTL which gives us a ULONG with bits indicating
  1407. // the presence of either/both data & audio tracks
  1408. CDROM_DISK_DATA data;
  1409. DWORD dwDummy;
  1410. // Requires GENERIC_READ access on the handle
  1411. if (DeviceIoControl(hDevice, IOCTL_CDROM_DISK_TYPE, NULL, 0, &data,
  1412. sizeof(data), &dwDummy, NULL))
  1413. {
  1414. if (data.DiskData & CDROM_DISK_AUDIO_TRACK)
  1415. {
  1416. _dwMediaCap |= HWDMC_HASAUDIOTRACKS;
  1417. }
  1418. if (data.DiskData & CDROM_DISK_DATA_TRACK)
  1419. {
  1420. _dwMediaCap |= HWDMC_HASDATATRACKS;
  1421. }
  1422. }
  1423. else
  1424. {
  1425. // else that failed, so try to look for audio tracks the old way, by
  1426. // looking throught the table of contents manually. Note that data tracks
  1427. // are supposed to be hidden in the TOC by CDFS now on mixed audio/data
  1428. // discs (at least if the data tracks follow the audio tracks).
  1429. CDROM_TOC toc = {0};
  1430. if (!DeviceIoControl(hDevice, IOCTL_CDROM_READ_TOC, NULL, 0, &toc,
  1431. sizeof(toc), &dwDummy, NULL))
  1432. {
  1433. SUB_Q_CHANNEL_DATA subq = {0};
  1434. CDROM_SUB_Q_DATA_FORMAT df = {0};
  1435. // We might not have been able to read the TOC because the drive
  1436. // was busy playing audio. Lets try querying the audio position.
  1437. df.Format = IOCTL_CDROM_CURRENT_POSITION;
  1438. df.Track = 0;
  1439. if (DeviceIoControl(hDevice, IOCTL_CDROM_READ_Q_CHANNEL, &df,
  1440. sizeof(df), &subq, sizeof(subq), &dwDummy, NULL))
  1441. {
  1442. if (AUDIO_DATA_TRACK & subq.CurrentPosition.Control)
  1443. {
  1444. _dwMediaCap |= HWDMC_HASDATATRACKS;
  1445. }
  1446. else
  1447. {
  1448. _dwMediaCap |= HWDMC_HASAUDIOTRACKS;
  1449. }
  1450. }
  1451. // Is there the equivalent of IOCTL_CDROM_READ_Q_CHANNEL for data?
  1452. _dwMediaCap |= HWDMC_HASDATATRACKS_UNDETERMINED;
  1453. }
  1454. else
  1455. {
  1456. int nTracks = (toc.LastTrack - toc.FirstTrack) + 1;
  1457. int iTrack = 0;
  1458. // Now iterate through the tracks looking for Audio data
  1459. while ((iTrack < nTracks) &&
  1460. ((_dwMediaCap & (HWDMC_HASDATATRACKS | HWDMC_HASDATATRACKS)) !=
  1461. (HWDMC_HASDATATRACKS | HWDMC_HASDATATRACKS))
  1462. )
  1463. {
  1464. if ((toc.TrackData[iTrack].Control & TRACK_TYPE_MASK) == AUDIO_TRACK)
  1465. {
  1466. _dwMediaCap |= HWDMC_HASAUDIOTRACKS;
  1467. }
  1468. else
  1469. {
  1470. if ((toc.TrackData[iTrack].Control & TRACK_TYPE_MASK) == DATA_TRACK)
  1471. {
  1472. _dwMediaCap |= HWDMC_HASDATATRACKS;
  1473. }
  1474. }
  1475. ++iTrack;
  1476. }
  1477. }
  1478. }
  1479. return hr;
  1480. }
  1481. HRESULT CVolume::_UpdateMediaInfoOnRemove()
  1482. {
  1483. _dwMediaCap = 0;
  1484. _dwMediaState = 0;
  1485. _szAutorunIconLocation[0] = 0;
  1486. _szAutorunLabel[0] = 0;
  1487. _dwSerialNumber = 0xBADBADBD;
  1488. SafeStrCpyN(_szLabel, TEXT("Invalid"), ARRAYSIZE(_szLabel));
  1489. SafeStrCpyN(_szFileSystem, TEXT("Invalid"), ARRAYSIZE(_szFileSystem));
  1490. _dwRootAttributes = 0xBADBADBD;
  1491. _dwMaxFileNameLen = 0xBADBADBD;
  1492. _dwFileSystemFlags = 0xBADBADBD;
  1493. _dwVolumeFlags &= ~(HWDVF_STATE_HASAUTOPLAYHANDLER |
  1494. HWDVF_STATE_DONOTSNIFFCONTENT | HWDVF_STATE_JUSTDOCKED);
  1495. return S_OK;
  1496. }
  1497. inline BOOL _XOR(BOOL bA, BOOL bB)
  1498. {
  1499. return (bA && !bB) || (!bA && bB);
  1500. }
  1501. HRESULT CVolume::_UpdateMediaInfo(HANDLE hDevice, BOOL fGetYourOwnHandle)
  1502. {
  1503. HRESULT hr;
  1504. CImpersonateEveryone* pieo = NULL;
  1505. ASSERT(_XOR((hDevice != INVALID_HANDLE_VALUE), fGetYourOwnHandle));
  1506. if (fGetYourOwnHandle)
  1507. {
  1508. hr = CHWEventDetectorHelper::GetImpersonateEveryone(&pieo);
  1509. if (SUCCEEDED(hr) && (S_FALSE != hr))
  1510. {
  1511. hr = pieo->Impersonate();
  1512. if (SUCCEEDED(hr) && (S_FALSE != hr))
  1513. {
  1514. hr = _GetDeviceHandleSafe(&hDevice, TRUE);
  1515. if (FAILED(hr) || (S_FALSE == hr))
  1516. {
  1517. pieo->RCRelease();
  1518. pieo = NULL;
  1519. }
  1520. }
  1521. }
  1522. }
  1523. else
  1524. {
  1525. hr = S_OK;
  1526. }
  1527. _dwVolumeFlags &= ~(HWDVF_STATE_HASAUTOPLAYHANDLER |
  1528. HWDVF_STATE_DONOTSNIFFCONTENT | HWDVF_STATE_JUSTDOCKED);
  1529. if (SUCCEEDED(hr) && (S_FALSE != hr))
  1530. {
  1531. if (HWDTS_CDROM == _dwDriveType)
  1532. {
  1533. ASSERT(_fGenericReadRequired);
  1534. // optimization
  1535. if (_fFirstTime)
  1536. {
  1537. // already updated by _UpdateConstInfo
  1538. _fFirstTime = FALSE;
  1539. }
  1540. else
  1541. {
  1542. _dwMediaCap = 0;
  1543. hr = _UpdateMMC2CDInfo(hDevice);
  1544. }
  1545. }
  1546. else
  1547. {
  1548. _dwMediaCap = 0;
  1549. }
  1550. if (SUCCEEDED(hr))
  1551. {
  1552. hr = _UpdateHasMedia(hDevice);
  1553. if (SUCCEEDED(hr) && (_dwMediaState & HWDMS_PRESENT))
  1554. {
  1555. if (GetVolumeInformation(_szVolumeGUID, _szLabel,
  1556. ARRAYSIZE(_szLabel), &_dwSerialNumber,
  1557. &_dwMaxFileNameLen, &_dwFileSystemFlags, _szFileSystem,
  1558. ARRAYSIZE(_szFileSystem)))
  1559. {
  1560. // use this?
  1561. // UINT err = SetErrorMode(SEM_FAILCRITICALERRORS);
  1562. // Root folder attributes
  1563. _dwRootAttributes = GetFileAttributes(_szVolumeGUID);
  1564. if (-1 != _dwRootAttributes)
  1565. {
  1566. // File presence
  1567. hr = _UpdateSpecialFilePresence();
  1568. if (SUCCEEDED(hr))
  1569. {
  1570. if (HWDTS_CDROM == _dwDriveType)
  1571. {
  1572. hr = _UpdateTrackInfo(hDevice);
  1573. }
  1574. if (HWDMC_HASAUTORUNINF & _dwMediaCap)
  1575. {
  1576. hr = _ExtractAutorunIconAndLabel();
  1577. // not critical
  1578. if (FAILED(hr))
  1579. {
  1580. hr = S_FALSE;
  1581. }
  1582. }
  1583. }
  1584. }
  1585. else
  1586. {
  1587. _HandleAccessDenied();
  1588. _dwState |= STATE_GFAFAILED;
  1589. hr = S_FALSE;
  1590. }
  1591. _dwMediaState |= HWDMS_FORMATTED;
  1592. }
  1593. else
  1594. {
  1595. if (ERROR_NOT_READY == GetLastError())
  1596. {
  1597. // We get this for offline cluster volumes. Setting
  1598. // dismounted gets us the right Shell behavior.
  1599. _dwVolumeFlags |= HWDVF_STATE_DISMOUNTED;
  1600. }
  1601. else
  1602. {
  1603. _HandleAccessDenied();
  1604. _dwMediaState &= ~HWDMS_FORMATTED;
  1605. }
  1606. // To help us debug, even in retail
  1607. _dwState |= STATE_GVIFAILED;
  1608. _dwSerialNumber = GetLastError();
  1609. hr = S_FALSE;
  1610. }
  1611. }
  1612. else
  1613. {
  1614. _dwState |= STATE_UPDATEHASMEDIAFAILED;
  1615. _dwMediaCap = 0;
  1616. hr = S_FALSE;
  1617. }
  1618. }
  1619. if (S_FALSE == hr)
  1620. {
  1621. // We don't care if they fail
  1622. SafeStrCpyN(_szLabel, TEXT("Invalid"), ARRAYSIZE(_szLabel));
  1623. SafeStrCpyN(_szFileSystem, TEXT("Invalid"), ARRAYSIZE(_szFileSystem));
  1624. _dwRootAttributes = 0xBADBADBD;
  1625. _dwMaxFileNameLen = 0xBADBADBD;
  1626. _dwFileSystemFlags = 0xBADBADBD;
  1627. }
  1628. if (fGetYourOwnHandle)
  1629. {
  1630. _CloseDeviceHandleSafe(hDevice);
  1631. pieo->RevertToSelf();
  1632. pieo->RCRelease();
  1633. }
  1634. }
  1635. return hr;
  1636. }
  1637. const FEATURE_NUMBER _rgfnInteresting[] =
  1638. {
  1639. // FeatureProfileList needs to remain the first one
  1640. FeatureProfileList, // = 0x0000,
  1641. FeatureCdRead, // = 0x001e,
  1642. FeatureDvdRead, // = 0x001f,
  1643. FeatureRandomWritable, // = 0x0020,
  1644. FeatureIncrementalStreamingWritable, // = 0x0021,
  1645. FeatureFormattable, // = 0x0023,
  1646. FeatureDefectManagement, // = 0x0024,
  1647. FeatureRestrictedOverwrite, // = 0x0026,
  1648. FeatureCdTrackAtOnce, // = 0x002d,
  1649. FeatureCdMastering, // = 0x002e,
  1650. FeatureDvdRecordableWrite, // = 0x002f,
  1651. FeatureCDAudioAnalogPlay, // = 0x0103,
  1652. };
  1653. struct CAPABILITYFEATURESMAP
  1654. {
  1655. DWORD dwCapability;
  1656. DWORD dwCapabilityDependent;
  1657. const FEATURE_NUMBER* prgFeature;
  1658. DWORD cFeature;
  1659. };
  1660. const FEATURE_NUMBER rgfnWRITECAP[] =
  1661. {
  1662. FeatureProfileList,
  1663. };
  1664. const FEATURE_NUMBER rgfnCDROM[] =
  1665. {
  1666. FeatureCdRead,
  1667. };
  1668. const FEATURE_NUMBER rgfnCDRECORDABLE[] =
  1669. {
  1670. FeatureIncrementalStreamingWritable,
  1671. FeatureCdTrackAtOnce,
  1672. FeatureCdMastering,
  1673. };
  1674. const FEATURE_NUMBER rgfnCDREWRITABLE[] =
  1675. {
  1676. FeatureFormattable,
  1677. };
  1678. const FEATURE_NUMBER rgfnDVDROM[] =
  1679. {
  1680. FeatureDvdRead,
  1681. };
  1682. const FEATURE_NUMBER rgfnDVDRECORDABLE[] =
  1683. {
  1684. FeatureDvdRecordableWrite,
  1685. };
  1686. const FEATURE_NUMBER rgfnDVDREWRITABLE[] =
  1687. {
  1688. FeatureFormattable,
  1689. };
  1690. const FEATURE_NUMBER rgfnDVDRAM[] =
  1691. {
  1692. FeatureRandomWritable,
  1693. FeatureDefectManagement,
  1694. };
  1695. const FEATURE_NUMBER rgfnANALOGAUDIOOUT[] =
  1696. {
  1697. FeatureCDAudioAnalogPlay,
  1698. };
  1699. const CAPABILITYFEATURESMAP _rgcapfeaturemap[] =
  1700. {
  1701. {
  1702. HWDMC_WRITECAPABILITY_SUPPORTDETECTION,
  1703. 0,
  1704. rgfnWRITECAP,
  1705. ARRAYSIZE(rgfnWRITECAP),
  1706. },
  1707. {
  1708. HWDMC_CDROM,
  1709. HWDMC_WRITECAPABILITY_SUPPORTDETECTION,
  1710. rgfnCDROM,
  1711. ARRAYSIZE(rgfnCDROM),
  1712. },
  1713. {
  1714. HWDMC_CDRECORDABLE,
  1715. HWDMC_WRITECAPABILITY_SUPPORTDETECTION,
  1716. rgfnCDRECORDABLE,
  1717. ARRAYSIZE(rgfnCDRECORDABLE),
  1718. },
  1719. {
  1720. HWDMC_CDREWRITABLE,
  1721. HWDMC_CDRECORDABLE,
  1722. rgfnCDREWRITABLE,
  1723. ARRAYSIZE(rgfnCDREWRITABLE),
  1724. },
  1725. {
  1726. HWDMC_DVDROM,
  1727. HWDMC_WRITECAPABILITY_SUPPORTDETECTION,
  1728. rgfnDVDROM,
  1729. ARRAYSIZE(rgfnDVDROM),
  1730. },
  1731. {
  1732. HWDMC_DVDRECORDABLE,
  1733. HWDMC_WRITECAPABILITY_SUPPORTDETECTION,
  1734. rgfnDVDRECORDABLE,
  1735. ARRAYSIZE(rgfnDVDRECORDABLE),
  1736. },
  1737. {
  1738. HWDMC_DVDREWRITABLE,
  1739. HWDMC_DVDRECORDABLE,
  1740. rgfnDVDREWRITABLE,
  1741. ARRAYSIZE(rgfnDVDREWRITABLE),
  1742. },
  1743. {
  1744. HWDMC_DVDRAM,
  1745. HWDMC_DVDROM,
  1746. rgfnDVDRAM,
  1747. ARRAYSIZE(rgfnDVDRAM),
  1748. },
  1749. {
  1750. HWDMC_ANALOGAUDIOOUT,
  1751. HWDMC_WRITECAPABILITY_SUPPORTDETECTION,
  1752. rgfnANALOGAUDIOOUT,
  1753. ARRAYSIZE(rgfnANALOGAUDIOOUT),
  1754. },
  1755. };
  1756. #define MMC2_NOTSUPPORTED 0
  1757. #define MMC2_DRIVESUPPORTED 1
  1758. #define MMC2_MEDIASUPPORTED 2
  1759. HRESULT CVolume::_FillMMC2CD(HANDLE hDevice)
  1760. {
  1761. HRESULT hr;
  1762. if (!_prgMMC2Features)
  1763. {
  1764. _prgMMC2Features = (DWORD*)LocalAlloc(LPTR,
  1765. ARRAYSIZE(_rgfnInteresting) * sizeof(DWORD));
  1766. }
  1767. if (_prgMMC2Features)
  1768. {
  1769. DWORD cbHeader = sizeof(GET_CONFIGURATION_HEADER) +
  1770. sizeof(FEATURE_HEADER);
  1771. GET_CONFIGURATION_HEADER* pheader = (GET_CONFIGURATION_HEADER*)
  1772. LocalAlloc(LPTR, cbHeader);
  1773. if (pheader)
  1774. {
  1775. GET_CONFIGURATION_IOCTL_INPUT gcii;
  1776. gcii.RequestType = SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE;
  1777. gcii.Reserved[0] = NULL;
  1778. gcii.Reserved[1] = NULL;
  1779. for (DWORD dw = 0; dw < ARRAYSIZE(_rgfnInteresting); ++dw)
  1780. {
  1781. FEATURE_HEADER* pfh;
  1782. DWORD cbReturned;
  1783. gcii.Feature = _rgfnInteresting[dw];
  1784. _prgMMC2Features[dw] = MMC2_NOTSUPPORTED;
  1785. // Requires GENERIC_READ access on the handle
  1786. if (DeviceIoControl(hDevice, IOCTL_CDROM_GET_CONFIGURATION,
  1787. &gcii, sizeof(GET_CONFIGURATION_IOCTL_INPUT), pheader,
  1788. cbHeader, &cbReturned, NULL))
  1789. {
  1790. pfh = (FEATURE_HEADER*)(pheader->Data);
  1791. WORD w = (pfh->FeatureCode[0]) << 8 | (pfh->FeatureCode[1]);
  1792. if (w == _rgfnInteresting[dw])
  1793. {
  1794. _prgMMC2Features[dw] = MMC2_DRIVESUPPORTED;
  1795. if (pfh->Current)
  1796. {
  1797. _prgMMC2Features[dw] |= MMC2_MEDIASUPPORTED;
  1798. }
  1799. else
  1800. {
  1801. _prgMMC2Features[dw] &= ~MMC2_MEDIASUPPORTED;
  1802. }
  1803. }
  1804. }
  1805. }
  1806. LocalFree(pheader);
  1807. }
  1808. hr = S_OK;
  1809. }
  1810. else
  1811. {
  1812. hr = E_OUTOFMEMORY;
  1813. }
  1814. return hr;
  1815. }
  1816. // Rainier drive exposes features which perfectly matches DVD-RAM
  1817. // required feature set. But they are CD-R/RW. For drives
  1818. // we think are DVD-RAM, check if they also expose a DVD_RAM profile.
  1819. // We cannot use profiles all the way because they are not reliable.
  1820. // The same Rainier drive that expose bug 446652 exposes only
  1821. // the CDRewritable profile but it does support CDRecordable and
  1822. // CD-ROM.
  1823. HRESULT CVolume::_DVDRAMHack(HANDLE hDevice)
  1824. {
  1825. BOOL fSupported = FALSE;
  1826. BOOL fCurrent = FALSE;
  1827. if (HWDDC_DVDRAM & _dwDriveCap)
  1828. {
  1829. // Do the check
  1830. const DWORD cbHeaderInitial = sizeof(GET_CONFIGURATION_HEADER) + sizeof(FEATURE_HEADER);
  1831. DWORD cbReturned;
  1832. DWORD cbHeader = cbHeaderInitial;
  1833. BYTE rgbBuffer[cbHeaderInitial];
  1834. GET_CONFIGURATION_IOCTL_INPUT input;
  1835. GET_CONFIGURATION_HEADER* pheader = (GET_CONFIGURATION_HEADER*)rgbBuffer;
  1836. ZeroMemory(&input, sizeof(GET_CONFIGURATION_IOCTL_INPUT));
  1837. ZeroMemory(rgbBuffer, sizeof(rgbBuffer));
  1838. // Ask for the profile list
  1839. input.Feature = FeatureProfileList;
  1840. // We want only this feature back
  1841. input.RequestType = SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL;
  1842. BOOL f = DeviceIoControl(hDevice,
  1843. IOCTL_CDROM_GET_CONFIGURATION,
  1844. &input,
  1845. sizeof(GET_CONFIGURATION_IOCTL_INPUT),
  1846. pheader,
  1847. cbHeader,
  1848. &cbReturned,
  1849. NULL);
  1850. if (f)
  1851. {
  1852. cbHeader = pheader->DataLength[0] << 24 |
  1853. pheader->DataLength[1] << 16 |
  1854. pheader->DataLength[2] << 8 |
  1855. pheader->DataLength[3] << 0;
  1856. GET_CONFIGURATION_HEADER* pheader2 = (GET_CONFIGURATION_HEADER*)LocalAlloc(LPTR,
  1857. cbHeader);
  1858. if (pheader2)
  1859. {
  1860. // We want all the profiles back
  1861. input.RequestType = SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL;
  1862. f = DeviceIoControl(hDevice,
  1863. IOCTL_CDROM_GET_CONFIGURATION,
  1864. &input,
  1865. sizeof(GET_CONFIGURATION_IOCTL_INPUT),
  1866. pheader2,
  1867. cbHeader,
  1868. &cbReturned,
  1869. NULL);
  1870. if (f)
  1871. {
  1872. FEATURE_DATA_PROFILE_LIST* pproflist =
  1873. (FEATURE_DATA_PROFILE_LIST*)pheader2->Data;
  1874. for (DWORD dw = 0; dw < (DWORD)(pproflist->Header.AdditionalLength / 4); ++dw)
  1875. {
  1876. FEATURE_DATA_PROFILE_LIST_EX* pprofile = &(pproflist->Profiles[dw]);
  1877. if (ProfileDvdRam == (pprofile->ProfileNumber[0] << 8 |
  1878. pprofile->ProfileNumber[1] << 0))
  1879. {
  1880. // It does support it! Is it current?
  1881. fSupported = TRUE;
  1882. if (pprofile->Current)
  1883. {
  1884. fCurrent = TRUE;
  1885. }
  1886. break;
  1887. }
  1888. }
  1889. }
  1890. LocalFree(pheader2);
  1891. }
  1892. }
  1893. if (fSupported)
  1894. {
  1895. if (!fCurrent)
  1896. {
  1897. _dwMediaCap &= ~HWDMC_DVDRAM;
  1898. }
  1899. }
  1900. else
  1901. {
  1902. _dwDriveCap &= ~HWDDC_DVDRAM;
  1903. _dwMediaCap &= ~HWDMC_DVDRAM;
  1904. }
  1905. }
  1906. return S_OK;
  1907. }
  1908. // Not worth updating only Const Info vs Media Info, do both
  1909. HRESULT CVolume::_UpdateMMC2CDInfo(HANDLE hDevice)
  1910. {
  1911. HRESULT hr = _FillMMC2CD(hDevice);
  1912. if (SUCCEEDED(hr))
  1913. {
  1914. for (DWORD dwCap = 0; dwCap < ARRAYSIZE(_rgcapfeaturemap); ++dwCap)
  1915. {
  1916. DWORD dwGoOn = MMC2_NOTSUPPORTED;
  1917. if (_rgcapfeaturemap[dwCap].dwCapabilityDependent)
  1918. {
  1919. // This capability is dependent on another one, let's
  1920. // check if the other is on
  1921. if (_dwDriveCap &
  1922. _rgcapfeaturemap[dwCap].dwCapabilityDependent)
  1923. {
  1924. dwGoOn |= MMC2_DRIVESUPPORTED;
  1925. if (_dwMediaCap &
  1926. _rgcapfeaturemap[dwCap].dwCapabilityDependent)
  1927. {
  1928. dwGoOn |= MMC2_MEDIASUPPORTED;
  1929. }
  1930. }
  1931. }
  1932. else
  1933. {
  1934. dwGoOn = MMC2_DRIVESUPPORTED | MMC2_MEDIASUPPORTED;
  1935. }
  1936. for (DWORD dwFeature = 0;
  1937. dwFeature < (_rgcapfeaturemap[dwCap].cFeature);
  1938. ++dwFeature)
  1939. {
  1940. for (DWORD dwFeatureOn = 0; (MMC2_DRIVESUPPORTED & dwGoOn) &&
  1941. (dwFeatureOn < ARRAYSIZE(_rgfnInteresting));
  1942. ++dwFeatureOn)
  1943. {
  1944. if (_rgfnInteresting[dwFeatureOn] ==
  1945. _rgcapfeaturemap[dwCap].prgFeature[dwFeature])
  1946. {
  1947. if (_prgMMC2Features[dwFeatureOn] &
  1948. MMC2_DRIVESUPPORTED)
  1949. {
  1950. if (!(dwGoOn & MMC2_MEDIASUPPORTED) ||
  1951. !(_prgMMC2Features[dwFeatureOn] &
  1952. MMC2_MEDIASUPPORTED))
  1953. {
  1954. dwGoOn &= ~MMC2_MEDIASUPPORTED;
  1955. }
  1956. }
  1957. else
  1958. {
  1959. dwGoOn = MMC2_NOTSUPPORTED;
  1960. }
  1961. break;
  1962. }
  1963. }
  1964. if (MMC2_DRIVESUPPORTED & dwGoOn)
  1965. {
  1966. _dwDriveCap |= _rgcapfeaturemap[dwCap].dwCapability;
  1967. if (MMC2_MEDIASUPPORTED & dwGoOn)
  1968. {
  1969. _dwMediaCap |= _rgcapfeaturemap[dwCap].
  1970. dwCapability;
  1971. }
  1972. else
  1973. {
  1974. _dwMediaCap &= ~(_rgcapfeaturemap[dwCap].
  1975. dwCapability);
  1976. }
  1977. }
  1978. else
  1979. {
  1980. _dwDriveCap &= ~(_rgcapfeaturemap[dwCap].dwCapability);
  1981. _dwMediaCap &= ~(_rgcapfeaturemap[dwCap].dwCapability);
  1982. }
  1983. }
  1984. }
  1985. }
  1986. _DVDRAMHack(hDevice);
  1987. return hr;
  1988. }
  1989. HRESULT CVolume::_UpdateRemovableDevice()
  1990. {
  1991. HRESULT hr = S_OK;
  1992. if (_fHWDevInstInited)
  1993. {
  1994. BOOL fRemovable;
  1995. hr = _hwdevinst.IsRemovableDevice(&fRemovable);
  1996. if (SUCCEEDED(hr))
  1997. {
  1998. if (fRemovable)
  1999. {
  2000. _dwDriveCap |= HWDDC_REMOVABLEDEVICE;
  2001. }
  2002. }
  2003. }
  2004. return hr;
  2005. }
  2006. HRESULT CVolume::_UpdateSoftEjectCaps()
  2007. {
  2008. HRESULT hr = S_OK;
  2009. if (_fHWDevInstInited)
  2010. {
  2011. DWORD dw;
  2012. DWORD dwType;
  2013. hr = _GetDevicePropertyGeneric(&_hwdevinst, TEXT("NoSoftEject"),
  2014. FALSE, &dwType, (PBYTE)&dw, sizeof(dw));
  2015. if (SUCCEEDED(hr) && (S_FALSE != hr))
  2016. {
  2017. hr = S_OK;
  2018. if (REG_DWORD == dwType)
  2019. {
  2020. if (1 == dw)
  2021. {
  2022. _dwDriveCap |= HWDDC_NOSOFTEJECT;
  2023. }
  2024. }
  2025. }
  2026. }
  2027. return hr;
  2028. }
  2029. HRESULT CVolume::_UpdateConstInfo(HANDLE hDevice)
  2030. {
  2031. HRESULT hr;
  2032. _dwVolumeFlags = 0;
  2033. if (HWDTS_CDROM == _dwDriveType)
  2034. {
  2035. _dwVolumeFlags = HWDVF_STATE_SUPPORTNOTIFICATION;
  2036. hr = _UpdateMMC2CDInfo(hDevice);
  2037. }
  2038. else
  2039. {
  2040. if (HWDTS_REMOVABLEDISK == _dwDriveType)
  2041. {
  2042. _dwVolumeFlags = HWDVF_STATE_SUPPORTNOTIFICATION;
  2043. }
  2044. else
  2045. {
  2046. if ((HWDTS_FLOPPY35 != _dwDriveType) &&
  2047. (HWDTS_FLOPPY525 != _dwDriveType))
  2048. {
  2049. // Do something for the 120MB floppy
  2050. _dwVolumeFlags = HWDVF_STATE_SUPPORTNOTIFICATION;
  2051. }
  2052. }
  2053. hr = S_OK;
  2054. }
  2055. if (SUCCEEDED(hr))
  2056. {
  2057. hr = _GetVolumeName(_pszElemName, _szVolumeGUID,
  2058. ARRAYSIZE(_szVolumeGUID));
  2059. }
  2060. if (SUCCEEDED(hr))
  2061. {
  2062. if (HWDTS_CDROM != _dwDriveType)
  2063. {
  2064. _dwDriveCap |= HWDMC_WRITECAPABILITY_SUPPORTDETECTION |
  2065. HWDDC_RANDOMWRITE;
  2066. }
  2067. }
  2068. return hr;
  2069. }
  2070. HRESULT CVolume::GetVolumeConstInfo(LPWSTR pszVolumeGUID, DWORD cchVolumeGUID,
  2071. DWORD* pdwVolumeFlags, DWORD* pdwDriveType, DWORD* pdwDriveCap)
  2072. {
  2073. HRESULT hr;
  2074. _cs.Enter();
  2075. hr = SafeStrCpyN(pszVolumeGUID, _szVolumeGUID, cchVolumeGUID);
  2076. if (SUCCEEDED(hr))
  2077. {
  2078. if (!(_dwVolumeFlags & HWDVF_STATE_ACCESSDENIED))
  2079. {
  2080. *pdwVolumeFlags = _dwVolumeFlags;
  2081. *pdwDriveType = _dwDriveType;
  2082. *pdwDriveCap = _dwDriveCap;
  2083. }
  2084. else
  2085. {
  2086. *pdwVolumeFlags = HWDVF_STATE_ACCESSDENIED;
  2087. *pdwDriveType = 0xBADBADBD;
  2088. *pdwDriveCap = 0xBADBADBD;
  2089. }
  2090. }
  2091. _cs.Leave();
  2092. return hr;
  2093. }
  2094. HRESULT CVolume::GetVolumeMediaInfo(LPWSTR pszLabel, DWORD cchLabel,
  2095. LPWSTR pszFileSystem, DWORD cchFileSystem, DWORD* pdwFileSystemFlags,
  2096. DWORD* pdwMaxFileNameLen, DWORD* pdwRootAttributes, DWORD* pdwSerialNumber,
  2097. DWORD* pdwDriveState, DWORD* pdwMediaState, DWORD* pdwMediaCap)
  2098. {
  2099. HRESULT hr;
  2100. _cs.Enter();
  2101. if (!(_dwVolumeFlags & HWDVF_STATE_ACCESSDENIED))
  2102. {
  2103. if (_dwMediaState & HWDMS_PRESENT)
  2104. {
  2105. hr = SafeStrCpyN(pszLabel, _szLabel, cchLabel);
  2106. if (SUCCEEDED(hr))
  2107. {
  2108. hr = SafeStrCpyN(pszFileSystem, _szFileSystem, cchFileSystem);
  2109. }
  2110. if (SUCCEEDED(hr))
  2111. {
  2112. *pdwFileSystemFlags = _dwFileSystemFlags;
  2113. *pdwMaxFileNameLen = _dwMaxFileNameLen;
  2114. *pdwRootAttributes = _dwRootAttributes;
  2115. *pdwSerialNumber = _dwSerialNumber;
  2116. *pdwDriveState = _dwDriveState;
  2117. *pdwMediaState = _dwMediaState;
  2118. }
  2119. }
  2120. else
  2121. {
  2122. *pdwMediaState = _dwMediaState;
  2123. // We don't care if they fail
  2124. SafeStrCpyN(pszLabel, TEXT("Invalid"), cchLabel);
  2125. SafeStrCpyN(pszFileSystem, TEXT("Invalid"), cchFileSystem);
  2126. *pdwSerialNumber = 0xBADBADBD;
  2127. *pdwMaxFileNameLen = 0xBADBADBD;
  2128. *pdwFileSystemFlags = 0xBADBADBD;
  2129. *pdwRootAttributes = 0xBADBADBD;
  2130. *pdwDriveState = 0xBADBADBD;
  2131. hr = S_OK;
  2132. }
  2133. *pdwMediaCap = _dwMediaCap;
  2134. }
  2135. else
  2136. {
  2137. *pdwMediaState = 0xBADBADBD;
  2138. // We don't care if they fail
  2139. SafeStrCpyN(pszLabel, TEXT("Access Denied"), cchLabel);
  2140. SafeStrCpyN(pszFileSystem, TEXT("Access Denied"), cchFileSystem);
  2141. *pdwSerialNumber = 0xBADBADBD;
  2142. *pdwMaxFileNameLen = 0xBADBADBD;
  2143. *pdwFileSystemFlags = 0xBADBADBD;
  2144. *pdwRootAttributes = 0xBADBADBD;
  2145. *pdwDriveState = 0xBADBADBD;
  2146. *pdwMediaCap = 0xBADBADBD;
  2147. hr = S_OK;
  2148. }
  2149. _cs.Leave();
  2150. return hr;
  2151. }
  2152. HRESULT CVolume::GetIconAndLabelInfo(LPWSTR pszAutorunIconLocation,
  2153. DWORD cchAutorunIconLocation, LPWSTR pszAutorunLabel, DWORD cchAutorunLabel,
  2154. LPWSTR pszIconLocationFromService, DWORD cchIconLocationFromService,
  2155. LPWSTR pszNoMediaIconLocationFromService, DWORD cchNoMediaIconLocationFromService,
  2156. LPWSTR pszLabelFromService, DWORD cchLabelFromService)
  2157. {
  2158. HRESULT hrTmp;
  2159. *pszAutorunIconLocation = NULL;
  2160. *pszAutorunLabel = NULL;
  2161. *pszIconLocationFromService = NULL;
  2162. *pszNoMediaIconLocationFromService = NULL;
  2163. *pszLabelFromService = NULL;
  2164. _cs.Enter();
  2165. if (!(_dwVolumeFlags & HWDVF_STATE_ACCESSDENIED))
  2166. {
  2167. if (_dwMediaCap & HWDMC_HASAUTORUNINF)
  2168. {
  2169. if (_szAutorunIconLocation[0])
  2170. {
  2171. hrTmp = SafeStrCpyN(pszAutorunIconLocation, _szAutorunIconLocation,
  2172. cchAutorunIconLocation);
  2173. if (FAILED(hrTmp))
  2174. {
  2175. *pszAutorunIconLocation = 0;
  2176. }
  2177. }
  2178. if (_szAutorunLabel[0])
  2179. {
  2180. hrTmp = SafeStrCpyN(pszAutorunLabel, _szAutorunLabel,
  2181. cchAutorunLabel);
  2182. if (FAILED(hrTmp))
  2183. {
  2184. *pszAutorunLabel = 0;
  2185. }
  2186. }
  2187. }
  2188. if (_fHWDevInstInited)
  2189. {
  2190. WORD_BLOB* pblob;
  2191. hrTmp = _GetDevicePropertyGenericAsMultiSz(&_hwdevinst, TEXT("Icons"),
  2192. TRUE, &pblob);
  2193. if (SUCCEEDED(hrTmp) && (S_FALSE != hrTmp))
  2194. {
  2195. hrTmp = SafeStrCpyN(pszIconLocationFromService, pblob->asData,
  2196. cchIconLocationFromService);
  2197. if (FAILED(hrTmp))
  2198. {
  2199. *pszIconLocationFromService = 0;
  2200. }
  2201. CoTaskMemFree(pblob);
  2202. }
  2203. else
  2204. {
  2205. *pszIconLocationFromService = 0;
  2206. hrTmp = S_FALSE;
  2207. }
  2208. hrTmp = _GetDevicePropertyGenericAsMultiSz(&_hwdevinst, TEXT("NoMediaIcons"),
  2209. TRUE, &pblob);
  2210. if (SUCCEEDED(hrTmp) && (S_FALSE != hrTmp))
  2211. {
  2212. hrTmp = SafeStrCpyN(pszNoMediaIconLocationFromService, pblob->asData,
  2213. cchNoMediaIconLocationFromService);
  2214. if (FAILED(hrTmp))
  2215. {
  2216. *pszNoMediaIconLocationFromService = 0;
  2217. }
  2218. CoTaskMemFree(pblob);
  2219. }
  2220. else
  2221. {
  2222. *pszNoMediaIconLocationFromService = 0;
  2223. hrTmp = S_FALSE;
  2224. }
  2225. if (SUCCEEDED(hrTmp))
  2226. {
  2227. hrTmp = _GetDevicePropertyAsString(&_hwdevinst, TEXT("Label"),
  2228. pszLabelFromService, cchLabelFromService);
  2229. if (FAILED(hrTmp) || (S_FALSE == hrTmp))
  2230. {
  2231. *pszLabelFromService = 0;
  2232. }
  2233. }
  2234. }
  2235. }
  2236. _cs.Leave();
  2237. return S_OK;
  2238. }
  2239. HRESULT CVolume::_GetVOLUMEINFO2(VOLUMEINFO2** ppvolinfo2)
  2240. {
  2241. ASSERT(_cs.IsInside());
  2242. DWORD cchReq;
  2243. // We allocate this buffer just to be stack friendly, otherwise it could
  2244. // have been on the stack
  2245. VOLUMEINFO2* pvolinfo2;
  2246. const DWORD cbvolinfo2 = MAX_VOLUMEINFO2;
  2247. HRESULT hr = _AllocMemoryChunk<VOLUMEINFO2*>(cbvolinfo2, &pvolinfo2);
  2248. *ppvolinfo2 = NULL;
  2249. if (SUCCEEDED(hr))
  2250. {
  2251. pvolinfo2->cbSize = MAX_VOLUMEINFO2;
  2252. hr = GetName(pvolinfo2->szDeviceIDVolume,
  2253. ARRAYSIZE(pvolinfo2->szDeviceIDVolume), &cchReq);
  2254. if (SUCCEEDED(hr))
  2255. {
  2256. // Const info
  2257. hr = SafeStrCpyN(pvolinfo2->szVolumeGUID, _szVolumeGUID,
  2258. ARRAYSIZE(pvolinfo2->szVolumeGUID));
  2259. if (_dwVolumeFlags & HWDVF_STATE_ACCESSDENIED)
  2260. {
  2261. pvolinfo2->dwVolumeFlags = HWDVF_STATE_ACCESSDENIED;
  2262. }
  2263. else
  2264. {
  2265. if (SUCCEEDED(hr))
  2266. {
  2267. pvolinfo2->dwVolumeFlags = _dwVolumeFlags;
  2268. pvolinfo2->dwDriveType = _dwDriveType;
  2269. pvolinfo2->dwDriveCapability = _dwDriveCap;
  2270. }
  2271. pvolinfo2->dwState = _dwState;
  2272. // Media info
  2273. if (SUCCEEDED(hr))
  2274. {
  2275. // This fct should be called from within the Volume critsect
  2276. if (_dwMediaState & HWDMS_PRESENT)
  2277. {
  2278. hr = SafeStrCpyN(pvolinfo2->szLabel, _szLabel,
  2279. ARRAYSIZE(pvolinfo2->szLabel));
  2280. if (SUCCEEDED(hr))
  2281. {
  2282. hr = SafeStrCpyN(pvolinfo2->szFileSystem, _szFileSystem,
  2283. ARRAYSIZE(pvolinfo2->szFileSystem));
  2284. }
  2285. if (SUCCEEDED(hr))
  2286. {
  2287. pvolinfo2->dwFileSystemFlags = _dwFileSystemFlags;
  2288. pvolinfo2->dwMaxFileNameLen = _dwMaxFileNameLen;
  2289. pvolinfo2->dwRootAttributes = _dwRootAttributes;
  2290. pvolinfo2->dwSerialNumber = _dwSerialNumber;
  2291. pvolinfo2->dwDriveState = _dwDriveState;
  2292. pvolinfo2->dwMediaCap = _dwMediaCap;
  2293. pvolinfo2->dwMediaState = _dwMediaState;
  2294. }
  2295. }
  2296. else
  2297. {
  2298. pvolinfo2->dwMediaState = _dwMediaState;
  2299. // We don't care if they fail
  2300. SafeStrCpyN(pvolinfo2->szLabel, TEXT("Invalid"),
  2301. ARRAYSIZE(pvolinfo2->szLabel));
  2302. SafeStrCpyN(pvolinfo2->szFileSystem, TEXT("Invalid"),
  2303. ARRAYSIZE(pvolinfo2->szFileSystem));
  2304. pvolinfo2->dwSerialNumber = 0xBADBADBD;
  2305. pvolinfo2->dwMaxFileNameLen = 0xBADBADBD;
  2306. pvolinfo2->dwFileSystemFlags = 0xBADBADBD;
  2307. pvolinfo2->dwRootAttributes = 0xBADBADBD;
  2308. pvolinfo2->dwDriveState = 0xBADBADBD;
  2309. hr = S_OK;
  2310. }
  2311. pvolinfo2->dwMediaCap = _dwMediaCap;
  2312. }
  2313. if (SUCCEEDED(hr))
  2314. {
  2315. WCHAR szAutorunIconLocation[MAX_ICONLOCATION];
  2316. WCHAR szAutorunLabel[MAX_LABEL];
  2317. WCHAR szIconLocationFromService[MAX_ICONLOCATION];
  2318. WCHAR szNoMediaIconLocationFromService[MAX_ICONLOCATION];
  2319. // We can now have a @%SystemRoot%\system32\shell32.dll,-1785 for MUI stuff
  2320. WCHAR szLabelFromService[MAX_ICONLOCATION];
  2321. pvolinfo2->oAutorunIconLocation = INVALID_DWORD;
  2322. pvolinfo2->oAutorunLabel = INVALID_DWORD;
  2323. pvolinfo2->oIconLocationFromService = INVALID_DWORD;
  2324. pvolinfo2->oNoMediaIconLocationFromService = INVALID_DWORD;
  2325. pvolinfo2->oLabelFromService = INVALID_DWORD;
  2326. hr = GetIconAndLabelInfo(szAutorunIconLocation,
  2327. ARRAYSIZE(szAutorunIconLocation), szAutorunLabel,
  2328. ARRAYSIZE(szAutorunLabel), szIconLocationFromService,
  2329. ARRAYSIZE(szIconLocationFromService), szNoMediaIconLocationFromService,
  2330. ARRAYSIZE(szNoMediaIconLocationFromService), szLabelFromService,
  2331. ARRAYSIZE(szLabelFromService));
  2332. if (SUCCEEDED(hr))
  2333. {
  2334. LPWSTR pszNext = pvolinfo2->szOptionalStrings;
  2335. size_t cchLeft = (cbvolinfo2 - sizeof(*pvolinfo2) +
  2336. sizeof(pvolinfo2->szOptionalStrings)) / sizeof(WCHAR);
  2337. size_t cchLeftBeginWith = cchLeft;
  2338. // The following five strings are optional
  2339. if (szAutorunIconLocation[0])
  2340. {
  2341. pvolinfo2->oAutorunIconLocation = (DWORD)(cchLeftBeginWith - cchLeft);
  2342. hr = StringCchCopyEx(pszNext, cchLeft, szAutorunIconLocation, &pszNext, &cchLeft, 0);
  2343. ++pszNext;
  2344. --cchLeft;
  2345. }
  2346. if (SUCCEEDED(hr) && szAutorunLabel[0])
  2347. {
  2348. pvolinfo2->oAutorunLabel = (DWORD)(cchLeftBeginWith - cchLeft);
  2349. hr = StringCchCopyEx(pszNext, cchLeft, szAutorunLabel, &pszNext, &cchLeft, 0);
  2350. ++pszNext;
  2351. --cchLeft;
  2352. }
  2353. if (SUCCEEDED(hr) && szIconLocationFromService[0])
  2354. {
  2355. pvolinfo2->oIconLocationFromService = (DWORD)(cchLeftBeginWith - cchLeft);
  2356. hr = StringCchCopyEx(pszNext, cchLeft, szIconLocationFromService, &pszNext, &cchLeft, 0);
  2357. ++pszNext;
  2358. --cchLeft;
  2359. }
  2360. if (SUCCEEDED(hr) && szNoMediaIconLocationFromService[0])
  2361. {
  2362. pvolinfo2->oNoMediaIconLocationFromService = (DWORD)(cchLeftBeginWith - cchLeft);
  2363. hr = StringCchCopyEx(pszNext, cchLeft, szNoMediaIconLocationFromService, &pszNext, &cchLeft, 0);
  2364. ++pszNext;
  2365. --cchLeft;
  2366. }
  2367. if (SUCCEEDED(hr) && szLabelFromService[0])
  2368. {
  2369. pvolinfo2->oLabelFromService = (DWORD)(cchLeftBeginWith - cchLeft);
  2370. hr = StringCchCopy(pszNext, cchLeft, szLabelFromService);
  2371. }
  2372. }
  2373. }
  2374. }
  2375. }
  2376. if (SUCCEEDED(hr))
  2377. {
  2378. *ppvolinfo2 = pvolinfo2;
  2379. }
  2380. else
  2381. {
  2382. _FreeMemoryChunk<VOLUMEINFO2*>(pvolinfo2);
  2383. }
  2384. }
  2385. else
  2386. {
  2387. hr = E_OUTOFMEMORY;
  2388. }
  2389. return hr;
  2390. }
  2391. HRESULT CVolume::HandleRemoval()
  2392. {
  2393. WCHAR szDeviceIDVolume[MAX_DEVICEID];
  2394. DWORD cchReq;
  2395. HRESULT hr = GetName(szDeviceIDVolume, ARRAYSIZE(szDeviceIDVolume), &cchReq);
  2396. if (SUCCEEDED(hr))
  2397. {
  2398. // This will launch a thread
  2399. CHardwareDevicesImpl::_AdviseVolumeRemoved(szDeviceIDVolume,
  2400. _pszMountPoints, _cchMountPoints);
  2401. }
  2402. return hr;
  2403. }
  2404. HRESULT CVolume::HandleArrival()
  2405. {
  2406. BOOL fJustDocked = FALSE;
  2407. HRESULT hr = CHWEventDetectorHelper::DockStateChanged(&fJustDocked);
  2408. if (SUCCEEDED(hr))
  2409. {
  2410. //
  2411. // ISSUE-2001/01/13-StephStm Pass the Docking change in there so
  2412. // that the Shell knows if it should
  2413. // Autorun or not.
  2414. //
  2415. if (_fHWDevInstInited)
  2416. {
  2417. BOOL fTryAutoplay = TRUE;
  2418. if ((_dwDriveType & HWDTS_CDROM) ||
  2419. (_dwDriveType & HWDTS_REMOVABLEDISK))
  2420. {
  2421. if (_dwMediaState & HWDMS_PRESENT)
  2422. {
  2423. // Not removable disk, but device
  2424. BOOL fRemovable;
  2425. hr = _hwdevinst.IsRemovableDevice(&fRemovable);
  2426. if (SUCCEEDED(hr))
  2427. {
  2428. if (fRemovable)
  2429. {
  2430. // We need to Autoplay these since cameras
  2431. // are removable-disk devices. And we want
  2432. // to autorun them when they come in.
  2433. fTryAutoplay = TRUE;
  2434. }
  2435. else
  2436. {
  2437. // For removable-disk drives/CD drives with
  2438. // media inserted when they are plugged,
  2439. // we do not Autoplay.
  2440. fTryAutoplay = FALSE;
  2441. DIAGNOSTIC((TEXT("[0311]Non removable device plugged with media in it -> No Autoplay!")));
  2442. }
  2443. }
  2444. }
  2445. }
  2446. if (!fJustDocked && fTryAutoplay)
  2447. {
  2448. HANDLE hDevice;
  2449. // Get a handle to regsiter for notification so that the
  2450. // FindFirstFile does not veto a PnP/Driver transition
  2451. hr = _GetDeviceHandleSafe(&hDevice, FALSE);
  2452. if (SUCCEEDED(hr) && (S_FALSE != hr))
  2453. {
  2454. hr = _ShouldTryAutoplay(&fTryAutoplay);
  2455. if (SUCCEEDED(hr))
  2456. {
  2457. if (fTryAutoplay)
  2458. {
  2459. BOOL fHasHandler;
  2460. hr = CHWEventDetectorImpl::HandleVolumeMediaEvent(
  2461. _pszElemName, &_hwdevinst, TEXT("DeviceArrival"),
  2462. &fHasHandler);
  2463. if (SUCCEEDED(hr) && fHasHandler)
  2464. {
  2465. _dwVolumeFlags |= HWDVF_STATE_HASAUTOPLAYHANDLER;
  2466. }
  2467. }
  2468. else
  2469. {
  2470. _dwVolumeFlags |= HWDVF_STATE_DONOTSNIFFCONTENT;
  2471. }
  2472. }
  2473. _CloseDeviceHandleSafe(hDevice);
  2474. }
  2475. }
  2476. else
  2477. {
  2478. if (fJustDocked)
  2479. {
  2480. DIAGNOSTIC((TEXT("[0301]Just docked -> No Autoplay!")));
  2481. TRACE(TF_VOLUME, TEXT("Just docked -> No Autoplay!"));
  2482. _dwVolumeFlags |= HWDVF_STATE_JUSTDOCKED;
  2483. }
  2484. }
  2485. }
  2486. else
  2487. {
  2488. DIAGNOSTIC((TEXT("[0310]Cannot find hardware device for this volume -> No Autoplay!")));
  2489. hr = S_FALSE;
  2490. }
  2491. if (SUCCEEDED(hr))
  2492. {
  2493. _AdviseVolumeChangeHelper(TRUE);
  2494. }
  2495. }
  2496. return hr;
  2497. }
  2498. ///////////////////////////////////////////////////////////////////////////////
  2499. //
  2500. CVolume::CVolume() : _dwMediaState(0),
  2501. _devtype((DEVICE_TYPE)-1), _ulDeviceNumber((ULONG)-1),
  2502. _ulPartitionNumber((ULONG)-1), _fHWDevInstInited(FALSE), _dwDriveType(0),
  2503. _dwDriveCap(0), _dwVolumeFlags(0), _prgMMC2Features(NULL),
  2504. _fFirstTime(TRUE), _dwMediaCap(0), _pszMountPoints(NULL), _dwDriveState(0),
  2505. _hdevnotify(NULL), _dwState(0),
  2506. _dwMediaPresentFromEvent(MPFE_UNDETERMINED)
  2507. {
  2508. _szVolumeGUID[0] = 0;
  2509. _szDeviceIDDisk[0] = 0;
  2510. }
  2511. CVolume::~CVolume()
  2512. {
  2513. _UnregisterNotif();
  2514. if (_pszMountPoints)
  2515. {
  2516. CNamedElemList* pnel;
  2517. HRESULT hres = CHWEventDetectorHelper::GetList(HWEDLIST_MTPT, &pnel);
  2518. if (S_OK == hres)
  2519. {
  2520. for (LPWSTR psz = _pszMountPoints; *psz; psz += (lstrlen(psz) + 1))
  2521. {
  2522. hres = pnel->Remove(psz);
  2523. }
  2524. pnel->RCRelease();
  2525. }
  2526. LocalFree(_pszMountPoints);
  2527. }
  2528. if (_prgMMC2Features)
  2529. {
  2530. LocalFree(_prgMMC2Features);
  2531. }
  2532. _cs.Delete();
  2533. }
  2534. ///////////////////////////////////////////////////////////////////////////////
  2535. //
  2536. //static
  2537. HRESULT CVolume::Create(CNamedElem** ppelem)
  2538. {
  2539. HRESULT hres = S_OK;
  2540. *ppelem = new CVolume();
  2541. if (!(*ppelem))
  2542. {
  2543. hres = E_OUTOFMEMORY;
  2544. }
  2545. return hres;
  2546. }
  2547. //static
  2548. HRESULT CVolume::GetFillEnum(CFillEnum** ppfillenum)
  2549. {
  2550. HRESULT hres;
  2551. CVolumeFillEnum* pfillenum = new CVolumeFillEnum();
  2552. if (pfillenum)
  2553. {
  2554. hres = pfillenum->_Init();
  2555. if (FAILED(hres))
  2556. {
  2557. delete pfillenum;
  2558. pfillenum = NULL;
  2559. }
  2560. }
  2561. else
  2562. {
  2563. hres = E_OUTOFMEMORY;
  2564. }
  2565. *ppfillenum = pfillenum;
  2566. return hres;
  2567. }
  2568. ///////////////////////////////////////////////////////////////////////////////
  2569. //
  2570. HRESULT CVolumeFillEnum::Next(LPWSTR pszElemName, DWORD cchElemName,
  2571. DWORD* pcchRequired)
  2572. {
  2573. return _intffillenum.Next(pszElemName, cchElemName, pcchRequired);
  2574. }
  2575. HRESULT CVolumeFillEnum::_Init()
  2576. {
  2577. return _intffillenum._Init(&guidVolumeClass, NULL);
  2578. }