shv_bg_cmenu.c 11.5 KB
Newer Older
1 2 3 4 5
/*
 *	IContextMenu
 *	ShellView Background Context Menu (shv_bg_cm)
 *
 *	Copyright 1999	Juergen Schmied <juergen.schmied@metronet.de>
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 22
 */
#include <string.h>

23
#define COBJMACROS
24 25
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
26

27
#include "wine/debug.h"
28

29 30
#include "windef.h"
#include "wingdi.h"
31
#include "pidl.h"
32
#include "shlobj.h"
33 34

#include "shell32_main.h"
Juergen Schmied's avatar
Juergen Schmied committed
35
#include "shellfolder.h"
36
#include "undocshell.h"
37

38
WINE_DEFAULT_DEBUG_CHANNEL(shell);
39 40 41 42

/**************************************************************************
*  IContextMenu Implementation
*/
43
typedef struct
Juergen Schmied's avatar
Juergen Schmied committed
44
{
45
	const IContextMenu2Vtbl *lpVtbl;
Juergen Schmied's avatar
Juergen Schmied committed
46
	IShellFolder*	pSFParent;
Mike McCormack's avatar
Mike McCormack committed
47
	LONG		ref;
48
	BOOL		bDesktop;
49 50 51
} BgCmImpl;


52
static const IContextMenu2Vtbl cmvt;
53 54 55 56

/**************************************************************************
*   ISVBgCm_Constructor()
*/
57
IContextMenu2 *ISvBgCm_Constructor(IShellFolder* pSFParent, BOOL bDesktop)
58 59 60
{
	BgCmImpl* cm;

61
	cm = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(BgCmImpl));
62
	cm->lpVtbl = &cmvt;
63
	cm->ref = 1;
Juergen Schmied's avatar
Juergen Schmied committed
64
	cm->pSFParent = pSFParent;
65
	cm->bDesktop = bDesktop;
Juergen Schmied's avatar
Juergen Schmied committed
66
	if(pSFParent) IShellFolder_AddRef(pSFParent);
67 68

	TRACE("(%p)->()\n",cm);
69
	return (IContextMenu2*)cm;
70 71 72 73 74
}

/**************************************************************************
*  ISVBgCm_fnQueryInterface
*/
75
static HRESULT WINAPI ISVBgCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj)
76
{
77
	BgCmImpl *This = (BgCmImpl *)iface;
78

79
	TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
80 81 82

	*ppvObj = NULL;

83 84 85
        if(IsEqualIID(riid, &IID_IUnknown) ||
           IsEqualIID(riid, &IID_IContextMenu) ||
           IsEqualIID(riid, &IID_IContextMenu2))
86 87
	{
	  *ppvObj = This;
88
	}
89 90 91 92 93 94
	else if(IsEqualIID(riid, &IID_IShellExtInit))  /*IShellExtInit*/
	{
	  FIXME("-- LPSHELLEXTINIT pointer requested\n");
	}

	if(*ppvObj)
95 96
	{
	  IUnknown_AddRef((IUnknown*)*ppvObj);
97 98 99 100 101 102 103 104 105 106
	  TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
	  return S_OK;
	}
	TRACE("-- Interface: E_NOINTERFACE\n");
	return E_NOINTERFACE;
}

/**************************************************************************
*  ISVBgCm_fnAddRef
*/
107
static ULONG WINAPI ISVBgCm_fnAddRef(IContextMenu2 *iface)
108
{
109
	BgCmImpl *This = (BgCmImpl *)iface;
110
	ULONG refCount = InterlockedIncrement(&This->ref);
111

112
	TRACE("(%p)->(count=%u)\n", This, refCount - 1);
113

114
	return refCount;
115 116 117 118 119
}

/**************************************************************************
*  ISVBgCm_fnRelease
*/
120
static ULONG WINAPI ISVBgCm_fnRelease(IContextMenu2 *iface)
121
{
122
	BgCmImpl *This = (BgCmImpl *)iface;
123
	ULONG refCount = InterlockedDecrement(&This->ref);
124

125
	TRACE("(%p)->(count=%i)\n", This, refCount + 1);
126

127
	if (!refCount)
Juergen Schmied's avatar
Juergen Schmied committed
128 129 130 131 132
	{
	  TRACE(" destroying IContextMenu(%p)\n",This);

	  if(This->pSFParent)
	    IShellFolder_Release(This->pSFParent);
133 134 135

	  HeapFree(GetProcessHeap(),0,This);
	}
136
	return refCount;
137 138 139 140 141 142 143
}

