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