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.

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