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
25 #define NONAMELESSUNION
28 #include "wine/debug.h"
33 #include "undocshell.h"
38 #include "shell32_main.h"
39 #include "shellfolder.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
47 IContextMenu3 IContextMenu3_iface
;
48 IShellExtInit IShellExtInit_iface
;
49 IObjectWithSite IObjectWithSite_iface
;
55 LPITEMIDLIST pidl
; /* root pidl */
56 LPITEMIDLIST
*apidl
; /* array of child pidls */
60 /* background menu data */
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
);
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
;
105 IContextMenu3_AddRef(iface
);
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
);
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
);
131 IShellFolder_Release(This
->parent
);
134 _ILFreeaPidl(This
->apidl
, This
->cidl
);
142 static HRESULT WINAPI
ItemMenu_QueryContextMenu(
143 IContextMenu3
*iface
,
150 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
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
);
170 mi
.cbSize
= sizeof(mi
);
171 mi
.fMask
= MIIM_ID
| MIIM_STRING
| MIIM_FTYPE
;
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
;
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
);
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
;
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 /**************************************************************************
219 static void DoOpenExplore(ContextMenu
*This
, HWND hwnd
, LPCSTR verb
)
222 BOOL bFolderFound
= FALSE
;
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
]))
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";
248 sei
.nShow
= SW_SHOWNORMAL
;
250 ShellExecuteExA(&sei
);
254 /**************************************************************************
257 * deletes the currently selected items
259 static void DoDelete(ContextMenu
*This
)
263 IShellFolder_QueryInterface(This
->parent
, &IID_ISFHelper
, (void**)&helper
);
266 ISFHelper_DeleteItems(helper
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
);
267 ISFHelper_Release(helper
);
271 /**************************************************************************
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
;
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
;
312 WCHAR wszFiletype
[MAX_PATH
];
313 WCHAR wszFilename
[MAX_PATH
];
314 PROPSHEETHEADERW psh
;
315 HPROPSHEETPAGE hpages
[MAX_PROP_PAGES
];
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
;
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]))
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
);
347 else if (_ILIsFolder(This
->apidl
[0]))
349 lstrcpynW(wszFiletype
, wszFolder
, 64);
351 else if (_ILIsSpecialFolder(This
->apidl
[0]))
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);
361 FIXME("Requested properties for unknown type.\n");
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
);
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
);
384 hpsxa
= SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT
, wszFiletype
, MAX_PROP_PAGES
- psh
.nPages
, lpDo
);
387 SHAddFromPropSheetExtArray(hpsxa
, Properties_AddPropSheetCallback
, (LPARAM
)&psh
);
388 SHDestroyPropSheetExtArray(hpsxa
);
390 hpsxa
= SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT
, wszFiletypeAll
, MAX_PROP_PAGES
- psh
.nPages
, lpDo
);
393 SHAddFromPropSheetExtArray(hpsxa
, Properties_AddPropSheetCallback
, (LPARAM
)&psh
);
394 SHDestroyPropSheetExtArray(hpsxa
);
396 IDataObject_Release(lpDo
);
400 PropertySheetW(&psh
);
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
));
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");
430 case FCIDM_SHVIEW_OPEN
:
431 TRACE("Verb FCIDM_SHVIEW_OPEN\n");
432 DoOpenExplore(This
, lpcmi
->hwnd
, "open");
434 case FCIDM_SHVIEW_RENAME
:
436 IShellBrowser
*browser
;
438 /* get the active IShellView */
439 browser
= (IShellBrowser
*)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
, 0, 0);
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
);
454 case FCIDM_SHVIEW_DELETE
:
455 TRACE("Verb FCIDM_SHVIEW_DELETE\n");
458 case FCIDM_SHVIEW_COPY
:
459 TRACE("Verb FCIDM_SHVIEW_COPY\n");
460 DoCopyOrCut(This
, lpcmi
->hwnd
, FALSE
);
462 case FCIDM_SHVIEW_CUT
:
463 TRACE("Verb FCIDM_SHVIEW_CUT\n");
464 DoCopyOrCut(This
, lpcmi
->hwnd
, TRUE
);
466 case FCIDM_SHVIEW_PROPERTIES
:
467 TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n");
468 DoOpenProperties(This
, lpcmi
->hwnd
);
471 FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi
->lpVerb
));
477 TRACE("Verb is %s\n",debugstr_a(lpcmi
->lpVerb
));
478 if (strcmp(lpcmi
->lpVerb
,"delete")==0)
480 else if (strcmp(lpcmi
->lpVerb
,"properties")==0)
481 DoOpenProperties(This
, lpcmi
->hwnd
);
483 FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi
->lpVerb
));
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
;
505 TRACE("(%p)->(%lx, %#x, %p, %p, %u)\n", This
, cmdid
, flags
, reserved
, name
, maxlen
);
518 case FCIDM_SHVIEW_OPEN
:
521 case FCIDM_SHVIEW_EXPLORE
:
524 case FCIDM_SHVIEW_CUT
:
527 case FCIDM_SHVIEW_COPY
:
530 case FCIDM_SHVIEW_CREATELINK
:
533 case FCIDM_SHVIEW_DELETE
:
536 case FCIDM_SHVIEW_PROPERTIES
:
539 case FCIDM_SHVIEW_RENAME
:
550 if (flags
== GCS_VERBA
)
551 WideCharToMultiByte(CP_ACP
, 0, cmdW
, -1, name
, maxlen
, NULL
, NULL
);
553 lstrcpynW((WCHAR
*)name
, cmdW
, maxlen
);
555 TRACE("name %s\n", flags
== GCS_VERBA
? debugstr_a(name
) : debugstr_w((WCHAR
*)name
));
566 /**************************************************************************
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
);
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
);
587 static const IContextMenu3Vtbl ItemContextMenuVtbl
=
589 ContextMenu_QueryInterface
,
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
);
627 static const IShellExtInitVtbl ShellExtInitVtbl
=
629 ShellExtInit_QueryInterface
,
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
);
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
);
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
)
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
;
694 This
->parent
= parent
;
695 if (parent
) IShellFolder_AddRef(parent
);
697 This
->pidl
= ILClone(pidl
);
698 This
->apidl
= _ILCopyaPidl(apidl
, 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
);
713 /* Background menu implementation */
714 static HRESULT WINAPI
BackgroundMenu_QueryContextMenu(
715 IContextMenu3
*iface
,
722 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
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);
741 hr
= MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
, 0);
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
);
755 static void DoNewFolder(ContextMenu
*This
, IShellView
*view
)
759 IShellFolder_QueryInterface(This
->parent
, &IID_ISFHelper
, (void**)&helper
);
762 WCHAR nameW
[MAX_PATH
];
765 ISFHelper_GetUniqueName(helper
, nameW
, MAX_PATH
);
766 ISFHelper_AddFolder(helper
, 0, nameW
, &pidl
);
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
));
777 ISFHelper_Release(helper
);
781 static BOOL
DoPaste(ContextMenu
*This
)
783 BOOL bSuccess
= FALSE
;
788 if(SUCCEEDED(OleGetClipboard(&pda
)))
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
;
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
);
814 IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfFrom
);
815 IShellFolder_Release(psfDesktop
);
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
);
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
);
841 /* release the medium*/
842 ReleaseStgMedium(&medium
);
844 IDataObject_Release(pda
);
850 hMem
= GetClipboardData(CF_HDROP
);
854 char * pDropFiles
= GlobalLock(hMem
);
857 int len
, offset
= sizeof(DROPFILESTRUCT
);
859 while( pDropFiles
[offset
] != 0)
861 len
= strlen(pDropFiles
+ offset
);
862 TRACE("%s\n", pDropFiles
+ offset
);
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
;
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);
909 FIXME("please report: unknown verb %s\n", debugstr_a(lpcmi
->lpVerb
));
914 switch (LOWORD(lpcmi
->lpVerb
))
916 case FCIDM_SHVIEW_REFRESH
:
917 if (view
) IShellView_Refresh(view
);
920 case FCIDM_SHVIEW_NEWFOLDER
:
921 DoNewFolder(This
, view
);
924 case FCIDM_SHVIEW_INSERT
:
928 case FCIDM_SHVIEW_PROPERTIES
:
930 ShellExecuteA(lpcmi
->hwnd
, "open", "rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL
, NULL
, SW_SHOWNORMAL
);
932 FIXME("launch item properties dialog\n");
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);
944 IShellView_Release(view
);
949 static HRESULT WINAPI
BackgroundMenu_GetCommandString(
950 IContextMenu3
*iface
,
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
))
976 FIXME("unknown command string\n");
980 static const IContextMenu3Vtbl BackgroundContextMenuVtbl
=
982 ContextMenu_QueryInterface
,
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
)
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
;
1004 This
->parent
= parent
;
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
);