[RICHED20_WINETEST] Sync with Wine Staging 3.9. CORE-14656
authorAmine Khaldi <amine.khaldi@reactos.org>
Mon, 4 Jun 2018 02:48:31 +0000 (03:48 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Mon, 4 Jun 2018 02:48:31 +0000 (03:48 +0100)
modules/rostests/winetests/riched20/editor.c
modules/rostests/winetests/riched20/richole.c
modules/rostests/winetests/riched20/txtsrv.c

index 0e0c960..6712ab1 100644 (file)
@@ -20,6 +20,8 @@
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */
 
+#define COBJMACROS
+
 #include <stdarg.h>
 #include <stdio.h>
 #include <assert.h>
@@ -30,6 +32,7 @@
 #include <winnls.h>
 #include <ole2.h>
 #include <richedit.h>
+#include <richole.h>
 #include <commdlg.h>
 #include <time.h>
 #include <wine/test.h>
@@ -8798,6 +8801,94 @@ static void test_para_numbering(void)
     DestroyWindow( edit );
 }
 
+static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj,
+                                 LPSTORAGE pstg, LPOLECLIENTSITE polesite, LONG sizel_cx,
+                                 LONG sizel_cy, DWORD aspect, DWORD flags, DWORD user)
+{
+    reobj->cbStruct = sizeof(*reobj);
+    reobj->clsid = CLSID_NULL;
+    reobj->cp = cp;
+    reobj->poleobj = poleobj;
+    reobj->pstg = pstg;
+    reobj->polesite = polesite;
+    reobj->sizel.cx = sizel_cx;
+    reobj->sizel.cy = sizel_cy;
+    reobj->dvaspect = aspect;
+    reobj->dwFlags = flags;
+    reobj->dwUser = user;
+}
+
+static void test_EM_SELECTIONTYPE(void)
+{
+    HWND hwnd = new_richedit(NULL);
+    IRichEditOle *reole = NULL;
+    static const char text1[] = "abcdefg\n";
+    int result;
+    REOBJECT reo1, reo2;
+    IOleClientSite *clientsite;
+    HRESULT hr;
+
+    SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)text1);
+    SendMessageA(hwnd, EM_GETOLEINTERFACE, 0, (LPARAM)&reole);
+
+    SendMessageA(hwnd, EM_SETSEL, 1, 1);
+    result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
+    ok(result == SEL_EMPTY, "got wrong selection type: %x.\n", result);
+
+    SendMessageA(hwnd, EM_SETSEL, 1, 2);
+    result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
+    ok(result == SEL_TEXT, "got wrong selection type: %x.\n", result);
+
+    SendMessageA(hwnd, EM_SETSEL, 2, 5);
+    result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
+    ok(result == (SEL_TEXT | SEL_MULTICHAR), "got wrong selection type: %x.\n", result);
+
+    SendMessageA(hwnd, EM_SETSEL, 0, 1);
+    hr = IRichEditOle_GetClientSite(reole, &clientsite);
+    ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
+    fill_reobject_struct(&reo1, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10,
+                         DVASPECT_CONTENT, 0, 1);
+    hr = IRichEditOle_InsertObject(reole, &reo1);
+    ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
+    IOleClientSite_Release(clientsite);
+
+    SendMessageA(hwnd, EM_SETSEL, 0, 1);
+    result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
+    ok(result == SEL_OBJECT, "got wrong selection type: %x.\n", result);
+
+    SendMessageA(hwnd, EM_SETSEL, 0, 2);
+    result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
+    ok(result == (SEL_TEXT | SEL_OBJECT), "got wrong selection type: %x.\n", result);
+
+    SendMessageA(hwnd, EM_SETSEL, 0, 3);
+    result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
+    ok(result == (SEL_TEXT | SEL_MULTICHAR | SEL_OBJECT), "got wrong selection type: %x.\n", result);
+
+    SendMessageA(hwnd, EM_SETSEL, 2, 3);
+    hr = IRichEditOle_GetClientSite(reole, &clientsite);
+    ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
+    fill_reobject_struct(&reo2, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10,
+                         DVASPECT_CONTENT, 0, 2);
+    hr = IRichEditOle_InsertObject(reole, &reo2);
+    ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
+    IOleClientSite_Release(clientsite);
+
+    SendMessageA(hwnd, EM_SETSEL, 0, 2);
+    result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
+    ok(result == (SEL_OBJECT | SEL_TEXT), "got wrong selection type: %x.\n", result);
+
+    SendMessageA(hwnd, EM_SETSEL, 0, 3);
+    result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
+    ok(result == (SEL_OBJECT | SEL_MULTIOBJECT | SEL_TEXT), "got wrong selection type: %x.\n", result);
+
+    SendMessageA(hwnd, EM_SETSEL, 0, 4);
+    result = SendMessageA(hwnd, EM_SELECTIONTYPE, 0, 0);
+    ok(result == (SEL_TEXT| SEL_MULTICHAR | SEL_OBJECT | SEL_MULTIOBJECT), "got wrong selection type: %x.\n", result);
+
+    IRichEditOle_Release(reole);
+    DestroyWindow(hwnd);
+}
+
 static void test_window_classes(void)
 {
     static const struct
@@ -8905,6 +8996,7 @@ START_TEST( editor )
   test_background();
   test_eop_char_fmt();
   test_para_numbering();
+  test_EM_SELECTIONTYPE();
 
   /* Set the environment variable WINETEST_RICHED20 to keep windows
    * responsive and open for 30 seconds. This is useful for debugging.
index 3a69819..617d1f9 100644 (file)
@@ -3132,39 +3132,152 @@ static void test_SetFont(void)
   ITextSelection_Release(selection);
 }
 
+static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj,
+                                 LPSTORAGE pstg, LPOLECLIENTSITE polesite, LONG sizel_cx,
+                                 LONG sizel_cy, DWORD aspect, DWORD flags, DWORD user)
+{
+  reobj->cbStruct = sizeof(*reobj);
+  reobj->clsid = CLSID_NULL;
+  reobj->cp = cp;
+  reobj->poleobj = poleobj;
+  reobj->pstg = pstg;
+  reobj->polesite = polesite;
+  reobj->sizel.cx = sizel_cx;
+  reobj->sizel.cy = sizel_cy;
+  reobj->dvaspect = aspect;
+  reobj->dwFlags = flags;
+  reobj->dwUser = user;
+}
+
+#define CHECK_REOBJECT_STRUCT(reobj,poleobj,pstg,polesite,user) \
+  _check_reobject_struct(reobj, poleobj, pstg, polesite, user, __LINE__)
+static void _check_reobject_struct(REOBJECT reobj, LPOLEOBJECT poleobj, LPSTORAGE pstg,
+                                  LPOLECLIENTSITE polesite, DWORD user, int line)
+{
+  ok_(__FILE__,line)(reobj.poleobj == poleobj, "got wrong object interface.\n");
+  ok_(__FILE__,line)(reobj.pstg == pstg, "got wrong storage interface.\n");
+  ok_(__FILE__,line)(reobj.polesite == polesite, "got wrong site interface.\n");
+  ok_(__FILE__,line)(reobj.dwUser == user, "got wrong user-defined value.\n");
+}
+
 static void test_InsertObject(void)
 {
+  static CHAR test_text1[] = "abcdefg";
   IRichEditOle *reole = NULL;
   ITextDocument *doc = NULL;
   IOleClientSite *clientsite;
-  REOBJECT reo;
+  REOBJECT reo1, reo2, reo3, received_reo1, received_reo2, received_reo3, received_reo4;
   HRESULT hr;
   HWND hwnd;
+  LONG count;
 
   create_interfaces(&hwnd, &reole, &doc, NULL);
+  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
 
   hr = IRichEditOle_InsertObject(reole, NULL);
   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
 
+  /* insert object1 in (0, 1)*/
+  SendMessageA(hwnd, EM_SETSEL, 0, 1);
   hr = IRichEditOle_GetClientSite(reole, &clientsite);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-
-  reo.cbStruct = sizeof(reo);
-  reo.cp = 0;
-  memset(&reo.clsid, 0, sizeof(reo.clsid));
-  reo.poleobj = NULL;
-  reo.pstg = NULL;
-  reo.polesite = clientsite;
-  reo.sizel.cx = 10;
-  reo.sizel.cy = 10;
-  reo.dvaspect = DVASPECT_CONTENT;
-  reo.dwFlags = 0;
-  reo.dwUser = 0;
+  ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
+  fill_reobject_struct(&reo1, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 1);
+  hr = IRichEditOle_InsertObject(reole, &reo1);
+  ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
+  count = IRichEditOle_GetObjectCount(reole);
+  ok(count == 1, "got wrong object count: %d\n", count);
+  IOleClientSite_Release(clientsite);
 
-  hr = IRichEditOle_InsertObject(reole, &reo);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
+  /* insert object2 in (2, 3)*/
+  SendMessageA(hwnd, EM_SETSEL, 2, 3);
+  hr = IRichEditOle_GetClientSite(reole, &clientsite);
+  ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
+  fill_reobject_struct(&reo2, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 2);
+  hr = IRichEditOle_InsertObject(reole, &reo2);
+  ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
+  count = IRichEditOle_GetObjectCount(reole);
+  ok(count == 2, "got wrong object count: %d\n", count);
+  IOleClientSite_Release(clientsite);
 
+  /* insert object3 in (1, 2)*/
+  SendMessageA(hwnd, EM_SETSEL, 1, 2);
+  hr = IRichEditOle_GetClientSite(reole, &clientsite);
+  ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
+  fill_reobject_struct(&reo3, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 3);
+  hr = IRichEditOle_InsertObject(reole, &reo3);
+  ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
+  count = IRichEditOle_GetObjectCount(reole);
+  ok(count == 3, "got wrong object count: %d\n", count);
   IOleClientSite_Release(clientsite);
+
+  /* tests below show that order of rebject (from 0 to 2) is: reo1,reo3,reo2 */
+  received_reo1.cbStruct = sizeof(received_reo1);
+  hr = IRichEditOle_GetObject(reole, 0, &received_reo1, REO_GETOBJ_ALL_INTERFACES);
+  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
+  CHECK_REOBJECT_STRUCT(received_reo1, NULL, NULL, reo1.polesite, 1);
+
+  received_reo2.cbStruct = sizeof(received_reo2);
+  hr = IRichEditOle_GetObject(reole, 1, &received_reo2, REO_GETOBJ_ALL_INTERFACES);
+  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
+  CHECK_REOBJECT_STRUCT(received_reo2, NULL, NULL, reo3.polesite, 3);
+
+  received_reo3.cbStruct = sizeof(received_reo3);
+  hr = IRichEditOle_GetObject(reole, 2, &received_reo3, REO_GETOBJ_ALL_INTERFACES);
+  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
+  CHECK_REOBJECT_STRUCT(received_reo3, NULL, NULL, reo2.polesite, 2);
+
+  hr = IRichEditOle_GetObject(reole, 2, NULL, REO_GETOBJ_ALL_INTERFACES);
+  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
+
+  received_reo4.cbStruct = 0;
+  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
+  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
+
+  received_reo4.cbStruct = sizeof(received_reo4);
+  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_PSTG);
+  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
+  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2);
+
+  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_POLESITE);
+  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
+  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2);
+
+  hr = IRichEditOle_GetObject(reole, 4, &received_reo4, REO_GETOBJ_POLESITE);
+  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
+
+  hr = IRichEditOle_GetObject(reole, 1024, &received_reo4, REO_GETOBJ_POLESITE);
+  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
+
+  /* received_reo4 will be zeroed before be used */
+  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_NO_INTERFACES);
+  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
+  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2);
+
+  received_reo4.cbStruct = sizeof(received_reo4);
+  received_reo4.cp = 0;
+  hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
+  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
+  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1);
+
+  received_reo4.cbStruct = sizeof(received_reo4);
+  received_reo4.cp = 1;
+  hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
+  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
+  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo3.polesite, 3);
+
+  received_reo4.cbStruct = sizeof(received_reo4);
+  received_reo4.cp = 2;
+  hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
+  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
+  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2);
+
+  received_reo4.cbStruct = sizeof(received_reo4);
+  received_reo4.cp = 4;
+  hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
+  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
+  /* received_reo4 didn't be zeroed in E_INVALIDARG case */
+  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2);
+
   release_interfaces(&hwnd, &reole, &doc, NULL);
 }
 
