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.

375 lines
9.2 KiB

  1. /*****************************************************************************
  2. *
  3. * fndcm.c - IContextMenu interface
  4. *
  5. *****************************************************************************/
  6. #include "fnd.h"
  7. /*****************************************************************************
  8. *
  9. * The sqiffle for this file.
  10. *
  11. *****************************************************************************/
  12. #define sqfl sqflCm
  13. /*****************************************************************************
  14. *
  15. * PICI
  16. *
  17. * I'm getting lazy.
  18. *
  19. *****************************************************************************/
  20. typedef LPCMINVOKECOMMANDINFO PICI;
  21. /*****************************************************************************
  22. *
  23. * Declare the interfaces we will be providing.
  24. *
  25. * We must implement an IShellExtInit so the shell
  26. * will know that we are ready for action.
  27. *
  28. *****************************************************************************/
  29. Primary_Interface(CFndCm, IContextMenu);
  30. Secondary_Interface(CFndCm, IShellExtInit);
  31. /*****************************************************************************
  32. *
  33. * CFndCm
  34. *
  35. * The context menu extension for "Find .... On the &Internet".
  36. *
  37. *****************************************************************************/
  38. typedef struct CFndCm {
  39. /* Supported interfaces */
  40. IContextMenu cm;
  41. IShellExtInit sxi;
  42. } CFndCm, FCM, *PFCM;
  43. typedef IContextMenu CM, *PCM;
  44. typedef IShellExtInit SXI, *PSXI;
  45. typedef IDataObject DTO, *PDTO;
  46. /*****************************************************************************
  47. *
  48. * CFndCm_QueryInterface (from IUnknown)
  49. *
  50. * We need to check for our additional interfaces before falling
  51. * through to Common_QueryInterface.
  52. *
  53. *****************************************************************************/
  54. STDMETHODIMP
  55. CFndCm_QueryInterface(PCM pcm, RIID riid, PPV ppvObj)
  56. {
  57. PFCM this = IToClass(CFndCm, cm, pcm);
  58. HRESULT hres;
  59. if (IsEqualIID(riid, &IID_IShellExtInit)) {
  60. *ppvObj = &this->sxi;
  61. Common_AddRef(this);
  62. hres = NOERROR;
  63. } else {
  64. hres = Common_QueryInterface(this, riid, ppvObj);
  65. }
  66. AssertF(fLimpFF(FAILED(hres), *ppvObj == 0));
  67. return hres;
  68. }
  69. /*****************************************************************************
  70. *
  71. * CFndCm_AddRef (from IUnknown)
  72. * CFndCm_Release (from IUnknown)
  73. *
  74. *****************************************************************************/
  75. #ifdef DEBUG
  76. Default_AddRef(CFndCm)
  77. Default_Release(CFndCm)
  78. #else
  79. #define CFndCm_AddRef Common_AddRef
  80. #define CFndCm_Release Common_Release
  81. #endif
  82. /*****************************************************************************
  83. *
  84. * CFndCm_Finalize (from Common)
  85. *
  86. * Release the resources of an CFndCm.
  87. *
  88. *****************************************************************************/
  89. void EXTERNAL
  90. CFndCm_Finalize(PV pv)
  91. {
  92. PFCM this = pv;
  93. EnterProc(CFndCm_Finalize, (_ "p", pv));
  94. ExitProc();
  95. }
  96. /*****************************************************************************
  97. *
  98. * CFndCm_QueryContextMenu (From IContextMenu)
  99. *
  100. * Given an existing context menu hmenu, insert new context menu
  101. * items at location imi (imi = index to menu imi), returning the
  102. * number of menu items added.
  103. *
  104. * Our job is to add the "Find ... On the Internet" menu option.
  105. *
  106. * hmenu - destination menu
  107. * imi - location at which menu items should be inserted
  108. * idcMin - first available menu identifier
  109. * idcMax - first unavailable menu identifier
  110. *
  111. *****************************************************************************/
  112. #pragma BEGIN_CONST_DATA
  113. TCHAR c_tszMyself[] = TEXT(".{37865980-75d1-11cf-bfc7-444553540000}");
  114. #pragma END_CONST_DATA
  115. STDMETHODIMP
  116. CFndCm_QueryContextMenu(PCM pcm, HMENU hmenu, UINT imi,
  117. UINT idcMin, UINT idcMax, UINT uFlags)
  118. {
  119. PFCM this = IToClass(CFndCm, cm, pcm);
  120. HRESULT hres;
  121. MENUITEMINFO mii;
  122. TCHAR tsz[256];
  123. SHFILEINFO sfi;
  124. EnterProc(CFndCm_QueryContextMenu, (_ "pu", pcm, idcMin));
  125. LoadString(g_hinst, IDS_ONTHEINTERNET, tsz, cA(tsz));
  126. SHGetFileInfo(c_tszMyself, FILE_ATTRIBUTE_DIRECTORY, &sfi, cbX(sfi),
  127. SHGFI_SMALLICON |
  128. SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
  129. mii.cbSize = sizeof(mii);
  130. mii.fMask = MIIM_DATA | MIIM_ID | MIIM_TYPE;
  131. mii.fType = MFT_STRING;
  132. mii.fState = MFS_UNCHECKED;
  133. mii.wID = idcMin;
  134. mii.dwItemData = sfi.iIcon;
  135. mii.dwTypeData = tsz;
  136. InsertMenuItem(hmenu, imi, TRUE, &mii);
  137. hres = hresUs(1);
  138. ExitOleProc();
  139. return hres;
  140. }
  141. /*****************************************************************************
  142. *
  143. * _CFndCm_InvokeFind
  144. *
  145. * Go find it by launching the search URL.
  146. *
  147. *****************************************************************************/
  148. #pragma BEGIN_CONST_DATA
  149. TCHAR c_tszIEMain[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  150. TCHAR c_tszSearch[] = TEXT("Search Page");
  151. TCHAR c_tszDefSearch[] = TEXT("http://http://www.msn.com/access/allinone.htm");
  152. #pragma END_CONST_DATA
  153. STDMETHODIMP
  154. _CFndCm_InvokeFind(void)
  155. {
  156. HRESULT hres;
  157. HKEY hk;
  158. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_tszIEMain,
  159. 0, KEY_ALL_ACCESS, &hk) == 0) {
  160. TCHAR tsz[MAX_PATH];
  161. LPCTSTR ptsz;
  162. DWORD cb = cbX(tsz);
  163. if (RegQueryValueEx(hk, c_tszSearch, 0, 0, tsz, &cb) == 0) {
  164. ptsz = tsz;
  165. } else {
  166. ptsz = c_tszDefSearch;
  167. }
  168. if (ShellExecute(0, 0, tsz, 0, 0, SW_NORMAL)) {
  169. hres = S_OK;
  170. } else {
  171. hres = E_FAIL;
  172. }
  173. RegCloseKey(hk);
  174. } else {
  175. hres = E_FAIL;
  176. }
  177. return hres;
  178. }
  179. /*****************************************************************************
  180. *
  181. * CFndCm_InvokeCommand (from IContextMenu)
  182. *
  183. * We have only one command, called "find".
  184. *
  185. *****************************************************************************/
  186. #pragma BEGIN_CONST_DATA
  187. TCHAR c_tszFind[] = TEXT("find");
  188. #pragma END_CONST_DATA
  189. STDMETHODIMP
  190. CFndCm_InvokeCommand(PCM pcm, PICI pici)
  191. {
  192. PFCM this = IToClass(CFndCm, cm, pcm);
  193. HRESULT hres;
  194. EnterProc(CFndCm_InvokeCommand,
  195. (_ HIWORD(pici->lpVerb) ? "pA" : "pu", pcm, pici->lpVerb));
  196. if (pici->cbSize >= sizeof(*pici)) {
  197. if (
  198. #ifdef SHELL32_IS_BUG_FREE //;Internal
  199. (HIWORD(pici->lpVerb) && lstrcmpi(c_tszFind, pici->lpVerb) == 0) || //;Internal
  200. pici->lpVerb == 0 //;Internal
  201. #else //;Internal
  202. fLimpFF(HIWORD(pici->lpVerb), lstrcmpi(c_tszFind, pici->lpVerb) == 0)
  203. #endif //;Internal
  204. ) {
  205. hres = _CFndCm_InvokeFind();
  206. } else {
  207. hres = E_INVALIDARG;
  208. }
  209. } else {
  210. hres = E_INVALIDARG;
  211. }
  212. ExitOleProc();
  213. return hres;
  214. }
  215. /*****************************************************************************
  216. *
  217. * CFndCm_GetCommandString (from IContextMenu)
  218. *
  219. * Somebody wants to convert a command id into a string of some sort.
  220. *
  221. *****************************************************************************/
  222. STDMETHODIMP
  223. CFndCm_GetCommandString(PCM pcm, UINT_PTR idCmd, UINT uFlags, UINT *pwRsv,
  224. LPSTR pszName, UINT cchMax)
  225. {
  226. PFCM this = IToClass(CFndCm, cm, pcm);
  227. HRESULT hres;
  228. EnterProc(CFndCm_GetCommandString, (_ "uu", idCmd, uFlags));
  229. if (idCmd == 0) {
  230. switch (uFlags) {
  231. case GCS_HELPTEXT:
  232. if (cchMax) {
  233. pszName[0] = '\0';
  234. if (LoadString(g_hinst, IDS_FINDHELP, pszName, cchMax)) {
  235. hres = NOERROR;
  236. } else {
  237. hres = E_INVALIDARG;
  238. }
  239. } else {
  240. hres = E_INVALIDARG;
  241. }
  242. break;
  243. case GCS_VALIDATE:
  244. hres = NOERROR;
  245. break;
  246. case GCS_VERB:
  247. lstrcpyn(pszName, c_tszFind, cchMax);
  248. hres = NOERROR;
  249. break;
  250. default:
  251. hres = E_NOTIMPL;
  252. break;
  253. }
  254. } else {
  255. hres = E_INVALIDARG;
  256. }
  257. ExitOleProc();
  258. return hres;
  259. }
  260. /*****************************************************************************
  261. *
  262. * CFndCm_SXI_Initialize (from IShellExtension)
  263. *
  264. *****************************************************************************/
  265. STDMETHODIMP
  266. CFndCm_SXI_Initialize(PSXI psxi, PCIDL pidlFolder, PDTO pdto, HKEY hk)
  267. {
  268. PFCM this = IToClass(CFndCm, sxi, psxi);
  269. HRESULT hres;
  270. EnterProc(CFndCm_SXI_Initialize, (_ ""));
  271. hres = S_OK;
  272. ExitOleProc();
  273. return hres;
  274. }
  275. /*****************************************************************************
  276. *
  277. * CFndCm_New (from IClassFactory)
  278. *
  279. * Note that we release the pfcm that Common_New created, because we
  280. * are done with it. The real refcount is handled by the
  281. * CFndCm_QueryInterface.
  282. *
  283. *****************************************************************************/
  284. STDMETHODIMP
  285. CFndCm_New(RIID riid, PPV ppvObj)
  286. {
  287. HRESULT hres;
  288. EnterProc(CFndCm_New, (_ "G", riid));
  289. *ppvObj = 0;
  290. hres = Common_New(CFndCm, ppvObj);
  291. if (SUCCEEDED(hres)) {
  292. PFCM pfcm = *ppvObj;
  293. pfcm->sxi.lpVtbl = Secondary_Vtbl(CFndCm, IShellExtInit);
  294. hres = CFndCm_QueryInterface(&pfcm->cm, riid, ppvObj);
  295. Common_Release(pfcm);
  296. }
  297. ExitOleProcPpv(ppvObj);
  298. return hres;
  299. }
  300. /*****************************************************************************
  301. *
  302. * The long-awaited vtbls
  303. *
  304. *****************************************************************************/
  305. #pragma BEGIN_CONST_DATA
  306. Primary_Interface_Begin(CFndCm, IContextMenu)
  307. CFndCm_QueryContextMenu,
  308. CFndCm_InvokeCommand,
  309. CFndCm_GetCommandString,
  310. Primary_Interface_End(CFndCm, IContextMenu)
  311. Secondary_Interface_Begin(CFndCm, IShellExtInit, sxi)
  312. CFndCm_SXI_Initialize,
  313. Secondary_Interface_End(CFndCm, IShellExtInit, sxi)