wine/dlls/shell32/dataobject.c
Juergen Schmied 0ae30d3027 - adjusted printing of refcounts to be equal
- cleaning up icon cache on PROCESS_DETACH
- fixed ascii/unicode use in SH/ILCreateFromPath
- fixed small memory leak in shellview
1999-03-28 12:35:24 +00:00

467 lines
14 KiB
C

/*
* IEnumFORMATETC, IDataObject
*
* selecting and droping objects within the shell and/or common dialogs
*
* Copyright 1998 <juergen.schmied@metronet.de>
*/
#include <string.h>
#include "oleidl.h"
#include "pidl.h"
#include "winerror.h"
#include "shell32_main.h"
#include "debug.h"
UINT cfShellIDList=0;
UINT cfFileGroupDesc=0;
UINT cfFileContents=0;
/***********************************************************************
* IEnumFORMATETC implementation
*/
typedef struct
{
/* IUnknown fields */
ICOM_VTABLE(IEnumFORMATETC)* lpvtbl;
DWORD ref;
/* IEnumFORMATETC fields */
UINT posFmt;
UINT countFmt;
LPFORMATETC pFmt;
} IEnumFORMATETCImpl;
static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed);
static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
{
IEnumFORMATETC_fnQueryInterface,
IEnumFORMATETC_fnAddRef,
IEnumFORMATETC_fnRelease,
IEnumFORMATETC_fnNext,
IEnumFORMATETC_fnSkip,
IEnumFORMATETC_fnReset,
IEnumFORMATETC_fnClone
};
LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
{
IEnumFORMATETCImpl* ef;
DWORD size=cfmt * sizeof(FORMATETC);
ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumFORMATETCImpl));
ef->ref=1;
ef->lpvtbl=&efvt;
ef->posFmt = 0;
ef->countFmt = cfmt;
ef->pFmt = SHAlloc (size);
if (ef->pFmt)
{ memcpy(ef->pFmt, afmt, size);
}
TRACE(shell,"(%p)->()\n",ef);
shell32_ObjCount++;
return (LPENUMFORMATETC)ef;
}
static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
{
ICOM_THIS(IEnumFORMATETCImpl,iface);
char xriid[50];
WINE_StringFromCLSID((LPCLSID)riid,xriid);
TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown))
{ *ppvObj = This;
}
else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
{ *ppvObj = (IDataObject*)This;
}
if(*ppvObj)
{ IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE(shell,"-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
{
ICOM_THIS(IEnumFORMATETCImpl,iface);
TRACE(shell,"(%p)->(count=%lu)\n",This, This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
{
ICOM_THIS(IEnumFORMATETCImpl,iface);
TRACE(shell,"(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{ TRACE(shell," destroying IEnumFORMATETC(%p)\n",This);
if (This->pFmt)
{ SHFree (This->pFmt);
}
HeapFree(GetProcessHeap(),0,This);
return 0;
}
return This->ref;
}
static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
{
ICOM_THIS(IEnumFORMATETCImpl,iface);
UINT cfetch;
HRESULT hres = S_FALSE;
TRACE (shell, "(%p)->()\n", This);
if (This->posFmt < This->countFmt)
{ cfetch = This->countFmt - This->posFmt;
if (cfetch >= celt)
{ cfetch = celt;
hres = S_OK;
}
memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
This->posFmt += cfetch;
}
else
{ cfetch = 0;
}
if (pceltFethed)
{ *pceltFethed = cfetch;
}
return hres;
}
static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
{
ICOM_THIS(IEnumFORMATETCImpl,iface);
FIXME (shell, "(%p)->(num=%lu)\n", This, celt);
This->posFmt += celt;
if (This->posFmt > This->countFmt)
{ This->posFmt = This->countFmt;
return S_FALSE;
}
return S_OK;
}
static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
{
ICOM_THIS(IEnumFORMATETCImpl,iface);
FIXME (shell, "(%p)->()\n", This);
This->posFmt = 0;
return S_OK;
}
static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
{
ICOM_THIS(IEnumFORMATETCImpl,iface);
FIXME (shell, "(%p)->(ppenum=%p)\n", This, ppenum);
return E_NOTIMPL;
}
/***********************************************************************
* IDataObject implementation
*/
typedef struct
{
/* IUnknown fields */
ICOM_VTABLE(IDataObject)* lpvtbl;
DWORD ref;
/* IDataObject fields */
LPSHELLFOLDER psf;
LPIDLLIST lpill; /* the data of the dataobject */
LPITEMIDLIST pidl;
} IDataObjectImpl;
static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID* ppvObj);
static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface);
static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface);
static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM* pmedium);
static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM* pmedium);
static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc);
static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut);
static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM* pmedium, BOOL fRelease);
static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc);
static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection);
static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection);
static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise);
static struct ICOM_VTABLE(IDataObject) dtovt =
{
IDataObject_fnQueryInterface,
IDataObject_fnAddRef,
IDataObject_fnRelease,
IDataObject_fnGetData,
IDataObject_fnGetDataHere,
IDataObject_fnQueryGetData,
IDataObject_fnGetCanonicalFormatEtc,
IDataObject_fnSetData,
IDataObject_fnEnumFormatEtc,
IDataObject_fnDAdvise,
IDataObject_fnDUnadvise,
IDataObject_fnEnumDAdvise
};
/**************************************************************************
* IDataObject_Constructor
*/
LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPSHELLFOLDER psf, LPITEMIDLIST * apidl, UINT cidl)
{
IDataObjectImpl* dto;
if (!(dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDataObjectImpl))))
return NULL;
dto->ref=1;
dto->lpvtbl=&dtovt;
dto->psf=psf;
dto->pidl=ILClone(((IGenericSFImpl*)psf)->pMyPidl); /* FIXME:add a reference and don't copy*/
/* fill the ItemID List List */
dto->lpill = IDLList_Constructor (8);
if (! dto->lpill )
return NULL;
dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl);
TRACE(shell,"(%p)->(sf=%p apidl=%p cidl=%u)\n",dto, psf, apidl, cidl);
shell32_ObjCount++;
return (LPDATAOBJECT)dto;
}
/***************************************************************************
* IDataObject_QueryInterface
*/
static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
{
ICOM_THIS(IDataObjectImpl,iface);
char xriid[50];
WINE_StringFromCLSID((LPCLSID)riid,xriid);
TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
{ *ppvObj = This;
}
else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
{ *ppvObj = (IDataObject*)This;
}
if(*ppvObj)
{ IDataObject_AddRef((IDataObject*)*ppvObj);
TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE(shell,"-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/**************************************************************************
* IDataObject_AddRef
*/
static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
{
ICOM_THIS(IDataObjectImpl,iface);
TRACE(shell,"(%p)->(count=%lu)\n",This, This->ref);
shell32_ObjCount++;
return ++(This->ref);
}
/**************************************************************************
* IDataObject_Release
*/
static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
{
ICOM_THIS(IDataObjectImpl,iface);
TRACE(shell,"(%p)->()\n",This);
shell32_ObjCount--;
if (!--(This->ref))
{ TRACE(shell," destroying IDataObject(%p)\n",This);
IDLList_Destructor(This->lpill);
HeapFree(GetProcessHeap(),0,This);
return 0;
}
return This->ref;
}
/**************************************************************************
* DATAOBJECT_InitShellIDList (internal)
*
* NOTES
* get or register the "Shell IDList Array" clipformat
*/
static BOOL DATAOBJECT_InitShellIDList(void)
{ if (cfShellIDList)
{ return(TRUE);
}
cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
return(cfShellIDList != 0);
}
/**************************************************************************
* DATAOBJECT_InitFileGroupDesc (internal)
*
* NOTES
* get or register the "FileGroupDescriptor" clipformat
*/
/* FIXME: DATAOBJECT_InitFileGroupDesc is not used (19981226)
static BOOL32 DATAOBJECT_InitFileGroupDesc(void)
{ if (cfFileGroupDesc)
{ return(TRUE);
}
cfFileGroupDesc = RegisterClipboardFormatA(CFSTR_FILEDESCRIPTORA);
return(cfFileGroupDesc != 0);
}
*/
/**************************************************************************
* DATAOBJECT_InitFileContents (internal)
*
* NOTES
* get or register the "FileContents" clipformat
*/
/* FIXME: DATAOBJECT_InitFileContents is not used (19981226)
static BOOL32 DATAOBJECT_InitFileContents(void)
{ if (cfFileContents)
{ return(TRUE);
}
cfFileContents = RegisterClipboardFormatA(CFSTR_FILECONTENTS);
return(cfFileContents != 0);
}
*/
/**************************************************************************
* interface implementation
*/
static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
{
ICOM_THIS(IDataObjectImpl,iface);
char temp[256];
UINT cItems;
DWORD size, size1, size2;
LPITEMIDLIST pidl;
LPCIDA pcida;
HGLOBAL hmem;
GetClipboardFormatNameA (pformatetcIn->cfFormat, temp, 256);
WARN (shell, "(%p)->(%p %p format=%s)semi-stub\n", This, pformatetcIn, pmedium, temp);
if (!DATAOBJECT_InitShellIDList()) /* is the clipformat registred? */
{ return(E_UNEXPECTED);
}
if (pformatetcIn->cfFormat == cfShellIDList)
{ if (pformatetcIn->ptd==NULL
&& (pformatetcIn->dwAspect & DVASPECT_CONTENT)
&& pformatetcIn->lindex==-1
&& (pformatetcIn->tymed&TYMED_HGLOBAL))
{ cItems = This->lpill->lpvtbl->fnGetCount(This->lpill);
if (cItems < 1)
{ return(E_UNEXPECTED);
}
pidl = This->lpill->lpvtbl->fnGetElement(This->lpill, 0);
pdump(This->pidl);
pdump(pidl);
/*hack consider only the first item*/
cItems = 2;
size = sizeof(CIDA) + sizeof (UINT)*(cItems-1);
size1 = ILGetSize (This->pidl);
size2 = ILGetSize (pidl);
hmem = GlobalAlloc(GMEM_FIXED, size+size1+size2);
pcida = GlobalLock (hmem);
if (!pcida)
{ return(E_OUTOFMEMORY);
}
pcida->cidl = 1;
pcida->aoffset[0] = size;
pcida->aoffset[1] = size+size1;
TRACE(shell,"-- %lu %lu %lu\n",size, size1, size2 );
TRACE(shell,"-- %p %p\n",This->pidl, pidl);
TRACE(shell,"-- %p %p %p\n",pcida, (LPBYTE)pcida+size,(LPBYTE)pcida+size+size1);
memcpy ((LPBYTE)pcida+size, This->pidl, size1);
memcpy ((LPBYTE)pcida+size+size1, pidl, size2);
TRACE(shell,"-- after copy\n");
GlobalUnlock(hmem);
pmedium->tymed = TYMED_HGLOBAL;
pmedium->u.hGlobal = (HGLOBAL)pcida;
pmedium->pUnkForRelease = NULL;
TRACE(shell,"-- ready\n");
return(NOERROR);
}
}
FIXME (shell, "-- clipformat not implemented\n");
return (E_INVALIDARG);
}
static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
{
ICOM_THIS(IDataObjectImpl,iface);
FIXME (shell, "(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
{
ICOM_THIS(IDataObjectImpl,iface);
FIXME (shell, "(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
{
ICOM_THIS(IDataObjectImpl,iface);
FIXME (shell, "(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
{
ICOM_THIS(IDataObjectImpl,iface);
FIXME (shell, "(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
{
ICOM_THIS(IDataObjectImpl,iface);
FIXME (shell, "(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
ICOM_THIS(IDataObjectImpl,iface);
FIXME (shell, "(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
{
ICOM_THIS(IDataObjectImpl,iface);
FIXME (shell, "(%p)->()\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
{
ICOM_THIS(IDataObjectImpl,iface);
FIXME (shell, "(%p)->()\n", This);
return E_NOTIMPL;
}