Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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