@@ -3310,6 +3423,64 @@ static void test_ITextSelection_GetDuplicate(void)
   ITextRange_Release(range);
 }
 
+#define RESET_RANGE(range,start,end) \
+  _reset_range(range, start, end, __LINE__)
+static void _reset_range(ITextRange *range, LONG start, LONG end, int line)
+{
+  HRESULT hr;
+
+  hr = ITextRange_SetStart(range, start);
+  ok_(__FILE__,line)(hr == S_OK, "SetStart failed: 0x%08x\n", hr);
+  hr = ITextRange_SetEnd(range, end);
+  ok_(__FILE__,line)(hr == S_OK, "SetEnd failed: 0x%08x\n", hr);
+}
+
+#define CHECK_RANGE(range,expected_start,expected_end) \
+  _check_range(range, expected_start, expected_end, __LINE__)
+static void _check_range(ITextRange* range, LONG expected_start, LONG expected_end, int line)
+{
+  HRESULT hr;
+  LONG value;
+
+  hr = ITextRange_GetStart(range, &value);
+  ok_(__FILE__,line)(hr == S_OK, "GetStart failed: 0x%08x\n", hr);
+  ok_(__FILE__,line)(value == expected_start, "Expected start %d got %d\n",
+                     expected_start, value);
+  hr = ITextRange_GetEnd(range, &value);
+  ok_(__FILE__,line)(hr == S_OK, "GetEnd failed: 0x%08x\n", hr);
+  ok_(__FILE__,line)(value == expected_end, "Expected end %d got %d\n",
+                     expected_end, value);
+}
+
+#define RESET_SELECTION(selection,start,end) \
+  _reset_selection(selection, start, end, __LINE__)
+static void _reset_selection(ITextSelection *selection, LONG start, LONG end, int line)
+{
+  HRESULT hr;
+
+  hr = ITextSelection_SetStart(selection, start);
+  ok_(__FILE__,line)(hr == S_OK, "SetStart failed: 0x%08x\n", hr);
+  hr = ITextSelection_SetEnd(selection, end);
+  ok_(__FILE__,line)(hr == S_OK, "SetEnd failed: 0x%08x\n", hr);
+}
+
+#define CHECK_SELECTION(selection,expected_start,expected_end) \
+  _check_selection(selection, expected_start, expected_end, __LINE__)
+static void _check_selection(ITextSelection *selection, LONG expected_start, LONG expected_end, int line)
+{
+  HRESULT hr;
+  LONG value;
+
+  hr = ITextSelection_GetStart(selection, &value);
+  ok_(__FILE__,line)(hr == S_OK, "GetStart failed: 0x%08x\n", hr);
+  ok_(__FILE__,line)(value == expected_start, "Expected start %d got %d\n",
+                     expected_start, value);
+  hr = ITextSelection_GetEnd(selection, &value);
+  ok_(__FILE__,line)(hr == S_OK, "GetEnd failed: 0x%08x\n", hr);
+  ok_(__FILE__,line)(value == expected_end, "Expected end %d got %d\n",
+                     expected_end, value);
+}
+
 static void test_Expand(void)
 {
   static const char test_text1[] = "TestSomeText";
@@ -3330,53 +3501,26 @@ static void test_Expand(void)
 
   hr = ITextRange_Expand(range, tomStory, NULL);
   ok(hr == S_OK, "got 0x%08x\n", hr);
-  hr = ITextRange_GetStart(range, &value);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-  ok(value == 0, "got %d\n", value);
-  hr = ITextRange_GetEnd(range, &value);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-  ok(value == 13, "got %d\n", value);
+  CHECK_RANGE(range, 0, 13);
 
   hr = ITextSelection_Expand(selection, tomStory, NULL);
   ok(hr == S_OK, "got 0x%08x\n", hr);
-  hr = ITextSelection_GetStart(selection, &value);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-  ok(value == 0, "got %d\n", value);
-  hr = ITextSelection_GetEnd(selection, &value);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-  ok(value == 13, "got %d\n", value);
+  CHECK_SELECTION(selection, 0, 13);
 
-  hr = ITextRange_SetStart(range, 1);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-  hr = ITextRange_SetEnd(range, 2);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-
-  hr = ITextSelection_SetStart(selection, 1);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-  hr = ITextSelection_SetEnd(selection, 2);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
+  RESET_RANGE(range, 1, 2);
+  RESET_SELECTION(selection, 1, 2);
 
   value = 0;
   hr = ITextRange_Expand(range, tomStory, &value);
   ok(hr == S_OK, "got 0x%08x\n", hr);
   ok(value == 12, "got %d\n", value);
-  hr = ITextRange_GetStart(range, &value);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-  ok(value == 0, "got %d\n", value);
-  hr = ITextRange_GetEnd(range, &value);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-  ok(value == 13, "got %d\n", value);
+  CHECK_RANGE(range, 0, 13);
 
   value = 0;
   hr = ITextSelection_Expand(selection, tomStory, &value);
   ok(hr == S_OK, "got 0x%08x\n", hr);
   ok(value == 12, "got %d\n", value);
-  hr = ITextSelection_GetStart(selection, &value);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-  ok(value == 0, "got %d\n", value);
-  hr = ITextSelection_GetEnd(selection, &value);
-  ok(hr == S_OK, "got 0x%08x\n", hr);
-  ok(value == 13, "got %d\n", value);
+  CHECK_SELECTION(selection, 0, 13);
 
   release_interfaces(&hwnd, &reole, &doc, NULL);
 
@@ -3396,6 +3540,120 @@ static void test_Expand(void)
   ITextRange_Release(range);
 }
 
