[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