shv_bg_cmenu.c 10.9 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 19
 *
 * 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
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 21 22
 */
#include <string.h>

23 24
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
25
#include "wine/debug.h"
26

27 28
#include "windef.h"
#include "wingdi.h"
29
#include "pidl.h"
30
#include "shlguid.h"
31
#include "shlobj.h"
32 33

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

37
WINE_DEFAULT_DEBUG_CHANNEL(shell);
38 39 40 41

/**************************************************************************
*  IContextMenu Implementation
*/
42
typedef struct
Juergen Schmied's avatar
Juergen Schmied committed
43
{
44
	ICOM_VFIELD(IContextMenu2);
Juergen Schmied's avatar
Juergen Schmied committed
45
	IShellFolder*	pSFParent;
46 47 48 49
	DWORD		ref;
} BgCmImpl;


50
static struct ICOM_VTABLE(IContextMenu2) cmvt;
51 52 53 54

/**************************************************************************
*   ISVBgCm_Constructor()
*/
55
IContextMenu2 *ISvBgCm_Constructor(IShellFolder*	pSFParent)
56 57 58 59
{
	BgCmImpl* cm;

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

	TRACE("(%p)->()\n",cm);
66
	return (IContextMenu2*)cm;
67 68 69 70 71
}

/**************************************************************************
*  ISVBgCm_fnQueryInterface
*/
72
static HRESULT WINAPI ISVBgCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj)
73 74 75
{
	ICOM_THIS(BgCmImpl, iface);

76
	TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
77 78 79

	*ppvObj = NULL;

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

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

/**************************************************************************
*  ISVBgCm_fnAddRef
*/
104
static ULONG WINAPI ISVBgCm_fnAddRef(IContextMenu2 *iface)
105 106 107 108 109 110 111 112 113 114 115
{
	ICOM_THIS(BgCmImpl, iface);

	TRACE("(%p)->(count=%lu)\n",This, This->ref);

	return ++(This->ref);
}

/**************************************************************************
*  ISVBgCm_fnRelease
*/
116
static ULONG WINAPI ISVBgCm_fnRelease(IContextMenu2 *iface)
117 118 119 120 121
{
	ICOM_THIS(BgCmImpl, iface);

	TRACE("(%p)->()\n",This);

122
	if (!--(This->ref))
Juergen Schmied's avatar
Juergen Schmied committed
123 124 125 126 127
	{
	  TRACE(" destroying IContextMenu(%p)\n",This);

	  if(This->pSFParent)
	    IShellFolder_Release(This->pSFParent);
128 129 130 131

	  HeapFree(GetProcessHeap(),0,This);
	  return 0;
	}
Juergen Schmied's avatar
Juergen Schmied committed
132

133 134 135 136 137 138 139 140
	return This->ref;
}

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

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

    ICOM_THIS(BgCmImpl, iface);

154
    TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
          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);

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

Juergen Schmied's avatar
Juergen Schmied committed
183 184 185 186
/**************************************************************************
* DoNewFolder
*/
static void DoNewFolder(
187
	IContextMenu2 *iface,
Juergen Schmied's avatar
Juergen Schmied committed
188 189 190 191 192
	IShellView *psv)
{
	ICOM_THIS(BgCmImpl, iface);
	ISFHelper * psfhlp;
	char szName[MAX_PATH];
193

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

Juergen Schmied's avatar
Juergen Schmied committed
201 202 203 204 205 206 207 208
	  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);
209

Juergen Schmied's avatar
Juergen Schmied committed
210 211 212 213 214 215 216 217
	  ISFHelper_Release(psfhlp);
	}
}

/**************************************************************************
* DoPaste
*/
static BOOL DoPaste(
218
	IContextMenu2 *iface)
Juergen Schmied's avatar
Juergen Schmied committed
219 220 221 222
{
	ICOM_THIS(BgCmImpl, iface);
	BOOL bSuccess = FALSE;
	IDataObject * pda;
223

Juergen Schmied's avatar
Juergen Schmied committed
224 225
	TRACE("\n");

226
	if(SUCCEEDED(pOleGetClipboard(&pda)))
Juergen Schmied's avatar
Juergen Schmied committed
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
	{
	  STGMEDIUM medium;
	  FORMATETC formatetc;

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

	  /* Set the FORMATETC structure*/
	  InitFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);

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

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

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

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

Juergen Schmied's avatar
Juergen Schmied committed
256 257 258 259 260 261
	    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);
262

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

Juergen Schmied's avatar
Juergen Schmied committed
276 277
	    _ILFreeaPidl(apidl, lpcida->cidl);
	    SHFree(pidl);
278

Juergen Schmied's avatar
Juergen Schmied committed
279 280 281 282 283 284 285 286 287 288
	    /* release the medium*/
	    pReleaseStgMedium(&medium);
	  }
	  IDataObject_Release(pda);
	}
