[PATCH v2 2/3] ole32: Add local user marshalling for bitmaps.

Zebediah Figura zfigura at codeweavers.com
Thu Dec 7 11:20:11 CST 2017


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/ole32/tests/usrmarshal.c | 32 ++++++++++++++++++-
 dlls/ole32/usrmarshal.c       | 73 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/dlls/ole32/tests/usrmarshal.c b/dlls/ole32/tests/usrmarshal.c
index aaf3556abd..839ade07eb 100644
--- a/dlls/ole32/tests/usrmarshal.c
+++ b/dlls/ole32/tests/usrmarshal.c
@@ -1192,16 +1192,22 @@ static void test_marshal_HBRUSH(void)
 
 static void test_marshal_HBITMAP(void)
 {
+    static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
     static BYTE bmp_bits[1024];
     MIDL_STUB_MESSAGE stub_msg;
     HBITMAP hBitmap, hBitmap2;
     USER_MARSHAL_CB umcb;
     RPC_MESSAGE rpc_msg;
     unsigned char *buffer, *buffer_end;
-    ULONG size;
+    unsigned char bitmap[1024];
+    ULONG size, bitmap_size;
 
     hBitmap = CreateBitmap(16, 16, 1, 1, bmp_bits);
     ok(hBitmap != 0, "CreateBitmap failed\n");
+    size = GetObjectA(hBitmap, sizeof(bitmap), bitmap);
+    ok(size != 0, "GetObject failed\n");
+    bitmap_size = GetBitmapBits(hBitmap, 0, NULL);
+    ok(bitmap_size != 0, "GetBitmapBits failed\n");
 
     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
     size = HBITMAP_UserSize(&umcb.Flags, 1, &hBitmap);
@@ -1220,6 +1226,30 @@ static void test_marshal_HBITMAP(void)
 
     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
     HBITMAP_UserFree(&umcb.Flags, &hBitmap2);
+
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
+    size = HBITMAP_UserSize(&umcb.Flags, 1, &hBitmap);
+    ok(size == 0x10 + header_size + bitmap_size ||
+       broken(size == 0x14 + header_size + bitmap_size), /* Windows adds 4 extra (unused) bytes */
+       "Wrong size %d\n", size);
+
+    buffer = HeapAlloc(GetProcessHeap(), 0, size + 4);
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
+    buffer_end = HBITMAP_UserMarshal(&umcb.Flags, buffer + 1, &hBitmap);
+    ok(buffer_end == buffer + 0x10 + header_size + bitmap_size, "HBITMAP_UserMarshal() returned wrong size %d\n", (LONG)(buffer_end - buffer));
+    ok(*(ULONG *)(buffer + 0x4) == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)buffer);
+    ok(*(ULONG *)(buffer + 0x8) == (ULONG)(ULONG_PTR)hBitmap, "wirestgm + 0x4 should be bitmap handle instead of 0x%08x\n", *(ULONG *)(buffer + 0x4));
+    ok(*(ULONG *)(buffer + 0xc) == (ULONG)(ULONG_PTR)bitmap_size, "wirestgm + 0x8 should be bitmap size instead of 0x%08x\n", *(ULONG *)(buffer + 0x4));
+    ok(!memcmp(buffer + 0x10, bitmap, header_size), "buffer mismatch\n");
+    ok(!memcmp(buffer + 0x10 + header_size, bmp_bits, bitmap_size), "buffer mismatch\n");
+
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
+    HBITMAP_UserUnmarshal(&umcb.Flags, buffer + 1, &hBitmap2);
+    ok(hBitmap2 != NULL, "Didn't unmarshal properly\n");
+    HeapFree(GetProcessHeap(), 0, buffer);
+
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
+    HBITMAP_UserFree(&umcb.Flags, &hBitmap2);
     DeleteObject(hBitmap);
 }
 
diff --git a/dlls/ole32/usrmarshal.c b/dlls/ole32/usrmarshal.c
index 696b243043..015c6a7ec8 100644
--- a/dlls/ole32/usrmarshal.c
+++ b/dlls/ole32/usrmarshal.c
@@ -593,6 +593,17 @@ ULONG __RPC_USER HBITMAP_UserSize(ULONG *flags, ULONG size, HBITMAP *bmp)
     size += sizeof(ULONG);
     if (LOWORD(*flags) == MSHCTX_INPROC)
         size += sizeof(ULONG);
+    else
+    {
+        size += sizeof(ULONG);
+
+        if (*bmp)
+        {
+            size += sizeof(ULONG);
+            size += FIELD_OFFSET(userBITMAP, cbSize);
+            size += GetBitmapBits(*bmp, 0, NULL);
+        }
+    }
 
     return size;
 }
@@ -629,6 +640,31 @@ unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *flags, unsigned char *buff
         *(ULONG *)buffer = (ULONG)(ULONG_PTR)*bmp;
         buffer += sizeof(ULONG);
     }
+    else
+    {
+        *(ULONG *)buffer = WDT_REMOTE_CALL;
+        buffer += sizeof(ULONG);
+        *(ULONG *)buffer = (ULONG)(ULONG_PTR)*bmp;
+        buffer += sizeof(ULONG);
+
+        if (*bmp)
+        {
+            static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
+            BITMAP bitmap;
+            ULONG bitmap_size;
+
+            bitmap_size = GetBitmapBits(*bmp, 0, NULL);
+            *(ULONG *)buffer = bitmap_size;
+            buffer += sizeof(ULONG);
+
+            GetObjectW(*bmp, sizeof(BITMAP), &bitmap);
+            memcpy(buffer, &bitmap, header_size);
+            buffer += header_size;
+
+            GetBitmapBits(*bmp, bitmap_size, buffer);
+            buffer += bitmap_size;
+        }
+    }
     return buffer;
 }
 
@@ -667,6 +703,36 @@ unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *flags, unsigned char *bu
         *bmp = *(HBITMAP *)buffer;
         buffer += sizeof(*bmp);
     }
+    else if (context == WDT_REMOTE_CALL)
+    {
+        ULONG handle = *(ULONG *)buffer;
+        buffer += sizeof(ULONG);
+
+        if (handle)
+        {
+            static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
+            BITMAP bitmap;
+            ULONG bitmap_size;
+            unsigned char *bits;
+
+            bitmap_size = *(ULONG *)buffer;
+            buffer += sizeof(ULONG);
+            bits = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
+
+            memcpy(&bitmap, buffer, header_size);
+            buffer += header_size;
+
+            memcpy(bits, buffer, bitmap_size);
+            buffer += bitmap_size;
+
+            bitmap.bmBits = bits;
+            *bmp = CreateBitmapIndirect(&bitmap);
+
+            HeapFree(GetProcessHeap(), 0, bits);
+        }
+        else
+            *bmp = NULL;
+    }
     else
         RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
 
@@ -691,9 +757,12 @@ unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *flags, unsigned char *bu
  *  which the first parameter is a ULONG.
  *  This function is only intended to be called by the RPC runtime.
  */
-void __RPC_USER HBITMAP_UserFree(ULONG *pFlags, HBITMAP *phBmp)
+void __RPC_USER HBITMAP_UserFree(ULONG *flags, HBITMAP *bmp)
 {
-    FIXME(":stub\n");
+    TRACE("(%s, %p)\n", debugstr_user_flags(flags), *bmp);
+
+    if (LOWORD(*flags) != MSHCTX_INPROC)
+        DeleteObject(*bmp);
 }
 
 /******************************************************************************
-- 
2.15.1




More information about the wine-devel mailing list