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.

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