[PATCH] ole32: Add user marshalling for bitmaps.

Zebediah Figura zfigura at codeweavers.com
Thu Nov 30 19:14:56 CST 2017


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/ole32/tests/usrmarshal.c |  46 +++++++++++++++
 dlls/ole32/usrmarshal.c       | 126 +++++++++++++++++++++++++++++++++++++-----
 2 files changed, 158 insertions(+), 14 deletions(-)

diff --git a/dlls/ole32/tests/usrmarshal.c b/dlls/ole32/tests/usrmarshal.c
index 529ad757c6a..ba62bb08c23 100644
--- a/dlls/ole32/tests/usrmarshal.c
+++ b/dlls/ole32/tests/usrmarshal.c
@@ -1190,6 +1190,51 @@ static void test_marshal_HBRUSH(void)
     DeleteObject(hBrush);
 }
 
+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;
+    unsigned char bitmap[1024];
+    ULONG size, bitmap_size;
+
+    memset(bmp_bits, 0xbb, sizeof(bmp_bits));
+    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_LOCAL);
+    size = HBITMAP_UserSize(&umcb.Flags, 0, &hBitmap);
+    ok(size == 0xc + header_size + bitmap_size ||
+       broken(size == 0x10 + header_size + bitmap_size), /* Windows adds 4 extra (unused) bytes */
+       "Wrong size %d\n", size);
+
+    buffer = HeapAlloc(GetProcessHeap(), 0, size);
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
+    HBITMAP_UserMarshal(&umcb.Flags, buffer, &hBitmap);
+    ok(*(ULONG *)buffer == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)buffer);
+    ok(*(ULONG *)(buffer + 0x4) == (ULONG)(ULONG_PTR)hBitmap, "wirestgm + 0x4 should be bitmap handle instead of 0x%08x\n", *(ULONG *)(buffer + 0x4));
+    ok(*(ULONG *)(buffer + 0x8) == (ULONG)(ULONG_PTR)bitmap_size, "wirestgm + 0x8 should be bitmap size instead of 0x%08x\n", *(ULONG *)(buffer + 0x4));
+    ok(!memcmp(buffer + 0xc, bitmap, header_size), "buffer mismatch\n");
+    ok(!memcmp(buffer + 0xc + 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, &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);
+}
+
 struct obj
 {
     IDataObject IDataObject_iface;
@@ -1353,6 +1398,7 @@ START_TEST(usrmarshal)
     test_marshal_HDC();
     test_marshal_HICON();
     test_marshal_HBRUSH();
+    test_marshal_HBITMAP();
 
     test_GetDataHere_Proxy();
 
diff --git a/dlls/ole32/usrmarshal.c b/dlls/ole32/usrmarshal.c
index 03ad689f03b..605cdbc1822 100644
--- a/dlls/ole32/usrmarshal.c
+++ b/dlls/ole32/usrmarshal.c
@@ -586,8 +586,26 @@ void __RPC_USER HGLOBAL_UserFree(ULONG *pFlags, HGLOBAL *phGlobal)
  */
 ULONG __RPC_USER HBITMAP_UserSize(ULONG *pFlags, ULONG StartingSize, HBITMAP *phBmp)
 {
-    FIXME(":stub\n");
-    return StartingSize;
+    ULONG size = StartingSize;
+
+    TRACE("(%s, %d, %p)\n", debugstr_user_flags(pFlags), StartingSize, *phBmp);
+
+    size += sizeof(ULONG);
+    if (LOWORD(*pFlags) == MSHCTX_INPROC)
+        size += sizeof(ULONG_PTR);
+    else
+    {
+        size += sizeof(ULONG);
+
+        if (*phBmp)
+        {
+            size += sizeof(ULONG);
+            size += FIELD_OFFSET(userBITMAP, cbSize);
+            size += GetBitmapBits(*phBmp, 0, NULL);
+        }
+    }
+
+    return size;
 }
 
 /******************************************************************************
@@ -611,7 +629,43 @@ ULONG __RPC_USER HBITMAP_UserSize(ULONG *pFlags, ULONG StartingSize, HBITMAP *ph
 */
 unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HBITMAP *phBmp)
 {
-    FIXME(":stub\n");
+    TRACE("(%s, %p, %p)\n", debugstr_user_flags(pFlags), pBuffer, *phBmp);
+
+    if (LOWORD(*pFlags) == MSHCTX_INPROC)
+    {
+        if (sizeof(*phBmp) == 8)
+            *(ULONG *)pBuffer = WDT_INPROC64_CALL;
+        else
+            *(ULONG *)pBuffer = WDT_INPROC_CALL;
+        pBuffer += sizeof(ULONG);
+        *(HBITMAP *)pBuffer = *phBmp;
+        pBuffer += sizeof(HBITMAP);
+    }
+    else
+    {
+        *(ULONG *)pBuffer = WDT_REMOTE_CALL;
+        pBuffer += sizeof(ULONG);
+        *(ULONG *)pBuffer = (ULONG)(ULONG_PTR)*phBmp;
+        pBuffer += sizeof(ULONG);
+
+        if (*phBmp)
+        {
+            static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
+            BITMAP bitmap;
+            ULONG bitmap_size;
+
+            bitmap_size = GetBitmapBits(*phBmp, 0, NULL);
+            *(ULONG *)pBuffer = bitmap_size;
+            pBuffer += sizeof(ULONG);
+
+            GetObjectW(*phBmp, sizeof(BITMAP), &bitmap);
+            memcpy(pBuffer, &bitmap, header_size);
+            pBuffer += header_size;
+
+            GetBitmapBits(*phBmp, bitmap_size, pBuffer);
+            pBuffer += bitmap_size;
+        }
+    }
     return pBuffer;
 }
 
