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.

405 lines
11 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. return CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER,
  137. IID_PPV_ARG(IUnknown, ppunk));
  138. // ZekeL: Add code to prep new Browser here.
  139. }
  140. IWebBrowser2* CBandProxy::_GetBrowser()
  141. {
  142. if (!_fHaveBrowser)
  143. {
  144. IUnknown * punkHack;
  145. _fHaveBrowser = TRUE;
  146. // HACK: Bands docked on the side of the screen besides the Taskbar will be
  147. // able to get a IWebBrowser2 interface pointer. But we expect this
  148. // to be pointing to a valid browser that we are attached to. Navigating
  149. // this interface appears to create new windows, which is not what we
  150. // want, because we will try to recycle windows and do special behavior
  151. // if the shift key is down. This QS will detect this case and prevent
  152. // it from confusing us.
  153. if (SUCCEEDED(IUnknown_QueryService(_punkSite, SID_SShellDesktop, IID_PPV_ARG(IUnknown, &punkHack))))
  154. punkHack->Release();
  155. else
  156. IUnknown_QueryService(_punkSite, SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, &_pwb));
  157. }
  158. return _pwb;
  159. }
  160. // this does the default UI work of opening a new window if the shift
  161. // key is down
  162. // or creating a browser if one isn't available already
  163. IWebBrowser2* CBandProxy::_GetBrowserWindow()
  164. {
  165. IUnknown* punk = NULL;
  166. IWebBrowser2* pwb = NULL;
  167. GetBrowserWindow(&punk);
  168. if (punk)
  169. {
  170. punk->QueryInterface(IID_PPV_ARG(IWebBrowser2, &pwb));
  171. // Always make browser visible.
  172. MakeBrowserVisible(punk);
  173. punk->Release();
  174. }
  175. return pwb;
  176. }
  177. /****************************************************\
  178. FUNCTION: GetBrowserWindow
  179. DESCRIPTION:
  180. this is to just *GET* the browser. It does not
  181. do any auto-creating work.
  182. If this function succseeds, the caller must
  183. use and release the returned interface quickly. The
  184. caller cannot hold on to the Interface because
  185. the user may close the window and make releasing
  186. it impossible.
  187. \****************************************************/
  188. HRESULT CBandProxy::GetBrowserWindow(IUnknown** ppunk)
  189. {
  190. HRESULT hr;
  191. *ppunk = _GetBrowser();
  192. if (*ppunk)
  193. {
  194. (*ppunk)->AddRef();
  195. hr = S_OK;
  196. }
  197. else
  198. {
  199. hr = E_FAIL;
  200. }
  201. return hr;
  202. }
  203. /****************************************************\
  204. FUNCTION: IsConnected
  205. DESCRIPTION:
  206. Indicate if we have a direct connection to the
  207. browser window.
  208. S_FALSE == no
  209. S_OK == yes.
  210. \****************************************************/
  211. HRESULT CBandProxy::IsConnected()
  212. {
  213. return _GetBrowser() ? S_OK : S_FALSE;
  214. }
  215. /****************************************************\
  216. FUNCTION: MakeBrowserVisible
  217. DESCRIPTION:
  218. Make browser visible.
  219. \****************************************************/
  220. HRESULT CBandProxy::MakeBrowserVisible(IUnknown* punk)
  221. {
  222. IWebBrowserApp * pdie;
  223. if (SUCCEEDED(punk->QueryInterface(IID_PPV_ARG(IWebBrowserApp, &pdie))))
  224. {
  225. pdie->put_Visible(TRUE);
  226. HWND hwnd;
  227. if (SUCCEEDED(SHGetTopBrowserWindow(punk, &hwnd)))
  228. {
  229. if (IsIconic(hwnd))
  230. ShowWindow(hwnd, SW_RESTORE);
  231. }
  232. pdie->Release();
  233. }
  234. return S_OK;
  235. }
  236. /****************************************************\
  237. FUNCTION: NavigateToPIDL
  238. DESCRIPTION:
  239. The caller needs to free the PIDL parameter and
  240. it can be done at any time. (No need to worry
  241. about async navigation)
  242. \****************************************************/
  243. HRESULT CBandProxy::NavigateToPIDL(LPCITEMIDLIST pidl)
  244. {
  245. HRESULT hr = E_FAIL;
  246. IWebBrowser2* pwb = _GetBrowserWindow();
  247. if (pwb)
  248. {
  249. VARIANT varThePidl;
  250. hr = InitVariantFromIDList(&varThePidl, pidl);
  251. if (SUCCEEDED(hr))
  252. {
  253. hr = pwb->Navigate2(&varThePidl, PVAREMPTY, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  254. VariantClear(&varThePidl);
  255. }
  256. pwb->Release();
  257. }
  258. else
  259. {
  260. LPCITEMIDLIST pidlTemp;
  261. IShellFolder* psf;
  262. if (SUCCEEDED(IEBindToParentFolder(pidl, &psf, &pidlTemp)))
  263. {
  264. IContextMenu* pcm;
  265. hr = psf->GetUIObjectOf(NULL, 1, &pidlTemp, IID_PPV_ARG_NULL(IContextMenu, &pcm));
  266. if (SUCCEEDED(hr))
  267. {
  268. hr = IContextMenu_Invoke(pcm, NULL, NULL, 0);
  269. pcm->Release();
  270. }
  271. psf->Release();
  272. }
  273. }
  274. return hr;
  275. }
  276. /****************************************************\
  277. FUNCTION: NavigateToUrlOLE
  278. DESCRIPTION:
  279. Navigate to the Specified URL.
  280. \****************************************************/
  281. HRESULT CBandProxy::_NavigateToUrlOLE(BSTR bstrURL, VARIANT * pvFlags)
  282. {
  283. HRESULT hr = S_OK;
  284. ASSERT(bstrURL); // must have valid URL to browse to
  285. IWebBrowser2* pwb = _GetBrowserWindow();
  286. // This will assert if someone was hanging around in the debugger
  287. // too long. While will cause the call to timing out.
  288. if (pwb)
  289. {
  290. VARIANT varURL;
  291. varURL.vt = VT_BSTR;
  292. varURL.bstrVal = bstrURL;
  293. hr = pwb->Navigate2(&varURL, pvFlags, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  294. // VariantClear() not called because caller will free the allocated string.
  295. pwb->Release();
  296. }
  297. else
  298. {
  299. SHELLEXECUTEINFO sei;
  300. FillExecInfo(sei, NULL, NULL, bstrURL, NULL, NULL, SW_SHOWNORMAL);
  301. // this navigate code path gets hit only from the edit address bar -- since the user
  302. // would have to interactively put in a weird failure case path to get here, its not an issue.
  303. if (ShellExecuteEx(&sei))
  304. hr = S_OK;
  305. else
  306. hr = E_FAIL;
  307. }
  308. return hr;
  309. }
  310. /****************************************************\
  311. FUNCTION: NavigateToURLW
  312. DESCRIPTION:
  313. Navigate to the Specified URL.
  314. \****************************************************/
  315. HRESULT CBandProxy::NavigateToURL(LPCWSTR lpwzURL, VARIANT * Flags)
  316. {
  317. HRESULT hr;
  318. LBSTR::CString strPath( lpwzURL );
  319. hr = _NavigateToUrlOLE( strPath, Flags );
  320. return hr;
  321. }