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

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