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.

1590 lines
47 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. //
  544. // This function either (1) Create a new CDocObjectHost or (2) reuse it from
  545. // the previous view. If also returns the DisplayName of previous moniker.
  546. //
  547. void CDocObjectView::_CreateDocObjHost(IShellView * psvPrev)
  548. {
  549. BOOL fWindowOpen = FALSE;
  550. // if there was a previous shell view, see if it was our class.
  551. if (psvPrev)
  552. {
  553. CDocObjectView * pdovPrev = NULL;
  554. HRESULT hres = psvPrev->QueryInterface(CLSID_CDocObjectView, (void **)&pdovPrev);
  555. if (SUCCEEDED(hres))
  556. {
  557. CDocObjectHost * pPrevDOH = pdovPrev->_pdoh;
  558. ASSERT(_psb);
  559. ASSERT(_psb == pdovPrev->_psb);
  560. // find out if we should be saving the view state when we close
  561. // if the one we're coming from says yes, then we'll take over that
  562. // job instead of them.
  563. //
  564. _fSaveViewState = pdovPrev->_fSaveViewState;
  565. pdovPrev->_fSaveViewState = FALSE;
  566. //
  567. // if this is a local anchor navigation,
  568. // we treat it substantially differently.
  569. // we can reuse the DOH and the OLE Object that
  570. // it holds. - zekel - 31-JUL-97
  571. //
  572. // WARNING: we should not reuse these objects for any other
  573. // reason than a local anchor (fragment) navigation.
  574. // we used to be a lot more lenient about reusing the DOH
  575. // but i think this was mostly because of the old object cache.
  576. //
  577. // we check for equal pidls so that we know we are on
  578. // the same URL. we require that _pszLocation be set.
  579. // this is for Netscape compat. this means that anytime
  580. // we get a navigate to ourself it will refresh completely
  581. // if there was no fragment. we also check to make sure that
  582. // the binding does not require us to hit the net for
  583. // this request.
  584. //
  585. // 08-11-1999 (scotrobe): We now reuse the DOH if the
  586. // hosted document has indicated that it knows how to
  587. // navigate on its own.
  588. //
  589. if (_pidl && pdovPrev->_pidl && pPrevDOH &&
  590. (pPrevDOH->_fDocCanNavigate
  591. || ( _pszLocation && IEILIsEqual(_pidl, pdovPrev->_pidl, TRUE)
  592. && _CanUseCache())))
  593. {
  594. IBrowserService *pbs;
  595. if (SUCCEEDED(_psb->QueryInterface(IID_PPV_ARG(IBrowserService, &pbs))))
  596. {
  597. DWORD dwFlags = 0;
  598. // If the document doesn't know how to navigate, then this may
  599. // mean that this navigation was delegated from the document.
  600. // In that case, if we have gotten this far, that means that
  601. // _pszLocation is set. If it is and this is a delegated navigation
  602. // (i.e., the navigation wasn't due to a link in a non-html document)
  603. // we must create a new document.
  604. //
  605. if (!pPrevDOH->_fDocCanNavigate)
  606. {
  607. pbs->GetFlags(&dwFlags);
  608. }
  609. if (!(dwFlags & BSF_DELEGATEDNAVIGATION))
  610. {
  611. //
  612. // if SetHistoryObject() fails, then that means there is already
  613. // an object there for us to use. this means that we should
  614. // not treat this as a local anchor navigation. and
  615. // we shouldnt reuse the DOH even though the pidl is identical
  616. //
  617. // TRUE is passed to SetHistoryObject even if this is not a
  618. // local anchor. In the case that this is not a local anchor,
  619. // the document (Trident) handles the navigation. Therefore,
  620. // the document will take care of updating the travel log and
  621. // the fIsLocalAnchor flag is ignored.
  622. //
  623. if (SUCCEEDED(pbs->SetHistoryObject(pPrevDOH->_pole,
  624. !pPrevDOH->_fDocCanNavigate ? TRUE : FALSE)))
  625. {
  626. TraceMsg(TF_TRAVELLOG, "CDOV::CreateDocObjHost reusing current DOH on local anchor navigate");
  627. //
  628. // we cant update in ActivateNow because at that point
  629. // we have already switched the dochost over to the new
  630. // (reused) view. so we need to update the entry now
  631. //
  632. // The fact that the hosted document can navigate on its own,
  633. // implies that it will take care of updating the travel log.
  634. //
  635. if (!pPrevDOH->_fDocCanNavigate)
  636. {
  637. ITravelLog * ptl;
  638. pbs->GetTravelLog(&ptl);
  639. if (ptl)
  640. {
  641. ptl->UpdateEntry(pbs, TRUE);
  642. ptl->Release();
  643. }
  644. }
  645. pdovPrev->_DisconnectHostSink(); // we will connect below
  646. // same target! pass the docobj host
  647. _pdoh = pPrevDOH;
  648. _pdoh->AddRef();
  649. if (_pdoh->_fDocCanNavigate)
  650. {
  651. _pdoh->OnInitialUpdate();
  652. }
  653. if ((_pdoh->_dwAppHack & BROWSERFLAG_SUPPORTTOP) && !_pszLocation)
  654. {
  655. // if there's no location for us to go to, and
  656. // we're traversing in the same document,
  657. // assume top.
  658. //
  659. _pszLocation = StrDup(TEXT("#top"));
  660. _uiCP = CP_ACP;
  661. }
  662. }
  663. pbs->Release();
  664. }
  665. }
  666. }
  667. // In the case where we are opening a non-html mime type
  668. // in a new window, we need to pass the _fWindowOpen
  669. // flag from the previous docobject host to the new
  670. // docobject host. This is needed so that if we are opening
  671. // a file outside of IE in a new window, we'll know to close
  672. // the newly created IE afterwards.
  673. // The problem is that there isn't really a good place to
  674. // clear this flag since it has to remain set from one
  675. // instance of the docobject host to the next. This causes
  676. // us to get into the situation where we'll close the browser
  677. // window if we click on a link to a file that opens outside
  678. // of IE after opening a new window for an html file.
  679. // The bottom line is that we only need to pass this flag to
  680. // the new docobject host if we opening an non-html mime type
  681. // in a new window.
  682. //
  683. if (!_pdoh && pPrevDOH && pPrevDOH->_fDelegatedNavigation)
  684. {
  685. fWindowOpen = pPrevDOH->_fWindowOpen;
  686. }
  687. //
  688. // FEATURE: We should take care of _pibscNC as well
  689. // to 'chain' the IBindStatusCallback.
  690. //
  691. pdovPrev->Release();
  692. }
  693. }
  694. // if we didn't pass the docobj host, create a new one and
  695. // pass the doc context
  696. if (!_pdoh)
  697. {
  698. ASSERT(_psb);
  699. _pdoh = new CDocObjectHost(fWindowOpen);
  700. // Reset host navigation flag in the browser
  701. //
  702. IUnknown_Exec(_psb,
  703. &CGID_DocHostCmdPriv,
  704. DOCHOST_DOCCANNAVIGATE,
  705. 0, NULL, NULL);
  706. }
  707. if (_pdoh)
  708. {
  709. _ConnectHostSink();
  710. }
  711. }
  712. extern HRESULT TargetQueryService(IUnknown *punk, REFIID riid, void **ppvObj);
  713. HRESULT CDocObjectView::CreateViewWindow2(LPSV2CVW2_PARAMS lpParams)
  714. {
  715. HRESULT hres = S_OK;
  716. IShellView * psvPrev = lpParams->psvPrev;
  717. LPCFOLDERSETTINGS lpfs = lpParams->pfs;
  718. IShellBrowser * psb = lpParams->psbOwner;
  719. RECT * prcView = lpParams->prcView;
  720. HWND UNALIGNED * phWnd = &lpParams->hwndView;
  721. if (_pdoh || !_pidl)
  722. {
  723. *phWnd = NULL;
  724. ASSERT(0);
  725. return E_UNEXPECTED;
  726. }
  727. _fs = *lpfs;
  728. ASSERT(_psb==NULL);
  729. _psb = psb;
  730. psb->AddRef();
  731. ASSERT(_pctShellBrowser==NULL);
  732. _psb->QueryInterface(IID_IOleCommandTarget, (void **)&_pctShellBrowser);
  733. //if somebody that is not a ShellBrowser (like the FileOpenBrowser)
  734. // tries to use us, we want to block them. we will fault later on
  735. // if we dont have the right stuff.
  736. if (!_pctShellBrowser)
  737. return E_UNEXPECTED;
  738. // prime the cache bit. this needs to be done while we're *the* guy navigating.
  739. // otherwise, if we ask later when there's a different pending navigation,
  740. // we'll get his info
  741. _CanUseCache();
  742. _SetLastRefreshTime();
  743. // Either create a new CDocObjectHost or reuse it from the previous view
  744. // and set it in _pdoh.
  745. _CreateDocObjHost(psvPrev);
  746. if (!_pdoh || !_pdoh->InitHostWindow(this, psb, prcView))
  747. {
  748. ATOMICRELEASE(_psb);
  749. _pctShellBrowser->Release();
  750. _pctShellBrowser = NULL;
  751. return E_OUTOFMEMORY;
  752. }
  753. _pdoh->GetWindow(phWnd);
  754. ASSERT(NULL == _pdho);
  755. _pdoh->QueryInterface(IID_IDocHostObject, (void **)&_pdho);
  756. IMoniker* pmk = NULL;
  757. BOOL fFileProtocol;
  758. hres = ::_URLMONMonikerFromPidl(_pidl, &pmk, &fFileProtocol);
  759. if (SUCCEEDED(hres) && EVAL(pmk))
  760. {
  761. hres = _pdoh->SetTarget(pmk, _uiCP, _pszLocation, _pidl, psvPrev, fFileProtocol);
  762. _psvPrev = psvPrev;
  763. if (_psvPrev)
  764. _psvPrev->AddRef();
  765. #ifdef NON_NATIVE_FRAMES
  766. _CompleteDocHostPassing(psvPrev, hres);
  767. #endif
  768. pmk->Release();
  769. }
  770. return hres;
  771. }
  772. void CDocObjectView::_GetViewSettings(IEVIEWINFO* pievi)
  773. {
  774. DWORD dwType, dwSize;
  775. // REVIEW: Currently, we have on setting for all docobj class views
  776. // (everything hosted by shdocvw). we may want to subclassify them by clsid
  777. // of the docobj or maybe special case mshtml...
  778. dwSize = sizeof(IEVIEWINFO);
  779. if (SHGetValueGoodBoot(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
  780. TEXT("ViewSettings"), &dwType, (PBYTE)pievi, &dwSize) == ERROR_SUCCESS)
  781. {
  782. if (pievi->cbSize != sizeof(IEVIEWINFO))
  783. {
  784. goto DefaultInfo;
  785. }
  786. }
  787. else
  788. {
  789. DefaultInfo:
  790. // can't count on 0 init because registry could have read stuff, but
  791. // of the wrong size (corruption)
  792. pievi->fToolbar = FALSE;
  793. pievi->fCoolbar = TRUE;
  794. pievi->fStatusbar = TRUE;
  795. }
  796. }
  797. void CDocObjectView::_SaveViewState()
  798. {
  799. IEVIEWINFO ievi;
  800. int id;
  801. // First ask up if it is ok for us to save view state. If we get the return value of
  802. // S_FALSE bail as we were told no.
  803. if (_pctShellBrowser &&
  804. (_pctShellBrowser->Exec(&CGID_Explorer, SBCMDID_MAYSAVEVIEWSTATE, 0, NULL, NULL) == S_FALSE))
  805. return;
  806. // first load to preserve things we're not going to set
  807. _GetViewSettings(&ievi);
  808. ievi.cbSize = sizeof(ievi);
  809. id = _ShowControl(FCW_STATUS, SBSC_QUERY);
  810. // bail if it's not supported
  811. if (id == -1)
  812. return;
  813. ievi.fStatusbar = (id == SBSC_SHOW);
  814. id = _ShowControl(FCW_TOOLBAR, SBSC_QUERY);
  815. if (id != -1) {
  816. // this is allowed to fail if toolbar isn't supported (ie30 case)
  817. ievi.fToolbar = (id == SBSC_SHOW);
  818. }
  819. id = _ShowControl(FCW_INTERNETBAR, SBSC_QUERY);
  820. if (id != -1) {
  821. // this is allowed to fail if coolbar isn't supported
  822. ievi.fCoolbar = (id == SBSC_SHOW);
  823. }
  824. SHSetValue(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
  825. TEXT("ViewSettings"), REG_BINARY, (const BYTE *)&ievi, sizeof(ievi));
  826. }
  827. int CDocObjectView::_ShowControl(UINT idControl, int idCmd)
  828. {
  829. VARIANTARG var;
  830. VariantInit(&var);
  831. var.vt = VT_I4;
  832. var.lVal = MAKELONG(idControl, idCmd);
  833. if (_pctShellBrowser &&
  834. SUCCEEDED(_pctShellBrowser->Exec(&CGID_Explorer, SBCMDID_SHOWCONTROL, OLECMDEXECOPT_DODEFAULT,
  835. &var, &var)))
  836. return var.lVal;
  837. return -1;
  838. }
  839. HRESULT CDocObjectView::DestroyViewWindow()
  840. {
  841. ATOMICRELEASE(_pdho);
  842. if (_pdoh)
  843. {
  844. BOOL fDestroyHost = TRUE;
  845. if (_psb && _pdoh->_pwb)
  846. {
  847. DWORD dwFlags;
  848. _pdoh->_pwb->GetFlags(&dwFlags);
  849. if (dwFlags & BSF_HTMLNAVCANCELED)
  850. {
  851. IShellView * psvCur;
  852. HRESULT hr = _psb->QueryActiveShellView(&psvCur);
  853. if (S_OK == hr)
  854. {
  855. CDocObjectView * pdovCur;
  856. hr = psvCur->QueryInterface(CLSID_CDocObjectView, (void**)&pdovCur);
  857. if (S_OK == hr)
  858. {
  859. ASSERT(this != pdovCur);
  860. if (_pdoh == pdovCur->_pdoh)
  861. {
  862. fDestroyHost = FALSE;
  863. }
  864. pdovCur->Release();
  865. }
  866. psvCur->Release();
  867. }
  868. }
  869. }
  870. if (fDestroyHost)
  871. {
  872. TraceMsg(DM_WARNING, "CDocObjectView::DestroyViewWindow(): Destroying Host Window");
  873. _DisconnectHostSink();
  874. if (_fSaveViewState)
  875. _SaveViewState();
  876. _pdoh->DestroyHostWindow();
  877. }
  878. ATOMICRELEASET(_pdoh, CDocObjectHost);
  879. }
  880. ATOMICRELEASE(_pctShellBrowser);
  881. // Note that we should release _psb at the very end.
  882. ATOMICRELEASE(_psb);
  883. return S_OK;
  884. }
  885. HRESULT CDocObjectView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
  886. {
  887. *lpfs = _fs;
  888. return S_OK;
  889. }
  890. HRESULT CDocObjectView::AddPropertySheetPages(DWORD dwReserved,
  891. LPFNADDPROPSHEETPAGE lpfn, LPARAM lParam)
  892. {
  893. if (_pdoh)
  894. return _pdoh->AddPages(lpfn, lParam);
  895. return E_FAIL;
  896. }
  897. HRESULT CDocObjectView::SaveViewState()
  898. {
  899. // No viewsate to be saved
  900. return S_OK;
  901. }
  902. HRESULT CDocObjectView::SelectItem(LPCITEMIDLIST pidlItem, UINT uFlags)
  903. {
  904. // No item
  905. return E_FAIL;
  906. }
  907. //
  908. // IShellView::GetItemObject
  909. //
  910. // For this IShellView object, the only valid uItem is SVGIO_BACKGROUND,
  911. // which allows the browser to access an interface pointer to the
  912. // currently active document object.
  913. //
  914. // Notes:
  915. // The browser should be aware that IShellView::CreateViewWindow might be
  916. // asynchronous. This method will fail with E_FAIL if the document is not
  917. // instanciated yet.
  918. //
  919. HRESULT CDocObjectView::GetItemObject(UINT uItem, REFIID riid, void **ppv)
  920. {
  921. HRESULT hres = E_INVALIDARG;
  922. *ppv = NULL; // assumes error
  923. switch(uItem)
  924. {
  925. case SVGIO_BACKGROUND:
  926. if (_pdoh)
  927. {
  928. if (_pdoh->_pole)
  929. {
  930. hres = _pdoh->_pole->QueryInterface(riid, ppv);
  931. break;
  932. }
  933. else if (_pdoh->_punkPending)
  934. {
  935. hres = _pdoh->_punkPending->QueryInterface(riid, ppv);
  936. break;
  937. }
  938. }
  939. // fall through on the else's
  940. default:
  941. hres = E_FAIL;
  942. break;
  943. }
  944. return hres;
  945. }
  946. HRESULT CDocObjectView::DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  947. {
  948. _fSelfDragging = FALSE;
  949. //
  950. // Check if this is a self-dragging or not.
  951. //
  952. if (_pdoh && _pdoh->_pmsot) {
  953. VARIANT var = { 0 };
  954. HRESULT hresT = _pdoh->_pmsot->Exec(
  955. &CGID_ShellDocView, SHDVID_ISDRAGSOURCE, 0, NULL, &var);
  956. if (SUCCEEDED(hresT) && var.vt==VT_I4 && var.lVal) {
  957. _fSelfDragging = TRUE;
  958. }
  959. VariantClearLazy(&var);
  960. }
  961. ASSERT(pdtobj);
  962. _DragEnter(_hwndParent, ptl, pdtobj);
  963. _dwDragEffect = CommonDragEnter(pdtobj, grfKeyState, ptl);
  964. return DragOver(grfKeyState, ptl, pdwEffect);
  965. }
  966. HRESULT CDocObjectView::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  967. {
  968. *pdwEffect &= _dwDragEffect;
  969. _DragMove(_hwndParent, ptl);
  970. if (_fSelfDragging && _pdoh && _pdoh->_hwnd) {
  971. RECT rc;
  972. GetClientRect(_pdoh->_hwnd, &rc);
  973. POINT ptMap = { ptl.x, ptl.y };
  974. MapWindowPoints(HWND_DESKTOP, _pdoh->_hwnd, &ptMap, 1);
  975. if (PtInRect(&rc, ptMap)) {
  976. *pdwEffect = DROPEFFECT_NONE;
  977. }
  978. }
  979. return S_OK;
  980. }
  981. HRESULT CDocObjectView::DragLeave(void)
  982. {
  983. DAD_DragLeave();
  984. return S_OK;
  985. }
  986. HRESULT CDocObjectView::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  987. {
  988. LPITEMIDLIST pidlTarget;
  989. HRESULT hr = SHPidlFromDataObject(pdtobj, &pidlTarget, NULL, 0);
  990. if (SUCCEEDED(hr)) {
  991. ASSERT(pidlTarget);
  992. if((!ILIsWeb(pidlTarget) && _pdoh && SHIsRestricted2W(_pdoh->_hwnd, REST_NOFILEURL, NULL, 0)) ||
  993. (_pdoh && !IEIsLinkSafe(_pdoh->_hwnd, pidlTarget, ILS_NAVIGATE)))
  994. {
  995. ILFree(pidlTarget);
  996. hr = E_ACCESSDENIED;
  997. }
  998. else
  999. {
  1000. DWORD flags = GetKeyState(VK_CONTROL) < 0 ?
  1001. (SBSP_NEWBROWSER | SBSP_ABSOLUTE) :
  1002. (SBSP_SAMEBROWSER | SBSP_ABSOLUTE);
  1003. hr = _psb->BrowseObject(pidlTarget, flags);
  1004. HFRMMSG2(TEXT("::Drop _psb->BrowseObject returned"), hr, 0);
  1005. ILFree(pidlTarget);
  1006. }
  1007. }
  1008. if (SUCCEEDED(hr))
  1009. {
  1010. *pdwEffect &= _dwDragEffect;
  1011. }
  1012. DAD_DragLeave();
  1013. return hr;
  1014. }
  1015. ULONG CDocObjectView::AddRef()
  1016. {
  1017. _cRef++;
  1018. TraceMsg(TF_SHDREF, "CDocObjectView(%x)::AddRef called new _cRef=%d", this, _cRef);
  1019. return _cRef;
  1020. }
  1021. ULONG CDocObjectView::Release()
  1022. {
  1023. _cRef--;
  1024. TraceMsg(TF_SHDREF, "CDocObjectView(%x)::Release called new _cRef=%d", this, _cRef);
  1025. if (_cRef > 0)
  1026. return _cRef;
  1027. delete this;
  1028. return 0;
  1029. }
  1030. HRESULT CDocObjectView::GetView(SHELLVIEWID* pvid, ULONG uView)
  1031. {
  1032. return E_NOTIMPL;
  1033. }
  1034. #ifdef DEBUG
  1035. #define _AddRef(psz) { ++_cRef; TraceMsg(TF_SHDREF, "CDocObjectView(%x)::QI(%s) is AddRefing _cRef=%d", this, psz, _cRef); }
  1036. #else
  1037. #define _AddRef(psz) ++_cRef
  1038. #endif
  1039. HRESULT CDocObjectView::QueryInterface(REFIID riid, void ** ppvObj)
  1040. {
  1041. HRESULT hres;
  1042. static const QITAB qit[] = {
  1043. QITABENT(CDocObjectView, IShellView2),
  1044. QITABENTMULTI(CDocObjectView, IShellView, IShellView2),
  1045. QITABENTMULTI(CDocObjectView, IOleWindow, IShellView2),
  1046. QITABENT(CDocObjectView, IDropTarget),
  1047. QITABENT(CDocObjectView, IViewObject),
  1048. QITABENT(CDocObjectView, IAdviseSink),
  1049. QITABENT(CDocObjectView, IOleCommandTarget),
  1050. QITABENT(CDocObjectView, IDocViewSite),
  1051. QITABENT(CDocObjectView, IPrivateOleObject ),
  1052. QITABENT(CDocObjectView, IPersistFolder),
  1053. QITABENTMULTI(CDocObjectView, IPersist, IPersistFolder),
  1054. QITABENT(CDocObjectView, IServiceProvider),
  1055. { 0 },
  1056. };
  1057. hres = QISearch(this, qit, riid, ppvObj);
  1058. if (S_OK != hres)
  1059. {
  1060. if (IsEqualIID(riid, CLSID_CDocObjectView))
  1061. {
  1062. *ppvObj = (void*)this;
  1063. _AddRef(TEXT("CLSID_CDocObjectView"));
  1064. return S_OK;
  1065. }
  1066. }
  1067. return hres;
  1068. }
  1069. /// ***** IViewObject ******
  1070. HRESULT CDocObjectView::GetColorSet(DWORD dwAspect, LONG lindex,
  1071. void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev,
  1072. LOGPALETTE **ppColorSet)
  1073. {
  1074. if (_pdoh)
  1075. {
  1076. return _pdoh->GetColorSet(dwAspect, lindex, pvAspect, ptd,
  1077. hicTargetDev, ppColorSet);
  1078. }
  1079. if (ppColorSet)
  1080. *ppColorSet = NULL;
  1081. return S_FALSE;
  1082. }
  1083. HRESULT CDocObjectView::Freeze(DWORD, LONG, void *, DWORD *pdwFreeze)
  1084. {
  1085. return E_NOTIMPL;
  1086. }
  1087. HRESULT CDocObjectView::Unfreeze(DWORD)
  1088. {
  1089. return E_NOTIMPL;
  1090. }
  1091. HRESULT CDocObjectView::SetAdvise(DWORD dwAspect, DWORD advf,
  1092. IAdviseSink *pSink)
  1093. {
  1094. if (dwAspect != DVASPECT_CONTENT)
  1095. return DV_E_DVASPECT;
  1096. if (advf & ~(ADVF_PRIMEFIRST | ADVF_ONLYONCE))
  1097. return E_INVALIDARG;
  1098. if (pSink != _padvise)
  1099. {
  1100. ATOMICRELEASE(_padvise);
  1101. _padvise = pSink;
  1102. if (_padvise)
  1103. _padvise->AddRef();
  1104. }
  1105. if (_padvise)
  1106. {
  1107. _advise_aspect = dwAspect;
  1108. _advise_advf = advf;
  1109. if (advf & ADVF_PRIMEFIRST)
  1110. OnViewChange(dwAspect, -1);
  1111. }
  1112. else
  1113. _advise_aspect = _advise_advf = 0;
  1114. return S_OK;
  1115. }
  1116. HRESULT CDocObjectView::GetAdvise(DWORD *pdwAspect, DWORD *padvf,
  1117. IAdviseSink **ppSink)
  1118. {
  1119. if (pdwAspect)
  1120. *pdwAspect = _advise_aspect;
  1121. if (padvf)
  1122. *padvf = _advise_advf;
  1123. if (ppSink)
  1124. {
  1125. if (_padvise)
  1126. _padvise->AddRef();
  1127. *ppSink = _padvise;
  1128. }
  1129. return S_OK;
  1130. }
  1131. HRESULT CDocObjectView::Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
  1132. DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
  1133. const RECTL *lprcBounds, const RECTL *lprcWBounds,
  1134. BOOL (*pfnContinue)(ULONG_PTR), ULONG_PTR dwContinue)
  1135. {
  1136. if (_pdoh) {
  1137. return _pdoh->Draw(dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev,
  1138. hdcDraw, lprcBounds, lprcWBounds, pfnContinue, dwContinue);
  1139. }
  1140. return OLE_E_BLANK;
  1141. }
  1142. // IAdviseSink
  1143. void CDocObjectView::OnDataChange(FORMATETC *, STGMEDIUM *)
  1144. {
  1145. }
  1146. void CDocObjectView::OnViewChange(DWORD dwAspect, LONG lindex)
  1147. {
  1148. dwAspect &= _advise_aspect;
  1149. if (dwAspect && _padvise)
  1150. {
  1151. IAdviseSink *pSink = _padvise;
  1152. IUnknown *punkRelease;
  1153. if (_advise_advf & ADVF_ONLYONCE)
  1154. {
  1155. punkRelease = pSink;
  1156. _padvise = NULL;
  1157. _advise_aspect = _advise_advf = 0;
  1158. }
  1159. else
  1160. punkRelease = NULL;
  1161. pSink->OnViewChange(dwAspect, lindex);
  1162. if (punkRelease)
  1163. punkRelease->Release();
  1164. }
  1165. }
  1166. void CDocObjectView::OnRename(IMoniker *)
  1167. {
  1168. }
  1169. void CDocObjectView::OnSave()
  1170. {
  1171. }
  1172. void CDocObjectView::OnClose()
  1173. {
  1174. //
  1175. // the doc object host went away so tell anybody above what happened
  1176. //
  1177. OnViewChange(_advise_aspect, -1);
  1178. }
  1179. HRESULT CDocObjectView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  1180. {
  1181. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  1182. if (_pdho && _pdoh)
  1183. hres = _pdho->QueryStatusDown(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  1184. return hres;
  1185. }
  1186. HRESULT CDocObjectView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  1187. {
  1188. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  1189. if (!pguidCmdGroup)
  1190. {
  1191. switch (nCmdID)
  1192. {
  1193. case OLECMDID_REFRESH:
  1194. _SetLastRefreshTime();
  1195. break;
  1196. default:
  1197. break;
  1198. }
  1199. }
  1200. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  1201. {
  1202. switch(nCmdID)
  1203. {
  1204. case SHDVID_UPDATEDOCHOSTSTATE:
  1205. if (_pdoh)
  1206. {
  1207. DOCHOSTUPDATEDATA * pdhud;
  1208. ASSERT(pvarargIn && pvarargIn->vt == VT_PTR);
  1209. pdhud = (DOCHOSTUPDATEDATA *) V_BYREF(pvarargIn);
  1210. return _pdoh->_UpdateState(pdhud->_pidl, pdhud->_fIsErrorUrl);
  1211. }
  1212. return S_OK;
  1213. case SHDVID_COMPLETEDOCHOSTPASSING:
  1214. _CompleteDocHostPassing(_psvPrev, S_OK);
  1215. ATOMICRELEASE(_psvPrev);
  1216. return S_OK;
  1217. case SHDVID_NAVSTART:
  1218. if (_pdoh)
  1219. {
  1220. _pdoh->_Init();
  1221. }
  1222. return S_OK;
  1223. default:
  1224. break;
  1225. }
  1226. }
  1227. // only forward on if we aren't 'stolen'.
  1228. // FEATURE ie4: clean this up to steal _pdho along w/ _pdoh.
  1229. if (_pdho && _pdoh)
  1230. hres = _pdho->ExecDown(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1231. // REVIEW: if _pdoh->ExecDown fails && pguidCmdGroup==NULL && nCmdID is
  1232. // OLECMDID_STOP or OLECMDID_REFRESH, then we are lying
  1233. // by returning a failure error code.
  1234. return hres;
  1235. }
  1236. HRESULT CDocObjectView::OnSetTitle(VARIANTARG *pvTitle)
  1237. {
  1238. return E_NOTIMPL;
  1239. }
  1240. HRESULT CDocObjectView::SetExtent( DWORD dwDrawAspect, SIZEL *psizel)
  1241. {
  1242. if ( _pdoh && _pdoh->GetOleObject() )
  1243. {
  1244. return _pdoh->GetOleObject()->SetExtent( dwDrawAspect, psizel );
  1245. }
  1246. return E_NOTIMPL;
  1247. }
  1248. HRESULT CDocObjectView::GetExtent( DWORD dwDrawAspect, SIZEL *psizel)
  1249. {
  1250. if ( _pdoh && _pdoh->GetOleObject() )
  1251. {
  1252. return _pdoh->GetOleObject()->GetExtent( dwDrawAspect, psizel );
  1253. }
  1254. return E_NOTIMPL;
  1255. }
  1256. HRESULT CDocObjectView::GetClassID(CLSID *pclsid)
  1257. {
  1258. if (pclsid)
  1259. {
  1260. *pclsid = CLSID_CDocObjectView;
  1261. return S_OK;
  1262. }
  1263. return E_INVALIDARG;
  1264. }
  1265. HRESULT CDocObjectView::Initialize(LPCITEMIDLIST pidl)
  1266. {
  1267. HRESULT hres = E_OUTOFMEMORY;
  1268. LPITEMIDLIST pidlClone = ILClone(pidl);
  1269. if (pidlClone)
  1270. {
  1271. IShellFolder* psf;
  1272. if (SUCCEEDED(IEBindToObject(_pidl, &psf)))
  1273. {
  1274. ILFree(_pidl);
  1275. ATOMICRELEASE(_psf);
  1276. _pidl = pidlClone;
  1277. _psf = psf;
  1278. hres = S_OK;
  1279. }
  1280. else
  1281. {
  1282. ILFree(pidlClone);
  1283. }
  1284. }
  1285. return hres;
  1286. }
  1287. HRESULT CDocObjectView::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
  1288. {
  1289. if( _pdoh && IsEqualGUID(guidService, IID_IElementNamespaceTable) )
  1290. {
  1291. return _pdoh->QueryService( guidService, riid, ppvObj);
  1292. }
  1293. else
  1294. return E_FAIL;
  1295. }