wbemprox: Add ConfigManagerErrorCode for Win32_VideoController.
[wine.git] / dlls / shell32 / shlview_cmenu.c
blob9baaa27eaae1a460bdd137615b529f4d493168b6
1 /*
2 * IContextMenu for items in the shellview
4 * Copyright 1998-2000 Juergen Schmied <juergen.schmied@debitel.net>,
5 * <juergen.schmied@metronet.de>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <string.h>
24 #define COBJMACROS
25 #define NONAMELESSUNION
27 #include "winerror.h"
28 #include "wine/debug.h"
30 #include "windef.h"
31 #include "wingdi.h"
32 #include "pidl.h"
33 #include "undocshell.h"
34 #include "shlobj.h"
35 #include "winreg.h"
36 #include "prsht.h"
38 #include "shell32_main.h"
39 #include "shellfolder.h"
41 #include "shresdef.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(shell);
45 typedef struct
47 IContextMenu3 IContextMenu3_iface;
48 IShellExtInit IShellExtInit_iface;
49 IObjectWithSite IObjectWithSite_iface;
50 LONG ref;
52 IShellFolder* parent;
54 /* item menu data */
55 LPITEMIDLIST pidl; /* root pidl */
56 LPITEMIDLIST *apidl; /* array of child pidls */
57 UINT cidl;
58 BOOL allvalues;
60 /* background menu data */
61 BOOL desktop;
62 } ContextMenu;
64 static inline ContextMenu *impl_from_IContextMenu3(IContextMenu3 *iface)
66 return CONTAINING_RECORD(iface, ContextMenu, IContextMenu3_iface);
69 static inline ContextMenu *impl_from_IShellExtInit(IShellExtInit *iface)
71 return CONTAINING_RECORD(iface, ContextMenu, IShellExtInit_iface);
74 static inline ContextMenu *impl_from_IObjectWithSite(IObjectWithSite *iface)
76 return CONTAINING_RECORD(iface, ContextMenu, IObjectWithSite_iface);
79 static HRESULT WINAPI ContextMenu_QueryInterface(IContextMenu3 *iface, REFIID riid, LPVOID *ppvObj)
81 ContextMenu *This = impl_from_IContextMenu3(iface);
83 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObj);
85 *ppvObj = NULL;
87 if (IsEqualIID(riid, &IID_IUnknown) ||
88 IsEqualIID(riid, &IID_IContextMenu) ||
89 IsEqualIID(riid, &IID_IContextMenu2) ||
90 IsEqualIID(riid, &IID_IContextMenu3))
92 *ppvObj = &This->IContextMenu3_iface;
94 else if (IsEqualIID(riid, &IID_IShellExtInit))
96 *ppvObj = &This->IShellExtInit_iface;
98 else if (IsEqualIID(riid, &IID_IObjectWithSite))
100 *ppvObj = &This->IObjectWithSite_iface;
103 if(*ppvObj)
105 IContextMenu3_AddRef(iface);
106 return S_OK;
109 TRACE("-- Interface: E_NOINTERFACE\n");
110 return E_NOINTERFACE;
113 static ULONG WINAPI ContextMenu_AddRef(IContextMenu3 *iface)
115 ContextMenu *This = impl_from_IContextMenu3(iface);
116 ULONG ref = InterlockedIncrement(&This->ref);
117 TRACE("(%p)->(%u)\n", This, ref);
118 return ref;
121 static ULONG WINAPI ContextMenu_Release(IContextMenu3 *iface)
123 ContextMenu *This = impl_from_IContextMenu3(iface);
124 ULONG ref = InterlockedDecrement(&This->ref);
126 TRACE("(%p)->(%u)\n", This, ref);
128 if (!ref)
130 if(This->parent)
131 IShellFolder_Release(This->parent);
133 SHFree(This->pidl);
134 _ILFreeaPidl(This->apidl, This->cidl);
136 heap_free(This);
139 return ref;
142 static HRESULT WINAPI ItemMenu_QueryContextMenu(
143 IContextMenu3 *iface,
144 HMENU hmenu,
145 UINT indexMenu,
146 UINT idCmdFirst,
147 UINT idCmdLast,
148 UINT uFlags)
150 ContextMenu *This = impl_from_IContextMenu3(iface);
151 INT uIDMax;
153 TRACE("(%p)->(%p %d 0x%x 0x%x 0x%x )\n", This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
155 if(!(CMF_DEFAULTONLY & uFlags) && This->cidl > 0)
157 HMENU hmenures = LoadMenuW(shell32_hInstance, MAKEINTRESOURCEW(MENU_SHV_FILE));
159 if(uFlags & CMF_EXPLORE)
160 RemoveMenu(hmenures, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
162 uIDMax = Shell_MergeMenus(hmenu, GetSubMenu(hmenures, 0), indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS);
164 DestroyMenu(hmenures);
166 if(This->allvalues)
168 MENUITEMINFOW mi;
169 WCHAR str[255];
170 mi.cbSize = sizeof(mi);
171 mi.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE;
172 mi.dwTypeData = str;
173 mi.cch = 255;
174 GetMenuItemInfoW(hmenu, FCIDM_SHVIEW_EXPLORE, MF_BYCOMMAND, &mi);
175 RemoveMenu(hmenu, FCIDM_SHVIEW_EXPLORE + idCmdFirst, MF_BYCOMMAND);
177 mi.cbSize = sizeof(mi);
178 mi.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_STRING;
179 mi.dwTypeData = str;
180 mi.fState = MFS_ENABLED;
181 mi.wID = FCIDM_SHVIEW_EXPLORE;
182 mi.fType = MFT_STRING;
183 InsertMenuItemW(hmenu, (uFlags & CMF_EXPLORE) ? 1 : 2, MF_BYPOSITION, &mi);
186 SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION);
188 if(uFlags & ~CMF_CANRENAME)
189 RemoveMenu(hmenu, FCIDM_SHVIEW_RENAME, MF_BYCOMMAND);
190 else
192 UINT enable = MF_BYCOMMAND;
194 /* can't rename more than one item at a time*/
195 if (!This->apidl || This->cidl > 1)
196 enable |= MFS_DISABLED;
197 else
199 DWORD attr = SFGAO_CANRENAME;
201 IShellFolder_GetAttributesOf(This->parent, 1, (LPCITEMIDLIST*)This->apidl, &attr);
202 enable |= (attr & SFGAO_CANRENAME) ? MFS_ENABLED : MFS_DISABLED;
205 EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, enable);
208 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, uIDMax-idCmdFirst);
210 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
213 /**************************************************************************
214 * DoOpenExplore
216 * for folders only
219 static void DoOpenExplore(ContextMenu *This, HWND hwnd, LPCSTR verb)
221 UINT i;
222 BOOL bFolderFound = FALSE;
223 LPITEMIDLIST pidlFQ;
224 SHELLEXECUTEINFOA sei;
226 /* Find the first item in the list that is not a value. These commands
227 should never be invoked if there isn't at least one folder item in the list.*/
229 for(i = 0; i<This->cidl; i++)
231 if(!_ILIsValue(This->apidl[i]))
233 bFolderFound = TRUE;
234 break;
238 if (!bFolderFound) return;
240 pidlFQ = ILCombine(This->pidl, This->apidl[i]);
242 ZeroMemory(&sei, sizeof(sei));
243 sei.cbSize = sizeof(sei);
244 sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
245 sei.lpIDList = pidlFQ;
246 sei.lpClass = "Folder";
247 sei.hwnd = hwnd;
248 sei.nShow = SW_SHOWNORMAL;
249 sei.lpVerb = verb;
250 ShellExecuteExA(&sei);
251 SHFree(pidlFQ);
254 /**************************************************************************
255 * DoDelete
257 * deletes the currently selected items
259 static void DoDelete(ContextMenu *This)
261 ISFHelper *helper;
263 IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&helper);
264 if (helper)
266 ISFHelper_DeleteItems(helper, This->cidl, (LPCITEMIDLIST*)This->apidl);
267 ISFHelper_Release(helper);
271 /**************************************************************************
272 * DoCopyOrCut
274 * copies the currently selected items into the clipboard
276 static void DoCopyOrCut(ContextMenu *This, HWND hwnd, BOOL cut)
278 IDataObject *dataobject;
280 TRACE("(%p)->(wnd=%p, cut=%d)\n", This, hwnd, cut);
282 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->parent, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject, 0, (void**)&dataobject)))
284 OleSetClipboard(dataobject);
285 IDataObject_Release(dataobject);
289 /**************************************************************************
290 * Properties_AddPropSheetCallback
292 * Used by DoOpenProperties through SHCreatePropSheetExtArrayEx to add
293 * propertysheet pages from shell extensions.
295 static BOOL CALLBACK Properties_AddPropSheetCallback(HPROPSHEETPAGE hpage, LPARAM lparam)
297 LPPROPSHEETHEADERW psh = (LPPROPSHEETHEADERW) lparam;
298 psh->u3.phpage[psh->nPages++] = hpage;
300 return TRUE;
303 #define MAX_PROP_PAGES 99
305 static void DoOpenProperties(ContextMenu *This, HWND hwnd)
307 static const WCHAR wszFolder[] = {'F','o','l','d','e','r', 0};
308 static const WCHAR wszFiletypeAll[] = {'*',0};
309 LPSHELLFOLDER lpDesktopSF;
310 LPSHELLFOLDER lpSF;
311 LPDATAOBJECT lpDo;
312 WCHAR wszFiletype[MAX_PATH];
313 WCHAR wszFilename[MAX_PATH];
314 PROPSHEETHEADERW psh;
315 HPROPSHEETPAGE hpages[MAX_PROP_PAGES];
316 HPSXA hpsxa;
317 UINT ret;
319 TRACE("(%p)->(wnd=%p)\n", This, hwnd);
321 ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
322 psh.dwSize = sizeof (PROPSHEETHEADERW);
323 psh.hwndParent = hwnd;
324 psh.dwFlags = PSH_PROPTITLE;
325 psh.nPages = 0;
326 psh.u3.phpage = hpages;
327 psh.u2.nStartPage = 0;
329 _ILSimpleGetTextW(This->apidl[0], (LPVOID)wszFilename, MAX_PATH);
330 psh.pszCaption = (LPCWSTR)wszFilename;
332 /* Find out where to look for the shell extensions */
333 if (_ILIsValue(This->apidl[0]))
335 char sTemp[64];
336 sTemp[0] = 0;
337 if (_ILGetExtension(This->apidl[0], sTemp, 64))
339 HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE);
340 MultiByteToWideChar(CP_ACP, 0, sTemp, -1, wszFiletype, MAX_PATH);
342 else
344 wszFiletype[0] = 0;
347 else if (_ILIsFolder(This->apidl[0]))
349 lstrcpynW(wszFiletype, wszFolder, 64);
351 else if (_ILIsSpecialFolder(This->apidl[0]))
353 LPGUID folderGUID;
354 static const WCHAR wszclsid[] = {'C','L','S','I','D','\\', 0};
355 folderGUID = _ILGetGUIDPointer(This->apidl[0]);
356 lstrcpyW(wszFiletype, wszclsid);
357 StringFromGUID2(folderGUID, &wszFiletype[6], MAX_PATH - 6);
359 else
361 FIXME("Requested properties for unknown type.\n");
362 return;
365 /* Get a suitable DataObject for accessing the files */
366 SHGetDesktopFolder(&lpDesktopSF);
367 if (_ILIsPidlSimple(This->pidl))
369 ret = IShellFolder_GetUIObjectOf(lpDesktopSF, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
370 &IID_IDataObject, NULL, (LPVOID *)&lpDo);
371 IShellFolder_Release(lpDesktopSF);
373 else
375 IShellFolder_BindToObject(lpDesktopSF, This->pidl, NULL, &IID_IShellFolder, (LPVOID*) &lpSF);
376 ret = IShellFolder_GetUIObjectOf(lpSF, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
377 &IID_IDataObject, NULL, (LPVOID *)&lpDo);
378 IShellFolder_Release(lpSF);
379 IShellFolder_Release(lpDesktopSF);
382 if (SUCCEEDED(ret))
384 hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszFiletype, MAX_PROP_PAGES - psh.nPages, lpDo);
385 if (hpsxa != NULL)
387 SHAddFromPropSheetExtArray(hpsxa, Properties_AddPropSheetCallback, (LPARAM)&psh);
388 SHDestroyPropSheetExtArray(hpsxa);
390 hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszFiletypeAll, MAX_PROP_PAGES - psh.nPages, lpDo);
391 if (hpsxa != NULL)
393 SHAddFromPropSheetExtArray(hpsxa, Properties_AddPropSheetCallback, (LPARAM)&psh);
394 SHDestroyPropSheetExtArray(hpsxa);
396 IDataObject_Release(lpDo);
399 if (psh.nPages)
400 PropertySheetW(&psh);
401 else
402 FIXME("No property pages found.\n");
405 static HRESULT WINAPI ItemMenu_InvokeCommand(
406 IContextMenu3 *iface,
407 LPCMINVOKECOMMANDINFO lpcmi)
409 ContextMenu *This = impl_from_IContextMenu3(iface);
411 if (lpcmi->cbSize != sizeof(CMINVOKECOMMANDINFO))
412 FIXME("Is an EX structure\n");
414 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
416 if (IS_INTRESOURCE(lpcmi->lpVerb) && LOWORD(lpcmi->lpVerb) > FCIDM_SHVIEWLAST)
418 TRACE("Invalid Verb %x\n", LOWORD(lpcmi->lpVerb));
419 return E_INVALIDARG;
422 if (IS_INTRESOURCE(lpcmi->lpVerb))
424 switch(LOWORD(lpcmi->lpVerb))
426 case FCIDM_SHVIEW_EXPLORE:
427 TRACE("Verb FCIDM_SHVIEW_EXPLORE\n");
428 DoOpenExplore(This, lpcmi->hwnd, "explore");
429 break;
430 case FCIDM_SHVIEW_OPEN:
431 TRACE("Verb FCIDM_SHVIEW_OPEN\n");
432 DoOpenExplore(This, lpcmi->hwnd, "open");
433 break;
434 case FCIDM_SHVIEW_RENAME:
436 IShellBrowser *browser;
438 /* get the active IShellView */
439 browser = (IShellBrowser*)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
440 if (browser)
442 IShellView *view;
444 if(SUCCEEDED(IShellBrowser_QueryActiveShellView(browser, &view)))
446 TRACE("(shellview=%p)\n", view);
447 IShellView_SelectItem(view, This->apidl[0],
448 SVSI_DESELECTOTHERS|SVSI_EDIT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_SELECT);
449 IShellView_Release(view);
452 break;
454 case FCIDM_SHVIEW_DELETE:
455 TRACE("Verb FCIDM_SHVIEW_DELETE\n");
456 DoDelete(This);
457 break;
458 case FCIDM_SHVIEW_COPY:
459 TRACE("Verb FCIDM_SHVIEW_COPY\n");
460 DoCopyOrCut(This, lpcmi->hwnd, FALSE);
461 break;
462 case FCIDM_SHVIEW_CUT:
463 TRACE("Verb FCIDM_SHVIEW_CUT\n");
464 DoCopyOrCut(This, lpcmi->hwnd, TRUE);
465 break;
466 case FCIDM_SHVIEW_PROPERTIES:
467 TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n");
468 DoOpenProperties(This, lpcmi->hwnd);
469 break;
470 default:
471 FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb));
472 return E_INVALIDARG;
475 else
477 TRACE("Verb is %s\n",debugstr_a(lpcmi->lpVerb));
478 if (strcmp(lpcmi->lpVerb,"delete")==0)
479 DoDelete(This);
480 else if (strcmp(lpcmi->lpVerb,"properties")==0)
481 DoOpenProperties(This, lpcmi->hwnd);
482 else {
483 FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi->lpVerb));
484 return E_FAIL;
487 return S_OK;
490 static HRESULT WINAPI ItemMenu_GetCommandString(IContextMenu3 *iface, UINT_PTR cmdid, UINT flags,
491 UINT *reserved, LPSTR name, UINT maxlen)
493 static const WCHAR openW[] = {'o','p','e','n',0};
494 static const WCHAR exploreW[] = {'e','x','p','l','o','r','e',0};
495 static const WCHAR cutW[] = {'c','u','t',0};
496 static const WCHAR copyW[] = {'c','o','p','y',0};
497 static const WCHAR linkW[] = {'l','i','n','k',0};
498 static const WCHAR deleteW[] = {'d','e','l','e','t','e',0};
499 static const WCHAR propertiesW[] = {'p','r','o','p','e','r','t','i','e','s',0};
500 static const WCHAR renameW[] = {'r','e','n','a','m','e',0};
501 ContextMenu *This = impl_from_IContextMenu3(iface);
502 const WCHAR *cmdW = NULL;
503 HRESULT hr = S_OK;
505 TRACE("(%p)->(%lx, %#x, %p, %p, %u)\n", This, cmdid, flags, reserved, name, maxlen);
507 switch (flags)
509 case GCS_HELPTEXTA:
510 case GCS_HELPTEXTW:
511 hr = E_NOTIMPL;
512 break;
514 case GCS_VERBA:
515 case GCS_VERBW:
516 switch (cmdid)
518 case FCIDM_SHVIEW_OPEN:
519 cmdW = openW;
520 break;
521 case FCIDM_SHVIEW_EXPLORE:
522 cmdW = exploreW;
523 break;
524 case FCIDM_SHVIEW_CUT:
525 cmdW = cutW;
526 break;
527 case FCIDM_SHVIEW_COPY:
528 cmdW = copyW;
529 break;
530 case FCIDM_SHVIEW_CREATELINK:
531 cmdW = linkW;
532 break;
533 case FCIDM_SHVIEW_DELETE:
534 cmdW = deleteW;
535 break;
536 case FCIDM_SHVIEW_PROPERTIES:
537 cmdW = propertiesW;
538 break;
539 case FCIDM_SHVIEW_RENAME:
540 cmdW = renameW;
541 break;
544 if (!cmdW)
546 hr = E_INVALIDARG;
547 break;
550 if (flags == GCS_VERBA)
551 WideCharToMultiByte(CP_ACP, 0, cmdW, -1, name, maxlen, NULL, NULL);
552 else
553 lstrcpynW((WCHAR *)name, cmdW, maxlen);
555 TRACE("name %s\n", flags == GCS_VERBA ? debugstr_a(name) : debugstr_w((WCHAR *)name));
556 break;
558 case GCS_VALIDATEA:
559 case GCS_VALIDATEW:
560 break;
563 return hr;
566 /**************************************************************************
567 * NOTES
568 * should be only in IContextMenu2 and IContextMenu3
569 * is nevertheless called from word95
571 static HRESULT WINAPI ContextMenu_HandleMenuMsg(IContextMenu3 *iface, UINT msg,
572 WPARAM wParam, LPARAM lParam)
574 ContextMenu *This = impl_from_IContextMenu3(iface);
575 FIXME("(%p)->(0x%x 0x%lx 0x%lx): stub\n", This, msg, wParam, lParam);
576 return E_NOTIMPL;
579 static HRESULT WINAPI ContextMenu_HandleMenuMsg2(IContextMenu3 *iface, UINT msg,
580 WPARAM wParam, LPARAM lParam, LRESULT *result)
582 ContextMenu *This = impl_from_IContextMenu3(iface);
583 FIXME("(%p)->(0x%x 0x%lx 0x%lx %p): stub\n", This, msg, wParam, lParam, result);
584 return E_NOTIMPL;
587 static const IContextMenu3Vtbl ItemContextMenuVtbl =
589 ContextMenu_QueryInterface,
590 ContextMenu_AddRef,
591 ContextMenu_Release,
592 ItemMenu_QueryContextMenu,
593 ItemMenu_InvokeCommand,
594 ItemMenu_GetCommandString,
595 ContextMenu_HandleMenuMsg,
596 ContextMenu_HandleMenuMsg2
599 static HRESULT WINAPI ShellExtInit_QueryInterface(IShellExtInit *iface, REFIID riid, void **obj)
601 ContextMenu *This = impl_from_IShellExtInit(iface);
602 return IContextMenu3_QueryInterface(&This->IContextMenu3_iface, riid, obj);
605 static ULONG WINAPI ShellExtInit_AddRef(IShellExtInit *iface)
607 ContextMenu *This = impl_from_IShellExtInit(iface);
608 return IContextMenu3_AddRef(&This->IContextMenu3_iface);
611 static ULONG WINAPI ShellExtInit_Release(IShellExtInit *iface)
613 ContextMenu *This = impl_from_IShellExtInit(iface);
614 return IContextMenu3_Release(&This->IContextMenu3_iface);
617 static HRESULT WINAPI ShellExtInit_Initialize(IShellExtInit *iface, LPCITEMIDLIST folder,
618 IDataObject *dataobj, HKEY progidkey)
620 ContextMenu *This = impl_from_IShellExtInit(iface);
622 FIXME("(%p)->(%p %p %p): stub\n", This, folder, dataobj, progidkey);
624 return E_NOTIMPL;
627 static const IShellExtInitVtbl ShellExtInitVtbl =
629 ShellExtInit_QueryInterface,
630 ShellExtInit_AddRef,
631 ShellExtInit_Release,
632 ShellExtInit_Initialize
635 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite *iface, REFIID riid, void **obj)
637 ContextMenu *This = impl_from_IObjectWithSite(iface);
638 return IContextMenu3_QueryInterface(&This->IContextMenu3_iface, riid, obj);
641 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
643 ContextMenu *This = impl_from_IObjectWithSite(iface);
644 return IContextMenu3_AddRef(&This->IContextMenu3_iface);
647 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
649 ContextMenu *This = impl_from_IObjectWithSite(iface);
650 return IContextMenu3_Release(&This->IContextMenu3_iface);
653 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *site)
655 ContextMenu *This = impl_from_IObjectWithSite(iface);
657 FIXME("(%p)->(%p): stub\n", This, site);
659 return E_NOTIMPL;
662 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, void **site)
664 ContextMenu *This = impl_from_IObjectWithSite(iface);
666 FIXME("(%p)->(%s %p): stub\n", This, debugstr_guid(riid), site);
668 return E_NOTIMPL;
671 static const IObjectWithSiteVtbl ObjectWithSiteVtbl =
673 ObjectWithSite_QueryInterface,
674 ObjectWithSite_AddRef,
675 ObjectWithSite_Release,
676 ObjectWithSite_SetSite,
677 ObjectWithSite_GetSite,
680 HRESULT ItemMenu_Constructor(IShellFolder *parent, LPCITEMIDLIST pidl, const LPCITEMIDLIST *apidl, UINT cidl,
681 REFIID riid, void **pObj)
683 ContextMenu* This;
684 HRESULT hr;
685 UINT i;
687 This = heap_alloc(sizeof(*This));
688 if (!This) return E_OUTOFMEMORY;
690 This->IContextMenu3_iface.lpVtbl = &ItemContextMenuVtbl;
691 This->IShellExtInit_iface.lpVtbl = &ShellExtInitVtbl;
692 This->IObjectWithSite_iface.lpVtbl = &ObjectWithSiteVtbl;
693 This->ref = 1;
694 This->parent = parent;
695 if (parent) IShellFolder_AddRef(parent);
697 This->pidl = ILClone(pidl);
698 This->apidl = _ILCopyaPidl(apidl, cidl);
699 This->cidl = cidl;
700 This->allvalues = TRUE;
702 This->desktop = FALSE;
704 for (i = 0; i < cidl; i++)
705 This->allvalues &= (_ILIsValue(apidl[i]) ? 1 : 0);
707 hr = IContextMenu3_QueryInterface(&This->IContextMenu3_iface, riid, pObj);
708 IContextMenu3_Release(&This->IContextMenu3_iface);
710 return hr;
713 /* Background menu implementation */
714 static HRESULT WINAPI BackgroundMenu_QueryContextMenu(
715 IContextMenu3 *iface,
716 HMENU hMenu,
717 UINT indexMenu,
718 UINT idCmdFirst,
719 UINT idCmdLast,
720 UINT uFlags)
722 ContextMenu *This = impl_from_IContextMenu3(iface);
723 HMENU hMyMenu;
724 UINT idMax;
725 HRESULT hr;
727 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
728 This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
730 hMyMenu = LoadMenuA(shell32_hInstance, "MENU_002");
731 if (uFlags & CMF_DEFAULTONLY)
733 HMENU ourMenu = GetSubMenu(hMyMenu,0);
734 UINT oldDef = GetMenuDefaultItem(hMenu,TRUE,GMDI_USEDISABLED);
735 UINT newDef = GetMenuDefaultItem(ourMenu,TRUE,GMDI_USEDISABLED);
736 if (newDef != oldDef)
737 SetMenuDefaultItem(hMenu,newDef,TRUE);
738 if (newDef!=0xFFFFFFFF)
739 hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, newDef+1);
740 else
741 hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
743 else
745 idMax = Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu,
746 idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS);
747 hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst);
749 DestroyMenu(hMyMenu);
751 TRACE("(%p)->returning 0x%x\n",This,hr);
752 return hr;
755 static void DoNewFolder(ContextMenu *This, IShellView *view)
757 ISFHelper *helper;
759 IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&helper);
760 if (helper)
762 WCHAR nameW[MAX_PATH];
763 LPITEMIDLIST pidl;
765 ISFHelper_GetUniqueName(helper, nameW, MAX_PATH);
766 ISFHelper_AddFolder(helper, 0, nameW, &pidl);
768 if (view)
770 /* if we are in a shellview do labeledit */
771 IShellView_SelectItem(view,
772 pidl,(SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
773 |SVSI_FOCUSED|SVSI_SELECT));
776 SHFree(pidl);
777 ISFHelper_Release(helper);
781 static BOOL DoPaste(ContextMenu *This)
783 BOOL bSuccess = FALSE;
784 IDataObject * pda;
786 TRACE("\n");
788 if(SUCCEEDED(OleGetClipboard(&pda)))
790 STGMEDIUM medium;
791 FORMATETC formatetc;
793 TRACE("pda=%p\n", pda);
795 /* Set the FORMATETC structure*/
796 InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLISTW), TYMED_HGLOBAL);
798 /* Get the pidls from IDataObject */
799 if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium)))
801 LPITEMIDLIST * apidl;
802 LPITEMIDLIST pidl;
803 IShellFolder *psfFrom = NULL, *psfDesktop;
805 LPIDA lpcida = GlobalLock(medium.u.hGlobal);
806 TRACE("cida=%p\n", lpcida);
808 apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
810 /* bind to the source shellfolder */
811 SHGetDesktopFolder(&psfDesktop);
812 if(psfDesktop)
814 IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom);
815 IShellFolder_Release(psfDesktop);
818 if (psfFrom)
820 /* get source and destination shellfolder */
821 ISFHelper *psfhlpdst, *psfhlpsrc;
822 IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst);
823 IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc);
825 /* do the copy/move */
826 if (psfhlpdst && psfhlpsrc)
828 ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl);
829 /* FIXME handle move
830 ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl);
833 if(psfhlpdst) ISFHelper_Release(psfhlpdst);
834 if(psfhlpsrc) ISFHelper_Release(psfhlpsrc);
835 IShellFolder_Release(psfFrom);
838 _ILFreeaPidl(apidl, lpcida->cidl);
839 SHFree(pidl);
841 /* release the medium*/
842 ReleaseStgMedium(&medium);
844 IDataObject_Release(pda);
846 #if 0
847 HGLOBAL hMem;
849 OpenClipboard(NULL);
850 hMem = GetClipboardData(CF_HDROP);
852 if(hMem)
854 char * pDropFiles = GlobalLock(hMem);
855 if(pDropFiles)
857 int len, offset = sizeof(DROPFILESTRUCT);
859 while( pDropFiles[offset] != 0)
861 len = strlen(pDropFiles + offset);
862 TRACE("%s\n", pDropFiles + offset);
863 offset += len+1;
866 GlobalUnlock(hMem);
868 CloseClipboard();
869 #endif
870 return bSuccess;
873 static HRESULT WINAPI BackgroundMenu_InvokeCommand(
874 IContextMenu3 *iface,
875 LPCMINVOKECOMMANDINFO lpcmi)
877 ContextMenu *This = impl_from_IContextMenu3(iface);
878 IShellBrowser *browser;
879 IShellView *view = NULL;
880 HWND hWnd = NULL;
882 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", This, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
884 /* get the active IShellView */
885 if ((browser = (IShellBrowser*)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0)))
887 if (SUCCEEDED(IShellBrowser_QueryActiveShellView(browser, &view)))
888 IShellView_GetWindow(view, &hWnd);
891 if(HIWORD(lpcmi->lpVerb))
893 TRACE("%s\n", debugstr_a(lpcmi->lpVerb));
895 if (!strcmp(lpcmi->lpVerb, CMDSTR_NEWFOLDERA))
897 DoNewFolder(This, view);
899 else if (!strcmp(lpcmi->lpVerb, CMDSTR_VIEWLISTA))
901 if (hWnd) SendMessageA(hWnd, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW, 0), 0);
903 else if (!strcmp(lpcmi->lpVerb, CMDSTR_VIEWDETAILSA))
905 if (hWnd) SendMessageA(hWnd, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW, 0), 0);
907 else
909 FIXME("please report: unknown verb %s\n", debugstr_a(lpcmi->lpVerb));
912 else
914 switch (LOWORD(lpcmi->lpVerb))
916 case FCIDM_SHVIEW_REFRESH:
917 if (view) IShellView_Refresh(view);
918 break;
920 case FCIDM_SHVIEW_NEWFOLDER:
921 DoNewFolder(This, view);
922 break;
924 case FCIDM_SHVIEW_INSERT:
925 DoPaste(This);
926 break;
928 case FCIDM_SHVIEW_PROPERTIES:
929 if (This->desktop) {
930 ShellExecuteA(lpcmi->hwnd, "open", "rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL);
931 } else {
932 FIXME("launch item properties dialog\n");
934 break;
936 default:
937 /* if it's an id just pass it to the parent shv */
938 if (hWnd) SendMessageA(hWnd, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0);
939 break;
943 if (view)
944 IShellView_Release(view);
946 return S_OK;
949 static HRESULT WINAPI BackgroundMenu_GetCommandString(
950 IContextMenu3 *iface,
951 UINT_PTR idCommand,
952 UINT uFlags,
953 UINT* lpReserved,
954 LPSTR lpszName,
955 UINT uMaxNameLen)
957 ContextMenu *This = impl_from_IContextMenu3(iface);
959 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
961 /* test the existence of the menu items, the file dialog enables
962 the buttons according to this */
963 if (uFlags == GCS_VALIDATEA)
965 if(HIWORD(idCommand))
967 if (!strcmp((LPSTR)idCommand, CMDSTR_VIEWLISTA) ||
968 !strcmp((LPSTR)idCommand, CMDSTR_VIEWDETAILSA) ||
969 !strcmp((LPSTR)idCommand, CMDSTR_NEWFOLDERA))
971 return S_OK;
976 FIXME("unknown command string\n");
977 return E_FAIL;
980 static const IContextMenu3Vtbl BackgroundContextMenuVtbl =
982 ContextMenu_QueryInterface,
983 ContextMenu_AddRef,
984 ContextMenu_Release,
985 BackgroundMenu_QueryContextMenu,
986 BackgroundMenu_InvokeCommand,
987 BackgroundMenu_GetCommandString,
988 ContextMenu_HandleMenuMsg,
989 ContextMenu_HandleMenuMsg2
992 HRESULT BackgroundMenu_Constructor(IShellFolder *parent, BOOL desktop, REFIID riid, void **pObj)
994 ContextMenu *This;
995 HRESULT hr;
997 This = heap_alloc(sizeof(*This));
998 if (!This) return E_OUTOFMEMORY;
1000 This->IContextMenu3_iface.lpVtbl = &BackgroundContextMenuVtbl;
1001 This->IShellExtInit_iface.lpVtbl = &ShellExtInitVtbl;
1002 This->IObjectWithSite_iface.lpVtbl = &ObjectWithSiteVtbl;
1003 This->ref = 1;
1004 This->parent = parent;
1006 This->pidl = NULL;
1007 This->apidl = NULL;
1008 This->cidl = 0;
1009 This->allvalues = FALSE;
1011 This->desktop = desktop;
1012 if (parent) IShellFolder_AddRef(parent);
1014 hr = IContextMenu3_QueryInterface(&This->IContextMenu3_iface, riid, pObj);
1015 IContextMenu3_Release(&This->IContextMenu3_iface);
1017 return hr;