Avoid calling FindExecutable16.
[wine] / dlls / shell32 / shv_bg_cmenu.c
1 /*
2  *      IContextMenu
3  *      ShellView Background Context Menu (shv_bg_cm)
4  *
5  *      Copyright 1999  Juergen Schmied <juergen.schmied@metronet.de>
6  *
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.
11  *
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.
16  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #include <string.h>
22
23 #include "wine/debug.h"
24
25 #include "pidl.h"
26 #include "shlguid.h"
27 #include "wine/obj_base.h"
28 #include "wine/obj_contextmenu.h"
29 #include "wine/obj_shellbrowser.h"
30
31 #include "shell32_main.h"
32 #include "shellfolder.h"
33 #include "undocshell.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(shell);
36
37 /**************************************************************************
38 *  IContextMenu Implementation
39 */
40 typedef struct
41 {
42         ICOM_VFIELD(IContextMenu);
43         IShellFolder*   pSFParent;
44         DWORD           ref;
45 } BgCmImpl;
46
47
48 static struct ICOM_VTABLE(IContextMenu) cmvt;
49
50 /**************************************************************************
51 *   ISVBgCm_Constructor()
52 */
53 IContextMenu *ISvBgCm_Constructor(IShellFolder* pSFParent)
54 {
55         BgCmImpl* cm;
56
57         cm = (BgCmImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(BgCmImpl));
58         ICOM_VTBL(cm)=&cmvt;
59         cm->ref = 1;
60         cm->pSFParent = pSFParent;
61         if(pSFParent) IShellFolder_AddRef(pSFParent);
62
63         TRACE("(%p)->()\n",cm);
64         return (IContextMenu*)cm;
65 }
66
67 /**************************************************************************
68 *  ISVBgCm_fnQueryInterface
69 */
70 static HRESULT WINAPI ISVBgCm_fnQueryInterface(IContextMenu *iface, REFIID riid, LPVOID *ppvObj)
71 {
72         ICOM_THIS(BgCmImpl, iface);
73
74         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
75
76         *ppvObj = NULL;
77
78         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
79         {
80           *ppvObj = This;
81         }
82         else if(IsEqualIID(riid, &IID_IContextMenu))  /*IContextMenu*/
83         {
84           *ppvObj = This;
85         }
86         else if(IsEqualIID(riid, &IID_IShellExtInit))  /*IShellExtInit*/
87         {
88           FIXME("-- LPSHELLEXTINIT pointer requested\n");
89         }
90
91         if(*ppvObj)
92         {
93           IUnknown_AddRef((IUnknown*)*ppvObj);
94           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
95           return S_OK;
96         }
97         TRACE("-- Interface: E_NOINTERFACE\n");
98         return E_NOINTERFACE;
99 }
100
101 /**************************************************************************
102 *  ISVBgCm_fnAddRef
103 */
104 static ULONG WINAPI ISVBgCm_fnAddRef(IContextMenu *iface)
105 {
106         ICOM_THIS(BgCmImpl, iface);
107
108         TRACE("(%p)->(count=%lu)\n",This, This->ref);
109
110         return ++(This->ref);
111 }
112
113 /**************************************************************************
114 *  ISVBgCm_fnRelease
115 */
116 static ULONG WINAPI ISVBgCm_fnRelease(IContextMenu *iface)
117 {
118         ICOM_THIS(BgCmImpl, iface);
119
120         TRACE("(%p)->()\n",This);
121
122         if (!--(This->ref))
123         {
124           TRACE(" destroying IContextMenu(%p)\n",This);
125
126           if(This->pSFParent)
127             IShellFolder_Release(This->pSFParent);
128
129           HeapFree(GetProcessHeap(),0,This);
130           return 0;
131         }
132
133         return This->ref;
134 }
135
136 /**************************************************************************
137 * ISVBgCm_fnQueryContextMenu()
138 */
139
140 static HRESULT WINAPI ISVBgCm_fnQueryContextMenu(
141         IContextMenu *iface,
142         HMENU hMenu,
143         UINT indexMenu,
144         UINT idCmdFirst,
145         UINT idCmdLast,
146         UINT uFlags)
147 {
148     HMENU       hMyMenu;
149     UINT        idMax;
150     HRESULT hr;
151
152     ICOM_THIS(BgCmImpl, iface);
153
154     TRACE("(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
155           This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
156
157
158     hMyMenu = LoadMenuA(shell32_hInstance, "MENU_002");
159     if (uFlags & CMF_DEFAULTONLY)
160     {
161         HMENU ourMenu = GetSubMenu(hMyMenu,0);
162         UINT oldDef = GetMenuDefaultItem(hMenu,TRUE,GMDI_USEDISABLED);
163         UINT newDef = GetMenuDefaultItem(ourMenu,TRUE,GMDI_USEDISABLED);
164         if (newDef != oldDef)
165             SetMenuDefaultItem(hMenu,newDef,TRUE);
166         if (newDef!=0xFFFFFFFF)
167             hr =  MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, newDef+1);
168         else
169             hr =  MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
170     }
171     else
172     {
173         idMax = Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu,
174                                   idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS);
175         hr =  MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst+1);
176     }
177     DestroyMenu(hMyMenu);
178
179     TRACE("(%p)->returning 0x%lx\n",This,hr);
180     return hr;
181 }
182
183 /**************************************************************************
184 * DoNewFolder
185 */
186 static void DoNewFolder(
187         IContextMenu *iface,
188         IShellView *psv)
189 {
190         ICOM_THIS(BgCmImpl, iface);
191         ISFHelper * psfhlp;
192         char szName[MAX_PATH];
193
194         IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlp);
195         if (psfhlp)
196         {
197           LPITEMIDLIST pidl;
198           ISFHelper_GetUniqueName(psfhlp, szName, MAX_PATH);
199           ISFHelper_AddFolder(psfhlp, 0, szName, &pidl);
200
201           if(psv)
202           {
203             /* if we are in a shellview do labeledit */
204             IShellView_SelectItem(psv,
205                     pidl,(SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
206                     |SVSI_FOCUSED|SVSI_SELECT));
207           }
208           SHFree(pidl);
209
210           ISFHelper_Release(psfhlp);
211         }
212 }
213
214 /**************************************************************************
215 * DoPaste
216 */
217 static BOOL DoPaste(
218         IContextMenu *iface)
219 {
220         ICOM_THIS(BgCmImpl, iface);
221         BOOL bSuccess = FALSE;
222         IDataObject * pda;
223
224         TRACE("\n");
225
226         if(SUCCEEDED(pOleGetClipboard(&pda)))
227         {
228           STGMEDIUM medium;
229           FORMATETC formatetc;
230
231           TRACE("pda=%p\n", pda);
232
233           /* Set the FORMATETC structure*/
234           InitFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
235
236           /* Get the pidls from IDataObject */
237           if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium)))
238           {
239             LPITEMIDLIST * apidl;
240             LPITEMIDLIST pidl;
241             IShellFolder *psfFrom = NULL, *psfDesktop;
242
243             LPCIDA lpcida = GlobalLock(medium.u.hGlobal);
244             TRACE("cida=%p\n", lpcida);
245
246             apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
247
248             /* bind to the source shellfolder */
249             SHGetDesktopFolder(&psfDesktop);
250             if(psfDesktop)
251             {
252               IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom);
253               IShellFolder_Release(psfDesktop);
254             }
255
256             if (psfFrom)
257             {
258               /* get source and destination shellfolder */
259               ISFHelper *psfhlpdst, *psfhlpsrc;
260               IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlpdst);
261               IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (LPVOID*)&psfhlpsrc);
262
263               /* do the copy/move */
264               if (psfhlpdst && psfhlpsrc)
265               {
266                 ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, apidl);
267                 /* FIXME handle move
268                 ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl);
269                 */
270               }
271               if(psfhlpdst) ISFHelper_Release(psfhlpdst);
272               if(psfhlpsrc) ISFHelper_Release(psfhlpsrc);
273               IShellFolder_Release(psfFrom);
274             }
275
276             _ILFreeaPidl(apidl, lpcida->cidl);
277             SHFree(pidl);
278
279             /* release the medium*/
280             pReleaseStgMedium(&medium);
281           }
282           IDataObject_Release(pda);
283         }
284 #if 0
285         HGLOBAL  hMem;
286
287         OpenClipboard(NULL);
288         hMem = GetClipboardData(CF_HDROP);
289
290         if(hMem)
291         {
292           char * pDropFiles = (char *)GlobalLock(hMem);
293           if(pDropFiles)
294           {
295             int len, offset = sizeof(DROPFILESTRUCT);
296
297             while( pDropFiles[offset] != 0)
298             {
299               len = strlen(pDropFiles + offset);
300               TRACE("%s\n", pDropFiles + offset);
301               offset += len+1;
302             }
303           }
304           GlobalUnlock(hMem);
305         }
306         CloseClipboard();
307 #endif
308         return bSuccess;
309 }
310 /**************************************************************************
311 * ISVBgCm_fnInvokeCommand()
312 */
313 static HRESULT WINAPI ISVBgCm_fnInvokeCommand(
314         IContextMenu *iface,
315         LPCMINVOKECOMMANDINFO lpcmi)
316 {
317         ICOM_THIS(BgCmImpl, iface);
318
319         LPSHELLBROWSER  lpSB;
320         LPSHELLVIEW     lpSV;
321         HWND    hWndSV;
322
323         TRACE("(%p)->(invcom=%p verb=%p wnd=%x)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
324
325         /* get the active IShellView */
326         if((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0)))
327         {
328           if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
329           {
330             IShellView_GetWindow(lpSV, &hWndSV);
331           }
332         }
333
334         if(lpSV)
335         {
336           if(HIWORD(lpcmi->lpVerb))
337           {
338             TRACE("%s\n",lpcmi->lpVerb);
339
340             if (! strcmp(lpcmi->lpVerb,CMDSTR_NEWFOLDERA))
341             {
342               if(lpSV) DoNewFolder(iface, lpSV);
343             }
344             else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWLISTA))
345             {
346               if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW,0),0 );
347             }
348             else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWDETAILSA))
349             {
350               if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW,0),0 );
351             }
352             else
353             {
354               FIXME("please report: unknown verb %s\n",lpcmi->lpVerb);
355             }
356           }
357           else
358           {
359             switch(LOWORD(lpcmi->lpVerb))
360             {
361               case FCIDM_SHVIEW_NEWFOLDER:
362                 DoNewFolder(iface, lpSV);
363                 break;
364               case FCIDM_SHVIEW_INSERT:
365                 DoPaste(iface);
366                 break;
367               default:
368                 /* if it's a id just pass it to the parent shv */
369                 SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0),0 );
370                 break;
371             }
372           }
373
374           IShellView_Release(lpSV);     /* QueryActiveShellView does AddRef*/
375         }
376         return NOERROR;
377 }
378
379 /**************************************************************************
380  *  ISVBgCm_fnGetCommandString()
381  *
382  */
383 static HRESULT WINAPI ISVBgCm_fnGetCommandString(
384         IContextMenu *iface,
385         UINT idCommand,
386         UINT uFlags,
387         UINT* lpReserved,
388         LPSTR lpszName,
389         UINT uMaxNameLen)
390 {
391         ICOM_THIS(BgCmImpl, iface);
392
393         TRACE("(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
394
395         /* test the existence of the menu items, the file dialog enables
396            the buttons according to this */
397         if (uFlags == GCS_VALIDATEA)
398         {
399           if(HIWORD(idCommand))
400           {
401             if (!strcmp((LPSTR)idCommand, CMDSTR_VIEWLISTA) ||
402                 !strcmp((LPSTR)idCommand, CMDSTR_VIEWDETAILSA) ||
403                 !strcmp((LPSTR)idCommand, CMDSTR_NEWFOLDERA))
404             {
405               return NOERROR;
406             }
407           }
408         }
409
410         FIXME("unknown command string\n");
411         return E_FAIL;
412 }
413
414 /**************************************************************************
415 * ISVBgCm_fnHandleMenuMsg()
416 */
417 static HRESULT WINAPI ISVBgCm_fnHandleMenuMsg(
418         IContextMenu *iface,
419         UINT uMsg,
420         WPARAM wParam,
421         LPARAM lParam)
422 {
423         ICOM_THIS(BgCmImpl, iface);
424
425         FIXME("(%p)->(msg=%x wp=%x lp=%lx)\n",This, uMsg, wParam, lParam);
426
427         return E_NOTIMPL;
428 }
429
430 /**************************************************************************
431 * IContextMenu VTable
432 *
433 */
434 static struct ICOM_VTABLE(IContextMenu) cmvt =
435 {
436         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
437         ISVBgCm_fnQueryInterface,
438         ISVBgCm_fnAddRef,
439         ISVBgCm_fnRelease,
440         ISVBgCm_fnQueryContextMenu,
441         ISVBgCm_fnInvokeCommand,
442         ISVBgCm_fnGetCommandString,
443         ISVBgCm_fnHandleMenuMsg,
444         (void *) 0xdeadbabe     /* just paranoia (IContextMenu3) */
445 };