Eliminated warnings.
[wine.git] / dlls / shell32 / contmenu.c
bloba3b57caf18a65572cc8dc1d82c433ea12d36d070
1 /*
2 * IContextMenu
4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
5 */
6 #include <string.h>
8 #include "winerror.h"
9 #include "debugtools.h"
11 #include "pidl.h"
12 #include "wine/obj_base.h"
13 #include "wine/obj_contextmenu.h"
14 #include "wine/obj_shellbrowser.h"
15 #include "wine/obj_shellextinit.h"
16 #include "wine/undocshell.h"
18 #include "shell32_main.h"
20 DEFAULT_DEBUG_CHANNEL(shell)
22 /**************************************************************************
23 * IContextMenu Implementation
25 typedef struct
26 { ICOM_VTABLE(IContextMenu)* lpvtbl;
27 DWORD ref;
28 IShellFolder* pSFParent;
29 LPITEMIDLIST pidl; /* root pidl */
30 LPITEMIDLIST *aPidls; /* array of child pidls */
31 BOOL bAllValues;
32 } IContextMenuImpl;
35 static struct ICOM_VTABLE(IContextMenu) cmvt;
37 /**************************************************************************
38 * IContextMenu_AllocPidlTable()
40 BOOL IContextMenu_AllocPidlTable(IContextMenuImpl *This, DWORD dwEntries)
42 TRACE("(%p)->(entrys=%lu)\n",This, dwEntries);
44 /*add one for NULL terminator */
45 dwEntries++;
47 This->aPidls = (LPITEMIDLIST*)SHAlloc(dwEntries * sizeof(LPITEMIDLIST));
49 if(This->aPidls)
50 { ZeroMemory(This->aPidls, dwEntries * sizeof(LPITEMIDLIST)); /*set all of the entries to NULL*/
52 return (This->aPidls != NULL);
55 /**************************************************************************
56 * IContextMenu_FreePidlTable()
58 void IContextMenu_FreePidlTable(IContextMenuImpl *This)
60 int i;
62 TRACE("(%p)->()\n",This);
64 if(This->aPidls)
65 { for(i = 0; This->aPidls[i]; i++)
66 { SHFree(This->aPidls[i]);
69 SHFree(This->aPidls);
70 This->aPidls = NULL;
74 /**************************************************************************
75 * IContextMenu_FillPidlTable()
77 BOOL IContextMenu_FillPidlTable(IContextMenuImpl *This, LPCITEMIDLIST *aPidls, UINT uItemCount)
79 UINT i;
81 TRACE("(%p)->(apidl=%p count=%u)\n",This, aPidls, uItemCount);
83 if(This->aPidls)
84 { for(i = 0; i < uItemCount; i++)
85 { This->aPidls[i] = ILClone(aPidls[i]);
87 return TRUE;
89 return FALSE;
92 /**************************************************************************
93 * IContextMenu_CanRenameItems()
95 BOOL IContextMenu_CanRenameItems(IContextMenuImpl *This)
96 { UINT i;
97 DWORD dwAttributes;
99 TRACE("(%p)->()\n",This);
101 if(This->aPidls)
103 for(i = 0; This->aPidls[i]; i++){} /*get the number of items assigned to This object*/
104 { if(i > 1) /*you can't rename more than one item at a time*/
105 { return FALSE;
108 dwAttributes = SFGAO_CANRENAME;
109 IShellFolder_GetAttributesOf(This->pSFParent, i, (LPCITEMIDLIST*)This->aPidls, &dwAttributes);
111 return dwAttributes & SFGAO_CANRENAME;
113 return FALSE;
116 /**************************************************************************
117 * IContextMenu_Constructor()
119 IContextMenu *IContextMenu_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, LPCITEMIDLIST *aPidls, UINT uItemCount)
120 { IContextMenuImpl* cm;
121 UINT u;
123 cm = (IContextMenuImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenuImpl));
124 cm->lpvtbl=&cmvt;
125 cm->ref = 1;
126 cm->pidl = ILClone(pidl);
128 cm->pSFParent = pSFParent;
130 if(pSFParent)
131 IShellFolder_AddRef(pSFParent);
133 cm->aPidls = NULL;
135 IContextMenu_AllocPidlTable(cm, uItemCount);
137 if(cm->aPidls)
138 { IContextMenu_FillPidlTable(cm, aPidls, uItemCount);
141 cm->bAllValues = 1;
142 for(u = 0; u < uItemCount; u++)
143 { cm->bAllValues &= (_ILIsValue(aPidls[u]) ? 1 : 0);
145 TRACE("(%p)->()\n",cm);
146 shell32_ObjCount++;
147 return (IContextMenu*)cm;
150 /**************************************************************************
151 * IContextMenu_fnQueryInterface
153 static HRESULT WINAPI IContextMenu_fnQueryInterface(IContextMenu *iface, REFIID riid, LPVOID *ppvObj)
155 ICOM_THIS(IContextMenuImpl, iface);
157 char xriid[50];
158 WINE_StringFromCLSID((LPCLSID)riid,xriid);
160 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
162 *ppvObj = NULL;
164 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
165 { *ppvObj = This;
167 else if(IsEqualIID(riid, &IID_IContextMenu)) /*IContextMenu*/
168 { *ppvObj = This;
170 else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/
171 { FIXME("-- LPSHELLEXTINIT pointer requested\n");
174 if(*ppvObj)
176 IContextMenu_AddRef((IContextMenu*)*ppvObj);
177 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
178 return S_OK;
180 TRACE("-- Interface: E_NOINTERFACE\n");
181 return E_NOINTERFACE;
184 /**************************************************************************
185 * IContextMenu_fnAddRef
187 static ULONG WINAPI IContextMenu_fnAddRef(IContextMenu *iface)
189 ICOM_THIS(IContextMenuImpl, iface);
191 TRACE("(%p)->(count=%lu)\n",This, This->ref);
193 shell32_ObjCount++;
194 return ++(This->ref);
197 /**************************************************************************
198 * IContextMenu_fnRelease
200 static ULONG WINAPI IContextMenu_fnRelease(IContextMenu *iface)
202 ICOM_THIS(IContextMenuImpl, iface);
204 TRACE("(%p)->()\n",This);
206 shell32_ObjCount--;
208 if (!--(This->ref))
209 { TRACE(" destroying IContextMenu(%p)\n",This);
211 if(This->pSFParent)
212 IShellFolder_Release(This->pSFParent);
214 if(This->pidl)
215 SHFree(This->pidl);
217 /*make sure the pidl is freed*/
218 if(This->aPidls)
219 { IContextMenu_FreePidlTable(This);
222 HeapFree(GetProcessHeap(),0,This);
223 return 0;
225 return This->ref;
228 /**************************************************************************
229 * ICM_InsertItem()
231 void WINAPI _InsertMenuItem (
232 HMENU hmenu,
233 UINT indexMenu,
234 BOOL fByPosition,
235 UINT wID,
236 UINT fType,
237 LPSTR dwTypeData,
238 UINT fState)
240 MENUITEMINFOA mii;
242 ZeroMemory(&mii, sizeof(mii));
243 mii.cbSize = sizeof(mii);
244 if (fType == MFT_SEPARATOR)
245 { mii.fMask = MIIM_ID | MIIM_TYPE;
247 else
248 { mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
249 mii.dwTypeData = dwTypeData;
250 mii.fState = fState;
252 mii.wID = wID;
253 mii.fType = fType;
254 InsertMenuItemA( hmenu, indexMenu, fByPosition, &mii);
256 /**************************************************************************
257 * IContextMenu_fnQueryContextMenu()
260 static HRESULT WINAPI IContextMenu_fnQueryContextMenu(
261 IContextMenu *iface,
262 HMENU hmenu,
263 UINT indexMenu,
264 UINT idCmdFirst,
265 UINT idCmdLast,
266 UINT uFlags)
268 ICOM_THIS(IContextMenuImpl, iface);
270 BOOL fExplore ;
272 TRACE("(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
274 if(!(CMF_DEFAULTONLY & uFlags))
275 { if(!This->bAllValues)
276 { /* folder menu */
277 fExplore = uFlags & CMF_EXPLORE;
278 if(fExplore)
279 { _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED|MFS_DEFAULT);
280 _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_OPEN, MFT_STRING, "&Open", MFS_ENABLED);
282 else
283 { _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_OPEN, MFT_STRING, "&Open", MFS_ENABLED|MFS_DEFAULT);
284 _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED);
287 if(uFlags & CMF_CANRENAME)
288 { _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
289 _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_RENAME, MFT_STRING, "&Rename", (IContextMenu_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED));
292 else /* file menu */
293 { _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_OPEN, MFT_STRING, "&Open", MFS_ENABLED|MFS_DEFAULT);
294 if(uFlags & CMF_CANRENAME)
295 { _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
296 _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_RENAME, MFT_STRING, "&Rename", (IContextMenu_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED));
299 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (IDM_LAST + 1));
301 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
304 /**************************************************************************
305 * IContextMenu_fnInvokeCommand()
307 static HRESULT WINAPI IContextMenu_fnInvokeCommand(
308 IContextMenu *iface,
309 LPCMINVOKECOMMANDINFO lpcmi)
311 ICOM_THIS(IContextMenuImpl, iface);
313 LPITEMIDLIST pidlFQ;
314 SHELLEXECUTEINFOA sei;
315 int i;
317 TRACE("(%p)->(invcom=%p verb=%p wnd=%x)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
319 if(LOWORD(lpcmi->lpVerb) > IDM_LAST)
320 return E_INVALIDARG;
322 switch(LOWORD(lpcmi->lpVerb))
323 { case IDM_EXPLORE:
324 case IDM_OPEN:
325 /* Find the first item in the list that is not a value. These commands
326 should never be invoked if there isn't at least one folder item in the list.*/
328 for(i = 0; This->aPidls[i]; i++)
329 { if(!_ILIsValue(This->aPidls[i]))
330 break;
333 pidlFQ = ILCombine(This->pidl, This->aPidls[i]);
335 ZeroMemory(&sei, sizeof(sei));
336 sei.cbSize = sizeof(sei);
337 sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
338 sei.lpIDList = pidlFQ;
339 sei.lpClass = "folder";
340 sei.hwnd = lpcmi->hwnd;
341 sei.nShow = SW_SHOWNORMAL;
343 if(LOWORD(lpcmi->lpVerb) == IDM_EXPLORE)
344 { sei.lpVerb = "explore";
346 else
347 { sei.lpVerb = "open";
349 ShellExecuteExA(&sei);
350 SHFree(pidlFQ);
351 break;
353 case IDM_RENAME:
354 MessageBeep(MB_OK);
355 /*handle rename for the view here*/
356 break;
358 return NOERROR;
361 /**************************************************************************
362 * IContextMenu_fnGetCommandString()
364 static HRESULT WINAPI IContextMenu_fnGetCommandString(
365 IContextMenu *iface,
366 UINT idCommand,
367 UINT uFlags,
368 LPUINT lpReserved,
369 LPSTR lpszName,
370 UINT uMaxNameLen)
372 ICOM_THIS(IContextMenuImpl, iface);
374 HRESULT hr = E_INVALIDARG;
376 TRACE("(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
378 switch(uFlags)
379 { case GCS_HELPTEXT:
380 hr = E_NOTIMPL;
381 break;
383 case GCS_VERBA:
384 switch(idCommand)
385 { case IDM_RENAME:
386 strcpy((LPSTR)lpszName, "rename");
387 hr = NOERROR;
388 break;
390 break;
392 /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
393 case, you need to do the lstrcpyW to the pointer passed.*/
394 case GCS_VERBW:
395 switch(idCommand)
396 { case IDM_RENAME:
397 lstrcpyAtoW((LPWSTR)lpszName, "rename");
398 hr = NOERROR;
399 break;
401 break;
403 case GCS_VALIDATE:
404 hr = NOERROR;
405 break;
407 TRACE("-- (%p)->(name=%s)\n",This, lpszName);
408 return hr;
411 /**************************************************************************
412 * IContextMenu_fnHandleMenuMsg()
413 * NOTES
414 * should be only in IContextMenu2 and IContextMenu3
415 * is nevertheless called from word95
417 static HRESULT WINAPI IContextMenu_fnHandleMenuMsg(
418 IContextMenu *iface,
419 UINT uMsg,
420 WPARAM wParam,
421 LPARAM lParam)
423 ICOM_THIS(IContextMenuImpl, iface);
425 TRACE("(%p)->(msg=%x wp=%x lp=%lx)\n",This, uMsg, wParam, lParam);
427 return E_NOTIMPL;
430 /**************************************************************************
431 * IContextMenu VTable
434 static struct ICOM_VTABLE(IContextMenu) cmvt =
436 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
437 IContextMenu_fnQueryInterface,
438 IContextMenu_fnAddRef,
439 IContextMenu_fnRelease,
440 IContextMenu_fnQueryContextMenu,
441 IContextMenu_fnInvokeCommand,
442 IContextMenu_fnGetCommandString,
443 IContextMenu_fnHandleMenuMsg,
444 (void *) 0xdeadbabe /* just paranoia */