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.

407 lines
10 KiB

  1. /**************************************************************\
  2. FILE: bandprxy.cpp
  3. DESCRIPTION:
  4. The CBandProxy class will allow bands to navigate a
  5. generic browser window. This will work correctly if the
  6. band is tied to the Browser Window because it's a ToolBar.
  7. Or if it's a toolband, each time a navigation happens,
  8. the top most browser window needs to be found or a new window
  9. created.
  10. \**************************************************************/
  11. #include "priv.h"
  12. #include "sccls.h"
  13. #include "itbar.h"
  14. #include "itbdrop.h"
  15. #include "util.h"
  16. #include <varutil.h>
  17. #include "bandprxy.h"
  18. #define DM_PERSIST DM_TRACE // trace IPS::Load, ::Save, etc.
  19. //=================================================================
  20. // Implementation of CBandProxy
  21. //=================================================================
  22. /****************************************************\
  23. FUNCTION: CBandProxy_CreateInstance
  24. DESCRIPTION:
  25. This function will create an instance of the
  26. CBandProxy COM object.
  27. \****************************************************/
  28. HRESULT CBandProxy_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
  29. {
  30. // aggregation checking is handled in class factory
  31. CBandProxy * p = new CBandProxy();
  32. if (p)
  33. {
  34. *ppunk = SAFECAST(p, IBandProxy *);
  35. return NOERROR;
  36. }
  37. return E_OUTOFMEMORY;
  38. }
  39. /****************************************************\
  40. FUNCTION: Address Band Constructor
  41. \****************************************************/
  42. CBandProxy::CBandProxy() : _cRef(1)
  43. {
  44. DllAddRef();
  45. TraceMsg(TF_SHDLIFE, "ctor CBandProxy %x", this);
  46. // This needs to be allocated in Zero Inited Memory.
  47. // Assert that all Member Variables are inited to Zero.
  48. ASSERT(!_pwb);
  49. ASSERT(!_punkSite);
  50. }
  51. /****************************************************\
  52. FUNCTION: Address Band destructor
  53. \****************************************************/
  54. CBandProxy::~CBandProxy()
  55. {
  56. ATOMICRELEASE(_pwb);
  57. ATOMICRELEASE(_punkSite);
  58. TraceMsg(TF_SHDLIFE, "dtor CBandProxy %x", this);
  59. DllRelease();
  60. }
  61. //===========================
  62. // *** IUnknown Interface ***
  63. /****************************************************\
  64. FUNCTION: AddRef
  65. \****************************************************/
  66. ULONG CBandProxy::AddRef()
  67. {
  68. _cRef++;
  69. return _cRef;
  70. }
  71. /****************************************************\
  72. FUNCTION: Release
  73. \****************************************************/
  74. ULONG CBandProxy::Release()
  75. {
  76. ASSERT(_cRef > 0);
  77. _cRef--;
  78. if (_cRef > 0)
  79. return _cRef;
  80. delete this;
  81. return 0;
  82. }
  83. /****************************************************\
  84. FUNCTION: QueryInterface
  85. \****************************************************/
  86. HRESULT CBandProxy::QueryInterface(REFIID riid, void **ppvObj)
  87. {
  88. if (IsEqualIID(riid, IID_IUnknown) ||
  89. IsEqualIID(riid, IID_IBandProxy))
  90. {
  91. *ppvObj = SAFECAST(this, IBandProxy*);
  92. }
  93. else
  94. {
  95. *ppvObj = NULL;
  96. return E_NOINTERFACE;
  97. }
  98. AddRef();
  99. return S_OK;
  100. }
  101. //================================
  102. // ** IBandProxy Interface ***
  103. /****************************************************\
  104. FUNCTION: SetSite
  105. DESCRIPTION:
  106. This function will be called to have this
  107. Toolband try to obtain enough information about it's
  108. parent Toolbar to create the Band window and maybe
  109. connect to a Browser Window.
  110. \****************************************************/
  111. HRESULT CBandProxy::SetSite(IUnknown * punk)
  112. {
  113. HRESULT hr = S_OK;
  114. // On UNIX, we always have a browser.
  115. // Note, that there's no memory leak happened,
  116. // because we get the browser only once
  117. // and release it once too (in destructor).
  118. #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
  119. _fHaveBrowser = FALSE;
  120. ATOMICRELEASE(_pwb);
  121. #endif
  122. IUnknown_Set(&_punkSite, punk);
  123. return hr;
  124. }
  125. /****************************************************\
  126. FUNCTION: CreateNewWindow
  127. DESCRIPTION:
  128. If this function succeeds, the caller must
  129. use and release the returned interface quickly. The
  130. caller cannot hold on to the Interface because
  131. the user may close the window and make releasing
  132. it impossible.
  133. \****************************************************/
  134. HRESULT CBandProxy::CreateNewWindow(IUnknown** ppunk)
  135. {
  136. #ifndef UNIX
  137. return CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER,
  138. IID_IUnknown, (void **)ppunk);
  139. #else
  140. return CoCreateInternetExplorer( IID_IUnknown, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER,
  141. (void **) ppunk );
  142. #endif
  143. // ZekeL: Add code to prep new Browser here.
  144. }
  145. IWebBrowser2* CBandProxy::_GetBrowser()
  146. {
  147. if (!_fHaveBrowser)
  148. {
  149. IUnknown * punkHack;
  150. _fHaveBrowser = TRUE;
  151. // HACK: Bands docked on the side of the screen besides the Taskbar will be
  152. // able to get a IWebBrowser2 interface pointer. But we expect this
  153. // to be pointing to a valid browser that we are attached to. Navigating
  154. // this interface appears to create new windows, which is not what we
  155. // want, because we will try to recycle windows and do special behavior
  156. // if the shift key is down. This QS will detect this case and prevent
  157. // it from confusing us.
  158. if (SUCCEEDED(IUnknown_QueryService(_punkSite, SID_SShellDesktop, IID_IUnknown, (void**)&punkHack)))
  159. punkHack->Release();
  160. else
  161. IUnknown_QueryService(_punkSite, SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID*)&_pwb);
  162. }
  163. return _pwb;
  164. }
  165. // this does the default UI work of opening a new window if the shift
  166. // key is down
  167. // or creating a browser if one isn't available already
  168. IWebBrowser2* CBandProxy::_GetBrowserWindow()
  169. {
  170. IUnknown* punk = NULL;
  171. IWebBrowser2* pwb = NULL;
  172. GetBrowserWindow(&punk);
  173. if (punk) {
  174. punk->QueryInterface(IID_IWebBrowser2, (LPVOID*)&pwb);
  175. // Always make browser visible.
  176. MakeBrowserVisible(punk);
  177. punk->Release();
  178. }
  179. return pwb;
  180. }
  181. /****************************************************\
  182. FUNCTION: GetBrowserWindow
  183. DESCRIPTION:
  184. this is to just *GET* the browser. It does not
  185. do any auto-creating work.
  186. If this function succseeds, the caller must
  187. use and release the returned interface quickly. The
  188. caller cannot hold on to the Interface because
  189. the user may close the window and make releasing
  190. it impossible.
  191. \****************************************************/
  192. HRESULT CBandProxy::GetBrowserWindow(IUnknown** ppunk)
  193. {
  194. HRESULT hr;
  195. *ppunk = _GetBrowser();
  196. if (*ppunk)
  197. {
  198. (*ppunk)->AddRef();
  199. hr = S_OK;
  200. }
  201. else
  202. {
  203. hr = E_FAIL;
  204. }
  205. return hr;
  206. }
  207. /****************************************************\
  208. FUNCTION: IsConnected
  209. DESCRIPTION:
  210. Indicate if we have a direct connection to the
  211. browser window.
  212. S_FALSE == no
  213. S_OK == yes.
  214. \****************************************************/
  215. HRESULT CBandProxy::IsConnected()
  216. {
  217. return _GetBrowser() ? S_OK : S_FALSE;
  218. }
  219. /****************************************************\
  220. FUNCTION: MakeBrowserVisible
  221. DESCRIPTION:
  222. Make browser visible.
  223. \****************************************************/
  224. HRESULT CBandProxy::MakeBrowserVisible(IUnknown* punk)
  225. {
  226. IWebBrowserApp * pdie;
  227. if (SUCCEEDED(punk->QueryInterface(IID_IWebBrowserApp, (void**)&pdie)))
  228. {
  229. pdie->put_Visible(TRUE);
  230. HWND hwnd;
  231. if (SUCCEEDED(SHGetTopBrowserWindow(punk, &hwnd)))
  232. {
  233. if (IsIconic(hwnd))
  234. ShowWindow(hwnd, SW_RESTORE);
  235. }
  236. pdie->Release();
  237. }
  238. return S_OK;
  239. }
  240. /****************************************************\
  241. FUNCTION: NavigateToPIDL
  242. DESCRIPTION:
  243. The caller needs to free the PIDL parameter and
  244. it can be done at any time. (No need to worry
  245. about async navigation)
  246. \****************************************************/
  247. HRESULT CBandProxy::NavigateToPIDL(LPCITEMIDLIST pidl)
  248. {
  249. HRESULT hr = E_FAIL;
  250. IWebBrowser2* pwb = _GetBrowserWindow();
  251. if (pwb)
  252. {
  253. VARIANT varThePidl;
  254. hr = InitVariantFromIDList(&varThePidl, pidl);
  255. if (SUCCEEDED(hr))
  256. {
  257. hr = pwb->Navigate2(&varThePidl, PVAREMPTY, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  258. VariantClear(&varThePidl);
  259. }
  260. pwb->Release();
  261. }
  262. else
  263. {
  264. LPCITEMIDLIST pidlTemp;
  265. IShellFolder* psf;
  266. if (SUCCEEDED(IEBindToParentFolder(pidl, &psf, &pidlTemp)))
  267. {
  268. IContextMenu* pcm;
  269. hr = psf->GetUIObjectOf(NULL, 1, &pidlTemp, IID_PPV_ARG_NULL(IContextMenu, &pcm));
  270. if (SUCCEEDED(hr))
  271. {
  272. hr = IContextMenu_Invoke(pcm, NULL, NULL, 0);
  273. pcm->Release();
  274. }
  275. psf->Release();
  276. }
  277. }
  278. return hr;
  279. }
  280. /****************************************************\
  281. FUNCTION: NavigateToUrlOLE
  282. DESCRIPTION:
  283. Navigate to the Specified URL.
  284. \****************************************************/
  285. HRESULT CBandProxy::_NavigateToUrlOLE(BSTR bstrURL, VARIANT * pvFlags)
  286. {
  287. HRESULT hr = S_OK;
  288. ASSERT(bstrURL); // must have valid URL to browse to
  289. IWebBrowser2* pwb = _GetBrowserWindow();
  290. // This will assert if someone was hanging around in the debugger
  291. // too long. While will cause the call to timing out.
  292. if (pwb)
  293. {
  294. VARIANT varURL;
  295. varURL.vt = VT_BSTR;
  296. varURL.bstrVal = bstrURL;
  297. hr = pwb->Navigate2(&varURL, pvFlags, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  298. // VariantClear() not called because caller will free the allocated string.
  299. pwb->Release();
  300. } else {
  301. SHELLEXECUTEINFO sei;
  302. USES_CONVERSION;
  303. FillExecInfo(sei, NULL, //hwnd,
  304. NULL, W2T(bstrURL), NULL, NULL, SW_SHOWNORMAL);
  305. if (ShellExecuteEx(&sei))
  306. hr = S_OK;
  307. else
  308. hr = E_FAIL;
  309. }
  310. return hr;
  311. }
  312. /****************************************************\
  313. FUNCTION: NavigateToURLW
  314. DESCRIPTION:
  315. Navigate to the Specified URL.
  316. \****************************************************/
  317. HRESULT CBandProxy::NavigateToURL(LPCWSTR lpwzURL, VARIANT * Flags)
  318. {
  319. HRESULT hr;
  320. LBSTR::CString strPath( lpwzURL );
  321. hr = _NavigateToUrlOLE( strPath, Flags );
  322. return hr;
  323. }