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.

1945 lines
78 KiB

  1. #include "shellprv.h"
  2. #include "filefldr.h"
  3. #include <shellp.h>
  4. #include <shguidp.h>
  5. #include "idlcomm.h"
  6. #include "pidl.h"
  7. #include "views.h"
  8. #include "ids.h"
  9. #include "shitemid.h"
  10. #include "datautil.h"
  11. #include "prop.h"
  12. #include "basefvcb.h"
  13. #include "brutil.h"
  14. #include "enumuicommand.h"
  15. #include "enumidlist.h"
  16. #include "wia.h"
  17. #include "shimgvw.h"
  18. #include "cdburn.h"
  19. #include "foldertypes.h"
  20. #include "htmlhelp.h"
  21. #include "buytasks.h"
  22. #include <crypto\md5.h> // for MD5DIGESTLEN
  23. const SHOP_INFO c_BuySampleMusic = { L"BuyURL", L"http://go.microsoft.com/fwlink/?LinkId=730&clcid={SUB_CLCID}", FALSE};
  24. const SHOP_INFO c_BuyMusic = { L"MusicBuyURL", L"http://go.microsoft.com/fwlink/?LinkId=493&clcid={SUB_CLCID}", TRUE};
  25. const SHOP_INFO c_BuySamplePictures = { L"BuyURL", L"http://go.microsoft.com/fwlink/?LinkId=625&clcid={SUB_CLCID}", TRUE};
  26. class CFSFolderViewCB : public CBaseShellFolderViewCB
  27. {
  28. public:
  29. CFSFolderViewCB(CFSFolder *pfsf);
  30. STDMETHODIMP RealMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
  31. STDMETHODIMP SetSite(IUnknown* pUnkSite);
  32. private:
  33. ~CFSFolderViewCB();
  34. HRESULT OnSize(DWORD pv, UINT cx, UINT cy);
  35. HRESULT OnGetPane(DWORD pv, LPARAM dwPaneID, DWORD *pdwPane);
  36. HRESULT OnGetCCHMax(DWORD pv, LPCITEMIDLIST pidlItem, UINT *pcchMax);
  37. HRESULT OnWindowCreated(DWORD pv, HWND wP);
  38. HRESULT OnInsertDeleteItem(int iMul, LPCITEMIDLIST wP);
  39. HRESULT OnSelChange(DWORD pv, UINT wPl, UINT wPh, SFVM_SELCHANGE_DATA*lP);
  40. HRESULT OnUpdateStatusBar(DWORD pv, BOOL wP);
  41. HRESULT OnRefresh(DWORD pv, BOOL fPreRefresh);
  42. HRESULT OnSelectAll(DWORD pv);
  43. HRESULT OnGetWorkingDir(DWORD pv, UINT wP, LPTSTR lP);
  44. HRESULT OnEnumeratedItems(DWORD pv, UINT celt, LPCITEMIDLIST* rgpidl);
  45. HRESULT OnGetViewData(DWORD pv, UINT uViewMode, SFVM_VIEW_DATA* pvi);
  46. HRESULT OnGetWebViewTemplate(DWORD pv, UINT uViewMode, SFVM_WEBVIEW_TEMPLATE_DATA* pvit);
  47. HRESULT OnGetWebViewLayout(DWORD pv, UINT uViewMode, SFVM_WEBVIEW_LAYOUT_DATA* pData);
  48. HRESULT OnGetWebViewContent(DWORD pv, SFVM_WEBVIEW_CONTENT_DATA* pData);
  49. HRESULT OnGetWebViewTasks(DWORD pv, SFVM_WEBVIEW_TASKSECTION_DATA* pTasks);
  50. HRESULT OnGetWebViewTheme(DWORD pv, SFVM_WEBVIEW_THEME_DATA* pTheme);
  51. HRESULT OnDefViewMode(DWORD pv, FOLDERVIEWMODE*lP);
  52. HRESULT OnGetCustomViewInfo(DWORD pv, SFVM_CUSTOMVIEWINFO_DATA* pData);
  53. HRESULT OnSupportsIdentity(DWORD pv);
  54. HRESULT OnQueryReuseExtView(DWORD pv, BOOL *pfReuseAllowed);
  55. HRESULT OnGetNotify(DWORD pv, LPITEMIDLIST*wP, LONG*lP);
  56. HRESULT OnGetDeferredViewSettings(DWORD pv, SFVM_DEFERRED_VIEW_SETTINGS* pSettings);
  57. BOOL _CollectDefaultFolderState();
  58. PERCEIVED _GetFolderPerceivedType(LPCIDFOLDER pidf);
  59. HRESULT _GetStringForFolderType(int iType, LPWSTR pszFolderType, UINT cchBuf);
  60. BOOL _IsBarricadedFolder();
  61. UINT _cItems;
  62. FSSELCHANGEINFO _fssci;
  63. CFSFolder* _pfsf;
  64. BOOL _fStatusInitialized;
  65. TRIBIT _fHasWIADevices;
  66. IPreview3 * _pPreview;
  67. HRESULT _GetPreview3(IPreview3** ppPreview3);
  68. HRESULT _GetShoppingBrowsePidl(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc, const SHOP_INFO *pShopInfo, LPITEMIDLIST *ppidl);
  69. HRESULT _GetShoppingURL(const SHOP_INFO *pShopInfo, LPTSTR pszURL, DWORD cchURL);
  70. HRESULT _DataObjectFromItemsOrFolder(IShellItemArray *psiItemArray, IDataObject **ppdto);
  71. public:
  72. // webview task implementations:
  73. static HRESULT _HasWiaDevices(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState);
  74. static HRESULT _HasItems(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState);
  75. static HRESULT _CanOrderPrints(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState);
  76. static HRESULT _CanPrintPictures(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState);
  77. static HRESULT _CanBuyPictures(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState);
  78. static HRESULT _CanWallpaper(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState);
  79. static HRESULT _CanPlayMusic(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState);
  80. static HRESULT _CanPlayVideos(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState);
  81. static HRESULT _CanSendToAudioCD(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState);
  82. static HRESULT _CanSendToCD(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState);
  83. static HRESULT _OnCommonDocumentsHelp(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  84. static HRESULT _OnPlayMusic(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  85. static HRESULT _OnPlayVideos(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  86. static HRESULT _OnShopForMusicOnline(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  87. static HRESULT _OnShopForPicturesOnline(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  88. static HRESULT _OnSendToAudioCD(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  89. static HRESULT _OnGetFromCamera(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  90. static HRESULT _OnSlideShow(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  91. static HRESULT _OnWallpaper(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  92. static HRESULT _OnOrderPrints(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  93. static HRESULT _OnPrintPictures(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  94. static HRESULT _OnSendToCD(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc);
  95. static HRESULT _CanPlay(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState, int fDATAOBJCB);
  96. static HRESULT _OnPlay(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc, int fDATAOBJCB);
  97. };
  98. #define FS_EVENTS (SHCNE_DISKEVENTS | SHCNE_ASSOCCHANGED | SHCNE_NETSHARE | SHCNE_NETUNSHARE)
  99. CFSFolderViewCB::CFSFolderViewCB(CFSFolder *pfsf) : CBaseShellFolderViewCB(pfsf->_pidl, FS_EVENTS), _pfsf(pfsf)
  100. {
  101. _pfsf->AddRef();
  102. ZeroMemory(&_fssci, sizeof(_fssci));
  103. // _fssci.szDrive[0] == '\0' means "unknown" / "not available"
  104. _fssci.cbFree = -1; // this field uses -1 to mean
  105. // "unknown" / "not available"
  106. _pPreview = NULL;
  107. ASSERT(!_fStatusInitialized);
  108. }
  109. CFSFolderViewCB::~CFSFolderViewCB()
  110. {
  111. if (_pPreview)
  112. {
  113. IUnknown_SetSite(_pPreview, NULL);
  114. _pPreview->Release();
  115. }
  116. _pfsf->Release();
  117. }
  118. STDMETHODIMP CFSFolderViewCB::SetSite(IUnknown* punkSite)
  119. {
  120. if (_pPreview)
  121. {
  122. IUnknown_SetSite(_pPreview, punkSite);
  123. }
  124. return CBaseShellFolderViewCB::SetSite(punkSite);
  125. }
  126. HRESULT CFSFolderViewCB::OnSize(DWORD pv, UINT cx, UINT cy)
  127. {
  128. ResizeStatus(_punkSite, cx);
  129. return S_OK;
  130. }
  131. HRESULT CFSFolderViewCB::OnGetPane(DWORD pv, LPARAM dwPaneID, DWORD *pdwPane)
  132. {
  133. if (PANE_ZONE == dwPaneID)
  134. *pdwPane = 2;
  135. return S_OK;
  136. }
  137. HRESULT CFSFolderViewCB::OnGetCCHMax(DWORD pv, LPCITEMIDLIST pidlItem, UINT *pcchMax)
  138. {
  139. TCHAR szName[MAX_PATH];
  140. if (SUCCEEDED(DisplayNameOf(_pfsf, pidlItem, SHGDN_FORPARSING | SHGDN_INFOLDER, szName, ARRAYSIZE(szName))))
  141. {
  142. _pfsf->GetMaxLength(szName, (int *)pcchMax);
  143. }
  144. return S_OK;
  145. }
  146. HRESULT CFSFolderViewCB::OnWindowCreated(DWORD pv, HWND wP)
  147. {
  148. if (SUCCEEDED(_pfsf->_GetPath(_fssci.szDrive, ARRAYSIZE(_fssci.szDrive))))
  149. {
  150. _fssci.cbFree = -1; // not known yet
  151. if (!_fStatusInitialized)
  152. {
  153. InitializeStatus(_punkSite);
  154. _fStatusInitialized = TRUE;
  155. }
  156. return S_OK;
  157. }
  158. return E_FAIL;
  159. }
  160. HRESULT CFSFolderViewCB::OnInsertDeleteItem(int iMul, LPCITEMIDLIST wP)
  161. {
  162. ViewInsertDeleteItem(_pfsf, &_fssci, wP, iMul);
  163. // Tell the FSFolder that it needs to update the extended columns
  164. // when we get an insert item. This will cause the next call to
  165. // IColumnProvider::GetItemData to flush it's row-wise cache.
  166. if (1 == iMul)
  167. {
  168. _pfsf->_bUpdateExtendedCols = TRUE;
  169. }
  170. return S_OK;
  171. }
  172. HRESULT CFSFolderViewCB::OnSelChange(DWORD pv, UINT wPl, UINT wPh, SFVM_SELCHANGE_DATA*lP)
  173. {
  174. ViewSelChange(_pfsf, lP, &_fssci);
  175. return S_OK;
  176. }
  177. HRESULT CFSFolderViewCB::OnUpdateStatusBar(DWORD pv, BOOL wP)
  178. {
  179. if (!_fStatusInitialized)
  180. {
  181. InitializeStatus(_punkSite);
  182. _fStatusInitialized = TRUE;
  183. }
  184. // if initializing, force refresh of disk free space
  185. if (wP)
  186. _fssci.cbFree = -1;
  187. return ViewUpdateStatusBar(_punkSite, _pidl, &_fssci);
  188. }
  189. HRESULT CFSFolderViewCB::OnRefresh(DWORD pv, BOOL fPreRefresh)
  190. {
  191. // pre refresh...
  192. if (fPreRefresh)
  193. {
  194. _fHasWIADevices = TRIBIT_UNDEFINED; // so we re-query
  195. }
  196. else
  197. {
  198. _fssci.cHiddenFiles = _pfsf->_cHiddenFiles;
  199. _fssci.cbSize = _pfsf->_cbSize;
  200. }
  201. return S_OK;
  202. }
  203. HRESULT CFSFolderViewCB::OnSelectAll(DWORD pv)
  204. {
  205. HRESULT hr = S_OK;
  206. if (_fssci.cHiddenFiles > 0)
  207. {
  208. if (ShellMessageBox(HINST_THISDLL, _hwndMain,
  209. MAKEINTRESOURCE(IDS_SELECTALLBUTHIDDEN),
  210. MAKEINTRESOURCE(IDS_SELECTALL), MB_OKCANCEL | MB_SETFOREGROUND | MB_ICONWARNING,
  211. _fssci.cHiddenFiles) == IDCANCEL)
  212. {
  213. hr = S_FALSE;
  214. }
  215. }
  216. return hr;
  217. }
  218. HRESULT CFSFolderViewCB::OnGetWorkingDir(DWORD pv, UINT wP, LPTSTR lP)
  219. {
  220. return _pfsf->_GetPath(lP, MAX_PATH); // assumed buffer size! possible overflow.
  221. }
  222. HRESULT CFSFolderViewCB::_HasWiaDevices(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState)
  223. {
  224. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  225. if (TRIBIT_UNDEFINED == pThis->_fHasWIADevices && fOkToBeSlow)
  226. {
  227. pThis->_fHasWIADevices = TRIBIT_FALSE;
  228. // strings stolen from stiregi.h
  229. // REGSTR_PATH_SOFT_STI, REGSTR_VAL_WIA_PRESEN
  230. if (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE,
  231. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\StillImage"),
  232. TEXT("WIADevicePresent"), NULL, NULL, NULL))
  233. {
  234. IWiaDevMgr* pwia;
  235. if (SUCCEEDED(CoCreateInstance(CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_NO_FAILURE_LOG, IID_PPV_ARG(IWiaDevMgr, &pwia))))
  236. {
  237. IEnumWIA_DEV_INFO* penum;
  238. if (S_OK == pwia->EnumDeviceInfo(0, &penum))
  239. {
  240. ULONG cItems;
  241. if ((S_OK == penum->GetCount(&cItems)) &&
  242. cItems > 0)
  243. {
  244. pThis->_fHasWIADevices = TRIBIT_TRUE;
  245. }
  246. penum->Release();
  247. }
  248. pwia->Release();
  249. }
  250. }
  251. }
  252. *puisState = (TRIBIT_TRUE == pThis->_fHasWIADevices) ? UIS_ENABLED : UIS_HIDDEN;
  253. return TRIBIT_UNDEFINED == pThis->_fHasWIADevices ? E_PENDING : S_OK;
  254. }
  255. HRESULT CFSFolderViewCB::_HasItems(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState)
  256. {
  257. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  258. *puisState = UIS_ENABLED;
  259. if (!psiItemArray)
  260. {
  261. // empty folders don't want this task
  262. *puisState = UIS_DISABLED;
  263. IFolderView* pfv;
  264. IDataObject *pdo;
  265. if (pThis->_punkSite && SUCCEEDED(pThis->_punkSite->QueryInterface(IID_PPV_ARG(IFolderView, &pfv))))
  266. {
  267. if (SUCCEEDED(pfv->Items(SVGIO_ALLVIEW, IID_PPV_ARG(IDataObject, &pdo))))
  268. {
  269. *puisState = UIS_ENABLED;
  270. pdo->Release();
  271. }
  272. pfv->Release();
  273. }
  274. }
  275. return S_OK;
  276. }
  277. // Image options
  278. #define IMAGEOPTION_CANROTATE 0x00000001
  279. #define IMAGEOPTION_CANWALLPAPER 0x00000002
  280. HRESULT CFSFolderViewCB::_CanWallpaper(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState)
  281. {
  282. *puisState = UIS_DISABLED;
  283. IDataObject *pdo;
  284. if (psiItemArray && SUCCEEDED(psiItemArray->BindToHandler(NULL, BHID_DataObject, IID_PPV_ARG(IDataObject, &pdo))))
  285. {
  286. LPITEMIDLIST pidl;
  287. if (SUCCEEDED(PidlFromDataObject(pdo, &pidl))) // could get this dircetly from ShellItemArray
  288. {
  289. IAssociationArray *paa;
  290. if (SUCCEEDED(SHGetUIObjectOf(pidl, NULL, IID_PPV_ARG(IAssociationArray, &paa))))
  291. {
  292. DWORD dwFlags, cb = sizeof(dwFlags);
  293. if (SUCCEEDED(paa->QueryDword(ASSOCELEM_MASK_QUERYNORMAL, AQN_NAMED_VALUE, L"ImageOptionFlags", &dwFlags)) &&
  294. (dwFlags & IMAGEOPTION_CANWALLPAPER))
  295. {
  296. *puisState = UIS_ENABLED;
  297. }
  298. paa->Release();
  299. }
  300. ILFree(pidl);
  301. }
  302. pdo->Release();
  303. }
  304. return S_OK;
  305. }
  306. enum
  307. {
  308. DATAOBJCB_IMAGE = 0x1,
  309. DATAOBJCB_MUSIC = 0x2,
  310. DATAOBJCB_VIDEO = 0x4,
  311. DATAOBJCB_ONLYCHECKEXISTENCE = 0x80000000
  312. };
  313. class CDataObjectCallback : public INamespaceWalkCB
  314. {
  315. public:
  316. // IUnknown
  317. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  318. STDMETHODIMP_(ULONG) AddRef(void);
  319. STDMETHODIMP_(ULONG) Release(void);
  320. // INamespaceWalkCB
  321. STDMETHODIMP FoundItem(IShellFolder *psf, LPCITEMIDLIST pidl);
  322. STDMETHODIMP EnterFolder(IShellFolder *psf, LPCITEMIDLIST pidl);
  323. STDMETHODIMP LeaveFolder(IShellFolder *psf, LPCITEMIDLIST pidl);
  324. STDMETHODIMP InitializeProgressDialog(LPWSTR *ppszTitle, LPWSTR *ppszCancel);
  325. CDataObjectCallback(DWORD dwFlags);
  326. BOOL Found();
  327. private:
  328. DWORD _dwFlags;
  329. BOOL _fAlreadyFound;
  330. };
  331. STDMETHODIMP_(ULONG) CDataObjectCallback::AddRef()
  332. {
  333. return 3;
  334. }
  335. STDMETHODIMP_(ULONG) CDataObjectCallback::Release()
  336. {
  337. return 2;
  338. }
  339. CDataObjectCallback::CDataObjectCallback(DWORD dwFlags)
  340. {
  341. _dwFlags = dwFlags;
  342. _fAlreadyFound = FALSE;
  343. }
  344. BOOL CDataObjectCallback::Found()
  345. {
  346. return _fAlreadyFound;
  347. }
  348. STDMETHODIMP CDataObjectCallback::QueryInterface(REFIID riid, void **ppv)
  349. {
  350. static const QITAB qit[] =
  351. {
  352. QITABENT(CDataObjectCallback, INamespaceWalkCB),
  353. { 0 },
  354. };
  355. return QISearch(this, qit, riid, ppv);
  356. }
  357. STDMETHODIMP CDataObjectCallback::FoundItem(IShellFolder *psf, LPCITEMIDLIST pidl)
  358. {
  359. // a slight misuse of the walker -- we bail out early if we know we've already found
  360. // what we're looking for
  361. if ((_dwFlags & DATAOBJCB_ONLYCHECKEXISTENCE) && _fAlreadyFound)
  362. return E_FAIL;
  363. PERCEIVED gen = GetPerceivedType(psf, pidl);
  364. if ((_dwFlags & DATAOBJCB_IMAGE) && (gen == GEN_IMAGE) ||
  365. (_dwFlags & DATAOBJCB_MUSIC) && (gen == GEN_AUDIO) ||
  366. (_dwFlags & DATAOBJCB_VIDEO) && (gen == GEN_VIDEO))
  367. {
  368. if (_dwFlags & DATAOBJCB_ONLYCHECKEXISTENCE)
  369. {
  370. _fAlreadyFound = TRUE;
  371. }
  372. return S_OK;
  373. }
  374. return S_FALSE;
  375. }
  376. STDMETHODIMP CDataObjectCallback::EnterFolder(IShellFolder *psf, LPCITEMIDLIST pidl)
  377. {
  378. if ((_dwFlags & DATAOBJCB_ONLYCHECKEXISTENCE) && _fAlreadyFound)
  379. return E_FAIL;
  380. return S_OK;
  381. }
  382. STDMETHODIMP CDataObjectCallback::LeaveFolder(IShellFolder *psf, LPCITEMIDLIST pidl)
  383. {
  384. return S_OK;
  385. }
  386. STDMETHODIMP CDataObjectCallback::InitializeProgressDialog(LPWSTR *ppszTitle, LPWSTR *ppszCancel)
  387. {
  388. *ppszCancel = NULL; // use default
  389. TCHAR szMsg[128];
  390. LoadString(HINST_THISDLL, IDS_WALK_PROGRESS_TITLE, szMsg, ARRAYSIZE(szMsg));
  391. return SHStrDup(szMsg, ppszTitle);
  392. }
  393. HRESULT InvokeVerbsOnItems(HWND hwndOwner, const LPCSTR rgszVerbs[], UINT cVerbs, LPITEMIDLIST *ppidls, UINT cItems)
  394. {
  395. IContextMenu *pcm;
  396. HRESULT hr = SHGetUIObjectFromFullPIDL(ppidls[0], NULL, IID_PPV_ARG(IContextMenu, &pcm));
  397. if (SUCCEEDED(hr))
  398. {
  399. ITEMIDLIST id = {0};
  400. IDataObject *pdtobj;
  401. hr = SHCreateFileDataObject(&id, cItems, (LPCITEMIDLIST *)ppidls, NULL, &pdtobj);
  402. if (SUCCEEDED(hr))
  403. {
  404. IShellExtInit *psei;
  405. hr = pcm->QueryInterface(IID_PPV_ARG(IShellExtInit, &psei));
  406. if (SUCCEEDED(hr))
  407. {
  408. psei->Initialize(NULL, pdtobj, NULL);
  409. psei->Release();
  410. }
  411. pdtobj->Release();
  412. }
  413. hr = SHInvokeCommandsOnContextMenu(hwndOwner, NULL, pcm, 0, rgszVerbs, cVerbs);
  414. pcm->Release();
  415. }
  416. return hr;
  417. }
  418. HRESULT PlayFromUnk(IUnknown *punk, HWND hwndOwner, int fDATAOBJCB)
  419. {
  420. INamespaceWalk *pnsw;
  421. HRESULT hr = CoCreateInstance(CLSID_NamespaceWalker, NULL, CLSCTX_INPROC, IID_PPV_ARG(INamespaceWalk, &pnsw));
  422. if (SUCCEEDED(hr))
  423. {
  424. CDataObjectCallback cb(fDATAOBJCB);
  425. hr = pnsw->Walk(punk, NSWF_NONE_IMPLIES_ALL | NSWF_ONE_IMPLIES_ALL | NSWF_SHOW_PROGRESS | NSWF_FLAG_VIEWORDER, 10, &cb);
  426. if (SUCCEEDED(hr))
  427. {
  428. UINT cItems;
  429. LPITEMIDLIST *ppidls;
  430. hr = pnsw->GetIDArrayResult(&cItems, &ppidls);
  431. if (SUCCEEDED(hr))
  432. {
  433. if (cItems)
  434. {
  435. const LPCSTR c_rgszVerbs[] = { "Play", "Open" };
  436. hr = InvokeVerbsOnItems(hwndOwner, c_rgszVerbs, ARRAYSIZE(c_rgszVerbs), ppidls, cItems);
  437. }
  438. else
  439. {
  440. ShellMessageBox(
  441. HINST_THISDLL,
  442. hwndOwner,
  443. MAKEINTRESOURCE(IDS_PLAYABLEFILENOTFOUND),
  444. NULL,
  445. MB_OK | MB_ICONERROR);
  446. hr = S_FALSE;
  447. }
  448. FreeIDListArray(ppidls, cItems);
  449. }
  450. }
  451. pnsw->Release();
  452. }
  453. return hr;
  454. }
  455. HRESULT CFSFolderViewCB::_OnCommonDocumentsHelp(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  456. {
  457. SHELLEXECUTEINFO sei = { 0 };
  458. sei.cbSize = sizeof(sei);
  459. sei.fMask = 0;
  460. sei.hwnd = ((CFSFolderViewCB*)(void*)pv)->_hwndMain;
  461. sei.nShow = SW_SHOWNORMAL;
  462. sei.lpFile = L"hcp://services/subsite?node=TopLevelBucket_2/Networking_and_the_Web&topic=MS-ITS%3A%25HELP_LOCATION%25%5Cfilefold.chm%3A%3A/using_shared_documents_folder.htm&select=TopLevelBucket_2/Networking_and_the_Web/Sharing_files__printers__and_other_resources";
  463. return ShellExecuteEx(&sei) ? S_OK : E_FAIL;
  464. }
  465. HRESULT CFSFolderViewCB::_CanOrderPrints(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState)
  466. {
  467. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  468. // TODO: Use fOkToBeSlow (with a return of E_PENDING) to allow walk to
  469. // occur on a background task thread (for performance reasons). However,
  470. // it doesn't work at present because it's completely specialized for WIA
  471. // stuff, and it will not be trivial to adapt to the general case. Thus,
  472. // we make assumptions as best we can in determining the state for now.
  473. *puisState = UIS_DISABLED;
  474. if (SHRestricted(REST_NOONLINEPRINTSWIZARD))
  475. {
  476. // bail out early with UIS_HIDDEN, we dont show the verb
  477. return S_OK;
  478. }
  479. IDataObject *pdo = NULL;
  480. HRESULT hr = psiItemArray ? psiItemArray->BindToHandler(NULL, BHID_DataObject, IID_PPV_ARG(IDataObject, &pdo)) : S_OK;
  481. if (SUCCEEDED(hr))
  482. {
  483. if (pThis->_fssci.nItems > 0) // Files selected. Determine if any images...
  484. {
  485. INamespaceWalk *pnsw;
  486. hr = CoCreateInstance(CLSID_NamespaceWalker, NULL, CLSCTX_INPROC, IID_PPV_ARG(INamespaceWalk, &pnsw));
  487. if (SUCCEEDED(hr))
  488. {
  489. CDataObjectCallback cb(DATAOBJCB_IMAGE | DATAOBJCB_ONLYCHECKEXISTENCE);
  490. pnsw->Walk(psiItemArray ? pdo : pThis->_punkSite, NSWF_NONE_IMPLIES_ALL | NSWF_DONT_ACCUMULATE_RESULT, 0, &cb);
  491. if (cb.Found())
  492. {
  493. *puisState = UIS_ENABLED;
  494. }
  495. pnsw->Release();
  496. }
  497. }
  498. else
  499. {
  500. *puisState = UIS_ENABLED; // No files selected. Assume image files exist.
  501. hr = S_OK; // Note we "assume" for the TODO perf reason above.
  502. }
  503. ATOMICRELEASE(pdo);
  504. }
  505. return hr;
  506. }
  507. HRESULT CFSFolderViewCB::_CanPrintPictures(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState)
  508. {
  509. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  510. HRESULT hr;
  511. // TODO: Use fOkToBeSlow (with a return of E_PENDING) to allow walk to
  512. // occur on a background task thread (for performance reasons). However,
  513. // it doesn't work at present because it's completely specialized for WIA
  514. // stuff, and it will not be trivial to adapt to the general case. Thus,
  515. // we make assumptions as best we can in determining the state for now.
  516. if (psiItemArray)
  517. {
  518. *puisState = UIS_DISABLED;
  519. IDataObject *pdo;
  520. hr = psiItemArray->BindToHandler(NULL, BHID_DataObject, IID_PPV_ARG(IDataObject, &pdo));
  521. if (SUCCEEDED(hr))
  522. {
  523. INamespaceWalk *pnsw;
  524. hr = CoCreateInstance(CLSID_NamespaceWalker, NULL, CLSCTX_INPROC, IID_PPV_ARG(INamespaceWalk, &pnsw));
  525. if (SUCCEEDED(hr))
  526. {
  527. CDataObjectCallback cb(DATAOBJCB_IMAGE | DATAOBJCB_ONLYCHECKEXISTENCE);
  528. pnsw->Walk(pdo, NSWF_DONT_ACCUMULATE_RESULT, 0, &cb);
  529. if (cb.Found())
  530. {
  531. *puisState = UIS_ENABLED;
  532. }
  533. pnsw->Release();
  534. }
  535. pdo->Release();
  536. }
  537. }
  538. else
  539. {
  540. *puisState = UIS_ENABLED; // No files selected. Assume image files exist.
  541. hr = S_OK; // Note we "assume" for the TODO perf reason above.
  542. }
  543. return hr;
  544. }
  545. HRESULT CFSFolderViewCB::_CanBuyPictures(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState)
  546. {
  547. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  548. *puisState = UIS_DISABLED;
  549. // If there is a BuyURL in the desktop.ini, then we'll show the buy pictures task.
  550. WCHAR szIniPath[MAX_PATH];
  551. if (pThis->_pfsf->_CheckDefaultIni(NULL, szIniPath, ARRAYSIZE(szIniPath)) && PathFileExistsAndAttributes(szIniPath, NULL))
  552. {
  553. WCHAR szURLArguments[MAX_PATH];
  554. if (GetPrivateProfileString(L".ShellClassInfo", c_BuySamplePictures.szURLKey, L"", szURLArguments, ARRAYSIZE(szURLArguments), szIniPath))
  555. {
  556. // Note:
  557. // String validation does not occur here (by design). This is
  558. // simply an "existance" check. Validation will occur only if
  559. // the user actually clicks on this task and we need to execute.
  560. // Yes - there's something.
  561. *puisState = UIS_ENABLED;
  562. }
  563. }
  564. return S_OK;
  565. }
  566. HRESULT CFSFolderViewCB::_CanPlayMusic(IUnknown* pv,IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState)
  567. {
  568. return _CanPlay(pv, psiItemArray, fOkToBeSlow, puisState, DATAOBJCB_MUSIC | DATAOBJCB_VIDEO);
  569. }
  570. HRESULT CFSFolderViewCB::_CanPlayVideos(IUnknown* pv,IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState)
  571. {
  572. return _CanPlay(pv, psiItemArray, fOkToBeSlow, puisState, DATAOBJCB_VIDEO);
  573. }
  574. HRESULT CFSFolderViewCB::_CanPlay(IUnknown* pv,IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState, int fDATAOBJCB)
  575. {
  576. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  577. *puisState = UIS_DISABLED;
  578. // TODO: Use fOkToBeSlow (with a return of E_PENDING) to allow walk to
  579. // occur on a background task thread (for performance reasons). However,
  580. // it doesn't work at present because it's completely specialized for WIA
  581. // stuff, and it will not be trivial to adapt to the general case. Thus,
  582. // we make assumptions as best we can in determining the state for now.
  583. IDataObject *pdo = NULL;
  584. HRESULT hr = psiItemArray ? psiItemArray->BindToHandler(NULL, BHID_DataObject, IID_PPV_ARG(IDataObject, &pdo)) : S_OK;
  585. if (SUCCEEDED(hr))
  586. {
  587. RIPMSG(!psiItemArray || pdo, "CFSFolderViewCB::_CanPlay - BindToHandler returned S_OK but NULL pdo");
  588. RIPMSG(psiItemArray || pThis->_punkSite, "CFSFolderViewCB::_CanPlay - no _punkSite!");
  589. if (pThis->_fssci.cFiles > 0)
  590. {
  591. if (pThis->_fssci.nItems > 0) // Files selected. Determine if any playable...
  592. {
  593. INamespaceWalk *pnsw;
  594. hr = CoCreateInstance(CLSID_NamespaceWalker, NULL, CLSCTX_INPROC, IID_PPV_ARG(INamespaceWalk, &pnsw));
  595. if (SUCCEEDED(hr))
  596. {
  597. CDataObjectCallback cb(fDATAOBJCB | DATAOBJCB_ONLYCHECKEXISTENCE);
  598. pnsw->Walk(psiItemArray ? pdo : pThis->_punkSite, NSWF_DONT_ACCUMULATE_RESULT, 4, &cb);
  599. if (cb.Found())
  600. {
  601. *puisState = UIS_ENABLED;
  602. }
  603. pnsw->Release();
  604. }
  605. }
  606. else
  607. *puisState = UIS_ENABLED; // No files selected. Assume playable files exist.
  608. } // Note we "assume" for the TODO perf reason above.
  609. ATOMICRELEASE(pdo);
  610. }
  611. return hr;
  612. }
  613. HRESULT CFSFolderViewCB::_OnPlayMusic(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  614. {
  615. return _OnPlay(pv, psiItemArray, pbc, DATAOBJCB_MUSIC | DATAOBJCB_VIDEO);
  616. }
  617. HRESULT CFSFolderViewCB::_OnPlayVideos(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  618. {
  619. return _OnPlay(pv, psiItemArray, pbc, DATAOBJCB_VIDEO);
  620. }
  621. HRESULT CFSFolderViewCB::_OnPlay(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc, int fDATAOBJCB)
  622. {
  623. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  624. HRESULT hr;
  625. if (psiItemArray)
  626. {
  627. IDataObject *pdo;
  628. hr = psiItemArray->BindToHandler(NULL, BHID_DataObject, IID_PPV_ARG(IDataObject, &pdo));
  629. if (SUCCEEDED(hr))
  630. {
  631. hr = PlayFromUnk(pdo, pThis->_hwndMain, fDATAOBJCB);
  632. pdo->Release();
  633. }
  634. }
  635. else
  636. {
  637. hr = PlayFromUnk(pThis->_punkSite, pThis->_hwndMain, fDATAOBJCB);
  638. }
  639. return hr;
  640. }
  641. HRESULT CFSFolderViewCB::_GetShoppingURL(const SHOP_INFO *pShopInfo, LPTSTR pszURL, DWORD cchURL)
  642. {
  643. HRESULT hr = URLSubstitution(pShopInfo->szURLPrefix, pszURL, cchURL, URLSUB_CLCID);
  644. if (SUCCEEDED(hr))
  645. {
  646. WCHAR szIniPath[MAX_PATH];
  647. // If we can't just use the fwlink with no arguments, then assume failure.
  648. hr = pShopInfo->bUseDefault ? S_OK : E_FAIL;
  649. if (_pfsf->_CheckDefaultIni(NULL, szIniPath, ARRAYSIZE(szIniPath)) && PathFileExistsAndAttributes(szIniPath, NULL))
  650. {
  651. WCHAR szURLArguments[MAX_PATH];
  652. if (GetPrivateProfileString(L".ShellClassInfo", pShopInfo->szURLKey, L"", szURLArguments, ARRAYSIZE(szURLArguments), szIniPath))
  653. {
  654. // Note:
  655. // All URL's are read from hard-coded strings in the code
  656. // base, and are of the form:
  657. //
  658. // http://go.microsoft.com/fwlink/?LinkId=730&clcid={SUB_CLCID}
  659. //
  660. // The desktop.ini simply offers an avenue to add additional
  661. // arguments onto the end of the URL to refine the redirect.
  662. // We do not validate these arguments here, because it is
  663. // assumed the fwlink service is robust enough to handle bad
  664. // input. If it wasn't, than anyone could type a bad fwlink
  665. // URL in their address bar and wreck havoc on the fwlink
  666. // service.
  667. StringCchCat(pszURL, cchURL, L"&");
  668. StringCchCat(pszURL, cchURL, szURLArguments);
  669. // Got some arguments - we're definitely ok.
  670. hr = S_OK;
  671. }
  672. }
  673. }
  674. return hr;
  675. }
  676. HRESULT CFSFolderViewCB::_GetShoppingBrowsePidl(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc, const SHOP_INFO *pShopInfo, LPITEMIDLIST *ppidl)
  677. {
  678. WCHAR wszShoppingURL[MAX_URL_STRING];
  679. HRESULT hr = _GetShoppingURL(pShopInfo, wszShoppingURL, ARRAYSIZE(wszShoppingURL));
  680. if (SUCCEEDED(hr))
  681. {
  682. IShellFolder *psfDesktop;
  683. hr = SHGetDesktopFolder(&psfDesktop);
  684. if (SUCCEEDED(hr))
  685. {
  686. hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszShoppingURL, NULL, ppidl, NULL);
  687. psfDesktop->Release();
  688. }
  689. }
  690. return hr;
  691. }
  692. HRESULT CFSFolderViewCB::_OnShopForMusicOnline(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  693. {
  694. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  695. LPITEMIDLIST pidl;
  696. // See if there is a sample music BuyURL
  697. // (do this check first, because the regular music buy URL should always succeed)
  698. HRESULT hr = pThis->_GetShoppingBrowsePidl(pv, psiItemArray, pbc, &c_BuySampleMusic, &pidl);
  699. if (SUCCEEDED(hr))
  700. {
  701. hr = pThis->_BrowseObject(pidl, SBSP_NEWBROWSER);
  702. ILFree(pidl);
  703. }
  704. else
  705. {
  706. // Nope - look for the regular music buy URL
  707. hr = pThis->_GetShoppingBrowsePidl(pv, psiItemArray, pbc, &c_BuyMusic, &pidl);
  708. if (SUCCEEDED(hr))
  709. {
  710. hr = pThis->_BrowseObject(pidl, SBSP_NEWBROWSER);
  711. ILFree(pidl);
  712. }
  713. }
  714. return hr;
  715. }
  716. HRESULT CFSFolderViewCB::_OnShopForPicturesOnline(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  717. {
  718. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  719. WCHAR wszShoppingURL[MAX_URL_STRING];
  720. HRESULT hr = pThis->_GetShoppingURL(&c_BuySamplePictures, wszShoppingURL, ARRAYSIZE(wszShoppingURL));
  721. if (SUCCEEDED(hr))
  722. {
  723. HINSTANCE hinstRet = ShellExecute(NULL, NULL, wszShoppingURL, NULL, NULL, SW_SHOWNORMAL);
  724. hr = ((UINT_PTR)hinstRet) <= 32 ? E_FAIL : S_OK;
  725. }
  726. return hr;
  727. }
  728. HRESULT CFSFolderViewCB::_DataObjectFromItemsOrFolder(IShellItemArray *psiItemArray, IDataObject **ppdto)
  729. {
  730. *ppdto = NULL;
  731. HRESULT hr;
  732. if (psiItemArray)
  733. {
  734. // Something selected -- work with selected items.
  735. hr = psiItemArray->BindToHandler(NULL, BHID_DataObject, IID_PPV_ARG(IDataObject, ppdto));
  736. }
  737. else
  738. {
  739. // Nothing selected -- imply folder selected.
  740. hr = SHGetUIObjectOf(_pidl, NULL, IID_PPV_ARG(IDataObject, ppdto));
  741. }
  742. return hr;
  743. }
  744. HRESULT CFSFolderViewCB::_CanSendToAudioCD(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState)
  745. {
  746. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  747. *puisState = UIS_DISABLED;
  748. IDataObject *pdo;
  749. HRESULT hr = pThis->_DataObjectFromItemsOrFolder(psiItemArray, &pdo);
  750. if (SUCCEEDED(hr))
  751. {
  752. // todo: use fOkToBeSlow to get off the UI thread -- right now it wont work because
  753. // its specialized just for the WIA stuff and things that have global state
  754. ICDBurn *pcdb;
  755. if (SUCCEEDED(CoCreateInstance(CLSID_CDBurn, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ICDBurn, &pcdb))))
  756. {
  757. // media player will get invoked, so we only worry about if the system has a
  758. // recordable drive at all -- whether the shell burning is enabled or not doesnt matter
  759. BOOL fHasRecorder;
  760. if (SUCCEEDED(pcdb->HasRecordableDrive(&fHasRecorder)) && fHasRecorder)
  761. {
  762. IUnknown *punk;
  763. // if this probe works, we can get something thats good to go and itll burn cds.
  764. if (SUCCEEDED(CDBurn_GetExtensionObject(CDBE_TYPE_MUSIC, pdo, IID_PPV_ARG(IUnknown, &punk))))
  765. {
  766. *puisState = UIS_ENABLED;
  767. punk->Release();
  768. }
  769. }
  770. pcdb->Release();
  771. }
  772. pdo->Release();
  773. }
  774. return hr;
  775. }
  776. HRESULT CFSFolderViewCB::_OnSendToAudioCD(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  777. {
  778. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  779. IDataObject *pdo;
  780. HRESULT hr = pThis->_DataObjectFromItemsOrFolder(psiItemArray, &pdo);
  781. if (SUCCEEDED(hr))
  782. {
  783. IDropTarget *pdt;
  784. hr = CDBurn_GetExtensionObject(CDBE_TYPE_MUSIC, pdo, IID_PPV_ARG(IDropTarget, &pdt));
  785. if (SUCCEEDED(hr))
  786. {
  787. hr = SHSimulateDrop(pdt, pdo, 0, NULL, NULL);
  788. pdt->Release();
  789. }
  790. pdo->Release();
  791. }
  792. return hr;
  793. }
  794. HRESULT CFSFolderViewCB::_CanSendToCD(IUnknown* pv, IShellItemArray *psiItemArray, BOOL fOkToBeSlow, UISTATE* puisState)
  795. {
  796. *puisState = UIS_DISABLED;
  797. WCHAR szDrive[4];
  798. if (SUCCEEDED(CDBurn_GetRecorderDriveLetter(szDrive, ARRAYSIZE(szDrive))))
  799. {
  800. // if this succeeds, shell cd burning is enabled.
  801. *puisState = UIS_ENABLED;
  802. }
  803. return S_OK;
  804. }
  805. HRESULT CFSFolderViewCB::_OnSendToCD(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  806. {
  807. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  808. IDataObject *pdo;
  809. HRESULT hr = pThis->_DataObjectFromItemsOrFolder(psiItemArray, &pdo);
  810. if (SUCCEEDED(hr))
  811. {
  812. WCHAR szDrive[4];
  813. hr = CDBurn_GetRecorderDriveLetter(szDrive, ARRAYSIZE(szDrive));
  814. if (SUCCEEDED(hr))
  815. {
  816. LPITEMIDLIST pidl;
  817. hr = SHILCreateFromPath(szDrive, &pidl, NULL);
  818. if (SUCCEEDED(hr))
  819. {
  820. IDropTarget *pdt;
  821. hr = SHGetUIObjectOf(pidl, NULL, IID_PPV_ARG(IDropTarget, &pdt));
  822. if (SUCCEEDED(hr))
  823. {
  824. hr = SHSimulateDropWithSite(pdt, pdo, 0, NULL, NULL, pThis->_punkSite);
  825. pdt->Release();
  826. }
  827. ILFree(pidl);
  828. }
  829. }
  830. pdo->Release();
  831. }
  832. return hr;
  833. }
  834. HRESULT CFSFolderViewCB::_OnGetFromCamera(IUnknown* pv,IShellItemArray *psiItemArray, IBindCtx *pbc)
  835. {
  836. SHELLEXECUTEINFO sei = {0};
  837. sei.cbSize = sizeof(sei);
  838. sei.fMask = SEE_MASK_DOENVSUBST;
  839. sei.hwnd = ((CFSFolderViewCB*)(void*)pv)->_hwndMain;
  840. sei.lpFile = TEXT("%SystemRoot%\\System32\\wiaacmgr.exe");
  841. sei.lpParameters = TEXT("/SelectDevice");
  842. sei.nShow = SW_SHOWNORMAL;
  843. return ShellExecuteEx(&sei) ? S_OK : E_FAIL;
  844. }
  845. HRESULT CFSFolderViewCB::_GetPreview3(IPreview3** ppPreview3)
  846. {
  847. HRESULT hr = E_FAIL;
  848. *ppPreview3 = NULL;
  849. if (!_pPreview)
  850. {
  851. hr = CoCreateInstance(CLSID_Preview, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPreview3, &_pPreview));
  852. if (SUCCEEDED(hr))
  853. {
  854. IUnknown_SetSite(_pPreview, _punkSite);
  855. }
  856. }
  857. if (_pPreview)
  858. {
  859. *ppPreview3 = _pPreview;
  860. _pPreview->AddRef();
  861. hr = S_OK;
  862. }
  863. return hr;
  864. }
  865. HRESULT CFSFolderViewCB::_OnSlideShow(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  866. {
  867. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  868. IPreview3* pPreview3;
  869. HRESULT hr = pThis->_GetPreview3(&pPreview3);
  870. if (SUCCEEDED(hr))
  871. {
  872. hr = pPreview3->SlideShow();
  873. pPreview3->Release();
  874. }
  875. return hr;
  876. }
  877. HRESULT CFSFolderViewCB::_OnWallpaper(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  878. {
  879. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  880. HRESULT hr = E_FAIL;
  881. IDataObject *pdo;
  882. if (psiItemArray && SUCCEEDED(psiItemArray->BindToHandler(NULL, BHID_DataObject, IID_PPV_ARG(IDataObject, &pdo))))
  883. {
  884. IPreview3* pPreview3;
  885. if (SUCCEEDED(pThis->_GetPreview3(&pPreview3)))
  886. {
  887. TCHAR szPath[MAX_PATH];
  888. if (SUCCEEDED(PathFromDataObject(pdo, szPath, ARRAYSIZE(szPath))))
  889. {
  890. hr = pPreview3->SetWallpaper(szPath);
  891. }
  892. pPreview3->Release();
  893. }
  894. pdo->Release();
  895. }
  896. return hr;
  897. }
  898. HRESULT CFSFolderViewCB::_OnOrderPrints(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  899. {
  900. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  901. IDataObject *pdo;
  902. HRESULT hr = pThis->_DataObjectFromItemsOrFolder(psiItemArray, &pdo);
  903. if (SUCCEEDED(hr))
  904. {
  905. hr = SHSimulateDropOnClsid(CLSID_InternetPrintOrdering, pThis->_punkSite, pdo);
  906. pdo->Release();
  907. }
  908. return hr;
  909. }
  910. HRESULT CFSFolderViewCB::_OnPrintPictures(IUnknown* pv, IShellItemArray *psiItemArray, IBindCtx *pbc)
  911. {
  912. CFSFolderViewCB* pThis = (CFSFolderViewCB*)(void*)pv;
  913. IDataObject *pdo;
  914. HRESULT hr = pThis->_DataObjectFromItemsOrFolder(psiItemArray, &pdo);
  915. if (SUCCEEDED(hr))
  916. {
  917. hr = SHSimulateDropOnClsid(CLSID_PrintPhotosDropTarget, pThis->_punkSite, pdo);
  918. pdo->Release();
  919. }
  920. return hr;
  921. }
  922. const WVTASKITEM c_CommonDocumentsSpecialTaskHeader = WVTI_HEADER(L"shell32.dll", IDS_HEADER_COMMONDOCUMENTS, IDS_HEADER_COMMONDOCUMENTS_TT);
  923. const WVTASKITEM c_CommonDocumentsSpecialTaskList[] =
  924. {
  925. WVTI_ENTRY_ALL(CLSID_NULL, L"shell32.dll", IDS_TASK_COMMONDOCUMENTSHELP, IDS_TASK_COMMONDOCUMENTSHELP_TT, IDI_TASK_HELP, NULL, CFSFolderViewCB::_OnCommonDocumentsHelp),
  926. };
  927. const LPCTSTR c_DocumentsOtherPlaces[] = { MAKEINTRESOURCE(CSIDL_PERSONAL), MAKEINTRESOURCE(CSIDL_COMMON_DOCUMENTS), MAKEINTRESOURCE(CSIDL_DRIVES), MAKEINTRESOURCE(CSIDL_NETWORK) };
  928. const WVTASKITEM c_MusicSpecialTaskHeader = WVTI_HEADER(L"shell32.dll", IDS_HEADER_MUSIC, IDS_HEADER_MUSIC_TT);
  929. const WVTASKITEM c_MusicSpecialTaskList[] =
  930. {
  931. WVTI_ENTRY_ALL_TITLE(UICID_PlayMusic, L"shell32.dll", IDS_TASK_PLAYALL, IDS_TASK_PLAYALL, IDS_TASK_PLAY, IDS_TASK_PLAY, IDS_TASK_PLAY_TT, IDI_TASK_PLAY_MUSIC, CFSFolderViewCB::_CanPlayMusic, CFSFolderViewCB::_OnPlayMusic),
  932. WVTI_ENTRY_ALL(UICID_ShopForMusicOnline, L"shell32.dll", IDS_TASK_SHOPFORMUSICONLINE, IDS_TASK_SHOPFORMUSICONLINE_TT, IDI_TASK_BUY_MUSIC, NULL, CFSFolderViewCB::_OnShopForMusicOnline),
  933. WVTI_ENTRY_ALL_TITLE(GUID_NULL, L"shell32.dll", IDS_TASK_COPYTOAUDIOCDALL, IDS_TASK_COPYTOAUDIOCD, IDS_TASK_COPYTOAUDIOCD, IDS_TASK_COPYTOAUDIOCD, IDS_TASK_COPYTOAUDIOCD_TT, IDI_TASK_SENDTOAUDIOCD, CFSFolderViewCB::_CanSendToAudioCD, CFSFolderViewCB::_OnSendToAudioCD),
  934. };
  935. const LPCTSTR c_MusicOtherPlaces[] = { MAKEINTRESOURCE(CSIDL_MYMUSIC), MAKEINTRESOURCE(CSIDL_DRIVES), MAKEINTRESOURCE(CSIDL_NETWORK) };
  936. const LPCTSTR c_MyMusicOtherPlaces[] = { MAKEINTRESOURCE(CSIDL_COMMON_MUSIC), MAKEINTRESOURCE(CSIDL_DRIVES), MAKEINTRESOURCE(CSIDL_NETWORK) };
  937. const WVTASKITEM c_PicturesSpecialTaskHeader = WVTI_HEADER(L"shell32.dll", IDS_HEADER_PICTURES, IDS_HEADER_PICTURES_TT);
  938. const WVTASKITEM c_PicturesSpecialTaskList[] =
  939. {
  940. WVTI_ENTRY_ALL(UICID_GetFromCamera, L"shell32.dll", IDS_TASK_GETFROMCAMERA, IDS_TASK_GETFROMCAMERA_TT, IDI_TASK_GETFROMCAMERA, CFSFolderViewCB::_HasWiaDevices, CFSFolderViewCB::_OnGetFromCamera),
  941. WVTI_ENTRY_ALL(UICID_SlideShow, L"shell32.dll", IDS_TASK_SLIDESHOW, IDS_TASK_SLIDESHOW_TT, IDI_TASK_SLIDESHOW, CFSFolderViewCB::_HasItems, CFSFolderViewCB::_OnSlideShow),
  942. WVTI_ENTRY_ALL(CLSID_NULL, L"shell32.dll", IDS_TASK_ORDERPRINTS, IDS_TASK_ORDERPRINTS_TT, IDI_TASK_ORDERPRINTS, CFSFolderViewCB::_CanOrderPrints, CFSFolderViewCB::_OnOrderPrints),
  943. WVTI_ENTRY_ALL_TITLE(CLSID_NULL, L"shell32.dll", IDS_TASK_PRINT_PICTURE_FOLDER, IDS_TASK_PRINT_PICTURE, IDS_TASK_PRINT_PICTURE_FOLDER, IDS_TASK_PRINT_PICTURES, IDS_TASK_PRINT_PICTURES_TT, IDI_TASK_PRINTPICTURES, CFSFolderViewCB::_CanPrintPictures, CFSFolderViewCB::_OnPrintPictures),
  944. WVTI_ENTRY_FILE(UICID_SetAsWallpaper,L"shell32.dll",IDS_TASK_SETASWALLPAPER, IDS_TASK_SETASWALLPAPER_TT, IDI_TASK_SETASWALLPAPER,CFSFolderViewCB::_CanWallpaper, CFSFolderViewCB::_OnWallpaper),
  945. WVTI_ENTRY_ALL_TITLE(CLSID_NULL, L"shell32.dll", IDS_TASK_COPYTOCDALL, IDS_TASK_COPYTOCD, IDS_TASK_COPYTOCD, IDS_TASK_COPYTOCD, IDS_TASK_COPYTOCD_TT, IDI_TASK_SENDTOCD, CFSFolderViewCB::_CanSendToCD, CFSFolderViewCB::_OnSendToCD),
  946. // Note: temporarily using IDI_ORDERPRINTS for the following task:
  947. WVTI_ENTRY_ALL(UICID_ShopForPicturesOnline, L"shell32.dll", IDS_TASK_SHOPFORPICTURESONLINE, IDS_TASK_SHOPFORPICTURESONLINE_TT, IDI_TASK_ORDERPRINTS, CFSFolderViewCB::_CanBuyPictures, CFSFolderViewCB::_OnShopForPicturesOnline),
  948. };
  949. const LPCTSTR c_PicturesOtherPlaces[] = { MAKEINTRESOURCE(CSIDL_MYPICTURES), MAKEINTRESOURCE(CSIDL_DRIVES), MAKEINTRESOURCE(CSIDL_NETWORK) };
  950. const LPCTSTR c_MyPicturesOtherPlaces[] = { MAKEINTRESOURCE(CSIDL_COMMON_PICTURES), MAKEINTRESOURCE(CSIDL_DRIVES), MAKEINTRESOURCE(CSIDL_NETWORK) };
  951. const WVTASKITEM c_VideosSpecialTaskHeader = WVTI_HEADER(L"shell32.dll", IDS_HEADER_VIDEOS, IDS_HEADER_VIDEOS_TT);
  952. const WVTASKITEM c_VideosSpecialTaskList[] =
  953. {
  954. WVTI_ENTRY_ALL_TITLE(CLSID_NULL, L"shell32.dll", IDS_TASK_PLAYALL, IDS_TASK_PLAYALL, IDS_TASK_PLAY, IDS_TASK_PLAY, IDS_TASK_PLAY_VIDEOS_TT, IDI_TASK_PLAY_MUSIC, CFSFolderViewCB::_CanPlayVideos, CFSFolderViewCB::_OnPlayVideos),
  955. WVTI_ENTRY_ALL(UICID_GetFromCamera, L"shell32.dll", IDS_TASK_GETFROMCAMERA, IDS_TASK_GETFROMCAMERA_TT, IDI_TASK_GETFROMCAMERA, CFSFolderViewCB::_HasWiaDevices, CFSFolderViewCB::_OnGetFromCamera),
  956. WVTI_ENTRY_ALL_TITLE(CLSID_NULL, L"shell32.dll", IDS_TASK_COPYTOCDALL, IDS_TASK_COPYTOCD, IDS_TASK_COPYTOCD, IDS_TASK_COPYTOCD, IDS_TASK_COPYTOCD_TT, IDI_TASK_SENDTOCD, CFSFolderViewCB::_CanSendToCD, CFSFolderViewCB::_OnSendToCD)
  957. };
  958. const LPCTSTR c_VideosOtherPlaces[] = { MAKEINTRESOURCE(CSIDL_MYVIDEO), MAKEINTRESOURCE(CSIDL_DRIVES), MAKEINTRESOURCE(CSIDL_NETWORK) };
  959. const LPCTSTR c_MyVideosOtherPlaces[] = { MAKEINTRESOURCE(CSIDL_COMMON_VIDEO), MAKEINTRESOURCE(CSIDL_DRIVES), MAKEINTRESOURCE(CSIDL_NETWORK) };
  960. typedef struct {
  961. const WVTASKITEM *pwvIntroText;
  962. const WVTASKITEM *pwvSpecialHeader;
  963. const WVTASKITEM *pwvSpecialTaskList;
  964. UINT cSpecialTaskList;
  965. const WVTASKITEM *pwvFolderHeader;
  966. const WVTASKITEM *pwvFolderTaskList;
  967. UINT cFolderTaskList;
  968. const LPCTSTR *pdwOtherPlacesList;
  969. UINT cOtherPlacesList;
  970. LPCWSTR pszThemeInfo;
  971. } WVCONTENT_DATA;
  972. #define WVCONTENT_DEFVIEWDEFAULT(op) { NULL, NULL, NULL, 0, NULL, NULL, 0, (op), ARRAYSIZE(op), NULL }
  973. #define WVCONTENT_FOLDER(fh, ft, op) { NULL, NULL, NULL, 0, &(fh), (ft), ARRAYSIZE(ft), (op), ARRAYSIZE(op), NULL }
  974. #define WVCONTENT_SPECIAL(sh, st, op, th) { NULL, &(sh), (st), ARRAYSIZE(st), NULL, NULL, 0, (op), ARRAYSIZE(op), (th) }
  975. const WVCONTENT_DATA c_wvContent[] =
  976. {
  977. WVCONTENT_DEFVIEWDEFAULT(c_DocumentsOtherPlaces), // FVCBFT_DOCUMENTS
  978. WVCONTENT_DEFVIEWDEFAULT(c_DocumentsOtherPlaces), // FVCBFT_MYDOCUMENTS
  979. WVCONTENT_SPECIAL(c_PicturesSpecialTaskHeader, c_PicturesSpecialTaskList, c_PicturesOtherPlaces, L"picture"),// FVCBFT_PICTURES
  980. WVCONTENT_SPECIAL(c_PicturesSpecialTaskHeader, c_PicturesSpecialTaskList, c_MyPicturesOtherPlaces, L"picture"),// FVCBFT_MYPICTURES
  981. WVCONTENT_SPECIAL(c_PicturesSpecialTaskHeader, c_PicturesSpecialTaskList, c_PicturesOtherPlaces, L"picture"),// FVCBFT_PHOTOALBUM
  982. WVCONTENT_SPECIAL(c_MusicSpecialTaskHeader, c_MusicSpecialTaskList, c_MusicOtherPlaces, L"music"), // FVCBFT_MUSIC
  983. WVCONTENT_SPECIAL(c_MusicSpecialTaskHeader, c_MusicSpecialTaskList, c_MyMusicOtherPlaces, L"music"), // FVCBFT_MYMUSIC
  984. WVCONTENT_SPECIAL(c_MusicSpecialTaskHeader, c_MusicSpecialTaskList, c_MusicOtherPlaces, L"music"), // FVCBFT_MUSICARTIST
  985. WVCONTENT_SPECIAL(c_MusicSpecialTaskHeader, c_MusicSpecialTaskList, c_MusicOtherPlaces, L"music"), // FVCBFT_MUSICALBUM
  986. WVCONTENT_SPECIAL(c_VideosSpecialTaskHeader, c_VideosSpecialTaskList, c_VideosOtherPlaces, L"video"), // FVCBFT_VIDEOS
  987. WVCONTENT_SPECIAL(c_VideosSpecialTaskHeader, c_VideosSpecialTaskList, c_MyVideosOtherPlaces, L"video"), // FVCBFT_MYVIDEOS
  988. WVCONTENT_SPECIAL(c_VideosSpecialTaskHeader, c_VideosSpecialTaskList, c_VideosOtherPlaces, L"video"), // FVCBFT_VIDEOALBUM
  989. WVCONTENT_DEFVIEWDEFAULT(c_DocumentsOtherPlaces),// stub, it should not be used as legacy htts wont have DUI view. // FVCBFT_USELEGACYHTT
  990. WVCONTENT_SPECIAL(c_CommonDocumentsSpecialTaskHeader, c_CommonDocumentsSpecialTaskList, c_DocumentsOtherPlaces, NULL), // FVCBFT_COMMONDOCUMENTS
  991. };
  992. // This structure describes what a Folder Type can control:
  993. //
  994. typedef struct {
  995. BOOL fIncludeThumbstrip;
  996. FOLDERVIEWMODE fvmFew;
  997. FOLDERVIEWMODE fvmMid;
  998. FOLDERVIEWMODE fvmMany;
  999. const SHCOLUMNID* pscidSort;
  1000. int iSortDirection;
  1001. } FVCBFOLDERTYPEDATA;
  1002. // Here are all the Folder Types we know about:
  1003. const FVCBFOLDERTYPEDATA c_rgFolderType[] =
  1004. { // flmstrip // <25 // 25..49 //50... //sort by //sort dir
  1005. { FALSE, FVM_TILE, FVM_TILE, FVM_ICON, &SCID_NAME, 1}, // FVCBFT_DOCUMENTS
  1006. { FALSE, FVM_TILE, FVM_TILE, FVM_ICON, &SCID_NAME, 1}, // FVCBFT_MYDOCUMENTS
  1007. { TRUE, FVM_THUMBNAIL, FVM_THUMBNAIL, FVM_THUMBNAIL, &SCID_NAME, 1}, // FVCBFT_PICTURES
  1008. { TRUE, FVM_THUMBNAIL, FVM_THUMBNAIL, FVM_THUMBNAIL, &SCID_NAME, 1}, // FVCBFT_MYPICTURES
  1009. { TRUE, FVM_THUMBSTRIP,FVM_THUMBNAIL, FVM_THUMBNAIL, &SCID_NAME, 1}, // FVCBFT_PHOTOALBUM
  1010. { FALSE, FVM_TILE, FVM_TILE, FVM_DETAILS, &SCID_NAME, 1}, // FVCBFT_MUSIC
  1011. { FALSE, FVM_THUMBNAIL, FVM_TILE, FVM_LIST, &SCID_NAME, 1}, // FVCBFT_MYMUSIC
  1012. { FALSE, FVM_THUMBNAIL, FVM_THUMBNAIL, FVM_THUMBNAIL, &SCID_NAME, -1}, // FVCBFT_MUSICARTIST
  1013. { FALSE, FVM_TILE, FVM_TILE, FVM_DETAILS, &SCID_NAME, 1}, // FVCBFT_MUSICALBUM, SCID_MUSIC_Track is the same as SCID_NAME
  1014. { FALSE, FVM_THUMBNAIL, FVM_THUMBNAIL, FVM_THUMBNAIL, &SCID_NAME, 1}, // FVCBFT_VIDEOS
  1015. { FALSE, FVM_THUMBNAIL, FVM_THUMBNAIL, FVM_THUMBNAIL, &SCID_NAME, 1}, // FVCBFT_MYVIDEOS
  1016. { FALSE, FVM_THUMBNAIL, FVM_THUMBNAIL, FVM_THUMBNAIL, &SCID_NAME, 1}, // FVCBFT_VIDEOALBUM
  1017. { FALSE, FVM_TILE, FVM_TILE, FVM_ICON, &SCID_NAME, 1}, // FVCBFT_USELEGACYHTT, only for listview state to look like FVCBFT_DOCUMENTS
  1018. { FALSE, FVM_TILE, FVM_TILE, FVM_ICON, &SCID_NAME, 1}, // FVCBFT_COMMONDOCUMENTS
  1019. };
  1020. // This is used to sniff the Folder Type based on folder location:
  1021. typedef struct {
  1022. UINT csidl;
  1023. FVCBFOLDERTYPE ft;
  1024. DWORD dwFlags;
  1025. } FVCBDATA;
  1026. #define FVCBDF_SUBFOLDERS_ONLY 1
  1027. #define FVCBDF_THISFOLDER_ONLY 2
  1028. const FVCBDATA c_rgFolderState[] =
  1029. {
  1030. {CSIDL_COMMON_PICTURES, FVCBFT_PHOTOALBUM, FVCBDF_SUBFOLDERS_ONLY},
  1031. {CSIDL_MYPICTURES, FVCBFT_PHOTOALBUM, FVCBDF_SUBFOLDERS_ONLY},
  1032. {CSIDL_COMMON_PICTURES, FVCBFT_PICTURES, FVCBDF_THISFOLDER_ONLY},
  1033. {CSIDL_MYPICTURES, FVCBFT_MYPICTURES, FVCBDF_THISFOLDER_ONLY},
  1034. {CSIDL_COMMON_MUSIC, FVCBFT_MUSIC, FVCBDF_THISFOLDER_ONLY},
  1035. {CSIDL_MYMUSIC, FVCBFT_MYMUSIC, FVCBDF_THISFOLDER_ONLY},
  1036. {CSIDL_MYMUSIC, FVCBFT_MUSICARTIST, FVCBDF_SUBFOLDERS_ONLY},
  1037. {CSIDL_COMMON_VIDEO, FVCBFT_VIDEOS, 0},
  1038. {CSIDL_MYVIDEO, FVCBFT_MYVIDEOS, 0},
  1039. {CSIDL_COMMON_DOCUMENTS,FVCBFT_COMMONDOCUMENTS, FVCBDF_THISFOLDER_ONLY},
  1040. {CSIDL_PERSONAL, FVCBFT_MYDOCUMENTS, FVCBDF_THISFOLDER_ONLY},
  1041. };
  1042. // these are special folders that used to be web view folders. we override the "support legacy" for this list:
  1043. const UINT c_rgFolderStateNoLegacy[] =
  1044. {
  1045. CSIDL_WINDOWS,
  1046. CSIDL_SYSTEM,
  1047. CSIDL_PROGRAM_FILES,
  1048. };
  1049. // This is used to map desktop.ini's folder type into our Folder Type
  1050. const struct {
  1051. LPCWSTR pszType;
  1052. FVCBFOLDERTYPE ft;
  1053. } c_rgPropBagFolderType[] =
  1054. {
  1055. {STR_TYPE_DOCUMENTS, FVCBFT_DOCUMENTS},
  1056. {STR_TYPE_MYDOCUMENTS, FVCBFT_MYDOCUMENTS},
  1057. {STR_TYPE_PICTURES, FVCBFT_PICTURES},
  1058. {STR_TYPE_MYPICTURES, FVCBFT_MYPICTURES},
  1059. {STR_TYPE_PHOTOALBUM, FVCBFT_PHOTOALBUM},
  1060. {STR_TYPE_MUSIC, FVCBFT_MUSIC},
  1061. {STR_TYPE_MYMUSIC, FVCBFT_MYMUSIC},
  1062. {STR_TYPE_MUSICARTIST, FVCBFT_MUSICARTIST},
  1063. {STR_TYPE_MUSICALBUM, FVCBFT_MUSICALBUM},
  1064. {STR_TYPE_VIDEOS, FVCBFT_VIDEOS},
  1065. {STR_TYPE_MYVIDEOS, FVCBFT_MYVIDEOS},
  1066. {STR_TYPE_VIDEOALBUM, FVCBFT_VIDEOALBUM},
  1067. {STR_TYPE_USELEGACYHTT, FVCBFT_USELEGACYHTT},
  1068. {STR_TYPE_COMMONDOCUMENTS, FVCBFT_COMMONDOCUMENTS},
  1069. };
  1070. const struct
  1071. {
  1072. PERCEIVED gen;
  1073. FVCBFOLDERTYPE ft;
  1074. }
  1075. c_rgSniffType[] =
  1076. {
  1077. {GEN_AUDIO, FVCBFT_MUSIC},
  1078. {GEN_IMAGE, FVCBFT_PHOTOALBUM},
  1079. {GEN_VIDEO, FVCBFT_VIDEOS},
  1080. };
  1081. HRESULT _GetFolderTypeForString(LPCWSTR pszFolderType, FVCBFOLDERTYPE *piType)
  1082. {
  1083. HRESULT hr = E_FAIL;
  1084. for (int i = 0; i < ARRAYSIZE(c_rgPropBagFolderType); i++)
  1085. {
  1086. if (!StrCmpI(c_rgPropBagFolderType[i].pszType, pszFolderType))
  1087. {
  1088. *piType = c_rgPropBagFolderType[i].ft;
  1089. hr = S_OK;
  1090. break;
  1091. }
  1092. }
  1093. return hr;
  1094. }
  1095. HRESULT CFSFolderViewCB::_GetStringForFolderType(int iType, LPWSTR pszFolderType, UINT cchBuf)
  1096. {
  1097. HRESULT hr = E_FAIL;
  1098. for (int i = 0; i < ARRAYSIZE(c_rgPropBagFolderType); i++)
  1099. {
  1100. if (c_rgPropBagFolderType[i].ft == iType)
  1101. {
  1102. hr = StringCchCopy(pszFolderType, cchBuf, c_rgPropBagFolderType[i].pszType);
  1103. break;
  1104. }
  1105. }
  1106. return hr;
  1107. }
  1108. extern HRESULT GetTemplateInfoFromHandle(HANDLE h, UCHAR * pKey, DWORD *pdwSize);
  1109. FVCBFOLDERTYPE _GetFolderType(LPCWSTR pszPath, LPCITEMIDLIST pidl, BOOL fIsSystemFolder)
  1110. {
  1111. // Assume we don't find a match
  1112. FVCBFOLDERTYPE nFolderType = FVCBFT_NOTSPECIFIED;
  1113. WCHAR szFolderType[MAX_PATH];
  1114. szFolderType[0] = 0;
  1115. // peruser is first
  1116. if (FVCBFT_NOTSPECIFIED == nFolderType)
  1117. {
  1118. IPropertyBag *ppb;
  1119. if (SUCCEEDED(SHGetViewStatePropertyBag(pidl, VS_BAGSTR_EXPLORER, SHGVSPB_PERUSER | SHGVSPB_PERFOLDER, IID_PPV_ARG(IPropertyBag, &ppb))))
  1120. {
  1121. SHPropertyBag_ReadStr(ppb, L"FolderType", szFolderType, ARRAYSIZE(szFolderType));
  1122. if (szFolderType[0])
  1123. _GetFolderTypeForString(szFolderType, &nFolderType);
  1124. ppb->Release();
  1125. }
  1126. }
  1127. // next, alluser
  1128. if ((FVCBFT_NOTSPECIFIED == nFolderType) && fIsSystemFolder)
  1129. {
  1130. GetFolderString(pszPath, NULL, szFolderType, ARRAYSIZE(szFolderType), TEXT("FolderType"));
  1131. if (szFolderType[0])
  1132. {
  1133. _GetFolderTypeForString(szFolderType, &nFolderType);
  1134. }
  1135. }
  1136. // Check the location of this folder is next
  1137. //
  1138. if (FVCBFT_NOTSPECIFIED == nFolderType)
  1139. {
  1140. for (int i = 0; i < ARRAYSIZE(c_rgFolderState); i++)
  1141. {
  1142. if (FVCBDF_THISFOLDER_ONLY & c_rgFolderState[i].dwFlags)
  1143. {
  1144. if (PathIsOneOf(pszPath, &(c_rgFolderState[i].csidl), 1))
  1145. {
  1146. nFolderType = c_rgFolderState[i].ft;
  1147. break;
  1148. }
  1149. }
  1150. else if (FVCBDF_SUBFOLDERS_ONLY & c_rgFolderState[i].dwFlags)
  1151. {
  1152. if (PathIsDirectChildOf(MAKEINTRESOURCE(c_rgFolderState[i].csidl), pszPath))
  1153. {
  1154. nFolderType = c_rgFolderState[i].ft;
  1155. break;
  1156. }
  1157. }
  1158. else if (PathIsEqualOrSubFolder(MAKEINTRESOURCE(c_rgFolderState[i].csidl), pszPath))
  1159. {
  1160. nFolderType = c_rgFolderState[i].ft;
  1161. break;
  1162. }
  1163. }
  1164. }
  1165. // Upgrade old webviews to their DUI equivalents, if we can
  1166. if (FVCBFT_NOTSPECIFIED == nFolderType && fIsSystemFolder && SHRestricted(REST_ALLOWLEGACYWEBVIEW))
  1167. {
  1168. // Don't check for legacy webview on our special folders
  1169. if (!PathIsOneOf(pszPath, c_rgFolderStateNoLegacy, ARRAYSIZE(c_rgFolderStateNoLegacy)))
  1170. {
  1171. SFVM_WEBVIEW_TEMPLATE_DATA wvData;
  1172. if (SUCCEEDED(DefaultGetWebViewTemplateFromPath(pszPath, &wvData)))
  1173. {
  1174. if (StrStrI(wvData.szWebView, L"ImgView.htt"))
  1175. {
  1176. nFolderType = FVCBFT_PHOTOALBUM;
  1177. }
  1178. else if (StrStrI(wvData.szWebView, L"classic.htt") ||
  1179. StrStrI(wvData.szWebView, L"default.htt") ||
  1180. StrStrI(wvData.szWebView, L"standard.htt"))
  1181. {
  1182. // map all of these to "documents", since DUI should take care
  1183. // of what the old templates did automatically
  1184. nFolderType = FVCBFT_DOCUMENTS;
  1185. }
  1186. else if (StrStrI(wvData.szWebView, L"folder.htt"))
  1187. {
  1188. LPTSTR pszFilePrefix = StrStrI(wvData.szWebView, L"file://");
  1189. HANDLE hfile = CreateFileWrapW(
  1190. pszFilePrefix && (&pszFilePrefix[6] < &wvData.szWebView[MAX_PATH - 1]) ? &pszFilePrefix[7] : wvData.szWebView,
  1191. GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  1192. if (INVALID_HANDLE_VALUE != hfile)
  1193. {
  1194. DWORD dwSize;
  1195. UCHAR pKey[MD5DIGESTLEN];
  1196. if (SUCCEEDED(GetTemplateInfoFromHandle(hfile, pKey, &dwSize)))
  1197. {
  1198. static const struct {
  1199. UCHAR pKey[MD5DIGESTLEN];
  1200. FVCBFOLDERTYPE nFolderType;
  1201. } c_paLegacyKeyMap[] = {
  1202. { { 0xf6, 0xad, 0x42, 0xbd, 0xfa, 0x92, 0xb6, 0x61, 0x08, 0x13, 0xd3, 0x71, 0x32, 0x18, 0x85, 0xc7 }, FVCBFT_DOCUMENTS }, // Win98 Gold Program Files
  1203. { { 0x80, 0xea, 0xcb, 0xc7, 0x85, 0x1e, 0xbb, 0x99, 0x12, 0x7b, 0x9d, 0xc7, 0x80, 0xa6, 0x55, 0x2f }, FVCBFT_DOCUMENTS }, // Win98 Gold System
  1204. //{ { 0x80, 0xea, 0xcb, 0xc7, 0x85, 0x1e, 0xbb, 0x99, 0x12, 0x7b, 0x9d, 0xc7, 0x80, 0xa6, 0x55, 0x2f }, FVCBFT_DOCUMENTS }, // Win98 Gold Windows
  1205. { { 0x13, 0x0b, 0xe7, 0xaa, 0x42, 0x6f, 0x9c, 0x2e, 0xab, 0x6b, 0x90, 0x77, 0xce, 0x2d, 0xd1, 0x04 }, FVCBFT_DOCUMENTS }, // Win98 Gold - folder.htt
  1206. //{ { 0xf6, 0xad, 0x42, 0xbd, 0xfa, 0x92, 0xb6, 0x61, 0x08, 0x13, 0xd3, 0x71, 0x32, 0x18, 0x85, 0xc7 }, FVCBFT_DOCUMENTS }, // Win98 SE Program Files
  1207. { { 0xc4, 0xab, 0x8f, 0x60, 0xf8, 0xfc, 0x5d, 0x07, 0x9e, 0x16, 0xd8, 0xea, 0x12, 0x2c, 0xad, 0x5c }, FVCBFT_DOCUMENTS }, // Win98 SE System
  1208. //{ { 0xc4, 0xab, 0x8f, 0x60, 0xf8, 0xfc, 0x5d, 0x07, 0x9e, 0x16, 0xd8, 0xea, 0x12, 0x2c, 0xad, 0x5c }, FVCBFT_DOCUMENTS }, // Win98 SE Windows
  1209. //{ { 0x13, 0x0b, 0xe7, 0xaa, 0x42, 0x6f, 0x9c, 0x2e, 0xab, 0x6b, 0x90, 0x77, 0xce, 0x2d, 0xd1, 0x04 }, FVCBFT_DOCUMENTS }, // Win98 SE - folder.htt
  1210. { { 0xef, 0xd0, 0x3e, 0x9e, 0xd8, 0x5e, 0xf3, 0xc5, 0x7e, 0x40, 0xbd, 0x8e, 0x52, 0xbc, 0x9c, 0x67 }, FVCBFT_DOCUMENTS }, // WinME Program Files
  1211. { { 0x49, 0xdb, 0x25, 0x79, 0x7a, 0x5c, 0xb2, 0x8a, 0xe2, 0x57, 0x59, 0xde, 0x2b, 0xd2, 0xa6, 0x70 }, FVCBFT_DOCUMENTS }, // WinME System
  1212. //{ { 0x49, 0xdb, 0x25, 0x79, 0x7a, 0x5c, 0xb2, 0x8a, 0xe2, 0x57, 0x59, 0xde, 0x2b, 0xd2, 0xa6, 0x70 }, FVCBFT_DOCUMENTS }, // WinME Windows
  1213. { { 0x2b, 0xcd, 0xc3, 0x11, 0x72, 0x28, 0x34, 0x46, 0xfa, 0x88, 0x31, 0x34, 0xfc, 0xee, 0x7a, 0x3b }, FVCBFT_DOCUMENTS }, // WinME - classic.htt
  1214. { { 0x68, 0x20, 0xa0, 0xa1, 0x6c, 0xba, 0xbf, 0x67, 0x80, 0xfe, 0x1e, 0x70, 0xdf, 0xcb, 0xd6, 0x34 }, FVCBFT_DOCUMENTS }, // WinME - folder.htt
  1215. { { 0x5e, 0x18, 0xaf, 0x48, 0xb1, 0x9f, 0xb8, 0x12, 0x58, 0x64, 0x4a, 0xa2, 0xf5, 0x12, 0x0f, 0x01 }, FVCBFT_PHOTOALBUM }, // WinME - imgview.htt
  1216. { { 0x33, 0x94, 0x21, 0x3b, 0x17, 0x31, 0x2b, 0xeb, 0xac, 0x93, 0x84, 0x13, 0xb8, 0x1f, 0x95, 0x24 }, FVCBFT_DOCUMENTS }, // WinME - standard.htt
  1217. { { 0x47, 0x03, 0x19, 0xf8, 0x0c, 0x20, 0xc4, 0x4f, 0x10, 0xfd, 0x63, 0xf1, 0x2d, 0x2d, 0x0a, 0xcb }, FVCBFT_DOCUMENTS }, // WinME - starter.htt
  1218. { { 0x60, 0x7d, 0xea, 0xa5, 0xaf, 0x5e, 0xbb, 0x9b, 0x10, 0x18, 0xf9, 0x59, 0x9e, 0x43, 0x89, 0x62 }, FVCBFT_DOCUMENTS }, // Win2k Program Files
  1219. { { 0x1c, 0xa6, 0x22, 0xd4, 0x4a, 0x31, 0x57, 0x93, 0xa7, 0x26, 0x68, 0x3c, 0x87, 0x95, 0x8c, 0xce }, FVCBFT_DOCUMENTS }, // Win2k System32
  1220. //{ { 0x1c, 0xa6, 0x22, 0xd4, 0x4a, 0x31, 0x57, 0x93, 0xa7, 0x26, 0x68, 0x3c, 0x87, 0x95, 0x8c, 0xce }, FVCBFT_DOCUMENTS }, // Win2k Windows (WinNT)
  1221. { { 0x03, 0x43, 0x48, 0xed, 0xe4, 0x9f, 0xd6, 0xc0, 0x58, 0xf7, 0x72, 0x3f, 0x1b, 0xd0, 0xa7, 0x10 }, FVCBFT_DOCUMENTS }, // Win2k - classic.htt
  1222. { { 0xa8, 0x84, 0xf9, 0x37, 0x84, 0x10, 0xde, 0x7c, 0x0b, 0x34, 0x90, 0x37, 0x23, 0x9e, 0x54, 0x35 }, FVCBFT_DOCUMENTS }, // Win2k - folder.htt
  1223. { { 0x75, 0x1f, 0xcf, 0xca, 0xdd, 0xc7, 0x1d, 0xc7, 0xe1, 0xaf, 0x0c, 0x3e, 0x1e, 0xae, 0x18, 0x51 }, FVCBFT_PHOTOALBUM }, // Win2k - imgview.htt
  1224. { { 0xcc, 0x3f, 0x15, 0xce, 0x4b, 0xfa, 0x36, 0xdf, 0x9b, 0xd8, 0x24, 0x82, 0x3a, 0x9c, 0x0b, 0xa7 }, FVCBFT_DOCUMENTS }, // Win2k - standard.htt
  1225. { { 0x6c, 0xd1, 0xbf, 0xcf, 0xf9, 0x24, 0x24, 0x24, 0x22, 0xfa, 0x1a, 0x8d, 0xd2, 0x1a, 0x41, 0x73 }, FVCBFT_DOCUMENTS }, // Win2k - starter.htt
  1226. };
  1227. static const size_t c_nLegacyKeys = ARRAYSIZE(c_paLegacyKeyMap);
  1228. for (size_t i = 0; i < c_nLegacyKeys; i++)
  1229. {
  1230. if (0 == memcmp(pKey, c_paLegacyKeyMap[i].pKey, sizeof(UCHAR) * MD5DIGESTLEN))
  1231. {
  1232. // It's a known legacy folder.htt.
  1233. nFolderType = c_paLegacyKeyMap[i].nFolderType;
  1234. break;
  1235. }
  1236. }
  1237. }
  1238. CloseHandle(hfile);
  1239. }
  1240. // If we can't say it's a known legacy folder.htt...
  1241. if (FVCBFT_NOTSPECIFIED == nFolderType)
  1242. {
  1243. // ...don't map it to a DUI folder type (preserve customizations).
  1244. nFolderType = FVCBFT_USELEGACYHTT;
  1245. }
  1246. }
  1247. else
  1248. {
  1249. nFolderType = FVCBFT_USELEGACYHTT;
  1250. }
  1251. }
  1252. }
  1253. }
  1254. return nFolderType;
  1255. }
  1256. BOOL CFSFolderViewCB::_IsBarricadedFolder()
  1257. {
  1258. BOOL bResult = FALSE;
  1259. TCHAR szPath[MAX_PATH];
  1260. if (SUCCEEDED(_pfsf->_GetPath(szPath, ARRAYSIZE(szPath))))
  1261. {
  1262. const UINT uiFolders[] = {CSIDL_PROGRAM_FILES, CSIDL_WINDOWS, CSIDL_SYSTEM};
  1263. if (PathIsOneOf(szPath, uiFolders, ARRAYSIZE(uiFolders)))
  1264. bResult = TRUE;
  1265. else
  1266. {
  1267. TCHAR szSystemDrive[4];
  1268. ExpandEnvironmentStrings(TEXT("%SystemDrive%\\"), szSystemDrive, ARRAYSIZE(szSystemDrive));
  1269. if (!lstrcmpi(szPath, szSystemDrive))
  1270. bResult = TRUE;
  1271. }
  1272. }
  1273. return bResult;
  1274. }
  1275. static const struct { FVCBFOLDERTYPE type; PCWSTR pszClass; PERCEIVED gen;} c_rgDirectoryClasses[] =
  1276. {
  1277. {FVCBFT_PICTURES, L"Directory.Image", GEN_IMAGE},
  1278. {FVCBFT_MYPICTURES, L"Directory.Image", GEN_IMAGE},
  1279. {FVCBFT_PHOTOALBUM, L"Directory.Image", GEN_IMAGE},
  1280. {FVCBFT_MUSIC, L"Directory.Audio", GEN_AUDIO},
  1281. {FVCBFT_MYMUSIC, L"Directory.Audio", GEN_AUDIO},
  1282. {FVCBFT_MUSICARTIST, L"Directory.Audio", GEN_AUDIO},
  1283. {FVCBFT_MUSICALBUM, L"Directory.Audio", GEN_AUDIO},
  1284. {FVCBFT_VIDEOS, L"Directory.Video", GEN_VIDEO},
  1285. {FVCBFT_MYVIDEOS, L"Directory.Video", GEN_VIDEO},
  1286. {FVCBFT_VIDEOALBUM, L"Directory.Video", GEN_VIDEO},
  1287. };
  1288. LPCWSTR _GetDirectoryClass(LPCWSTR pszPath, LPCITEMIDLIST pidl, BOOL fIsSystemFolder)
  1289. {
  1290. FVCBFOLDERTYPE type = _GetFolderType(pszPath, pidl, fIsSystemFolder);
  1291. if (type != FVCBFT_NOTSPECIFIED)
  1292. {
  1293. for (int i = 0; i < ARRAYSIZE(c_rgDirectoryClasses); i++)
  1294. {
  1295. if (c_rgDirectoryClasses[i].type == type)
  1296. return c_rgDirectoryClasses[i].pszClass;
  1297. }
  1298. }
  1299. return NULL;
  1300. }
  1301. PERCEIVED CFSFolderViewCB::_GetFolderPerceivedType(LPCIDFOLDER pidf)
  1302. {
  1303. PERCEIVED gen = GEN_FOLDER;
  1304. WCHAR szPath[MAX_PATH];
  1305. if (SUCCEEDED(_pfsf->_GetPathForItem(pidf, szPath, ARRAYSIZE(szPath))))
  1306. {
  1307. LPITEMIDLIST pidl = ILCombine(_pfsf->_GetIDList(), (LPCITEMIDLIST)pidf);
  1308. if (pidl)
  1309. {
  1310. FVCBFOLDERTYPE type = _GetFolderType(szPath, pidl, CFSFolder::_IsSystemFolder(pidf));
  1311. if (type != -1)
  1312. {
  1313. for (int i = 0; i < ARRAYSIZE(c_rgDirectoryClasses); i++)
  1314. {
  1315. if (c_rgDirectoryClasses[i].type == type)
  1316. {
  1317. gen = c_rgDirectoryClasses[i].gen;
  1318. break;
  1319. }
  1320. }
  1321. }
  1322. ILFree(pidl);
  1323. }
  1324. }
  1325. return gen;
  1326. }
  1327. HRESULT CFSFolderViewCB::OnEnumeratedItems(DWORD pv, UINT celt, LPCITEMIDLIST* rgpidl)
  1328. {
  1329. // Remember the count of items
  1330. _cItems = celt;
  1331. FVCBFOLDERTYPE nFolderType = FVCBFT_NOTSPECIFIED;
  1332. WCHAR szHere[MAX_PATH];
  1333. if (SUCCEEDED(_pfsf->_GetPath(szHere, ARRAYSIZE(szHere))))
  1334. {
  1335. nFolderType = _GetFolderType(szHere, _pfsf->_GetIDList(), _pfsf->_CheckDefaultIni(NULL, NULL, 0));
  1336. }
  1337. if (FVCBFT_NOTSPECIFIED == nFolderType)
  1338. {
  1339. if (_IsBarricadedFolder())
  1340. {
  1341. nFolderType = FVCBFT_DOCUMENTS;
  1342. }
  1343. }
  1344. // Our location didn't do the trick, so look at the enumerated contents
  1345. if (FVCBFT_NOTSPECIFIED == nFolderType && celt > 0)
  1346. {
  1347. DWORD dwExtCount[ARRAYSIZE(c_rgSniffType)] = {0};
  1348. // look at each pidl -> what type is it
  1349. //
  1350. // But don't look at too many pidls or we really slow down folder
  1351. // creation time. If we can't figure it out in the first 100, give up.
  1352. //
  1353. DWORD dwTotalCount = 0;
  1354. for (UINT n = 0; n < celt && dwTotalCount < 100; n++)
  1355. {
  1356. LPCIDFOLDER pidf = CFSFolder_IsValidID(rgpidl[n]);
  1357. ASSERT(pidf);
  1358. CFileSysItemString fsi(pidf);
  1359. PERCEIVED gen = fsi.PerceivedType();
  1360. if (gen == GEN_FOLDER)
  1361. {
  1362. gen = _GetFolderPerceivedType(pidf);
  1363. }
  1364. for (int i = 0; i < ARRAYSIZE(c_rgSniffType); i++)
  1365. {
  1366. if (c_rgSniffType[i].gen == gen)
  1367. {
  1368. dwExtCount[i]++;
  1369. break;
  1370. }
  1371. }
  1372. if (gen != GEN_FOLDER)
  1373. dwTotalCount++;
  1374. }
  1375. // if we found files we determine the overall folder type
  1376. if (dwTotalCount > 0)
  1377. {
  1378. DWORD dwSixtyPercent = MulDiv(dwTotalCount, 3, 5);
  1379. for (int i = 0; i < ARRAYSIZE(c_rgSniffType); i++)
  1380. {
  1381. if (dwExtCount[i] >= dwSixtyPercent)
  1382. {
  1383. nFolderType = c_rgSniffType[i].ft;
  1384. break;
  1385. }
  1386. }
  1387. }
  1388. }
  1389. // if at this point we've already decided on a folder type, then it either came from sniffing
  1390. // or the folder location and we can safely persist that out.
  1391. // if celt != 0 then we've sniffed it and we dont want to sniff again, so persist that out.
  1392. // otherwise we're in a random folder with 0 elements and we'll sniff it next time.
  1393. BOOL fCommit = (FVCBFT_NOTSPECIFIED != nFolderType) || (celt != 0);
  1394. // Last resort, assume we're a document folder:
  1395. if (FVCBFT_NOTSPECIFIED == nFolderType)
  1396. {
  1397. nFolderType = FVCBFT_DOCUMENTS;
  1398. }
  1399. // store what we found out back into the bag.
  1400. IPropertyBag *ppb;
  1401. if (fCommit && SUCCEEDED(SHGetViewStatePropertyBag(_pfsf->_GetIDList(), VS_BAGSTR_EXPLORER, SHGVSPB_PERUSER | SHGVSPB_PERFOLDER, IID_PPV_ARG(IPropertyBag, &ppb))))
  1402. {
  1403. WCHAR szFolderType[MAX_PATH];
  1404. if (SUCCEEDED(_GetStringForFolderType(nFolderType, szFolderType, ARRAYSIZE(szFolderType))))
  1405. {
  1406. SHPropertyBag_WriteStr(ppb, PROPSTR_FOLDERTYPE, szFolderType);
  1407. }
  1408. ppb->Release();
  1409. }
  1410. _pfsf->_nFolderType = nFolderType;
  1411. return S_OK;
  1412. }
  1413. HRESULT CFSFolderViewCB::OnGetViewData(DWORD pv, UINT uViewMode, SFVM_VIEW_DATA* pvi)
  1414. {
  1415. // Normally whatever defview wants is good for us
  1416. pvi->dwOptions = SFVMQVI_NORMAL;
  1417. // If our sniff type likes THUMBSTRIP, then override defview
  1418. //
  1419. if (FVM_THUMBSTRIP == uViewMode)
  1420. {
  1421. if (c_rgFolderType[_pfsf->_nFolderType].fIncludeThumbstrip)
  1422. {
  1423. pvi->dwOptions = SFVMQVI_INCLUDE;
  1424. }
  1425. }
  1426. return S_OK;
  1427. }
  1428. HRESULT CFSFolderViewCB::OnGetWebViewTemplate(DWORD pv, UINT uViewMode, SFVM_WEBVIEW_TEMPLATE_DATA* pvit)
  1429. {
  1430. HRESULT hr = E_FAIL;
  1431. if (FVCBFT_USELEGACYHTT == _pfsf->_nFolderType)
  1432. {
  1433. TCHAR szHere[MAX_PATH];
  1434. if (SUCCEEDED(_pfsf->_GetPath(szHere, ARRAYSIZE(szHere))) && _pfsf->_CheckDefaultIni(NULL, NULL, 0))
  1435. {
  1436. hr = DefaultGetWebViewTemplateFromPath(szHere, pvit);
  1437. }
  1438. }
  1439. return hr;
  1440. }
  1441. // Note: defview provides this implementation, this is only for testing
  1442. // so the WIA guys can override defview's behavior (and as a way for us
  1443. // to force DUI in the presence of HTML content)
  1444. //
  1445. HRESULT CFSFolderViewCB::OnGetWebViewLayout(DWORD pv, UINT uViewMode, SFVM_WEBVIEW_LAYOUT_DATA* pData)
  1446. {
  1447. HRESULT hr = E_FAIL;
  1448. if (FVCBFT_USELEGACYHTT != _pfsf->_nFolderType)
  1449. {
  1450. ZeroMemory(pData, sizeof(*pData));
  1451. pData->dwLayout = SFVMWVL_NORMAL | SFVMWVL_FILES;
  1452. if (FVM_THUMBSTRIP == uViewMode)
  1453. {
  1454. pData->dwLayout = SFVMWVL_PREVIEW | SFVMWVL_FILES;
  1455. // duiview will do a release on this pointer when the control is destroyed
  1456. _GetPreview3((IPreview3 **)&pData->punkPreview);
  1457. }
  1458. // RAID 242382
  1459. // If we have an image folder, we want to unconditionally hide DefView's
  1460. // default "Print this file" folder task since we will supply a context
  1461. // appropriate "Print pictures" special task.
  1462. //
  1463. // RAID 359567
  1464. // If we have a music folder, we want to unconditionally hide DefView's
  1465. // default "Publish this file" folder task. Not sure the rationale
  1466. // behind this, but perhaps they don't want us to be seen as a Napster.
  1467. //
  1468. // Note:
  1469. // This is a HACK added for Whistler, which should be removed in Blackcomb.
  1470. //
  1471. switch (_pfsf->_nFolderType)
  1472. {
  1473. case FVCBFT_PICTURES:
  1474. case FVCBFT_MYPICTURES:
  1475. case FVCBFT_PHOTOALBUM:
  1476. case FVCBFT_VIDEOS:
  1477. case FVCBFT_MYVIDEOS:
  1478. case FVCBFT_VIDEOALBUM:
  1479. pData->dwLayout |= SFVMWVL_NOPRINT;
  1480. break;
  1481. case FVCBFT_MUSIC:
  1482. case FVCBFT_MYMUSIC:
  1483. case FVCBFT_MUSICARTIST:
  1484. case FVCBFT_MUSICALBUM:
  1485. pData->dwLayout |= SFVMWVL_NOPUBLISH;
  1486. break;
  1487. }
  1488. hr = S_OK;
  1489. }
  1490. return hr;
  1491. }
  1492. HRESULT CFSFolderViewCB::OnGetWebViewContent(DWORD pv, SFVM_WEBVIEW_CONTENT_DATA* pData)
  1493. {
  1494. ZeroMemory(pData, sizeof(*pData));
  1495. // Check if the folder we are currently over is one of the blockaded folders.
  1496. if (_IsBarricadedFolder())
  1497. {
  1498. pData->dwFlags = SFVMWVF_BARRICADE;
  1499. }
  1500. if (c_wvContent[_pfsf->_nFolderType].pwvIntroText)
  1501. Create_IUIElement(c_wvContent[_pfsf->_nFolderType].pwvIntroText, &(pData->pIntroText));
  1502. if (c_wvContent[_pfsf->_nFolderType].pwvSpecialHeader && c_wvContent[_pfsf->_nFolderType].pwvSpecialTaskList)
  1503. Create_IUIElement(c_wvContent[_pfsf->_nFolderType].pwvSpecialHeader, &(pData->pSpecialTaskHeader));
  1504. if (c_wvContent[_pfsf->_nFolderType].pwvFolderHeader && c_wvContent[_pfsf->_nFolderType].pwvFolderTaskList)
  1505. Create_IUIElement(c_wvContent[_pfsf->_nFolderType].pwvFolderHeader, &(pData->pFolderTaskHeader));
  1506. if (c_wvContent[_pfsf->_nFolderType].pdwOtherPlacesList)
  1507. CreateIEnumIDListOnCSIDLs(_pfsf->_pidl, (LPCTSTR *)c_wvContent[_pfsf->_nFolderType].pdwOtherPlacesList, c_wvContent[_pfsf->_nFolderType].cOtherPlacesList, &(pData->penumOtherPlaces));
  1508. return S_OK;
  1509. }
  1510. HRESULT CFSFolderViewCB::OnGetWebViewTasks(DWORD pv, SFVM_WEBVIEW_TASKSECTION_DATA* pTasks)
  1511. {
  1512. ZeroMemory(pTasks, sizeof(*pTasks));
  1513. if (c_wvContent[_pfsf->_nFolderType].pwvSpecialHeader && c_wvContent[_pfsf->_nFolderType].pwvSpecialTaskList)
  1514. {
  1515. Create_IEnumUICommand((IUnknown*)(void*)this, c_wvContent[_pfsf->_nFolderType].pwvSpecialTaskList, c_wvContent[_pfsf->_nFolderType].cSpecialTaskList, &pTasks->penumSpecialTasks);
  1516. }
  1517. if (c_wvContent[_pfsf->_nFolderType].pwvFolderHeader && c_wvContent[_pfsf->_nFolderType].pwvFolderTaskList)
  1518. {
  1519. Create_IEnumUICommand((IUnknown*)(void*)this, c_wvContent[_pfsf->_nFolderType].pwvFolderTaskList, c_wvContent[_pfsf->_nFolderType].cFolderTaskList, &pTasks->penumFolderTasks);
  1520. }
  1521. return S_OK;
  1522. }
  1523. HRESULT CFSFolderViewCB::OnGetWebViewTheme(DWORD pv, SFVM_WEBVIEW_THEME_DATA* pTheme)
  1524. {
  1525. ZeroMemory(pTheme, sizeof(*pTheme));
  1526. pTheme->pszThemeID = c_wvContent[_pfsf->_nFolderType].pszThemeInfo;
  1527. return S_OK;
  1528. }
  1529. HRESULT CFSFolderViewCB::OnDefViewMode(DWORD pv, FOLDERVIEWMODE* pfvm)
  1530. {
  1531. HRESULT hr = E_FAIL;
  1532. IPropertyBag* pPB;
  1533. if (SUCCEEDED(SHGetViewStatePropertyBag(_pfsf->_GetIDList(), VS_BAGSTR_EXPLORER, SHGVSPB_FOLDER, IID_PPV_ARG(IPropertyBag, &pPB))))
  1534. {
  1535. SHELLVIEWID vidDefault;
  1536. if (SUCCEEDED(SHPropertyBag_ReadGUID(pPB, L"ExtShellFolderViews\\Default", &vidDefault)))
  1537. {
  1538. hr = ViewModeFromSVID(&vidDefault, pfvm);
  1539. }
  1540. pPB->Release();
  1541. }
  1542. if (FAILED(hr))
  1543. {
  1544. if (IsOS(OS_SERVERADMINUI))
  1545. *pfvm = FVM_DETAILS; // Server Admin always gets DETAILS
  1546. else if (_cItems < DEFVIEW_FVM_FEW_CUTOFF)
  1547. *pfvm = c_rgFolderType[_pfsf->_nFolderType].fvmFew;
  1548. else if (_cItems < DEFVIEW_FVM_MANY_CUTOFF)
  1549. *pfvm = c_rgFolderType[_pfsf->_nFolderType].fvmMid;
  1550. else
  1551. *pfvm = c_rgFolderType[_pfsf->_nFolderType].fvmMany;
  1552. hr = S_OK;
  1553. }
  1554. return hr;
  1555. }
  1556. HRESULT CFSFolderViewCB::OnGetDeferredViewSettings(DWORD pv, SFVM_DEFERRED_VIEW_SETTINGS* pSettings)
  1557. {
  1558. HRESULT hr = OnDefViewMode(pv, &pSettings->fvm);
  1559. if (SUCCEEDED(hr))
  1560. {
  1561. pSettings->fGroupView = (_cItems >= 100) && !IsEqualSCID(SCID_NAME, *c_rgFolderType[_pfsf->_nFolderType].pscidSort);
  1562. pSettings->iSortDirection = c_rgFolderType[_pfsf->_nFolderType].iSortDirection;
  1563. if (pSettings->fvm == FVM_THUMBNAIL || pSettings->fvm == FVM_THUMBSTRIP || pSettings->fvm == FVM_TILE)
  1564. pSettings->fFlags = FWF_AUTOARRANGE;
  1565. if (FAILED(_pfsf->_MapSCIDToColumn(c_rgFolderType[_pfsf->_nFolderType].pscidSort, &pSettings->uSortCol)))
  1566. pSettings->uSortCol = 0;
  1567. }
  1568. return hr;
  1569. }
  1570. HRESULT CFSFolderViewCB::OnGetCustomViewInfo(DWORD pv, SFVM_CUSTOMVIEWINFO_DATA* pData)
  1571. {
  1572. HRESULT hr = E_FAIL;
  1573. TCHAR szIniFile[MAX_PATH];
  1574. if (_pfsf->_CheckDefaultIni(NULL, szIniFile, ARRAYSIZE(szIniFile)))
  1575. {
  1576. if (PathFileExistsAndAttributes(szIniFile, NULL))
  1577. {
  1578. // Read the custom colors
  1579. //
  1580. const LPCTSTR c_szCustomColors[CRID_COLORCOUNT] =
  1581. {
  1582. TEXT("IconArea_TextBackground"),
  1583. TEXT("IconArea_Text")
  1584. };
  1585. for (int i = 0; i < CRID_COLORCOUNT; i++)
  1586. {
  1587. pData->crCustomColors[i] = GetPrivateProfileInt(TEXT("{BE098140-A513-11D0-A3A4-00C04FD706EC}"), c_szCustomColors[i], CLR_MYINVALID, szIniFile);
  1588. }
  1589. // Read the background image
  1590. TCHAR szTemp1[MAX_PATH];
  1591. if (0 < GetPrivateProfileString(TEXT("{BE098140-A513-11D0-A3A4-00C04FD706EC}") /* VID_FolderState */, TEXT("IconArea_Image"), TEXT(""), szTemp1, ARRAYSIZE(szTemp1), szIniFile))
  1592. {
  1593. TCHAR szTemp2[MAX_PATH];
  1594. SHExpandEnvironmentStrings(szTemp1, szTemp2, ARRAYSIZE(szTemp2)); // expand the env vars if any
  1595. if (SUCCEEDED(_pfsf->_GetPath(szTemp1, ARRAYSIZE(szTemp1))))
  1596. {
  1597. if (PathCombine(szTemp2, szTemp1, szTemp2))
  1598. {
  1599. if (FAILED(StringCchCopy(pData->szIconAreaImage, ARRAYSIZE(pData->szIconAreaImage), szTemp2)))
  1600. {
  1601. pData->szIconAreaImage[0] = NULL;
  1602. }
  1603. }
  1604. }
  1605. }
  1606. // Success if we have any real data
  1607. hr = (*(pData->szIconAreaImage) ||
  1608. pData->crCustomColors[0]!=CLR_MYINVALID ||
  1609. pData->crCustomColors[1]!=CLR_MYINVALID)
  1610. ? S_OK : E_FAIL;
  1611. }
  1612. }
  1613. return hr;
  1614. }
  1615. const CLSID *c_rgFilePages[] = {
  1616. &CLSID_FileTypes,
  1617. &CLSID_OfflineFilesOptions
  1618. };
  1619. // add optional pages to Explore/Options.
  1620. HRESULT SFVCB_OnAddPropertyPages(DWORD pv, SFVM_PROPPAGE_DATA *ppagedata)
  1621. {
  1622. for (int i = 0; i < ARRAYSIZE(c_rgFilePages); i++)
  1623. {
  1624. IShellPropSheetExt * pspse;
  1625. HRESULT hr = SHCoCreateInstance(NULL, c_rgFilePages[i], NULL, IID_PPV_ARG(IShellPropSheetExt, &pspse));
  1626. if (SUCCEEDED(hr))
  1627. {
  1628. pspse->AddPages(ppagedata->pfn, ppagedata->lParam);
  1629. pspse->Release();
  1630. }
  1631. }
  1632. return S_OK;
  1633. }
  1634. HRESULT CFSFolderViewCB::OnGetNotify(DWORD pv, LPITEMIDLIST*wP, LONG*lP)
  1635. {
  1636. if (IsExplorerModeBrowser(_punkSite))
  1637. _lEvents |= SHCNE_FREESPACE; // need free space info here too
  1638. return E_FAIL; // return failure to let base guy do the rest
  1639. }
  1640. STDMETHODIMP CFSFolderViewCB::RealMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  1641. {
  1642. switch (uMsg)
  1643. {
  1644. HANDLE_MSG(0, SFVM_GETCCHMAX, OnGetCCHMax);
  1645. HANDLE_MSG(0, SFVM_WINDOWCREATED, OnWindowCreated);
  1646. HANDLE_MSG(1 , SFVM_INSERTITEM, OnInsertDeleteItem);
  1647. HANDLE_MSG(-1, SFVM_DELETEITEM, OnInsertDeleteItem);
  1648. HANDLE_MSG(0, SFVM_SELCHANGE, OnSelChange);
  1649. HANDLE_MSG(0, SFVM_UPDATESTATUSBAR, OnUpdateStatusBar);
  1650. HANDLE_MSG(0, SFVM_REFRESH, OnRefresh);
  1651. HANDLE_MSG(0, SFVM_SELECTALL, OnSelectAll);
  1652. HANDLE_MSG(0, SFVM_GETWORKINGDIR, OnGetWorkingDir);
  1653. HANDLE_MSG(0, SFVM_ENUMERATEDITEMS, OnEnumeratedItems);
  1654. HANDLE_MSG(0, SFVM_GETVIEWDATA, OnGetViewData);
  1655. HANDLE_MSG(0, SFVM_GETWEBVIEW_TEMPLATE, OnGetWebViewTemplate);
  1656. HANDLE_MSG(0, SFVM_GETWEBVIEWLAYOUT, OnGetWebViewLayout);
  1657. HANDLE_MSG(0, SFVM_GETWEBVIEWCONTENT, OnGetWebViewContent);
  1658. HANDLE_MSG(0, SFVM_GETWEBVIEWTASKS, OnGetWebViewTasks);
  1659. HANDLE_MSG(0, SFVM_GETWEBVIEWTHEME, OnGetWebViewTheme);
  1660. HANDLE_MSG(0, SFVM_DEFVIEWMODE, OnDefViewMode);
  1661. HANDLE_MSG(0, SFVM_GETCUSTOMVIEWINFO, OnGetCustomViewInfo);
  1662. HANDLE_MSG(0, SFVM_ADDPROPERTYPAGES, SFVCB_OnAddPropertyPages);
  1663. HANDLE_MSG(0, SFVM_SIZE, OnSize);
  1664. HANDLE_MSG(0, SFVM_GETPANE, OnGetPane);
  1665. HANDLE_MSG(0, SFVM_GETNOTIFY, OnGetNotify);
  1666. HANDLE_MSG(0, SFVM_GETDEFERREDVIEWSETTINGS, OnGetDeferredViewSettings);
  1667. default:
  1668. return E_FAIL;
  1669. }
  1670. return S_OK;
  1671. }
  1672. STDAPI CFSFolderCallback_Create(CFSFolder *pfsf, IShellFolderViewCB **ppsfvcb)
  1673. {
  1674. *ppsfvcb = new CFSFolderViewCB(pfsf);
  1675. return *ppsfvcb ? S_OK : E_OUTOFMEMORY;
  1676. }