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
10 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: I C O N T E X T M . C P P
  7. //
  8. // Contents: IContextMenu implementation for CConnectionFolderExtractIcon
  9. //
  10. // Notes:
  11. //
  12. // Author: jeffspr 24 Oct 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "foldinc.h" // Standard shell\folder includes
  18. #include <nsres.h>
  19. #include "foldres.h"
  20. #include "oncommand.h"
  21. #include "cmdtable.h"
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Member: CConnectionFolderContextMenu::CreateInstance
  25. //
  26. // Purpose: Create an instance of the CConnectionFolderContextMenu object
  27. //
  28. // Arguments:
  29. // riid [in] Interface requested
  30. // ppv [out] Pointer to receive the requested interface
  31. //
  32. // Returns:
  33. //
  34. // Author: jeffspr 7 Aug 1998
  35. //
  36. // Notes:
  37. //
  38. HRESULT CConnectionFolderContextMenu::CreateInstance(
  39. REFIID riid,
  40. void** ppv,
  41. CMENU_TYPE cmt,
  42. HWND hwndOwner,
  43. const PCONFOLDPIDLVEC& apidl,
  44. LPSHELLFOLDER psf)
  45. {
  46. TraceFileFunc(ttidShellFolderIface);
  47. HRESULT hr = E_OUTOFMEMORY;
  48. CConnectionFolderContextMenu * pObj = NULL;
  49. pObj = new CComObject <CConnectionFolderContextMenu>;
  50. if (pObj)
  51. {
  52. // Do the standard CComCreator::CreateInstance stuff.
  53. //
  54. pObj->SetVoid (NULL);
  55. pObj->InternalFinalConstructAddRef ();
  56. hr = pObj->FinalConstruct ();
  57. pObj->InternalFinalConstructRelease ();
  58. if (SUCCEEDED(hr))
  59. {
  60. hr = pObj->HrInitialize(cmt, hwndOwner, apidl, psf);
  61. if (SUCCEEDED(hr))
  62. {
  63. hr = pObj->QueryInterface (riid, ppv);
  64. }
  65. }
  66. if (FAILED(hr))
  67. {
  68. delete pObj;
  69. }
  70. }
  71. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolderContextMenu::CreateInstance");
  72. return hr;
  73. }
  74. //+---------------------------------------------------------------------------
  75. //
  76. // Member: CConnectionFolderContextMenu::CConnectionFolderContextMenu
  77. //
  78. // Purpose: Constructor for CConnectionFolderContextMenu. Initialize
  79. // data members
  80. //
  81. // Arguments:
  82. // (none)
  83. //
  84. // Returns:
  85. //
  86. // Author: jeffspr 7 Aug 1998
  87. //
  88. // Notes:
  89. //
  90. CConnectionFolderContextMenu::CConnectionFolderContextMenu()
  91. {
  92. TraceFileFunc(ttidShellFolderIface);
  93. m_psf = NULL;
  94. m_cidl = 0;
  95. m_hwndOwner = NULL;
  96. m_cmt = CMT_OBJECT; // arbitrary. Just make sure it's something
  97. }
  98. //+---------------------------------------------------------------------------
  99. //
  100. // Member: CConnectionFolderContextMenu::HrInitialize
  101. //
  102. // Purpose: Initialization for the context menu object. Make copies of
  103. // the pidl array, etc.
  104. //
  105. // Arguments:
  106. // hwndOwner [in] Our parent hwnd
  107. // apidl [in] Pidl array of selected items
  108. // psf [in] Our shell folder pointer
  109. //
  110. // Returns:
  111. //
  112. // Author: jeffspr 7 Aug 1998
  113. //
  114. // Notes:
  115. //
  116. HRESULT CConnectionFolderContextMenu::HrInitialize(
  117. CMENU_TYPE cmt,
  118. HWND hwndOwner,
  119. const PCONFOLDPIDLVEC& apidl,
  120. LPSHELLFOLDER psf)
  121. {
  122. TraceFileFunc(ttidShellFolderIface);
  123. HRESULT hr = NOERROR;
  124. // Grab and addref the folder object
  125. //
  126. Assert(psf);
  127. psf->AddRef();
  128. m_psf = static_cast<CConnectionFolder *>(psf);
  129. // Copy the context menu type (object -vs- background)
  130. //
  131. m_cmt = cmt;
  132. // Note: This will be NULL if the context menu is invoked from the desktop
  133. //
  134. m_hwndOwner = hwndOwner;
  135. if (!apidl.empty())
  136. {
  137. Assert(CMT_OBJECT == cmt);
  138. // Clone the pidl array using the cache
  139. //
  140. hr = HrCloneRgIDL(apidl, TRUE, TRUE, m_apidl);
  141. if (FAILED(hr))
  142. {
  143. TraceHr(ttidError, FAL, hr, FALSE, "HrCloneRgIDL failed on apidl in "
  144. "CConnectionFolderContextMenu::HrInitialize");
  145. }
  146. }
  147. else
  148. {
  149. Assert(CMT_BACKGROUND == cmt);
  150. }
  151. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolderContextMenu::HrInitialize");
  152. return hr;
  153. }
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Member: CConnectionFolderContextMenu::~CConnectionFolderContextMenu
  157. //
  158. // Purpose: Destructor. Free the pidl array and release the shell folder
  159. // object
  160. //
  161. // Arguments:
  162. // (none)
  163. //
  164. // Returns:
  165. //
  166. // Author: jeffspr 7 Aug 1998
  167. //
  168. // Notes:
  169. //
  170. CConnectionFolderContextMenu::~CConnectionFolderContextMenu()
  171. {
  172. TraceFileFunc(ttidShellFolderIface);
  173. if (m_psf)
  174. {
  175. ReleaseObj(reinterpret_cast<LPSHELLFOLDER>(m_psf));
  176. }
  177. }
  178. //+---------------------------------------------------------------------------
  179. //
  180. // Member: CConnectionFolderContextMenu::QueryContextMenu
  181. //
  182. // Purpose: Adds menu items to the specified menu. The menu items should
  183. // be inserted in the menu at the position specified by
  184. // indexMenu, and their menu item identifiers must be between
  185. // the idCmdFirst and idCmdLast parameter values.
  186. //
  187. // Arguments:
  188. // hmenu [in] Handle to the menu. The handler should specify this
  189. // handle when adding menu items
  190. // indexMenu [in] Zero-based position at which to insert the first
  191. // menu item.
  192. // idCmdFirst [in] Min value the handler can specify for a menu item
  193. // idCmdLast [in] Max value the handler can specify for a menu item
  194. // uFlags [in] Optional flags specifying how the context menu
  195. // can be changed. See MSDN for the full list.
  196. //
  197. // Returns:
  198. //
  199. // Author: jeffspr 7 Aug 1998
  200. //
  201. // Notes:
  202. //
  203. HRESULT CConnectionFolderContextMenu::QueryContextMenu(
  204. HMENU hmenu,
  205. UINT indexMenu,
  206. UINT idCmdFirst,
  207. UINT idCmdLast,
  208. UINT uFlags)
  209. {
  210. TraceFileFunc(ttidShellFolderIface);
  211. HRESULT hr = S_OK;
  212. BOOL fVerbsOnly = !!(uFlags & CMF_VERBSONLY);
  213. if ( (m_apidl.size() != 0) && !(uFlags & CMF_DVFILE))
  214. {
  215. HMENU hMenuTmp = NULL;
  216. hMenuTmp = CreateMenu();
  217. if (hMenuTmp)
  218. {
  219. hr = HrBuildMenu(hMenuTmp, fVerbsOnly, m_apidl, 0);
  220. if (SUCCEEDED(hr))
  221. {
  222. UINT idMax = Shell_MergeMenus(
  223. hmenu,
  224. hMenuTmp,
  225. 0,
  226. idCmdFirst,
  227. idCmdLast,
  228. MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS);
  229. hr = ResultFromShort(idMax - idCmdFirst);
  230. }
  231. DestroyMenu(hMenuTmp);
  232. }
  233. }
  234. else
  235. {
  236. // mbend - we skip this because defview does file menu merging.
  237. }
  238. // Ignore this trace if it's a short, basically.
  239. //
  240. TraceHr(ttidError, FAL, hr, SUCCEEDED(hr), "CConnectionFolderContextMenu::QueryContextMenu");
  241. return hr;
  242. }
  243. //+---------------------------------------------------------------------------
  244. //
  245. // Member: CConnectionFolderContextMenu::InvokeCommand
  246. //
  247. // Purpose: Carries out the command associated with a context menu item.
  248. //
  249. // Arguments:
  250. // lpici [in] Address of a CMINVOKECOMMANDINFO structure containing
  251. // information about the command.
  252. //
  253. // Returns: Returns NOERROR if successful, or an OLE-defined
  254. // error code otherwise.
  255. //
  256. // Author: jeffspr 27 Apr 1999
  257. //
  258. // Notes:
  259. //
  260. HRESULT CConnectionFolderContextMenu::InvokeCommand(
  261. LPCMINVOKECOMMANDINFO lpici)
  262. {
  263. TraceFileFunc(ttidShellFolderIface);
  264. HRESULT hr = NOERROR;
  265. UINT uiCmd = 0;
  266. Assert(lpici);
  267. Assert(lpici->lpVerb);
  268. if (HIWORD(lpici->lpVerb))
  269. {
  270. // Deal with string commands
  271. PSTR pszCmd = (PSTR)lpici->lpVerb;
  272. // Only folder objects currently support string-based invoke commands.
  273. // (The background does not)
  274. //
  275. if (CMT_OBJECT == m_cmt)
  276. {
  277. if (0 == lstrcmpA(pszCmd, "delete"))
  278. {
  279. uiCmd = CMIDM_DELETE;
  280. }
  281. else if (0 == lstrcmpA(pszCmd, "properties"))
  282. {
  283. uiCmd = CMIDM_PROPERTIES;
  284. }
  285. else if (0 == lstrcmpA(pszCmd, "wzcproperties"))
  286. {
  287. uiCmd = CMIDM_WZCPROPERTIES;
  288. }
  289. else if (0 == lstrcmpA(pszCmd, "rename"))
  290. {
  291. uiCmd = CMIDM_RENAME;
  292. }
  293. else if (0 == lstrcmpA(pszCmd, "link"))
  294. {
  295. uiCmd = CMIDM_CREATE_SHORTCUT;
  296. }
  297. }
  298. if (0 == uiCmd)
  299. {
  300. TraceTag(ttidError, "Unprocessed InvokeCommand<%s>\n", pszCmd);
  301. hr = E_INVALIDARG;
  302. }
  303. }
  304. else
  305. {
  306. uiCmd = (UINT)LOWORD((DWORD_PTR)lpici->lpVerb);
  307. }
  308. if (SUCCEEDED(hr))
  309. {
  310. // Handle the actual command
  311. //
  312. hr = HrFolderCommandHandler(uiCmd, m_apidl, m_hwndOwner, lpici, m_psf);
  313. }
  314. TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolderContextMenu::InvokeCommand");
  315. return hr;
  316. }
  317. HRESULT CConnectionFolderContextMenu::GetCommandString(
  318. UINT_PTR idCmd,
  319. UINT uType,
  320. UINT * pwReserved,
  321. PSTR pszName,
  322. UINT cchMax)
  323. {
  324. TraceFileFunc(ttidShellFolderIface);
  325. HRESULT hr = E_FAIL; // Not handled
  326. *((PWSTR)pszName) = L'\0';
  327. if (uType == GCS_HELPTEXT)
  328. {
  329. int iLength = LoadString( _Module.GetResourceInstance(),
  330. idCmd + IDS_CMIDM_START,
  331. (PWSTR) pszName,
  332. cchMax);
  333. if (iLength > 0)
  334. {
  335. hr = NOERROR;
  336. }
  337. else
  338. {
  339. AssertSz(FALSE, "Resource string not found for one of the connections folder commands");
  340. }
  341. }
  342. else
  343. {
  344. if (uType == GCS_VERB && idCmd == CMIDM_RENAME)
  345. {
  346. // "rename" is language independent
  347. lstrcpyW((PWSTR)pszName, L"rename");
  348. hr = NOERROR;
  349. }
  350. }
  351. TraceHr(ttidError, FAL, hr, (hr == E_FAIL), "CConnectionFolderContextMenu::GetCommandString");
  352. return hr;
  353. }