/**************************************************************************
* ISVBgCm_fnQueryContextMenu()
*/

static HRESULT WINAPI ISVBgCm_fnQueryContextMenu(
144
	IContextMenu2 *iface,
145 146 147 148 149 150
	HMENU hMenu,
	UINT indexMenu,
	UINT idCmdFirst,
	UINT idCmdLast,
	UINT uFlags)
{
151 152 153 154
    HMENU	hMyMenu;
    UINT	idMax;
    HRESULT hr;

155
    BgCmImpl *This = (BgCmImpl *)iface;
156

157
    TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
          This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);


    hMyMenu = LoadMenuA(shell32_hInstance, "MENU_002");
    if (uFlags & CMF_DEFAULTONLY)
    {
        HMENU ourMenu = GetSubMenu(hMyMenu,0);
        UINT oldDef = GetMenuDefaultItem(hMenu,TRUE,GMDI_USEDISABLED);
        UINT newDef = GetMenuDefaultItem(ourMenu,TRUE,GMDI_USEDISABLED);
        if (newDef != oldDef)
            SetMenuDefaultItem(hMenu,newDef,TRUE);
        if (newDef!=0xFFFFFFFF)
            hr =  MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, newDef+1);
        else
            hr =  MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
    }
    else
    {
        idMax = Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu,
                                  idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS);
        hr =  MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst+1);
    }
    DestroyMenu(hMyMenu);

182
    TRACE("(%p)->returning 0x%x\n",This,hr);
183
    return hr;
184 185
}

Juergen Schmied's avatar
Juergen Schmied committed
186 187 188 189
/**************************************************************************
* DoNewFolder
*/
static void DoNewFolder(
190
	IContextMenu2 *iface,
Juergen Schmied's avatar
Juergen Schmied committed
191 192
	IShellView *psv)
{
193
	BgCmImpl *This = (BgCmImpl *)iface;
Juergen Schmied's avatar
Juergen Schmied committed
194
	ISFHelper * psfhlp;
195
	WCHAR wszName[MAX_PATH];
196

Juergen Schmied's avatar
Juergen Schmied committed
197 198 199 200
	IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlp);
	if (psfhlp)
	{
	  LPITEMIDLIST pidl;
201 202
	  ISFHelper_GetUniqueName(psfhlp, wszName, MAX_PATH);
	  ISFHelper_AddFolder(psfhlp, 0, wszName, &pidl);
203

Juergen Schmied's avatar
Juergen Schmied committed
204 205 206 207 208 209 210 211
	  if(psv)
	  {
	    /* if we are in a shellview do labeledit */
	    IShellView_SelectItem(psv,
                    pidl,(SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
                    |SVSI_FOCUSED|SVSI_SELECT));
	  }
	  SHFree(pidl);
212

Juergen Schmied's avatar
Juergen Schmied committed
213 214 215 216 217 218 219 220
	  ISFHelper_Release(psfhlp);
	}
}

/**************************************************************************
* DoPaste
*/
static BOOL DoPaste(
221
	IContextMenu2 *iface)
Juergen Schmied's avatar
Juergen Schmied committed
222
{
223
	BgCmImpl *This = (BgCmImpl *)iface;
Juergen Schmied's avatar
Juergen Schmied committed
224 225
	BOOL bSuccess = FALSE;
	IDataObject * pda;
226

Juergen Schmied's avatar
Juergen Schmied committed
227 228
	TRACE("\n");

229
	if(SUCCEEDED(OleGetClipboard(&pda)))
Juergen Schmied's avatar
Juergen Schmied committed
230 231 232 233 234 235 236
	{
	  STGMEDIUM medium;
	  FORMATETC formatetc;

	  TRACE("pda=%p\n", pda);

	  /* Set the FORMATETC structure*/
237
	  InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLISTW), TYMED_HGLOBAL);