@@ -636,7 +690,54 @@ unsigned char * __RPC_USER HBITMAP_UserMarshal(ULONG *pFlags, unsigned char *pBu
  */
 unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HBITMAP *phBmp)
 {
-    FIXME(":stub\n");
+    ULONG fContext;
+
+    TRACE("(%s, %p, %p)\n", debugstr_user_flags(pFlags), pBuffer, phBmp);
+
+    fContext = *(ULONG *)pBuffer;
+    pBuffer += sizeof(ULONG);
+
+    if (((fContext == WDT_INPROC_CALL) && (sizeof(*phBmp) < 8)) ||
+        ((fContext == WDT_INPROC64_CALL) && (sizeof(*phBmp) == 8)))
+    {
+        *phBmp = *(HBITMAP *)pBuffer;
+        pBuffer += sizeof(*phBmp);
+    }
+    else if (fContext == WDT_REMOTE_CALL)
+    {
+        ULONG handle;
+
+        handle = *(ULONG *)pBuffer;
+        pBuffer += sizeof(ULONG);
+
+        if (handle)
+        {
+            static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
+            BITMAP bitmap;
+            ULONG bitmap_size;
+            unsigned char *bits;
+
+            bitmap_size = *(ULONG *)pBuffer;
+            pBuffer += sizeof(ULONG);
+            bits = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
+
+            memcpy(&bitmap, pBuffer, header_size);
+            pBuffer += header_size;
+
+            memcpy(bits, pBuffer, bitmap_size);
+            pBuffer += bitmap_size;
+
+            bitmap.bmBits = bits;
+            *phBmp = CreateBitmapIndirect(&bitmap);
+
+            HeapFree(GetProcessHeap(), 0, bits);
+        }
+        else
+            *phBmp = NULL;
+    }
+    else
+        RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
+
     return pBuffer;
 }
 
@@ -660,7 +761,10 @@ unsigned char * __RPC_USER HBITMAP_UserUnmarshal(ULONG *pFlags, unsigned char *p
  */
 void __RPC_USER HBITMAP_UserFree(ULONG *pFlags, HBITMAP *phBmp)
 {
-    FIXME(":stub\n");
+    TRACE("(%s, %p)\n", debugstr_user_flags(pFlags), *phBmp);
+
+    if (LOWORD(*pFlags) != MSHCTX_INPROC)
+        DeleteObject(*phBmp);
 }
 
 /******************************************************************************
@@ -1620,9 +1724,7 @@ ULONG __RPC_USER STGMEDIUM_UserSize(ULONG *pFlags, ULONG StartingSize, STGMEDIUM
     case TYMED_GDI:
         TRACE("TYMED_GDI\n");
         if (pStgMedium->u.hBitmap)
-        {
-            FIXME("not implemented for GDI object %p\n", pStgMedium->u.hBitmap);
-        }
+            size = HBITMAP_UserSize(pFlags, size, &pStgMedium->u.hBitmap);
         break;
     case TYMED_MFPICT:
         TRACE("TYMED_MFPICT\n");
@@ -1732,9 +1834,7 @@ unsigned char * __RPC_USER STGMEDIUM_UserMarshal(ULONG *pFlags, unsigned char *p
     case TYMED_GDI:
         TRACE("TYMED_GDI\n");
         if (pStgMedium->u.hBitmap)
-        {
-            FIXME("not implemented for GDI object %p\n", pStgMedium->u.hBitmap);
-        }
+            pBuffer = HBITMAP_UserMarshal(pFlags, pBuffer, &pStgMedium->u.hBitmap);
         break;
     case TYMED_MFPICT:
         TRACE("TYMED_MFPICT\n");
@@ -1870,9 +1970,7 @@ unsigned char * __RPC_USER STGMEDIUM_UserUnmarshal(ULONG *pFlags, unsigned char
     case TYMED_GDI:
         TRACE("TYMED_GDI\n");
         if (content)
-        {
-            FIXME("not implemented for GDI object\n");
-        }
+            pBuffer = HBITMAP_UserUnmarshal(pFlags, pBuffer, &pStgMedium->u.hBitmap);
         else
             pStgMedium->u.hBitmap = NULL;
         break;
-- 
2.15.0




More information about the wine-devel mailing list