- remove unneccesary ISF_MyComputer_Constructor() declaration
[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 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
25 #include "wine/debug.h"
26
27 #include "windef.h"
28 #include "wingdi.h"
29 #include "pidl.h"
30 #include "shlguid.h"
31 #include "shlobj.h"
32
33 #include "shell32_main.h"
34 #include "shellfolder.h"
35 #include "undocshell.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(shell);
38
39 /**************************************************************************
40 *  IContextMenu Implementation
41 */
42 typedef struct
43 {
44         ICOM_VFIELD(IContextMenu2);
45         IShellFolder*   pSFParent;
46         DWORD           ref;
47 } BgCmImpl;
48
49
50 static struct ICOM_VTABLE(IContextMenu2) cmvt;
51
52 /**************************************************************************
53 *   ISVBgCm_Constructor()
54 */
55 IContextMenu2 *ISvBgCm_Constructor(IShellFolder*        pSFParent)
56 {
57         BgCmImpl* cm;
58
59         cm = (BgCmImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(BgCmImpl));
60         cm->lpVtbl = &cmvt;
61         cm->ref = 1;
62         cm->pSFParent = pSFParent;
63         if(pSFParent) IShellFolder_AddRef(pSFParent);
64
65         TRACE("(%p)->()\n",cm);
66         return (IContextMenu2*)cm;
67 }
68
69 /**************************************************************************
70 *  ISVBgCm_fnQueryInterface
71 */
72 static HRESULT WINAPI ISVBgCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj)
73 {
74         ICOM_THIS(BgCmImpl, iface);
75
76         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
77
78         *ppvObj = NULL;
79
80         if(IsEqualIID(riid, &IID_IUnknown) ||
81            IsEqualIID(riid, &IID_IContextMenu) ||
82            IsEqualIID(riid, &IID_IContextMenu2))
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(IContextMenu2 *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(IContextMenu2 *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         IContextMenu2 *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=%p 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         IContextMenu2 *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         IContextMenu2 *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             LPIDA 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, (LPCITEMIDLIST*)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 /**************************************************************************
312 * ISVBgCm_fnInvokeCommand()
313 */
314 static HRESULT WINAPI ISVBgCm_fnInvokeCommand(
315         IContextMenu2 *iface,
316         LPCMINVOKECOMMANDINFO lpcmi)
317 {
318         ICOM_THIS(BgCmImpl, iface);
319
320         LPSHELLBROWSER  lpSB;
321         LPSHELLVIEW lpSV = NULL;
322         HWND hWndSV = 0;
323
324         TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
325
326         /* get the active IShellView */
327         if((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0)))
328         {
329           if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
330           {
331             IShellView_GetWindow(lpSV, &hWndSV);
332           }
333         }
334
335           if(HIWORD(lpcmi->lpVerb))
336           {
337             TRACE("%s\n",lpcmi->lpVerb);
338
339             if (! strcmp(lpcmi->lpVerb,CMDSTR_NEWFOLDERA))
340             {
341                 DoNewFolder(iface, lpSV);
342             }
343             else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWLISTA))
344             {
345               if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW,0),0 );
346             }
347             else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWDETAILSA))
348             {
349               if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW,0),0 );
350             }
351             else
352             {
353               FIXME("please report: unknown verb %s\n",lpcmi->lpVerb);
354             }
355           }
356           else
357           {
358             switch(LOWORD(lpcmi->lpVerb))
359             {
360               case FCIDM_SHVIEW_NEWFOLDER:
361                 DoNewFolder(iface, lpSV);
362                 break;
363               case FCIDM_SHVIEW_INSERT:
364                 DoPaste(iface);
365                 break;
366               default:
367                 /* if it's a id just pass it to the parent shv */
368                 SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0),0 );
369                 break;
370             }
371           }
372
373         if (lpSV)
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         IContextMenu2 *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         IContextMenu2 *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 * IContextMenu2 VTable
432 *
433 */
434 static struct ICOM_VTABLE(IContextMenu2) 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 };