gdiplus: Add write_region_data helper and use it in GdipGetRegionData.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Vincent Povirk <vincent@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2017-08-10 20:56:12 +02:00 committed by Alexandre Julliard
parent cb56d0ce2b
commit 4a02870296
1 changed files with 35 additions and 26 deletions

View File

@ -84,12 +84,17 @@ struct memory_buffer
struct region_header struct region_header
{ {
DWORD size;
DWORD checksum;
DWORD magic; DWORD magic;
DWORD num_children; DWORD num_children;
}; };
struct region_data_header
{
DWORD size;
DWORD checksum;
struct region_header header;
};
struct path_header struct path_header
{ {
DWORD size; DWORD size;
@ -98,11 +103,6 @@ struct path_header
DWORD flags; DWORD flags;
}; };
/* Header size as far as header->size is concerned. This doesn't include
* header->size or header->checksum
*/
static const INT sizeheader_size = sizeof(DWORD) * 2;
typedef struct packed_point typedef struct packed_point
{ {
short X; short X;
@ -699,6 +699,24 @@ static void write_element(const region_element* element, DWORD *buffer,
} }
} }
static DWORD write_region_data(const GpRegion *region, void *data)
{
struct region_header *header = data;
INT filled = 0;
DWORD size;
size = sizeof(struct region_header) + get_element_size(&region->node);
if (!data) return size;
header->magic = VERSION_MAGIC2;
header->num_children = region->num_children;
filled += 2;
/* With few exceptions, everything written is DWORD aligned,
* so use that as our base */
write_element(&region->node, (DWORD*)data, &filled);
return size;
}
/***************************************************************************** /*****************************************************************************
* GdipGetRegionData [GDIPLUS.@] * GdipGetRegionData [GDIPLUS.@]
* *
@ -735,36 +753,27 @@ static void write_element(const region_element* element, DWORD *buffer,
GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size, GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
UINT *needed) UINT *needed)
{ {
struct region_header *region_header; struct region_data_header *region_data_header;
INT filled = 0;
UINT required; UINT required;
GpStatus status;
TRACE("%p, %p, %d, %p\n", region, buffer, size, needed); TRACE("%p, %p, %d, %p\n", region, buffer, size, needed);
if (!region || !buffer || !size) if (!region || !buffer || !size)
return InvalidParameter; return InvalidParameter;
status = GdipGetRegionDataSize(region, &required); required = FIELD_OFFSET(struct region_data_header, header) + write_region_data(region, NULL);
if (status != Ok) return status;
if (size < required) if (size < required)
{ {
if (needed) *needed = size; if (needed) *needed = size;
return InsufficientBuffer; return InsufficientBuffer;
} }
region_header = (struct region_header *)buffer; region_data_header = (struct region_data_header *)buffer;
region_header->size = sizeheader_size + get_element_size(&region->node); region_data_header->size = write_region_data(region, &region_data_header->header);
region_header->checksum = 0; region_data_header->checksum = 0;
region_header->magic = VERSION_MAGIC2;
region_header->num_children = region->num_children;
filled += 4;
/* With few exceptions, everything written is DWORD aligned,
* so use that as our base */
write_element(&region->node, (DWORD*)buffer, &filled);
if (needed) if (needed)
*needed = filled * sizeof(DWORD); *needed = required;
return Ok; return Ok;
} }
@ -960,7 +969,7 @@ static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, regio
*/ */
GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRegion **region) GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRegion **region)
{ {
const struct region_header *region_header; const struct region_data_header *region_data_header;
struct memory_buffer mbuf; struct memory_buffer mbuf;
GpStatus status; GpStatus status;
INT count; INT count;
@ -972,8 +981,8 @@ GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRe
init_memory_buffer(&mbuf, data, size); init_memory_buffer(&mbuf, data, size);
region_header = buffer_read(&mbuf, sizeof(*region_header)); region_data_header = buffer_read(&mbuf, sizeof(*region_data_header));
if (!region_header || !VALID_MAGIC(region_header->magic)) if (!region_data_header || !VALID_MAGIC(region_data_header->header.magic))
return InvalidParameter; return InvalidParameter;
status = GdipCreateRegion(region); status = GdipCreateRegion(region);
@ -1005,7 +1014,7 @@ GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed)
return InvalidParameter; return InvalidParameter;
/* header.size doesn't count header.size and header.checksum */ /* header.size doesn't count header.size and header.checksum */
*needed = sizeof(DWORD) * 2 + sizeheader_size + get_element_size(&region->node); *needed = FIELD_OFFSET(struct region_data_header, header) + write_region_data(region, NULL);
return Ok; return Ok;
} }