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.

1606 lines
46 KiB

  1. #include "priv.h"
  2. #include "hlframe.h"
  3. #include "dochost.h"
  4. #include "bindcb.h"
  5. #include "iface.h"
  6. #include "resource.h"
  7. #include "idhidden.h"
  8. #include "shdocfl.h"
  9. const ITEMIDLIST s_idNull = { {0} };
  10. extern HRESULT VariantClearLazy(VARIANTARG *pvarg);
  11. LPWSTR URLFindExtensionW(LPCWSTR pszURL, int * piLen);
  12. #define DM_CACHETRACE 0
  13. #define DM_ZONECROSSING 0
  14. #define NAVMSG3(psz, x, y) TraceMsg(0, "NAV::%s %x %x", psz, x, y)
  15. #define PAINTMSG(psz,x) TraceMsg(0, "TraceMsgPAINT::%s %x", psz, x)
  16. #define JMPMSG(psz, psz2) TraceMsg(0, "TraceMsgCDOV::%s %s", psz, psz2)
  17. #define JMPMSG2(psz, x) TraceMsg(0, "TraceMsgCDOV::%s %x", psz, x)
  18. #define DOFMSG(psz) TraceMsg(0, "TraceMsgDOF::%s", psz)
  19. #define DOFMSG2(psz, x) TraceMsg(0, "TraceMsgDOF::%s %x", psz, x)
  20. #define URLMSG(psz) TraceMsg(0, "TraceMsgDOF::%s", psz)
  21. #define URLMSG2(psz, x) TraceMsg(0, "TraceMsgDOF::%s %x", psz, x)
  22. #define URLMSG3(psz, x, y) TraceMsg(0, "TraceMsgDOF::%s %x %x", psz, x, y)
  23. #define BSCMSG(psz, i, j) TraceMsg(0, "TraceMsgBSC::%s %x %x", psz, i, j)
  24. #define BSCMSG3(psz, i, j, k) TraceMsg(0, "TraceMsgBSC::%s %x %x %x", psz, i, j, k)
  25. #define BSCMSG4(psz, i, j, k, l) TraceMsg(0, "TraceMsgBSC::%s %x %x %x %x", psz, i, j, k, l)
  26. #define BSCMSGS(psz, sz) TraceMsg(0, "TraceMsgBSC::%s %s", psz, sz)
  27. #define OIPSMSG(psz) TraceMsg(0, "TraceMsgOIPS::%s", psz)
  28. #define OIPSMSG3(psz, sz, p) TraceMsg(0, "TraceMsgOIPS::%s %s,%x", psz, sz,p)
  29. #define VIEWMSG(psz) TraceMsg(0, "CDOV::%s", psz)
  30. #define VIEWMSG2(psz,xx) TraceMsg(0, "CDOV::%s %x", psz,xx)
  31. #define CACHEMSG(psz, d) TraceMsg(0, "CDocObjectCtx::%s %d", psz, d)
  32. #define OPENMSG(psz) TraceMsg(0, "OPENING %s", psz)
  33. #define OPENMSG2(psz, x) TraceMsg(0, "OPENING %s %x", psz, x)
  34. #define HFRMMSG(psz) TraceMsg(0, "HFRM::%s", psz)
  35. #define HFRMMSG2(psz, x, y) TraceMsg(0, "HFRM::%s %x %x", psz, x, y)
  36. #define MNKMSG(psz, psz2) TraceMsg(0, "MNK::%s (%s)", psz, psz2)
  37. #define CHAINMSG(psz, x) TraceMsg(0, "CHAIN::%s %x", psz, x)
  38. #define SHVMSG(psz, x, y) TraceMsg(0, "SHV::%s %x %x", psz, x, y)
  39. #define HOMEMSG(psz, psz2, x) TraceMsg(0, "HOME::%s %s %x", psz, psz2, x)
  40. #define SAVEMSG(psz, x) TraceMsg(0, "SAVE::%s %x", psz, x)
  41. #define PERFMSG(psz, x) TraceMsg(TF_SHDPERF, "PERF::%s %d msec", psz, x)
  42. // this saves the view information for this shell view class
  43. typedef struct {
  44. UINT cbSize;
  45. BOOL fCoolbar:1;
  46. BOOL fToolbar:1;
  47. BOOL fStatusbar:1;
  48. } IEVIEWINFO;
  49. class CDocObjectView :
  50. /* Group 1 */ public IShellView2, public IDropTarget
  51. , public IViewObject, public IAdviseSink
  52. , public IOleCommandTarget
  53. , public IDocViewSite
  54. , public IPrivateOleObject
  55. , public IPersistFolder
  56. , public IServiceProvider
  57. {
  58. protected:
  59. CDocObjectHost* _pdoh;
  60. IDocHostObject* _pdho;
  61. UINT _cRef;
  62. IShellFolder *_psf;
  63. IShellBrowser* _psb;
  64. IOleCommandTarget* _pctShellBrowser;
  65. FOLDERSETTINGS _fs;
  66. LPITEMIDLIST _pidl;
  67. LPTSTR _pszLocation;
  68. UINT _uiCP;
  69. IShellView * _psvPrev;
  70. // Advisory connection
  71. IAdviseSink *_padvise;
  72. DWORD _advise_aspect;
  73. DWORD _advise_advf;
  74. BOOL _fInHistory : 1;
  75. BOOL _fSaveViewState : 1;
  76. BOOL _fIsGet : 1;
  77. BOOL _fCanCache : 1;
  78. BOOL _fCanCacheFetched : 1;
  79. BOOL _fPrevViewIsDocView : 1;
  80. BOOL _fSelfDragging : 1; // DocObject is the drag source
  81. SYSTEMTIME _stLastRefresh;
  82. HWND _hwndParent;
  83. UINT _uState;
  84. // DragContext
  85. DWORD _dwDragEffect;
  86. ~CDocObjectView();
  87. void _RestoreViewSettings();
  88. void _SaveViewState();
  89. void _GetViewSettings(IEVIEWINFO* pievi);
  90. int _ShowControl(UINT idControl, int idCmd);
  91. void _CreateDocObjHost(IShellView * psvPrev);
  92. void _CompleteDocHostPassing(IShellView *psvPrev, HRESULT hres);
  93. BOOL _CanUseCache();
  94. void _SetLastRefreshTime() { GetSystemTime(&_stLastRefresh); };
  95. void _ConnectHostSink();
  96. void _DisconnectHostSink();
  97. public:
  98. CDocObjectView(LPCITEMIDLIST pidl, IShellFolder *psf);
  99. // *** IUnknown methods ***
  100. STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj);
  101. STDMETHODIMP_(ULONG) AddRef(void) ;
  102. STDMETHODIMP_(ULONG) Release(void);
  103. // *** IOleWindow methods ***
  104. STDMETHODIMP GetWindow(HWND * lphwnd);
  105. STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode);
  106. // *** IShellView methods ***
  107. STDMETHODIMP TranslateAccelerator(LPMSG lpmsg);
  108. STDMETHODIMP EnableModelessSV(BOOL fEnable);
  109. STDMETHODIMP UIActivate(UINT uState);
  110. STDMETHODIMP Refresh();
  111. STDMETHODIMP CreateViewWindow(IShellView *lpPrevView,
  112. LPCFOLDERSETTINGS lpfs, IShellBrowser * psb,
  113. RECT * prcView, HWND *phWnd);
  114. STDMETHODIMP DestroyViewWindow();
  115. STDMETHODIMP GetCurrentInfo(LPFOLDERSETTINGS lpfs);
  116. STDMETHODIMP AddPropertySheetPages(DWORD dwReserved,
  117. LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam);
  118. STDMETHODIMP SaveViewState();
  119. STDMETHODIMP SelectItem(LPCITEMIDLIST pidlItem, UINT uFlags);
  120. STDMETHODIMP GetItemObject(UINT uItem, REFIID riid, void **ppv);
  121. STDMETHODIMP GetView(SHELLVIEWID* pvid, ULONG uView) ;
  122. STDMETHODIMP CreateViewWindow2(LPSV2CVW2_PARAMS lpParams) ;
  123. STDMETHODIMP HandleRename(LPCITEMIDLIST pidl) ;
  124. STDMETHODIMP SelectAndPositionItem(LPCITEMIDLIST pidlItem, UINT uFlags, POINT *ppt) {
  125. return E_NOTIMPL;
  126. }
  127. // IViewObject
  128. STDMETHODIMP Draw(DWORD, LONG, void *, DVTARGETDEVICE *, HDC, HDC,
  129. const RECTL *, const RECTL *, BOOL (*)(ULONG_PTR), ULONG_PTR);
  130. STDMETHODIMP GetColorSet(DWORD, LONG, void *, DVTARGETDEVICE *,
  131. HDC, LOGPALETTE **);
  132. STDMETHODIMP Freeze(DWORD, LONG, void *, DWORD *);
  133. STDMETHODIMP Unfreeze(DWORD);
  134. STDMETHODIMP SetAdvise(DWORD, DWORD, IAdviseSink *);
  135. STDMETHODIMP GetAdvise(DWORD *, DWORD *, IAdviseSink **);
  136. // IAdviseSink
  137. STDMETHODIMP_(void) OnDataChange(FORMATETC *, STGMEDIUM *);
  138. STDMETHODIMP_(void) OnViewChange(DWORD dwAspect, LONG lindex);
  139. STDMETHODIMP_(void) OnRename(IMoniker *);
  140. STDMETHODIMP_(void) OnSave();
  141. STDMETHODIMP_(void) OnClose();
  142. // IOleCommandTarget
  143. STDMETHODIMP QueryStatus(const GUID *pguidCmdGroup,
  144. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext);
  145. STDMETHODIMP Exec(const GUID *pguidCmdGroup,
  146. DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut);
  147. // IDropTarget
  148. STDMETHODIMP DragEnter(
  149. IDataObject *pdtobj,
  150. DWORD grfKeyState,
  151. POINTL pt,
  152. DWORD *pdwEffect);
  153. STDMETHODIMP DragOver(
  154. DWORD grfKeyState,
  155. POINTL pt,
  156. DWORD *pdwEffect);
  157. STDMETHODIMP DragLeave(void);
  158. STDMETHODIMP Drop(
  159. IDataObject *pdtobj,
  160. DWORD grfKeyState,
  161. POINTL pt,
  162. DWORD *pdwEffect);
  163. // IDocViewSite
  164. STDMETHODIMP OnSetTitle(VARIANTARG *pvTitle);
  165. // IPrivateOleObject
  166. STDMETHODIMP SetExtent( DWORD dwDrawAspect, SIZEL *psizel);
  167. STDMETHODIMP GetExtent( DWORD dwDrawAspect, SIZEL *psizel);
  168. // IPersist methods
  169. STDMETHODIMP GetClassID(CLSID *pclsid);
  170. // IPersistFolder methods
  171. STDMETHODIMP Initialize(LPCITEMIDLIST pidl);
  172. // IServiceProvider methods
  173. STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void ** ppvObj);
  174. };
  175. //--------------------------------------------------------------------------
  176. // Detecting a memory leak
  177. //--------------------------------------------------------------------------
  178. CDocObjectView::~CDocObjectView()
  179. {
  180. // just in case
  181. DestroyViewWindow();
  182. if (_pidl)
  183. {
  184. ILFree(_pidl);
  185. _pidl = NULL;
  186. }
  187. ATOMICRELEASE(_psf);
  188. if (_pszLocation)
  189. {
  190. LocalFree(_pszLocation);
  191. _pszLocation = NULL;
  192. }
  193. ATOMICRELEASE(_padvise);
  194. ATOMICRELEASE(_psvPrev);
  195. TraceMsg(TF_SHDLIFE, "dtor CDocObjectView(%x) being destructed", this);
  196. }
  197. CDocObjectView::CDocObjectView(LPCITEMIDLIST pidl, IShellFolder* psf) :
  198. _psf(psf),
  199. _cRef(1)
  200. {
  201. TraceMsg(TF_SHDLIFE, "ctor CDocObjectView(%x) being constructed", this);
  202. _dwDragEffect = DROPEFFECT_NONE;
  203. if (pidl)
  204. {
  205. _pidl = ILClone(pidl);
  206. if (_pidl)
  207. {
  208. #ifndef UNIX
  209. WCHAR wszPath[MAX_URL_STRING];
  210. #else
  211. WCHAR wszPath[MAX_URL_STRING] = TEXT("");
  212. #endif
  213. if(IEILGetFragment(_pidl, wszPath, SIZECHARS(wszPath)))
  214. {
  215. _pszLocation = StrDup(wszPath);
  216. }
  217. _uiCP = IEILGetCP(_pidl);
  218. }
  219. }
  220. ASSERT(psf);
  221. if (_psf) {
  222. _psf->AddRef();
  223. }
  224. }
  225. HRESULT CDocObjectView_Create(IShellView** ppvOut, IShellFolder * psf, LPCITEMIDLIST pidl)
  226. {
  227. *ppvOut = new CDocObjectView(pidl, psf);
  228. return (*ppvOut) ? S_OK : E_OUTOFMEMORY;
  229. }
  230. HRESULT CDocObjectView::GetWindow(HWND * lphwnd)
  231. {
  232. *lphwnd = NULL;
  233. if (_pdoh)
  234. return _pdoh->GetWindow(lphwnd);
  235. return S_OK;
  236. }
  237. HRESULT CDocObjectView::ContextSensitiveHelp(BOOL fEnterMode)
  238. {
  239. // NOTES: This is optional
  240. return E_NOTIMPL; // As specified in Kraig's document (optional)
  241. }
  242. // IShellView::TranslateAccelerator
  243. // From Browser -> DocView -> DocObject
  244. HRESULT CDocObjectView::TranslateAccelerator(LPMSG lpmsg)
  245. {
  246. HRESULT hres = S_FALSE;
  247. if (_pdoh)
  248. hres = _pdoh->_xao.TranslateAccelerator(lpmsg);
  249. if (hres == S_FALSE && lpmsg->message == WM_KEYDOWN) {
  250. HWND hwndFocus = GetFocus();
  251. HWND hwndView = NULL;
  252. if(_pdoh) //WARNING ZEKEL i found this NULL
  253. _pdoh->GetWindow(&hwndView);
  254. if (hwndView && IsChildOrSelf(hwndView, hwndFocus) == S_OK) {
  255. switch (lpmsg->wParam) {
  256. case VK_BACK:
  257. TranslateMessage(lpmsg);
  258. DispatchMessage(lpmsg);
  259. hres = NOERROR;
  260. break;
  261. }
  262. }
  263. }
  264. return hres;
  265. }
  266. // IShellView::EnableModelessSV
  267. // From Browser -> DocView -> DocObject
  268. HRESULT CDocObjectView::EnableModelessSV(BOOL fEnable)
  269. {
  270. HRESULT hres = S_OK;
  271. // We have no modeless window to be enabled/disabled
  272. TraceMsg(0, "sdv TR - ::EnableModelessSV(%d) called", fEnable);
  273. if (_pdoh) {
  274. hres = _pdoh->_xao.EnableModeless(fEnable);
  275. TraceMsg(0, "sdv TR - _piact->EnableModeless returned %x", hres);
  276. }
  277. return hres;
  278. }
  279. HRESULT CDocObjectView::UIActivate(UINT uState)
  280. {
  281. HRESULT hres = E_FAIL;
  282. if (_pdoh)
  283. {
  284. hres = _pdoh->UIActivate(uState, _fPrevViewIsDocView);
  285. }
  286. _uState = uState;
  287. return hres;
  288. }
  289. HRESULT CDocObjectView::Refresh()
  290. {
  291. if (_pdoh)
  292. {
  293. VARIANT v = {0};
  294. v.vt = VT_I4;
  295. v.lVal = OLECMDIDF_REFRESH_NO_CACHE;
  296. // send this to exec so that it will update last refresh time.
  297. // all refresh to dochost should go through our own exec
  298. return Exec(NULL, OLECMDID_REFRESH, OLECMDEXECOPT_PROMPTUSER, &v, NULL);
  299. }
  300. return S_OK;
  301. }
  302. // Return:
  303. // S_OK: It is a folder shortcut and ppidlTarget is filled out if provided.
  304. // S_FALSE: It is not a folder shortcut and ppidlTarget is filled with NULL if provided.
  305. // FAILED: An error occured trying to detect.
  306. //
  307. // Don't use this function if there is a better way. Look into using
  308. // IBrowserFrameOptions. -BryanSt
  309. HRESULT IsFolderShortcutPidl(IN LPCITEMIDLIST pidl)
  310. {
  311. IShellFolder * psf = NULL;
  312. HRESULT hr = IEBindToObject(pidl, &psf);
  313. if (SUCCEEDED(hr))
  314. {
  315. IShellLinkA * psl;
  316. hr = psf->QueryInterface(IID_PPV_ARG(IShellLinkA, &psl));
  317. if (SUCCEEDED(hr))
  318. {
  319. hr = S_OK;
  320. psl->Release();
  321. }
  322. else
  323. hr = S_FALSE; // It's not a folder shortcut.
  324. psf->Release();
  325. }
  326. return hr;
  327. }
  328. // WARNING: This function explicitely creates URLMON monikers
  329. // because that's what the caller needs. Some NSEs will
  330. // support IShellFolder::BindToObject(IMoniker)
  331. // but this function doesn't use that logic intentionally.
  332. //
  333. STDAPI _URLMONMonikerFromPidl(LPCITEMIDLIST pidl, IMoniker** ppmk, BOOL* pfFileProtocol)
  334. {
  335. TCHAR szPath[MAX_URL_STRING];
  336. HRESULT hres = E_UNEXPECTED;
  337. *ppmk = NULL;
  338. *pfFileProtocol = FALSE;
  339. MNKMSG(TEXT("_URLMONMonikerFromPidl"), TEXT("called"));
  340. AssertMsg((S_OK != IsFolderShortcutPidl(pidl)), TEXT("We shouldn't get Folder Shortcuts here because we don't deref them to get the target. And we should never need to."));
  341. // Is this a child of the "Internet Explorer" name space?
  342. if (!IsURLChild(pidl, TRUE))
  343. {
  344. // No, so we want to get the display name to use to
  345. // create the moniker. We will try to turn it into
  346. // an URL if it isn't already an URL.
  347. // NOTE: We don't try IEBindToObject(pidl, IID_IMoniker)
  348. // because the caller requires that this
  349. // IMoniker come from URLMON.
  350. HRESULT hrTemp = SHGetPathFromIDList(pidl, szPath);
  351. AssertMsg(SUCCEEDED(hrTemp), TEXT("_URLMONMonikerFromPidl() failed SHGetPathFromIDList() which is really bad because we probably won't be able to create a moniker from it. We will try to create a URLMON moniker below."));
  352. if (SUCCEEDED(hrTemp))
  353. {
  354. // this should never be a fully qualified URL
  355. DWORD cchPath = ARRAYSIZE(szPath);
  356. ASSERT(URL_SCHEME_INVALID == GetUrlScheme(szPath));
  357. if(SUCCEEDED(hres = UrlCreateFromPath(szPath, szPath, &cchPath, 0)))
  358. {
  359. MNKMSG(TEXT("_URLMONMonikerFromPidl Creating File Moniker"), szPath);
  360. }
  361. *pfFileProtocol = TRUE;
  362. }
  363. }
  364. else
  365. {
  366. // Yes so we are guaranteed this is from the "Internet Explorer"
  367. // name space so remove Fragment hidden itemID.
  368. // We do this because we navigate to the fragment later,
  369. // after the page is downloaded. This is also needed
  370. // for delegates of the IE name space. (FTP is one example of
  371. // a delegate).
  372. ASSERT(pidl);
  373. ASSERT(!ILIsEmpty(_ILNext(pidl))); // Make sure it's not the start page URL.
  374. LPITEMIDLIST pidlClone = ILClone(pidl);
  375. if (pidlClone)
  376. {
  377. // we dont want to pass the fragment into URLMON
  378. // so we pull it off before calling into GDN.
  379. // Note that pidlClone needs to be the pidlTarget
  380. // of folder shortcuts or the dislpay name will
  381. // be the file system path of the folder shortcut
  382. // if at the top level.
  383. ILRemoveHiddenID(pidlClone, IDLHID_URLFRAGMENT);
  384. IEGetDisplayName(pidlClone, szPath, SHGDN_FORPARSING);
  385. hres = S_OK;
  386. ILFree(pidlClone);
  387. }
  388. }
  389. if (SUCCEEDED(hres))
  390. {
  391. if (szPath[0])
  392. {
  393. hres = MonikerFromString(szPath, ppmk);
  394. }
  395. else
  396. {
  397. ASSERT(FALSE);
  398. hres = E_UNEXPECTED;
  399. }
  400. }
  401. return hres;
  402. }
  403. HRESULT CDocObjectView::HandleRename(LPCITEMIDLIST pidl)
  404. {
  405. return E_NOTIMPL;
  406. }
  407. HRESULT CDocObjectView::CreateViewWindow(IShellView *psvPrev,
  408. LPCFOLDERSETTINGS lpfs, IShellBrowser * psb,
  409. RECT * prcView, HWND *phWnd)
  410. {
  411. SV2CVW2_PARAMS cParams;
  412. cParams.cbSize = SIZEOF(SV2CVW2_PARAMS);
  413. cParams.psvPrev = psvPrev;
  414. cParams.pfs = lpfs;
  415. cParams.psbOwner = psb;
  416. cParams.prcView = prcView;
  417. cParams.pvid = NULL;
  418. HRESULT hres = CreateViewWindow2(&cParams);
  419. *phWnd = cParams.hwndView;
  420. IOleWindow *pOleWindow;
  421. // need top level frame available for D&D
  422. HRESULT hr = IUnknown_QueryService(_psb, SID_STopLevelBrowser, IID_PPV_ARG(IOleWindow, &pOleWindow));
  423. if(SUCCEEDED(hr))
  424. {
  425. ASSERT(pOleWindow);
  426. pOleWindow->GetWindow(&_hwndParent);
  427. pOleWindow->Release();
  428. }
  429. return(hres);
  430. }
  431. void CDocObjectView::_CompleteDocHostPassing(IShellView * psvPrev, HRESULT hresBinding)
  432. {
  433. BOOL fPassedSV = FALSE;
  434. // If there was a previous shell view, see if it was our class.
  435. //
  436. if (psvPrev)
  437. {
  438. CDocObjectView * pdovPrev;
  439. HRESULT hres = psvPrev->QueryInterface(CLSID_CDocObjectView, (void **)&pdovPrev);
  440. if (SUCCEEDED(hres))
  441. {
  442. // Previous shell view is also an instance of CDocObjectView,
  443. // Remember that for optimization later.
  444. //
  445. _fPrevViewIsDocView = TRUE;
  446. // it was, and we have the same doc host as they do.
  447. // we've succeeded in taking over, so null them out if we
  448. // succeeeded in our bind. null ourselves out if we failed
  449. //
  450. if (pdovPrev->_pdoh == _pdoh)
  451. {
  452. if (SUCCEEDED(hresBinding))
  453. {
  454. pdovPrev->_DisconnectHostSink(); // just in case
  455. _ConnectHostSink(); // just in case
  456. ATOMICRELEASET(pdovPrev->_pdoh, CDocObjectHost);
  457. }
  458. else
  459. {
  460. _DisconnectHostSink(); // unhook
  461. pdovPrev->_ConnectHostSink(); // kick other guy
  462. ATOMICRELEASET(_pdoh, CDocObjectHost);
  463. }
  464. fPassedSV = TRUE;
  465. }
  466. pdovPrev->Release();
  467. }
  468. }
  469. if (!fPassedSV)
  470. {
  471. if (FAILED(hresBinding))
  472. {
  473. DestroyViewWindow();
  474. }
  475. }
  476. }
  477. BOOL CDocObjectView::_CanUseCache()
  478. {
  479. // NOTE: this function is more like _DontHaveToHitTheNet()
  480. // the name is legacy from the objectcache.
  481. if (!_fCanCacheFetched)
  482. {
  483. _fCanCache = TRUE;
  484. _fCanCacheFetched = TRUE;
  485. _fIsGet = TRUE;
  486. IServiceProvider *psp;
  487. _psb->QueryInterface(IID_PPV_ARG(IServiceProvider, &psp));
  488. if (psp)
  489. {
  490. IBindStatusCallback *pbsc;
  491. if (SUCCEEDED(GetTopLevelBindStatusCallback(psp, &pbsc)))
  492. {
  493. BINDINFO binfo;
  494. ZeroMemory(&binfo, sizeof(BINDINFO));
  495. binfo.cbSize = sizeof(BINDINFO);
  496. DWORD grfBINDF = BINDF_ASYNCHRONOUS;
  497. HRESULT hr = pbsc->GetBindInfo(&grfBINDF, &binfo);
  498. if (SUCCEEDED(hr))
  499. {
  500. if (grfBINDF & (BINDF_GETNEWESTVERSION | BINDF_RESYNCHRONIZE))
  501. {
  502. _fCanCache = FALSE;
  503. }
  504. _fIsGet = (binfo.dwBindVerb == BINDVERB_GET);
  505. ReleaseBindInfo(&binfo);
  506. }
  507. pbsc->Release();
  508. }
  509. // I believe that failing to get the Bindstatuscallback should
  510. // not happen since we no longer use the object cache.
  511. // and if it does, then we no that we didnt have to repost
  512. // or something similar
  513. psp->Release();
  514. }
  515. }
  516. return _fCanCache;
  517. }
  518. void CDocObjectView::_ConnectHostSink()
  519. {
  520. if (_pdoh)
  521. {
  522. IAdviseSink *pSink;
  523. if (FAILED(_pdoh->GetAdvise(NULL, NULL, &pSink)))
  524. pSink = NULL;
  525. if (pSink != (IAdviseSink *)this)
  526. _pdoh->SetAdvise(DVASPECT_CONTENT, ADVF_PRIMEFIRST, this);
  527. if (pSink)
  528. pSink->Release();
  529. }
  530. }
  531. void CDocObjectView::_DisconnectHostSink()
  532. {
  533. IAdviseSink *pSink;
  534. // paranoia: only blow away the advise sink if it is still us
  535. if (_pdoh && SUCCEEDED(_pdoh->GetAdvise(NULL, NULL, &pSink)) && pSink)
  536. {
  537. if (pSink == (IAdviseSink *)this)
  538. _pdoh->SetAdvise(0, 0, NULL);
  539. pSink->Release();
  540. }
  541. OnViewChange(DVASPECT_CONTENT, -1);
  542. }
  543. #if 0
  544. BOOL _SameLocations(LPSTR pszLoc1, LPSTR pszLoc2)
  545. {
  546. // if they're both the same pointer (null)
  547. // or if they both exist and have the same string, then
  548. // they are the same location
  549. if (pszLoc1 == pszLoc2 ||
  550. (pszLoc1 && pszLoc2 &&
  551. !lstrcmp(pszLoc1, pszLoc2))) {
  552. return TRUE;
  553. }
  554. return FALSE;
  555. }
  556. #endif
  557. //
  558. // This function either (1) Create a new CDocObjectHost or (2) reuse it from
  559. // the previous view. If also returns the DisplayName of previous moniker.
  560. //
  561. void CDocObjectView::_CreateDocObjHost(IShellView * psvPrev)
  562. {
  563. BOOL fWindowOpen = FALSE;
  564. // if there was a previous shell view, see if it was our class.
  565. if (psvPrev)
  566. {
  567. CDocObjectView * pdovPrev = NULL;
  568. HRESULT hres = psvPrev->QueryInterface(CLSID_CDocObjectView, (void **)&pdovPrev);
  569. if (SUCCEEDED(hres))
  570. {
  571. CDocObjectHost * pPrevDOH = pdovPrev->_pdoh;
  572. ASSERT(_psb);
  573. ASSERT(_psb == pdovPrev->_psb);
  574. // find out if we should be saving the view state when we close
  575. // if the one we're coming from says yes, then we'll take over that
  576. // job instead of them.
  577. //
  578. _fSaveViewState = pdovPrev->_fSaveViewState;
  579. pdovPrev->_fSaveViewState = FALSE;
  580. //
  581. // if this is a local anchor navigation,
  582. // we treat it substantially differently.
  583. // we can reuse the DOH and the OLE Object that
  584. // it holds. - zekel - 31-JUL-97
  585. //
  586. // WARNING: we should not reuse these objects for any other
  587. // reason than a local anchor (fragment) navigation.
  588. // we used to be a lot more lenient about reusing the DOH
  589. // but i think this was mostly because of the old object cache.
  590. //
  591. // we check for equal pidls so that we know we are on
  592. // the same URL. we require that _pszLocation be set.
  593. // this is for Netscape compat. this means that anytime
  594. // we get a navigate to ourself it will refresh completely
  595. // if there was no fragment. we also check to make sure that
  596. // the binding does not require us to hit the net for
  597. // this request.
  598. //
  599. // 08-11-1999 (scotrobe): We now reuse the DOH if the
  600. // hosted document has indicated that it knows how to
  601. // navigate on its own.
  602. //
  603. if (_pidl && pdovPrev->_pidl && pPrevDOH &&
  604. (pPrevDOH->_fDocCanNavigate
  605. || ( _pszLocation && IEILIsEqual(_pidl, pdovPrev->_pidl, TRUE)
  606. && _CanUseCache())))
  607. {
  608. IBrowserService *pbs;
  609. if (SUCCEEDED(_psb->QueryInterface(IID_PPV_ARG(IBrowserService, &pbs))))
  610. {
  611. DWORD dwFlags = 0;
  612. // If the document doesn't know how to navigate, then this may
  613. // mean that this navigation was delegated from the document.
  614. // In that case, if we have gotten this far, that means that
  615. // _pszLocation is set. If it is and this is a delegated navigation
  616. // (i.e., the navigation wasn't due to a link in a non-html document)
  617. // we must create a new document.
  618. //
  619. if (!pPrevDOH->_fDocCanNavigate)
  620. {
  621. pbs->GetFlags(&dwFlags);
  622. }
  623. if (!(dwFlags & BSF_DELEGATEDNAVIGATION))
  624. {
  625. //
  626. // if SetHistoryObject() fails, then that means there is already
  627. // an object there for us to use. this means that we should
  628. // not treat this as a local anchor navigation. and
  629. // we shouldnt reuse the DOH even though the pidl is identical
  630. //
  631. // TRUE is passed to SetHistoryObject even if this is not a
  632. // local anchor. In the case that this is not a local anchor,
  633. // the document (Trident) handles the navigation. Therefore,
  634. // the document will take care of updating the travel log and
  635. // the fIsLocalAnchor flag is ignored.
  636. //
  637. if (SUCCEEDED(pbs->SetHistoryObject(pPrevDOH->_pole,
  638. !pPrevDOH->_fDocCanNavigate ? TRUE : FALSE)))
  639. {
  640. TraceMsg(TF_TRAVELLOG, "CDOV::CreateDocObjHost reusing current DOH on local anchor navigate");
  641. //
  642. // we cant update in ActivateNow because at that point
  643. // we have already switched the dochost over to the new
  644. // (reused) view. so we need to update the entry now
  645. //
  646. // The fact that the hosted document can navigate on its own,
  647. // implies that it will take care of updating the travel log.
  648. //
  649. if (!pPrevDOH->_fDocCanNavigate)
  650. {
  651. ITravelLog * ptl;
  652. pbs->GetTravelLog(&ptl);
  653. if (ptl)
  654. {
  655. ptl->UpdateEntry(pbs, TRUE);
  656. ptl->Release();
  657. }
  658. }
  659. pdovPrev->_DisconnectHostSink(); // we will connect below
  660. // same target! pass the docobj host
  661. _pdoh = pPrevDOH;
  662. _pdoh->AddRef();
  663. if (_pdoh->_fDocCanNavigate)
  664. {
  665. _pdoh->OnInitialUpdate();
  666. }
  667. if ((_pdoh->_dwAppHack & BROWSERFLAG_SUPPORTTOP) && !_pszLocation)
  668. {
  669. // if there's no location for us to go to, and
  670. // we're traversing in the same document,
  671. // assume top.
  672. //
  673. _pszLocation = StrDup(TEXT("#top"));
  674. _uiCP = CP_ACP;
  675. }
  676. }
  677. pbs->Release();
  678. }
  679. }
  680. }
  681. // In the case where we are opening a non-html mime type
  682. // in a new window, we need to pass the _fWindowOpen
  683. // flag from the previous docobject host to the new
  684. // docobject host. This is needed so that if we are opening
  685. // a file outside of IE in a new window, we'll know to close
  686. // the newly created IE afterwards.
  687. // The problem is that there isn't really a good place to
  688. // clear this flag since it has to remain set from one
  689. // instance of the docobject host to the next. This causes
  690. // us to get into the situation where we'll close the browser
  691. // window if we click on a link to a file that opens outside
  692. // of IE after opening a new window for an html file.
  693. // The bottom line is that we only need to pass this flag to
  694. // the new docobject host if we opening an non-html mime type
  695. // in a new window.
  696. //
  697. if (!_pdoh && pPrevDOH && pPrevDOH->_fDelegatedNavigation)
  698. {
  699. fWindowOpen = pPrevDOH->_fWindowOpen;
  700. }
  701. //
  702. // FEATURE: We should take care of _pibscNC as well
  703. // to 'chain' the IBindStatusCallback.
  704. //
  705. pdovPrev->Release();
  706. }
  707. }
  708. // if we didn't pass the docobj host, create a new one and
  709. // pass the doc context
  710. if (!_pdoh)
  711. {
  712. ASSERT(_psb);
  713. _pdoh = new CDocObjectHost(fWindowOpen);
  714. // Reset host navigation flag in the browser
  715. //
  716. IUnknown_Exec(_psb,
  717. &CGID_DocHostCmdPriv,
  718. DOCHOST_DOCCANNAVIGATE,
  719. 0, NULL, NULL);
  720. }
  721. if (_pdoh)
  722. {
  723. _ConnectHostSink();
  724. }
  725. }
  726. extern HRESULT TargetQueryService(IUnknown *punk, REFIID riid, void **ppvObj);
  727. HRESULT CDocObjectView::CreateViewWindow2(LPSV2CVW2_PARAMS lpParams)
  728. {
  729. HRESULT hres = S_OK;
  730. IShellView * psvPrev = lpParams->psvPrev;
  731. LPCFOLDERSETTINGS lpfs = lpParams->pfs;
  732. IShellBrowser * psb = lpParams->psbOwner;
  733. RECT * prcView = lpParams->prcView;
  734. HWND UNALIGNED * phWnd = &lpParams->hwndView;
  735. if (_pdoh || !_pidl)
  736. {
  737. *phWnd = NULL;
  738. ASSERT(0);
  739. return E_UNEXPECTED;
  740. }
  741. _fs = *lpfs;
  742. ASSERT(_psb==NULL);
  743. _psb = psb;
  744. psb->AddRef();
  745. ASSERT(_pctShellBrowser==NULL);
  746. _psb->QueryInterface(IID_IOleCommandTarget, (void **)&_pctShellBrowser);
  747. //if somebody that is not a ShellBrowser (like the FileOpenBrowser)
  748. // tries to use us, we want to block them. we will fault later on
  749. // if we dont have the right stuff.
  750. if (!_pctShellBrowser)
  751. return E_UNEXPECTED;
  752. // prime the cache bit. this needs to be done while we're *the* guy navigating.
  753. // otherwise, if we ask later when there's a different pending navigation,
  754. // we'll get his info
  755. _CanUseCache();
  756. _SetLastRefreshTime();
  757. // Either create a new CDocObjectHost or reuse it from the previous view
  758. // and set it in _pdoh.
  759. _CreateDocObjHost(psvPrev);
  760. if (!_pdoh || !_pdoh->InitHostWindow(this, psb, prcView))
  761. {
  762. ATOMICRELEASE(_psb);
  763. _pctShellBrowser->Release();
  764. _pctShellBrowser = NULL;
  765. return E_OUTOFMEMORY;
  766. }
  767. _pdoh->GetWindow(phWnd);
  768. ASSERT(NULL == _pdho);
  769. _pdoh->QueryInterface(IID_IDocHostObject, (void **)&_pdho);
  770. IMoniker* pmk = NULL;
  771. BOOL fFileProtocol;
  772. hres = ::_URLMONMonikerFromPidl(_pidl, &pmk, &fFileProtocol);
  773. if (SUCCEEDED(hres) && EVAL(pmk))
  774. {
  775. hres = _pdoh->SetTarget(pmk, _uiCP, _pszLocation, _pidl, psvPrev, fFileProtocol);
  776. _psvPrev = psvPrev;
  777. if (_psvPrev)
  778. _psvPrev->AddRef();
  779. #ifdef NON_NATIVE_FRAMES
  780. _CompleteDocHostPassing(psvPrev, hres);
  781. #endif
  782. pmk->Release();
  783. }
  784. return hres;
  785. }
  786. void CDocObjectView::_GetViewSettings(IEVIEWINFO* pievi)
  787. {
  788. DWORD dwType, dwSize;
  789. // REVIEW: Currently, we have on setting for all docobj class views
  790. // (everything hosted by shdocvw). we may want to subclassify them by clsid
  791. // of the docobj or maybe special case mshtml...
  792. dwSize = sizeof(IEVIEWINFO);
  793. if (SHGetValueGoodBoot(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
  794. TEXT("ViewSettings"), &dwType, (PBYTE)pievi, &dwSize) == ERROR_SUCCESS)
  795. {
  796. if (pievi->cbSize != sizeof(IEVIEWINFO))
  797. {
  798. goto DefaultInfo;
  799. }
  800. }
  801. else
  802. {
  803. DefaultInfo:
  804. // can't count on 0 init because registry could have read stuff, but
  805. // of the wrong size (corruption)
  806. pievi->fToolbar = FALSE;
  807. pievi->fCoolbar = TRUE;
  808. pievi->fStatusbar = TRUE;
  809. }
  810. }
  811. void CDocObjectView::_SaveViewState()
  812. {
  813. IEVIEWINFO ievi;
  814. int id;
  815. // First ask up if it is ok for us to save view state. If we get the return value of
  816. // S_FALSE bail as we were told no.
  817. if (_pctShellBrowser &&
  818. (_pctShellBrowser->Exec(&CGID_Explorer, SBCMDID_MAYSAVEVIEWSTATE, 0, NULL, NULL) == S_FALSE))
  819. return;
  820. // first load to preserve things we're not going to set
  821. _GetViewSettings(&ievi);
  822. ievi.cbSize = sizeof(ievi);
  823. id = _ShowControl(FCW_STATUS, SBSC_QUERY);
  824. // bail if it's not supported
  825. if (id == -1)
  826. return;
  827. ievi.fStatusbar = (id == SBSC_SHOW);
  828. id = _ShowControl(FCW_TOOLBAR, SBSC_QUERY);
  829. if (id != -1) {
  830. // this is allowed to fail if toolbar isn't supported (ie30 case)
  831. ievi.fToolbar = (id == SBSC_SHOW);
  832. }
  833. id = _ShowControl(FCW_INTERNETBAR, SBSC_QUERY);
  834. if (id != -1) {
  835. // this is allowed to fail if coolbar isn't supported
  836. ievi.fCoolbar = (id == SBSC_SHOW);
  837. }
  838. SHSetValue(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
  839. TEXT("ViewSettings"), REG_BINARY, (const BYTE *)&ievi, sizeof(ievi));
  840. }
  841. int CDocObjectView::_ShowControl(UINT idControl, int idCmd)
  842. {
  843. VARIANTARG var;
  844. VariantInit(&var);
  845. var.vt = VT_I4;
  846. var.lVal = MAKELONG(idControl, idCmd);
  847. if (_pctShellBrowser &&
  848. SUCCEEDED(_pctShellBrowser->Exec(&CGID_Explorer, SBCMDID_SHOWCONTROL, OLECMDEXECOPT_DODEFAULT,
  849. &var, &var)))
  850. return var.lVal;
  851. return -1;
  852. }
  853. HRESULT CDocObjectView::DestroyViewWindow()
  854. {
  855. ATOMICRELEASE(_pdho);
  856. if (_pdoh)
  857. {
  858. BOOL fDestroyHost = TRUE;
  859. if (_psb && _pdoh->_pwb)
  860. {
  861. DWORD dwFlags;
  862. _pdoh->_pwb->GetFlags(&dwFlags);
  863. if (dwFlags & BSF_HTMLNAVCANCELED)
  864. {
  865. IShellView * psvCur;
  866. HRESULT hr = _psb->QueryActiveShellView(&psvCur);
  867. if (S_OK == hr)
  868. {
  869. CDocObjectView * pdovCur;
  870. hr = psvCur->QueryInterface(CLSID_CDocObjectView, (void**)&pdovCur);
  871. if (S_OK == hr)
  872. {
  873. ASSERT(this != pdovCur);
  874. if (_pdoh == pdovCur->_pdoh)
  875. {
  876. fDestroyHost = FALSE;
  877. }
  878. pdovCur->Release();
  879. }
  880. psvCur->Release();
  881. }
  882. }
  883. }
  884. if (fDestroyHost)
  885. {
  886. TraceMsg(DM_WARNING, "CDocObjectView::DestroyViewWindow(): Destroying Host Window");
  887. _DisconnectHostSink();
  888. if (_fSaveViewState)
  889. _SaveViewState();
  890. _pdoh->DestroyHostWindow();
  891. }
  892. ATOMICRELEASET(_pdoh, CDocObjectHost);
  893. }
  894. ATOMICRELEASE(_pctShellBrowser);
  895. // Note that we should release _psb at the very end.
  896. ATOMICRELEASE(_psb);
  897. return S_OK;
  898. }
  899. HRESULT CDocObjectView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
  900. {
  901. *lpfs = _fs;
  902. return S_OK;
  903. }
  904. HRESULT CDocObjectView::AddPropertySheetPages(DWORD dwReserved,
  905. LPFNADDPROPSHEETPAGE lpfn, LPARAM lParam)
  906. {
  907. if (_pdoh)
  908. return _pdoh->AddPages(lpfn, lParam);
  909. return E_FAIL;
  910. }
  911. HRESULT CDocObjectView::SaveViewState()
  912. {
  913. // No viewsate to be saved
  914. return S_OK;
  915. }
  916. HRESULT CDocObjectView::SelectItem(LPCITEMIDLIST pidlItem, UINT uFlags)
  917. {
  918. // No item
  919. return E_FAIL;
  920. }
  921. //
  922. // IShellView::GetItemObject
  923. //
  924. // For this IShellView object, the only valid uItem is SVGIO_BACKGROUND,
  925. // which allows the browser to access an interface pointer to the
  926. // currently active document object.
  927. //
  928. // Notes:
  929. // The browser should be aware that IShellView::CreateViewWindow might be
  930. // asynchronous. This method will fail with E_FAIL if the document is not
  931. // instanciated yet.
  932. //
  933. HRESULT CDocObjectView::GetItemObject(UINT uItem, REFIID riid, void **ppv)
  934. {
  935. HRESULT hres = E_INVALIDARG;
  936. *ppv = NULL; // assumes error
  937. switch(uItem)
  938. {
  939. case SVGIO_BACKGROUND:
  940. if (_pdoh)
  941. {
  942. if (_pdoh->_pole)
  943. {
  944. hres = _pdoh->_pole->QueryInterface(riid, ppv);
  945. break;
  946. }
  947. else if (_pdoh->_punkPending)
  948. {
  949. hres = _pdoh->_punkPending->QueryInterface(riid, ppv);
  950. break;
  951. }
  952. }
  953. // fall through on the else's
  954. default:
  955. hres = E_FAIL;
  956. break;
  957. }
  958. return hres;
  959. }
  960. HRESULT CDocObjectView::DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  961. {
  962. _fSelfDragging = FALSE;
  963. //
  964. // Check if this is a self-dragging or not.
  965. //
  966. if (_pdoh && _pdoh->_pmsot) {
  967. VARIANT var = { 0 };
  968. HRESULT hresT = _pdoh->_pmsot->Exec(
  969. &CGID_ShellDocView, SHDVID_ISDRAGSOURCE, 0, NULL, &var);
  970. if (SUCCEEDED(hresT) && var.vt==VT_I4 && var.lVal) {
  971. _fSelfDragging = TRUE;
  972. }
  973. VariantClearLazy(&var);
  974. }
  975. ASSERT(pdtobj);
  976. _DragEnter(_hwndParent, ptl, pdtobj);
  977. _dwDragEffect = CommonDragEnter(pdtobj, grfKeyState, ptl);
  978. return DragOver(grfKeyState, ptl, pdwEffect);
  979. }
  980. HRESULT CDocObjectView::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  981. {
  982. *pdwEffect &= _dwDragEffect;
  983. _DragMove(_hwndParent, ptl);
  984. if (_fSelfDragging && _pdoh && _pdoh->_hwnd) {
  985. RECT rc;
  986. GetClientRect(_pdoh->_hwnd, &rc);
  987. POINT ptMap = { ptl.x, ptl.y };
  988. MapWindowPoints(HWND_DESKTOP, _pdoh->_hwnd, &ptMap, 1);
  989. if (PtInRect(&rc, ptMap)) {
  990. *pdwEffect = DROPEFFECT_NONE;
  991. }
  992. }
  993. return S_OK;
  994. }
  995. HRESULT CDocObjectView::DragLeave(void)
  996. {
  997. DAD_DragLeave();
  998. return S_OK;
  999. }
  1000. HRESULT CDocObjectView::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  1001. {
  1002. LPITEMIDLIST pidlTarget;
  1003. HRESULT hr = SHPidlFromDataObject(pdtobj, &pidlTarget, NULL, 0);
  1004. if (SUCCEEDED(hr)) {
  1005. ASSERT(pidlTarget);
  1006. if((!ILIsWeb(pidlTarget) && _pdoh && SHIsRestricted2W(_pdoh->_hwnd, REST_NOFILEURL, NULL, 0)) ||
  1007. (_pdoh && !IEIsLinkSafe(_pdoh->_hwnd, pidlTarget, ILS_NAVIGATE)))
  1008. {
  1009. ILFree(pidlTarget);
  1010. hr = E_ACCESSDENIED;
  1011. }
  1012. else
  1013. {
  1014. DWORD flags = GetKeyState(VK_CONTROL) < 0 ?
  1015. (SBSP_NEWBROWSER | SBSP_ABSOLUTE) :
  1016. (SBSP_SAMEBROWSER | SBSP_ABSOLUTE);
  1017. hr = _psb->BrowseObject(pidlTarget, flags);
  1018. HFRMMSG2(TEXT("::Drop _psb->BrowseObject returned"), hr, 0);
  1019. ILFree(pidlTarget);
  1020. }
  1021. }
  1022. if (SUCCEEDED(hr))
  1023. {
  1024. *pdwEffect &= _dwDragEffect;
  1025. }
  1026. DAD_DragLeave();
  1027. return hr;
  1028. }
  1029. ULONG CDocObjectView::AddRef()
  1030. {
  1031. _cRef++;
  1032. TraceMsg(TF_SHDREF, "CDocObjectView(%x)::AddRef called new _cRef=%d", this, _cRef);
  1033. return _cRef;
  1034. }
  1035. ULONG CDocObjectView::Release()
  1036. {
  1037. _cRef--;
  1038. TraceMsg(TF_SHDREF, "CDocObjectView(%x)::Release called new _cRef=%d", this, _cRef);
  1039. if (_cRef > 0)
  1040. return _cRef;
  1041. delete this;
  1042. return 0;
  1043. }
  1044. HRESULT CDocObjectView::GetView(SHELLVIEWID* pvid, ULONG uView)
  1045. {
  1046. return E_NOTIMPL;
  1047. }
  1048. #ifdef DEBUG
  1049. #define _AddRef(psz) { ++_cRef; TraceMsg(TF_SHDREF, "CDocObjectView(%x)::QI(%s) is AddRefing _cRef=%d", this, psz, _cRef); }
  1050. #else
  1051. #define _AddRef(psz) ++_cRef
  1052. #endif
  1053. HRESULT CDocObjectView::QueryInterface(REFIID riid, void ** ppvObj)
  1054. {
  1055. HRESULT hres;
  1056. static const QITAB qit[] = {
  1057. QITABENT(CDocObjectView, IShellView2),
  1058. QITABENTMULTI(CDocObjectView, IShellView, IShellView2),
  1059. QITABENTMULTI(CDocObjectView, IOleWindow, IShellView2),
  1060. QITABENT(CDocObjectView, IDropTarget),
  1061. QITABENT(CDocObjectView, IViewObject),
  1062. QITABENT(CDocObjectView, IAdviseSink),
  1063. QITABENT(CDocObjectView, IOleCommandTarget),
  1064. QITABENT(CDocObjectView, IDocViewSite),
  1065. QITABENT(CDocObjectView, IPrivateOleObject ),
  1066. QITABENT(CDocObjectView, IPersistFolder),
  1067. QITABENTMULTI(CDocObjectView, IPersist, IPersistFolder),
  1068. QITABENT(CDocObjectView, IServiceProvider),
  1069. { 0 },
  1070. };
  1071. hres = QISearch(this, qit, riid, ppvObj);
  1072. if (S_OK != hres)
  1073. {
  1074. if (IsEqualIID(riid, CLSID_CDocObjectView))
  1075. {
  1076. *ppvObj = (void*)this;
  1077. _AddRef(TEXT("CLSID_CDocObjectView"));
  1078. return S_OK;
  1079. }
  1080. }
  1081. return hres;
  1082. }
  1083. /// ***** IViewObject ******
  1084. HRESULT CDocObjectView::GetColorSet(DWORD dwAspect, LONG lindex,
  1085. void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev,
  1086. LOGPALETTE **ppColorSet)
  1087. {
  1088. if (_pdoh)
  1089. {
  1090. return _pdoh->GetColorSet(dwAspect, lindex, pvAspect, ptd,
  1091. hicTargetDev, ppColorSet);
  1092. }
  1093. if (ppColorSet)
  1094. *ppColorSet = NULL;
  1095. return S_FALSE;
  1096. }
  1097. HRESULT CDocObjectView::Freeze(DWORD, LONG, void *, DWORD *pdwFreeze)
  1098. {
  1099. return E_NOTIMPL;
  1100. }
  1101. HRESULT CDocObjectView::Unfreeze(DWORD)
  1102. {
  1103. return E_NOTIMPL;
  1104. }
  1105. HRESULT CDocObjectView::SetAdvise(DWORD dwAspect, DWORD advf,
  1106. IAdviseSink *pSink)
  1107. {
  1108. if (dwAspect != DVASPECT_CONTENT)
  1109. return DV_E_DVASPECT;
  1110. if (advf & ~(ADVF_PRIMEFIRST | ADVF_ONLYONCE))
  1111. return E_INVALIDARG;
  1112. if (pSink != _padvise)
  1113. {
  1114. ATOMICRELEASE(_padvise);
  1115. _padvise = pSink;
  1116. if (_padvise)
  1117. _padvise->AddRef();
  1118. }
  1119. if (_padvise)
  1120. {
  1121. _advise_aspect = dwAspect;
  1122. _advise_advf = advf;
  1123. if (advf & ADVF_PRIMEFIRST)
  1124. OnViewChange(dwAspect, -1);
  1125. }
  1126. else
  1127. _advise_aspect = _advise_advf = 0;
  1128. return S_OK;
  1129. }
  1130. HRESULT CDocObjectView::GetAdvise(DWORD *pdwAspect, DWORD *padvf,
  1131. IAdviseSink **ppSink)
  1132. {
  1133. if (pdwAspect)
  1134. *pdwAspect = _advise_aspect;
  1135. if (padvf)
  1136. *padvf = _advise_advf;
  1137. if (ppSink)
  1138. {
  1139. if (_padvise)
  1140. _padvise->AddRef();
  1141. *ppSink = _padvise;
  1142. }
  1143. return S_OK;
  1144. }
  1145. HRESULT CDocObjectView::Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
  1146. DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
  1147. const RECTL *lprcBounds, const RECTL *lprcWBounds,
  1148. BOOL (*pfnContinue)(ULONG_PTR), ULONG_PTR dwContinue)
  1149. {
  1150. if (_pdoh) {
  1151. return _pdoh->Draw(dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev,
  1152. hdcDraw, lprcBounds, lprcWBounds, pfnContinue, dwContinue);
  1153. }
  1154. return OLE_E_BLANK;
  1155. }
  1156. // IAdviseSink
  1157. void CDocObjectView::OnDataChange(FORMATETC *, STGMEDIUM *)
  1158. {
  1159. }
  1160. void CDocObjectView::OnViewChange(DWORD dwAspect, LONG lindex)
  1161. {
  1162. dwAspect &= _advise_aspect;
  1163. if (dwAspect && _padvise)
  1164. {
  1165. IAdviseSink *pSink = _padvise;
  1166. IUnknown *punkRelease;
  1167. if (_advise_advf & ADVF_ONLYONCE)
  1168. {
  1169. punkRelease = pSink;
  1170. _padvise = NULL;
  1171. _advise_aspect = _advise_advf = 0;
  1172. }
  1173. else
  1174. punkRelease = NULL;
  1175. pSink->OnViewChange(dwAspect, lindex);
  1176. if (punkRelease)
  1177. punkRelease->Release();
  1178. }
  1179. }
  1180. void CDocObjectView::OnRename(IMoniker *)
  1181. {
  1182. }
  1183. void CDocObjectView::OnSave()
  1184. {
  1185. }
  1186. void CDocObjectView::OnClose()
  1187. {
  1188. //
  1189. // the doc object host went away so tell anybody above what happened
  1190. //
  1191. OnViewChange(_advise_aspect, -1);
  1192. }
  1193. HRESULT CDocObjectView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  1194. {
  1195. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  1196. if (_pdho && _pdoh)
  1197. hres = _pdho->QueryStatusDown(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  1198. return hres;
  1199. }
  1200. HRESULT CDocObjectView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  1201. {
  1202. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  1203. if (!pguidCmdGroup)
  1204. {
  1205. switch (nCmdID)
  1206. {
  1207. case OLECMDID_REFRESH:
  1208. _SetLastRefreshTime();
  1209. break;
  1210. default:
  1211. break;
  1212. }
  1213. }
  1214. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  1215. {
  1216. switch(nCmdID)
  1217. {
  1218. case SHDVID_UPDATEDOCHOSTSTATE:
  1219. if (_pdoh)
  1220. {
  1221. DOCHOSTUPDATEDATA * pdhud;
  1222. ASSERT(pvarargIn && pvarargIn->vt == VT_PTR);
  1223. pdhud = (DOCHOSTUPDATEDATA *) V_BYREF(pvarargIn);
  1224. return _pdoh->_UpdateState(pdhud->_pidl, pdhud->_fIsErrorUrl);
  1225. }
  1226. return S_OK;
  1227. case SHDVID_COMPLETEDOCHOSTPASSING:
  1228. _CompleteDocHostPassing(_psvPrev, S_OK);
  1229. ATOMICRELEASE(_psvPrev);
  1230. return S_OK;
  1231. case SHDVID_NAVSTART:
  1232. if (_pdoh)
  1233. {
  1234. _pdoh->_Init();
  1235. }
  1236. return S_OK;
  1237. default:
  1238. break;
  1239. }
  1240. }
  1241. // only forward on if we aren't 'stolen'.
  1242. // FEATURE ie4: clean this up to steal _pdho along w/ _pdoh.
  1243. if (_pdho && _pdoh)
  1244. hres = _pdho->ExecDown(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1245. // REVIEW: if _pdoh->ExecDown fails && pguidCmdGroup==NULL && nCmdID is
  1246. // OLECMDID_STOP or OLECMDID_REFRESH, then we are lying
  1247. // by returning a failure error code.
  1248. return hres;
  1249. }
  1250. HRESULT CDocObjectView::OnSetTitle(VARIANTARG *pvTitle)
  1251. {
  1252. return E_NOTIMPL;
  1253. }
  1254. HRESULT CDocObjectView::SetExtent( DWORD dwDrawAspect, SIZEL *psizel)
  1255. {
  1256. if ( _pdoh && _pdoh->GetOleObject() )
  1257. {
  1258. return _pdoh->GetOleObject()->SetExtent( dwDrawAspect, psizel );
  1259. }
  1260. return E_NOTIMPL;
  1261. }
  1262. HRESULT CDocObjectView::GetExtent( DWORD dwDrawAspect, SIZEL *psizel)
  1263. {
  1264. if ( _pdoh && _pdoh->GetOleObject() )
  1265. {
  1266. return _pdoh->GetOleObject()->GetExtent( dwDrawAspect, psizel );
  1267. }
  1268. return E_NOTIMPL;
  1269. }
  1270. HRESULT CDocObjectView::GetClassID(CLSID *pclsid)
  1271. {
  1272. if (pclsid)
  1273. {
  1274. *pclsid = CLSID_CDocObjectView;
  1275. return S_OK;
  1276. }
  1277. return E_INVALIDARG;
  1278. }
  1279. HRESULT CDocObjectView::Initialize(LPCITEMIDLIST pidl)
  1280. {
  1281. HRESULT hres = E_OUTOFMEMORY;
  1282. LPITEMIDLIST pidlClone = ILClone(pidl);
  1283. if (pidlClone)
  1284. {
  1285. IShellFolder* psf;
  1286. if (SUCCEEDED(IEBindToObject(_pidl, &psf)))
  1287. {
  1288. ILFree(_pidl);
  1289. ATOMICRELEASE(_psf);
  1290. _pidl = pidlClone;
  1291. _psf = psf;
  1292. hres = S_OK;
  1293. }
  1294. else
  1295. {
  1296. ILFree(pidlClone);
  1297. }
  1298. }
  1299. return hres;
  1300. }
  1301. HRESULT CDocObjectView::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
  1302. {
  1303. if( _pdoh && IsEqualGUID(guidService, IID_IElementNamespaceTable) )
  1304. {
  1305. return _pdoh->QueryService( guidService, riid, ppvObj);
  1306. }
  1307. else
  1308. return E_FAIL;
  1309. }