Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
[PATCH v2 2/2] riched20: Draw OLE objects with IViewObject implementation.
by Jinoh Kang
From: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52752
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/riched20/richole.c | 64 +++++++++++++++++++++++++++++++++++
dlls/riched20/tests/richole.c | 2 --
2 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index 936f1c928b3..9d414af8ee2 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -5656,6 +5656,7 @@ static void convert_sizel(const ME_Context *c, const SIZEL* szl, SIZE* sz)
void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize)
{
IDataObject* ido;
+ IViewObject* ivo;
FORMATETC fmt;
STGMEDIUM stgm;
DIBSECTION dibsect;
@@ -5681,6 +5682,29 @@ void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize)
return;
}
+ if (SUCCEEDED(IOleObject_QueryInterface(run->reobj->obj.poleobj, &IID_IViewObject, (void**)&ivo)))
+ {
+ HRESULT hr;
+ SIZEL sizel;
+
+ hr = IOleObject_GetExtent(run->reobj->obj.poleobj, DVASPECT_CONTENT, &sizel);
+ if (FAILED(hr))
+ {
+ WARN("failed to get extent: %#08lx\n", hr);
+ sizel.cx = sizel.cy = 0;
+ }
+
+ convert_sizel(c, &sizel, pSize);
+ if (c->editor->nZoomNumerator != 0)
+ {
+ pSize->cx = MulDiv(pSize->cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
+ pSize->cy = MulDiv(pSize->cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
+ }
+
+ IViewObject_Release(ivo);
+ return;
+ }
+
if (IOleObject_QueryInterface(run->reobj->obj.poleobj, &IID_IDataObject, (void**)&ido) != S_OK)
{
FIXME("Query Interface IID_IDataObject failed!\n");
@@ -5733,6 +5757,7 @@ void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize)
void draw_ole( ME_Context *c, int x, int y, ME_Run *run, BOOL selected )
{
IDataObject* ido;
+ IViewObject* ivo;
FORMATETC fmt;
STGMEDIUM stgm;
DIBSECTION dibsect;
@@ -5745,6 +5770,45 @@ void draw_ole( ME_Context *c, int x, int y, ME_Run *run, BOOL selected )
assert(run->nFlags & MERF_GRAPHICS);
assert(run->reobj);
+
+ if (SUCCEEDED(IOleObject_QueryInterface(run->reobj->obj.poleobj, &IID_IViewObject, (void**)&ivo)))
+ {
+ HRESULT hr;
+ SIZEL sizel = run->reobj->obj.sizel;
+
+ if (sizel.cx == 0 && sizel.cy == 0)
+ {
+ hr = IOleObject_GetExtent(run->reobj->obj.poleobj, DVASPECT_CONTENT, &sizel);
+ if (FAILED(hr))
+ {
+ WARN("failed to get extent: %#08lx\n", hr);
+ IViewObject_Release(ivo);
+ return;
+ }
+ }
+
+ convert_sizel(c, &sizel, &sz);
+ if (c->editor->nZoomNumerator != 0)
+ {
+ sz.cx = MulDiv(sz.cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
+ sz.cy = MulDiv(sz.cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
+ }
+
+ rc.left = x;
+ rc.top = y - sz.cy;
+ rc.right = x + sz.cx;
+ rc.bottom = y;
+
+ hr = IViewObject_Draw(ivo, DVASPECT_CONTENT, -1, 0, 0, 0, c->hDC, (RECTL*)&rc, NULL, NULL, 0);
+ if (FAILED(hr))
+ {
+ WARN("failed to draw object: %#08lx\n", hr);
+ }
+
+ IViewObject_Release(ivo);
+ return;
+ }
+
if (IOleObject_QueryInterface(run->reobj->obj.poleobj, &IID_IDataObject, (void**)&ido) != S_OK)
{
FIXME("Couldn't get interface\n");
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index 36ff4eeb696..4c7f19199fa 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -4181,7 +4181,6 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
testobj->line = __LINE__;
UpdateWindow(hwnd);
- todo_wine
ok(testobj->draw_count, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
@@ -4205,7 +4204,6 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
testobj->line = __LINE__;
UpdateWindow(hwnd);
- todo_wine
ok(testobj->draw_count, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/227
June 11, 2022
[PATCH v2 1/2] riched20/tests: Add tests for drawing embedded OLE objects.
by Jinoh Kang
From: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/riched20/tests/richole.c | 452 +++++++++++++++++++++++++++++++++-
1 file changed, 449 insertions(+), 3 deletions(-)
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index c34c87ef646..36ff4eeb696 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -212,6 +212,396 @@ static void olecb_check_QueryInsertObject(struct reolecb_obj *This, int line)
olecb_expect_QueryInsertObject(This, 0, 0, NULL, NULL, 0, S_OK);
}
+DEFINE_GUID(CLSID_testoleobj, 0x4484082e, 0x6d18, 0x4932, 0xa0, 0x86, 0x5b, 0x4d, 0xcf, 0x36, 0xb3, 0xde);
+
+struct testoleobj {
+ IOleObject IOleObject_iface;
+ LONG ref;
+ int line;
+ int draw_count;
+
+ IOleClientSite *clientsite;
+ IOleAdviseHolder *advise_holder;
+ SIZEL extent;
+
+ IViewObject IViewObject_iface;
+};
+
+static struct testoleobj *impl_from_IOleObject( IOleObject *iface )
+{
+ return CONTAINING_RECORD( iface, struct testoleobj, IOleObject_iface );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_QueryInterface( IOleObject *iface, REFIID riid, void **obj )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (IsEqualGUID( riid, &IID_IUnknown ) || IsEqualGUID( riid, &IID_IOleObject ))
+ {
+ *obj = iface;
+ }
+ else if (IsEqualGUID( riid, &IID_IViewObject ))
+ {
+ *obj = &This->IViewObject_iface;
+ }
+ else
+ {
+ if (!IsEqualGUID( riid, &IID_IOleLink ) &&
+ !IsEqualGUID( riid, &IID_IRunnableObject ) &&
+ !IsEqualGUID( riid, &IID_IMarshal ))
+ {
+ trace( "Unsupported interface: %s\n", debugstr_guid( riid ));
+ }
+ *obj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef( (IUnknown *)*obj );
+ return S_OK;
+}
+
+static ULONG STDMETHODCALLTYPE testoleobj_AddRef( IOleObject *iface )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+ ULONG ref = InterlockedIncrement( &This->ref );
+ return ref;
+}
+
+static ULONG STDMETHODCALLTYPE testoleobj_Release( IOleObject *iface )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+ ULONG ref = InterlockedDecrement( &This->ref );
+ if (!ref)
+ {
+ if (This->advise_holder)
+ {
+ IOleAdviseHolder_Release( This->advise_holder );
+ This->advise_holder = NULL;
+ }
+ if (This->clientsite)
+ {
+ IOleClientSite_Release( This->clientsite );
+ This->clientsite = NULL;
+ }
+ free( This );
+ }
+ return ref;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_SetClientSite( IOleObject *iface, IOleClientSite *clientsite )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (This->clientsite != clientsite)
+ {
+ if (This->clientsite) IOleClientSite_Release( This->clientsite );
+ This->clientsite = clientsite;
+ if (This->clientsite) IOleClientSite_AddRef( This->clientsite );
+ }
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetClientSite( IOleObject *iface, IOleClientSite **clientsite )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (This->clientsite) IOleClientSite_AddRef( This->clientsite );
+ *clientsite = This->clientsite;
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_SetHostNames( IOleObject *iface,
+ LPCOLESTR container_app,
+ LPCOLESTR container_obj )
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_Close( IOleObject *iface, DWORD save_option )
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_SetMoniker( IOleObject *iface,
+ DWORD which_moniker, IMoniker *mk )
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetMoniker( IOleObject *iface, DWORD assign,
+ DWORD which_moniker, IMoniker **mk )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ *mk = NULL;
+
+ if (!This->clientsite) return E_UNEXPECTED;
+
+ return IOleClientSite_GetMoniker( This->clientsite, assign, which_moniker, mk );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_InitFromData( IOleObject *iface, IDataObject *dataobj,
+ BOOL creation, DWORD reserved )
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetClipboardData( IOleObject *iface, DWORD reserved,
+ IDataObject **dataobj )
+{
+ *dataobj = NULL;
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_DoVerb( IOleObject *iface, LONG verb, MSG *msg,
+ IOleClientSite *activesite, LONG index,
+ HWND parentwnd, LPCRECT posrect )
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_EnumVerbs( IOleObject *iface, IEnumOLEVERB **enumoleverb )
+{
+ *enumoleverb = NULL;
+ return OLEOBJ_E_NOVERBS;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_Update( IOleObject *iface )
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_IsUpToDate( IOleObject *iface )
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetUserClassID( IOleObject *iface, CLSID *clsid )
+{
+ *clsid = CLSID_testoleobj;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetUserType( IOleObject *iface, DWORD form_of_type, LPOLESTR *user_type )
+{
+ static const OLECHAR typename[] = L"richole testoleobj";
+
+ *user_type = CoTaskMemAlloc( sizeof(typename) );
+ if (!*user_type) return E_OUTOFMEMORY;
+
+ memcpy( *user_type, typename, sizeof(typename) );
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_SetExtent( IOleObject *iface, DWORD draw_aspect, SIZEL *sizel )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (draw_aspect != DVASPECT_CONTENT) return E_FAIL;
+
+ This->extent = *sizel;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetExtent( IOleObject *iface, DWORD draw_aspect, SIZEL *sizel )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (draw_aspect != DVASPECT_CONTENT) return E_FAIL;
+
+ *sizel = This->extent;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_Advise( IOleObject *iface, IAdviseSink *adv_sink, DWORD *connection )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+ HRESULT hr = S_OK;
+
+ if (!This->advise_holder) hr = CreateOleAdviseHolder( &This->advise_holder );
+ if (SUCCEEDED( hr )) hr = IOleAdviseHolder_Advise( This->advise_holder, adv_sink, connection );
+ return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_Unadvise( IOleObject *iface, DWORD connection )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (!This->advise_holder) return OLE_E_NOCONNECTION;
+ return IOleAdviseHolder_Unadvise( This->advise_holder, connection );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_EnumAdvise( IOleObject *iface, IEnumSTATDATA **enum_advise )
+{
+ struct testoleobj *This = impl_from_IOleObject( iface );
+
+ if (!This->advise_holder)
+ {
+ *enum_advise = NULL;
+ return S_OK;
+ }
+ return IOleAdviseHolder_EnumAdvise( This->advise_holder, enum_advise );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_GetMiscStatus( IOleObject *iface, DWORD aspect, DWORD *status )
+{
+ *status = 0;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IOleObject_SetColorScheme( IOleObject *iface, LOGPALETTE *palette )
+{
+ return E_NOTIMPL;
+}
+
+static const struct IOleObjectVtbl testoleobj_IOleObject_Vtbl = {
+ testoleobj_QueryInterface,
+ testoleobj_AddRef,
+ testoleobj_Release,
+ testoleobj_IOleObject_SetClientSite,
+ testoleobj_IOleObject_GetClientSite,
+ testoleobj_IOleObject_SetHostNames,
+ testoleobj_IOleObject_Close,
+ testoleobj_IOleObject_SetMoniker,
+ testoleobj_IOleObject_GetMoniker,
+ testoleobj_IOleObject_InitFromData,
+ testoleobj_IOleObject_GetClipboardData,
+ testoleobj_IOleObject_DoVerb,
+ testoleobj_IOleObject_EnumVerbs,
+ testoleobj_IOleObject_Update,
+ testoleobj_IOleObject_IsUpToDate,
+ testoleobj_IOleObject_GetUserClassID,
+ testoleobj_IOleObject_GetUserType,
+ testoleobj_IOleObject_SetExtent,
+ testoleobj_IOleObject_GetExtent,
+ testoleobj_IOleObject_Advise,
+ testoleobj_IOleObject_Unadvise,
+ testoleobj_IOleObject_EnumAdvise,
+ testoleobj_IOleObject_GetMiscStatus,
+ testoleobj_IOleObject_SetColorScheme
+};
+
+static struct testoleobj *impl_from_IViewObject( IViewObject *iface )
+{
+ return CONTAINING_RECORD( iface, struct testoleobj, IViewObject_iface );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_QueryInterface( IViewObject *iface, REFIID riid, void **obj )
+{
+ struct testoleobj *This = impl_from_IViewObject( iface );
+ return IOleObject_QueryInterface( &This->IOleObject_iface, riid, obj );
+}
+
+static ULONG STDMETHODCALLTYPE testoleobj_IViewObject_AddRef( IViewObject *iface )
+{
+ struct testoleobj *This = impl_from_IViewObject( iface );
+ return IOleObject_AddRef( &This->IOleObject_iface );
+}
+
+static ULONG STDMETHODCALLTYPE testoleobj_IViewObject_Release( IViewObject *iface )
+{
+ struct testoleobj *This = impl_from_IViewObject( iface );
+ return IOleObject_Release( &This->IOleObject_iface );
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_Draw( IViewObject *iface, DWORD draw_aspect,
+ LONG index, void *aspect, DVTARGETDEVICE *td,
+ HDC hdc_target_dev, HDC hdc_draw,
+ LPCRECTL bounds, LPCRECTL wbounds,
+ BOOL (CALLBACK *fn_continue)(ULONG_PTR),
+ ULONG_PTR arg_continue )
+{
+ struct testoleobj *This = impl_from_IViewObject( iface );
+ SIZEL dpi;
+
+ if (draw_aspect != DVASPECT_CONTENT || index != -1) return E_NOTIMPL;
+
+ ok_(__FILE__,This->line)( td == NULL, "expected td to be NULL, got %p\n", td );
+ ok_(__FILE__,This->line)( hdc_target_dev == NULL, "expected hdc_target_dev to be NULL, got %p\n", hdc_target_dev );
+ ok_(__FILE__,This->line)( wbounds == NULL, "expected wbounds to be NULL, got %p\n", wbounds );
+
+ dpi.cx = GetDeviceCaps(hdc_draw, LOGPIXELSX);
+ dpi.cy = GetDeviceCaps(hdc_draw, LOGPIXELSY);
+
+ ok_(__FILE__,This->line)( bounds->right - bounds->left == MulDiv( This->extent.cx, dpi.cx, 2540 ),
+ "bounds->right (= %ld) - bounds->left (= %ld) != "
+ "MulDiv( This->extent.cx (= %ld), dpi.cx (= %ld), 2540 )\n",
+ bounds->right, bounds->left, This->extent.cx, dpi.cx );
+ ok_(__FILE__,This->line)( bounds->bottom - bounds->top == MulDiv( This->extent.cy, dpi.cy, 2540 ),
+ "bounds->bottom (= %ld) - bounds->top (= %ld) != "
+ "MulDiv( This->extent.cy (= %ld), dpi.cy (= %ld), 2540 )\n",
+ bounds->bottom, bounds->top, This->extent.cy, dpi.cy );
+
+ FillRect( hdc_draw, (const RECT *)bounds, GetStockObject( DKGRAY_BRUSH ));
+ This->draw_count++;
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_GetColorSet( IViewObject *iface, DWORD draw_aspect,
+ LONG index, void *aspect, DVTARGETDEVICE *td,
+ HDC hdc_target_dev, LOGPALETTE **color_set )
+{
+ *color_set = NULL;
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_Freeze( IViewObject *iface, DWORD draw_aspect,
+ LONG index, void *aspect, DWORD *freeze )
+{
+ *freeze = 0;
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_Unfreeze( IViewObject *iface, DWORD freeze )
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_SetAdvise( IViewObject *iface, DWORD aspects,
+ DWORD advf, IAdviseSink *adv_sink )
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE testoleobj_IViewObject_GetAdvise( IViewObject *iface, DWORD *aspects,
+ DWORD *advf, IAdviseSink **adv_sink )
+{
+ *aspects = 0;
+ *advf = 0;
+ *adv_sink = NULL;
+ return E_NOTIMPL;
+}
+
+static const struct IViewObjectVtbl testoleobj_IViewObject_Vtbl = {
+ testoleobj_IViewObject_QueryInterface,
+ testoleobj_IViewObject_AddRef,
+ testoleobj_IViewObject_Release,
+ testoleobj_IViewObject_Draw,
+ testoleobj_IViewObject_GetColorSet,
+ testoleobj_IViewObject_Freeze,
+ testoleobj_IViewObject_Unfreeze,
+ testoleobj_IViewObject_SetAdvise,
+ testoleobj_IViewObject_GetAdvise,
+};
+
+static HRESULT testoleobj_Create( struct testoleobj **objptr )
+{
+ struct testoleobj *obj;
+
+ obj = calloc( sizeof(struct testoleobj), 1 );
+ if (!obj) return E_OUTOFMEMORY;
+
+ obj->IOleObject_iface.lpVtbl = &testoleobj_IOleObject_Vtbl;
+ obj->ref = 1;
+ obj->IViewObject_iface.lpVtbl = &testoleobj_IViewObject_Vtbl;
+
+ *objptr = obj;
+ return S_OK;
+}
+
static HMODULE hmoduleRichEdit;
DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -3453,6 +3843,9 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
LONG count, result;
ITextRange *range;
BSTR bstr;
+ struct testoleobj *testobj;
+ IOleClientSite *clientsite;
+ REOBJECT reobj;
create_interfaces(&hwnd, &reole, &doc, &selection);
if (callback)
@@ -3486,9 +3879,6 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
if (callback)
{
- IOleClientSite *clientsite;
- REOBJECT reobj;
-
/* (fail to) insert object1 in (3, 4)*/
SendMessageA(hwnd, EM_SETSEL, 3, 4);
@@ -3765,6 +4155,62 @@ static void subtest_InsertObject(struct reolecb_obj *callback)
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(result == 0xfffc, "Got char: %lc\n", (WCHAR)result);
+ hr = testoleobj_Create(&testobj);
+ ok(hr == S_OK, "testoleobj_Create got hr %#lx.\n", hr);
+ testobj->extent.cx = 800;
+ testobj->extent.cy = 800;
+
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
+ testobj->draw_count = 0;
+ testobj->line = __LINE__;
+
+ hr = IRichEditOle_GetClientSite(reole, &clientsite);
+ ok(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
+ hr = IOleObject_SetClientSite(&testobj->IOleObject_iface, clientsite);
+ ok(hr == S_OK, "IOleObject_SetClientSite got hr %#lx.\n", hr);
+
+ olecb_expect_QueryInsertObject(callback, __LINE__, 1,
+ &CLSID_testoleobj, NULL, REO_CP_SELECTION, S_OK);
+ fill_reobject_struct(&reobj, REO_CP_SELECTION, &testobj->IOleObject_iface, NULL, clientsite, 800, 800, DVASPECT_CONTENT, 0, 0);
+ reobj.clsid = CLSID_testoleobj;
+ hr = IRichEditOle_InsertObject(reole, &reobj);
+ ok(hr == S_OK, "IRichEditOle_InsertObject got hr %#lx.\n", hr);
+ olecb_check_QueryInsertObject(callback, __LINE__);
+
+ IOleClientSite_Release(clientsite);
+
+ testobj->line = __LINE__;
+ UpdateWindow(hwnd);
+ todo_wine
+ ok(testobj->draw_count, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
+
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
+ testobj->draw_count = 0;
+ testobj->line = __LINE__;
+
+ hr = IRichEditOle_GetClientSite(reole, &clientsite);
+ ok(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
+ hr = IOleObject_SetClientSite(&testobj->IOleObject_iface, clientsite);
+ ok(hr == S_OK, "IOleObject_SetClientSite got hr %#lx.\n", hr);
+
+ olecb_expect_QueryInsertObject(callback, __LINE__, 1,
+ &CLSID_testoleobj, NULL, REO_CP_SELECTION, S_OK);
+ fill_reobject_struct(&reobj, REO_CP_SELECTION, &testobj->IOleObject_iface, NULL, clientsite, 0, 0, DVASPECT_CONTENT, 0, 0);
+ reobj.clsid = CLSID_testoleobj;
+ hr = IRichEditOle_InsertObject(reole, &reobj);
+ ok(hr == S_OK, "IRichEditOle_InsertObject got hr %#lx.\n", hr);
+ olecb_check_QueryInsertObject(callback, __LINE__);
+
+ IOleClientSite_Release(clientsite);
+
+ testobj->line = __LINE__;
+ UpdateWindow(hwnd);
+ todo_wine
+ ok(testobj->draw_count, "expected draw_count to be nonzero, got %d\n", testobj->draw_count);
+
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
+ IOleObject_Release(&testobj->IOleObject_iface);
+
if (callback)
{
LRESULT sendres = SendMessageA(hwnd, EM_SETOLECALLBACK, 0, 0);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/227
June 11, 2022
[PATCH v2 0/2] MR227: riched20: Fix for #52752 (use IViewObject implementation)
by Jinoh Kang (@iamahuman)
Fixes https://bugs.winehq.org/show_bug.cgi?id=52752.
--
v2: riched20: Draw OLE objects with IViewObject implementation.
riched20/tests: Add tests for drawing embedded OLE objects.
https://gitlab.winehq.org/wine/wine/-/merge_requests/227
June 11, 2022
Re: [PATCH v2 resend 3/6] comctl32/listview: Send LVN_ODSTATECHANGED only for virtual lists.
by Zhiyi Zhang
On 6/11/22 07:56, Angelo Haller wrote:
> On 10/06/2022 03.13, Zhiyi Zhang wrote:
>>
>> On 5/26/22 04:00, Angelo Haller wrote:
>>> From: Angelo Haller <angelo(a)szanni.org>
>>>
>>> The LVN_ODSTATECHANGED notification should only be sent to lists
>>> that have LVS_OWNERDATA set.
>>>
>>> Signed-off-by: Angelo Haller <angelo(a)szanni.org>
>>> ---
>>> dlls/comctl32/listview.c | 1 +
>>> 1 file changed, 1 insertion(+)
>>>
>>> diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
>>> index 72ade724313..318df0a4093 100644
>>> --- a/dlls/comctl32/listview.c
>>> +++ b/dlls/comctl32/listview.c
>>> @@ -8946,6 +8946,7 @@ static VOID LISTVIEW_SetOwnerDataState(LISTVIEW_INFO *infoPtr, INT nFirst, INT n
>>> {
>>> NMLVODSTATECHANGE nmlv;
>>> + if (!(infoPtr->dwStyle & LVS_OWNERDATA)) return;
>> Make sense. It will be better if you can add a simple test before this patch and remove the todo_wines after the fix.
> Is this strictly necessary? The call site has special handling for:
> infoPtr->dwStyle & LVS_OWNERDATA
>
> We could guard the call to the function at the call site, if that is preferred.
>
> Apart from that I am not sure how to write a test for this. This bug is triggered by creating a non ownerdata list and selecting multiple entries holding shift+ctrl and clicking with the mouse. This will send an LVN_ODSTATECHANGED notification where it is not supposed to (as it is not an ownerdata list).
You can write a test that demonstrate the exact same thing. Create a non onwerdata listview control and test the message sequence doesn't contain LVN_ODSTATECHANGED, which should have a todo_wine
because Wine is currently broken in this case. Then you fix it in the next patch and removes the todo_wine.
As for the mouse emulation, could you do it using only the keyboard? Such as sending VK_DOWN while holding Shift and Ctrl?
>
> I have not found any test examples with mouse emulation. Maybe I missed something.
>
> Or should I open a separate bug report for this line?
>
>>> if (!item) return;
>>> ZeroMemory(&nmlv, sizeof(nmlv));
>
>
June 11, 2022
Re: [PATCH v2 resend 1/6] comctl32/tests: Expand ownerdata listview tests.
by Zhiyi Zhang
On 6/11/22 02:33, Angelo Haller wrote:
> On 10/06/2022 03.12, Zhiyi Zhang wrote:
>>
>> On 5/26/22 04:00, Angelo Haller wrote:
>>> From: Angelo Haller <angelo(a)szanni.org>
>>>
>>> Add more test cases to ownderdata listviews.
>>> Check LVN_ITEMCHANGED IDs.
>>>
>>> Signed-off-by: Angelo Haller <angelo(a)szanni.org>
>>> ---
>>> dlls/comctl32/tests/listview.c | 59 +++++++++++++++++++++++++++++-----
>>> 1 file changed, 51 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
>>> index 6ac7f53137d..78b3e3ae069 100644
>>> --- a/dlls/comctl32/tests/listview.c
>>> +++ b/dlls/comctl32/tests/listview.c
>>> @@ -255,11 +255,33 @@ static const struct message ownerdata_deselect_all_parent_seq[] = {
>>> { 0 }
>>> };
>>> -static const struct message ownerdata_multiselect_odstatechanged_seq[] = {
>>> - { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
>>> +static const struct message ownerdata_multiselect_select_0_to_1_seq[] = {
>>> + { WM_NOTIFY, sent|id|wparam, -1, 0, LVN_ITEMCHANGED },
>>> { WM_NOTIFY, sent|id, 0, 0, LVN_ODSTATECHANGED },
>>> - { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
>>> - { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
>>> + { WM_NOTIFY, sent|id|wparam, 0, 0, LVN_ITEMCHANGED },
>>> + { WM_NOTIFY, sent|id|wparam, 1, 0, LVN_ITEMCHANGED },
>>> + { 0 }
>>> +};
>>> +
>>> +static const struct message ownerdata_multiselect_select_0_to_2_seq[] = {
>>> + { WM_NOTIFY, sent|id|wparam, -1, 0, LVN_ITEMCHANGED },
>>> + { WM_NOTIFY, sent|id, 0, 0, LVN_ODSTATECHANGED },
>>> + { WM_NOTIFY, sent|id|wparam, 1, 0, LVN_ITEMCHANGED },
>>> + { WM_NOTIFY, sent|id|wparam, 2, 0, LVN_ITEMCHANGED },
>>> + { 0 }
>>> +};
>>> +
>>> +static const struct message ownerdata_multiselect_deselect_all_select_3_seq[] = {
>>> + { WM_NOTIFY, sent|id|wparam, -1, 0, LVN_ITEMCHANGED },
>>> + { WM_NOTIFY, sent|id|wparam, 2, 0, LVN_ITEMCHANGED },
>>> + { WM_NOTIFY, sent|id|wparam, 3, 0, LVN_ITEMCHANGED },
>>> + { 0 }
>>> +};
>>> +
>>> +static const struct message ownerdata_multiselect_deselect_3_select_2_seq[] = {
>>> + { WM_NOTIFY, sent|id|wparam, -1, 0, LVN_ITEMCHANGED },
>>> + { WM_NOTIFY, sent|id|wparam, 3, 0, LVN_ITEMCHANGED },
>>> + { WM_NOTIFY, sent|id|wparam, 2, 0, LVN_ITEMCHANGED },
>>> { 0 }
>>> };
>>> @@ -3575,8 +3597,8 @@ static void test_ownerdata_multiselect(void)
>>> expect(0, res);
>>> ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>>> - ownerdata_multiselect_odstatechanged_seq,
>>> - "ownerdata select multiple notification", TRUE);
>>> + ownerdata_multiselect_select_0_to_1_seq,
>>> + "ownerdata multiselect: select multiple via SHIFT", TRUE);
>>> res = SendMessageA(hwnd, WM_KEYUP, VK_DOWN, 0);
>>> expect(0, res);
>>> @@ -3592,8 +3614,8 @@ static void test_ownerdata_multiselect(void)
>>> expect(0, res);
>>> ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>>> - ownerdata_multiselect_odstatechanged_seq,
>>> - "ownerdata select multiple notification", TRUE);
>>> + ownerdata_multiselect_select_0_to_2_seq,
>>> + "ownerdata multiselect: select multiple via SHIFT+CONTROL", TRUE);
>>> res = SendMessageA(hwnd, WM_KEYUP, VK_DOWN, 0);
>>> expect(0, res);
>>> @@ -3604,6 +3626,27 @@ static void test_ownerdata_multiselect(void)
>>> res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
>>> expect(3, res);
>>> + flush_sequences(sequences, NUM_MSG_SEQUENCES);
>>> +
>>> + res = SendMessageA(hwnd, WM_KEYDOWN, VK_DOWN, 0);
>>> + expect(0, res);
>>> +
>>> + ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>>> + ownerdata_multiselect_deselect_all_select_3_seq,
>>> + "ownerdata multiselect: deselect all, select item 3", TRUE);
>>> +
>>> + res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
>>> + expect(1, res);
>> Hi Angelo,
>>
>> Thanks for looking into this. There are a few things can be improved for this series.
>>
>> Please complete the keyboard sequence by sending WM_KEYUP for VK_DOWN and
>> WM_KEYUP for VK_UP.
> I'll add the WM_KEYUP events for sure. Not sure how that slipped.
>> Also please add tests for pressing VK_UP while holding Shift after setting pressing VK_DOWN while holding Shift.
>> Same for holding both Shift and Control And add checks for NMLVODSTATECHANGE member values. For example,
>> I don't think uOldState should always be 0.
>
> Happy to add more tests for VK_UP.
>
> With regards to the uOldState: I have not found an instance where it is not 0. Which kind of makes sense, at least according to the underlying logic.
>
> Windows seems to only use LVN_ODSTATECHANGED to set a new state (selection of multiple items). For un-setting (uOldState != 0) Windows will instead send an all items changed (LVN_ITEMCHANGED = -1) signal instead. That is at least what I have observed in my testing.
I see. Please add that tests as well.
>
>>> +
>>> + flush_sequences(sequences, NUM_MSG_SEQUENCES);
>>> +
>>> + res = SendMessageA(hwnd, WM_KEYDOWN, VK_UP, 0);
>>> + expect(0, res);
>>> +
>>> + ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>>> + ownerdata_multiselect_deselect_3_select_2_seq,
>>> + "ownerdata multiselect: deselect item 3, select item 2", TRUE);
>>> +
>>> DestroyWindow(hwnd);
>>> }
>>>
>
>
June 11, 2022
Re: [PATCH v2 resend 6/6] comctl32/listview: Fix deselect on LVS_OWNERDATA.
by Zhiyi Zhang
On 6/11/22 02:18, Angelo Haller wrote:
> On 10/06/2022 03.13, Zhiyi Zhang wrote:
>>
>> On 5/26/22 04:00, Angelo Haller wrote:
>>> From: Angelo Haller <angelo(a)szanni.org>
>>>
>>> Send one "deselect all items" notification on selection change for
>>> LVS_OWNERDATA listviews instead of notifying about each individual
>>> item change.
>>>
>>> Enable LVS_OWNERDATA multi select tests for wine.
>>>
>>> Signed-off-by: Angelo Haller <angelo(a)szanni.org>
>>> ---
>>> dlls/comctl32/listview.c | 6 ++++++
>>> dlls/comctl32/tests/listview.c | 8 ++++----
>>> 2 files changed, 10 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
>>> index bb394974906..a71e34b99d9 100644
>>> --- a/dlls/comctl32/listview.c
>>> +++ b/dlls/comctl32/listview.c
>>> @@ -3406,6 +3406,12 @@ static BOOL LISTVIEW_DeselectAllSkipItems(LISTVIEW_INFO *infoPtr, RANGES toSkip)
>>> lvItem.state = 0;
>>> lvItem.stateMask = LVIS_SELECTED;
>>> +
>>> + /* notify deselect of all items (-1) on LVS_OWNERDATA style */
>>> + if (infoPtr->dwStyle & LVS_OWNERDATA) {
>>> + LISTVIEW_SetItemState(infoPtr, -1, &lvItem);
>>> + return TRUE;
>>> + }
>> Please add a separate test for this. Select and then deselect all items instead of mixing it with other tests.
>
> Maybe the comment needs to be better. Deselect all (-1) is the ONLY signal ever sent on ANY deselection,
> be it one or multiple items (for LVS_OWNERDATA).
> This is how win32 implements it, hence there is no way of making this a separate test.
>
> Maybe the line should read:
>
> /* Always send one deselect all (-1) notification for LVS_OWNERDATA style instead of
> * informing individual items of deselection */
>
> And I am still looking into the other remarks. Some might need reordering as I won't be able to
> enable the tests without this last patch.
>
> Thanks for the feedback so far!
I was thinking adding a test that selects items, and them maybe send a mouse click somewhere
in the blank space of the listview control to deselect them all to show that only a -1 notification is sent.
But it may be difficult to get the tests work reliably. If you can't make it work, I guess mixing it with
other tests is okay.
>
>>> /* need to clone the DPA because callbacks can change it */
>>> if (!(clone = ranges_clone(infoPtr->selectionRanges))) return FALSE;
>>> diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
>>> index 78b3e3ae069..066858ac7e8 100644
>>> --- a/dlls/comctl32/tests/listview.c
>>> +++ b/dlls/comctl32/tests/listview.c
>>> @@ -3598,7 +3598,7 @@ static void test_ownerdata_multiselect(void)
>>> ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>>> ownerdata_multiselect_select_0_to_1_seq,
>>> - "ownerdata multiselect: select multiple via SHIFT", TRUE);
>>> + "ownerdata multiselect: select multiple via SHIFT", FALSE);
>>> res = SendMessageA(hwnd, WM_KEYUP, VK_DOWN, 0);
>>> expect(0, res);
>>> @@ -3615,7 +3615,7 @@ static void test_ownerdata_multiselect(void)
>>> ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>>> ownerdata_multiselect_select_0_to_2_seq,
>>> - "ownerdata multiselect: select multiple via SHIFT+CONTROL", TRUE);
>>> + "ownerdata multiselect: select multiple via SHIFT+CONTROL", FALSE);
>>> res = SendMessageA(hwnd, WM_KEYUP, VK_DOWN, 0);
>>> expect(0, res);
>>> @@ -3633,7 +3633,7 @@ static void test_ownerdata_multiselect(void)
>>> ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>>> ownerdata_multiselect_deselect_all_select_3_seq,
>>> - "ownerdata multiselect: deselect all, select item 3", TRUE);
>>> + "ownerdata multiselect: deselect all, select item 3", FALSE);
>>> res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
>>> expect(1, res);
>>> @@ -3645,7 +3645,7 @@ static void test_ownerdata_multiselect(void)
>>> ok_sequence(sequences, PARENT_ODSTATECHANGED_SEQ_INDEX,
>>> ownerdata_multiselect_deselect_3_select_2_seq,
>>> - "ownerdata multiselect: deselect item 3, select item 2", TRUE);
>>> + "ownerdata multiselect: deselect item 3, select item 2", FALSE);;
>> Extra ;
>>
>>
>> Thanks,
>> Zhiyi
>>
>>
>>> DestroyWindow(hwnd);
>>> }
>
>
June 11, 2022
June 11, 2022
June 11, 2022
Re: [PATCH v2 2/3] server: Don't reset socket error in poll_socket.
by Zebediah Figura
On 6/10/22 12:33, Piotr Caban wrote:
> -static inline int sock_error( struct fd *fd )
> +static inline int sock_error( struct sock *sock, int *error )
> {
> - unsigned int optval = 0;
> - socklen_t optlen = sizeof(optval);
> + socklen_t len = sizeof(*error);
>
> - getsockopt( get_unix_fd(fd), SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
> - return optval;
> + if (getsockopt( get_unix_fd(sock->fd), SOL_SOCKET, SO_ERROR, (void *)error, &len) < 0)
> + return -1;
I'd personally just throw away the getsockopt() return value check
instead; it should never fail.
June 11, 2022
Re: [PATCH v2 resend 3/6] comctl32/listview: Send LVN_ODSTATECHANGED only for virtual lists.
by Angelo Haller
On 10/06/2022 03.13, Zhiyi Zhang wrote:
>
> On 5/26/22 04:00, Angelo Haller wrote:
>> From: Angelo Haller <angelo(a)szanni.org>
>>
>> The LVN_ODSTATECHANGED notification should only be sent to lists
>> that have LVS_OWNERDATA set.
>>
>> Signed-off-by: Angelo Haller <angelo(a)szanni.org>
>> ---
>> dlls/comctl32/listview.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
>> index 72ade724313..318df0a4093 100644
>> --- a/dlls/comctl32/listview.c
>> +++ b/dlls/comctl32/listview.c
>> @@ -8946,6 +8946,7 @@ static VOID LISTVIEW_SetOwnerDataState(LISTVIEW_INFO *infoPtr, INT nFirst, INT n
>> {
>> NMLVODSTATECHANGE nmlv;
>>
>> + if (!(infoPtr->dwStyle & LVS_OWNERDATA)) return;
> Make sense. It will be better if you can add a simple test before this patch and remove the todo_wines after the fix.
Is this strictly necessary? The call site has special handling for:
infoPtr->dwStyle & LVS_OWNERDATA
We could guard the call to the function at the call site, if that is
preferred.
Apart from that I am not sure how to write a test for this. This bug is
triggered by creating a non ownerdata list and selecting multiple
entries holding shift+ctrl and clicking with the mouse. This will send
an LVN_ODSTATECHANGED notification where it is not supposed to (as it is
not an ownerdata list).
I have not found any test examples with mouse emulation. Maybe I missed
something.
Or should I open a separate bug report for this line?
>> if (!item) return;
>>
>> ZeroMemory(&nmlv, sizeof(nmlv));
June 10, 2022