/* * IEnumFORMATETC, IDataObject * * selecting and droping objects within the shell and/or common dialogs * * Copyright 1998 */ #include #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; }