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.

396 lines
13 KiB

  1. #include "priv.h"
  2. #include "varutil.h"
  3. // static context menu for the start.search menu. note, this gets invoked directly
  4. // by a number of clients (in shell32 for example)
  5. class CShellSearchExt : public IContextMenu, public IObjectWithSite
  6. {
  7. public:
  8. CShellSearchExt();
  9. // IUnknown
  10. STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj);
  11. STDMETHODIMP_(ULONG) AddRef();
  12. STDMETHODIMP_(ULONG) Release();
  13. // IContextMenu
  14. STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
  15. STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici);
  16. STDMETHODIMP GetCommandString(UINT_PTR idCmd, UINT wFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax);
  17. // IObjectWithSite
  18. STDMETHODIMP SetSite(IUnknown *pUnkSite);
  19. STDMETHODIMP GetSite(REFIID riid, void **ppvSite);
  20. protected:
  21. virtual ~CShellSearchExt(); // for a derived class
  22. private:
  23. virtual BOOL _GetSearchUrls(GUID *pguid, LPTSTR psz, DWORD cch,
  24. LPTSTR pszUrlNavNew, DWORD cchNavNew, BOOL *pfRunInProcess);
  25. HRESULT _IsShellSearchBand(REFGUID guidSearch);
  26. HRESULT _ShowShellSearchResults(IWebBrowser2* pwb2, BOOL fNewFrame, REFGUID guidSearch);
  27. LONG _cRef;
  28. IUnknown *_pSite;
  29. };
  30. STDAPI CShellSearchExt_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  31. {
  32. CShellSearchExt* psse = new CShellSearchExt();
  33. if (psse)
  34. {
  35. *ppunk = SAFECAST(psse, IContextMenu*);
  36. return S_OK;
  37. }
  38. else
  39. {
  40. *ppunk = NULL;
  41. return E_OUTOFMEMORY;
  42. }
  43. }
  44. STDMETHODIMP CShellSearchExt::QueryInterface(REFIID riid, void **ppvObj)
  45. {
  46. static const QITAB qit[] = {
  47. QITABENT(CShellSearchExt, IContextMenu),
  48. QITABENT(CShellSearchExt, IObjectWithSite),
  49. { 0 },
  50. };
  51. return QISearch(this, qit, riid, ppvObj);
  52. }
  53. STDMETHODIMP_(ULONG) CShellSearchExt::AddRef()
  54. {
  55. return InterlockedIncrement(&_cRef);
  56. }
  57. STDMETHODIMP_(ULONG) CShellSearchExt::Release()
  58. {
  59. if (InterlockedDecrement(&_cRef))
  60. return _cRef;
  61. delete this;
  62. return 0;
  63. }
  64. STDMETHODIMP CShellSearchExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
  65. {
  66. return E_NOTIMPL;
  67. }
  68. #define SZ_SHELL_SEARCH TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FindExtensions\\Static\\ShellSearch")
  69. BOOL CShellSearchExt::_GetSearchUrls(GUID *pguidSearch, LPTSTR pszUrl, DWORD cch,
  70. LPTSTR pszUrlNavNew, DWORD cchNavNew, BOOL *pfRunInProcess)
  71. {
  72. BOOL bRet = FALSE;
  73. *pfRunInProcess = FALSE; // Assume that we are not forcing it to run in process.
  74. if (pszUrl == NULL || IsEqualGUID(*pguidSearch, GUID_NULL) || pszUrlNavNew == NULL)
  75. return bRet;
  76. *pszUrlNavNew = 0;
  77. HKEY hkey;
  78. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_SHELL_SEARCH, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  79. {
  80. TCHAR szSubKey[32];
  81. HKEY hkeySub;
  82. for (int i = 0; wnsprintf(szSubKey, ARRAYSIZE(szSubKey), TEXT("%d"), i),
  83. RegOpenKey(hkey, szSubKey, &hkeySub) == ERROR_SUCCESS;
  84. i++)
  85. {
  86. TCHAR szSearchGuid[MAX_PATH];
  87. DWORD dwType, cb = sizeof(szSearchGuid);
  88. if (SHGetValue(hkeySub, TEXT("SearchGUID"), NULL, &dwType, (BYTE*)szSearchGuid, &cb) == ERROR_SUCCESS)
  89. {
  90. GUID guid;
  91. if (GUIDFromString(szSearchGuid, &guid) &&
  92. IsEqualGUID(guid, *pguidSearch))
  93. {
  94. cb = cch * sizeof(TCHAR);
  95. bRet = (SHGetValue(hkeySub, TEXT("SearchGUID\\Url"), NULL, &dwType, (BYTE*)pszUrl, &cb) == ERROR_SUCCESS);
  96. if (bRet || IsEqualGUID(*pguidSearch, SRCID_SFileSearch))
  97. {
  98. if (!bRet)
  99. {
  100. *pszUrl = 0;
  101. // in file search case we don't need url but we still succeed
  102. bRet = TRUE;
  103. }
  104. // See if there is a URL that we should navigate to if we
  105. // are navigating to a new
  106. cb = cchNavNew * sizeof(TCHAR);
  107. SHGetValue(hkeySub, TEXT("SearchGUID\\UrlNavNew"), NULL, &dwType, (BYTE*)pszUrlNavNew, &cb);
  108. // likewise try to grab the RunInProcess flag, if not there or zero then off, else on
  109. // reuse szSearchGuid for now...
  110. *pfRunInProcess = (BOOL)SHRegGetIntW(hkeySub, L"RunInProcess", 0);
  111. }
  112. RegCloseKey(hkeySub);
  113. break;
  114. }
  115. }
  116. RegCloseKey(hkeySub);
  117. }
  118. RegCloseKey(hkey);
  119. }
  120. if (!bRet)
  121. pszUrl[0] = 0;
  122. return bRet;
  123. }
  124. STDMETHODIMP CShellSearchExt::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
  125. {
  126. TCHAR szUrl[MAX_URL_STRING], szUrlNavNew[MAX_URL_STRING];
  127. BOOL bNewFrame = FALSE;
  128. // First get the Urls such that we can see which class we should create...
  129. GUID guidSearch = GUID_NULL;
  130. BOOL fRunInProcess = FALSE;
  131. CLSID clsidBand; // deskband object for search
  132. // Retrieve search ID from invoke params
  133. if (pici->lpParameters)
  134. GUIDFromStringA(pici->lpParameters, &guidSearch);
  135. HRESULT hr = S_OK;
  136. BOOL fShellSearchBand = (S_OK == _IsShellSearchBand(guidSearch));
  137. if (fShellSearchBand)
  138. {
  139. clsidBand = CLSID_FileSearchBand;
  140. if (SHRestricted(REST_NOFIND) && IsEqualGUID(guidSearch, SRCID_SFileSearch))
  141. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED); // user saw the error
  142. }
  143. else
  144. {
  145. clsidBand = CLSID_SearchBand;
  146. // retrieve search URLs from registry
  147. if (!_GetSearchUrls(&guidSearch, szUrl, ARRAYSIZE(szUrl), szUrlNavNew, ARRAYSIZE(szUrlNavNew), &fRunInProcess))
  148. hr = E_FAIL;
  149. }
  150. if (SUCCEEDED(hr))
  151. {
  152. // if invoked from within a browser reuse it, else open a new browser
  153. IWebBrowser2 *pwb2;
  154. hr = IUnknown_QueryServiceForWebBrowserApp(_pSite, IID_PPV_ARG(IWebBrowser2, &pwb2));
  155. if (FAILED(hr))
  156. {
  157. // Note: we want the frame to display shell characteristics (CLSID_ShellBrowserWindow),
  158. // including persistence behavior, if we're loading shell search (CLSID_FileSearchBand).
  159. if (fRunInProcess || IsEqualGUID(clsidBand, CLSID_FileSearchBand))
  160. hr = CoCreateInstance(CLSID_ShellBrowserWindow, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IWebBrowser2, &pwb2));
  161. else
  162. hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IWebBrowser2, &pwb2));
  163. bNewFrame = TRUE;
  164. }
  165. if (SUCCEEDED(hr))
  166. {
  167. // show html-hosting band
  168. VARIANT var, varEmpty = {0};
  169. hr = InitBSTRVariantFromGUID(&var, clsidBand);
  170. if (SUCCEEDED(hr))
  171. {
  172. hr = pwb2->ShowBrowserBar(&var, &varEmpty, &varEmpty);
  173. VariantClear(&var);
  174. }
  175. if (SUCCEEDED(hr))
  176. {
  177. if (fShellSearchBand)
  178. {
  179. hr = _ShowShellSearchResults(pwb2, bNewFrame, guidSearch);
  180. }
  181. else
  182. {
  183. LBSTR::CString strUrl;
  184. VARIANT varFlags;
  185. varFlags.vt = VT_I4;
  186. varFlags.lVal = navBrowserBar;
  187. LPTSTR pstrUrl = strUrl.GetBuffer( MAX_URL_STRING );
  188. if ( strUrl.GetAllocLength() < MAX_URL_STRING )
  189. {
  190. TraceMsg( TF_WARNING, "CShellSearchExt::InvokeCommand() - strUrl Allocation Failed!" );
  191. strUrl.Empty();
  192. }
  193. else
  194. {
  195. SHTCharToUnicode( szUrl, pstrUrl, MAX_URL_STRING );
  196. // Let CString class own the buffer again.
  197. strUrl.ReleaseBuffer();
  198. }
  199. var.vt = VT_BSTR;
  200. var.bstrVal = strUrl;
  201. // if we opened a new window, navigate the right side to about.blank
  202. if (bNewFrame)
  203. {
  204. LBSTR::CString strNavNew;
  205. if ( szUrlNavNew[0] )
  206. {
  207. LPTSTR pstrNavNew = strNavNew.GetBuffer( MAX_URL_STRING );
  208. if ( strNavNew.GetAllocLength() < MAX_URL_STRING )
  209. {
  210. TraceMsg( TF_WARNING, "CShellSearchExt::InvokeCommand() - strNavNew Allocation Failed!" );
  211. strNavNew.Empty();
  212. }
  213. else
  214. {
  215. SHTCharToUnicode( szUrlNavNew, pstrNavNew, MAX_URL_STRING );
  216. // Let CString class own the buffer again.
  217. strNavNew.ReleaseBuffer();
  218. }
  219. }
  220. else
  221. {
  222. strNavNew = L"about:blank";
  223. }
  224. // we don't care about the error here
  225. pwb2->Navigate( strNavNew, &varEmpty, &varEmpty, &varEmpty, &varEmpty );
  226. }
  227. // navigate the search bar to the correct url
  228. hr = pwb2->Navigate2( &var, &varFlags, &varEmpty, &varEmpty, &varEmpty );
  229. }
  230. }
  231. if (SUCCEEDED(hr) && bNewFrame)
  232. hr = pwb2->put_Visible(TRUE);
  233. pwb2->Release();
  234. }
  235. }
  236. return hr;
  237. }
  238. HRESULT CShellSearchExt::_IsShellSearchBand(REFGUID guidSearch)
  239. {
  240. if (IsEqualGUID(guidSearch, SRCID_SFileSearch) ||
  241. IsEqualGUID(guidSearch, SRCID_SFindComputer) ||
  242. IsEqualGUID(guidSearch, SRCID_SFindPrinter))
  243. return S_OK;
  244. return S_FALSE;
  245. }
  246. HRESULT CShellSearchExt::_ShowShellSearchResults(IWebBrowser2* pwb2, BOOL bNewFrame, REFGUID guidSearch)
  247. {
  248. VARIANT varBand;
  249. HRESULT hr = InitBSTRVariantFromGUID(&varBand, CLSID_FileSearchBand);
  250. if (SUCCEEDED(hr))
  251. {
  252. // Retrieve the FileSearchBand's unknown from the browser frame as a VT_UNKNOWN property;
  253. // (FileSearchBand initialized and this when he was created and hosted.)
  254. VARIANT varFsb;
  255. hr = pwb2->GetProperty(varBand.bstrVal, &varFsb);
  256. if (SUCCEEDED(hr))
  257. {
  258. IFileSearchBand* pfsb;
  259. if (SUCCEEDED(QueryInterfaceVariant(varFsb, IID_PPV_ARG(IFileSearchBand, &pfsb))))
  260. {
  261. // Assign the correct search type to the band
  262. VARIANT varSearchID;
  263. if (SUCCEEDED(InitBSTRVariantFromGUID(&varSearchID, guidSearch)))
  264. {
  265. VARIANT varNil = {0};
  266. VARIANT_BOOL bNavToResults = bNewFrame ? VARIANT_TRUE : VARIANT_FALSE ;
  267. pfsb->SetSearchParameters(&varSearchID.bstrVal, bNavToResults, &varNil, &varNil);
  268. VariantClear(&varSearchID);
  269. }
  270. pfsb->Release();
  271. }
  272. VariantClear(&varFsb);
  273. }
  274. VariantClear(&varBand);
  275. }
  276. return hr;
  277. }
  278. STDMETHODIMP CShellSearchExt::GetCommandString(UINT_PTR idCmd, UINT wFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
  279. {
  280. return E_NOTIMPL;
  281. }
  282. STDMETHODIMP CShellSearchExt::SetSite(IUnknown *pUnkSite)
  283. {
  284. IUnknown_Set(&_pSite, pUnkSite);
  285. return S_OK;
  286. }
  287. STDMETHODIMP CShellSearchExt::GetSite(REFIID riid, void **ppvSite)
  288. {
  289. if (_pSite)
  290. return _pSite->QueryInterface(riid, ppvSite);
  291. *ppvSite = NULL;
  292. return E_NOINTERFACE;
  293. }
  294. CShellSearchExt::CShellSearchExt() : _cRef(1), _pSite(NULL)
  295. {
  296. }
  297. CShellSearchExt::~CShellSearchExt()
  298. {
  299. ATOMICRELEASE(_pSite);
  300. }
  301. class CWebSearchExt : public CShellSearchExt
  302. {
  303. public:
  304. CWebSearchExt();
  305. private:
  306. virtual BOOL _GetSearchUrls(GUID *pguidSearch, LPTSTR pszUrl, DWORD cch,
  307. LPTSTR pszUrlNavNew, DWORD cchNavNew, BOOL *pfRunInProcess);
  308. };
  309. STDAPI CWebSearchExt_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  310. {
  311. CWebSearchExt* pwse;
  312. pwse = new CWebSearchExt();
  313. if (pwse)
  314. {
  315. *ppunk = SAFECAST(pwse, IContextMenu*);
  316. return S_OK;
  317. }
  318. else
  319. {
  320. *ppunk = NULL;
  321. return E_OUTOFMEMORY;
  322. }
  323. }
  324. CWebSearchExt::CWebSearchExt() : CShellSearchExt()
  325. {
  326. }
  327. BOOL CWebSearchExt::_GetSearchUrls(GUID *pguidSearch, LPTSTR pszUrl, DWORD cch,
  328. LPTSTR pszUrlNavNew, DWORD cchNavNew, BOOL *pfRunInProcess)
  329. {
  330. // Currently does not support NavNew, can be extended later if desired, likewise for RunInProcess...
  331. *pfRunInProcess = FALSE;
  332. if (pszUrlNavNew && cchNavNew)
  333. *pszUrlNavNew = 0;
  334. return GetDefaultInternetSearchUrl(pszUrl, cch, TRUE);
  335. }