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.

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