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.

1910 lines
59 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include <hwtab.h>
  4. #include "fstreex.h"
  5. #include "views.h"
  6. #include "drives.h"
  7. #include "propsht.h"
  8. #include "infotip.h"
  9. #include "datautil.h"
  10. #include "netview.h"
  11. #include "bitbuck.h"
  12. #include "drawpie.h"
  13. #include "shitemid.h"
  14. #include "devguid.h"
  15. #include "ids.h"
  16. #include "idldrop.h"
  17. #include "util.h"
  18. #include "shcombox.h"
  19. #include "hwcmmn.h"
  20. #include "prop.h"
  21. #include "mtpt.h"
  22. #include "ftascstr.h" // for CFTAssocStore
  23. #include "ascstr.h" // for IAssocInfo class
  24. #include "apdlg.h"
  25. #include "cdburn.h"
  26. #define REL_KEY_DEFRAG TEXT("MyComputer\\defragpath")
  27. #define REL_KEY_BACKUP TEXT("MyComputer\\backuppath")
  28. ///////////////////////////////////////////////////////////////////////////////
  29. // Begin: Old C fct required externally
  30. ///////////////////////////////////////////////////////////////////////////////
  31. STDAPI_(int) RealDriveTypeFlags(int iDrive, BOOL fOKToHitNet)
  32. {
  33. int iType = DRIVE_NO_ROOT_DIR;
  34. CMountPoint* pMtPt = CMountPoint::GetMountPoint(iDrive, TRUE, fOKToHitNet);
  35. if (pMtPt)
  36. {
  37. WCHAR szDrive[4];
  38. iType = GetDriveType(PathBuildRoot(szDrive, iDrive));
  39. iType |= pMtPt->GetDriveFlags();
  40. iType |= pMtPt->GetVolumeFlags();
  41. pMtPt->Release();
  42. }
  43. return iType;
  44. }
  45. STDAPI_(int) RealDriveType(int iDrive, BOOL fOKToHitNet)
  46. {
  47. WCHAR szDrive[4];
  48. return GetDriveType(PathBuildRoot(szDrive, iDrive)) & DRIVE_TYPE;
  49. }
  50. STDAPI_(int) DriveType(int iDrive)
  51. {
  52. return RealDriveType(iDrive, TRUE);
  53. }
  54. STDAPI_(DWORD) PathGetClusterSize(LPCTSTR pszPath)
  55. {
  56. static TCHAR s_szRoot[MAX_PATH] = {'\0'};
  57. static int s_nszRootLen = 0;
  58. static DWORD s_dwSize = 0;
  59. DWORD dwSize = 0;
  60. // Do we have a cache hit? No need to hit the net if we can avoid it...
  61. if (s_nszRootLen)
  62. {
  63. ENTERCRITICAL;
  64. if (wcsncmp(pszPath, s_szRoot, s_nszRootLen) == 0)
  65. {
  66. dwSize = s_dwSize;
  67. }
  68. LEAVECRITICAL;
  69. }
  70. if (0 == dwSize)
  71. {
  72. TCHAR szRoot[MAX_PATH];
  73. lstrcpy(szRoot, pszPath);
  74. PathStripToRoot(szRoot);
  75. if (PathIsUNC(szRoot))
  76. {
  77. DWORD dwSecPerClus, dwBytesPerSec, dwClusters, dwTemp;
  78. PathAddBackslash(szRoot);
  79. if (GetDiskFreeSpace(szRoot, &dwSecPerClus, &dwBytesPerSec, &dwTemp, &dwClusters))
  80. {
  81. dwSize = dwSecPerClus * dwBytesPerSec;
  82. }
  83. }
  84. else
  85. {
  86. CMountPoint* pMtPt = CMountPoint::GetMountPoint(pszPath);
  87. if (pMtPt)
  88. {
  89. dwSize = pMtPt->GetClusterSize();
  90. pMtPt->Release();
  91. }
  92. }
  93. // Sometimes on Millennium, we get 0 as the cluster size.
  94. // Reason unknown. Sanitize the value so we don't go insane.
  95. if (dwSize == 0)
  96. dwSize = 512;
  97. // Remember this for later - chances are we'll be queried for the same drive again
  98. ENTERCRITICAL;
  99. StrCpyN(s_szRoot, szRoot, ARRAYSIZE(s_szRoot));
  100. s_nszRootLen = lstrlen(s_szRoot);
  101. s_dwSize = dwSize;
  102. LEAVECRITICAL;
  103. }
  104. return dwSize;
  105. }
  106. STDAPI_(UINT) GetMountedVolumeIcon(LPCTSTR pszMountPoint, LPTSTR pszModule, DWORD cchModule)
  107. {
  108. UINT iIcon = II_FOLDER;
  109. // zero-init string
  110. if (pszModule)
  111. *pszModule = 0;
  112. CMountPoint* pMtPt = CMountPoint::GetMountPoint(pszMountPoint);
  113. if (pMtPt)
  114. {
  115. iIcon = pMtPt->GetIcon(pszModule, cchModule);
  116. pMtPt->Release();
  117. }
  118. return iIcon;
  119. }
  120. STDAPI_(BOOL) IsDisconnectedNetDrive(int iDrive)
  121. {
  122. BOOL fDisc = 0;
  123. CMountPoint* pMtPt = CMountPoint::GetMountPoint(iDrive);
  124. if (pMtPt)
  125. {
  126. fDisc = pMtPt->IsDisconnectedNetDrive();
  127. pMtPt->Release();
  128. }
  129. return fDisc;
  130. }
  131. STDAPI_(BOOL) IsUnavailableNetDrive(int iDrive)
  132. {
  133. BOOL fUnAvail = 0;
  134. CMountPoint* pMtPt = CMountPoint::GetMountPoint(iDrive);
  135. if (pMtPt)
  136. {
  137. fUnAvail = pMtPt->IsUnavailableNetDrive();
  138. pMtPt->Release();
  139. }
  140. return fUnAvail;
  141. }
  142. STDMETHODIMP SetDriveLabel(HWND hwnd, IUnknown* punkEnableModless, int iDrive, LPCTSTR pszDriveLabel)
  143. {
  144. HRESULT hr = E_FAIL;
  145. CMountPoint* pMtPt = CMountPoint::GetMountPoint(iDrive);
  146. if (pMtPt)
  147. {
  148. hr = pMtPt->SetDriveLabel(hwnd, pszDriveLabel);
  149. pMtPt->Release();
  150. }
  151. return hr;
  152. }
  153. STDMETHODIMP GetDriveComment(int iDrive, LPTSTR pszComment, int cchComment)
  154. {
  155. HRESULT hr = E_FAIL;
  156. CMountPoint* pMtPt = CMountPoint::GetMountPoint(iDrive);
  157. if (pMtPt)
  158. {
  159. hr = pMtPt->GetComment(pszComment, cchComment);
  160. pMtPt->Release();
  161. }
  162. return hr;
  163. }
  164. ///////////////////////////////////////////////////////////////////////////////
  165. // End: Old C fct required externally
  166. ///////////////////////////////////////////////////////////////////////////////
  167. //
  168. // fDoIt -- TRUE, if we make connections; FALSE, if just querying.
  169. //
  170. BOOL _MakeConnection(IDataObject *pDataObj, BOOL fDoIt)
  171. {
  172. STGMEDIUM medium;
  173. FORMATETC fmte = {g_cfNetResource, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  174. BOOL fAnyConnectable = FALSE;
  175. if (SUCCEEDED(pDataObj->GetData(&fmte, &medium)))
  176. {
  177. LPNETRESOURCE pnr = (LPNETRESOURCE)LocalAlloc(LPTR, 1024);
  178. if (pnr)
  179. {
  180. UINT iItem, cItems = SHGetNetResource(medium.hGlobal, (UINT)-1, NULL, 0);
  181. for (iItem = 0; iItem < cItems; iItem++)
  182. {
  183. if (SHGetNetResource(medium.hGlobal, iItem, pnr, 1024) &&
  184. pnr->dwUsage & RESOURCEUSAGE_CONNECTABLE &&
  185. !(pnr->dwType & RESOURCETYPE_PRINT))
  186. {
  187. fAnyConnectable = TRUE;
  188. if (fDoIt)
  189. {
  190. SHNetConnectionDialog(NULL, pnr->lpRemoteName, pnr->dwType);
  191. SHChangeNotifyHandleEvents();
  192. }
  193. else
  194. {
  195. break; // We are just querying.
  196. }
  197. }
  198. }
  199. LocalFree(pnr);
  200. }
  201. ReleaseStgMedium(&medium);
  202. }
  203. return fAnyConnectable;
  204. }
  205. //
  206. // the entry of "make connection thread"
  207. //
  208. DWORD WINAPI MakeConnectionThreadProc(void *pv)
  209. {
  210. IDataObject *pdtobj;
  211. if (SUCCEEDED(CoGetInterfaceAndReleaseStream((IStream *)pv, IID_PPV_ARG(IDataObject, &pdtobj))))
  212. {
  213. _MakeConnection(pdtobj, TRUE);
  214. pdtobj->Release();
  215. }
  216. return 0;
  217. }
  218. STDAPI CDrivesDropTarget_Create(HWND hwnd, LPCITEMIDLIST pidl, IDropTarget **ppdropt);
  219. class CDrivesDropTarget : public CIDLDropTarget
  220. {
  221. friend HRESULT CDrivesDropTarget_Create(HWND hwnd, LPCITEMIDLIST pidl, IDropTarget **ppdropt);
  222. public:
  223. CDrivesDropTarget(HWND hwnd) : CIDLDropTarget(hwnd) { };
  224. // IDropTarget methods overwirte
  225. STDMETHODIMP DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  226. STDMETHODIMP Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  227. };
  228. STDAPI CDrivesDropTarget_Create(HWND hwnd, LPCITEMIDLIST pidl, IDropTarget **ppdropt)
  229. {
  230. *ppdropt = NULL;
  231. HRESULT hr;
  232. CDrivesDropTarget *pCIDLDT = new CDrivesDropTarget(hwnd);
  233. if (pCIDLDT)
  234. {
  235. hr = pCIDLDT->_Init(pidl);
  236. if (SUCCEEDED(hr))
  237. pCIDLDT->QueryInterface(IID_PPV_ARG(IDropTarget, ppdropt));
  238. pCIDLDT->Release();
  239. }
  240. else
  241. hr = E_OUTOFMEMORY;
  242. return hr;
  243. }
  244. //
  245. // puts DROPEFFECT_LINK in *pdwEffect, only if the data object
  246. // contains one or more net resource.
  247. //
  248. STDMETHODIMP CDrivesDropTarget::DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  249. {
  250. // Call the base class first.
  251. CIDLDropTarget::DragEnter(pDataObj, grfKeyState, pt, pdwEffect);
  252. *pdwEffect &= _MakeConnection(pDataObj, FALSE) ? DROPEFFECT_LINK : DROPEFFECT_NONE;
  253. m_dwEffectLastReturned = *pdwEffect;
  254. return S_OK; // Notes: we should NOT return hr as it.
  255. }
  256. //
  257. // creates a connection to a dropped net resource object.
  258. //
  259. STDMETHODIMP CDrivesDropTarget::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  260. {
  261. HRESULT hr;
  262. if (m_dwData & DTID_NETRES)
  263. {
  264. *pdwEffect = DROPEFFECT_LINK;
  265. hr = CIDLDropTarget::DragDropMenu(DROPEFFECT_LINK, pDataObj,
  266. pt, pdwEffect, NULL, NULL, POPUP_DRIVES_NONDEFAULTDD, grfKeyState);
  267. if (hr == S_FALSE)
  268. {
  269. // we create another thread to avoid blocking the source thread.
  270. IStream *pstm;
  271. if (S_OK == CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObj, &pstm))
  272. {
  273. if (SHCreateThread(MakeConnectionThreadProc, pstm, CTF_COINIT, NULL))
  274. {
  275. hr = S_OK;
  276. }
  277. else
  278. {
  279. pstm->Release();
  280. hr = E_OUTOFMEMORY;
  281. }
  282. }
  283. }
  284. }
  285. else
  286. {
  287. //
  288. // Because QueryGetData() failed, we don't call CIDLDropTarget_
  289. // DragDropMenu(). Therefore, we must call this explicitly.
  290. //
  291. DAD_DragLeave();
  292. hr = E_FAIL;
  293. }
  294. CIDLDropTarget::DragLeave();
  295. return hr;
  296. }
  297. STDAPI_(DWORD) DrivesPropertiesThreadProc(void *pv)
  298. {
  299. PROPSTUFF *pps = (PROPSTUFF *)pv;
  300. STGMEDIUM medium;
  301. ULONG_PTR dwCookie = 0;
  302. BOOL bDidActivate = FALSE;
  303. //
  304. // This __try/__finally block is to ensure that the activation context gets
  305. // removed, even if there's an assertion elsewhere in this code. A missing
  306. // DeactivateActCtx will lead to a very strange-looking assertion in one of
  307. // the RtlpDeactivateActCtx-variant functions from the caller. Old code
  308. // was missing the deactivate in all circumstances.
  309. //
  310. // (jonwis) 1/2/2001
  311. //
  312. __try
  313. {
  314. bDidActivate = ActivateActCtx(NULL, &dwCookie);
  315. LPIDA pida = DataObj_GetHIDA(pps->pdtobj, &medium);
  316. BOOL bMountedDriveInfo = FALSE;
  317. // Were we able to get data for a HIDA?
  318. if (!pida)
  319. {
  320. // No, pida is first choice, but if not present check for mounteddrive info
  321. FORMATETC fmte;
  322. fmte.cfFormat = g_cfMountedVolume;
  323. fmte.ptd = NULL;
  324. fmte.dwAspect = DVASPECT_CONTENT;
  325. fmte.lindex = -1;
  326. fmte.tymed = TYMED_HGLOBAL;
  327. // Is data available for the MountedVolume format?
  328. if (SUCCEEDED(pps->pdtobj->GetData(&fmte, &medium)))
  329. // Yes
  330. bMountedDriveInfo = TRUE;
  331. }
  332. // Do we have data for a HIDA or a mountedvolume?
  333. if (pida || bMountedDriveInfo)
  334. {
  335. // Yes
  336. TCHAR szCaption[MAX_PATH];
  337. LPTSTR pszCaption = NULL;
  338. if (pida)
  339. {
  340. pszCaption = SHGetCaption(medium.hGlobal);
  341. }
  342. else
  343. {
  344. TCHAR szMountPoint[MAX_PATH];
  345. TCHAR szVolumeGUID[MAX_PATH];
  346. DragQueryFile((HDROP)medium.hGlobal, 0, szMountPoint, ARRAYSIZE(szMountPoint));
  347. GetVolumeNameForVolumeMountPoint(szMountPoint, szVolumeGUID, ARRAYSIZE(szVolumeGUID));
  348. szCaption[0] = 0;
  349. GetVolumeInformation(szVolumeGUID, szCaption, ARRAYSIZE(szCaption), NULL, NULL, NULL, NULL, 0);
  350. if (!(*szCaption))
  351. LoadString(HINST_THISDLL, IDS_UNLABELEDVOLUME, szCaption, ARRAYSIZE(szCaption));
  352. PathRemoveBackslash(szMountPoint);
  353. // Fix 330388
  354. // If the szMountPoint is not a valid local path, do not
  355. // display it in the properties dialog title:
  356. if (-1 != PathGetDriveNumber(szMountPoint))
  357. {
  358. int nCaptionLength = lstrlen(szCaption) ;
  359. wnsprintf(szCaption + nCaptionLength, ARRAYSIZE(szCaption) - nCaptionLength, TEXT(" (%s)"), szMountPoint);
  360. }
  361. pszCaption = szCaption;
  362. }
  363. // NOTE - if we pass the name of the drive then we can get a lot more keys...
  364. HKEY rgk[MAX_ASSOC_KEYS];
  365. DWORD ck = CDrives_GetKeys(NULL, rgk, ARRAYSIZE(rgk));
  366. SHOpenPropSheet(pszCaption, rgk, ck,
  367. &CLSID_ShellDrvDefExt, pps->pdtobj, NULL, pps->pStartPage);
  368. SHRegCloseKeys(rgk, ck);
  369. if (pida && pszCaption)
  370. SHFree(pszCaption);
  371. if (pida)
  372. HIDA_ReleaseStgMedium(pida, &medium);
  373. else
  374. ReleaseStgMedium(&medium);
  375. }
  376. else
  377. {
  378. TraceMsg(DM_TRACE, "no HIDA in data obj nor Mounted drive info");
  379. }
  380. }
  381. __finally
  382. {
  383. if ( bDidActivate )
  384. {
  385. DeactivateActCtx( 0, dwCookie );
  386. }
  387. }
  388. return 0;
  389. }
  390. //
  391. // To be called back from within CDefFolderMenu
  392. //
  393. STDAPI CDrives_DFMCallBack(IShellFolder *psf, HWND hwnd,
  394. IDataObject *pdtobj, UINT uMsg,
  395. WPARAM wParam, LPARAM lParam)
  396. {
  397. HRESULT hr = S_OK;
  398. switch (uMsg)
  399. {
  400. case DFM_MERGECONTEXTMENU:
  401. if (pdtobj)
  402. {
  403. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  404. // Check if only file system objects are selected.
  405. if (pdtobj->QueryGetData(&fmte) == S_OK)
  406. {
  407. #define pqcm ((LPQCMINFO)lParam)
  408. STGMEDIUM medium;
  409. // Yes, only file system objects are selected.
  410. LPIDA pida = DataObj_GetHIDA(pdtobj, &medium);
  411. if (pida)
  412. {
  413. LPIDDRIVE pidd = (LPIDDRIVE)IDA_GetIDListPtr(pida, 0);
  414. if (pidd)
  415. {
  416. int iDrive = DRIVEID(pidd->cName);
  417. UINT idCmdBase = pqcm->idCmdFirst; // store it away
  418. BOOL fIsEjectable = FALSE;
  419. CDefFolderMenu_MergeMenu(HINST_THISDLL, POPUP_DRIVES_ITEM, 0, pqcm);
  420. CMountPoint* pmtpt = CMountPoint::GetMountPoint(DRIVEID(pidd->cName));
  421. if (pmtpt)
  422. {
  423. if (!pmtpt->IsRemote() ||
  424. SHRestricted( REST_NONETCONNECTDISCONNECT ))
  425. {
  426. DeleteMenu(pqcm->hmenu, idCmdBase + FSIDM_DISCONNECT, MF_BYCOMMAND);
  427. }
  428. if ((pida->cidl != 1) ||
  429. (!pmtpt->IsFormattable()))
  430. {
  431. // Don't even try to format more than one disk
  432. // Or a net drive, or a CD-ROM, or a RAM drive ...
  433. // Note we are going to show the Format command on the
  434. // boot drive, Windows drive, System drive, compressed
  435. // drives, etc. An appropriate error should be shown
  436. // after the user chooses this command
  437. DeleteMenu(pqcm->hmenu, idCmdBase + FSIDM_FORMAT, MF_BYCOMMAND);
  438. }
  439. if (pmtpt->IsEjectable())
  440. fIsEjectable = TRUE;
  441. pmtpt->Release();
  442. }
  443. if ((pida->cidl != 1) || (iDrive < 0) || !fIsEjectable)
  444. DeleteMenu(pqcm->hmenu, idCmdBase + FSIDM_EJECT, MF_BYCOMMAND);
  445. }
  446. HIDA_ReleaseStgMedium(pida, &medium);
  447. }
  448. #undef pqcm
  449. }
  450. }
  451. // Note that we always return S_OK from this function so that
  452. // default processing of menu items will occur
  453. ASSERT(hr == S_OK);
  454. break;
  455. case DFM_GETHELPTEXT:
  456. LoadStringA(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPSTR)lParam, HIWORD(wParam));;
  457. break;
  458. case DFM_GETHELPTEXTW:
  459. LoadStringW(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPWSTR)lParam, HIWORD(wParam));;
  460. break;
  461. case DFM_MAPCOMMANDNAME:
  462. if (lstrcmpi((LPCTSTR)lParam, TEXT("eject")) == 0)
  463. *(int *)wParam = FSIDM_EJECT;
  464. else if (lstrcmpi((LPCTSTR)lParam, TEXT("format")) == 0)
  465. *(int *)wParam = FSIDM_FORMAT;
  466. else
  467. hr = E_FAIL; // command not found
  468. break;
  469. case DFM_INVOKECOMMAND:
  470. switch (wParam)
  471. {
  472. case DFM_CMD_PROPERTIES:
  473. // lParam contains the page name to open
  474. hr = SHLaunchPropSheet(DrivesPropertiesThreadProc, pdtobj, (LPCTSTR)lParam, NULL, NULL);
  475. break;
  476. case FSIDM_EJECT:
  477. case FSIDM_FORMAT:
  478. {
  479. STGMEDIUM medium;
  480. LPIDA pida = DataObj_GetHIDA(pdtobj, &medium);
  481. ASSERT(HIDA_GetCount(medium.hGlobal) == 1);
  482. LPIDDRIVE pidd = (LPIDDRIVE)IDA_GetIDListPtr(pida, 0);
  483. if (pidd)
  484. {
  485. UINT iDrive = DRIVEID(pidd->cName);
  486. ASSERT((int)iDrive >= 0);
  487. switch (wParam)
  488. {
  489. case FSIDM_FORMAT:
  490. SHFormatDriveAsync(hwnd, iDrive, SHFMT_ID_DEFAULT, 0);
  491. break;
  492. case FSIDM_EJECT:
  493. {
  494. CDBurn_OnEject(hwnd, iDrive);
  495. CMountPoint* pMtPt = CMountPoint::GetMountPoint(iDrive);
  496. if (pMtPt)
  497. {
  498. pMtPt->Eject(hwnd);
  499. pMtPt->Release();
  500. }
  501. break;
  502. }
  503. }
  504. }
  505. HIDA_ReleaseStgMedium(pida, &medium);
  506. break;
  507. }
  508. case FSIDM_DISCONNECT:
  509. if (pdtobj)
  510. {
  511. STGMEDIUM medium;
  512. LPIDA pida = DataObj_GetHIDA(pdtobj, &medium);
  513. if (pida)
  514. {
  515. DISCDLGSTRUCT discd = {
  516. sizeof(discd), // cbStructure
  517. hwnd, // hwndOwner
  518. NULL, // lpLocalName
  519. NULL, // lpRemoteName
  520. DISC_UPDATE_PROFILE // dwFlags
  521. };
  522. for (UINT iidl = 0; iidl < pida->cidl; iidl++)
  523. {
  524. LPIDDRIVE pidd = (LPIDDRIVE)IDA_GetIDListPtr(pida, iidl);
  525. CMountPoint* pmtpt = CMountPoint::GetMountPoint(DRIVEID(pidd->cName));
  526. if (pmtpt)
  527. {
  528. if (pmtpt->IsRemote())
  529. {
  530. TCHAR szPath[4], szDrive[4];
  531. BOOL fUnavailable = pmtpt->IsUnavailableNetDrive();
  532. SHAnsiToTChar(pidd->cName, szPath, ARRAYSIZE(szPath));
  533. SHAnsiToTChar(pidd->cName, szDrive, ARRAYSIZE(szDrive));
  534. szDrive[2] = 0; // remove slash
  535. discd.lpLocalName = szDrive;
  536. if (SHWNetDisconnectDialog1(&discd) == WN_SUCCESS)
  537. {
  538. // If it is a unavailable drive we get no
  539. // file system notification and as such
  540. // the drive will not disappear, so lets
  541. // set up to do it ourself...
  542. if (fUnavailable)
  543. {
  544. CMountPoint::NotifyUnavailableNetDriveGone(szPath);
  545. // Do we need this if we have the above?
  546. SHChangeNotify(SHCNE_DRIVEREMOVED, SHCNF_PATH, szPath, NULL);
  547. }
  548. }
  549. }
  550. pmtpt->Release();
  551. }
  552. }
  553. // flush them altogether
  554. SHChangeNotifyHandleEvents();
  555. HIDA_ReleaseStgMedium(pida, &medium);
  556. }
  557. }
  558. break;
  559. case FSIDM_CONNECT_PRN:
  560. SHNetConnectionDialog(hwnd, NULL, RESOURCETYPE_PRINT);
  561. break;
  562. case FSIDM_DISCONNECT_PRN:
  563. WNetDisconnectDialog(hwnd, RESOURCETYPE_PRINT);
  564. break;
  565. default:
  566. // This is one of view menu items, use the default code.
  567. hr = S_FALSE;
  568. break;
  569. }
  570. break;
  571. default:
  572. hr = E_NOTIMPL;
  573. break;
  574. }
  575. return hr;
  576. }
  577. #define REGSTR_LASTUNCHASH TEXT("LastUNCHash")
  578. STDMETHODIMP GetUNCPathHash(HKEY hkDrives, LPCTSTR pszUNCPath, LPTSTR pszUNCPathHash, int cchUNCPathHash)
  579. {
  580. HRESULT hr = E_FAIL;
  581. DWORD dwLastUNCHash = 0;
  582. SHQueryValueEx(hkDrives, REGSTR_LASTUNCHASH, NULL, NULL, (BYTE *)&dwLastUNCHash, NULL);
  583. dwLastUNCHash++;
  584. if (RegSetValueEx(hkDrives, REGSTR_LASTUNCHASH, 0, REG_DWORD, (LPCBYTE)&dwLastUNCHash, sizeof(dwLastUNCHash)) == ERROR_SUCCESS)
  585. {
  586. hr = S_OK;
  587. }
  588. wnsprintf(pszUNCPathHash, cchUNCPathHash, TEXT("%lu"), (ULONG)dwLastUNCHash);
  589. return hr;
  590. }
  591. void _DrvPrshtSetSpaceValues(DRIVEPROPSHEETPAGE *pdpsp)
  592. {
  593. LPITEMIDLIST pidl;
  594. TCHAR szFormat[30];
  595. TCHAR szTemp[30];
  596. TCHAR szBuffer[64]; // needs to be big enough to hold "99,999,999,999,999 bytes" + room for localization
  597. // reset the total/free values to start with
  598. pdpsp->qwTot = pdpsp->qwFree = 0;
  599. // lets try to ask the shellfolder for this information!
  600. HRESULT hr = SHILCreateFromPath(pdpsp->szDrive, &pidl, NULL);
  601. if (SUCCEEDED(hr))
  602. {
  603. IShellFolder2 *psf2;
  604. LPCITEMIDLIST pidlLast;
  605. hr = SHBindToIDListParent(pidl, IID_PPV_ARG(IShellFolder2, &psf2), &pidlLast);
  606. if (SUCCEEDED(hr))
  607. {
  608. ULONGLONG ullFree;
  609. hr = GetLongProperty(psf2, pidlLast, &SCID_FREESPACE, &ullFree);
  610. if (SUCCEEDED(hr))
  611. {
  612. ULONGLONG ullTotal;
  613. hr = GetLongProperty(psf2, pidlLast, &SCID_CAPACITY, &ullTotal);
  614. if (SUCCEEDED(hr))
  615. {
  616. pdpsp->qwTot = ullTotal;
  617. pdpsp->qwFree = ullFree;
  618. }
  619. }
  620. psf2->Release();
  621. }
  622. ILFree(pidl);
  623. }
  624. // we want to use the IShellFolder stuff above so cdrom burning will be happy. However, the
  625. // above code fails for removable drives that have no media, so we need a fallback
  626. if (FAILED(hr))
  627. {
  628. ULARGE_INTEGER qwFreeUser;
  629. ULARGE_INTEGER qwTotal;
  630. ULARGE_INTEGER qwTotalFree;
  631. if (SHGetDiskFreeSpaceEx(pdpsp->szDrive, &qwFreeUser, &qwTotal, &qwTotalFree))
  632. {
  633. // Save away to use when drawing the pie
  634. pdpsp->qwTot = qwTotal.QuadPart;
  635. pdpsp->qwFree = qwFreeUser.QuadPart;
  636. }
  637. }
  638. LoadString(HINST_THISDLL, IDS_BYTES, szFormat, ARRAYSIZE(szFormat));
  639. // NT must be able to display 64-bit numbers; at least as much
  640. // as is realistic. We've made the decision
  641. // that volumes up to 100 Terrabytes will display the byte value
  642. // and the short-format value. Volumes of greater size will display
  643. // "---" in the byte field and the short-format value. Note that the
  644. // short format is always displayed.
  645. const _int64 MaxDisplayNumber = 99999999999999; // 100TB - 1.
  646. if ((pdpsp->qwTot - pdpsp->qwFree) <= MaxDisplayNumber)
  647. {
  648. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szFormat, AddCommas64(pdpsp->qwTot - pdpsp->qwFree, szTemp, ARRAYSIZE(szTemp)));
  649. SetDlgItemText(pdpsp->hDlg, IDC_DRV_USEDBYTES, szBuffer);
  650. }
  651. if (pdpsp->qwFree <= MaxDisplayNumber)
  652. {
  653. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szFormat, AddCommas64(pdpsp->qwFree, szTemp, ARRAYSIZE(szTemp)));
  654. SetDlgItemText(pdpsp->hDlg, IDC_DRV_FREEBYTES, szBuffer);
  655. }
  656. if (pdpsp->qwTot <= MaxDisplayNumber)
  657. {
  658. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szFormat, AddCommas64(pdpsp->qwTot, szTemp, ARRAYSIZE(szTemp)));
  659. SetDlgItemText(pdpsp->hDlg, IDC_DRV_TOTBYTES, szBuffer);
  660. }
  661. ShortSizeFormat64(pdpsp->qwTot-pdpsp->qwFree, szBuffer, ARRAYSIZE(szBuffer));
  662. SetDlgItemText(pdpsp->hDlg, IDC_DRV_USEDMB, szBuffer);
  663. ShortSizeFormat64(pdpsp->qwFree, szBuffer, ARRAYSIZE(szBuffer));
  664. SetDlgItemText(pdpsp->hDlg, IDC_DRV_FREEMB, szBuffer);
  665. ShortSizeFormat64(pdpsp->qwTot, szBuffer, ARRAYSIZE(szBuffer));
  666. SetDlgItemText(pdpsp->hDlg, IDC_DRV_TOTMB, szBuffer);
  667. }
  668. void _DrvPrshtGetPieShadowHeight(DRIVEPROPSHEETPAGE* pdpsp)
  669. {
  670. SIZE size;
  671. HDC hDC = GetDC(pdpsp->hDlg);
  672. // some bizzare black magic calculation for the pie size...
  673. GetTextExtentPoint(hDC, TEXT("W"), 1, &size);
  674. pdpsp->dwPieShadowHgt = size.cy * 2 / 3;
  675. ReleaseDC(pdpsp->hDlg, hDC);
  676. }
  677. void _DrvPrshtSetDriveIcon(DRIVEPROPSHEETPAGE* pdpsp, CMountPoint* pMtPt)
  678. {
  679. TCHAR szModule[MAX_PATH];
  680. if (pMtPt)
  681. {
  682. UINT uIcon = pMtPt->GetIcon(szModule, ARRAYSIZE(szModule));
  683. if (uIcon)
  684. {
  685. HIMAGELIST hIL = NULL;
  686. Shell_GetImageLists(&hIL, NULL);
  687. if (hIL)
  688. {
  689. int iIndex = Shell_GetCachedImageIndex(szModule[0] ? szModule : c_szShell32Dll, uIcon, 0);
  690. HICON hIcon = ImageList_ExtractIcon(g_hinst, hIL, iIndex);
  691. if (hIcon)
  692. {
  693. ReplaceDlgIcon(pdpsp->hDlg, IDC_DRV_ICON, hIcon);
  694. }
  695. }
  696. }
  697. }
  698. }
  699. void _DrvPrshtSetDriveAttributes(DRIVEPROPSHEETPAGE* pdpsp, CMountPoint* pMtPt)
  700. {
  701. if (pMtPt)
  702. {
  703. if (pMtPt->IsCompressible())
  704. {
  705. // file-based compression is supported (must be NTFS)
  706. pdpsp->fIsCompressionAvailable = TRUE;
  707. if (pMtPt->IsCompressed())
  708. {
  709. // the volume root is compressed
  710. pdpsp->asInitial.fCompress = TRUE;
  711. // if its compressed, compression better be available
  712. ASSERT(pdpsp->fIsCompressionAvailable);
  713. }
  714. }
  715. //
  716. // HACK (reinerf) - we dont have a FS_SUPPORTS_INDEXING so we
  717. // use the FILE_SUPPORTS_SPARSE_FILES flag, because native index support
  718. // appeared first on NTFS5 volumes, at the same time sparse file support
  719. // was implemented.
  720. //
  721. if (pMtPt->IsSupportingSparseFile())
  722. {
  723. // yup, we are on NTFS 5 or greater
  724. pdpsp->fIsIndexAvailable = TRUE;
  725. if (pMtPt->IsContentIndexed())
  726. {
  727. pdpsp->asInitial.fIndex = TRUE;
  728. }
  729. }
  730. }
  731. else
  732. {
  733. // if we don't have a mount point, we just leave everything alone
  734. }
  735. // Set the inital state of the compression / content index checkboxes
  736. if (!pdpsp->fIsCompressionAvailable)
  737. {
  738. // file-based compression is not supported
  739. DestroyWindow(GetDlgItem(pdpsp->hDlg, IDD_COMPRESS));
  740. }
  741. else
  742. {
  743. CheckDlgButton(pdpsp->hDlg, IDD_COMPRESS, pdpsp->asInitial.fCompress);
  744. }
  745. if (!pdpsp->fIsIndexAvailable)
  746. {
  747. // content index is only supported on NTFS 5 volumes
  748. DestroyWindow(GetDlgItem(pdpsp->hDlg, IDD_INDEX));
  749. }
  750. else
  751. {
  752. CheckDlgButton(pdpsp->hDlg, IDD_INDEX, pdpsp->asInitial.fIndex);
  753. }
  754. }
  755. void _DrvPrshtSetFileSystem(DRIVEPROPSHEETPAGE* pdpsp, CMountPoint* pMtPt)
  756. {
  757. TCHAR szFileSystem[64];
  758. szFileSystem[0] = TEXT('\0');
  759. if (pMtPt)
  760. {
  761. if (!pMtPt->GetFileSystemName(szFileSystem, ARRAYSIZE(szFileSystem)) ||
  762. (*szFileSystem == TEXT('\0')))
  763. {
  764. if ((pMtPt->IsStrictRemovable() || pMtPt->IsFloppy() || pMtPt->IsCDROM()) &&
  765. !pMtPt->HasMedia())
  766. {
  767. // if this drive has removable media and it is empty, then fall back to "Unknown"
  768. LoadString(HINST_THISDLL, IDS_FMT_MEDIA0, szFileSystem, ARRAYSIZE(szFileSystem));
  769. }
  770. else
  771. {
  772. // for fixed drives, leave the text as "RAW" (set by default in dlg template)
  773. szFileSystem[0] = TEXT('\0');
  774. }
  775. }
  776. }
  777. if (*szFileSystem)
  778. {
  779. SetDlgItemText(pdpsp->hDlg, IDC_DRV_FS, szFileSystem);
  780. }
  781. }
  782. void _DrvPrshtSetVolumeLabel(DRIVEPROPSHEETPAGE* pdpsp, CMountPoint* pMtPt)
  783. {
  784. TCHAR szLabel[MAX_LABEL_NTFS + 1];
  785. UINT cchLabel = MAX_LABEL_FAT; // assume the drive is FAT
  786. HWND hwndLabel = GetDlgItem(pdpsp->hDlg, IDC_DRV_LABEL);
  787. BOOL bAllowRename = TRUE;
  788. HRESULT hr = E_FAIL;
  789. szLabel[0] = TEXT('\0');
  790. if (pMtPt)
  791. {
  792. hr = pMtPt->GetLabelNoFancy(szLabel, ARRAYSIZE(szLabel));
  793. if (pMtPt->IsRemote() ||
  794. (pMtPt->IsCDROM() && !pMtPt->IsDVDRAMMedia()))
  795. {
  796. // ISSUE-2000/10/30-StephStm We probably want to distinguish between diff types of cdrom drives
  797. bAllowRename = FALSE;
  798. }
  799. if ( !bAllowRename && pMtPt->IsCDROM( ) )
  800. {
  801. //
  802. // Check to see if it is CDFS, if not, make no assumptions about
  803. // writing the label.
  804. //
  805. WCHAR szFS[ 10 ]; // random - just more than "CDFS\0"
  806. BOOL b = pMtPt->GetFileSystemName( szFS, ARRAYSIZE(szFS) );
  807. if (b && lstrcmpi(szFS, L"CDFS") != 0 )
  808. {
  809. // Re-enable the label as we don't know if the FS doesn't support this
  810. // until we actually try it.
  811. bAllowRename = TRUE;
  812. }
  813. }
  814. if (pMtPt->IsNTFS())
  815. {
  816. cchLabel = MAX_LABEL_NTFS;
  817. }
  818. }
  819. SetWindowText(hwndLabel, szLabel);
  820. if (FAILED(hr) || !bAllowRename)
  821. {
  822. Edit_SetReadOnly(hwndLabel, TRUE);
  823. }
  824. // limit the "Label" edit box based on the filesystem
  825. Edit_LimitText(hwndLabel, cchLabel);
  826. // make sure we don't recieve an EN_CHANGED message for the volume edit box
  827. // because we set it above
  828. Edit_SetModify(hwndLabel, FALSE);
  829. }
  830. void _DrvPrshtSetDriveType(DRIVEPROPSHEETPAGE* pdpsp, CMountPoint* pMtPt)
  831. {
  832. TCHAR szDriveType[80];
  833. szDriveType[0] = TEXT('\0');
  834. if (pMtPt)
  835. {
  836. if (pMtPt->IsUnavailableNetDrive())
  837. {
  838. LoadString(HINST_THISDLL, IDS_DRIVES_NETUNAVAIL, szDriveType, ARRAYSIZE(szDriveType));
  839. }
  840. else
  841. {
  842. pMtPt->GetTypeString(szDriveType, ARRAYSIZE(szDriveType));
  843. }
  844. }
  845. SetDlgItemText(pdpsp->hDlg, IDC_DRV_TYPE, szDriveType);
  846. }
  847. void _DrvPrshtSetDriveLetter(DRIVEPROPSHEETPAGE* pdpsp)
  848. {
  849. TCHAR szDriveLetterText[80];
  850. TCHAR szFormat[80];
  851. if (pdpsp->fMountedDrive)
  852. {
  853. TCHAR szLabel[MAX_LABEL_NTFS + 1];
  854. if (GetDlgItemText(pdpsp->hDlg, IDC_DRV_LABEL, szLabel, ARRAYSIZE(szLabel)))
  855. {
  856. LoadString(HINST_THISDLL, IDS_VOLUMELABEL, szFormat, ARRAYSIZE(szFormat));
  857. wnsprintf(szDriveLetterText, ARRAYSIZE(szDriveLetterText), szFormat, szLabel);
  858. SetDlgItemText(pdpsp->hDlg, IDC_DRV_LETTER, szDriveLetterText);
  859. }
  860. }
  861. else
  862. {
  863. LoadString(HINST_THISDLL, IDS_DRIVELETTER, szFormat, ARRAYSIZE(szFormat));
  864. wnsprintf(szDriveLetterText, ARRAYSIZE(szDriveLetterText), szFormat, pdpsp->iDrive + TEXT('A'));
  865. SetDlgItemText(pdpsp->hDlg, IDC_DRV_LETTER, szDriveLetterText);
  866. }
  867. }
  868. void _DrvPrshtSetDiskCleanup(DRIVEPROPSHEETPAGE* pdpsp)
  869. {
  870. // if we have a cleanup path in the registry, turn on the Disk Cleanup button on
  871. // NOTE: disk cleanup and mounted volumes don't get along to well, so disable it for now.
  872. if (!pdpsp->fMountedDrive && GetDiskCleanupPath(NULL, 0) && IsBitBucketableDrive(pdpsp->iDrive))
  873. {
  874. ShowWindow(GetDlgItem(pdpsp->hDlg, IDC_DRV_CLEANUP), SW_SHOW);
  875. EnableWindow(GetDlgItem(pdpsp->hDlg, IDC_DRV_CLEANUP), TRUE);
  876. }
  877. else
  878. {
  879. ShowWindow(GetDlgItem(pdpsp->hDlg, IDC_DRV_CLEANUP), SW_HIDE);
  880. EnableWindow(GetDlgItem(pdpsp->hDlg, IDC_DRV_CLEANUP), FALSE);
  881. }
  882. }
  883. void _DrvPrshtInit(DRIVEPROPSHEETPAGE* pdpsp)
  884. {
  885. HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  886. // get the MountPoint object for this drive
  887. CMountPoint* pMtPt = CMountPoint::GetMountPoint(pdpsp->szDrive);
  888. if ( !pMtPt )
  889. {
  890. pMtPt = CMountPoint::GetSimulatedMountPointFromVolumeGuid( pdpsp->szDrive );
  891. }
  892. _DrvPrshtGetPieShadowHeight(pdpsp);
  893. _DrvPrshtSetDriveIcon(pdpsp, pMtPt);
  894. _DrvPrshtSetDriveAttributes(pdpsp, pMtPt);
  895. _DrvPrshtSetFileSystem(pdpsp, pMtPt);
  896. _DrvPrshtSetVolumeLabel(pdpsp, pMtPt);
  897. _DrvPrshtSetDriveType(pdpsp, pMtPt);
  898. _DrvPrshtSetSpaceValues(pdpsp);
  899. _DrvPrshtSetDriveLetter(pdpsp);
  900. _DrvPrshtSetDiskCleanup(pdpsp);
  901. SetCursor(hcurOld);
  902. if (pMtPt)
  903. {
  904. pMtPt->Release();
  905. }
  906. }
  907. void _DrvPrshtUpdateInfo(DRIVEPROPSHEETPAGE* pdpsp)
  908. {
  909. CMountPoint* pMtPt = CMountPoint::GetMountPoint(pdpsp->szDrive);
  910. _DrvPrshtSetSpaceValues(pdpsp);
  911. _DrvPrshtSetDriveType(pdpsp, pMtPt);
  912. if (pMtPt)
  913. {
  914. pMtPt->Release();
  915. }
  916. }
  917. const COLORREF c_crPieColors[] =
  918. {
  919. RGB( 0, 0, 255), // Blue
  920. RGB(255, 0, 255), // Red-Blue
  921. RGB( 0, 0, 128), // 1/2 Blue
  922. RGB(128, 0, 128), // 1/2 Red-Blue
  923. };
  924. STDAPI Draw3dPie(HDC hdc, RECT *prc, DWORD dwPer1000, const COLORREF *lpColors);
  925. void DrawColorRect(HDC hdc, COLORREF crDraw, const RECT *prc)
  926. {
  927. HBRUSH hbDraw = CreateSolidBrush(crDraw);
  928. if (hbDraw)
  929. {
  930. HBRUSH hbOld = (HBRUSH)SelectObject(hdc, hbDraw);
  931. if (hbOld)
  932. {
  933. PatBlt(hdc, prc->left, prc->top,
  934. prc->right - prc->left,
  935. prc->bottom - prc->top,
  936. PATCOPY);
  937. SelectObject(hdc, hbOld);
  938. }
  939. DeleteObject(hbDraw);
  940. }
  941. }
  942. void _DrvPrshtDrawItem(DRIVEPROPSHEETPAGE *pdpsp, const DRAWITEMSTRUCT * lpdi)
  943. {
  944. switch (lpdi->CtlID)
  945. {
  946. case IDC_DRV_PIE:
  947. {
  948. DWORD dwPctX10 = pdpsp->qwTot ?
  949. (DWORD)((__int64)1000 * (pdpsp->qwTot - pdpsp->qwFree) / pdpsp->qwTot) :
  950. 1000;
  951. #if 1
  952. DrawPie(lpdi->hDC, &lpdi->rcItem,
  953. dwPctX10, pdpsp->qwFree==0 || pdpsp->qwFree==pdpsp->qwTot,
  954. pdpsp->dwPieShadowHgt, c_crPieColors);
  955. #else
  956. {
  957. RECT rcTemp = lpdi->rcItem;
  958. Draw3dPie(lpdi->hDC, &rcTemp, dwPctX10, c_crPieColors);
  959. }
  960. #endif
  961. }
  962. break;
  963. case IDC_DRV_USEDCOLOR:
  964. DrawColorRect(lpdi->hDC, c_crPieColors[DP_USEDCOLOR], &lpdi->rcItem);
  965. break;
  966. case IDC_DRV_FREECOLOR:
  967. DrawColorRect(lpdi->hDC, c_crPieColors[DP_FREECOLOR], &lpdi->rcItem);
  968. break;
  969. default:
  970. break;
  971. }
  972. }
  973. BOOL_PTR CALLBACK DriveAttribsDlgProc(HWND hDlgRecurse, UINT uMessage, WPARAM wParam, LPARAM lParam)
  974. {
  975. DRIVEPROPSHEETPAGE* pdpsp = (DRIVEPROPSHEETPAGE *)GetWindowLongPtr(hDlgRecurse, DWLP_USER);
  976. switch (uMessage)
  977. {
  978. case WM_INITDIALOG:
  979. {
  980. TCHAR szTemp[MAX_PATH];
  981. TCHAR szAttribsToApply[MAX_PATH];
  982. TCHAR szDriveText[MAX_PATH];
  983. TCHAR szFormatString[MAX_PATH];
  984. TCHAR szDlgText[MAX_PATH];
  985. int iLength;
  986. SetWindowLongPtr(hDlgRecurse, DWLP_USER, lParam);
  987. pdpsp = (DRIVEPROPSHEETPAGE *)lParam;
  988. // set the initial state of the radio button
  989. CheckDlgButton(hDlgRecurse, IDD_RECURSIVE, TRUE);
  990. szAttribsToApply[0] = 0;
  991. // set the IDD_ATTRIBSTOAPPLY based on what attribs we are applying
  992. if (pdpsp->asInitial.fIndex != pdpsp->asCurrent.fIndex)
  993. {
  994. if (pdpsp->asCurrent.fIndex)
  995. LoadString(HINST_THISDLL, IDS_INDEX, szTemp, ARRAYSIZE(szTemp));
  996. else
  997. LoadString(HINST_THISDLL, IDS_DISABLEINDEX, szTemp, ARRAYSIZE(szTemp));
  998. lstrcatn(szAttribsToApply, szTemp, ARRAYSIZE(szAttribsToApply));
  999. }
  1000. if (pdpsp->asInitial.fCompress != pdpsp->asCurrent.fCompress)
  1001. {
  1002. if (pdpsp->asCurrent.fCompress)
  1003. LoadString(HINST_THISDLL, IDS_COMPRESS, szTemp, ARRAYSIZE(szTemp));
  1004. else
  1005. LoadString(HINST_THISDLL, IDS_UNCOMPRESS, szTemp, ARRAYSIZE(szTemp));
  1006. lstrcatn(szAttribsToApply, szTemp, ARRAYSIZE(szAttribsToApply));
  1007. }
  1008. // remove the trailing ", "
  1009. iLength = lstrlen(szAttribsToApply);
  1010. ASSERT(iLength >= 3);
  1011. szAttribsToApply[iLength - 2] = 0;
  1012. SetDlgItemText(hDlgRecurse, IDD_ATTRIBSTOAPPLY, szAttribsToApply);
  1013. // this dialog was only designed for nice short paths like "c:\" not "\\?\Volume{GUID}\" paths
  1014. if (lstrlen(pdpsp->szDrive) > 3)
  1015. {
  1016. // get the default string
  1017. LoadString(HINST_THISDLL, IDS_THISVOLUME, szDriveText, ARRAYSIZE(szDriveText));
  1018. }
  1019. else
  1020. {
  1021. // Create the string "C:\"
  1022. lstrcpyn(szDriveText, pdpsp->szDrive, ARRAYSIZE(szDriveText));
  1023. PathAddBackslash(szDriveText);
  1024. // sanity check; this better be a drive root!
  1025. ASSERT(PathIsRoot(szDriveText));
  1026. }
  1027. // set the IDD_RECURSIVE_TXT text to have "C:\"
  1028. GetDlgItemText(hDlgRecurse, IDD_RECURSIVE_TXT, szFormatString, ARRAYSIZE(szFormatString));
  1029. wnsprintf(szDlgText, ARRAYSIZE(szDlgText), szFormatString, szDriveText);
  1030. SetDlgItemText(hDlgRecurse, IDD_RECURSIVE_TXT, szDlgText);
  1031. // set the IDD_NOTRECURSIVE raido button text to have "C:\"
  1032. GetDlgItemText(hDlgRecurse, IDD_NOTRECURSIVE, szFormatString, ARRAYSIZE(szFormatString));
  1033. wnsprintf(szDlgText, ARRAYSIZE(szDlgText), szFormatString, szDriveText);
  1034. SetDlgItemText(hDlgRecurse, IDD_NOTRECURSIVE, szDlgText);
  1035. // set the IDD_RECURSIVE raido button text to have "C:\"
  1036. GetDlgItemText(hDlgRecurse, IDD_RECURSIVE, szFormatString, ARRAYSIZE(szFormatString));
  1037. wnsprintf(szDlgText, ARRAYSIZE(szDlgText), szFormatString, szDriveText);
  1038. SetDlgItemText(hDlgRecurse, IDD_RECURSIVE, szDlgText);
  1039. }
  1040. break;
  1041. case WM_COMMAND:
  1042. {
  1043. UINT uID = GET_WM_COMMAND_ID(wParam, lParam);
  1044. switch (uID)
  1045. {
  1046. case IDOK:
  1047. pdpsp->fRecursive = (IsDlgButtonChecked(hDlgRecurse, IDD_RECURSIVE) == BST_CHECKED);
  1048. // fall through
  1049. case IDCANCEL:
  1050. EndDialog(hDlgRecurse, (uID == IDCANCEL) ? FALSE : TRUE);
  1051. break;
  1052. }
  1053. }
  1054. default:
  1055. return FALSE;
  1056. }
  1057. return TRUE;
  1058. }
  1059. BOOL _DrvPrshtApply(DRIVEPROPSHEETPAGE* pdpsp)
  1060. {
  1061. BOOL bFctRet;
  1062. HWND hCtl;
  1063. // take care of compression / content indexing first
  1064. pdpsp->asCurrent.fCompress = (IsDlgButtonChecked(pdpsp->hDlg, IDD_COMPRESS) == BST_CHECKED);
  1065. pdpsp->asCurrent.fIndex = (IsDlgButtonChecked(pdpsp->hDlg, IDD_INDEX) == BST_CHECKED);
  1066. pdpsp->asCurrent.fRecordingEnabled = (IsDlgButtonChecked(pdpsp->hDlg, IDC_RECORD_ENABLE) == BST_CHECKED);
  1067. // check to see if something has changed before applying attribs
  1068. if (memcmp(&pdpsp->asInitial, &pdpsp->asCurrent, sizeof(pdpsp->asInitial)) != 0)
  1069. {
  1070. // the user toggled the attributes, so ask them if they want to recurse
  1071. BOOL_PTR bRet = DialogBoxParam(HINST_THISDLL,
  1072. MAKEINTRESOURCE(DLG_ATTRIBS_RECURSIVE),
  1073. pdpsp->hDlg,
  1074. DriveAttribsDlgProc,
  1075. (LPARAM)pdpsp);
  1076. if (bRet)
  1077. {
  1078. FILEPROPSHEETPAGE fpsp = {0};
  1079. fpsp.pfci = Create_FolderContentsInfo();
  1080. if (fpsp.pfci)
  1081. {
  1082. // we cook up a fpsp and call ApplySingleFileAttributes instead of
  1083. // rewriting the apply attributes code
  1084. if (pdpsp->fMountedDrive)
  1085. {
  1086. GetVolumeNameForVolumeMountPoint(pdpsp->szDrive, fpsp.szPath, ARRAYSIZE(fpsp.szPath));
  1087. }
  1088. else
  1089. {
  1090. lstrcpyn(fpsp.szPath, pdpsp->szDrive, ARRAYSIZE(fpsp.szPath));
  1091. }
  1092. fpsp.hDlg = pdpsp->hDlg;
  1093. fpsp.asInitial = pdpsp->asInitial;
  1094. fpsp.asCurrent = pdpsp->asCurrent;
  1095. fpsp.pfci->fIsCompressionAvailable = pdpsp->fIsCompressionAvailable;
  1096. fpsp.pfci->ulTotalNumberOfBytes.QuadPart = pdpsp->qwTot - pdpsp->qwFree; // for progress calculations
  1097. fpsp.fIsIndexAvailable = pdpsp->fIsIndexAvailable;
  1098. fpsp.fRecursive = pdpsp->fRecursive;
  1099. fpsp.fIsDirectory = TRUE;
  1100. bRet = ApplySingleFileAttributes(&fpsp);
  1101. Release_FolderContentsInfo(fpsp.pfci);
  1102. fpsp.pfci = NULL;
  1103. // update the free/used space after applying attribs because something could
  1104. // have changed (eg compression frees up space)
  1105. _DrvPrshtUpdateInfo(pdpsp);
  1106. // update the initial attributes to reflect the ones we just applied, regardless
  1107. // if the operation was sucessful or not. If they hit cancel, then the volume
  1108. // root was most likely still changed so we need to update.
  1109. pdpsp->asInitial = pdpsp->asCurrent;
  1110. }
  1111. else
  1112. {
  1113. bRet = FALSE;
  1114. }
  1115. }
  1116. if (!bRet)
  1117. {
  1118. // the user hit cancel somewhere
  1119. return FALSE;
  1120. }
  1121. }
  1122. hCtl = GetDlgItem(pdpsp->hDlg, IDC_DRV_LABEL);
  1123. bFctRet = TRUE;
  1124. if (Edit_GetModify(hCtl))
  1125. {
  1126. bFctRet = FALSE; // assume we fail to set the label
  1127. TCHAR szLabel[MAX_LABEL_NTFS + 1];
  1128. GetWindowText(hCtl, szLabel, ARRAYSIZE(szLabel));
  1129. CMountPoint* pMtPt = CMountPoint::GetMountPoint(pdpsp->szDrive);
  1130. if ( !pMtPt )
  1131. {
  1132. pMtPt = CMountPoint::GetSimulatedMountPointFromVolumeGuid( pdpsp->szDrive );
  1133. }
  1134. if (pMtPt)
  1135. {
  1136. if (SUCCEEDED(pMtPt->SetLabel(GetParent(pdpsp->hDlg), szLabel)))
  1137. bFctRet = TRUE;
  1138. pMtPt->Release();
  1139. }
  1140. }
  1141. return bFctRet;
  1142. }
  1143. const static DWORD aDrvPrshtHelpIDs[] = { // Context Help IDs
  1144. IDC_DRV_ICON, IDH_FCAB_DRV_ICON,
  1145. IDC_DRV_LABEL, IDH_FCAB_DRV_LABEL,
  1146. IDC_DRV_TYPE_TXT, IDH_FCAB_DRV_TYPE,
  1147. IDC_DRV_TYPE, IDH_FCAB_DRV_TYPE,
  1148. IDC_DRV_FS_TXT, IDH_FCAB_DRV_FS,
  1149. IDC_DRV_FS, IDH_FCAB_DRV_FS,
  1150. IDC_DRV_USEDCOLOR, IDH_FCAB_DRV_USEDCOLORS,
  1151. IDC_DRV_USEDBYTES_TXT, IDH_FCAB_DRV_USEDCOLORS,
  1152. IDC_DRV_USEDBYTES, IDH_FCAB_DRV_USEDCOLORS,
  1153. IDC_DRV_USEDMB, IDH_FCAB_DRV_USEDCOLORS,
  1154. IDC_DRV_FREECOLOR, IDH_FCAB_DRV_USEDCOLORS,
  1155. IDC_DRV_FREEBYTES_TXT, IDH_FCAB_DRV_USEDCOLORS,
  1156. IDC_DRV_FREEBYTES, IDH_FCAB_DRV_USEDCOLORS,
  1157. IDC_DRV_FREEMB, IDH_FCAB_DRV_USEDCOLORS,
  1158. IDC_DRV_TOTSEP, NO_HELP,
  1159. IDC_DRV_TOTBYTES_TXT, IDH_FCAB_DRV_TOTSEP,
  1160. IDC_DRV_TOTBYTES, IDH_FCAB_DRV_TOTSEP,
  1161. IDC_DRV_TOTMB, IDH_FCAB_DRV_TOTSEP,
  1162. IDC_DRV_PIE, IDH_FCAB_DRV_PIE,
  1163. IDC_DRV_LETTER, IDH_FCAB_DRV_LETTER,
  1164. IDC_DRV_CLEANUP, IDH_FCAB_DRV_CLEANUP,
  1165. IDD_COMPRESS, IDH_FCAB_DRV_COMPRESS,
  1166. IDD_INDEX, IDH_FCAB_DRV_INDEX,
  1167. 0, 0
  1168. };
  1169. //
  1170. // Descriptions:
  1171. // This is the dialog procedure for the "general" page of a property sheet.
  1172. //
  1173. BOOL_PTR CALLBACK _DrvGeneralDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
  1174. {
  1175. DRIVEPROPSHEETPAGE * pdpsp = (DRIVEPROPSHEETPAGE *)GetWindowLongPtr(hDlg, DWLP_USER);
  1176. switch (uMessage)
  1177. {
  1178. case WM_INITDIALOG:
  1179. // REVIEW, we should store more state info here, for example
  1180. // the hIcon being displayed and the FILEINFO pointer, not just
  1181. // the file name ptr
  1182. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  1183. pdpsp = (DRIVEPROPSHEETPAGE *)lParam;
  1184. pdpsp->hDlg = hDlg;
  1185. _DrvPrshtInit(pdpsp);
  1186. break;
  1187. case WM_DESTROY:
  1188. ReplaceDlgIcon(hDlg, IDC_DRV_ICON, NULL); // free the icon
  1189. break;
  1190. case WM_ACTIVATE:
  1191. if (GET_WM_ACTIVATE_STATE(wParam, lParam) != WA_INACTIVE && pdpsp)
  1192. _DrvPrshtUpdateInfo(pdpsp);
  1193. return FALSE; // Let DefDlgProc know we did not handle this
  1194. case WM_DRAWITEM:
  1195. _DrvPrshtDrawItem(pdpsp, (DRAWITEMSTRUCT *)lParam);
  1196. break;
  1197. case WM_HELP:
  1198. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aDrvPrshtHelpIDs);
  1199. break;
  1200. case WM_CONTEXTMENU:
  1201. WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aDrvPrshtHelpIDs);
  1202. break;
  1203. case WM_COMMAND:
  1204. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1205. {
  1206. case IDC_DRV_LABEL:
  1207. if (GET_WM_COMMAND_CMD(wParam, lParam) != EN_CHANGE)
  1208. break;
  1209. // else, fall through
  1210. case IDD_COMPRESS:
  1211. case IDD_INDEX:
  1212. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
  1213. break;
  1214. // handle disk cleanup button
  1215. case IDC_DRV_CLEANUP:
  1216. LaunchDiskCleanup(hDlg, pdpsp->iDrive, DISKCLEANUP_NOFLAG);
  1217. break;
  1218. default:
  1219. return TRUE;
  1220. }
  1221. break;
  1222. case WM_NOTIFY:
  1223. switch (((NMHDR *)lParam)->code)
  1224. {
  1225. case PSN_SETACTIVE:
  1226. break;
  1227. case PSN_APPLY:
  1228. if (!_DrvPrshtApply(pdpsp))
  1229. {
  1230. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  1231. }
  1232. break;
  1233. default:
  1234. return FALSE;
  1235. }
  1236. break;
  1237. default:
  1238. return FALSE;
  1239. }
  1240. return TRUE;
  1241. }
  1242. void _DiskToolsPrshtInit(DRIVEPROPSHEETPAGE * pdpsp)
  1243. {
  1244. TCHAR szFmt[MAX_PATH + 20];
  1245. DWORD cbLen = sizeof(szFmt);
  1246. BOOL bFoundBackup = SUCCEEDED(SKGetValue(SHELLKEY_HKLM_EXPLORER, REL_KEY_BACKUP, NULL, NULL, szFmt, &cbLen));
  1247. // If no backup utility is installed, then remove everything in the backup groupbox
  1248. if (!bFoundBackup)
  1249. {
  1250. DestroyWindow(GetDlgItem(pdpsp->hDlg, IDC_DISKTOOLS_BKPNOW));
  1251. DestroyWindow(GetDlgItem(pdpsp->hDlg, IDC_DISKTOOLS_BKPICON));
  1252. DestroyWindow(GetDlgItem(pdpsp->hDlg, IDC_DISKTOOLS_BKPDAYS));
  1253. DestroyWindow(GetDlgItem(pdpsp->hDlg, IDC_DISKTOOLS_BKPTXT));
  1254. }
  1255. cbLen = sizeof(szFmt);
  1256. BOOL bFoundFmt = SUCCEEDED(SKGetValue(SHELLKEY_HKLM_EXPLORER, REL_KEY_DEFRAG, NULL, NULL, szFmt, &cbLen)) && szFmt[0];
  1257. // If no defrag utility is installed, replace the default defrag text with
  1258. // the "No defrag installed" message. Also grey out the "defrag now" button.
  1259. if (!bFoundFmt)
  1260. {
  1261. TCHAR szMessage[50]; // WARNING: IDS_DRIVES_NOOPTINSTALLED is currently 47
  1262. // characters long. Resize this buffer if
  1263. // the string resource is lengthened.
  1264. LoadString(HINST_THISDLL, IDS_DRIVES_NOOPTINSTALLED, szMessage, ARRAYSIZE(szMessage));
  1265. SetDlgItemText(pdpsp->hDlg, IDC_DISKTOOLS_OPTDAYS, szMessage);
  1266. Button_Enable(GetDlgItem(pdpsp->hDlg, IDC_DISKTOOLS_OPTNOW), FALSE);
  1267. }
  1268. }
  1269. const static DWORD aDiskToolsHelpIDs[] = { // Context Help IDs
  1270. IDC_DISKTOOLS_TRLIGHT, IDH_FCAB_DISKTOOLS_CHKNOW,
  1271. IDC_DISKTOOLS_CHKDAYS, IDH_FCAB_DISKTOOLS_CHKNOW,
  1272. IDC_DISKTOOLS_CHKNOW, IDH_FCAB_DISKTOOLS_CHKNOW,
  1273. IDC_DISKTOOLS_BKPTXT, IDH_FCAB_DISKTOOLS_BKPNOW,
  1274. IDC_DISKTOOLS_BKPDAYS, IDH_FCAB_DISKTOOLS_BKPNOW,
  1275. IDC_DISKTOOLS_BKPNOW, IDH_FCAB_DISKTOOLS_BKPNOW,
  1276. IDC_DISKTOOLS_OPTDAYS, IDH_FCAB_DISKTOOLS_OPTNOW,
  1277. IDC_DISKTOOLS_OPTNOW, IDH_FCAB_DISKTOOLS_OPTNOW,
  1278. 0, 0
  1279. };
  1280. BOOL _DiskToolsCommand(DRIVEPROPSHEETPAGE * pdpsp, WPARAM wParam, LPARAM lParam)
  1281. {
  1282. // Add 20 for extra formatting
  1283. TCHAR szFmt[MAX_PATH + 20];
  1284. TCHAR szCmd[MAX_PATH + 20];
  1285. LPCTSTR pszRegName, pszDefFmt;
  1286. int nErrMsg = 0;
  1287. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1288. {
  1289. case IDC_DISKTOOLS_CHKNOW:
  1290. SHChkDskDriveEx(pdpsp->hDlg, pdpsp->szDrive);
  1291. return FALSE;
  1292. case IDC_DISKTOOLS_OPTNOW:
  1293. pszRegName = REL_KEY_DEFRAG;
  1294. if (pdpsp->fMountedDrive)
  1295. {
  1296. pszDefFmt = TEXT("defrag.exe");
  1297. }
  1298. else
  1299. {
  1300. pszDefFmt = TEXT("defrag.exe %c:");
  1301. }
  1302. nErrMsg = IDS_NO_OPTIMISE_APP;
  1303. break;
  1304. case IDC_DISKTOOLS_BKPNOW:
  1305. pszRegName = REL_KEY_BACKUP;
  1306. pszDefFmt = TEXT("ntbackup.exe");
  1307. nErrMsg = IDS_NO_BACKUP_APP;
  1308. break;
  1309. default:
  1310. return FALSE;
  1311. }
  1312. DWORD cbLen = sizeof(szFmt);
  1313. if (FAILED(SKGetValue(SHELLKEY_HKLM_EXPLORER, pszRegName, NULL, NULL, szFmt, &cbLen)))
  1314. {
  1315. // failed to read out the reg value, just use the default
  1316. lstrcpy(szFmt, pszDefFmt);
  1317. }
  1318. // some apps write REG_SZ keys to the registry even though they have env variables in them
  1319. ExpandEnvironmentStrings(szFmt, szCmd, ARRAYSIZE(szCmd));
  1320. lstrcpyn(szFmt, szCmd, ARRAYSIZE(szFmt));
  1321. // Plug in the drive letter in case they want it
  1322. wnsprintf(szCmd, ARRAYSIZE(szCmd), szFmt, pdpsp->iDrive + TEXT('A'));
  1323. if (!ShellExecCmdLine(pdpsp->hDlg,
  1324. szCmd,
  1325. NULL,
  1326. SW_SHOWNORMAL,
  1327. NULL,
  1328. SECL_USEFULLPATHDIR | SECL_NO_UI))
  1329. {
  1330. // Something went wrong - app's probably not installed.
  1331. if (nErrMsg)
  1332. {
  1333. ShellMessageBox(HINST_THISDLL,
  1334. pdpsp->hDlg,
  1335. MAKEINTRESOURCE(nErrMsg), NULL,
  1336. MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
  1337. }
  1338. return FALSE;
  1339. }
  1340. return TRUE;
  1341. }
  1342. //
  1343. // Descriptions:
  1344. // This is the dialog procedure for the "Tools" page of a property sheet.
  1345. //
  1346. BOOL_PTR CALLBACK _DiskToolsDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
  1347. {
  1348. DRIVEPROPSHEETPAGE * pdpsp = (DRIVEPROPSHEETPAGE *)GetWindowLongPtr(hDlg, DWLP_USER);
  1349. switch (uMessage)
  1350. {
  1351. case WM_INITDIALOG:
  1352. // REVIEW, we should store more state info here, for example
  1353. // the hIcon being displayed and the FILEINFO pointer, not just
  1354. // the file name ptr
  1355. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  1356. pdpsp = (DRIVEPROPSHEETPAGE *)lParam;
  1357. pdpsp->hDlg = hDlg;
  1358. _DiskToolsPrshtInit(pdpsp);
  1359. break;
  1360. case WM_ACTIVATE:
  1361. if (GET_WM_ACTIVATE_STATE(wParam, lParam) != WA_INACTIVE && pdpsp)
  1362. {
  1363. _DiskToolsPrshtInit(pdpsp);
  1364. }
  1365. return FALSE; // Let DefDlgProc know we did not handle this
  1366. case WM_HELP:
  1367. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL,
  1368. HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aDiskToolsHelpIDs);
  1369. break;
  1370. case WM_CONTEXTMENU:
  1371. WinHelp((HWND)wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aDiskToolsHelpIDs);
  1372. break;
  1373. case WM_COMMAND:
  1374. return _DiskToolsCommand(pdpsp, wParam, lParam);
  1375. case WM_NOTIFY:
  1376. switch (((NMHDR *)lParam)->code)
  1377. {
  1378. case PSN_SETACTIVE:
  1379. break;
  1380. case PSN_APPLY:
  1381. return TRUE;
  1382. default:
  1383. return FALSE;
  1384. }
  1385. break;
  1386. default:
  1387. return FALSE;
  1388. }
  1389. return TRUE;
  1390. }
  1391. //
  1392. // This is the dialog procedure for the "Hardware" page.
  1393. //
  1394. const GUID c_rgguidDevMgr[] =
  1395. {
  1396. { 0x4d36e967, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } }, // GUID_DEVCLASS_DISKDRIVE
  1397. { 0x4d36e980, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } }, // GUID_DEVCLASS_FLOPPYDISK
  1398. { 0x4d36e965, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } }, // GUID_DEVCLASS_CDROM
  1399. };
  1400. BOOL_PTR CALLBACK _DriveHWDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
  1401. {
  1402. switch (uMessage)
  1403. {
  1404. case WM_INITDIALOG:
  1405. {
  1406. DRIVEPROPSHEETPAGE * pdpsp = (DRIVEPROPSHEETPAGE *)lParam;
  1407. HWND hwndHW = DeviceCreateHardwarePageEx(hDlg, c_rgguidDevMgr, ARRAYSIZE(c_rgguidDevMgr), HWTAB_LARGELIST);
  1408. if (hwndHW)
  1409. {
  1410. TCHAR szBuf[MAX_PATH];
  1411. LoadString(HINST_THISDLL, IDS_DRIVETSHOOT, szBuf, ARRAYSIZE(szBuf));
  1412. SetWindowText(hwndHW, szBuf);
  1413. LoadString(HINST_THISDLL, IDS_THESEDRIVES, szBuf, ARRAYSIZE(szBuf));
  1414. SetDlgItemText(hwndHW, IDC_HWTAB_LVSTATIC, szBuf);
  1415. }
  1416. else
  1417. {
  1418. DestroyWindow(hDlg); // catastrophic failure
  1419. }
  1420. }
  1421. return FALSE;
  1422. }
  1423. return FALSE;
  1424. }
  1425. BOOL CDrives_AddPage(LPPROPSHEETPAGE ppsp, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
  1426. {
  1427. BOOL fSuccess;
  1428. HPROPSHEETPAGE hpage = CreatePropertySheetPage(ppsp);
  1429. if (hpage)
  1430. {
  1431. fSuccess = pfnAddPage(hpage, lParam);
  1432. if (!fSuccess)
  1433. { // Couldn't add page
  1434. DestroyPropertySheetPage(hpage);
  1435. fSuccess = FALSE;
  1436. }
  1437. }
  1438. else
  1439. { // Couldn't create page
  1440. fSuccess = FALSE;
  1441. }
  1442. return fSuccess;
  1443. }
  1444. HRESULT CDrives_AddPagesHelper(DRIVEPROPSHEETPAGE* pdpsp, int iType,
  1445. LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
  1446. {
  1447. if ((iType == DRIVE_NO_ROOT_DIR) ||
  1448. (iType == DRIVE_REMOTE))
  1449. {
  1450. return S_OK;
  1451. }
  1452. CMountPoint* pMtPt = CMountPoint::GetMountPoint(pdpsp->szDrive);
  1453. if (pMtPt)
  1454. {
  1455. if (IsShellServiceRunning())
  1456. {
  1457. if (pMtPt->IsStrictRemovable() || pMtPt->IsCDROM() ||
  1458. (pMtPt->IsFixedDisk() && pMtPt->IsRemovableDevice()))
  1459. {
  1460. CAutoPlayDlg* papdlg = new CAutoPlayDlg();
  1461. if (papdlg)
  1462. {
  1463. // Autoplay
  1464. pdpsp->psp.pszTemplate = MAKEINTRESOURCE(DLG_AUTOPLAY);
  1465. pdpsp->psp.pfnDlgProc = CAutoPlayDlg::BaseDlgWndProc;
  1466. pdpsp->psp.pfnCallback = CBaseDlg::BaseDlgPropSheetCallback;
  1467. pdpsp->psp.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
  1468. papdlg->Init(pdpsp->szDrive, iType);
  1469. // for now
  1470. pdpsp->psp.lParam = (LPARAM)(CBaseDlg*)papdlg;
  1471. if (CDrives_AddPage(&pdpsp->psp, pfnAddPage, lParam))
  1472. {
  1473. papdlg->AddRef();
  1474. }
  1475. pdpsp->psp.lParam = NULL;
  1476. pdpsp->psp.pfnCallback = NULL;
  1477. pdpsp->psp.dwFlags = NULL;
  1478. papdlg->Release();
  1479. }
  1480. }
  1481. }
  1482. if ((iType != DRIVE_CDROM) || pMtPt->IsDVDRAMMedia())
  1483. {
  1484. // we add the tools page for non-cdrom and DVD-RAM disks
  1485. pdpsp->psp.pszTemplate = MAKEINTRESOURCE(DLG_DISKTOOLS);
  1486. pdpsp->psp.pfnDlgProc = _DiskToolsDlgProc;
  1487. CDrives_AddPage(&pdpsp->psp, pfnAddPage, lParam);
  1488. }
  1489. pMtPt->Release();
  1490. }
  1491. if (!SHRestricted(REST_NOHARDWARETAB))
  1492. {
  1493. pdpsp->psp.pszTemplate = MAKEINTRESOURCE(DLG_DRV_HWTAB);
  1494. pdpsp->psp.pfnDlgProc = _DriveHWDlgProc;
  1495. CDrives_AddPage(&pdpsp->psp, pfnAddPage, lParam);
  1496. }
  1497. return S_OK;
  1498. }
  1499. //
  1500. // We check if any of the IDList's points to a drive root. If so, we use the
  1501. // drives property page.
  1502. // Note that drives should not be mixed with folders and files, even in a
  1503. // search window.
  1504. //
  1505. STDAPI CDrives_AddPages(IDataObject *pdtobj, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
  1506. {
  1507. STGMEDIUM medium;
  1508. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  1509. if (SUCCEEDED(pdtobj->GetData(&fmte, &medium)))
  1510. {
  1511. TCHAR szPath[MAX_PATH];
  1512. int i, cItems = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0);
  1513. for (i = 0; DragQueryFile((HDROP)medium.hGlobal, i, szPath, ARRAYSIZE(szPath)); i++)
  1514. {
  1515. DRIVEPROPSHEETPAGE dpsp = {0};
  1516. TCHAR szTitle[80];
  1517. if (lstrlen(szPath) > 3)
  1518. continue; // can't be a drive letter
  1519. dpsp.psp.dwSize = sizeof(dpsp); // extra data
  1520. dpsp.psp.dwFlags = PSP_DEFAULT;
  1521. dpsp.psp.hInstance = HINST_THISDLL;
  1522. dpsp.psp.pszTemplate = MAKEINTRESOURCE(DLG_DRV_GENERAL);
  1523. dpsp.psp.pfnDlgProc = _DrvGeneralDlgProc,
  1524. lstrcpyn(dpsp.szDrive, szPath, ARRAYSIZE(dpsp.szDrive));
  1525. dpsp.iDrive = DRIVEID(szPath);
  1526. // if more than one drive selected give each tab the title of the drive
  1527. // otherwise use "General"
  1528. if (cItems > 1)
  1529. {
  1530. CMountPoint* pMtPt = CMountPoint::GetMountPoint(dpsp.iDrive);
  1531. if (pMtPt)
  1532. {
  1533. dpsp.psp.dwFlags = PSP_USETITLE;
  1534. dpsp.psp.pszTitle = szTitle;
  1535. pMtPt->GetDisplayName(szTitle, ARRAYSIZE(szTitle));
  1536. pMtPt->Release();
  1537. }
  1538. }
  1539. if (!CDrives_AddPage(&dpsp.psp, pfnAddPage, lParam))
  1540. break;
  1541. // if only one property page added add the disk tools
  1542. // and Hardware tab too...
  1543. if (cItems == 1)
  1544. {
  1545. CDrives_AddPagesHelper(&dpsp,
  1546. RealDriveType(dpsp.iDrive, FALSE /* fOKToHitNet */),
  1547. pfnAddPage,
  1548. lParam);
  1549. }
  1550. }
  1551. ReleaseStgMedium(&medium);
  1552. }
  1553. else
  1554. {
  1555. // try mounteddrive
  1556. fmte.cfFormat = g_cfMountedVolume;
  1557. // Can we retrieve the MountedVolume format?
  1558. if (SUCCEEDED(pdtobj->GetData(&fmte, &medium)))
  1559. {
  1560. // Yes
  1561. DRIVEPROPSHEETPAGE dpsp = {0};
  1562. HPROPSHEETPAGE hpage;
  1563. TCHAR szMountPoint[MAX_PATH];
  1564. dpsp.psp.dwSize = sizeof(dpsp); // extra data
  1565. dpsp.psp.dwFlags = PSP_DEFAULT;
  1566. dpsp.psp.hInstance = HINST_THISDLL;
  1567. dpsp.psp.pszTemplate = MAKEINTRESOURCE(DLG_DRV_GENERAL);
  1568. dpsp.psp.pfnDlgProc = _DrvGeneralDlgProc,
  1569. dpsp.iDrive = -1;
  1570. dpsp.fMountedDrive = TRUE;
  1571. DragQueryFile((HDROP)medium.hGlobal, 0, szMountPoint, ARRAYSIZE(szMountPoint));
  1572. lstrcpyn(dpsp.szDrive, szMountPoint, ARRAYSIZE(dpsp.szDrive));
  1573. hpage = CreatePropertySheetPage(&dpsp.psp);
  1574. if (hpage)
  1575. {
  1576. if (!pfnAddPage(hpage, lParam))
  1577. {
  1578. DestroyPropertySheetPage(hpage);
  1579. }
  1580. }
  1581. // Disk tools page
  1582. CMountPoint* pMtPt = CMountPoint::GetMountPoint(szMountPoint);
  1583. if (pMtPt)
  1584. {
  1585. CDrives_AddPagesHelper(&dpsp, GetDriveType(szMountPoint),
  1586. pfnAddPage, lParam);
  1587. pMtPt->Release();
  1588. }
  1589. ReleaseStgMedium(&medium);
  1590. }
  1591. }
  1592. return S_OK;
  1593. }