[PATCH] ole32: Add user marshalling for bitmaps.

Huw Davies huw at codeweavers.com
Fri Dec 1 04:21:45 CST 2017


On Thu, Nov 30, 2017 at 07:14:56PM -0600, Zebediah Figura wrote:
> 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);

Pass in a 1 rather than 0 to test alignment.

> +    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);

Similarly buffer + 1

Could you also test the return value.

> +    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);
> +}

It would be nice to have the MSHCTX_INPROC stuff tested too, since
you're implementing that.

> 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;

Rename the parameter StartingSize to size and you're done.  In fact
let's take the opportunity to rename all of the parameters to flags,
size and bmp.  Do the same with the others below.

> +
> +    TRACE("(%s, %d, %p)\n", debugstr_user_flags(pFlags), StartingSize, *phBmp);

ALIGN_LENGTH(size, 3);

> +
> +    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);

ALIGN_POINTER(buffer, 3);

> +
> +    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;

ULONG context;

> +
> +    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);

The stgmedium changes should probably be a separate patch.

Huw.



More information about the wine-devel mailing list