Juergen Schmied's avatar
Juergen Schmied committed
238 239 240 241 242 243 244 245

	  /* Get the pidls from IDataObject */
	  if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium)))
          {
	    LPITEMIDLIST * apidl;
	    LPITEMIDLIST pidl;
	    IShellFolder *psfFrom = NULL, *psfDesktop;

246
	    LPIDA lpcida = GlobalLock(medium.u.hGlobal);
Juergen Schmied's avatar
Juergen Schmied committed
247
	    TRACE("cida=%p\n", lpcida);
248

Juergen Schmied's avatar
Juergen Schmied committed
249
	    apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
250

Juergen Schmied's avatar
Juergen Schmied committed
251 252 253 254 255 256 257
	    /* bind to the source shellfolder */
	    SHGetDesktopFolder(&psfDesktop);
	    if(psfDesktop)
	    {
	      IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom);
	      IShellFolder_Release(psfDesktop);
	    }
258

Juergen Schmied's avatar
Juergen Schmied committed
259 260 261 262 263 264
	    if (psfFrom)
	    {
	      /* get source and destination shellfolder */
	      ISFHelper *psfhlpdst, *psfhlpsrc;
	      IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlpdst);
	      IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (LPVOID*)&psfhlpsrc);
265

Juergen Schmied's avatar
Juergen Schmied committed
266 267 268
	      /* do the copy/move */
	      if (psfhlpdst && psfhlpsrc)
	      {
269
	        ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl);
270
		/* FIXME handle move
Juergen Schmied's avatar
Juergen Schmied committed
271 272 273 274 275 276 277
		ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl);
		*/
	      }
	      if(psfhlpdst) ISFHelper_Release(psfhlpdst);
	      if(psfhlpsrc) ISFHelper_Release(psfhlpsrc);
	      IShellFolder_Release(psfFrom);
	    }
278

Juergen Schmied's avatar
Juergen Schmied committed
279 280
	    _ILFreeaPidl(apidl, lpcida->cidl);
	    SHFree(pidl);
281

Juergen Schmied's avatar
Juergen Schmied committed
282
	    /* release the medium*/
283
	    ReleaseStgMedium(&medium);
Juergen Schmied's avatar
Juergen Schmied committed
284 285 286 287 288 289 290 291
	  }
	  IDataObject_Release(pda);
	}
#if 0
	HGLOBAL  hMem;

	OpenClipboard(NULL);
	hMem = GetClipboardData(CF_HDROP);
292

Juergen Schmied's avatar
Juergen Schmied committed
293 294
	if(hMem)
	{
295
          char * pDropFiles = GlobalLock(hMem);
Juergen Schmied's avatar
Juergen Schmied committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
	  if(pDropFiles)
	  {
	    int len, offset = sizeof(DROPFILESTRUCT);

	    while( pDropFiles[offset] != 0)
	    {
	      len = strlen(pDropFiles + offset);
	      TRACE("%s\n", pDropFiles + offset);
	      offset += len+1;
	    }
	  }
	  GlobalUnlock(hMem);
	}
	CloseClipboard();
#endif
	return bSuccess;
}
313

314 315 316 317
/**************************************************************************
* ISVBgCm_fnInvokeCommand()
*/
static HRESULT WINAPI ISVBgCm_fnInvokeCommand(
318
	IContextMenu2 *iface,
319 320
	LPCMINVOKECOMMANDINFO lpcmi)
{
321
	BgCmImpl *This = (BgCmImpl *)iface;
322 323

	LPSHELLBROWSER	lpSB;
324 325
	LPSHELLVIEW lpSV = NULL;
	HWND hWndSV = 0;
326

327
	TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
328 329

	/* get the active IShellView */
Juergen Schmied's avatar
Juergen Schmied committed
330
	if((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0)))
331
	{
Juergen Schmied's avatar
Juergen Schmied committed
332
	  if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
333
	  {
Juergen Schmied's avatar
Juergen Schmied committed
334
	    IShellView_GetWindow(lpSV, &hWndSV);
335
	  }
Juergen Schmied's avatar
Juergen Schmied committed
336 337 338
	}

	  if(HIWORD(lpcmi->lpVerb))