#if 0
	HGLOBAL  hMem;

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

Juergen Schmied's avatar
Juergen Schmied committed
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
	if(hMem)
	{
	  char * pDropFiles = (char *)GlobalLock(hMem);
	  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;
}
310

311 312 313 314
/**************************************************************************
* ISVBgCm_fnInvokeCommand()
*/
static HRESULT WINAPI ISVBgCm_fnInvokeCommand(
315
	IContextMenu2 *iface,
316 317 318 319 320
	LPCMINVOKECOMMANDINFO lpcmi)
{
	ICOM_THIS(BgCmImpl, iface);

	LPSHELLBROWSER	lpSB;
321 322
	LPSHELLVIEW lpSV = NULL;
	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 */
Juergen Schmied's avatar
Juergen Schmied committed
327
	if((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0)))
328
	{
Juergen Schmied's avatar
Juergen Schmied committed
329
	  if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
330
	  {
Juergen Schmied's avatar
Juergen Schmied committed
331
	    IShellView_GetWindow(lpSV, &hWndSV);
332
	  }
Juergen Schmied's avatar
Juergen Schmied committed
333 334 335
	}

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

	    if (! strcmp(lpcmi->lpVerb,CMDSTR_NEWFOLDERA))
	    {
341
                DoNewFolder(iface, lpSV);
Juergen Schmied's avatar
Juergen Schmied committed
342 343 344 345 346 347 348 349
	    }
	    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 );
350
	    }
Juergen Schmied's avatar
Juergen Schmied committed
351 352 353 354
	    else
	    {
	      FIXME("please report: unknown verb %s\n",lpcmi->lpVerb);
	    }
355 356 357
	  }
	  else
	  {
Juergen Schmied's avatar
Juergen Schmied committed
358 359 360 361 362 363 364 365 366 367 368 369 370
	    switch(LOWORD(lpcmi->lpVerb))
	    {
	      case FCIDM_SHVIEW_NEWFOLDER:
	        DoNewFolder(iface, lpSV);
		break;
	      case FCIDM_SHVIEW_INSERT:
	        DoPaste(iface);
	        break;
	      default:
	        /* if it's a id just pass it to the parent shv */
	        SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0),0 );
		break;
	    }
371
	  }
372

373
        if (lpSV)
Juergen Schmied's avatar
Juergen Schmied committed
374
	  IShellView_Release(lpSV);	/* QueryActiveShellView does AddRef*/
375

376 377 378 379 380 381 382 383
	return NOERROR;
}

/**************************************************************************
 *  ISVBgCm_fnGetCommandString()
 *
 */
static HRESULT WINAPI ISVBgCm_fnGetCommandString(
384
	IContextMenu2 *iface,
385 386
	UINT idCommand,
	UINT uFlags,
387
	UINT* lpReserved,
388 389
	LPSTR lpszName,
	UINT uMaxNameLen)
390
{
391 392 393 394
	ICOM_THIS(BgCmImpl, iface);

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

395
	/* test the existence of the menu items, the file dialog enables
396 397 398
	   the buttons according to this */
	if (uFlags == GCS_VALIDATEA)
	{
399 400 401 402 403
	  if(HIWORD(idCommand))
	  {
	    if (!strcmp((LPSTR)idCommand, CMDSTR_VIEWLISTA) ||
	        !strcmp((LPSTR)idCommand, CMDSTR_VIEWDETAILSA) ||
	        !strcmp((LPSTR)idCommand, CMDSTR_NEWFOLDERA))
404
	    {
405 406
	      return NOERROR;
	    }
407 408 409 410 411 412 413 414 415 416 417
	  }
	}

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

/**************************************************************************
* ISVBgCm_fnHandleMenuMsg()
*/
static HRESULT WINAPI ISVBgCm_fnHandleMenuMsg(
418
	IContextMenu2 *iface,
419 420 421 422 423 424 425 426 427 428 429 430
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam)
{
	ICOM_THIS(BgCmImpl, iface);

	FIXME("(%p)->(msg=%x wp=%x lp=%lx)\n",This, uMsg, wParam, lParam);

	return E_NOTIMPL;
}

/**************************************************************************
431
* IContextMenu2 VTable
432
*
433
*/
434
static struct ICOM_VTABLE(IContextMenu2) cmvt =
435
{
436 437 438 439 440 441 442
	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
	ISVBgCm_fnQueryInterface,
	ISVBgCm_fnAddRef,
	ISVBgCm_fnRelease,
	ISVBgCm_fnQueryContextMenu,
	ISVBgCm_fnInvokeCommand,
	ISVBgCm_fnGetCommandString,
443
	ISVBgCm_fnHandleMenuMsg
444
};