- new files related to context menu and drag drop file operations

- render functions for clipboardformats
This commit is contained in:
Juergen Schmied 2000-02-20 18:46:28 +00:00 committed by Alexandre Julliard
parent 3712c46511
commit e2b8804525
7 changed files with 827 additions and 465 deletions

View File

@ -16,8 +16,9 @@ SPEC_SRCS = \
C_SRCS = \
brsfolder.c \
changenotify.c \
classes.c \
contmenu.c \
clipboard.c \
dataobject.c \
enumidlist.c \
folders.c \
@ -33,10 +34,12 @@ C_SRCS = \
shellole.c \
shellord.c \
shellpath.c \
shlfileop.c \
shlfolder.c \
shlview.c \
shpolicy.c \
shv_bg_cmenu.c \
shv_item_cmenu.c \
systray.c
RC_SRCS= \

260
dlls/shell32/clipboard.c Normal file
View File

@ -0,0 +1,260 @@
/*
* clipboard helper functions
*
* Copyright 2000 Juergen Schmied <juergen.schmied@debitel.de>
*
* For copy & paste functions within contextmenus does the shell use
* the OLE clipboard functions in combination with dataobjects.
* The OLE32.DLL gets loaded with LoadLibrary
*
* - a right mousebutton-copy sets the following formats:
* classic:
* Shell IDList Array
* Prefered Drop Effect
* Shell Object Offsets
* HDROP
* FileName
* ole:
* OlePrivateData (ClipboardDataObjectInterface)
*
*/
#include <string.h>
#include "debugtools.h"
#include "pidl.h"
#include "wine/undocshell.h"
#include "shell32_main.h"
#include "shell.h" /* DROPFILESTRUCT */
DEFAULT_DEBUG_CHANNEL(shell)
static int refClipCount = 0;
static HINSTANCE hShellOle32 = 0;
/**************************************************************************
* InitShellOle
*
*
*/
void InitShellOle(void)
{
}
/**************************************************************************
* FreeShellOle
*
* unload OLE32.DLL
*/
void FreeShellOle(void)
{
if (!--refClipCount)
{
pOleUninitialize();
FreeLibrary(hShellOle32);
}
}
/**************************************************************************
* LoadShellOle
*
* make sure OLE32.DLL is loaded
*/
BOOL GetShellOle(void)
{
if(!refClipCount)
{
hShellOle32 = LoadLibraryA("ole32.dll");
if(hShellOle32)
{
pOleInitialize=(void*)GetProcAddress(hShellOle32,"OleInitialize");
pOleUninitialize=(void*)GetProcAddress(hShellOle32,"OleUninitialize");
pRegisterDragDrop=(void*)GetProcAddress(hShellOle32,"RegisterDragDrop");
pRevokeDragDrop=(void*)GetProcAddress(hShellOle32,"RevokeDragDrop");
pDoDragDrop=(void*)GetProcAddress(hShellOle32,"DoDragDrop");
pReleaseStgMedium=(void*)GetProcAddress(hShellOle32,"ReleaseStgMedium");
pOleSetClipboard=(void*)GetProcAddress(hShellOle32,"OleSetClipboard");
pOleGetClipboard=(void*)GetProcAddress(hShellOle32,"OleGetClipboard");
pOleInitialize(NULL);
refClipCount++;
}
}
return TRUE;
}
/**************************************************************************
* RenderHDROP
*
* creates a CF_HDROP structure
*/
HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
{
int i;
int rootsize = 0,size = 0;
char szRootPath[MAX_PATH];
char szFileName[MAX_PATH];
HGLOBAL hGlobal;
LPDROPFILESTRUCT pDropFiles;
int offset;
TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
/* get the size needed */
size = sizeof(DROPFILESTRUCT);
SHGetPathFromIDListA(pidlRoot, szRootPath);
PathAddBackslashA(szRootPath);
rootsize = strlen(szRootPath);
for (i=0; i<cidl;i++)
{
_ILSimpleGetText(apidl[i], szFileName, MAX_PATH);
size += rootsize + strlen(szFileName) + 1;
}
size++;
/* Fill the structure */
hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
if(!hGlobal) return hGlobal;
pDropFiles = (LPDROPFILESTRUCT)GlobalLock(hGlobal);
pDropFiles->lSize = sizeof(DROPFILESTRUCT);
pDropFiles->fWideChar = FALSE;
offset = pDropFiles->lSize;
strcpy(szFileName, szRootPath);
for (i=0; i<cidl;i++)
{
_ILSimpleGetText(apidl[i], szFileName + rootsize, MAX_PATH - rootsize);
size = strlen(szFileName) + 1;
lstrcpyA(((char*)pDropFiles)+offset, szFileName);
offset += size;
}
((char*)pDropFiles)[offset] = 0;
GlobalUnlock(hGlobal);
return hGlobal;
}
HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
{
int i,offset = 0, sizePidl, size;
HGLOBAL hGlobal;
LPCIDA pcida;
TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
/* get the size needed */
size = sizeof(CIDA) + sizeof (UINT)*(cidl); /* header */
size += ILGetSize (pidlRoot); /* root pidl */
for(i=0; i<cidl; i++)
{
size += ILGetSize(apidl[i]); /* child pidls */
}
/* fill the structure */
hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
if(!hGlobal) return hGlobal;
pcida = GlobalLock (hGlobal);
pcida->cidl = cidl;
/* root pidl */
offset = sizeof(CIDA) + sizeof (UINT)*(cidl);
pcida->aoffset[0] = offset; /* first element */
sizePidl = ILGetSize (pidlRoot);
memcpy(((LPBYTE)pcida)+offset, pidlRoot, sizePidl);
offset += sizePidl;
for(i=0; i<cidl; i++) /* child pidls */
{
pcida->aoffset[i+1] = offset;
sizePidl = ILGetSize(apidl[i]);
memcpy(((LPBYTE)pcida)+offset, apidl[i], sizePidl);
offset += sizePidl;
}
GlobalUnlock(hGlobal);
return hGlobal;
}
HGLOBAL RenderSHELLIDLISTOFFSET (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
{
FIXME("\n");
return 0;
}
HGLOBAL RenderFILECONTENTS (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
{
FIXME("\n");
return 0;
}
HGLOBAL RenderFILEDESCRIPTOR (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
{
FIXME("\n");
return 0;
}
HGLOBAL RenderFILENAME (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl)
{
int len, size = 0;
char szTemp[MAX_PATH], *szFileName;
HGLOBAL hGlobal;
TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl);
/* build name of first file */
SHGetPathFromIDListA(pidlRoot, szTemp);
PathAddBackslashA(szTemp);
len = strlen(szTemp);
_ILSimpleGetText(apidl[0], szTemp+len, MAX_PATH - len);
size = strlen(szTemp) + 1;
/* fill the structure */
hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size);
if(!hGlobal) return hGlobal;
szFileName = (char *)GlobalLock(hGlobal);
GlobalUnlock(hGlobal);
return hGlobal;
}
HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags)
{
DWORD * pdwFlag;
HGLOBAL hGlobal;
TRACE("(0x%08lx)\n", dwFlags);
hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD));
if(!hGlobal) return hGlobal;
pdwFlag = (DWORD*)GlobalLock(hGlobal);
*pdwFlag = dwFlags;
GlobalUnlock(hGlobal);
return hGlobal;
}
/**************************************************************************
* IsDataInClipboard
*
* checks if there is something in the clipboard we can use
*/
BOOL IsDataInClipboard (HWND hwnd)
{
BOOL ret = FALSE;
if (OpenClipboard(hwnd))
{
if (GetOpenClipboardWindow())
{
ret = IsClipboardFormatAvailable(CF_TEXT);
}
CloseClipboard();
}
return ret;
}

