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