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