View File

@ -1,452 +0,0 @@
/*
* IContextMenu
*
* Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
*/
#include <string.h>
#include "winerror.h"
#include "debugtools.h"
#include "pidl.h"
#include "wine/obj_base.h"
#include "wine/obj_contextmenu.h"
#include "wine/obj_shellbrowser.h"
#include "wine/obj_shellextinit.h"
#include "wine/undocshell.h"
#include "shell32_main.h"
DEFAULT_DEBUG_CHANNEL(shell)
/**************************************************************************
* IContextMenu VTable
*
*/
static HRESULT WINAPI IContextMenu_fnQueryInterface(IContextMenu *iface, REFIID riid, LPVOID *ppvObj);
static ULONG WINAPI IContextMenu_fnAddRef(IContextMenu *iface);
static ULONG WINAPI IContextMenu_fnRelease(IContextMenu *iface);
static HRESULT WINAPI IContextMenu_fnQueryContextMenu(IContextMenu *iface, HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
static HRESULT WINAPI IContextMenu_fnInvokeCommand(IContextMenu *iface, LPCMINVOKECOMMANDINFO lpcmi);
static HRESULT WINAPI IContextMenu_fnGetCommandString(IContextMenu *iface, UINT idCommand, UINT uFlags, LPUINT lpReserved, LPSTR lpszName, UINT uMaxNameLen);
static HRESULT WINAPI IContextMenu_fnHandleMenuMsg(IContextMenu *iface, UINT uMsg, WPARAM wParam, LPARAM lParam);
static struct ICOM_VTABLE(IContextMenu) cmvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IContextMenu_fnQueryInterface,
IContextMenu_fnAddRef,
IContextMenu_fnRelease,
IContextMenu_fnQueryContextMenu,
IContextMenu_fnInvokeCommand,
IContextMenu_fnGetCommandString,
IContextMenu_fnHandleMenuMsg,
(void *) 0xdeadbabe /* just paranoia */
};
/**************************************************************************
* IContextMenu Implementation
*/
typedef struct
{ ICOM_VFIELD(IContextMenu);
DWORD ref;
IShellFolder* pSFParent;
LPITEMIDLIST pidl; /* root pidl */
LPITEMIDLIST *aPidls; /* array of child pidls */
BOOL bAllValues;
} IContextMenuImpl;
static struct ICOM_VTABLE(IContextMenu) cmvt;
/**************************************************************************
* IContextMenu_AllocPidlTable()
*/
static BOOL IContextMenu_AllocPidlTable(IContextMenuImpl *This, DWORD dwEntries)
{
TRACE("(%p)->(entrys=%lu)\n",This, dwEntries);
/*add one for NULL terminator */
dwEntries++;
This->aPidls = (LPITEMIDLIST*)SHAlloc(dwEntries * sizeof(LPITEMIDLIST));
if(This->aPidls)
{ ZeroMemory(This->aPidls, dwEntries * sizeof(LPITEMIDLIST)); /*set all of the entries to NULL*/
}
return (This->aPidls != NULL);
}
/**************************************************************************
* IContextMenu_FreePidlTable()
*/
static void IContextMenu_FreePidlTable(IContextMenuImpl *This)
{
int i;
TRACE("(%p)->()\n",This);
if(This->aPidls)
{ for(i = 0; This->aPidls[i]; i++)
{ SHFree(This->aPidls[i]);
}
SHFree(This->aPidls);
This->aPidls = NULL;
}
}
/**************************************************************************
* IContextMenu_FillPidlTable()
*/
static BOOL IContextMenu_FillPidlTable(IContextMenuImpl *This, LPCITEMIDLIST *aPidls, UINT uItemCount)
{
UINT i;
TRACE("(%p)->(apidl=%p count=%u)\n",This, aPidls, uItemCount);
if(This->aPidls)
{ for(i = 0; i < uItemCount; i++)
{ This->aPidls[i] = ILClone(aPidls[i]);
}
return TRUE;
}
return FALSE;
}
/**************************************************************************
* IContextMenu_CanRenameItems()
*/
static BOOL IContextMenu_CanRenameItems(IContextMenuImpl *This)
{ UINT i;
DWORD dwAttributes;
TRACE("(%p)->()\n",This);
if(This->aPidls)
{
for(i = 0; This->aPidls[i]; i++){} /*get the number of items assigned to This object*/
{ if(i > 1) /*you can't rename more than one item at a time*/
{ return FALSE;
}
}
dwAttributes = SFGAO_CANRENAME;
IShellFolder_GetAttributesOf(This->pSFParent, i, (LPCITEMIDLIST*)This->aPidls, &dwAttributes);
return dwAttributes & SFGAO_CANRENAME;
}
return FALSE;
}
/**************************************************************************
* IContextMenu_Constructor()
*/
IContextMenu *IContextMenu_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, LPCITEMIDLIST *aPidls, UINT uItemCount)
{ IContextMenuImpl* cm;
UINT u;
cm = (IContextMenuImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenuImpl));
ICOM_VTBL(cm)=&cmvt;
cm->ref = 1;
cm->pidl = ILClone(pidl);
cm->pSFParent = pSFParent;
if(pSFParent)
IShellFolder_AddRef(pSFParent);
cm->aPidls = NULL;
IContextMenu_AllocPidlTable(cm, uItemCount);
if(cm->aPidls)
{ IContextMenu_FillPidlTable(cm, aPidls, uItemCount);
}
cm->bAllValues = 1;
for(u = 0; u < uItemCount; u++)
{ cm->bAllValues &= (_ILIsValue(aPidls[u]) ? 1 : 0);
}
TRACE("(%p)->()\n",cm);
shell32_ObjCount++;
return (IContextMenu*)cm;
}
/**************************************************************************
* IContextMenu_fnQueryInterface
*/
static HRESULT WINAPI IContextMenu_fnQueryInterface(IContextMenu *iface, REFIID riid, LPVOID *ppvObj)
{
ICOM_THIS(IContextMenuImpl, iface);
TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
{ *ppvObj = This;
}
else if(IsEqualIID(riid, &IID_IContextMenu)) /*IContextMenu*/
{ *ppvObj = This;
}
else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/
{ FIXME("-- LPSHELLEXTINIT pointer requested\n");
}
if(*ppvObj)
{
IContextMenu_AddRef((IContextMenu*)*ppvObj);
TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/**************************************************************************
* IContextMenu_fnAddRef
*/
static ULONG WINAPI IContextMenu_fnAddRef(IContextMenu *iface)
{
ICOM_THIS(IContextMenuImpl, iface);
TRACE("(%p)->(count=%lu)\n",This, This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
/**************************************************************************
* IContextMenu_fnRelease
*/
static ULONG WINAPI IContextMenu_fnRelease(IContextMenu *iface)
{
ICOM_THIS(IContextMenuImpl, iface);
TRACE("(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{ TRACE(" destroying IContextMenu(%p)\n",This);
if(This->pSFParent)
IShellFolder_Release(This->pSFParent);
if(This->pidl)
SHFree(This->pidl);
/*make sure the pidl is freed*/
if(This->aPidls)
{ IContextMenu_FreePidlTable(This);
}
HeapFree(GetProcessHeap(),0,This);
return 0;
}
return This->ref;
}
/**************************************************************************
* ICM_InsertItem()
*/
void WINAPI _InsertMenuItem (
HMENU hmenu,
UINT indexMenu,
BOOL fByPosition,
UINT wID,
UINT fType,
LPSTR dwTypeData,
UINT fState)
{
MENUITEMINFOA mii;
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
if (fType == MFT_SEPARATOR)
{ mii.fMask = MIIM_ID | MIIM_TYPE;
}
else
{ mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
mii.dwTypeData = dwTypeData;
mii.fState = fState;
}
mii.wID = wID;
mii.fType = fType;
InsertMenuItemA( hmenu, indexMenu, fByPosition, &mii);
}
/**************************************************************************
* IContextMenu_fnQueryContextMenu()
*/
static HRESULT WINAPI IContextMenu_fnQueryContextMenu(
IContextMenu *iface,
HMENU hmenu,
UINT indexMenu,
UINT idCmdFirst,
UINT idCmdLast,
UINT uFlags)
{
ICOM_THIS(IContextMenuImpl, iface);
BOOL fExplore ;
TRACE("(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
if(!(CMF_DEFAULTONLY & uFlags))
{ if(!This->bAllValues)
{ /* folder menu */
fExplore = uFlags & CMF_EXPLORE;
if(fExplore)
{ _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED|MFS_DEFAULT);
_InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_OPEN, MFT_STRING, "&Open", MFS_ENABLED);
}
else
{ _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_OPEN, MFT_STRING, "&Open", MFS_ENABLED|MFS_DEFAULT);
_InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED);
}
if(uFlags & CMF_CANRENAME)
{ _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
_InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_RENAME, MFT_STRING, "&Rename", (IContextMenu_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED));
}
}
else /* file menu */
{ _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_OPEN, MFT_STRING, "&Open", MFS_ENABLED|MFS_DEFAULT);
if(uFlags & CMF_CANRENAME)
{ _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
_InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_RENAME, MFT_STRING, "&Rename", (IContextMenu_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED));
}
}
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (IDM_LAST + 1));
}
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
}
/**************************************************************************
* IContextMenu_fnInvokeCommand()
*/
static HRESULT WINAPI IContextMenu_fnInvokeCommand(
IContextMenu *iface,
LPCMINVOKECOMMANDINFO lpcmi)
{
ICOM_THIS(IContextMenuImpl, iface);
LPITEMIDLIST pidlFQ;
SHELLEXECUTEINFOA sei;
int i;
TRACE("(%p)->(invcom=%p verb=%p wnd=%x)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
if(LOWORD(lpcmi->lpVerb) > IDM_LAST)
return E_INVALIDARG;
switch(LOWORD(lpcmi->lpVerb))
{ case IDM_EXPLORE:
case IDM_OPEN:
/* Find the first item in the list that is not a value. These commands
should never be invoked if there isn't at least one folder item in the list.*/
for(i = 0; This->aPidls[i]; i++)
{ if(!_ILIsValue(This->aPidls[i]))
break;
}
pidlFQ = ILCombine(This->pidl, This->aPidls[i]);
ZeroMemory(&sei, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
sei.lpIDList = pidlFQ;
sei.lpClass = "folder";
sei.hwnd = lpcmi->hwnd;
sei.nShow = SW_SHOWNORMAL;
if(LOWORD(lpcmi->lpVerb) == IDM_EXPLORE)
{ sei.lpVerb = "explore";
}
else
{ sei.lpVerb = "open";
}
ShellExecuteExA(&sei);
SHFree(pidlFQ);
break;
case IDM_RENAME:
MessageBeep(MB_OK);
/*handle rename for the view here*/
break;
}
return NOERROR;
}
/**************************************************************************
* IContextMenu_fnGetCommandString()
*/
static HRESULT WINAPI IContextMenu_fnGetCommandString(
IContextMenu *iface,
UINT idCommand,
UINT uFlags,
LPUINT lpReserved,
LPSTR lpszName,
UINT uMaxNameLen)
{
ICOM_THIS(IContextMenuImpl, iface);
HRESULT hr = E_INVALIDARG;
TRACE("(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
switch(uFlags)
{ case GCS_HELPTEXT:
hr = E_NOTIMPL;
break;
case GCS_VERBA:
switch(idCommand)
{ case IDM_RENAME:
strcpy((LPSTR)lpszName, "rename");
hr = NOERROR;
break;
}
break;
/* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
case, you need to do the lstrcpyW to the pointer passed.*/
case GCS_VERBW:
switch(idCommand)
{ case IDM_RENAME:
lstrcpyAtoW((LPWSTR)lpszName, "rename");
hr = NOERROR;
break;
}
break;
case GCS_VALIDATE:
hr = NOERROR;
break;
}
TRACE("-- (%p)->(name=%s)\n",This, lpszName);
return hr;
}
/**************************************************************************
* IContextMenu_fnHandleMenuMsg()
* NOTES
* should be only in IContextMenu2 and IContextMenu3
* is nevertheless called from word95
*/
static HRESULT WINAPI IContextMenu_fnHandleMenuMsg(
IContextMenu *iface,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
ICOM_THIS(IContextMenuImpl, iface);
TRACE("(%p)->(msg=%x wp=%x lp=%lx)\n",This, uMsg, wParam, lParam);
return E_NOTIMPL;
}

View File

@ -0,0 +1,543 @@
/*
* IContextMenu for items in the shellview
*
* 1998, 2000 Juergen Schmied <juergen.schmied@debitel.net>
*/
#include <string.h>
#include "winerror.h"
#include "debugtools.h"
#include "pidl.h"
#include "wine/obj_base.h"
#include "wine/obj_contextmenu.h"
#include "wine/obj_shellbrowser.h"
#include "wine/obj_shellextinit.h"
#include "wine/undocshell.h"
#include "shell32_main.h"
#include "shellfolder.h"
#include "shell.h" /* DROPFILESTRUCT */
DEFAULT_DEBUG_CHANNEL(shell)
/**************************************************************************
* IContextMenu Implementation
*/
typedef struct
{ ICOM_VFIELD(IContextMenu);
DWORD ref;
IShellFolder* pSFParent;
LPITEMIDLIST pidl; /* root pidl */
LPITEMIDLIST *apidl; /* array of child pidls */
UINT cidl;
BOOL bAllValues;
} ItemCmImpl;
static struct ICOM_VTABLE(IContextMenu) cmvt;
/**************************************************************************
* ISvItemCm_CanRenameItems()
*/
static BOOL ISvItemCm_CanRenameItems(ItemCmImpl *This)
{ UINT i;
DWORD dwAttributes;
TRACE("(%p)->()\n",This);
if(This->apidl)
{
for(i = 0; i < This->cidl; i++){}
if(i > 1) return FALSE; /* can't rename more than one item at a time*/
dwAttributes = SFGAO_CANRENAME;
IShellFolder_GetAttributesOf(This->pSFParent, 1, This->apidl, &dwAttributes);
return dwAttributes & SFGAO_CANRENAME;
}
return FALSE;
}
/**************************************************************************
* ISvItemCm_Constructor()
*/
IContextMenu *ISvItemCm_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, LPCITEMIDLIST *apidl, UINT cidl)
{ ItemCmImpl* cm;
UINT u;
cm = (ItemCmImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ItemCmImpl));
ICOM_VTBL(cm)=&cmvt;
cm->ref = 1;
cm->pidl = ILClone(pidl);
cm->pSFParent = pSFParent;
if(pSFParent) IShellFolder_AddRef(pSFParent);
cm->apidl = _ILCopyaPidl(apidl, cidl);
cm->cidl = cidl;
cm->bAllValues = 1;
for(u = 0; u < cidl; u++)
{
cm->bAllValues &= (_ILIsValue(apidl[u]) ? 1 : 0);
}
TRACE("(%p)->()\n",cm);
shell32_ObjCount++;
return (IContextMenu*)cm;
}
/**************************************************************************
* ISvItemCm_fnQueryInterface
*/
static HRESULT WINAPI ISvItemCm_fnQueryInterface(IContextMenu *iface, REFIID riid, LPVOID *ppvObj)
{
ICOM_THIS(ItemCmImpl, iface);
TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
{
*ppvObj = This;
}
else if(IsEqualIID(riid, &IID_IContextMenu)) /*IContextMenu*/
{
*ppvObj = This;
}
else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/
{
FIXME("-- LPSHELLEXTINIT pointer requested\n");
}
if(*ppvObj)
{
IUnknown_AddRef((IUnknown*)*ppvObj);
TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/**************************************************************************
* ISvItemCm_fnAddRef
*/
static ULONG WINAPI ISvItemCm_fnAddRef(IContextMenu *iface)
{
ICOM_THIS(ItemCmImpl, iface);
TRACE("(%p)->(count=%lu)\n",This, This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
/**************************************************************************
* ISvItemCm_fnRelease
*/
static ULONG WINAPI ISvItemCm_fnRelease(IContextMenu *iface)
{
ICOM_THIS(ItemCmImpl, iface);
TRACE("(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{
TRACE(" destroying IContextMenu(%p)\n",This);
if(This->pSFParent)
IShellFolder_Release(This->pSFParent);
if(This->pidl)
SHFree(This->pidl);
/*make sure the pidl is freed*/
_ILFreeaPidl(This->apidl, This->cidl);
HeapFree(GetProcessHeap(),0,This);
return 0;
}
return This->ref;
}
/**************************************************************************
* ICM_InsertItem()
*/
void WINAPI _InsertMenuItem (
HMENU hmenu,
UINT indexMenu,
BOOL fByPosition,
UINT wID,
UINT fType,
LPSTR dwTypeData,
UINT fState)
{
MENUITEMINFOA mii;
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
if (fType == MFT_SEPARATOR)
{
mii.fMask = MIIM_ID | MIIM_TYPE;
}
else
{
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
mii.dwTypeData = dwTypeData;
mii.fState = fState;
}
mii.wID = wID;
mii.fType = fType;
InsertMenuItemA( hmenu, indexMenu, fByPosition, &mii);
}
/**************************************************************************
* ISvItemCm_fnQueryContextMenu()
*/
static HRESULT WINAPI ISvItemCm_fnQueryContextMenu(
IContextMenu *iface,
HMENU hmenu,
UINT indexMenu,
UINT idCmdFirst,
UINT idCmdLast,
UINT uFlags)
{
ICOM_THIS(ItemCmImpl, iface);
TRACE("(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
if(!(CMF_DEFAULTONLY & uFlags))
{
if(uFlags & CMF_EXPLORE)
{
if(This->bAllValues)
{
_InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Open", MFS_ENABLED);
_InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED|MFS_DEFAULT);
}
else
{
_InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED|MFS_DEFAULT);
_InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Open", MFS_ENABLED);
}
}
else
{
_InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Select", MFS_ENABLED|MFS_DEFAULT);
}
_InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
_InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_COPY, MFT_STRING, "&Copy", MFS_ENABLED);
_InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_CUT, MFT_STRING, "&Cut", MFS_ENABLED);
_InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
_InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_DELETE, MFT_STRING, "&Delete", MFS_ENABLED);
if(uFlags & CMF_CANRENAME)
_InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_RENAME, MFT_STRING, "&Rename", ISvItemCm_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED);
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (FCIDM_SHVIEWLAST));
}
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
}
/**************************************************************************
* DoOpenExplore
*
* for folders only
*/
static void DoOpenExplore(
IContextMenu *iface,
HWND hwnd,
LPCSTR verb)
{
ICOM_THIS(ItemCmImpl, iface);
int i, bFolderFound = FALSE;
LPITEMIDLIST pidlFQ;
SHELLEXECUTEINFOA sei;
/* Find the first item in the list that is not a value. These commands
should never be invoked if there isn't at least one folder item in the list.*/
for(i = 0; i<This->cidl; i++)
{
if(!_ILIsValue(This->apidl[i]))
{
bFolderFound = TRUE;
break;
}
}
if (!bFolderFound) return;
pidlFQ = ILCombine(This->pidl, This->apidl[i]);
ZeroMemory(&sei, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
sei.lpIDList = pidlFQ;
sei.lpClass = "folder";
sei.hwnd = hwnd;
sei.nShow = SW_SHOWNORMAL;
sei.lpVerb = verb;
ShellExecuteExA(&sei);
SHFree(pidlFQ);
}
/**************************************************************************
* DoRename
*/
static void DoRename(
IContextMenu *iface,
HWND hwnd)
{
ICOM_THIS(ItemCmImpl, iface);
LPSHELLBROWSER lpSB;
LPSHELLVIEW lpSV;
TRACE("(%p)->(wnd=%x)\n",This, hwnd);
/* get the active IShellView */
if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0)))
{
if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
{
TRACE("(sv=%p)\n",lpSV);
IShellView_EditItem(lpSV, This->apidl[0]);
IShellView_Release(lpSV);
}
}
}
/**************************************************************************
* DoDelete
*
* deletes the currently selected items
*/
static void DoDelete(
IContextMenu *iface,
IShellView *psv)
{
ICOM_THIS(ItemCmImpl, iface);
ISFHelper * psfhlp;
IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlp);
if (psfhlp)
{
ISFHelper_DeleteItems(psfhlp, This->cidl, This->apidl);
if(psv)
IShellView_Refresh(psv); /* fixme: so long we dont have SHChangeNotify */
ISFHelper_Release(psfhlp);
}
}
/**************************************************************************
* DoCopyOrCut
*
* copys the currently selected items into the clipboard
*/
static BOOL DoCopyOrCut(
IContextMenu *iface,
HWND hwnd,
BOOL bCut)
{
ICOM_THIS(ItemCmImpl, iface);
LPSHELLBROWSER lpSB;
LPSHELLVIEW lpSV;
LPDATAOBJECT lpDo;
TRACE("(%p)->(wnd=0x%04x,bCut=0x%08x)\n",This, hwnd, bCut);
if(GetShellOle())
{
/* get the active IShellView */
if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0)))
{
if (SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
{
if (SUCCEEDED(IShellView_GetItemObject(lpSV, SVGIO_SELECTION, &IID_IDataObject, (LPVOID*)&lpDo)))
{
pOleSetClipboard(lpDo);
IDataObject_Release(lpDo);
}
IShellView_Release(lpSV);
}
}
}
return TRUE;
#if 0
/*
the following code does the copy operation witout ole32.dll
we might need this possibility too (js)
*/
BOOL bSuccess = FALSE;
TRACE("(%p)\n", iface);
if(OpenClipboard(NULL))
{
if(EmptyClipboard())
{
IPersistFolder2 * ppf2;
IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
if (ppf2)
{
LPITEMIDLIST pidl;
IPersistFolder2_GetCurFolder(ppf2, &pidl);
if(pidl)
{
HGLOBAL hMem;
hMem = RenderHDROP(pidl, This->apidl, This->cidl);
if(SetClipboardData(CF_HDROP, hMem))
{
bSuccess = TRUE;
}
SHFree(pidl);
}
IPersistFolder2_Release(ppf2);
}
}
CloseClipboard();
}
return bSuccess;
#endif
}
/**************************************************************************
* ISvItemCm_fnInvokeCommand()
*/
static HRESULT WINAPI ISvItemCm_fnInvokeCommand(
IContextMenu *iface,
LPCMINVOKECOMMANDINFO lpcmi)
{
ICOM_THIS(ItemCmImpl, iface);
LPSHELLBROWSER lpSB;
LPSHELLVIEW lpSV = NULL;
TRACE("(%p)->(invcom=%p verb=%p wnd=%x)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
/* get the active IShellView */
lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0);
/* we are not in a ShellView every time */
if (lpSB) IShellBrowser_QueryActiveShellView(lpSB, &lpSV);
if(LOWORD(lpcmi->lpVerb) > FCIDM_SHVIEWLAST) return E_INVALIDARG;
switch(LOWORD(lpcmi->lpVerb))
{
case FCIDM_SHVIEW_EXPLORE:
DoOpenExplore(iface, lpcmi->hwnd, "explore");
break;
case FCIDM_SHVIEW_OPEN:
DoOpenExplore(iface, lpcmi->hwnd, "open");
break;
case FCIDM_SHVIEW_RENAME:
DoRename(iface, lpcmi->hwnd);
break;
case FCIDM_SHVIEW_DELETE:
DoDelete(iface, lpSV);
break;
case FCIDM_SHVIEW_COPY:
DoCopyOrCut(iface, lpcmi->hwnd, FALSE);
break;
case FCIDM_SHVIEW_CUT:
DoCopyOrCut(iface, lpcmi->hwnd, TRUE);
break;
}
return NOERROR;
}
/**************************************************************************
* ISvItemCm_fnGetCommandString()
*/
static HRESULT WINAPI ISvItemCm_fnGetCommandString(
IContextMenu *iface,
UINT idCommand,
UINT uFlags,
LPUINT lpReserved,
LPSTR lpszName,
UINT uMaxNameLen)
{
ICOM_THIS(ItemCmImpl, iface);
HRESULT hr = E_INVALIDARG;
TRACE("(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
switch(uFlags)
{
case GCS_HELPTEXT:
hr = E_NOTIMPL;
break;
case GCS_VERBA:
switch(idCommand)
{
case FCIDM_SHVIEW_RENAME:
strcpy((LPSTR)lpszName, "rename");
hr = NOERROR;
break;
}
break;
/* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
case, you need to do the lstrcpyW to the pointer passed.*/
case GCS_VERBW:
switch(idCommand)
{ case FCIDM_SHVIEW_RENAME:
lstrcpyAtoW((LPWSTR)lpszName, "rename");
hr = NOERROR;
break;
}
break;
case GCS_VALIDATE:
hr = NOERROR;
break;
}
TRACE("-- (%p)->(name=%s)\n",This, lpszName);
return hr;
}
/**************************************************************************
* ISvItemCm_fnHandleMenuMsg()
* NOTES
* should be only in IContextMenu2 and IContextMenu3
* is nevertheless called from word95
*/
static HRESULT WINAPI ISvItemCm_fnHandleMenuMsg(
IContextMenu *iface,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
ICOM_THIS(ItemCmImpl, iface);
TRACE("(%p)->(msg=%x wp=%x lp=%lx)\n",This, uMsg, wParam, lParam);
return E_NOTIMPL;
}
static struct ICOM_VTABLE(IContextMenu) cmvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
ISvItemCm_fnQueryInterface,
ISvItemCm_fnAddRef,
ISvItemCm_fnRelease,
ISvItemCm_fnQueryContextMenu,
ISvItemCm_fnInvokeCommand,
ISvItemCm_fnGetCommandString,
ISvItemCm_fnHandleMenuMsg,
(void *) 0xdeadbabe /* just paranoia */
};

