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
26 #define NONAMELESSSTRUCT
29 #include "wine/debug.h"
34 #include "undocshell.h"
39 #include "shell32_main.h"
40 #include "shellfolder.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
48 IContextMenu2 IContextMenu2_iface
;
57 LPITEMIDLIST pidl
; /* root pidl */
58 LPITEMIDLIST
*apidl
; /* array of child pidls */
63 static inline ItemMenu
*impl_from_IContextMenu2_Item(IContextMenu2
*iface
)
65 return CONTAINING_RECORD(iface
, ItemMenu
, menu
.IContextMenu2_iface
);
74 static inline BackgroundMenu
*impl_from_IContextMenu2_Back(IContextMenu2
*iface
)
76 return CONTAINING_RECORD(iface
, BackgroundMenu
, menu
.IContextMenu2_iface
);
79 static BOOL
ItemMenu_CanRenameItems(ItemMenu
*This
)
83 TRACE("(%p)\n", This
);
85 /* can't rename more than one item at a time*/
86 if (!This
->apidl
|| This
->cidl
> 1) return FALSE
;
88 attr
= SFGAO_CANRENAME
;
89 IShellFolder_GetAttributesOf(This
->menu
.parent
, 1, (LPCITEMIDLIST
*)This
->apidl
, &attr
);
90 return attr
& SFGAO_CANRENAME
;
93 static HRESULT WINAPI
ItemMenu_QueryInterface(IContextMenu2
*iface
, REFIID riid
, LPVOID
*ppvObj
)
95 ItemMenu
*This
= impl_from_IContextMenu2_Item(iface
);
97 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
101 if(IsEqualIID(riid
, &IID_IUnknown
) ||
102 IsEqualIID(riid
, &IID_IContextMenu
) ||
103 IsEqualIID(riid
, &IID_IContextMenu2
))
107 else if(IsEqualIID(riid
, &IID_IShellExtInit
)) /*IShellExtInit*/
109 FIXME("-- LPSHELLEXTINIT pointer requested\n");
114 IUnknown_AddRef((IUnknown
*)*ppvObj
);
115 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
118 TRACE("-- Interface: E_NOINTERFACE\n");
119 return E_NOINTERFACE
;
122 static ULONG WINAPI
ItemMenu_AddRef(IContextMenu2
*iface
)
124 ItemMenu
*This
= impl_from_IContextMenu2_Item(iface
);
125 ULONG refCount
= InterlockedIncrement(&This
->menu
.ref
);
127 TRACE("(%p)->(count=%u)\n", This
, refCount
- 1);
132 static ULONG WINAPI
ItemMenu_Release(IContextMenu2
*iface
)
134 ItemMenu
*This
= impl_from_IContextMenu2_Item(iface
);
135 ULONG refCount
= InterlockedDecrement(&This
->menu
.ref
);
137 TRACE("(%p)->(count=%i)\n", This
, refCount
+ 1);
141 TRACE(" destroying IContextMenu(%p)\n",This
);
143 if(This
->menu
.parent
)
144 IShellFolder_Release(This
->menu
.parent
);
148 /*make sure the pidl is freed*/
149 _ILFreeaPidl(This
->apidl
, This
->cidl
);
151 HeapFree(GetProcessHeap(),0,This
);
156 static HRESULT WINAPI
ItemMenu_QueryContextMenu(
157 IContextMenu2
*iface
,
164 ItemMenu
*This
= impl_from_IContextMenu2_Item(iface
);
167 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This
, hmenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
169 This
->menu
.verb_offset
=idCmdFirst
;
171 if(!(CMF_DEFAULTONLY
& uFlags
) && This
->cidl
>0)
173 HMENU hmenures
= LoadMenuW(shell32_hInstance
, MAKEINTRESOURCEW(MENU_SHV_FILE
));
175 if(uFlags
& CMF_EXPLORE
)
176 RemoveMenu(hmenures
, FCIDM_SHVIEW_OPEN
, MF_BYCOMMAND
);
178 uIDMax
= Shell_MergeMenus(hmenu
, GetSubMenu(hmenures
, 0), indexMenu
, idCmdFirst
, idCmdLast
, MM_SUBMENUSHAVEIDS
);
180 DestroyMenu(hmenures
);
186 mi
.cbSize
= sizeof(mi
);
187 mi
.fMask
= MIIM_ID
| MIIM_STRING
| MIIM_FTYPE
;
190 GetMenuItemInfoW(hmenu
, FCIDM_SHVIEW_EXPLORE
, MF_BYCOMMAND
, &mi
);
191 RemoveMenu(hmenu
, FCIDM_SHVIEW_EXPLORE
, MF_BYCOMMAND
);
193 mi
.cbSize
= sizeof(mi
);
194 mi
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
196 mi
.fState
= MFS_ENABLED
;
197 mi
.wID
= FCIDM_SHVIEW_EXPLORE
;
198 mi
.fType
= MFT_STRING
;
199 InsertMenuItemW(hmenu
, (uFlags
& CMF_EXPLORE
) ? 1 : 2, MF_BYPOSITION
, &mi
);
202 SetMenuDefaultItem(hmenu
, 0, MF_BYPOSITION
);
204 if(uFlags
& ~CMF_CANRENAME
)
205 RemoveMenu(hmenu
, FCIDM_SHVIEW_RENAME
, MF_BYCOMMAND
);
207 EnableMenuItem(hmenu
, FCIDM_SHVIEW_RENAME
, MF_BYCOMMAND
| ItemMenu_CanRenameItems(This
) ? MFS_ENABLED
: MFS_DISABLED
);
209 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, uIDMax
-idCmdFirst
);
211 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 0);
214 /**************************************************************************
220 static void DoOpenExplore(ItemMenu
*This
, HWND hwnd
, LPCSTR verb
)
222 UINT i
, 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(ItemMenu
*This
)
263 IShellFolder_QueryInterface(This
->menu
.parent
, &IID_ISFHelper
, (LPVOID
*)&psfhlp
);
266 ISFHelper_DeleteItems(psfhlp
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
);
267 ISFHelper_Release(psfhlp
);
271 /**************************************************************************
274 * copies the currently selected items into the clipboard
276 static BOOL
DoCopyOrCut(ItemMenu
*This
, HWND hwnd
, BOOL bCut
)
282 TRACE("(%p)->(wnd=%p,bCut=0x%08x)\n",This
, hwnd
, bCut
);
284 /* get the active IShellView */
285 if ((lpSB
= (LPSHELLBROWSER
)SendMessageA(hwnd
, CWM_GETISHELLBROWSER
,0,0)))
287 if (SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
)))
289 if (SUCCEEDED(IShellView_GetItemObject(lpSV
, SVGIO_SELECTION
, &IID_IDataObject
, (LPVOID
*)&lpDo
)))
291 OleSetClipboard(lpDo
);
292 IDataObject_Release(lpDo
);
294 IShellView_Release(lpSV
);
300 /**************************************************************************
301 * Properties_AddPropSheetCallback
303 * Used by DoOpenProperties through SHCreatePropSheetExtArrayEx to add
304 * propertysheet pages from shell extensions.
306 static BOOL CALLBACK
Properties_AddPropSheetCallback(HPROPSHEETPAGE hpage
, LPARAM lparam
)
308 LPPROPSHEETHEADERW psh
= (LPPROPSHEETHEADERW
) lparam
;
309 psh
->u3
.phpage
[psh
->nPages
++] = hpage
;
314 /**************************************************************************
317 static void DoOpenProperties(ItemMenu
*This
, HWND hwnd
)
319 static const UINT MAX_PROP_PAGES
= 99;
320 static const WCHAR wszFolder
[] = {'F','o','l','d','e','r', 0};
321 static const WCHAR wszFiletypeAll
[] = {'*',0};
322 LPSHELLFOLDER lpDesktopSF
;
325 WCHAR wszFiletype
[MAX_PATH
];
326 WCHAR wszFilename
[MAX_PATH
];
327 PROPSHEETHEADERW psh
;
328 HPROPSHEETPAGE hpages
[MAX_PROP_PAGES
];
332 TRACE("(%p)->(wnd=%p)\n", This
, hwnd
);
334 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
335 psh
.dwSize
= sizeof (PROPSHEETHEADERW
);
336 psh
.hwndParent
= hwnd
;
337 psh
.dwFlags
= PSH_PROPTITLE
;
339 psh
.u3
.phpage
= hpages
;
340 psh
.u2
.nStartPage
= 0;
342 _ILSimpleGetTextW(This
->apidl
[0], (LPVOID
)wszFilename
, MAX_PATH
);
343 psh
.pszCaption
= (LPCWSTR
)wszFilename
;
345 /* Find out where to look for the shell extensions */
346 if (_ILIsValue(This
->apidl
[0]))
350 if (_ILGetExtension(This
->apidl
[0], sTemp
, 64))
352 HCR_MapTypeToValueA(sTemp
, sTemp
, 64, TRUE
);
353 MultiByteToWideChar(CP_ACP
, 0, sTemp
, -1, wszFiletype
, MAX_PATH
);
360 else if (_ILIsFolder(This
->apidl
[0]))
362 lstrcpynW(wszFiletype
, wszFolder
, 64);
364 else if (_ILIsSpecialFolder(This
->apidl
[0]))
367 static const WCHAR wszclsid
[] = {'C','L','S','I','D','\\', 0};
368 folderGUID
= _ILGetGUIDPointer(This
->apidl
[0]);
369 lstrcpyW(wszFiletype
, wszclsid
);
370 StringFromGUID2(folderGUID
, &wszFiletype
[6], MAX_PATH
- 6);
374 FIXME("Requested properties for unknown type.\n");
378 /* Get a suitable DataObject for accessing the files */
379 SHGetDesktopFolder(&lpDesktopSF
);
380 if (_ILIsPidlSimple(This
->pidl
))
382 ret
= IShellFolder_GetUIObjectOf(lpDesktopSF
, hwnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
,
383 &IID_IDataObject
, NULL
, (LPVOID
*)&lpDo
);
384 IShellFolder_Release(lpDesktopSF
);
388 IShellFolder_BindToObject(lpDesktopSF
, This
->pidl
, NULL
, &IID_IShellFolder
, (LPVOID
*) &lpSF
);
389 ret
= IShellFolder_GetUIObjectOf(lpSF
, hwnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
,
390 &IID_IDataObject
, NULL
, (LPVOID
*)&lpDo
);
391 IShellFolder_Release(lpSF
);
392 IShellFolder_Release(lpDesktopSF
);
397 hpsxa
= SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT
, wszFiletype
, MAX_PROP_PAGES
- psh
.nPages
, lpDo
);
400 SHAddFromPropSheetExtArray(hpsxa
, Properties_AddPropSheetCallback
, (LPARAM
)&psh
);
401 SHDestroyPropSheetExtArray(hpsxa
);
403 hpsxa
= SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT
, wszFiletypeAll
, MAX_PROP_PAGES
- psh
.nPages
, lpDo
);
406 SHAddFromPropSheetExtArray(hpsxa
, Properties_AddPropSheetCallback
, (LPARAM
)&psh
);
407 SHDestroyPropSheetExtArray(hpsxa
);
409 IDataObject_Release(lpDo
);
413 PropertySheetW(&psh
);
415 FIXME("No property pages found.\n");
418 static HRESULT WINAPI
ItemMenu_InvokeCommand(
419 IContextMenu2
*iface
,
420 LPCMINVOKECOMMANDINFO lpcmi
)
422 ItemMenu
*This
= impl_from_IContextMenu2_Item(iface
);
424 if (lpcmi
->cbSize
!= sizeof(CMINVOKECOMMANDINFO
))
425 FIXME("Is an EX structure\n");
427 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This
,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
429 if( HIWORD(lpcmi
->lpVerb
)==0 && LOWORD(lpcmi
->lpVerb
) > FCIDM_SHVIEWLAST
)
431 TRACE("Invalid Verb %x\n",LOWORD(lpcmi
->lpVerb
));
435 if (HIWORD(lpcmi
->lpVerb
) == 0)
437 switch(LOWORD(lpcmi
->lpVerb
-This
->menu
.verb_offset
))
439 case FCIDM_SHVIEW_EXPLORE
:
440 TRACE("Verb FCIDM_SHVIEW_EXPLORE\n");
441 DoOpenExplore(This
, lpcmi
->hwnd
, "explore");
443 case FCIDM_SHVIEW_OPEN
:
444 TRACE("Verb FCIDM_SHVIEW_OPEN\n");
445 DoOpenExplore(This
, lpcmi
->hwnd
, "open");
447 case FCIDM_SHVIEW_RENAME
:
449 IShellBrowser
*browser
;
451 /* get the active IShellView */
452 browser
= (IShellBrowser
*)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
, 0, 0);
457 if(SUCCEEDED(IShellBrowser_QueryActiveShellView(browser
, &view
)))
459 TRACE("(shellview=%p)\n", view
);
460 IShellView_SelectItem(view
, This
->apidl
[0],
461 SVSI_DESELECTOTHERS
|SVSI_EDIT
|SVSI_ENSUREVISIBLE
|SVSI_FOCUSED
|SVSI_SELECT
);
462 IShellView_Release(view
);
467 case FCIDM_SHVIEW_DELETE
:
468 TRACE("Verb FCIDM_SHVIEW_DELETE\n");
471 case FCIDM_SHVIEW_COPY
:
472 TRACE("Verb FCIDM_SHVIEW_COPY\n");
473 DoCopyOrCut(This
, lpcmi
->hwnd
, FALSE
);
475 case FCIDM_SHVIEW_CUT
:
476 TRACE("Verb FCIDM_SHVIEW_CUT\n");
477 DoCopyOrCut(This
, lpcmi
->hwnd
, TRUE
);
479 case FCIDM_SHVIEW_PROPERTIES
:
480 TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n");
481 DoOpenProperties(This
, lpcmi
->hwnd
);
484 FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi
->lpVerb
)-This
->menu
.verb_offset
);
490 TRACE("Verb is %s\n",debugstr_a(lpcmi
->lpVerb
));
491 if (strcmp(lpcmi
->lpVerb
,"delete")==0)
493 else if (strcmp(lpcmi
->lpVerb
,"properties")==0)
494 DoOpenProperties(This
, lpcmi
->hwnd
);
496 FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi
->lpVerb
));
503 static HRESULT WINAPI
ItemMenu_GetCommandString(
504 IContextMenu2
*iface
,
511 ItemMenu
*This
= impl_from_IContextMenu2_Item(iface
);
513 HRESULT hr
= E_INVALIDARG
;
515 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This
, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
525 switch(idCommand
-This
->menu
.verb_offset
)
527 case FCIDM_SHVIEW_RENAME
:
528 strcpy(lpszName
, "rename");
534 /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
535 case, you need to do the lstrcpyW to the pointer passed.*/
537 switch(idCommand
-This
->menu
.verb_offset
)
539 case FCIDM_SHVIEW_RENAME
:
540 MultiByteToWideChar( CP_ACP
, 0, "rename", -1, (LPWSTR
)lpszName
, uMaxNameLen
);
551 TRACE("-- (%p)->(name=%s)\n",This
, lpszName
);
555 /**************************************************************************
557 * should be only in IContextMenu2 and IContextMenu3
558 * is nevertheless called from word95
560 static HRESULT WINAPI
ItemMenu_HandleMenuMsg(
561 IContextMenu2
*iface
,
566 ItemMenu
*This
= impl_from_IContextMenu2_Item(iface
);
568 TRACE("(%p)->(msg=%x wp=%lx lp=%lx)\n",This
, uMsg
, wParam
, lParam
);
573 static const IContextMenu2Vtbl ItemContextMenuVtbl
=
575 ItemMenu_QueryInterface
,
578 ItemMenu_QueryContextMenu
,
579 ItemMenu_InvokeCommand
,
580 ItemMenu_GetCommandString
,
581 ItemMenu_HandleMenuMsg
584 IContextMenu2
*ItemMenu_Constructor(IShellFolder
*parent
, LPCITEMIDLIST pidl
, const LPCITEMIDLIST
*apidl
, UINT cidl
)
588 cm
= HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMenu
));
589 cm
->menu
.IContextMenu2_iface
.lpVtbl
= &ItemContextMenuVtbl
;
591 cm
->menu
.verb_offset
= 0;
592 cm
->menu
.parent
= parent
;
594 cm
->pidl
= ILClone(pidl
);
596 if (parent
) IShellFolder_AddRef(parent
);
598 cm
->apidl
= _ILCopyaPidl(apidl
, cidl
);
602 for(u
= 0; u
< cidl
; u
++)
603 cm
->bAllValues
&= (_ILIsValue(apidl
[u
]) ? 1 : 0);
607 return &cm
->menu
.IContextMenu2_iface
;
610 /* Background menu implementation */
611 static HRESULT WINAPI
BackgroundMenu_QueryInterface(IContextMenu2
*iface
, REFIID riid
, void **ppvObj
)
613 BackgroundMenu
*This
= impl_from_IContextMenu2_Back(iface
);
615 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObj
);
619 if(IsEqualIID(riid
, &IID_IUnknown
) ||
620 IsEqualIID(riid
, &IID_IContextMenu
) ||
621 IsEqualIID(riid
, &IID_IContextMenu2
))
625 else if(IsEqualIID(riid
, &IID_IShellExtInit
)) /*IShellExtInit*/
627 FIXME("-- LPSHELLEXTINIT pointer requested\n");
632 IUnknown_AddRef((IUnknown
*)*ppvObj
);
633 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
637 TRACE("-- Interface: E_NOINTERFACE\n");
638 return E_NOINTERFACE
;
641 static ULONG WINAPI
BackgroundMenu_AddRef(IContextMenu2
*iface
)
643 BackgroundMenu
*This
= impl_from_IContextMenu2_Back(iface
);
644 ULONG ref
= InterlockedIncrement(&This
->menu
.ref
);
645 TRACE("(%p)->(%u)\n", This
, ref
);
649 static ULONG WINAPI
BackgroundMenu_Release(IContextMenu2
*iface
)
651 BackgroundMenu
*This
= impl_from_IContextMenu2_Back(iface
);
652 ULONG ref
= InterlockedDecrement(&This
->menu
.ref
);
654 TRACE("(%p)->(%u)\n", This
, ref
);
658 if (This
->menu
.parent
)
659 IShellFolder_Release(This
->menu
.parent
);
661 HeapFree(GetProcessHeap(), 0, This
);
667 static HRESULT WINAPI
BackgroundMenu_QueryContextMenu(
668 IContextMenu2
*iface
,
675 BackgroundMenu
*This
= impl_from_IContextMenu2_Back(iface
);
680 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
681 This
, hMenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
683 This
->menu
.verb_offset
= idCmdFirst
;
685 hMyMenu
= LoadMenuA(shell32_hInstance
, "MENU_002");
686 if (uFlags
& CMF_DEFAULTONLY
)
688 HMENU ourMenu
= GetSubMenu(hMyMenu
,0);
689 UINT oldDef
= GetMenuDefaultItem(hMenu
,TRUE
,GMDI_USEDISABLED
);
690 UINT newDef
= GetMenuDefaultItem(ourMenu
,TRUE
,GMDI_USEDISABLED
);
691 if (newDef
!= oldDef
)
692 SetMenuDefaultItem(hMenu
,newDef
,TRUE
);
693 if (newDef
!=0xFFFFFFFF)
694 hr
= MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
, newDef
+1);
696 hr
= MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
, 0);
700 idMax
= Shell_MergeMenus (hMenu
, GetSubMenu(hMyMenu
,0), indexMenu
,
701 idCmdFirst
, idCmdLast
, MM_SUBMENUSHAVEIDS
);
702 hr
= MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
, idMax
-idCmdFirst
);
704 DestroyMenu(hMyMenu
);
706 TRACE("(%p)->returning 0x%x\n",This
,hr
);
710 static void DoNewFolder(BackgroundMenu
*This
, IShellView
*psv
)
713 WCHAR wszName
[MAX_PATH
];
715 IShellFolder_QueryInterface(This
->menu
.parent
, &IID_ISFHelper
, (LPVOID
*)&psfhlp
);
719 ISFHelper_GetUniqueName(psfhlp
, wszName
, MAX_PATH
);
720 ISFHelper_AddFolder(psfhlp
, 0, wszName
, &pidl
);
724 /* if we are in a shellview do labeledit */
725 IShellView_SelectItem(psv
,
726 pidl
,(SVSI_DESELECTOTHERS
| SVSI_EDIT
| SVSI_ENSUREVISIBLE
727 |SVSI_FOCUSED
|SVSI_SELECT
));
731 ISFHelper_Release(psfhlp
);
735 static BOOL
DoPaste(BackgroundMenu
*This
)
737 BOOL bSuccess
= FALSE
;
742 if(SUCCEEDED(OleGetClipboard(&pda
)))
747 TRACE("pda=%p\n", pda
);
749 /* Set the FORMATETC structure*/
750 InitFormatEtc(formatetc
, RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
), TYMED_HGLOBAL
);
752 /* Get the pidls from IDataObject */
753 if(SUCCEEDED(IDataObject_GetData(pda
,&formatetc
,&medium
)))
755 LPITEMIDLIST
* apidl
;
757 IShellFolder
*psfFrom
= NULL
, *psfDesktop
;
759 LPIDA lpcida
= GlobalLock(medium
.u
.hGlobal
);
760 TRACE("cida=%p\n", lpcida
);
762 apidl
= _ILCopyCidaToaPidl(&pidl
, lpcida
);
764 /* bind to the source shellfolder */
765 SHGetDesktopFolder(&psfDesktop
);
768 IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfFrom
);
769 IShellFolder_Release(psfDesktop
);
774 /* get source and destination shellfolder */
775 ISFHelper
*psfhlpdst
, *psfhlpsrc
;
776 IShellFolder_QueryInterface(This
->menu
.parent
, &IID_ISFHelper
, (LPVOID
*)&psfhlpdst
);
777 IShellFolder_QueryInterface(psfFrom
, &IID_ISFHelper
, (LPVOID
*)&psfhlpsrc
);
779 /* do the copy/move */
780 if (psfhlpdst
&& psfhlpsrc
)
782 ISFHelper_CopyItems(psfhlpdst
, psfFrom
, lpcida
->cidl
, (LPCITEMIDLIST
*)apidl
);
784 ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl);
787 if(psfhlpdst
) ISFHelper_Release(psfhlpdst
);
788 if(psfhlpsrc
) ISFHelper_Release(psfhlpsrc
);
789 IShellFolder_Release(psfFrom
);
792 _ILFreeaPidl(apidl
, lpcida
->cidl
);
795 /* release the medium*/
796 ReleaseStgMedium(&medium
);
798 IDataObject_Release(pda
);
804 hMem
= GetClipboardData(CF_HDROP
);
808 char * pDropFiles
= GlobalLock(hMem
);
811 int len
, offset
= sizeof(DROPFILESTRUCT
);
813 while( pDropFiles
[offset
] != 0)
815 len
= strlen(pDropFiles
+ offset
);
816 TRACE("%s\n", pDropFiles
+ offset
);
827 static HRESULT WINAPI
BackgroundMenu_InvokeCommand(
828 IContextMenu2
*iface
,
829 LPCMINVOKECOMMANDINFO lpcmi
)
831 BackgroundMenu
*This
= impl_from_IContextMenu2_Back(iface
);
833 LPSHELLVIEW lpSV
= NULL
;
836 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This
,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
838 /* get the active IShellView */
839 if((lpSB
= (LPSHELLBROWSER
)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
,0,0)))
841 if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
)))
843 IShellView_GetWindow(lpSV
, &hWndSV
);
847 if(HIWORD(lpcmi
->lpVerb
))
849 TRACE("%s\n",lpcmi
->lpVerb
);
851 if (! strcmp(lpcmi
->lpVerb
,CMDSTR_NEWFOLDERA
))
853 DoNewFolder(This
, lpSV
);
855 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWLISTA
))
857 if(hWndSV
) SendMessageA(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW
,0),0 );
859 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWDETAILSA
))
861 if(hWndSV
) SendMessageA(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW
,0),0 );
865 FIXME("please report: unknown verb %s\n",lpcmi
->lpVerb
);
870 switch(LOWORD(lpcmi
->lpVerb
)-This
->menu
.verb_offset
)
872 case FCIDM_SHVIEW_REFRESH
:
873 if (lpSV
) IShellView_Refresh(lpSV
);
876 case FCIDM_SHVIEW_NEWFOLDER
:
877 DoNewFolder(This
, lpSV
);
880 case FCIDM_SHVIEW_INSERT
:
884 case FCIDM_SHVIEW_PROPERTIES
:
886 ShellExecuteA(lpcmi
->hwnd
, "open", "rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL
, NULL
, SW_SHOWNORMAL
);
888 FIXME("launch item properties dialog\n");
893 /* if it's an id just pass it to the parent shv */
894 if (hWndSV
) SendMessageA(hWndSV
, WM_COMMAND
, MAKEWPARAM(LOWORD(lpcmi
->lpVerb
), 0),0 );
900 IShellView_Release(lpSV
); /* QueryActiveShellView does AddRef */
905 static HRESULT WINAPI
BackgroundMenu_GetCommandString(
906 IContextMenu2
*iface
,
913 BackgroundMenu
*This
= impl_from_IContextMenu2_Back(iface
);
915 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This
, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
917 /* test the existence of the menu items, the file dialog enables
918 the buttons according to this */
919 if (uFlags
== GCS_VALIDATEA
)
921 if(HIWORD(idCommand
))
923 if (!strcmp((LPSTR
)idCommand
, CMDSTR_VIEWLISTA
) ||
924 !strcmp((LPSTR
)idCommand
, CMDSTR_VIEWDETAILSA
) ||
925 !strcmp((LPSTR
)idCommand
, CMDSTR_NEWFOLDERA
))
932 FIXME("unknown command string\n");
936 static HRESULT WINAPI
BackgroundMenu_HandleMenuMsg(
937 IContextMenu2
*iface
,
942 BackgroundMenu
*This
= impl_from_IContextMenu2_Back(iface
);
943 FIXME("(%p)->(msg=%x wp=%lx lp=%lx)\n",This
, uMsg
, wParam
, lParam
);
947 static const IContextMenu2Vtbl BackgroundContextMenuVtbl
=
949 BackgroundMenu_QueryInterface
,
950 BackgroundMenu_AddRef
,
951 BackgroundMenu_Release
,
952 BackgroundMenu_QueryContextMenu
,
953 BackgroundMenu_InvokeCommand
,
954 BackgroundMenu_GetCommandString
,
955 BackgroundMenu_HandleMenuMsg
958 IContextMenu2
*BackgroundMenu_Constructor(IShellFolder
*parent
, BOOL desktop
)
962 cm
= HeapAlloc(GetProcessHeap(), 0, sizeof(*cm
));
963 cm
->menu
.IContextMenu2_iface
.lpVtbl
= &BackgroundContextMenuVtbl
;
965 cm
->menu
.parent
= parent
;
966 cm
->menu
.verb_offset
= 0;
968 cm
->desktop
= desktop
;
969 if (parent
) IShellFolder_AddRef(parent
);
971 TRACE("(%p)->()\n", cm
);
972 return &cm
->menu
.IContextMenu2_iface
;