339
	  {
Juergen Schmied's avatar
Juergen Schmied committed
340 341 342 343
	    TRACE("%s\n",lpcmi->lpVerb);

	    if (! strcmp(lpcmi->lpVerb,CMDSTR_NEWFOLDERA))
	    {
344
                DoNewFolder(iface, lpSV);
Juergen Schmied's avatar
Juergen Schmied committed
345 346 347 348 349 350 351 352
	    }
	    else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWLISTA))
	    {
	      if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW,0),0 );
	    }
	    else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWDETAILSA))
	    {
	      if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW,0),0 );
353
	    }
Juergen Schmied's avatar
Juergen Schmied committed
354 355 356 357
	    else
	    {
	      FIXME("please report: unknown verb %s\n",lpcmi->lpVerb);
	    }
358 359 360
	  }
	  else
	  {
Juergen Schmied's avatar
Juergen Schmied committed
361 362
	    switch(LOWORD(lpcmi->lpVerb))
	    {
363 364 365 366
	      case FCIDM_SHVIEW_REFRESH:
	        if (lpSV) IShellView_Refresh(lpSV);
	        break;

Juergen Schmied's avatar
Juergen Schmied committed
367 368 369
	      case FCIDM_SHVIEW_NEWFOLDER:
	        DoNewFolder(iface, lpSV);
		break;
370

Juergen Schmied's avatar
Juergen Schmied committed
371 372 373
	      case FCIDM_SHVIEW_INSERT:
	        DoPaste(iface);
	        break;
374 375 376 377 378 379 380 381 382

	      case FCIDM_SHVIEW_PROPERTIES:
		if (This->bDesktop) {
		    ShellExecuteA(lpcmi->hwnd, "open", "rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL);
		} else {
		    FIXME("launch item properties dialog\n");
		}
		break;

Juergen Schmied's avatar
Juergen Schmied committed
383
	      default:
384
	        /* if it's an id just pass it to the parent shv */
385
	        if (hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0),0 );
Juergen Schmied's avatar
Juergen Schmied committed
386 387
		break;
	    }
388
	  }
389

390
        if (lpSV)
391
	  IShellView_Release(lpSV);	/* QueryActiveShellView does AddRef */
392

393 394 395 396 397 398 399 400
	return NOERROR;
}

/**************************************************************************
 *  ISVBgCm_fnGetCommandString()
 *
 */
static HRESULT WINAPI ISVBgCm_fnGetCommandString(
401
	IContextMenu2 *iface,
Kevin Koltzau's avatar
Kevin Koltzau committed
402
	UINT_PTR idCommand,
403
	UINT uFlags,
404
	UINT* lpReserved,
405 406
	LPSTR lpszName,
	UINT uMaxNameLen)
407
{
408
	BgCmImpl *This = (BgCmImpl *)iface;
409

410
	TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
411

412
	/* test the existence of the menu items, the file dialog enables
413 414 415
	   the buttons according to this */
	if (uFlags == GCS_VALIDATEA)
	{
416 417 418 419 420
	  if(HIWORD(idCommand))
	  {
	    if (!strcmp((LPSTR)idCommand, CMDSTR_VIEWLISTA) ||
	        !strcmp((LPSTR)idCommand, CMDSTR_VIEWDETAILSA) ||
	        !strcmp((LPSTR)idCommand, CMDSTR_NEWFOLDERA))
421
	    {
422 423
	      return NOERROR;
	    }
424 425 426 427 428 429 430 431 432 433 434
	  }
	}

	FIXME("unknown command string\n");
	return E_FAIL;
}

/**************************************************************************
* ISVBgCm_fnHandleMenuMsg()
*/
static HRESULT WINAPI ISVBgCm_fnHandleMenuMsg(
435
	IContextMenu2 *iface,
436 437 438 439
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam)
{
440
	BgCmImpl *This = (BgCmImpl *)iface;
441

442
	FIXME("(%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam);
443 444 445 446 447

	return E_NOTIMPL;
}

/**************************************************************************
448
* IContextMenu2 VTable
449
*
450
*/
451
static const IContextMenu2Vtbl cmvt =
452
{
453 454 455 456 457 458
	ISVBgCm_fnQueryInterface,
	ISVBgCm_fnAddRef,
	ISVBgCm_fnRelease,
	ISVBgCm_fnQueryContextMenu,
	ISVBgCm_fnInvokeCommand,
	ISVBgCm_fnGetCommandString,
459
	ISVBgCm_fnHandleMenuMsg
460
};