[PATCH 1/2] riched20/tests: Add tests for IRichEditOleCallback_QueryInsertObject.

Jinoh Kang jinoh.kang.kr at gmail.com
Thu Mar 31 09:39:05 CDT 2022


Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---
 dlls/riched20/tests/richole.c | 247 ++++++++++++++++++++++++++++++++--
 1 file changed, 236 insertions(+), 11 deletions(-)

diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index 24284a24484..bb99a9a7276 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -33,6 +33,169 @@
 #include <tom.h>
 #include <wine/test.h>
 
+#define EXPECT_TODO_WINE 0x80000000UL
+
+typedef struct IRichEditOleCallbackImpl {
+    IRichEditOleCallback IRichEditOleCallback_iface;
+    LONG ref;
+    int line;
+
+    ULONG expect_queryinsertobject;
+
+    const CLSID *lpclsid;
+    LPSTORAGE lpstg;
+    LONG cp;
+    HRESULT queryinsertobject_result;
+};
+
+static inline struct IRichEditOleCallbackImpl *impl_from_IRichEditOleCallback(IRichEditOleCallback *iface)
+{
+    return CONTAINING_RECORD(iface, struct IRichEditOleCallbackImpl, IRichEditOleCallback_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_QueryInterface(IRichEditOleCallback *iface, REFIID riid, void **ppvObj)
+{
+    if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IRichEditOleCallback)) {
+        IRichEditOleCallback_AddRef(iface);
+        *ppvObj = iface;
+        return S_OK;
+    }
+    *ppvObj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE RichEditOleCallbackImpl_AddRef(IRichEditOleCallback *iface)
+{
+    struct IRichEditOleCallbackImpl *This = impl_from_IRichEditOleCallback(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+    return ref;
+}
+
+static ULONG STDMETHODCALLTYPE RichEditOleCallbackImpl_Release(IRichEditOleCallback *iface)
+{
+    struct IRichEditOleCallbackImpl *This = impl_from_IRichEditOleCallback(iface);
+    ULONG ref = InterlockedDecrement(&This->ref);
+    if (!ref) free(This);
+    return ref;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_GetNewStorage(IRichEditOleCallback *iface, LPSTORAGE *lplpstg)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_GetInPlaceContext(IRichEditOleCallback *iface, LPOLEINPLACEFRAME *lplpFrame, LPOLEINPLACEUIWINDOW *lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo)
+{
+    return E_INVALIDARG;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_ShowContainerUI(IRichEditOleCallback *iface, BOOL fShow)
+{
+    return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_QueryInsertObject(IRichEditOleCallback *iface, LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp)
+{
+    struct IRichEditOleCallbackImpl *This = impl_from_IRichEditOleCallback(iface);
+    ULONG expect = This->expect_queryinsertobject;
+
+    todo_wine_if(expect & EXPECT_TODO_WINE)
+    ok_(__FILE__,This->line)( expect & ~EXPECT_TODO_WINE, "unexpected call to IRichEditOleCallback_QueryInsertObject\n");
+    if (!(expect & ~EXPECT_TODO_WINE)) return S_OK;
+    This->expect_queryinsertobject--;
+
+    if (This->lpclsid && lpclsid)
+        ok_(__FILE__,This->line)( IsEqualGUID(This->lpclsid, lpclsid), "QueryInsertObject lpclsid expected %s, got %s\n", wine_dbgstr_guid( This->lpclsid ), wine_dbgstr_guid( lpclsid ));
+    else
+        ok_(__FILE__,This->line)( This->lpclsid == lpclsid, "QueryInsertObject lpclsid expected %p, got %p\n", This->lpclsid, lpclsid );
+    ok_(__FILE__,This->line)( This->lpstg == lpstg, "QueryInsertObject lpstg expected %p, got %p\n", This->lpstg, lpstg );
+    ok_(__FILE__,This->line)( This->cp == cp, "QueryInsertObject cp expected %ld, got %ld\n", This->cp, cp );
+    return This->queryinsertobject_result;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_DeleteObject(IRichEditOleCallback *iface, LPOLEOBJECT lpoleobj)
+{
+    return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_QueryAcceptData(IRichEditOleCallback *iface, LPDATAOBJECT lpdataobj, CLIPFORMAT *lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict)
+{
+    return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_ContextSensitiveHelp(IRichEditOleCallback *iface, BOOL fEnterMode)
+{
+    return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_GetClipboardData(IRichEditOleCallback *iface, CHARRANGE *lpchrg, DWORD reco, LPDATAOBJECT *lplpdataobj)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_GetDragDropEffect(IRichEditOleCallback *iface, BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect)
+{
+    if (pdwEffect) *pdwEffect = DROPEFFECT_COPY;
+    return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_GetContextMenu(IRichEditOleCallback *iface, WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE *lpchrg, HMENU *lphmenu)
+{
+    return E_NOTIMPL;
+}
+
+static const struct IRichEditOleCallbackVtbl RichEditOleCallbackImpl_Vtbl = {
+    RichEditOleCallbackImpl_QueryInterface,
+    RichEditOleCallbackImpl_AddRef,
+    RichEditOleCallbackImpl_Release,
+    RichEditOleCallbackImpl_GetNewStorage,
+    RichEditOleCallbackImpl_GetInPlaceContext,
+    RichEditOleCallbackImpl_ShowContainerUI,
+    RichEditOleCallbackImpl_QueryInsertObject,
+    RichEditOleCallbackImpl_DeleteObject,
+    RichEditOleCallbackImpl_QueryAcceptData,
+    RichEditOleCallbackImpl_ContextSensitiveHelp,
+    RichEditOleCallbackImpl_GetClipboardData,
+    RichEditOleCallbackImpl_GetDragDropEffect,
+    RichEditOleCallbackImpl_GetContextMenu,
+};
+
+static HRESULT RichEditOleCallbackImpl_Create(struct IRichEditOleCallbackImpl **objptr)
+{
+    struct IRichEditOleCallbackImpl *obj;
+
+    obj = calloc(sizeof(struct IRichEditOleCallbackImpl), 1);
+    if (!obj) return E_OUTOFMEMORY;
+
+    obj->IRichEditOleCallback_iface.lpVtbl = &RichEditOleCallbackImpl_Vtbl;
+    obj->ref = 1;
+
+    *objptr = obj;
+    return S_OK;
+}
+
+static void olecb_expect_QueryInsertObject(struct IRichEditOleCallbackImpl *This, int line, ULONG expect, const CLSID *lpclsid, LPSTORAGE lpstg, LONG cp, HRESULT result)
+{
+    if (!This) return;
+
+    This->line = line;
+    This->expect_queryinsertobject = expect;
+    This->lpclsid = lpclsid;
+    This->lpstg = lpstg;
+    This->cp = cp;
+    This->queryinsertobject_result = result;
+}
+
+static void olecb_check_QueryInsertObject(struct IRichEditOleCallbackImpl *This, int line)
+{
+    if (!This) return;
+
+    todo_wine_if(This->expect_queryinsertobject & EXPECT_TODO_WINE)
+    ok(!(This->expect_queryinsertobject & ~EXPECT_TODO_WINE), "expected IRichEditOleCallback_QueryInsertObject to be called\n");
+
+    olecb_expect_QueryInsertObject(This, 0, 0, NULL, NULL, 0, S_OK);
+}
+
 static HMODULE hmoduleRichEdit;
 
 DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -3233,21 +3396,24 @@ static void _check_reobject_struct(IRichEditOle *reole, LONG index, DWORD flags,
   ok_(__FILE__,line)(reobj.dwUser == user, "got wrong user-defined value.\n");
 }
 
-#define INSERT_REOBJECT(reole,reobj,cp,user) \
-  _insert_reobject(reole, reobj, cp, user, __LINE__)
-static void _insert_reobject(IRichEditOle *reole, REOBJECT *reobj, LONG cp, DWORD user, int line)
+#define INSERT_REOBJECT(callback,reole,reobj,cp,user) \
+  _insert_reobject(callback, reole, reobj, cp, user, __LINE__)
+static void _insert_reobject(struct IRichEditOleCallbackImpl *callback, IRichEditOle *reole, REOBJECT *reobj, LONG cp, DWORD user, int line)
 {
   IOleClientSite *clientsite;
   HRESULT hr;
+
+  olecb_expect_QueryInsertObject(callback, line, EXPECT_TODO_WINE | 1, &CLSID_NULL, NULL, REO_CP_SELECTION /* cp overriden */, S_OK);
   hr = IRichEditOle_GetClientSite(reole, &clientsite);
   ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
   fill_reobject_struct(reobj, cp, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, user);
   hr = IRichEditOle_InsertObject(reole, reobj);
   ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_InsertObject got hr %#lx.\n", hr);
   IOleClientSite_Release(clientsite);
+  olecb_check_QueryInsertObject(callback, line);
 }
 
-static void test_InsertObject(void)
+static void subtest_InsertObject(struct IRichEditOleCallbackImpl *callback)
 {
   static CHAR test_text1[] = "abcdefg";
   IRichEditOle *reole = NULL;
@@ -3271,6 +3437,12 @@ static void test_InsertObject(void)
   BSTR bstr;
 
   create_interfaces(&hwnd, &reole, &doc, &selection);
+  if (callback)
+  {
+    LRESULT sendres = SendMessageA(hwnd, EM_SETOLECALLBACK, 0, (LPARAM)&callback->IRichEditOleCallback_iface);
+    ok( !!sendres, "EM_SETOLECALLBACK should succeed\n" );
+  }
+
   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
 
   hr = IRichEditOle_InsertObject(reole, NULL);
@@ -3278,22 +3450,47 @@ static void test_InsertObject(void)
 
   /* insert object1 in (0, 1)*/
   SendMessageA(hwnd, EM_SETSEL, 0, 1);
-  INSERT_REOBJECT(reole, &reo1, REO_CP_SELECTION, 1);
+  INSERT_REOBJECT(callback, reole, &reo1, REO_CP_SELECTION, 1);
   count = IRichEditOle_GetObjectCount(reole);
   ok(count == 1, "got wrong object count: %ld\n", count);
 
   /* insert object2 in (2, 3)*/
   SendMessageA(hwnd, EM_SETSEL, 2, 3);
-  INSERT_REOBJECT(reole, &reo2, REO_CP_SELECTION, 2);
+  INSERT_REOBJECT(callback, reole, &reo2, REO_CP_SELECTION, 2);
   count = IRichEditOle_GetObjectCount(reole);
   ok(count == 2, "got wrong object count: %ld\n", count);
 
   /* insert object3 in (1, 2)*/
   SendMessageA(hwnd, EM_SETSEL, 1, 2);
-  INSERT_REOBJECT(reole, &reo3, REO_CP_SELECTION, 3);
+  INSERT_REOBJECT(callback, reole, &reo3, REO_CP_SELECTION, 3);
   count = IRichEditOle_GetObjectCount(reole);
   ok(count == 3, "got wrong object count: %ld\n", count);
 
+  if (callback)
+  {
+    IOleClientSite *clientsite;
+    REOBJECT reobj;
+
+    /* (fail to) insert object1 in (3, 4)*/
+    SendMessageA(hwnd, EM_SETSEL, 3, 4);
+
+    hr = IRichEditOle_GetClientSite(reole, &clientsite);
+    ok(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
+
+    olecb_expect_QueryInsertObject(callback, __LINE__, EXPECT_TODO_WINE | 1, &CLSID_NULL, NULL, REO_CP_SELECTION, S_FALSE);
+    fill_reobject_struct(&reobj, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 0);
+    hr = IRichEditOle_InsertObject(reole, &reobj);
+    todo_wine
+    ok(hr == S_FALSE, "IRichEditOle_InsertObject got hr %#lx.\n", hr);
+    olecb_check_QueryInsertObject(callback, __LINE__);
+
+    IOleClientSite_Release(clientsite);
+
+    count = IRichEditOle_GetObjectCount(reole);
+    todo_wine
+    ok(count == 3, "got wrong object count: %ld\n", count);
+  }
+
   /* tests below show that order of rebject (from 0 to 2) is: reo1,reo3,reo2 */
   CHECK_REOBJECT_STRUCT(reole, 0, REO_GETOBJ_ALL_INTERFACES, 0, 0, NULL, NULL, reo1.polesite, 1);
   CHECK_REOBJECT_STRUCT(reole, 1, REO_GETOBJ_ALL_INTERFACES, 0, 1, NULL, NULL, reo3.polesite, 3);
@@ -3371,8 +3568,8 @@ static void test_InsertObject(void)
   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
 
   /* "abc|d|efg" */
-  INSERT_REOBJECT(reole, &reo1, 3, 1);
-  INSERT_REOBJECT(reole, &reo2, 5, 2);
+  INSERT_REOBJECT(callback, reole, &reo1, 3, 1);
+  INSERT_REOBJECT(callback, reole, &reo2, 5, 2);
 
   SendMessageW(hwnd, EM_SETSEL, 2, 3);
   result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0);
@@ -3473,8 +3670,8 @@ static void test_InsertObject(void)
   ok(!result, "Got result %lx.\n", result);
   /* "abc|d|efg" */
   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
-  INSERT_REOBJECT(reole, &reo1, 3, 1);
-  INSERT_REOBJECT(reole, &reo2, 5, 2);
+  INSERT_REOBJECT(callback, reole, &reo1, 3, 1);
+  INSERT_REOBJECT(callback, reole, &reo2, 5, 2);
 
   expected_string = L"abc d efg";
   charrange.cpMin = 0;
@@ -3551,9 +3748,37 @@ static void test_InsertObject(void)
   ok(hr == S_OK, "Got hr %#lx.\n", hr);
   todo_wine ok(result == 0xfffc, "Got char: %lc\n", (WCHAR)result);
 
+  if (callback)
+  {
+    LRESULT sendres = SendMessageA(hwnd, EM_SETOLECALLBACK, 0, 0);
+    ok( !!sendres, "EM_SETOLECALLBACK should succeed\n" );
+  }
+
   release_interfaces(&hwnd, &reole, &doc, &selection);
 }
 
+static void test_InsertObject(void)
+{
+  struct IRichEditOleCallbackImpl *callback;
+  HRESULT hr;
+  ULONG ref;
+
+  subtest_InsertObject(NULL);
+
+  hr = RichEditOleCallbackImpl_Create(&callback);
+  ok(SUCCEEDED(hr), "RichEditOleCallbackImpl_Create returned %#lx\n", hr);
+  if (SUCCEEDED(hr))
+  {
+    subtest_InsertObject(callback);
+    ref = IRichEditOleCallback_Release(&callback->IRichEditOleCallback_iface);
+    ok(ref == 0, "expected IRichEditOleCallback recount to be 0, got %lu\n", ref);
+  }
+  else
+  {
+    skip("cannot test InsertObject with callback\n");
+  }
+}
+
 static void test_GetStoryLength(void)
 {
   static const CHAR test_text1[] = "TestSomeText";
-- 
2.34.1




More information about the wine-devel mailing list