ReactOS  0.4.14-dev-358-gbef841c
CDefViewBckgrndMenu.cpp
Go to the documentation of this file.
1 /*
2  * PROJECT: shell32
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: dll/win32/shell32/CDefViewBckgrndMenu.cpp
5  * PURPOSE: background context menu of the CDefView
6  * PROGRAMMERS: Giannis Adamopoulos
7  */
8 
9 #include <precomp.h>
10 
12 
14  public CComObjectRootEx<CComMultiThreadModelNoCS>,
15  public IContextMenu3,
16  public IObjectWithSite
17 {
18  private:
22 
25 
27  BOOL _bCanPaste();
28  public:
32 
33  // IContextMenu
34  virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
36  virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen);
37 
38  // IContextMenu2
40 
41  // IContextMenu3
42  virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
43 
44  // IObjectWithSite
45  virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
46  virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
47 
49  COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
50  COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
51  COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3)
53  END_COM_MAP()
54 };
55 
57 {
58  m_idCmdFirst = 0;
59  m_LastFolderCMId = 0;
60 }
61 
63 {
64 }
65 
67 {
68  if (!m_site)
69  return FALSE;
70 
71  /* Get a pointer to the shell browser */
75  return FALSE;
76 
77  FOLDERSETTINGS FolderSettings;
78  hr = psv->GetCurrentInfo(&FolderSettings);
80  return FALSE;
81 
82  return ((FolderSettings.fFlags & FWF_DESKTOP) == FWF_DESKTOP);
83 }
84 
86 {
87  /* If the folder doesn't have a drop target we can't paste */
89  HRESULT hr = m_psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdt));
90  if (FAILED(hr))
91  return FALSE;
92 
93  /* We can only paste if CFSTR_SHELLIDLIST is present in the clipboard */
94  CComPtr<IDataObject> pDataObj;
95  hr = OleGetClipboard(&pDataObj);
96  if (FAILED(hr))
97  return FALSE;
98 
99  STGMEDIUM medium;
100  FORMATETC formatetc;
101 
102  /* Set the FORMATETC structure*/
103  InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
104  hr = pDataObj->GetData(&formatetc, &medium);
105  if (FAILED(hr))
106  return FALSE;
107 
108  ReleaseStgMedium(&medium);
109  return TRUE;
110 }
111 
112 HRESULT
114 {
115  m_psf = psf;
116 
117  /* Get the context menu of the folder. Do it here because someone may call
118  InvokeCommand without calling QueryContextMenu. It is fine if this fails */
119  m_psf->CreateViewObject(NULL, IID_PPV_ARG(IContextMenu, &m_folderCM));
120 
121  return S_OK;
122 }
123 
124 HRESULT
125 WINAPI
127 {
128  m_site = pUnkSite;
129 
130  if(m_folderCM)
131  IUnknown_SetSite(m_folderCM, pUnkSite);
132 
133  return S_OK;
134 }
135 
136 HRESULT
137 WINAPI
139 {
140  if (!m_site)
141  return E_FAIL;
142 
143  return m_site->QueryInterface(riid, ppvSite);
144 }
145 
146 HRESULT
147 WINAPI
148 CDefViewBckgrndMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
149 {
150  HRESULT hr;
151  HMENU hMenuPart;
152  UINT cIds = 0;
153 
154  /* This is something the implementations of IContextMenu should never really do.
155  However CDefViewBckgrndMenu is more or less an overengineering result, its code could really be part of the
156  CDefView. Given this, I think that abusing the interface here is not that bad since only CDefView is the ony
157  user of this class. Here we need to do two things to keep things as simple as possible.
158  First we want the menu part added by the shell folder to be the first to add so as to make as few id translations
159  as possible. Second, we want to add the default part of the background menu without shifted ids, so as
160  to let the CDefView fill some parts like filling the arrange modes or checking the view mode. In order
161  for that to work we need to save idCmdFirst because our caller will pass id offsets to InvokeCommand.
162  This makes it impossible to concatenate the CDefViewBckgrndMenu with other menus since it abuses IContextMenu
163  but as stated above, its sole user is CDefView and should really be that way. */
164  m_idCmdFirst = idCmdFirst;
165 
166  /* Let the shell folder add any items it wants to add in the background context menu */
167  if (m_folderCM)
168  {
169  hr = m_folderCM->QueryContextMenu(hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
170  if (SUCCEEDED(hr))
171  {
173  cIds = m_LastFolderCMId;
174  }
175  else
176  {
177  WARN("QueryContextMenu failed!\n");
178  }
179  }
180  else
181  {
182  WARN("GetUIObjectOf didn't give any context menu!\n");
183  }
184 
185  /* Load the default part of the background context menu */
186  hMenuPart = LoadMenuW(shell32_hInstance, L"MENU_002");
187  if (hMenuPart)
188  {
189  /* Don't show the view submenu for the desktop */
191  {
193  }
194 
195  /* Disable the paste options if it is not possible */
196  if (!_bCanPaste())
197  {
200  }
201 
202  /* merge general background context menu in */
203  Shell_MergeMenus(hMenu, GetSubMenu(hMenuPart, 0), indexMenu, 0, idCmdLast, MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS | MM_ADDSEPARATOR);
204  DestroyMenu(hMenuPart);
205  }
206  else
207  {
208  ERR("Failed to load menu from resource!\n");
209  }
210 
211  return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cIds);
212 }
213 
214 HRESULT
215 WINAPI
217 {
218  UINT idCmd = LOWORD(lpcmi->lpVerb);
219 
220  if (HIWORD(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, CMDSTR_VIEWLISTA))
221  {
222  idCmd = FCIDM_SHVIEW_LISTVIEW;
223  }
224  else if (HIWORD(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, CMDSTR_VIEWDETAILSA))
225  {
226  idCmd = FCIDM_SHVIEW_REPORTVIEW;
227  }
228  else if(HIWORD(lpcmi->lpVerb) != 0 || idCmd < m_LastFolderCMId)
229  {
230  if (m_folderCM)
231  {
232  return m_folderCM->InvokeCommand(lpcmi);
233  }
234  WARN("m_folderCM is NULL!\n");
235  return E_NOTIMPL;
236  }
237  else
238  {
239  /* The default part of the background menu doesn't have shifted ids so we need to convert the id offset to the real id */
240  idCmd += m_idCmdFirst;
241  }
242 
243  /* The commands that are handled by the def view are forwarded to it */
244  switch (idCmd)
245  {
246  case FCIDM_SHVIEW_INSERT:
248  if (m_folderCM)
249  {
250  lpcmi->lpVerb = MAKEINTRESOURCEA(idCmd);
251  return m_folderCM->InvokeCommand(lpcmi);
252  }
253  WARN("m_folderCM is NULL!\n");
254  return E_NOTIMPL;
259  case 0x30: /* FIX IDS in resource files */
260  case 0x31:
261  case 0x32:
262  case 0x33:
266  if (!m_site)
267  return E_FAIL;
268 
269  /* Get a pointer to the shell browser */
272  if (FAILED_UNEXPECTEDLY(hr))
273  return hr;
274 
275  HWND hwndSV = NULL;
276  if (SUCCEEDED(psv->GetWindow(&hwndSV)))
277  SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(idCmd, 0), 0);
278  return S_OK;
279  }
280 
281  ERR("Got unknown command id %ul\n", LOWORD(lpcmi->lpVerb));
282  return E_FAIL;
283 }
284 
285 HRESULT
286 WINAPI
287 CDefViewBckgrndMenu::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
288 {
289  if (m_folderCM)
290  {
291  return m_folderCM->GetCommandString(idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
292  }
293 
294  return E_NOTIMPL;
295 }
296 
297 HRESULT
298 WINAPI
300 {
301  if(m_folderCM)
302  {
303  CComPtr<IContextMenu2> pfolderCM2;
304  HRESULT hr = m_folderCM->QueryInterface(IID_PPV_ARG(IContextMenu2, &pfolderCM2));
305  if (FAILED_UNEXPECTEDLY(hr))
306  return hr;
307 
308  return pfolderCM2->HandleMenuMsg(uMsg, wParam, lParam);
309  }
310 
311  return E_NOTIMPL;
312 }
313 
314 HRESULT
315 WINAPI
317 {
318  if(m_folderCM)
319  {
320  CComPtr<IContextMenu3> pfolderCM3;
321  HRESULT hr = m_folderCM->QueryInterface(IID_PPV_ARG(IContextMenu3, &pfolderCM3));
322  if (FAILED_UNEXPECTEDLY(hr))
323  return hr;
324 
325  return pfolderCM3->HandleMenuMsg2(uMsg, wParam, lParam, plResult);
326  }
327 
328  return E_NOTIMPL;
329 }
330 
331 
332 HRESULT
334 {
335  return ShellObjectCreatorInit<CDefViewBckgrndMenu>(psf, riid, ppv);
336 }
virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
#define FCIDM_SHVIEW_LISTVIEW
Definition: shresdef.h:751
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define MAKEWPARAM(l, h)
Definition: winuser.h:3948
#define MF_BYCOMMAND
Definition: winuser.h:202
#define FCIDM_SHVIEW_SNAPTOGRID
Definition: shresdef.h:755
UINT WINAPI Shell_MergeMenus(HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags)
Definition: shlmenu.c:857
#define CFSTR_SHELLIDLIST
Definition: shlobj.h:469
#define FCIDM_SHVIEW_AUTOARRANGE
Definition: shresdef.h:754
HRESULT hr
Definition: shlfolder.c:183
#define InitFormatEtc(fe, cf, med)
Definition: editor.h:33
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
REFIID riid
Definition: precomp.h:44
UINT WINAPI RegisterClipboardFormatW(_In_ LPCWSTR)
CComPtr< IShellFolder > m_psf
virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite)
#define WARN(fmt,...)
Definition: debug.h:111
REFIID LPVOID * ppv
Definition: atlbase.h:39
CComPtr< IContextMenu > m_folderCM
#define MAKEINTRESOURCEA(i)
Definition: winuser.h:581
UINT_PTR WPARAM
Definition: windef.h:207
UINT uFlags
Definition: api.c:59
virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
char * LPSTR
Definition: xmlstorage.h:182
#define SID_IFolderView
#define IID_PPV_ARG(Itype, ppType)
#define E_FAIL
Definition: ddrawi.h:102
HRESULT WINAPI IUnknown_QueryService(IUnknown *, REFGUID, REFIID, LPVOID *)
Definition: ordinal.c:1448
WPARAM wParam
Definition: combotst.c:138
#define SEVERITY_SUCCESS
Definition: winerror.h:64
#define FCIDM_SHVIEW_INSERTLINK
Definition: shresdef.h:743
#define FCIDM_SHVIEW_REFRESH
Definition: shresdef.h:763
BOOL WINAPI EnableMenuItem(_In_ HMENU, _In_ UINT, _In_ UINT)
HINSTANCE shell32_hInstance
Definition: misc.cpp:82
unsigned int BOOL
Definition: ntddk_ex.h:94
HRESULT WINAPI OleGetClipboard(IDataObject **obj)
Definition: clipboard.c:2249
#define FCIDM_SHVIEW_INSERT
Definition: shresdef.h:741
HRESULT CDefViewBckgrndMenu_CreateInstance(IShellFolder *psf, REFIID riid, void **ppv)
HRESULT WINAPI IUnknown_SetSite(IUnknown *obj, IUnknown *site)
Definition: ordinal.c:1358
virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
smooth NULL
Definition: ftsmooth.c:416
LONG_PTR LPARAM
Definition: windef.h:208
#define MAKE_HRESULT(sev, fac, code)
Definition: dmerror.h:30
#define BEGIN_COM_MAP(x)
Definition: atlcom.h:541
HRESULT Initialize(IShellFolder *psf)
#define MM_ADDSEPARATOR
Definition: shlobj.h:2319
virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite)
LONG HRESULT
Definition: typedefs.h:77
BOOL WINAPI DeleteMenu(_In_ HMENU, _In_ UINT, _In_ UINT)
#define FCIDM_SHVIEW_REPORTVIEW
Definition: shresdef.h:752
#define FAILED_UNEXPECTEDLY(hr)
Definition: shellutils.h:71
#define FCIDM_SHVIEW_VIEW
Definition: shresdef.h:736
#define WINAPI
Definition: msvc.h:8
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
const IID IID_IObjectWithSite
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
static const WCHAR L[]
Definition: oid.c:1250
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
#define WM_COMMAND
Definition: winuser.h:1722
#define FCIDM_SHVIEW_BIGICON
Definition: shresdef.h:749
CComPtr< IUnknown > m_site
BOOL WINAPI DestroyMenu(_In_ HMENU)
#define ERR(fmt,...)
Definition: debug.h:109
#define S_OK
Definition: intsafe.h:59
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define COM_INTERFACE_ENTRY_IID(iid, x)
Definition: atlcom.h:561
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define E_NOTIMPL
Definition: ddrawi.h:99
unsigned int UINT
Definition: ndis.h:50
WINE_DEFAULT_DEBUG_CHANNEL(shell)
virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
#define MM_SUBMENUSHAVEIDS
Definition: shlobj.h:2320
virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
HMENU WINAPI LoadMenuW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
#define HIWORD(l)
Definition: typedefs.h:246
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define END_COM_MAP()
Definition: atlcom.h:552
#define MF_GRAYED
Definition: winuser.h:129
LONG_PTR LRESULT
Definition: windef.h:209
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
#define FCIDM_SHVIEW_SMALLICON
Definition: shresdef.h:750
LPARAM lParam
Definition: combotst.c:139
#define LOWORD(l)
Definition: pedump.c:82
#define MM_DONTREMOVESEPS
Definition: shlobj.h:2321
#define SUCCEEDED(hr)
Definition: intsafe.h:57