+static void test_MoveEnd(void)
+{
+  static const char test_text1[] = "Word1 Word2";
+  IRichEditOle *reole = NULL;
+  ITextDocument *doc = NULL;
+  ITextSelection *selection;
+  ITextRange *range;
+  LONG delta;
+  HRESULT hr;
+  HWND hwnd;
+
+  create_interfaces(&hwnd, &reole, &doc, &selection);
+  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
+  SendMessageA(hwnd, EM_SETSEL, 1, 2);
+
+  hr = ITextDocument_Range(doc, 1, 2, &range);
+  ok(hr == S_OK, "got 0x%08x\n", hr);
+
+  hr = ITextRange_MoveEnd(range, tomStory, 0, &delta);
+  ok(hr == S_FALSE, "got 0x%08x\n", hr);
+  ok(delta == 0, "got %d\n", delta);
+  CHECK_RANGE(range, 1, 2);
+
+  hr = ITextRange_MoveEnd(range, tomStory, -1, &delta);
+  ok(hr == S_OK, "got 0x%08x\n", hr);
+  ok(delta == -1, "got %d\n", delta);
+  CHECK_RANGE(range, 0, 0);
+
+  hr = ITextRange_MoveEnd(range, tomStory, 1, &delta);
+  ok(hr == S_OK, "got 0x%08x\n", hr);
+  ok(delta == 1, "got %d\n", delta);
+  CHECK_RANGE(range, 0, 12);
+
+  hr = ITextRange_MoveEnd(range, tomStory, 1, &delta);
+  ok(hr == S_FALSE, "got 0x%08x\n", hr);
+  ok(delta == 0, "got %d\n", delta);
+  CHECK_RANGE(range, 0, 12);
+
+  RESET_RANGE(range, 1, 2);
+
+  hr = ITextRange_MoveEnd(range, tomStory, 3, &delta);
+  ok(hr == S_OK, "got 0x%08x\n", hr);
+  ok(delta == 1, "got %d\n", delta);
+  CHECK_RANGE(range, 1, 12);
+
+  RESET_RANGE(range, 2, 3);
+
+  hr = ITextRange_MoveEnd(range, tomStory, -3, &delta);
+  ok(hr == S_OK, "got 0x%08x\n", hr);
+  ok(delta == -1, "got %d\n", delta);
+  CHECK_RANGE(range, 0, 0);
+
+  hr = ITextRange_MoveEnd(range, tomStory, -1, &delta);
+  ok(hr == S_FALSE, "got 0x%08x\n", hr);
+  ok(delta == 0, "got %d\n", delta);
+  CHECK_RANGE(range, 0, 0);
+
+  hr = ITextSelection_MoveEnd(selection, tomStory, 0, &delta);
+  ok(hr == S_FALSE, "got 0x%08x\n", hr);
+  ok(delta == 0, "got %d\n", delta);
+  CHECK_SELECTION(selection, 1, 2);
+
+  hr = ITextSelection_MoveEnd(selection, tomStory, -1, &delta);
+  ok(hr == S_OK, "got 0x%08x\n", hr);
+  ok(delta == -1, "got %d\n", delta);
+  CHECK_SELECTION(selection, 0, 0);
+
+  hr = ITextSelection_MoveEnd(selection, tomStory, 1, &delta);
+  ok(hr == S_OK, "got 0x%08x\n", hr);
+  ok(delta == 1, "got %d\n", delta);
+  CHECK_SELECTION(selection, 0, 12);
+
+  hr = ITextSelection_MoveEnd(selection, tomStory, 1, &delta);
+  ok(hr == S_FALSE, "got 0x%08x\n", hr);
+  ok(delta == 0, "got %d\n", delta);
+  CHECK_SELECTION(selection, 0, 12);
+
+  RESET_SELECTION(selection, 1, 2);
+
+  hr = ITextSelection_MoveEnd(selection, tomStory, 3, &delta);
+  ok(hr == S_OK, "got 0x%08x\n", hr);
+  ok(delta == 1, "got %d\n", delta);
+  CHECK_SELECTION(selection, 1, 12);
+
+  RESET_SELECTION(selection, 2, 3);
+
+  hr = ITextSelection_MoveEnd(selection, tomStory, -3, &delta);
+  ok(hr == S_OK, "got 0x%08x\n", hr);
+  ok(delta == -1, "got %d\n", delta);
+  CHECK_SELECTION(selection, 0, 0);
+
+  hr = ITextSelection_MoveEnd(selection, tomStory, -1, &delta);
+  ok(hr == S_FALSE, "got 0x%08x\n", hr);
+  ok(delta == 0, "got %d\n", delta);
+  CHECK_SELECTION(selection, 0, 0);
+
+  release_interfaces(&hwnd, &reole, &doc, NULL);
+
+  hr = ITextRange_MoveEnd(range, tomStory, 1, NULL);
+  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
+
+  hr = ITextRange_MoveEnd(range, tomStory, 1, &delta);
+  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
+
+  hr = ITextSelection_MoveEnd(selection, tomStory, 1, NULL);
+  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
+
+  hr = ITextSelection_MoveEnd(selection, tomStory, 1, &delta);
+  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
+
+  ITextSelection_Release(selection);
+  ITextRange_Release(range);
+}
+
 static void test_ITextRange_SetStart(void)
 {
   HWND w;
@@ -3890,4 +4148,5 @@ START_TEST(richole)
   test_GetStoryLength();
   test_ITextSelection_GetDuplicate();
   test_Expand();
+  test_MoveEnd();
 }
index 73ca7cd..88b5adf 100644 (file)
@@ -654,6 +654,7 @@ static void test_TxGetText(void)
 
     hres = ITextServices_TxGetText(txtserv, &rettext);
     ok(hres == S_OK, "ITextServices_TxGetText failed (result = %x)\n", hres);
+    SysFreeString(rettext);
 
     ITextServices_Release(txtserv);
     ITextHost_Release(host);