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.

466 lines
12 KiB

  1. /*****************************************************************************
  2. *
  3. * fndcm.c - IContextMenu interface
  4. *
  5. *****************************************************************************/
  6. #include "fnd.h"
  7. #include <wab.h>
  8. #include <shlwapi.h>
  9. #ifdef _WIN64
  10. #pragma pack(push,8)
  11. #endif // _WIN64
  12. /*****************************************************************************
  13. *
  14. * The sqiffle for this file.
  15. *
  16. *****************************************************************************/
  17. #define sqfl sqflCm
  18. /*****************************************************************************
  19. *
  20. * PICI
  21. *
  22. * I'm getting lazy.
  23. *
  24. *****************************************************************************/
  25. typedef LPCMINVOKECOMMANDINFO PICI;
  26. /*****************************************************************************
  27. *
  28. * Declare the interfaces we will be providing.
  29. *
  30. * We must implement an IShellExtInit so the shell
  31. * will know that we are ready for action.
  32. *
  33. *****************************************************************************/
  34. Primary_Interface(CFndCm, IContextMenu);
  35. Secondary_Interface(CFndCm, IShellExtInit);
  36. /*****************************************************************************
  37. *
  38. * CFndCm
  39. *
  40. * The context menu extension for "Find... &People".
  41. *
  42. *****************************************************************************/
  43. typedef struct CFndCm {
  44. /* Supported interfaces */
  45. IContextMenu cm;
  46. IShellExtInit sxi;
  47. } CFndCm, FCM, *PFCM;
  48. typedef IContextMenu CM, *PCM;
  49. typedef IShellExtInit SXI, *PSXI;
  50. typedef IDataObject DTO, *PDTO;
  51. /*****************************************************************************
  52. *
  53. * CFndCm_QueryInterface (from IUnknown)
  54. *
  55. * We need to check for our additional interfaces before falling
  56. * through to Common_QueryInterface.
  57. *
  58. *****************************************************************************/
  59. STDMETHODIMP
  60. CFndCm_QueryInterface(PCM pcm, RIID riid, PPV ppvObj)
  61. {
  62. PFCM this = IToClass(CFndCm, cm, pcm);
  63. HRESULT hres;
  64. if (IsEqualIID(riid, &IID_IShellExtInit)) {
  65. *ppvObj = &this->sxi;
  66. Common_AddRef(this);
  67. hres = NOERROR;
  68. } else {
  69. hres = Common_QueryInterface(this, riid, ppvObj);
  70. }
  71. AssertF(fLimpFF(FAILED(hres), *ppvObj == 0));
  72. return hres;
  73. }
  74. /*****************************************************************************
  75. *
  76. * CFndCm_AddRef (from IUnknown)
  77. * CFndCm_Release (from IUnknown)
  78. *
  79. *****************************************************************************/
  80. #define CFndCm_AddRef Common_AddRef
  81. #define CFndCm_Release Common_Release
  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... People" 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(".{32714800-2E5F-11d0-8B85-00AA0044F941}");
  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. const static TCHAR lpszWABRegPathKey[] = TEXT("Software\\Microsoft\\WAB\\DLLPath");
  142. const static TCHAR lpszWABDll[] = TEXT("Wab32.dll");
  143. // GetWABDllPath - loads the WAB DLL path from the registry
  144. // szPath - ptr to buffer
  145. // cb - sizeof buffer
  146. //
  147. void GetWABDllPath(LPTSTR szPath, ULONG cb)
  148. {
  149. DWORD dwType = 0;
  150. ULONG cbData = cb;
  151. HKEY hKey = NULL;
  152. if(szPath)
  153. {
  154. *szPath = '\0';
  155. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszWABRegPathKey, 0, KEY_READ, &hKey))
  156. RegQueryValueEx( hKey, "", NULL, &dwType, (LPBYTE) szPath, &cbData);
  157. }
  158. if(hKey) RegCloseKey(hKey);
  159. return;
  160. }
  161. // LoadLibrary_WABDll() - Load the WAB library based on the WAB DLL path
  162. //
  163. HINSTANCE LoadLibrary_WABDll()
  164. {
  165. TCHAR szWABDllPath[MAX_PATH];
  166. // [PaulHi] We only need one reference count on the wab32.dll. The wabfind.dll
  167. // will unload the wab32.dll when it unloads. The wabfind.dll won't unload
  168. // until all CMFind threads are finished through the global g_cRef variable.
  169. if (g_hinstWABDLL)
  170. return g_hinstWABDLL;
  171. GetWABDllPath(szWABDllPath, sizeof(szWABDllPath));
  172. // if you want an IE4.0x WAB or later then you should fail here if the WAB
  173. // DLL path could not be retreived from the registry
  174. // Otherwise, if you don't care, you can just do a LoadLibrary("wab32.dll")
  175. return(g_hinstWABDLL = LoadLibrary( (lstrlen(szWABDllPath)) ? szWABDllPath : lpszWABDll ));
  176. }
  177. //
  178. // Initialize the WAB and get an instance of IWABObject and IAddrBook
  179. //
  180. HRESULT InitWAB(LPWABOBJECT * lppWABObject,
  181. LPADRBOOK * lppAdrBook)
  182. {
  183. HRESULT hr = E_FAIL;
  184. LPWABOPEN lpfnWABOpen = NULL; // defined in WABAPI.H
  185. HINSTANCE hinstWAB = NULL;
  186. WAB_PARAM WP = {0};
  187. WP.ulFlags = WAB_ENABLE_PROFILES;
  188. hinstWAB = LoadLibrary_WABDll();
  189. if(hinstWAB)
  190. {
  191. lpfnWABOpen = (LPWABOPEN) GetProcAddress(hinstWAB, "WABOpen");
  192. if(lpfnWABOpen)
  193. hr = lpfnWABOpen(lppAdrBook, lppWABObject, &WP, 0);
  194. }
  195. // Remember to release the IAddrBook and IWABObject objects retrieved above
  196. return hr;
  197. }
  198. /*
  199. -
  200. - WABThreadProc
  201. *
  202. * Since the WAB Find thing is a dialog, it is blocking Explorer's thread
  203. * and user's can't access the Start menu anymore .. so we put the dialog
  204. * on a seperate thread
  205. *
  206. */
  207. DWORD WINAPI WABThreadProc( LPVOID lpParam )
  208. {
  209. HRESULT hres;
  210. LPWABOBJECT lpWABObject = NULL;
  211. LPADRBOOK lpAdrBook = NULL;
  212. if(!HR_FAILED(hres = InitWAB(&lpWABObject,&lpAdrBook)))
  213. {
  214. hres = lpWABObject->lpVtbl->Find(lpWABObject,lpAdrBook,NULL);
  215. // Release the WAB and AB objects
  216. lpAdrBook->lpVtbl->Release(lpAdrBook);
  217. lpWABObject->lpVtbl->Release(lpWABObject);
  218. }
  219. // Our work is done, wabfind.dll can safely go away
  220. InterlockedDecrement((LPLONG)&g_cRef);
  221. return 0;
  222. }
  223. /*****************************************************************************
  224. *
  225. * _CFndCm_InvokeFind
  226. *
  227. *****************************************************************************/
  228. STDMETHODIMP
  229. _CFndCm_InvokeFind(void)
  230. {
  231. HANDLE hThread = NULL;
  232. DWORD dwThreadID = 0;
  233. // Increment the refcount so that when the Shell continues (the Invoke returns)
  234. // wabfind.dll doesn't unload when the Shell releases the FindCM
  235. InterlockedIncrement((LPLONG)&g_cRef);
  236. hThread = CreateThread( NULL, // no security attributes
  237. 0, // use default stack size
  238. WABThreadProc, // thread function
  239. (LPVOID) NULL, // argument to thread function
  240. 0, // use default creation flags
  241. &dwThreadID); // returns the thread identifier
  242. CloseHandle(hThread);
  243. return S_OK;
  244. }
  245. /*****************************************************************************
  246. *
  247. * CFndCm_InvokeCommand (from IContextMenu)
  248. *
  249. * We have only one command, called "find".
  250. *
  251. *****************************************************************************/
  252. #pragma BEGIN_CONST_DATA
  253. TCHAR c_tszFind[] = TEXT("find");
  254. #pragma END_CONST_DATA
  255. STDMETHODIMP
  256. CFndCm_InvokeCommand(PCM pcm, PICI pici)
  257. {
  258. PFCM this = IToClass(CFndCm, cm, pcm);
  259. HRESULT hres;
  260. EnterProc(CFndCm_InvokeCommand,
  261. (_ HIWORD(pici->lpVerb) ? "pA" : "pu", pcm, pici->lpVerb));
  262. if (pici->cbSize >= sizeof(*pici)) {
  263. if (
  264. #ifdef SHELL32_IS_BUG_FREE //;Internal
  265. (HIWORD(pici->lpVerb) && lstrcmpi(c_tszFind, pici->lpVerb) == 0) || //;Internal
  266. pici->lpVerb == 0 //;Internal
  267. #else //;Internal
  268. fLimpFF(HIWORD(pici->lpVerb), lstrcmpi(c_tszFind, pici->lpVerb) == 0)
  269. #endif //;Internal
  270. ) {
  271. hres = _CFndCm_InvokeFind();
  272. } else {
  273. hres = E_INVALIDARG;
  274. }
  275. } else {
  276. hres = E_INVALIDARG;
  277. }
  278. ExitOleProc();
  279. return hres;
  280. }
  281. /*****************************************************************************
  282. *
  283. * CFndCm_GetCommandString (from IContextMenu)
  284. *
  285. * Somebody wants to convert a command id into a string of some sort.
  286. *
  287. *****************************************************************************/
  288. STDMETHODIMP
  289. CFndCm_GetCommandString(PCM pcm, UINT_PTR idCmd, UINT uFlags, UINT *pwRsv,
  290. LPSTR pszName, UINT cchMax)
  291. {
  292. PFCM this = IToClass(CFndCm, cm, pcm);
  293. HRESULT hres;
  294. EnterProc(CFndCm_GetCommandString, (_ "uu", idCmd, uFlags));
  295. if (idCmd == 0) {
  296. switch (uFlags) {
  297. case GCS_HELPTEXT:
  298. if (cchMax) {
  299. pszName[0] = '\0';
  300. if (LoadString(g_hinst, IDS_FINDHELP, pszName, cchMax)) {
  301. hres = NOERROR;
  302. } else {
  303. hres = E_INVALIDARG;
  304. }
  305. } else {
  306. hres = E_INVALIDARG;
  307. }
  308. break;
  309. case GCS_VALIDATE:
  310. hres = NOERROR;
  311. break;
  312. case GCS_VERB:
  313. StrCpyN(pszName, c_tszFind, cchMax);
  314. hres = NOERROR;
  315. break;
  316. default:
  317. hres = E_NOTIMPL;
  318. break;
  319. }
  320. } else {
  321. hres = E_INVALIDARG;
  322. }
  323. ExitOleProc();
  324. return hres;
  325. }
  326. /*****************************************************************************
  327. *
  328. * CFndCm_SXI_Initialize (from IShellExtension)
  329. *
  330. *****************************************************************************/
  331. STDMETHODIMP
  332. CFndCm_SXI_Initialize(PSXI psxi, PCIDL pidlFolder, PDTO pdto, HKEY hk)
  333. {
  334. PFCM this = IToClass(CFndCm, sxi, psxi);
  335. HRESULT hres;
  336. EnterProc(CFndCm_SXI_Initialize, (_ ""));
  337. hres = S_OK;
  338. ExitOleProc();
  339. return hres;
  340. }
  341. /*****************************************************************************
  342. *
  343. * CFndCm_New (from IClassFactory)
  344. *
  345. * Note that we release the pfcm that Common_New created, because we
  346. * are done with it. The real refcount is handled by the
  347. * CFndCm_QueryInterface.
  348. *
  349. *****************************************************************************/
  350. STDMETHODIMP
  351. CFndCm_New(RIID riid, PPV ppvObj)
  352. {
  353. HRESULT hres;
  354. EnterProc(CFndCm_New, (_ "G", riid));
  355. *ppvObj = 0;
  356. hres = Common_New(CFndCm, ppvObj);
  357. if (SUCCEEDED(hres)) {
  358. PFCM pfcm = *ppvObj;
  359. pfcm->sxi.lpVtbl = Secondary_Vtbl(CFndCm, IShellExtInit);
  360. hres = CFndCm_QueryInterface(&pfcm->cm, riid, ppvObj);
  361. Common_Release(pfcm);
  362. }
  363. ExitOleProcPpv(ppvObj);
  364. return hres;
  365. }
  366. /*****************************************************************************
  367. *
  368. * The long-awaited vtbls
  369. *
  370. *****************************************************************************/
  371. #pragma BEGIN_CONST_DATA
  372. Primary_Interface_Begin(CFndCm, IContextMenu)
  373. CFndCm_QueryContextMenu,
  374. CFndCm_InvokeCommand,
  375. CFndCm_GetCommandString,
  376. Primary_Interface_End(CFndCm, IContextMenu)
  377. Secondary_Interface_Begin(CFndCm, IShellExtInit, sxi)
  378. CFndCm_SXI_Initialize,
  379. Secondary_Interface_End(CFndCm, IShellExtInit, sxi)
  380. #ifdef _WIN64
  381. #pragma pack(pop)
  382. #endif //_WIN64