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.

695 lines
20 KiB

  1. #include "shellprv.h"
  2. #include <shellp.h>
  3. #include <sfview.h>
  4. #include "basefvcb.h"
  5. #include "ids.h"
  6. #include "prop.h"
  7. CBaseShellFolderViewCB::CBaseShellFolderViewCB(LPCITEMIDLIST pidl, LONG lEvents)
  8. : _cRef(1), _hwndMain(NULL), _lEvents(lEvents)
  9. {
  10. _pidl = ILClone(pidl);
  11. }
  12. CBaseShellFolderViewCB::~CBaseShellFolderViewCB()
  13. {
  14. ILFree(_pidl); // accpets NULL
  15. }
  16. STDMETHODIMP CBaseShellFolderViewCB::QueryInterface(REFIID riid, void **ppv)
  17. {
  18. static const QITAB qit[] = {
  19. QITABENT(CBaseShellFolderViewCB, IShellFolderViewCB), // IID_IShellFolderViewCB
  20. QITABENT(CBaseShellFolderViewCB, IObjectWithSite), // IID_IObjectWithSite
  21. QITABENT(CBaseShellFolderViewCB, IServiceProvider), // IID_IServiceProvider
  22. { 0 },
  23. };
  24. return QISearch(this, qit, riid, ppv);
  25. }
  26. STDMETHODIMP_(ULONG) CBaseShellFolderViewCB::AddRef()
  27. {
  28. return InterlockedIncrement(&_cRef);
  29. }
  30. STDMETHODIMP_(ULONG) CBaseShellFolderViewCB::Release()
  31. {
  32. ASSERT( 0 != _cRef );
  33. ULONG cRef = InterlockedDecrement(&_cRef);
  34. if ( 0 == cRef )
  35. {
  36. delete this;
  37. }
  38. return cRef;
  39. }
  40. STDMETHODIMP CBaseShellFolderViewCB::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
  41. {
  42. HRESULT hr = RealMessage(uMsg, wParam, lParam);
  43. if (FAILED(hr))
  44. {
  45. switch (uMsg)
  46. {
  47. case SFVM_HWNDMAIN:
  48. _hwndMain = (HWND)lParam;
  49. hr = S_OK;
  50. break;
  51. case SFVM_GETNOTIFY:
  52. *(LPCITEMIDLIST*)wParam = _pidl;
  53. *(LONG*)lParam = _lEvents;
  54. hr = S_OK;
  55. break;
  56. }
  57. }
  58. return hr;
  59. }
  60. class CWrapOldCallback : public CBaseShellFolderViewCB
  61. {
  62. public:
  63. CWrapOldCallback(LPCSFV pcsfv);
  64. STDMETHODIMP RealMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
  65. // IObjectWithSite
  66. STDMETHODIMP SetSite(IUnknown *punkSite);
  67. private:
  68. ~CWrapOldCallback();
  69. LPFNVIEWCALLBACK _pfnCB;
  70. IShellView* _psvOuter;
  71. IShellFolder *_psf;
  72. UINT _fvm;
  73. LPARAM _lSelChangeInfo;
  74. };
  75. CWrapOldCallback::CWrapOldCallback(LPCSFV pcsfv) : CBaseShellFolderViewCB(pcsfv->pidl, pcsfv->lEvents)
  76. {
  77. _psf = pcsfv->pshf;
  78. _psf->AddRef();
  79. _psvOuter = pcsfv->psvOuter;
  80. _fvm = pcsfv->fvm;
  81. _pfnCB = pcsfv->pfnCallback;
  82. }
  83. CWrapOldCallback::~CWrapOldCallback()
  84. {
  85. _psf->Release();
  86. }
  87. // Some older clients may not support IObjectWithSite::SetSite
  88. // For compat send them the old SFVM_SETISFV message
  89. HRESULT CWrapOldCallback::SetSite(IUnknown *punkSite)
  90. {
  91. HRESULT hr = CBaseShellFolderViewCB::SetSite( punkSite );
  92. MessageSFVCB( SFVM_SETISFV, 0, (LPARAM)punkSite );
  93. return hr;
  94. }
  95. STDMETHODIMP CWrapOldCallback::RealMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  96. {
  97. DVSELCHANGEINFO dvsci;
  98. switch (uMsg)
  99. {
  100. case SFVM_DEFVIEWMODE:
  101. if (_fvm)
  102. *(UINT*)lParam = _fvm;
  103. break;
  104. case SFVM_SELCHANGE:
  105. {
  106. SFVM_SELCHANGE_DATA* pSelChange = (SFVM_SELCHANGE_DATA*)lParam;
  107. dvsci.uNewState = pSelChange->uNewState;
  108. dvsci.uOldState = pSelChange->uOldState;
  109. dvsci.plParam = &_lSelChangeInfo;
  110. dvsci.lParamItem = pSelChange->lParamItem;
  111. lParam = (LPARAM)&dvsci;
  112. break;
  113. }
  114. case SFVM_INSERTITEM:
  115. case SFVM_DELETEITEM:
  116. case SFVM_WINDOWCREATED:
  117. dvsci.plParam = &_lSelChangeInfo;
  118. dvsci.lParamItem = lParam;
  119. lParam = (LPARAM)&dvsci;
  120. break;
  121. case SFVM_REFRESH:
  122. case SFVM_SELECTALL:
  123. case SFVM_UPDATESTATUSBAR:
  124. case SFVM_SETFOCUS:
  125. case SFVM_PRERELEASE:
  126. lParam = _lSelChangeInfo;
  127. break;
  128. default:
  129. break;
  130. }
  131. // NOTE: The DVM_ messages are the same as the SFVM_ message
  132. return _pfnCB(_psvOuter, _psf, _hwndMain, uMsg, wParam, lParam);
  133. }
  134. LRESULT _ShellFolderViewMessage(IShellFolderView* psfv, UINT uMsg, LPARAM lParam)
  135. {
  136. UINT uScratch;
  137. switch (uMsg)
  138. {
  139. case SFVM_REARRANGE:
  140. psfv->Rearrange(lParam);
  141. break;
  142. case SFVM_ARRANGEGRID:
  143. psfv->ArrangeGrid();
  144. break;
  145. case SFVM_AUTOARRANGE:
  146. psfv->AutoArrange();
  147. break;
  148. case SFVM_GETAUTOARRANGE:
  149. return psfv->GetAutoArrange() == S_OK;
  150. case SFVM_GETARRANGEPARAM:
  151. psfv->GetArrangeParam(&lParam);
  152. return lParam;
  153. case SFVM_ADDOBJECT:
  154. if (SUCCEEDED(psfv->AddObject((LPITEMIDLIST)lParam, &uScratch))
  155. && (int)uScratch >= 0)
  156. {
  157. // New semantics make a copy of the IDList
  158. ILFree((LPITEMIDLIST)lParam);
  159. return uScratch;
  160. }
  161. return -1;
  162. case SFVM_GETOBJECTCOUNT:
  163. return SUCCEEDED(psfv->GetObjectCount(&uScratch)) ? uScratch : -1;
  164. case SFVM_GETOBJECT:
  165. {
  166. LPITEMIDLIST pidl;
  167. return SUCCEEDED(psfv->GetObject(&pidl, (UINT)lParam)) ? (LPARAM)pidl : NULL;
  168. }
  169. case SFVM_REMOVEOBJECT:
  170. return SUCCEEDED(psfv->RemoveObject((LPITEMIDLIST)lParam, &uScratch)) ? uScratch : -1;
  171. case SFVM_UPDATEOBJECT:
  172. {
  173. LPITEMIDLIST *ppidl = (LPITEMIDLIST*)lParam;
  174. if (SUCCEEDED(psfv->UpdateObject(ppidl[0], ppidl[1], &uScratch))
  175. && (int)uScratch >= 0)
  176. {
  177. // New semantics make a copy of the IDList
  178. ILFree(ppidl[1]);
  179. return uScratch;
  180. }
  181. return -1;
  182. }
  183. case SFVM_REFRESHOBJECT:
  184. {
  185. LPITEMIDLIST *ppidl = (LPITEMIDLIST*)lParam;
  186. return SUCCEEDED(psfv->RefreshObject(ppidl[0], &uScratch)) ? uScratch : -1;
  187. }
  188. case SFVM_SETREDRAW:
  189. psfv->SetRedraw(BOOLFROMPTR(lParam));
  190. break;
  191. case SFVM_GETSELECTEDOBJECTS:
  192. return SUCCEEDED(psfv->GetSelectedObjects((LPCITEMIDLIST**)lParam, &uScratch)) ? uScratch : -1;
  193. case SFVM_GETSELECTEDCOUNT:
  194. return SUCCEEDED(psfv->GetSelectedCount(&uScratch)) ? uScratch : -1;
  195. case SFVM_ISDROPONSOURCE:
  196. return psfv->IsDropOnSource((IDropTarget *)lParam) == S_OK;
  197. case SFVM_MOVEICONS:
  198. psfv->MoveIcons((IDataObject *)lParam);
  199. break;
  200. case SFVM_GETDROPPOINT:
  201. return psfv->GetDropPoint((POINT *)lParam) == S_OK;
  202. case SFVM_GETDRAGPOINT:
  203. return psfv->GetDragPoint((POINT *)lParam) == S_OK;
  204. case SFVM_SETITEMPOS:
  205. {
  206. SFV_SETITEMPOS* psip = (SFV_SETITEMPOS*)lParam;
  207. psfv->SetItemPos(psip->pidl, &psip->pt);
  208. break;
  209. }
  210. case SFVM_ISBKDROPTARGET:
  211. return psfv->IsBkDropTarget((IDropTarget *)lParam) == S_OK;
  212. case SFVM_SETCLIPBOARD:
  213. psfv->SetClipboard(lParam == DFM_CMD_MOVE);
  214. break;
  215. case SFVM_SETPOINTS:
  216. psfv->SetPoints((IDataObject *)lParam);
  217. return 0;
  218. case SFVM_GETITEMSPACING:
  219. return psfv->GetItemSpacing((LPITEMSPACING)lParam) == S_OK;
  220. default:
  221. // -1L is the default return value
  222. return 0;
  223. }
  224. return 1;
  225. }
  226. IShellFolderView* ShellFolderViewFromWindow(HWND hwnd)
  227. {
  228. IShellFolderView* psfv = NULL;
  229. // HPCView sometimes gets confused and passes HWND_BROADCAST as its
  230. // window. We can't let this reach FileCabinet_GetIShellBrowser or
  231. // we end up broadcasting the CWM_GETISHELLBROWSER message and screwing
  232. // up everybody in the system. (Not to mention that it will return TRUE,
  233. // indicating a successful broadcast, and then we fault thinking that
  234. // it's a vtbl.)
  235. if (hwnd && hwnd != HWND_BROADCAST)
  236. {
  237. IShellBrowser* psb = FileCabinet_GetIShellBrowser(hwnd);
  238. // Use !IS_INTRESOURCE() to protect against blatanly bogus values
  239. // that clearly aren't pointers to objects.
  240. if (!IS_INTRESOURCE(psb))
  241. {
  242. IShellView* psv;
  243. if (SUCCEEDED(psb->QueryActiveShellView(&psv)))
  244. {
  245. psv->QueryInterface(IID_PPV_ARG(IShellFolderView, &psfv));
  246. psv->Release();
  247. }
  248. }
  249. }
  250. return psfv;
  251. }
  252. STDAPI_(HWND) ShellFolderViewWindow(HWND hwnd)
  253. {
  254. HWND hwndRet = NULL;
  255. IShellBrowser *psb = FileCabinet_GetIShellBrowser(hwnd);
  256. if (psb)
  257. {
  258. IShellView *psv;
  259. if (SUCCEEDED(psb->QueryActiveShellView(&psv)))
  260. {
  261. IUnknown_GetWindow(psv, &hwndRet);
  262. psv->Release();
  263. }
  264. }
  265. return hwndRet;
  266. }
  267. // undoced shell32 export
  268. STDAPI_(IShellFolderViewCB *) SHGetShellFolderViewCB(HWND hwnd)
  269. {
  270. ASSERT(0);
  271. return NULL; // no one calls this (search of the NT code finds no callers)
  272. }
  273. // old msg based way of programming defview (pre dates IShellFolderView)
  274. STDAPI_(LRESULT) SHShellFolderView_Message(HWND hwnd, UINT uMsg, LPARAM lParam)
  275. {
  276. LRESULT lret = 0;
  277. IShellFolderView* psfv = ShellFolderViewFromWindow(hwnd);
  278. if (psfv)
  279. {
  280. lret = _ShellFolderViewMessage(psfv, uMsg, lParam);
  281. psfv->Release();
  282. }
  283. return lret;
  284. }
  285. STDAPI SHCreateShellFolderViewEx(LPCSFV pcsfv, IShellView **ppsv)
  286. {
  287. SFV_CREATE sfvc;
  288. sfvc.cbSize = sizeof(sfvc);
  289. sfvc.pshf = pcsfv->pshf;
  290. sfvc.psvOuter = pcsfv->psvOuter;
  291. sfvc.psfvcb = pcsfv->pfnCallback ? new CWrapOldCallback(pcsfv) : NULL;
  292. HRESULT hr = SHCreateShellFolderView(&sfvc, ppsv);
  293. if (sfvc.psfvcb)
  294. sfvc.psfvcb->Release();
  295. return hr;
  296. }
  297. STDAPI_(void) InitializeStatus(IUnknown *psite)
  298. {
  299. IShellBrowser *psb;
  300. if (SUCCEEDED(IUnknown_QueryService(psite, SID_STopLevelBrowser, IID_PPV_ARG(IShellBrowser, &psb))))
  301. {
  302. LONG_PTR nParts = 0, n;
  303. psb->SendControlMsg(FCW_STATUS, SB_GETPARTS, 0, 0, &nParts);
  304. for (n = 0; n < nParts; n ++)
  305. {
  306. psb->SendControlMsg(FCW_STATUS, SB_SETTEXT, n, (LPARAM)TEXT(""), NULL);
  307. psb->SendControlMsg(FCW_STATUS, SB_SETICON, n, (LPARAM)NULL, NULL);
  308. }
  309. psb->SendControlMsg(FCW_STATUS, SB_SETPARTS, 0, 0, NULL);
  310. psb->Release();
  311. }
  312. }
  313. //
  314. // The status bar partitioning has undergone several changes. Here's
  315. // what we've got right now:
  316. //
  317. // Pane 0 = Selection - all remaining space
  318. // Pane 1 = Size - just big enough to say 9,999 bytes (11 chars)
  319. // Pane 2 = Zone - just big enough to hold longest zone
  320. //
  321. STDAPI_(void) ResizeStatus(IUnknown *psite, UINT cx)
  322. {
  323. IShellBrowser *psb;
  324. if (SUCCEEDED(IUnknown_QueryService(psite, SID_STopLevelBrowser, IID_PPV_ARG(IShellBrowser, &psb))))
  325. {
  326. HWND hwndStatus;
  327. if (SUCCEEDED(psb->GetControlWindow(FCW_STATUS, &hwndStatus)) && hwndStatus)
  328. {
  329. RECT rc;
  330. int ciParts[3];
  331. int ciBorders[3];
  332. int cxPart;
  333. GetClientRect(hwndStatus, &rc);
  334. // Must also take status bar borders into account.
  335. psb->SendControlMsg(FCW_STATUS, SB_GETBORDERS, 0, (LPARAM)ciBorders, NULL);
  336. // We build the panes from right to left.
  337. ciParts[2] = -1;
  338. // The Zones part
  339. cxPart = ciBorders[0] + ZoneComputePaneSize(hwndStatus) + ciBorders[2];
  340. ciParts[1] = rc.right - cxPart;
  341. // The Size part
  342. HDC hdc = GetDC(hwndStatus);
  343. HFONT hfPrev = SelectFont(hdc, GetWindowFont(hwndStatus));
  344. SIZE siz;
  345. GetTextExtentPoint32(hdc, TEXT("0"), 1, &siz);
  346. SelectObject(hdc, hfPrev);
  347. ReleaseDC(hwndStatus, hdc);
  348. cxPart = ciBorders[0] + siz.cx * (11 + 2); // "+2" for slop
  349. ciParts[0] = ciParts[1] - cxPart;
  350. //
  351. // If we underflowed, then give up and just give everybody
  352. // one third.
  353. //
  354. if (ciParts[0] < 0)
  355. {
  356. ciParts[0] = rc.right / 3;
  357. ciParts[1] = 2 * ciParts[0];
  358. }
  359. psb->SendControlMsg(FCW_STATUS, SB_SETPARTS, ARRAYSIZE(ciParts), (LPARAM)ciParts, NULL);
  360. }
  361. psb->Release();
  362. }
  363. }
  364. STDAPI_(void) SetStatusText(IUnknown *psite, LPCTSTR *ppszText, int iStart, int iEnd)
  365. {
  366. IShellBrowser *psb;
  367. if (SUCCEEDED(IUnknown_QueryService(psite, SID_STopLevelBrowser, IID_PPV_ARG(IShellBrowser, &psb))))
  368. {
  369. for (; iStart <= iEnd; iStart++)
  370. {
  371. LPCTSTR psz;
  372. if (ppszText)
  373. {
  374. psz = *ppszText;
  375. ppszText++;
  376. }
  377. else
  378. psz = c_szNULL;
  379. psb->SendControlMsg(FCW_STATUS, SB_SETTEXT, (WPARAM)iStart, (LPARAM)psz, NULL);
  380. }
  381. psb->Release();
  382. }
  383. }
  384. STDAPI_(void) ViewShowSelectionState(IUnknown *psite, FSSELCHANGEINFO *pfssci)
  385. {
  386. TCHAR szTemp[20], szBytes[30];
  387. LPTSTR pszStatus = NULL;
  388. if (pfssci->nItems > 1)
  389. {
  390. pszStatus = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_FSSTATUSSELECTED),
  391. AddCommas(pfssci->nItems, szTemp, ARRAYSIZE(szTemp)));
  392. }
  393. if (pfssci->cNonFolders)
  394. ShortSizeFormat64(pfssci->cbBytes, szBytes, ARRAYSIZE(szBytes));
  395. else
  396. szBytes[0] = 0;
  397. LPCTSTR rgpsz[] = { pszStatus, szBytes };
  398. SetStatusText(psite, rgpsz, 0, 1);
  399. if (pszStatus)
  400. LocalFree(pszStatus);
  401. }
  402. HRESULT _UpdateDiskFreeSpace(LPCITEMIDLIST pidlFolder, FSSELCHANGEINFO *pfssci)
  403. {
  404. IShellFolder2 *psf2;
  405. LPCITEMIDLIST pidlLast;
  406. HRESULT hr = SHBindToIDListParent(pidlFolder, IID_PPV_ARG(IShellFolder2, &psf2), &pidlLast);
  407. if (SUCCEEDED(hr))
  408. {
  409. ULONGLONG ullTotalFreeCaller;
  410. hr = GetLongProperty(psf2, pidlLast, &SCID_FREESPACE, &ullTotalFreeCaller);
  411. if (SUCCEEDED(hr))
  412. {
  413. pfssci->cbFree = ullTotalFreeCaller;
  414. }
  415. else if (!ILIsEmpty(pidlFolder) && !ILIsEmpty(_ILNext(pidlFolder)))
  416. {
  417. // if there are at least 2 segments in the IDList rip off the
  418. // last item and recurse to compute the size
  419. LPITEMIDLIST pidl = ILCloneParent(pidlFolder);
  420. if (pidl)
  421. {
  422. hr = _UpdateDiskFreeSpace(pidl, pfssci);
  423. ILFree(pidl);
  424. }
  425. }
  426. psf2->Release();
  427. }
  428. return hr;
  429. }
  430. void _ShowNoSelectionState(IUnknown *psite, LPCITEMIDLIST pidlFolder, FSSELCHANGEINFO *pfssci)
  431. {
  432. TCHAR szTemp[30], szTempHidden[30], szFreeSpace[30];
  433. UINT ids = IDS_FSSTATUSBASE;
  434. // Assume we don't need freespace info
  435. szFreeSpace[0] = 0;
  436. // See if we need the freespace info (idDrive != -1)
  437. ULONGLONG cbFree = -1;
  438. if (pidlFolder && IsExplorerModeBrowser(psite))
  439. {
  440. if (pfssci->cbFree == -1)
  441. _UpdateDiskFreeSpace(pidlFolder, pfssci);
  442. // cbFree couldstill be -1 if GetDiskFreeSpace didn't get any info
  443. cbFree = pfssci->cbFree;
  444. if (cbFree != -1)
  445. {
  446. ShortSizeFormat64(pfssci->cbFree, szFreeSpace, ARRAYSIZE(szFreeSpace));
  447. ids += DIDS_FSSPACE; // Also show freespace
  448. }
  449. }
  450. // hidden files -> show "and nn hidden".
  451. if (pfssci->cHiddenFiles)
  452. ids += DIDS_FSHIDDEN;
  453. // Get the status string
  454. LPTSTR pszStatus = ShellConstructMessageString(HINST_THISDLL, IntToPtr_(LPCTSTR, ids),
  455. AddCommas(pfssci->cFiles, szTemp, ARRAYSIZE(szTemp)),
  456. AddCommas(pfssci->cHiddenFiles, szTempHidden, ARRAYSIZE(szTempHidden)),
  457. szFreeSpace);
  458. // Get the size portion
  459. StrFormatByteSize64(pfssci->cbSize, szTemp, ARRAYSIZE(szTemp));
  460. LPCTSTR rgpsz[] = { pszStatus, szTemp };
  461. SetStatusText(psite, rgpsz, 0, 1);
  462. LocalFree(pszStatus); // may be NULL
  463. }
  464. STDAPI ViewUpdateStatusBar(IUnknown *psite, LPCITEMIDLIST pidlFolder, FSSELCHANGEINFO *pfssci)
  465. {
  466. HRESULT hr = S_OK;
  467. switch (pfssci->nItems)
  468. {
  469. case 0:
  470. _ShowNoSelectionState(psite, pidlFolder, pfssci);
  471. hr = S_OK;
  472. break;
  473. case 1:
  474. ViewShowSelectionState(psite, pfssci); //Set the Size only.
  475. hr = SFVUSB_INITED; // Make defview set infotip as text
  476. break;
  477. default:
  478. ViewShowSelectionState(psite, pfssci);
  479. hr = S_OK;
  480. break;
  481. }
  482. return hr;
  483. }
  484. STDAPI_(void) ViewInsertDeleteItem(IShellFolder2 *psf, FSSELCHANGEINFO *pfssci, LPCITEMIDLIST pidl, int iMul)
  485. {
  486. ULONGLONG ullSize;
  487. if (SUCCEEDED(GetLongProperty(psf, pidl, &SCID_SIZE, &ullSize)))
  488. {
  489. pfssci->cFiles += iMul;
  490. pfssci->cbSize += iMul * ullSize;
  491. if (pfssci->cFiles <= 0)
  492. {
  493. pfssci->cbSize = 0;
  494. pfssci->cFiles = 0;
  495. }
  496. }
  497. else
  498. {
  499. // means a delete all
  500. pfssci->cFiles = 0;
  501. pfssci->cbSize = 0;
  502. pfssci->nItems = 0;
  503. pfssci->cbBytes = 0;
  504. pfssci->cNonFolders = 0;
  505. pfssci->cHiddenFiles = 0;
  506. }
  507. }
  508. STDAPI_(void) ViewSelChange(IShellFolder2 *psf, SFVM_SELCHANGE_DATA* pdvsci, FSSELCHANGEINFO *pfssci)
  509. {
  510. ULONGLONG ullSize;
  511. LPCITEMIDLIST pidl = (LPCITEMIDLIST)pdvsci->lParamItem;
  512. if (SUCCEEDED(GetLongProperty(psf, pidl, &SCID_SIZE, &ullSize)))
  513. {
  514. int iMul = -1;
  515. // Update selection count
  516. if (pdvsci->uNewState & LVIS_SELECTED)
  517. iMul = 1;
  518. else
  519. ASSERT(0 != pfssci->nItems);
  520. // assert that soemthing changed
  521. ASSERT((pdvsci->uOldState & LVIS_SELECTED) != (pdvsci->uNewState & LVIS_SELECTED));
  522. pfssci->nItems += iMul;
  523. pfssci->cbBytes += (iMul * ullSize);
  524. if (!SHGetAttributes(psf, pidl, SFGAO_FOLDER))
  525. pfssci->cNonFolders += iMul;
  526. }
  527. }
  528. STDAPI DefaultGetWebViewTemplateFromHandler(LPCTSTR pszKey, SFVM_WEBVIEW_TEMPLATE_DATA* pvit)
  529. {
  530. HRESULT hr = S_OK;
  531. TCHAR szKey[200];
  532. wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("%s\\shellex\\ExtShellFolderViews\\{5984FFE0-28D4-11CF-AE66-08002B2E1262}"), pszKey);
  533. DWORD cbSize = sizeof(pvit->szWebView);
  534. if (ERROR_SUCCESS == SHGetValueW(HKEY_CLASSES_ROOT, szKey, TEXT("PersistMoniker"), NULL, pvit->szWebView, &cbSize))
  535. {
  536. //if the %UserAppData% exists, expand it!
  537. hr = ExpandOtherVariables(pvit->szWebView, ARRAYSIZE(pvit->szWebView));
  538. }
  539. else
  540. {
  541. hr = E_FAIL;
  542. }
  543. return hr;
  544. }
  545. STDAPI DefaultGetWebViewTemplateFromClsid(REFCLSID clsid, SFVM_WEBVIEW_TEMPLATE_DATA* pvit)
  546. {
  547. TCHAR szHandler[6+40] = TEXT("CLSID\\"); // 6 for "CLSID\\", 40 for GUID
  548. SHStringFromGUID(clsid, &szHandler[6], ARRAYSIZE(szHandler)-6);
  549. return DefaultGetWebViewTemplateFromHandler(szHandler, pvit);
  550. }
  551. STDAPI DefaultGetWebViewTemplateFromPath(LPCTSTR pszDir, SFVM_WEBVIEW_TEMPLATE_DATA* pvit)
  552. {
  553. SHFOLDERCUSTOMSETTINGS fcs = {0};
  554. TCHAR szPath[MAX_PATH+40]; // slop for "webview://file://"
  555. fcs.dwSize = sizeof(fcs);
  556. fcs.dwMask = FCSM_WEBVIEWTEMPLATE;
  557. fcs.pszWebViewTemplate = szPath;
  558. fcs.cchWebViewTemplate = ARRAYSIZE(szPath);
  559. HRESULT hr = SHGetSetFolderCustomSettings(&fcs, pszDir, FCS_READ);
  560. if (SUCCEEDED(hr))
  561. {
  562. LPTSTR pszPath = szPath;
  563. // We want to allow relative paths for the file: protocol
  564. //
  565. if (0 == StrCmpNI(TEXT("file://"), pszPath, 7)) // ARRAYSIZE(TEXT("file://"))
  566. {
  567. pszPath += 7; // ARRAYSIZE(TEXT("file://"))
  568. }
  569. // for webview:// compatibility, keep this working:
  570. else if (0 == StrCmpNI(TEXT("webview://file://"), pszPath, 17)) // ARRAYSIZE(TEXT("webview://file://"))
  571. {
  572. pszPath += 17; // ARRAYSIZE(TEXT("webview://file://"))
  573. }
  574. // handle relative references...
  575. PathCombine(pszPath, pszDir, pszPath);
  576. StrCpyN(pvit->szWebView, szPath, ARRAYSIZE(pvit->szWebView));
  577. }
  578. return hr;
  579. }