From: Zebediah Figura zfigura@codeweavers.com
--- dlls/shell32/tests/shlfolder.c | 236 +++++++++++++++++++++++++++++++-- 1 file changed, 223 insertions(+), 13 deletions(-)
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 55ee8235f73..eb77e2113f3 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -5259,22 +5259,126 @@ static void test_SHCreateDefaultContextMenu(void) Cleanup(); }
+static void test_enum_format(IDataObject *data_obj) +{ + IEnumFORMATETC *enum1, *enum2; + FORMATETC formats[4]; + STGMEDIUM medium; + ULONG count, ref; + HRESULT hr; + + hr = IDataObject_EnumFormatEtc(data_obj, DATADIR_GET, &enum1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IEnumFORMATETC_Next(enum1, 1, formats, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Next(enum1, 1, formats, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Next(enum1, 1, formats, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Next(enum1, 1, formats, NULL); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + hr = IEnumFORMATETC_Reset(enum1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + count = 0xdeadbeef; + hr = IEnumFORMATETC_Next(enum1, 1, formats, &count); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(count == 1, "Got count %lu.\n", count); + hr = IEnumFORMATETC_Next(enum1, 1, formats, &count); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(count == 1, "Got count %lu.\n", count); + hr = IEnumFORMATETC_Next(enum1, 1, formats, &count); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(count == 1, "Got count %lu.\n", count); + hr = IEnumFORMATETC_Next(enum1, 1, formats, &count); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + todo_wine ok(!count, "Got count %lu.\n", count); + + hr = IEnumFORMATETC_Reset(enum1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IEnumFORMATETC_Next(enum1, 2, formats, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Next(enum1, 2, formats, &count); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + todo_wine ok(count == 1, "Got count %lu.\n", count); + + hr = IEnumFORMATETC_Reset(enum1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IEnumFORMATETC_Next(enum1, 4, formats, &count); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + todo_wine ok(count == 3, "Got count %lu.\n", count); + + hr = IEnumFORMATETC_Clone(enum1, &enum2); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IEnumFORMATETC_Reset(enum1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Skip(enum1, 4); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Skip(enum1, 1); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Reset(enum1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Skip(enum1, 3); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Skip(enum1, 1); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Next(enum1, 1, formats, NULL); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Next(enum2, 1, formats, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + /* Adding another format does not affect existing enum objects. */ + medium.tymed = TYMED_HGLOBAL; + medium.pUnkForRelease = NULL; + medium.hGlobal = GlobalAlloc(GMEM_MOVEABLE, 1); + formats[0].cfFormat = RegisterClipboardFormatW(L"bogus_format2"); + formats[0].ptd = NULL; + formats[0].dwAspect = DVASPECT_CONTENT; + formats[0].lindex = -1; + formats[0].tymed = TYMED_HGLOBAL; + hr = IDataObject_SetData(data_obj, &formats[0], &medium, TRUE); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IEnumFORMATETC_Reset(enum1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Next(enum1, 4, formats, &count); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + todo_wine ok(count == 3, "Got count %lu.\n", count); + + ref = IEnumFORMATETC_Release(enum1); + ok(!ref, "Got outstanding refcount %ld.\n", ref); + ref = IEnumFORMATETC_Release(enum2); + ok(!ref, "Got outstanding refcount %ld.\n", ref); +} + static void test_DataObject(void) { + IEnumFORMATETC *enum_format; IShellFolder *desktop; IDataObject *data_obj; - HRESULT hres; + WCHAR format_name[50]; + HRESULT hr; IEnumIDList *peidl; LPITEMIDLIST apidl; FORMATETC fmt; DWORD cf_shellidlist; STGMEDIUM medium; + HGLOBAL global; + int *value; + int ret; + + static const DWORD enum_directions[] = {DATADIR_GET, DATADIR_SET};
SHGetDesktopFolder(&desktop);
- hres = IShellFolder_EnumObjects(desktop, NULL, + hr = IShellFolder_EnumObjects(desktop, NULL, SHCONTF_NONFOLDERS|SHCONTF_FOLDERS|SHCONTF_INCLUDEHIDDEN, &peidl); - ok(hres == S_OK, "got %lx\n", hres); + ok(hr == S_OK, "Got hr %#lx.\n", hr);
if(IEnumIDList_Next(peidl, 1, &apidl, NULL) != S_OK) { skip("no files on desktop - skipping GetDataObject tests\n"); @@ -5284,9 +5388,9 @@ static void test_DataObject(void) } IEnumIDList_Release(peidl);
- hres = IShellFolder_GetUIObjectOf(desktop, NULL, 1, (LPCITEMIDLIST*)&apidl, + hr = IShellFolder_GetUIObjectOf(desktop, NULL, 1, (LPCITEMIDLIST*)&apidl, &IID_IDataObject, NULL, (void**)&data_obj); - ok(hres == S_OK, "got %lx\n", hres); + ok(hr == S_OK, "Got hr %#lx.\n", hr); ILFree(apidl); IShellFolder_Release(desktop);
@@ -5296,23 +5400,129 @@ static void test_DataObject(void) fmt.dwAspect = DVASPECT_CONTENT; fmt.lindex = -1; fmt.tymed = TYMED_HGLOBAL; - hres = IDataObject_QueryGetData(data_obj, &fmt); - ok(hres == S_OK, "got %lx\n", hres); + hr = IDataObject_QueryGetData(data_obj, &fmt); + ok(hr == S_OK, "Got hr %#lx.\n", hr);
fmt.tymed = TYMED_HGLOBAL | TYMED_ISTREAM; - hres = IDataObject_QueryGetData(data_obj, &fmt); - ok(hres == S_OK, "got %lx\n", hres); + hr = IDataObject_QueryGetData(data_obj, &fmt); + ok(hr == S_OK, "Got hr %#lx.\n", hr);
fmt.tymed = TYMED_ISTREAM; - hres = IDataObject_QueryGetData(data_obj, &fmt); - todo_wine ok(hres == S_FALSE, "got %lx\n", hres); + hr = IDataObject_QueryGetData(data_obj, &fmt); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + hr = IDataObject_GetData(data_obj, &fmt, &medium); + todo_wine ok(hr == DV_E_FORMATETC, "Got hr %#lx.\n", hr);
fmt.tymed = TYMED_HGLOBAL | TYMED_ISTREAM; - hres = IDataObject_GetData(data_obj, &fmt, &medium); - ok(hres == S_OK, "got %lx\n", hres); + hr = IDataObject_GetData(data_obj, &fmt, &medium); + ok(hr == S_OK, "Got hr %#lx.\n", hr); ok(medium.tymed == TYMED_HGLOBAL, "medium.tymed = %lx\n", medium.tymed); ReleaseStgMedium(&medium);
+ fmt.cfFormat = RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECTW); + hr = IDataObject_GetData(data_obj, &fmt, &medium); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr == S_OK) + { + ok(medium.tymed == TYMED_HGLOBAL, "medium.tymed = %lx\n", medium.tymed); + value = GlobalLock(medium.hGlobal); + ok(*value == DROPEFFECT_LINK, "Got value %#x.\n", *value); + GlobalUnlock(medium.hGlobal); + ReleaseStgMedium(&medium); + } + + fmt.cfFormat = CF_HDROP; + hr = IDataObject_GetData(data_obj, &fmt, &medium); + todo_wine ok(hr == DV_E_FORMATETC, "Got hr %#lx.\n", hr); + fmt.cfFormat = RegisterClipboardFormatA(CFSTR_FILENAMEA); + hr = IDataObject_GetData(data_obj, &fmt, &medium); + todo_wine ok(hr == DV_E_FORMATETC, "Got hr %#lx.\n", hr); + fmt.cfFormat = RegisterClipboardFormatW(CFSTR_FILENAMEW); + hr = IDataObject_GetData(data_obj, &fmt, &medium); + todo_wine ok(hr == DV_E_FORMATETC, "Got hr %#lx.\n", hr); + + fmt.cfFormat = RegisterClipboardFormatW(L"bogus_format"); + + hr = IDataObject_QueryGetData(data_obj, &fmt); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + hr = IDataObject_GetData(data_obj, &fmt, &medium); + todo_wine ok(hr == DV_E_FORMATETC, "Got hr %#lx.\n", hr); + + global = GlobalAlloc(GMEM_MOVEABLE, sizeof(*value)); + value = GlobalLock(global); + *value = 0xabacab; + GlobalUnlock(global); + medium.tymed = TYMED_HGLOBAL; + medium.pUnkForRelease = NULL; + medium.hGlobal = global; + fmt.tymed = TYMED_HGLOBAL; + hr = IDataObject_SetData(data_obj, &fmt, &medium, FALSE); + todo_wine ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr); + hr = IDataObject_SetData(data_obj, &fmt, &medium, TRUE); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDataObject_QueryGetData(data_obj, &fmt); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + memset(&medium, 0xcc, sizeof(medium)); + hr = IDataObject_GetData(data_obj, &fmt, &medium); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr == S_OK) + { + ok(medium.hGlobal && medium.hGlobal != global, "Got global %p.\n", medium.hGlobal); + value = GlobalLock(medium.hGlobal); + ok(*value == 0xabacab, "Got value %#x.\n", *value); + GlobalUnlock(medium.hGlobal); + ReleaseStgMedium(&medium); + } + + for (unsigned int i = 0; i < ARRAY_SIZE(enum_directions); ++i) + { + hr = IDataObject_EnumFormatEtc(data_obj, enum_directions[i], &enum_format); + todo_wine_if (enum_directions[i] == DATADIR_SET) + ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr != S_OK) + continue; + + memset(&fmt, 0xcc, sizeof(fmt)); + hr = IEnumFORMATETC_Next(enum_format, 1, &fmt, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ret = GetClipboardFormatNameW(fmt.cfFormat, format_name, ARRAY_SIZE(format_name)); + ok(ret > 0, "Got %d.\n",ret); + ok(!wcscmp(format_name, CFSTR_SHELLIDLISTW), "Got clipboard format %s.\n", debugstr_w(format_name)); + ok(!fmt.ptd, "Got target device %p.\n", fmt.ptd); + ok(fmt.dwAspect == DVASPECT_CONTENT, "Got aspect %#lx.\n", fmt.dwAspect); + ok(fmt.lindex == -1, "Got index %ld.\n", fmt.lindex); + ok(fmt.tymed == TYMED_HGLOBAL, "Got tymed %#lx.\n", fmt.tymed); + + hr = IEnumFORMATETC_Next(enum_format, 1, &fmt, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ret = GetClipboardFormatNameW(fmt.cfFormat, format_name, ARRAY_SIZE(format_name)); + todo_wine ok(ret > 0, "Got %d.\n",ret); + if (ret > 0) + ok(!wcscmp(format_name, CFSTR_PREFERREDDROPEFFECTW), "Got clipboard format %s.\n", debugstr_w(format_name)); + ok(!fmt.ptd, "Got target device %p.\n", fmt.ptd); + ok(fmt.dwAspect == DVASPECT_CONTENT, "Got aspect %#lx.\n", fmt.dwAspect); + ok(fmt.lindex == -1, "Got index %ld.\n", fmt.lindex); + ok(fmt.tymed == TYMED_HGLOBAL, "Got tymed %#lx.\n", fmt.tymed); + + hr = IEnumFORMATETC_Next(enum_format, 1, &fmt, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ret = GetClipboardFormatNameW(fmt.cfFormat, format_name, ARRAY_SIZE(format_name)); + ok(ret > 0, "Got %d.\n",ret); + todo_wine ok(!wcscmp(format_name, L"bogus_format"), "Got clipboard format %s.\n", debugstr_w(format_name)); + ok(!fmt.ptd, "Got target device %p.\n", fmt.ptd); + ok(fmt.dwAspect == DVASPECT_CONTENT, "Got aspect %#lx.\n", fmt.dwAspect); + ok(fmt.lindex == -1, "Got index %ld.\n", fmt.lindex); + ok(fmt.tymed == TYMED_HGLOBAL, "Got tymed %#lx.\n", fmt.tymed); + + hr = IEnumFORMATETC_Next(enum_format, 1, &fmt, NULL); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + IEnumFORMATETC_Release(enum_format); + } + + test_enum_format(data_obj); + IDataObject_Release(data_obj); }
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/shell32/dataobject.c | 18 ++++++------------ dlls/shell32/tests/shlfolder.c | 5 +---- 2 files changed, 7 insertions(+), 16 deletions(-)
diff --git a/dlls/shell32/dataobject.c b/dlls/shell32/dataobject.c index 96b9a0ad5dd..2b4ee6bb55b 100644 --- a/dlls/shell32/dataobject.c +++ b/dlls/shell32/dataobject.c @@ -368,21 +368,15 @@ static HRESULT WINAPI IDataObject_fnSetData(IDataObject *iface, LPFORMATETC pfor return E_NOTIMPL; }
-static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject *iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc) +static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject *iface, DWORD direction, IEnumFORMATETC **out) { - IDataObjectImpl *This = impl_from_IDataObject(iface); - - TRACE("(%p)->()\n", This); - *ppenumFormatEtc=NULL; + IDataObjectImpl *obj = impl_from_IDataObject(iface);
- /* only get data */ - if (DATADIR_GET == dwDirection) - { - *ppenumFormatEtc = IEnumFORMATETC_Constructor(MAX_FORMATS, This->pFormatEtc); - return (*ppenumFormatEtc) ? S_OK : E_FAIL; - } + TRACE("iface %p, direction %#lx, out %p.\n", iface, direction, out);
- return E_NOTIMPL; + if (!(*out = IEnumFORMATETC_Constructor(MAX_FORMATS, obj->pFormatEtc))) + return E_OUTOFMEMORY; + return S_OK; }
static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject *iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection) diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index eb77e2113f3..7e85ced8ded 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -5478,10 +5478,7 @@ static void test_DataObject(void) for (unsigned int i = 0; i < ARRAY_SIZE(enum_directions); ++i) { hr = IDataObject_EnumFormatEtc(data_obj, enum_directions[i], &enum_format); - todo_wine_if (enum_directions[i] == DATADIR_SET) - ok(hr == S_OK, "Got hr %#lx.\n", hr); - if (hr != S_OK) - continue; + ok(hr == S_OK, "Got hr %#lx.\n", hr);
memset(&fmt, 0xcc, sizeof(fmt)); hr = IEnumFORMATETC_Next(enum_format, 1, &fmt, NULL);
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/shell32/clipboard.c | 8 +- dlls/shell32/dataobject.c | 212 ++++++++++++++++----------------- dlls/shell32/shell32_main.h | 8 +- dlls/shell32/tests/shlfolder.c | 8 +- 4 files changed, 113 insertions(+), 123 deletions(-)
diff --git a/dlls/shell32/clipboard.c b/dlls/shell32/clipboard.c index 487fd0dcf8c..6ab2ad16c9d 100644 --- a/dlls/shell32/clipboard.c +++ b/dlls/shell32/clipboard.c @@ -55,7 +55,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell); * * creates a CF_HDROP structure */ -HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) +HGLOBAL RenderHDROP(const ITEMIDLIST *pidlRoot, const ITEMIDLIST **apidl, unsigned int cidl) { UINT i; int rootlen = 0,size = 0; @@ -107,7 +107,7 @@ HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) return hGlobal; }
-HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) +HGLOBAL RenderSHELLIDLIST(const ITEMIDLIST *pidlRoot, const ITEMIDLIST **apidl, unsigned int cidl) { UINT i; int offset = 0, sizePidl, size; @@ -149,7 +149,7 @@ HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cid return hGlobal; }
-HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) +HGLOBAL RenderFILENAMEA(const ITEMIDLIST *pidlRoot, const ITEMIDLIST **apidl, unsigned int cidl) { int size = 0; char szTemp[MAX_PATH], *szFileName; @@ -181,7 +181,7 @@ HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) return hGlobal; }
-HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) +HGLOBAL RenderFILENAMEW(const ITEMIDLIST *pidlRoot, const ITEMIDLIST **apidl, unsigned int cidl) { int size = 0; WCHAR szTemp[MAX_PATH], *szFileName; diff --git a/dlls/shell32/dataobject.c b/dlls/shell32/dataobject.c index 2b4ee6bb55b..dd4d77f6942 100644 --- a/dlls/shell32/dataobject.c +++ b/dlls/shell32/dataobject.c @@ -187,30 +187,19 @@ LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[]) return &ef->IEnumFORMATETC_iface; }
- -/*********************************************************************** -* IDataObject implementation -*/ - -/* number of supported formats */ -#define MAX_FORMATS 4 +struct data +{ + UINT cf; + HGLOBAL global; +};
typedef struct { - /* IUnknown fields */ - IDataObject IDataObject_iface; - LONG ref; - - /* IDataObject fields */ - LPITEMIDLIST pidl; - LPITEMIDLIST * apidl; - UINT cidl; - - FORMATETC pFormatEtc[MAX_FORMATS]; - UINT cfShellIDList; - UINT cfFileNameA; - UINT cfFileNameW; + IDataObject IDataObject_iface; + LONG ref;
+ struct data *data; + size_t data_count; } IDataObjectImpl;
static inline IDataObjectImpl *impl_from_IDataObject(IDataObject *iface) @@ -262,66 +251,62 @@ static ULONG WINAPI IDataObject_fnAddRef(IDataObject *iface) */ static ULONG WINAPI IDataObject_fnRelease(IDataObject *iface) { - IDataObjectImpl *This = impl_from_IDataObject(iface); - ULONG refCount = InterlockedDecrement(&This->ref); + IDataObjectImpl *obj = impl_from_IDataObject(iface); + ULONG refcount = InterlockedDecrement(&obj->ref);
- TRACE("(%p)->(%lu)\n", This, refCount + 1); + TRACE("%p decreasing refcount to %lu.\n", obj, refcount);
- if (!refCount) - { - TRACE(" destroying IDataObject(%p)\n",This); - _ILFreeaPidl(This->apidl, This->cidl); - ILFree(This->pidl); - free(This); - } - return refCount; + if (!refcount) + { + for (size_t i = 0; i < obj->data_count; ++i) + GlobalFree(obj->data[i].global); + free(obj->data); + free(obj); + } + return refcount; }
/************************************************************************** * IDataObject_fnGetData */ -static HRESULT WINAPI IDataObject_fnGetData(IDataObject *iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium) +static HRESULT WINAPI IDataObject_fnGetData(IDataObject *iface, FORMATETC *format, STGMEDIUM *medium) { - IDataObjectImpl *This = impl_from_IDataObject(iface); + IDataObjectImpl *obj = impl_from_IDataObject(iface);
- char szTemp[256]; + TRACE("iface %p, format %p, medium %p.\n", iface, format, medium);
- szTemp[0]=0; - GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256); - TRACE("(%p)->(%p %p format=%s)\n", This, pformatetcIn, pmedium, szTemp); + if (!(format->tymed & TYMED_HGLOBAL)) + { + FIXME("Unrecognized tymed %#lx, returning DV_E_FORMATETC.\n", format->tymed); + return DV_E_FORMATETC; + }
- if (pformatetcIn->cfFormat == This->cfShellIDList) - { - if (This->cidl < 1) return(E_UNEXPECTED); - pmedium->hGlobal = RenderSHELLIDLIST(This->pidl, This->apidl, This->cidl); - } - else if (pformatetcIn->cfFormat == CF_HDROP) - { - if (This->cidl < 1) return(E_UNEXPECTED); - pmedium->hGlobal = RenderHDROP(This->pidl, This->apidl, This->cidl); - } - else if (pformatetcIn->cfFormat == This->cfFileNameA) - { - if (This->cidl < 1) return(E_UNEXPECTED); - pmedium->hGlobal = RenderFILENAMEA(This->pidl, This->apidl, This->cidl); - } - else if (pformatetcIn->cfFormat == This->cfFileNameW) - { - if (This->cidl < 1) return(E_UNEXPECTED); - pmedium->hGlobal = RenderFILENAMEW(This->pidl, This->apidl, This->cidl); - } - 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; + for (size_t i = 0; i < obj->data_count; ++i) + { + if (obj->data[i].cf == format->cfFormat) + { + HGLOBAL src_global = obj->data[i].global; + size_t size = GlobalSize(src_global); + HGLOBAL dst_global; + const void *src; + void *dst; + + if (!(dst_global = GlobalAlloc(GMEM_MOVEABLE, size))) + return E_OUTOFMEMORY; + src = GlobalLock(src_global); + dst = GlobalLock(dst_global); + memcpy(dst, src, size); + GlobalUnlock(src_global); + GlobalUnlock(dst_global); + + medium->tymed = TYMED_HGLOBAL; + medium->pUnkForRelease = NULL; + medium->hGlobal = dst_global; + return S_OK; + } + } + + return DV_E_FORMATETC; }
static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject *iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium) @@ -331,27 +316,25 @@ static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject *iface, LPFORMATETC return E_NOTIMPL; }
-static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject *iface, LPFORMATETC pformatetc) +static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject *iface, FORMATETC *format) { - IDataObjectImpl *This = impl_from_IDataObject(iface); - UINT i; + IDataObjectImpl *obj = impl_from_IDataObject(iface);
- TRACE("(%p)->(fmt=0x%08x tym=0x%08lx)\n", This, pformatetc->cfFormat, pformatetc->tymed); + TRACE("iface %p, format %p.\n", iface, format);
- if(!(DVASPECT_CONTENT & pformatetc->dwAspect)) - return DV_E_DVASPECT; + if (!(format->tymed & TYMED_HGLOBAL)) + { + FIXME("Unrecognized tymed %#lx, returning S_FALSE.\n", format->tymed); + return S_FALSE; + }
- /* check our formats table what we have */ - for (i=0; i<MAX_FORMATS; i++) - { - if ((This->pFormatEtc[i].cfFormat == pformatetc->cfFormat) - && (This->pFormatEtc[i].tymed & pformatetc->tymed)) - { - return S_OK; - } - } + for (size_t i = 0; i < obj->data_count; ++i) + { + if (obj->data[i].cf == format->cfFormat) + return S_OK; + }
- return DV_E_TYMED; + return S_FALSE; }
static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(IDataObject *iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut) @@ -371,11 +354,21 @@ static HRESULT WINAPI IDataObject_fnSetData(IDataObject *iface, LPFORMATETC pfor static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject *iface, DWORD direction, IEnumFORMATETC **out) { IDataObjectImpl *obj = impl_from_IDataObject(iface); + FORMATETC *formats;
TRACE("iface %p, direction %#lx, out %p.\n", iface, direction, out);
- if (!(*out = IEnumFORMATETC_Constructor(MAX_FORMATS, obj->pFormatEtc))) + if (!(formats = calloc(obj->data_count, sizeof(*formats)))) + return E_OUTOFMEMORY; + for (size_t i = 0; i < obj->data_count; ++i) + InitFormatEtc(formats[i], obj->data[i].cf, TYMED_HGLOBAL); + + if (!(*out = IEnumFORMATETC_Constructor(obj->data_count, formats))) + { + free(formats); return E_OUTOFMEMORY; + } + free(formats); return S_OK; }
@@ -417,30 +410,27 @@ static const IDataObjectVtbl dtovt = /************************************************************************** * IDataObject_Constructor */ -IDataObject* IDataObject_Constructor(HWND hwndOwner, - LPCITEMIDLIST pMyPidl, LPCITEMIDLIST * apidl, UINT cidl) +IDataObject *IDataObject_Constructor(HWND hwnd, const ITEMIDLIST *root_pidl, + const ITEMIDLIST **pidls, UINT pidl_count) { - IDataObjectImpl* dto; - - dto = calloc(1, sizeof(*dto)); - - if (dto) - { - dto->ref = 1; - dto->IDataObject_iface.lpVtbl = &dtovt; - dto->pidl = ILClone(pMyPidl); - dto->apidl = _ILCopyaPidl(apidl, cidl); - dto->cidl = cidl; - - dto->cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW); - dto->cfFileNameA = RegisterClipboardFormatA(CFSTR_FILENAMEA); - dto->cfFileNameW = RegisterClipboardFormatW(CFSTR_FILENAMEW); - InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL); - InitFormatEtc(dto->pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL); - InitFormatEtc(dto->pFormatEtc[2], dto->cfFileNameA, TYMED_HGLOBAL); - InitFormatEtc(dto->pFormatEtc[3], dto->cfFileNameW, TYMED_HGLOBAL); - } - - TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl); - return &dto->IDataObject_iface; + IDataObjectImpl *obj; + + if (!(obj = calloc(1, sizeof(*obj)))) + return NULL; + + obj->ref = 1; + obj->IDataObject_iface.lpVtbl = &dtovt; + obj->data = calloc(4, sizeof(*obj->data)); + obj->data[0].cf = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW); + obj->data[0].global = RenderSHELLIDLIST(root_pidl, pidls, pidl_count); + obj->data[1].cf = CF_HDROP; + obj->data[1].global = RenderHDROP(root_pidl, pidls, pidl_count); + obj->data[2].cf = RegisterClipboardFormatA(CFSTR_FILENAMEA); + obj->data[2].global = RenderFILENAMEA(root_pidl, pidls, pidl_count); + obj->data[3].cf = RegisterClipboardFormatW(CFSTR_FILENAMEW); + obj->data[3].global = RenderFILENAMEW(root_pidl, pidls, pidl_count); + obj->data_count = 4; + + TRACE("Created data object %p.\n", obj); + return &obj->IDataObject_iface; } diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h index f6fea65344d..6b5575c6879 100644 --- a/dlls/shell32/shell32_main.h +++ b/dlls/shell32/shell32_main.h @@ -139,10 +139,10 @@ HRESULT WINAPI CustomDestinationList_Constructor(IUnknown *outer, REFIID riid, v DROPEFFECT_MOVE))
-HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); -HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); -HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); -HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); +HGLOBAL RenderHDROP(const ITEMIDLIST *root_pidl, const ITEMIDLIST **pidls, unsigned int count); +HGLOBAL RenderSHELLIDLIST(const ITEMIDLIST *root_pidl, const ITEMIDLIST **pidls, unsigned int count); +HGLOBAL RenderFILENAMEA(const ITEMIDLIST *root_pidl, const ITEMIDLIST **pidls, unsigned int count); +HGLOBAL RenderFILENAMEW(const ITEMIDLIST *root_pidl, const ITEMIDLIST **pidls, unsigned int count);
/* Change Notification */ void InitChangeNotifications(void); diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 7e85ced8ded..3f364b49769 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -5409,9 +5409,9 @@ static void test_DataObject(void)
fmt.tymed = TYMED_ISTREAM; hr = IDataObject_QueryGetData(data_obj, &fmt); - todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); hr = IDataObject_GetData(data_obj, &fmt, &medium); - todo_wine ok(hr == DV_E_FORMATETC, "Got hr %#lx.\n", hr); + ok(hr == DV_E_FORMATETC, "Got hr %#lx.\n", hr);
fmt.tymed = TYMED_HGLOBAL | TYMED_ISTREAM; hr = IDataObject_GetData(data_obj, &fmt, &medium); @@ -5444,9 +5444,9 @@ static void test_DataObject(void) fmt.cfFormat = RegisterClipboardFormatW(L"bogus_format");
hr = IDataObject_QueryGetData(data_obj, &fmt); - todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); hr = IDataObject_GetData(data_obj, &fmt, &medium); - todo_wine ok(hr == DV_E_FORMATETC, "Got hr %#lx.\n", hr); + ok(hr == DV_E_FORMATETC, "Got hr %#lx.\n", hr);
global = GlobalAlloc(GMEM_MOVEABLE, sizeof(*value)); value = GlobalLock(global);
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/shell32/dataobject.c | 46 +++++++++++++++++++++++++++++++--- dlls/shell32/tests/shlfolder.c | 29 ++++++++++----------- 2 files changed, 55 insertions(+), 20 deletions(-)
diff --git a/dlls/shell32/dataobject.c b/dlls/shell32/dataobject.c index dd4d77f6942..d0ed644c437 100644 --- a/dlls/shell32/dataobject.c +++ b/dlls/shell32/dataobject.c @@ -344,11 +344,49 @@ static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(IDataObject *iface, LP return E_NOTIMPL; }
-static HRESULT WINAPI IDataObject_fnSetData(IDataObject *iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease) +static HRESULT WINAPI IDataObject_fnSetData(IDataObject *iface, + FORMATETC *format, STGMEDIUM *medium, BOOL release) { - IDataObjectImpl *This = impl_from_IDataObject(iface); - FIXME("(%p)->()\n", This); - return E_NOTIMPL; + IDataObjectImpl *obj = impl_from_IDataObject(iface); + struct data *new_array; + + TRACE("iface %p, format %p, medium %p, release %d.\n", iface, format, medium, release); + + if (!release) + return E_INVALIDARG; + + if (format->tymed != TYMED_HGLOBAL) + { + FIXME("Unhandled format tymed %#lx.\n", format->tymed); + return E_NOTIMPL; + } + + if (medium->tymed != TYMED_HGLOBAL) + { + FIXME("Unhandled medium tymed %#lx.\n", format->tymed); + return E_NOTIMPL; + } + + if (medium->pUnkForRelease) + FIXME("Ignoring IUnknown %p.\n", medium->pUnkForRelease); + + for (size_t i = 0; i < obj->data_count; ++i) + { + if (obj->data[i].cf == format->cfFormat) + { + GlobalFree(obj->data[i].global); + obj->data[i].global = medium->hGlobal; + return S_OK; + } + } + + if (!(new_array = realloc(obj->data, (obj->data_count + 1) * sizeof(*obj->data)))) + return E_OUTOFMEMORY; + obj->data = new_array; + obj->data[obj->data_count].cf = format->cfFormat; + obj->data[obj->data_count].global = medium->hGlobal; + ++obj->data_count; + return S_OK; }
static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject *iface, DWORD direction, IEnumFORMATETC **out) diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 3f364b49769..b2448938728 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -5318,15 +5318,15 @@ static void test_enum_format(IDataObject *data_obj) hr = IEnumFORMATETC_Reset(enum1); ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IEnumFORMATETC_Skip(enum1, 4); - ok(hr == S_FALSE, "Got hr %#lx.\n", hr); - hr = IEnumFORMATETC_Skip(enum1, 1); todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + hr = IEnumFORMATETC_Skip(enum1, 1); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); hr = IEnumFORMATETC_Reset(enum1); ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IEnumFORMATETC_Skip(enum1, 3); ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IEnumFORMATETC_Skip(enum1, 1); - ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); hr = IEnumFORMATETC_Next(enum1, 1, formats, NULL); todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); hr = IEnumFORMATETC_Next(enum2, 1, formats, NULL); @@ -5342,7 +5342,7 @@ static void test_enum_format(IDataObject *data_obj) formats[0].lindex = -1; formats[0].tymed = TYMED_HGLOBAL; hr = IDataObject_SetData(data_obj, &formats[0], &medium, TRUE); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(hr == S_OK, "Got hr %#lx.\n", hr);
hr = IEnumFORMATETC_Reset(enum1); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -5457,23 +5457,20 @@ static void test_DataObject(void) medium.hGlobal = global; fmt.tymed = TYMED_HGLOBAL; hr = IDataObject_SetData(data_obj, &fmt, &medium, FALSE); - todo_wine ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr); + ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr); hr = IDataObject_SetData(data_obj, &fmt, &medium, TRUE); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(hr == S_OK, "Got hr %#lx.\n", hr);
hr = IDataObject_QueryGetData(data_obj, &fmt); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(hr == S_OK, "Got hr %#lx.\n", hr); memset(&medium, 0xcc, sizeof(medium)); hr = IDataObject_GetData(data_obj, &fmt, &medium); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - if (hr == S_OK) - { - ok(medium.hGlobal && medium.hGlobal != global, "Got global %p.\n", medium.hGlobal); - value = GlobalLock(medium.hGlobal); - ok(*value == 0xabacab, "Got value %#x.\n", *value); - GlobalUnlock(medium.hGlobal); - ReleaseStgMedium(&medium); - } + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(medium.hGlobal && medium.hGlobal != global, "Got global %p.\n", medium.hGlobal); + value = GlobalLock(medium.hGlobal); + ok(*value == 0xabacab, "Got value %#x.\n", *value); + GlobalUnlock(medium.hGlobal); + ReleaseStgMedium(&medium);
for (unsigned int i = 0; i < ARRAY_SIZE(enum_directions); ++i) {
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=143734
Your paranoid android.
=== w8 (32 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w8adm (32 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w864 (32 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w1064v1507 (32 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w1064v1809 (32 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w1064_tsign (32 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w10pro64 (32 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w10pro64_en_AE_u8 (32 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w11pro64 (32 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w864 (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w1064v1507 (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w1064v1809 (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w1064_2qxl (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w1064_adm (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w1064_tsign (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w10pro64 (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w10pro64_ar (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w10pro64_ja (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w10pro64_zh_CN (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.
=== w11pro64_amd (64 bit report) ===
shell32: shlfolder.c:5460: Test failed: Got hr 0x80004001.