View File

@ -17,12 +17,6 @@ DEFINE_SHLGUID(IID_IContextMenu, 0x000214E4L, 0, 0);
DEFINE_SHLGUID(IID_IContextMenu2, 0x000214F4L, 0, 0);
typedef struct IContextMenu IContextMenu, *LPCONTEXTMENU;
/* default menu items*/
#define IDM_EXPLORE 0
#define IDM_OPEN 1
#define IDM_RENAME 2
#define IDM_LAST IDM_RENAME
/* QueryContextMenu uFlags */
#define CMF_NORMAL 0x00000000
#define CMF_DEFAULTONLY 0x00000001

View File

@ -62,14 +62,25 @@ typedef struct IShellView IShellView, *LPSHELLVIEW;
#define FCIDM_SHVIEW_UNDO 0x701B
#define FCIDM_SHVIEW_INSERTLINK 0x701C
#define FCIDM_SHVIEW_SELECTALL 0x7021
#define FCIDM_SHVIEW_INVERTSELECTION 0x7022
#define FCIDM_SHVIEW_INVERTSELECTION 0x7022
#define FCIDM_SHVIEW_BIGICON 0x7029
#define FCIDM_SHVIEW_SMALLICON 0x702A
#define FCIDM_SHVIEW_LISTVIEW 0x702B
#define FCIDM_SHVIEW_REPORTVIEW 0x702C
#define FCIDM_SHVIEW_AUTOARRANGE 0x7031
/* 0x7030-0x703f are used by the shellbrowser */
#define FCIDM_SHVIEW_AUTOARRANGE 0x7031
#define FCIDM_SHVIEW_SNAPTOGRID 0x7032
#define FCIDM_SHVIEW_HELP 0x7041
#define FCIDM_SHVIEW_RENAME 0x7050
#define FCIDM_SHVIEW_CREATELINK 0x7051
#define FCIDM_SHVIEW_NEWLINK 0x7052
#define FCIDM_SHVIEW_NEWFOLDER 0x7053
#define FCIDM_SHVIEW_REFRESH 0x7100 /* fixme */
#define FCIDM_SHVIEW_EXPLORE 0x7101 /* fixme */
#define FCIDM_SHVIEW_OPEN 0x7102 /* fixme */
#define FCIDM_SHVIEWLAST 0x7fff
#define FCIDM_BROWSERFIRST 0xA000
@ -121,7 +132,8 @@ typedef enum
ICOM_METHOD3(HRESULT, AddPropertySheetPages, DWORD, dwReserved, LPFNADDPROPSHEETPAGE, lpfn, LPARAM, lparam) \
ICOM_METHOD (HRESULT, SaveViewState) \
ICOM_METHOD2(HRESULT, SelectItem, LPCITEMIDLIST, pidlItem, UINT, uFlags) \
ICOM_METHOD3(HRESULT, GetItemObject, UINT, uItem, REFIID, riid, LPVOID*, ppv)
ICOM_METHOD3(HRESULT, GetItemObject, UINT, uItem, REFIID, riid, LPVOID*, ppv) \
ICOM_METHOD1(HRESULT, EditItem, LPCITEMIDLIST, pidlItem)
#define IShellView_IMETHODS \
IOleWindow_IMETHODS \
IShellView_METHODS
@ -146,6 +158,8 @@ ICOM_DEFINE(IShellView,IOleWindow)
#define IShellView_SaveViewState(p) ICOM_CALL(SaveViewState,p)
#define IShellView_SelectItem(p,a,b) ICOM_CALL2(SelectItem,p,a,b)
#define IShellView_GetItemObject(p,a,b,c) ICOM_CALL3(GetItemObject,p,a,b,c)
/* WINE specific */
#define IShellView_EditItem(p,a) ICOM_CALL1(EditItem,p,a)
#ifdef __cplusplus
} /* extern "C" */

View File

@ -29,9 +29,9 @@ BOOL WINAPI ILGetDisplayName(LPCITEMIDLIST pidl,LPSTR path);
DWORD WINAPI ILFree(LPITEMIDLIST pidl);
LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPSTR lpszPath);
LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPWSTR lpszPath);
LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW (LPVOID lpszPath);
LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPCSTR lpszPath);
LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPCWSTR lpszPath);
LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW (LPCVOID lpszPath);
HRESULT WINAPI SHILCreateFromPathA (LPCSTR path, LPITEMIDLIST * ppidl, DWORD *attributes);
HRESULT WINAPI SHILCreateFromPathW (LPCWSTR path, LPITEMIDLIST * ppidl, DWORD *attributes);