https://git.reactos.org/?p=reactos.git;a=commitdiff;h=730a99c8606c442e1467eb...
commit 730a99c8606c442e1467eb30d5521802e5309361 Author: Mark Jansen mark.jansen@reactos.org AuthorDate: Sat Oct 12 02:11:25 2019 +0200 Commit: Mark Jansen mark.jansen@reactos.org CommitDate: Sat Oct 19 18:42:15 2019 +0200
[SHELL32] Update CDataObject, allowing it to accept new formats and behave a bit more like windows --- dll/win32/shell32/CIDLDataObj.cpp | 283 ++++++++++++++++---------------------- 1 file changed, 116 insertions(+), 167 deletions(-)
diff --git a/dll/win32/shell32/CIDLDataObj.cpp b/dll/win32/shell32/CIDLDataObj.cpp index a28aed1718e..b1704ff9b5a 100644 --- a/dll/win32/shell32/CIDLDataObj.cpp +++ b/dll/win32/shell32/CIDLDataObj.cpp @@ -1,23 +1,9 @@ /* - * IEnumFORMATETC, IDataObject - * - * selecting and droping objects within the shell and/or common dialogs - * - * Copyright 1998, 1999 juergen.schmied@metronet.de - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * PROJECT: shell32 + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: IEnumFORMATETC, IDataObject implementation + * COPYRIGHT: Copyright 1998, 1999 juergen.schmied@metronet.de + * Copyright 2019 Mark Jansen (mark.jansen@reactos.org) */
#include "precomp.h" @@ -65,7 +51,7 @@ IEnumFORMATETCImpl::~IEnumFORMATETCImpl()
HRESULT WINAPI IEnumFORMATETCImpl::Initialize(UINT cfmt, const FORMATETC afmt[]) { - DWORD size; + DWORD size;
size = cfmt * sizeof(FORMATETC); countFmt = cfmt; @@ -83,16 +69,20 @@ HRESULT WINAPI IEnumFORMATETCImpl::Next(ULONG celt, FORMATETC *rgelt, ULONG *pce
TRACE("(%p)->(%u,%p)\n", this, celt, rgelt);
- if(!pFmt)return S_FALSE; - if(!rgelt) return E_INVALIDARG; - if (pceltFethed) *pceltFethed = 0; + if (!pFmt) + return S_FALSE; + if (!rgelt) + return E_INVALIDARG; + if (pceltFethed) + *pceltFethed = 0;
- for(i = 0; posFmt < countFmt && celt > i; i++) + for (i = 0; posFmt < countFmt && celt > i; i++) { - *rgelt++ = pFmt[posFmt++]; + *rgelt++ = pFmt[posFmt++]; }
- if (pceltFethed) *pceltFethed = i; + if (pceltFethed) + *pceltFethed = i;
return ((i == celt) ? S_OK : S_FALSE); } @@ -101,7 +91,8 @@ HRESULT WINAPI IEnumFORMATETCImpl::Skip(ULONG celt) { TRACE("(%p)->(num=%u)\n", this, celt);
- if (posFmt + celt >= countFmt) return S_FALSE; + if (posFmt + celt >= countFmt) + return S_FALSE; posFmt += celt; return S_OK; } @@ -110,19 +101,19 @@ HRESULT WINAPI IEnumFORMATETCImpl::Reset() { TRACE("(%p)->()\n", this);
- posFmt = 0; - return S_OK; + posFmt = 0; + return S_OK; }
HRESULT WINAPI IEnumFORMATETCImpl::Clone(LPENUMFORMATETC* ppenum) { - HRESULT hResult; + HRESULT hResult;
TRACE("(%p)->(ppenum=%p)\n", this, ppenum);
if (!ppenum) return E_INVALIDARG; hResult = IEnumFORMATETC_Constructor(countFmt, pFmt, ppenum); - if (FAILED (hResult)) + if (FAILED_UNEXPECTEDLY(hResult)) return hResult; return (*ppenum)->Skip(posFmt); } @@ -135,34 +126,26 @@ HRESULT IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[], IEnumFORMA
/*********************************************************************** * IDataObject implementation +* For now (2019-10-12) it's compatible with 2k3's data object +* See shell32_apitest!CIDLData for changes between versions */
-/* number of supported formats */ -#define MAX_FORMATS 5 - class CIDLDataObj : public CComObjectRootEx<CComMultiThreadModelNoCS>, public IDataObject, public IAsyncOperation { private: - LPITEMIDLIST pidl; - PIDLIST_RELATIVE *apidl; - UINT cidl; - DWORD dropeffect; - - FORMATETC pFormatEtc[MAX_FORMATS]; - UINT cfShellIDList; - UINT cfFileNameA; - UINT cfFileNameW; - UINT cfPreferredDropEffect; - BOOL doasync; + CSimpleArray<FORMATETC> m_Formats; + CSimpleArray<STGMEDIUM> m_Storage; + UINT m_cfShellIDList; + BOOL m_doasync; public: CIDLDataObj(); ~CIDLDataObj(); HRESULT WINAPI Initialize(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidlx, UINT cidlx);
- /////////// + // *** IDataObject methods *** virtual HRESULT WINAPI GetData(LPFORMATETC pformatetcIn, STGMEDIUM *pmedium); virtual HRESULT WINAPI GetDataHere(LPFORMATETC pformatetc, STGMEDIUM *pmedium); virtual HRESULT WINAPI QueryGetData(LPFORMATETC pformatetc); @@ -172,10 +155,12 @@ public: virtual HRESULT WINAPI DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection); virtual HRESULT WINAPI DUnadvise(DWORD dwConnection); virtual HRESULT WINAPI EnumDAdvise(IEnumSTATDATA **ppenumAdvise); - virtual HRESULT WINAPI GetAsyncMode(BOOL *pfIsOpAsync); - virtual HRESULT WINAPI InOperation(BOOL *pfInAsyncOp); + + // *** IAsyncOperation methods *** virtual HRESULT WINAPI SetAsyncMode(BOOL fDoOpAsync); + virtual HRESULT WINAPI GetAsyncMode(BOOL *pfIsOpAsync); virtual HRESULT WINAPI StartOperation(IBindCtx *pbcReserved); + virtual HRESULT WINAPI InOperation(BOOL *pfInAsyncOp); virtual HRESULT WINAPI EndOperation(HRESULT hResult, IBindCtx *pbcReserved, DWORD dwEffects);
BEGIN_COM_MAP(CIDLDataObj) @@ -186,107 +171,71 @@ END_COM_MAP()
CIDLDataObj::CIDLDataObj() { - pidl = NULL; - apidl = NULL; - cidl = 0; - dropeffect = 0; - cfShellIDList = 0; - cfFileNameA = 0; - cfFileNameW = 0; - cfPreferredDropEffect = 0; - doasync = FALSE; + m_cfShellIDList = 0; + m_doasync = FALSE; }
CIDLDataObj::~CIDLDataObj() { - TRACE(" destroying IDataObject(%p)\n",this); - _ILFreeaPidl(apidl, cidl); - ILFree(pidl); + TRACE(" destroying IDataObject(%p)\n", this); + + for (int n = 0; n < m_Storage.GetSize(); ++n) + { + ReleaseStgMedium(&m_Storage[n]); + } + m_Formats.RemoveAll(); + m_Storage.RemoveAll(); }
HRESULT WINAPI CIDLDataObj::Initialize(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidlx, UINT cidlx) { - pidl = ILClone(pMyPidl); - apidl = _ILCopyaPidl(apidlx, cidlx); - if (pidl == NULL || apidl == NULL) + HGLOBAL hida = RenderSHELLIDLIST((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx); + if (!hida) + { + ERR("Failed to render " CFSTR_SHELLIDLISTA "\n"); return E_OUTOFMEMORY; - cidl = cidlx; - dropeffect = DROPEFFECT_COPY; - - cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST); - cfFileNameA = RegisterClipboardFormatA(CFSTR_FILENAMEA); - cfFileNameW = RegisterClipboardFormatW(CFSTR_FILENAMEW); - cfPreferredDropEffect = RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECTW); - InitFormatEtc(pFormatEtc[0], cfShellIDList, TYMED_HGLOBAL); - InitFormatEtc(pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL); - InitFormatEtc(pFormatEtc[2], cfFileNameA, TYMED_HGLOBAL); - InitFormatEtc(pFormatEtc[3], cfFileNameW, TYMED_HGLOBAL); - InitFormatEtc(pFormatEtc[4], cfPreferredDropEffect, TYMED_HGLOBAL); - return S_OK; -} + }
-static HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags) -{ - DWORD * pdwFlag; - HGLOBAL hGlobal; + m_cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
- TRACE("(0x%08x)\n", dwFlags); + FORMATETC HIDAFormat = { (CLIPFORMAT)m_cfShellIDList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM medium = {0}; + medium.tymed = TYMED_HGLOBAL; + medium.hGlobal = hida;
- hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD)); - if(!hGlobal) return hGlobal; - pdwFlag = (DWORD*)GlobalLock(hGlobal); - *pdwFlag = dwFlags; - GlobalUnlock(hGlobal); - return hGlobal; + return SetData(&HIDAFormat, &medium, TRUE); }
-/************************************************************************** -* IDataObject_fnGetData -*/ + HRESULT WINAPI CIDLDataObj::GetData(LPFORMATETC pformatetcIn, STGMEDIUM *pmedium) { - char szTemp[256]; - - szTemp[0] = 0; - GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256); - TRACE("(%p)->(%p %p format=%s)\n", this, pformatetcIn, pmedium, szTemp); - - if (pformatetcIn->cfFormat == cfShellIDList) - { - if (cidl < 1) return(E_UNEXPECTED); - pmedium->hGlobal = RenderSHELLIDLIST(pidl, apidl, cidl); - } - else if (pformatetcIn->cfFormat == CF_HDROP) + if (TRACE_ON(shell)) { - if (cidl < 1) return(E_UNEXPECTED); - pmedium->hGlobal = RenderHDROP(pidl, apidl, cidl); + char szTemp[256] = {0}; + GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256); + TRACE("(%p)->(%p %p format=%s)\n", this, pformatetcIn, pmedium, szTemp); } - else if (pformatetcIn->cfFormat == cfFileNameA) + for (int n = 0; n < m_Formats.GetSize(); ++n) { - if (cidl < 1) return(E_UNEXPECTED); - pmedium->hGlobal = RenderFILENAMEA(pidl, apidl, cidl); + const FORMATETC& fmt = m_Formats[n]; + if (fmt.cfFormat == pformatetcIn->cfFormat && + fmt.dwAspect == pformatetcIn->dwAspect && + fmt.tymed == pformatetcIn->tymed) + { + if (pformatetcIn->tymed != TYMED_HGLOBAL) + { + UNIMPLEMENTED; + return E_INVALIDARG; + } + else + { + *pmedium = m_Storage[n]; + return QueryInterface(IID_PPV_ARG(IUnknown, &pmedium->pUnkForRelease)); + } + } } - else if (pformatetcIn->cfFormat == cfFileNameW) - { - if (cidl < 1) return(E_UNEXPECTED); - pmedium->hGlobal = RenderFILENAMEW(pidl, apidl, cidl); - } - else if (pformatetcIn->cfFormat == cfPreferredDropEffect) - { - pmedium->hGlobal = RenderPREFEREDDROPEFFECT(dropeffect); - } - else - { - FIXME("-- expected clipformat not implemented\n"); - return (E_INVALIDARG); - } - if (pmedium->hGlobal) - { - pmedium->tymed = TYMED_HGLOBAL; - pmedium->pUnkForRelease = NULL; - return S_OK; - } - return E_OUTOFMEMORY; + + return E_INVALIDARG; }
HRESULT WINAPI CIDLDataObj::GetDataHere(LPFORMATETC pformatetc, STGMEDIUM *pmedium) @@ -297,49 +246,50 @@ HRESULT WINAPI CIDLDataObj::GetDataHere(LPFORMATETC pformatetc, STGMEDIUM *pmedi
HRESULT WINAPI CIDLDataObj::QueryGetData(LPFORMATETC pformatetc) { - UINT i; - TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", this, pformatetc->cfFormat, pformatetc->tymed);
- if(!(DVASPECT_CONTENT & pformatetc->dwAspect)) - return DV_E_DVASPECT; - - /* check our formats table what we have */ - for (i=0; i<MAX_FORMATS; i++) + for (int n = 0; n < m_Formats.GetSize(); ++n) { - if ((pFormatEtc[i].cfFormat == pformatetc->cfFormat) - && (pFormatEtc[i].tymed == pformatetc->tymed)) - { - return S_OK; - } + const FORMATETC& fmt = m_Formats[n]; + if (fmt.cfFormat == pformatetc->cfFormat && + fmt.dwAspect == pformatetc->dwAspect && + fmt.tymed == pformatetc->tymed) + { + return S_OK; + } }
- return DV_E_TYMED; + return S_FALSE; }
HRESULT WINAPI CIDLDataObj::GetCanonicalFormatEtc(LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut) { - FIXME("(%p)->()\n", this); - return E_NOTIMPL; + //FIXME("(%p)->()\n", this); + return DATA_S_SAMEFORMATETC; }
HRESULT WINAPI CIDLDataObj::SetData(LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease) { - if (pformatetc->cfFormat == cfPreferredDropEffect) + if (!fRelease) + return E_INVALIDARG; + + for (int n = 0; n < m_Formats.GetSize(); ++n) { - const DWORD *src = (const DWORD *)GlobalLock(pmedium->hGlobal); - if (src != 0) - { - dropeffect = *src; - GlobalUnlock(pmedium->hGlobal); - return S_OK; - } - FIXME("Error setting data"); - return E_FAIL; + const FORMATETC& fmt = m_Formats[n]; + if (fmt.cfFormat == pformatetc->cfFormat && + fmt.dwAspect == pformatetc->dwAspect && + fmt.tymed == pformatetc->tymed) + { + ReleaseStgMedium(&m_Storage[n]); + m_Storage[n] = *pmedium; + return S_OK; + } }
- FIXME("(%p)->()\n", this); - return E_NOTIMPL; + m_Formats.Add(*pformatetc); + m_Storage.Add(*pmedium); + + return S_OK; }
HRESULT WINAPI CIDLDataObj::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc) @@ -350,7 +300,7 @@ HRESULT WINAPI CIDLDataObj::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **pp /* only get data */ if (DATADIR_GET == dwDirection) { - return IEnumFORMATETC_Constructor(MAX_FORMATS, pFormatEtc, ppenumFormatEtc); + return IEnumFORMATETC_Constructor(m_Formats.GetSize(), m_Formats.GetData(), ppenumFormatEtc); }
return E_NOTIMPL; @@ -358,26 +308,23 @@ HRESULT WINAPI CIDLDataObj::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **pp
HRESULT WINAPI CIDLDataObj::DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection) { - FIXME("(%p)->()\n", this); - return E_NOTIMPL; + return OLE_E_ADVISENOTSUPPORTED; }
HRESULT WINAPI CIDLDataObj::DUnadvise(DWORD dwConnection) { - FIXME("(%p)->()\n", this); - return E_NOTIMPL; + return OLE_E_ADVISENOTSUPPORTED; }
HRESULT WINAPI CIDLDataObj::EnumDAdvise(IEnumSTATDATA **ppenumAdvise) { - FIXME("(%p)->()\n", this); - return E_NOTIMPL; + return OLE_E_ADVISENOTSUPPORTED; }
HRESULT WINAPI CIDLDataObj::GetAsyncMode(BOOL *pfIsOpAsync) { TRACE("(%p)->()\n", this); - *pfIsOpAsync = doasync; + *pfIsOpAsync = m_doasync; return S_OK; } HRESULT WINAPI CIDLDataObj::InOperation(BOOL *pfInAsyncOp) @@ -388,7 +335,7 @@ HRESULT WINAPI CIDLDataObj::InOperation(BOOL *pfInAsyncOp) HRESULT WINAPI CIDLDataObj::SetAsyncMode(BOOL fDoOpAsync) { TRACE("(%p)->()\n", this); - doasync = fDoOpAsync; + m_doasync = fDoOpAsync; return S_OK; }
@@ -406,8 +353,8 @@ HRESULT WINAPI CIDLDataObj::EndOperation(HRESULT hResult, IBindCtx *pbcReserved,
/************************************************************************** -* IDataObject_Constructor -*/ + * IDataObject_Constructor + */ HRESULT IDataObject_Constructor(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidl, UINT cidl, IDataObject **dataObject) { if (!dataObject) @@ -424,6 +371,8 @@ HRESULT WINAPI SHCreateDataObject(PCIDLIST_ABSOLUTE pidlFolder, UINT cidl, PCUIT { if (IsEqualIID(riid, IID_IDataObject)) { + if (pdtInner) + UNIMPLEMENTED; return CIDLData_CreateFromIDArray(pidlFolder, cidl, apidl, (IDataObject **)ppv); } return E_FAIL;