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.

964 lines
28 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #include <dobjutil.h>
  4. #include <regstr.h>
  5. #include <strsafe.h>
  6. #include "cputil.h"
  7. #include <strsafe.h>
  8. #define REGSTR_EXPLORER_ADVANCED (REGSTR_PATH_EXPLORER TEXT("\\Advanced"))
  9. HRESULT CFolder_Create2(HWND hwnd, LPCITEMIDLIST pidl, IShellFolder *psf, CFolder **ppsdf)
  10. {
  11. HRESULT hr;
  12. CFolder *psdf = new CFolder(hwnd);
  13. if (psdf)
  14. {
  15. hr = psdf->Init(pidl, psf);
  16. if (SUCCEEDED(hr))
  17. *ppsdf = psdf;
  18. else
  19. {
  20. psdf->Release();
  21. psdf = NULL;
  22. }
  23. }
  24. else
  25. hr = E_OUTOFMEMORY;
  26. return hr;
  27. }
  28. HRESULT CFolder_Create(HWND hwnd, LPCITEMIDLIST pidl, IShellFolder *psf, REFIID riid, void **ppv)
  29. {
  30. *ppv = NULL;
  31. CFolder *psdf;
  32. HRESULT hr = CFolder_Create2(hwnd, pidl, psf, &psdf);
  33. if (SUCCEEDED(hr))
  34. {
  35. hr = psdf->QueryInterface(riid, ppv);
  36. psdf->Release();
  37. }
  38. return hr;
  39. }
  40. // HRESULT CFolder_Create(HWND hwnd, LPITEMIDLIST pidl, IShellFolder *psf, CFolder **ppsdf)
  41. CFolder::CFolder(HWND hwnd) :
  42. _cRef(1), _hwnd(hwnd), _pidl(NULL), _psf(NULL), _psf2(NULL),
  43. CImpIDispatch(SDSPATCH_TYPELIB, IID_Folder3)
  44. {
  45. _fmt = 0;
  46. // Be sure that the OS is supporting the flags DATE_LTRREADING and DATE_RTLREADING
  47. if (g_bBiDiPlatform)
  48. {
  49. // Get the date format reading order
  50. LCID locale = GetUserDefaultLCID();
  51. if ( (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_ARABIC))
  52. {
  53. //Get the real list view windows ExStyle.
  54. // [msadek]; we shouldn't check for either WS_EX_RTLREADING OR RTL_MIRRORED_WINDOW
  55. // on localized builds we have both of them to display dirve letters,..etc correctly
  56. // on enabled builds we have none of them. let's check on RTL_MIRRORED_WINDOW only
  57. DWORD dwExStyle = GetWindowLong(_hwnd, GWL_EXSTYLE);
  58. if (dwExStyle & RTL_MIRRORED_WINDOW)
  59. _fmt = LVCFMT_RIGHT_TO_LEFT;
  60. else
  61. _fmt = LVCFMT_LEFT_TO_RIGHT;
  62. }
  63. }
  64. DllAddRef();
  65. }
  66. CFolder::~CFolder(void)
  67. {
  68. ATOMICRELEASE(_psd);
  69. ATOMICRELEASE(_psf2);
  70. ATOMICRELEASE(_psf);
  71. ATOMICRELEASE(_punkOwner);
  72. if (_pidl)
  73. ILFree(_pidl);
  74. // If we created an Application object release its site object...
  75. if (_pidApp)
  76. {
  77. IUnknown_SetSite(SAFECAST(_pidApp, IUnknown*), NULL);
  78. _pidApp->Release();
  79. }
  80. DllRelease();
  81. }
  82. STDMETHODIMP CFolder::SetSite(IUnknown *punkSite)
  83. {
  84. IUnknown_SetSite(SAFECAST(_pidApp, IUnknown*), punkSite);
  85. return CObjectWithSite::SetSite(punkSite);
  86. }
  87. STDMETHODIMP CFolder::SetOwner(IUnknown* punkOwner)
  88. {
  89. IUnknown_Set(&_punkOwner, punkOwner);
  90. return S_OK;
  91. }
  92. HRESULT CFolder::Init(LPCITEMIDLIST pidl, IShellFolder *psf)
  93. {
  94. HRESULT hr = SHILClone(pidl, &_pidl);
  95. if (SUCCEEDED(hr))
  96. {
  97. _psf = psf;
  98. if (_psf)
  99. _psf->AddRef();
  100. else
  101. hr = SHBindToObject(NULL, IID_X_PPV_ARG(IShellFolder, _pidl, &_psf));
  102. if (_psf)
  103. _psf->QueryInterface(IID_PPV_ARG(IShellFolder2, &_psf2));
  104. }
  105. return hr;
  106. }
  107. STDMETHODIMP CFolder::QueryInterface(REFIID riid, void **ppv)
  108. {
  109. static const QITAB qit[] = {
  110. QITABENT(CFolder, Folder3),
  111. QITABENTMULTI(CFolder, Folder, Folder3),
  112. QITABENTMULTI(CFolder, Folder2, Folder3),
  113. QITABENTMULTI(CFolder, IDispatch, Folder3),
  114. QITABENTMULTI(CFolder, IPersist, IPersistFolder2),
  115. QITABENTMULTI(CFolder, IPersistFolder, IPersistFolder2),
  116. QITABENT(CFolder, IPersistFolder2),
  117. QITABENT(CFolder, IObjectSafety),
  118. QITABENT(CFolder, IObjectWithSite),
  119. QITABENT(CFolder, IShellService),
  120. { 0 },
  121. };
  122. return QISearch(this, qit, riid, ppv);
  123. }
  124. STDMETHODIMP_(ULONG) CFolder::AddRef(void)
  125. {
  126. return InterlockedIncrement(&_cRef);
  127. }
  128. STDMETHODIMP_(ULONG) CFolder::Release(void)
  129. {
  130. ASSERT( 0 != _cRef );
  131. ULONG cRef = InterlockedDecrement(&_cRef);
  132. if ( 0 == cRef )
  133. {
  134. delete this;
  135. }
  136. return cRef;
  137. }
  138. HRESULT CFolder::_Application(IDispatch **ppid)
  139. {
  140. HRESULT hr = _SecurityCheck();
  141. if (SUCCEEDED(hr))
  142. {
  143. hr = CShellDispatch_CreateInstance(NULL, IID_PPV_ARG(IDispatch, ppid));
  144. if (SUCCEEDED(hr))
  145. {
  146. IUnknown_SetSite(*ppid, _punkSite);
  147. if (_dwSafetyOptions)
  148. hr = MakeSafeForScripting((IUnknown**)ppid);
  149. }
  150. }
  151. return hr;
  152. }
  153. // Folder implementation
  154. STDMETHODIMP CFolder::get_Application(IDispatch **ppid)
  155. {
  156. *ppid = NULL;
  157. if (!_pidApp)
  158. _Application(&_pidApp);
  159. return _pidApp ? _pidApp->QueryInterface(IID_PPV_ARG(IDispatch, ppid)) : E_FAIL;
  160. }
  161. STDMETHODIMP CFolder::get_Parent(IDispatch **ppid)
  162. {
  163. *ppid = NULL;
  164. return E_NOTIMPL;
  165. }
  166. // returns:
  167. // S_OK - success
  168. // S_FALSE - failure, but not a script error
  169. STDMETHODIMP CFolder::_ParentFolder(Folder **ppdf)
  170. {
  171. *ppdf = NULL; // assume error
  172. if (ILIsEmpty(_pidl))
  173. return S_FALSE; // automation compat, let script check error
  174. LPITEMIDLIST pidl;
  175. HRESULT hr = SHILClone(_pidl, &pidl);
  176. if (SUCCEEDED(hr))
  177. {
  178. ILRemoveLastID(pidl);
  179. hr = CFolder_Create(_hwnd, pidl, NULL, IID_PPV_ARG(Folder, ppdf));
  180. if (SUCCEEDED(hr))
  181. {
  182. IUnknown_SetSite(*ppdf, _punkSite);
  183. if (_dwSafetyOptions)
  184. {
  185. hr = MakeSafeForScripting((IUnknown**)ppdf);
  186. }
  187. }
  188. ILFree(pidl);
  189. }
  190. return hr;
  191. }
  192. HRESULT CFolder::_SecurityCheck()
  193. {
  194. return (!_dwSafetyOptions || (IsSafePage(_punkSite) == S_OK)) ? S_OK : E_ACCESSDENIED;
  195. }
  196. STDMETHODIMP CFolder::get_ParentFolder(Folder **ppdf)
  197. {
  198. *ppdf = NULL; // assume error
  199. HRESULT hr = _SecurityCheck();
  200. if (SUCCEEDED(hr))
  201. {
  202. hr = _ParentFolder(ppdf);
  203. }
  204. return hr;
  205. }
  206. STDMETHODIMP CFolder::get_Title(BSTR *pbs)
  207. {
  208. *pbs = NULL;
  209. HRESULT hr = _SecurityCheck();
  210. if (SUCCEEDED(hr))
  211. {
  212. SHFILEINFO sfi;
  213. if (SHGetFileInfo((LPCTSTR)_pidl, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME | SHGFI_PIDL))
  214. *pbs = SysAllocStringT(sfi.szDisplayName);
  215. hr = S_OK;
  216. }
  217. return hr;
  218. }
  219. IShellDetails * CFolder::_GetShellDetails(void)
  220. {
  221. if (!_psd)
  222. {
  223. if (_psf)
  224. _psf->CreateViewObject(_hwnd, IID_PPV_ARG(IShellDetails, &_psd));
  225. }
  226. return _psd;
  227. }
  228. STDMETHODIMP CFolder::Items(FolderItems **ppid)
  229. {
  230. *ppid = NULL;
  231. HRESULT hr = _SecurityCheck();
  232. if (SUCCEEDED(hr))
  233. {
  234. hr = CFolderItems_Create(this, FALSE, ppid);
  235. if (SUCCEEDED(hr))
  236. {
  237. IUnknown_SetSite(*ppid, _punkSite);
  238. if (_dwSafetyOptions)
  239. {
  240. hr = MakeSafeForScripting((IUnknown**)ppid);
  241. }
  242. }
  243. }
  244. return hr;
  245. }
  246. STDMETHODIMP CFolder::ParseName(BSTR bName, FolderItem **ppfi)
  247. {
  248. *ppfi = NULL;
  249. // lets be strict here and not allow them to do much...
  250. HRESULT hr = _SecurityCheck();
  251. if (SUCCEEDED(hr))
  252. {
  253. ULONG chEaten;
  254. LPITEMIDLIST pidl;
  255. hr = _psf->ParseDisplayName(_hwnd, NULL, bName, &chEaten, &pidl, NULL);
  256. if (SUCCEEDED(hr))
  257. {
  258. LPITEMIDLIST pidlLast = ILFindLastID(pidl);
  259. if (pidlLast == pidl)
  260. {
  261. hr = CFolderItem_Create(this, pidl, ppfi);
  262. }
  263. else
  264. {
  265. LPITEMIDLIST pidlFull = ILCombine(_pidl, pidl);
  266. if (pidlFull)
  267. {
  268. CFolderItem_CreateFromIDList(_hwnd, pidlFull, ppfi);
  269. ILFree(pidlFull);
  270. }
  271. else
  272. hr = E_OUTOFMEMORY;
  273. }
  274. ILFree(pidl);
  275. }
  276. if (hr != S_OK) // Scripts barf on errors returned
  277. {
  278. ppfi = NULL;
  279. hr = S_FALSE;
  280. }
  281. }
  282. return hr;
  283. }
  284. STDMETHODIMP CFolder::NewFolder(BSTR bName, VARIANT vOptions)
  285. {
  286. HRESULT hr = _SecurityCheck();
  287. if (SUCCEEDED(hr))
  288. {
  289. IStorage *pstg;
  290. hr = SHBindToObject(NULL, IID_X_PPV_ARG(IStorage, _pidl, &pstg));
  291. if (SUCCEEDED(hr))
  292. {
  293. IStorage *pstgNew;
  294. hr = pstg->CreateStorage(bName, STGM_FAILIFTHERE, 0, 0, &pstgNew);
  295. if (SUCCEEDED(hr))
  296. {
  297. pstgNew->Release();
  298. }
  299. else if (STG_E_FILEALREADYEXISTS == hr)
  300. {
  301. hr = S_OK;
  302. }
  303. pstg->Release();
  304. }
  305. }
  306. return hr;
  307. }
  308. STDMETHODIMP CFolder::MoveHere(VARIANT vItem, VARIANT vOptions)
  309. {
  310. return _MoveOrCopy(TRUE, vItem, vOptions);
  311. }
  312. STDMETHODIMP CFolder::CopyHere(VARIANT vItem, VARIANT vOptions)
  313. {
  314. return _MoveOrCopy(FALSE, vItem, vOptions);
  315. }
  316. // get the IDList for an item from a VARIANT that is a FolderItem dispatch object
  317. STDMETHODIMP CFolder::GetDetailsOf(VARIANT vItem, int iColumn, BSTR *pbs)
  318. {
  319. *pbs = NULL;
  320. HRESULT hr = _SecurityCheck();
  321. if (SUCCEEDED(hr))
  322. {
  323. TCHAR szBuf[INFOTIPSIZE];
  324. szBuf[0] = 0;
  325. LPCITEMIDLIST pidl = CFolderItem::_GetIDListFromVariant(&vItem); // returns an ALIAS
  326. if (iColumn == -1) // infotip for the item
  327. {
  328. if (pidl)
  329. GetInfoTipHelp(_psf, pidl, szBuf, ARRAYSIZE(szBuf));
  330. }
  331. else
  332. {
  333. BOOL bUseDetails;
  334. SHELLDETAILS sd;
  335. sd.fmt = _fmt;
  336. sd.str.uType = STRRET_CSTR;
  337. sd.str.cStr[0] = 0;
  338. if (_psf2)
  339. bUseDetails = (E_NOTIMPL == _psf2->GetDetailsOf(pidl, iColumn, &sd));
  340. else
  341. bUseDetails = TRUE;
  342. if (bUseDetails)
  343. {
  344. IShellDetails* psd = _GetShellDetails();
  345. if (psd)
  346. psd->GetDetailsOf(pidl, iColumn, &sd);
  347. }
  348. StrRetToBuf(&sd.str, pidl, szBuf, ARRAYSIZE(szBuf));
  349. }
  350. *pbs = SysAllocStringT(szBuf);
  351. hr = *pbs ? S_OK : E_OUTOFMEMORY;
  352. }
  353. return hr;
  354. }
  355. HRESULT CFolder::get_Self(FolderItem **ppfi)
  356. {
  357. *ppfi = NULL;
  358. HRESULT hr = _SecurityCheck();
  359. if (SUCCEEDED(hr))
  360. {
  361. Folder *psdf;
  362. if (ILIsEmpty(_pidl))
  363. {
  364. psdf = this;
  365. psdf->AddRef();
  366. hr = S_OK;
  367. }
  368. else
  369. hr = _ParentFolder(&psdf);
  370. if (SUCCEEDED(hr))
  371. {
  372. hr = CFolderItem_Create((CFolder*)psdf, ILFindLastID(_pidl), ppfi);
  373. if (SUCCEEDED(hr) && _dwSafetyOptions)
  374. hr = MakeSafeForScripting((IUnknown**)ppfi);
  375. psdf->Release();
  376. }
  377. else
  378. *ppfi = NULL;
  379. }
  380. return hr;
  381. }
  382. BOOL _VerifyUNC(LPTSTR psz, ULONG cch)
  383. {
  384. if (PathIsUNC(psz))
  385. {
  386. return TRUE;
  387. }
  388. else if (psz[1] == TEXT(':'))
  389. {
  390. TCHAR szLocalName[3] = { psz[0], psz[1], TEXT('\0') };
  391. // Call GetDriveType before WNetGetConnection, to avoid loading
  392. // MPR.DLL unless absolutely necessary.
  393. if (DRIVE_REMOTE == GetDriveType(szLocalName) &&
  394. S_OK == WNetGetConnection(szLocalName, psz, &cch))
  395. {
  396. return TRUE;
  397. }
  398. }
  399. return FALSE;
  400. }
  401. HRESULT GetSharePath(LPCITEMIDLIST pidl, LPTSTR psz, ULONG cch)
  402. {
  403. HRESULT hr = E_FAIL;
  404. if (SHGetPathFromIDList(pidl, psz))
  405. {
  406. if (_VerifyUNC(psz, cch))
  407. hr = S_OK;
  408. else
  409. {
  410. // check for folder shortcuts.
  411. IShellFolder *psf;
  412. if (SUCCEEDED(SHBindToObject(NULL, IID_X_PPV_ARG(IShellFolder, pidl, &psf))))
  413. {
  414. IShellLink *psl;
  415. if (SUCCEEDED(psf->QueryInterface(IID_PPV_ARG(IShellLink, &psl))))
  416. {
  417. if (SUCCEEDED(psl->GetPath(psz, cch, NULL, 0))
  418. && _VerifyUNC(psz, cch))
  419. hr = S_OK;
  420. psl->Release();
  421. }
  422. psf->Release();
  423. }
  424. }
  425. if (SUCCEEDED(hr))
  426. PathStripToRoot(psz);
  427. }
  428. return hr;
  429. }
  430. #include <cscuiext.h>
  431. STDMETHODIMP CFolder::get_OfflineStatus(LONG *pul)
  432. {
  433. HRESULT hr = _SecurityCheck();
  434. if (SUCCEEDED(hr))
  435. {
  436. TCHAR szShare[MAX_PATH];
  437. *pul = OFS_INACTIVE; // default
  438. // Make sure we have a UNC \\server\share path. Do this before
  439. // checking whether CSC is enabled, to avoid loading CSCDLL.DLL
  440. // unless absolutely necessary.
  441. if (SUCCEEDED(GetSharePath(_pidl, szShare, ARRAYSIZE(szShare))))
  442. {
  443. *pul = GetOfflineShareStatus(szShare);
  444. }
  445. hr = S_OK;
  446. }
  447. return hr;
  448. }
  449. STDMETHODIMP CFolder::Synchronize(void)
  450. {
  451. HRESULT hr = _SecurityCheck();
  452. if (SUCCEEDED(hr))
  453. {
  454. HWND hwndCSCUI = FindWindow(STR_CSCHIDDENWND_CLASSNAME, NULL);
  455. if (hwndCSCUI)
  456. PostMessage(hwndCSCUI, CSCWM_SYNCHRONIZE, 0, 0);
  457. hr = S_OK;
  458. }
  459. return hr;
  460. }
  461. #define REGSTR_WEBVIEW_BARRICADEDFOLDERS (REGSTR_PATH_EXPLORER TEXT("\\WebView\\BarricadedFolders"))
  462. #define REGSTR_VALUE_BARRICADE TEXT("WebViewBarricade")
  463. #define SHELL_ENTIRENET TEXT("shell:EntireNetwork")
  464. #define SHELL_SYSROOT TEXT("shell:SystemDriveRootFolder")
  465. #define SHELL_CPLFLDR TEXT("shell:ControlPanelFolder")
  466. BOOL GetBarricadeValueNameFromPidl(LPCITEMIDLIST pidl, LPTSTR pszValueName, UINT cch)
  467. {
  468. ASSERT(cch > (UINT)lstrlen(SHELL_ENTIRENET) &&
  469. cch > (UINT)lstrlen(SHELL_SYSROOT) &&
  470. cch > (UINT)lstrlen(SHELL_CPLFLDR));
  471. pszValueName[0] = TEXT('\0');
  472. TCHAR szPath[MAX_PATH];
  473. if (SUCCEEDED(SHGetNameAndFlags(pidl, SHGDN_FORPARSING, szPath, ARRAYSIZE(szPath), NULL)))
  474. {
  475. if (!MakeShellURLFromPath(szPath, pszValueName, cch))
  476. {
  477. HRESULT hr;
  478. if (lstrcmp(szPath, TEXT("EntireNetwork")) == 0)
  479. {
  480. hr = StringCchCopy(pszValueName, cch, SHELL_ENTIRENET);
  481. if (FAILED(hr))
  482. {
  483. pszValueName[0] = '\0';
  484. }
  485. }
  486. else if (PathIsRoot(szPath))
  487. {
  488. TCHAR szSystemDir[MAX_PATH];
  489. szSystemDir[0] = TEXT('\0');
  490. GetWindowsDirectory(szSystemDir, ARRAYSIZE(szSystemDir));
  491. if (PathIsSameRoot(szPath, szSystemDir))
  492. {
  493. hr = StringCchCopy(pszValueName, cch, SHELL_SYSROOT);
  494. if (FAILED(hr))
  495. {
  496. pszValueName[0] = '\0';
  497. }
  498. }
  499. }
  500. else
  501. {
  502. LPITEMIDLIST pidlTemp = NULL;
  503. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlTemp)))
  504. {
  505. if (ILIsEqual(pidl, pidlTemp))
  506. {
  507. hr = StringCchCopy(pszValueName, cch, SHELL_CPLFLDR);
  508. if (FAILED(hr))
  509. {
  510. pszValueName[0] = '\0';
  511. }
  512. }
  513. ILFree(pidlTemp);
  514. }
  515. }
  516. }
  517. }
  518. return BOOLIFY(pszValueName[0]);
  519. }
  520. BOOL IsBarricadeGloballyOff()
  521. {
  522. return SHRegGetBoolUSValue(REGSTR_EXPLORER_ADVANCED, REGSTR_VALUE_BARRICADE, FALSE, FALSE);
  523. }
  524. VARIANT_BOOL GetBarricadeStatus(LPCTSTR pszValueName)
  525. {
  526. VARIANT_BOOL bShowBarricade;
  527. if (!SHRegGetBoolUSValue(REGSTR_WEBVIEW_BARRICADEDFOLDERS, pszValueName, FALSE, TRUE))
  528. {
  529. bShowBarricade = VARIANT_FALSE; // ==> Don't show the barricade
  530. }
  531. else
  532. {
  533. bShowBarricade = VARIANT_TRUE;
  534. }
  535. return bShowBarricade;
  536. }
  537. STDMETHODIMP CFolder::get_ShowWebViewBarricade(VARIANT_BOOL *pbShowWebViewBarricade)
  538. {
  539. HRESULT hr = _SecurityCheck();
  540. if (SUCCEEDED(hr))
  541. {
  542. VARIANT_BOOL bShowBarricade = VARIANT_FALSE;
  543. //
  544. // Control panel is a special case.
  545. // The barricade is used to represent 'category view' which can
  546. // be turned on/off by the user and also by global webview settings.
  547. // To determine the true barricade status, we ask the control panel
  548. // code if the new 'category' view is active.
  549. //
  550. BOOL bIsControlPanel = FALSE;
  551. LPITEMIDLIST pidlControlPanel;
  552. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlControlPanel)))
  553. {
  554. bIsControlPanel = ILIsEqual(_pidl, pidlControlPanel);
  555. ILFree (pidlControlPanel);
  556. }
  557. if (bIsControlPanel)
  558. {
  559. //
  560. // When someone wants' to know if control panel's barricade is on,
  561. // they really want to know if it's configured for 'category' view.
  562. //
  563. if (CPL::CategoryViewIsActive(NULL))
  564. {
  565. bShowBarricade = VARIANT_TRUE;
  566. }
  567. }
  568. else
  569. {
  570. TCHAR szValueName[MAX_PATH];
  571. if (GetBarricadeValueNameFromPidl(_pidl, szValueName, ARRAYSIZE(szValueName)))
  572. {
  573. bShowBarricade = GetBarricadeStatus(szValueName);
  574. }
  575. }
  576. *pbShowWebViewBarricade = bShowBarricade;
  577. hr = S_OK;
  578. }
  579. return hr;
  580. }
  581. STDMETHODIMP CFolder::get_HaveToShowWebViewBarricade(VARIANT_BOOL *pbHaveToShowWebViewBarricade)
  582. {
  583. return get_ShowWebViewBarricade(pbHaveToShowWebViewBarricade);
  584. }
  585. HRESULT SetBarricadeStatus(LPCTSTR pszValueName, VARIANT_BOOL bShowBarricade)
  586. {
  587. HRESULT hr = E_FAIL;
  588. DWORD dwBarricade = (bShowBarricade == VARIANT_FALSE) ? 0 : 1;
  589. if (dwBarricade)
  590. {
  591. DWORD dw = 0; // Unset "Barricade off for all folders" key
  592. SHRegSetUSValue(REGSTR_EXPLORER_ADVANCED, REGSTR_VALUE_BARRICADE, REG_DWORD, (void *)&dw, sizeof(dw), SHREGSET_FORCE_HKCU);
  593. }
  594. if (SHRegSetUSValue(REGSTR_WEBVIEW_BARRICADEDFOLDERS, pszValueName, REG_DWORD, (void *)&dwBarricade, sizeof(dwBarricade), SHREGSET_FORCE_HKCU) == ERROR_SUCCESS)
  595. {
  596. hr = S_OK;
  597. }
  598. return hr;
  599. }
  600. STDMETHODIMP CFolder::put_ShowWebViewBarricade(VARIANT_BOOL bShowWebViewBarricade)
  601. {
  602. HRESULT hr = _SecurityCheck();
  603. if (SUCCEEDED(hr))
  604. {
  605. // First, see if it is the root of the system drive
  606. TCHAR szValueName[MAX_PATH];
  607. if (GetBarricadeValueNameFromPidl(_pidl, szValueName, ARRAYSIZE(szValueName)))
  608. {
  609. SetBarricadeStatus(szValueName, bShowWebViewBarricade);
  610. }
  611. }
  612. return hr;
  613. }
  614. STDMETHODIMP CFolder::DismissedWebViewBarricade()
  615. {
  616. return put_ShowWebViewBarricade(VARIANT_FALSE);
  617. }
  618. HRESULT GetUIObjectFromVariant(VARIANT vItems, HWND hwnd, REFIID riid, void **ppv)
  619. {
  620. *ppv = NULL;
  621. HRESULT hr = E_FAIL;
  622. LPITEMIDLIST pidl = VariantToIDList(&vItems);
  623. if (pidl)
  624. {
  625. hr = SHGetUIObjectFromFullPIDL(pidl, hwnd, riid, ppv);
  626. ILFree(pidl);
  627. }
  628. else
  629. {
  630. if (vItems.vt == (VT_BYREF | VT_VARIANT) && vItems.pvarVal)
  631. vItems = *vItems.pvarVal;
  632. FolderItems *pfis;
  633. if ((VT_DISPATCH == vItems.vt) && vItems.pdispVal &&
  634. SUCCEEDED(vItems.pdispVal->QueryInterface(IID_PPV_ARG(FolderItems, &pfis))))
  635. {
  636. long cItems;
  637. if (S_OK == pfis->get_Count(&cItems) && cItems)
  638. {
  639. LPITEMIDLIST *ppidl = (LPITEMIDLIST *)LocalAlloc(LPTR, sizeof(*ppidl) * cItems);
  640. if (ppidl)
  641. {
  642. IShellFolder *psf = NULL;
  643. VARIANT v = {VT_I4};
  644. for (v.lVal = 0; v.lVal < cItems; v.lVal++)
  645. {
  646. FolderItem *pfi;
  647. if (SUCCEEDED(pfis->Item(v, &pfi)) && pfi)
  648. {
  649. IParentAndItem *pfai;
  650. if (SUCCEEDED(pfi->QueryInterface(IID_PPV_ARG(IParentAndItem, &pfai))))
  651. {
  652. pfai->GetParentAndItem(NULL, 0 == v.lVal ? &psf : NULL, &(ppidl[v.lVal]));
  653. pfai->Release();
  654. }
  655. pfi->Release();
  656. }
  657. }
  658. if (psf)
  659. {
  660. hr = psf->GetUIObjectOf(hwnd, cItems, (LPCITEMIDLIST *)ppidl, riid, NULL, ppv);
  661. psf->Release();
  662. }
  663. for (v.lVal = 0; v.lVal < cItems; v.lVal++)
  664. {
  665. ILFree(ppidl[v.lVal]);
  666. }
  667. LocalFree(ppidl);
  668. }
  669. }
  670. pfis->Release();
  671. }
  672. }
  673. return hr;
  674. }
  675. DWORD VariantToDWORD(VARIANT vOptions)
  676. {
  677. DWORD dw = 0;
  678. if (vOptions.vt == (VT_BYREF | VT_VARIANT) && vOptions.pvarVal)
  679. vOptions = *vOptions.pvarVal;
  680. // We need to get the source files out of the variant.
  681. // Currently support string, or IDispatch (Either FolderItem or FolderItems)
  682. switch (vOptions.vt)
  683. {
  684. case VT_I2:
  685. dw = (FILEOP_FLAGS)vOptions.iVal;
  686. break;
  687. case VT_I4:
  688. dw = (FILEOP_FLAGS)vOptions.lVal;
  689. break;
  690. }
  691. return dw;
  692. }
  693. // Main function to do Move or Copy
  694. HRESULT CFolder::_MoveOrCopy(BOOL bMove, VARIANT vItems, VARIANT vOptions)
  695. {
  696. HRESULT hr = _SecurityCheck();
  697. if (SUCCEEDED(hr))
  698. {
  699. IDropTarget *pdtgt;
  700. hr = _psf->CreateViewObject(_hwnd, IID_PPV_ARG(IDropTarget, &pdtgt));
  701. if (SUCCEEDED(hr))
  702. {
  703. IUnknown_SetSite(pdtgt, _punkSite);
  704. IDataObject *pdtobj;
  705. hr = GetUIObjectFromVariant(vItems, _hwnd, IID_PPV_ARG(IDataObject, &pdtobj));
  706. if (SUCCEEDED(hr))
  707. {
  708. FILEOP_FLAGS fof = (FILEOP_FLAGS)VariantToDWORD(vOptions);
  709. if (fof)
  710. {
  711. static UINT s_cfFileOpFlags = 0;
  712. if (0 == s_cfFileOpFlags)
  713. s_cfFileOpFlags = RegisterClipboardFormat(TEXT("FileOpFlags"));
  714. DataObj_SetDWORD(pdtobj, s_cfFileOpFlags, fof);
  715. }
  716. DWORD grfKeyState = bMove ? MK_SHIFT | MK_LBUTTON : MK_CONTROL | MK_LBUTTON;
  717. hr = SHSimulateDrop(pdtgt, pdtobj, grfKeyState, NULL, NULL);
  718. pdtobj->Release();
  719. }
  720. IUnknown_SetSite(pdtgt, NULL);
  721. pdtgt->Release();
  722. }
  723. hr = SUCCEEDED(hr) ? S_OK : S_FALSE;
  724. }
  725. return hr;
  726. }
  727. STDMETHODIMP CFolder::GetClassID(CLSID *pClassID)
  728. {
  729. return E_NOTIMPL;
  730. }
  731. STDMETHODIMP CFolder::Initialize(LPCITEMIDLIST pidl)
  732. {
  733. return E_NOTIMPL;
  734. }
  735. STDMETHODIMP CFolder::GetCurFolder(LPITEMIDLIST *ppidl)
  736. {
  737. return SHILClone(_pidl, ppidl);
  738. }
  739. HRESULT CFolder::InvokeVerbHelper(VARIANT vVerb, VARIANT vArgs, LPCITEMIDLIST *ppidl, int cItems, DWORD dwSafetyOptions)
  740. {
  741. if (!dwSafetyOptions || (_SecurityCheck() == S_OK))
  742. {
  743. BOOL fDefaultVerb = TRUE;
  744. TCHAR szCmd[128];
  745. switch (vVerb.vt)
  746. {
  747. case VT_BSTR:
  748. fDefaultVerb = FALSE;
  749. SHUnicodeToTChar(vVerb.bstrVal, szCmd, ARRAYSIZE(szCmd));
  750. break;
  751. }
  752. HRESULT hr = S_OK;
  753. IContextMenu *pcm;
  754. if (SUCCEEDED(_psf->GetUIObjectOf(_hwnd, cItems, ppidl, IID_PPV_ARG_NULL(IContextMenu, &pcm))))
  755. {
  756. IShellFolderView *psfv;
  757. if (SUCCEEDED(GetShellFolderView(&psfv)))
  758. {
  759. IUnknown_SetSite(pcm, psfv);
  760. }
  761. else
  762. {
  763. ASSERT(NULL == psfv);
  764. }
  765. MENUITEMINFO mii;
  766. HMENU hmenu = CreatePopupMenu();
  767. if (NULL != hmenu)
  768. {
  769. pcm->QueryContextMenu(hmenu, 0, CONTEXTMENU_IDCMD_FIRST, CONTEXTMENU_IDCMD_LAST, fDefaultVerb ? CMF_DEFAULTONLY : CMF_CANRENAME);
  770. int idCmd = 0;
  771. if (fDefaultVerb)
  772. idCmd = GetMenuDefaultItem(hmenu, MF_BYCOMMAND, 0);
  773. else
  774. {
  775. // REVIEW: this should never have been done this way. Can we rip it out?
  776. //
  777. // find a verb that matches name by display name (ugly)
  778. for (int i = GetMenuItemCount(hmenu) - 1; i >= 0; i--)
  779. {
  780. TCHAR szText[128]; // should be big enough for this
  781. mii.cbSize = sizeof(MENUITEMINFO);
  782. mii.dwTypeData = szText;
  783. mii.fMask = MIIM_ID | MIIM_TYPE;
  784. mii.cch = ARRAYSIZE(szText);
  785. mii.fType = MFT_SEPARATOR; // to avoid ramdom result.
  786. mii.dwItemData = 0;
  787. GetMenuItemInfo(hmenu, i, TRUE, &mii);
  788. if (lstrcmpi(szText, szCmd) == 0)
  789. {
  790. idCmd = mii.wID;
  791. break;
  792. }
  793. }
  794. }
  795. if (!idCmd)
  796. {
  797. // that didn't work, find it the right way by the canonical verb name
  798. int iItem = GetMenuIndexForCanonicalVerb(hmenu, pcm, CONTEXTMENU_IDCMD_FIRST, vVerb.bstrVal);
  799. if (-1 != iItem)
  800. {
  801. mii.cbSize = sizeof(MENUITEMINFO);
  802. mii.fMask = MIIM_ID;
  803. if (GetMenuItemInfo(hmenu, iItem, MF_BYPOSITION, &mii))
  804. idCmd = mii.wID;
  805. }
  806. }
  807. if (idCmd)
  808. {
  809. CMINVOKECOMMANDINFO ici = {
  810. sizeof(CMINVOKECOMMANDINFO),
  811. 0L,
  812. _hwnd,
  813. NULL,
  814. NULL, NULL,
  815. SW_SHOWNORMAL,
  816. };
  817. ici.lpVerb = (LPSTR)MAKEINTRESOURCE(idCmd - CONTEXTMENU_IDCMD_FIRST);
  818. char szArgs[MAX_PATH]; // max size we will currently use.
  819. // See if we are supposed to pass any arguments on the command line
  820. switch (vArgs.vt)
  821. {
  822. case VT_BSTR:
  823. SHUnicodeToAnsi(vArgs.bstrVal, szArgs, ARRAYSIZE(szArgs));
  824. ici.lpParameters = szArgs;
  825. break;
  826. }
  827. // Finally invoke the command
  828. pcm->InvokeCommand(&ici);
  829. }
  830. DestroyMenu(hmenu);
  831. }
  832. else
  833. {
  834. hr = E_OUTOFMEMORY;
  835. }
  836. if (psfv)
  837. {
  838. IUnknown_SetSite(pcm, NULL);
  839. psfv->Release();
  840. }
  841. pcm->Release();
  842. }
  843. return hr;
  844. }
  845. return E_ACCESSDENIED;
  846. }
  847. HRESULT CFolder::GetShellFolderView(IShellFolderView **ppsfv)
  848. {
  849. return IUnknown_QueryService(_punkOwner, SID_DefView, IID_PPV_ARG(IShellFolderView, ppsfv));
  850. }