Module: wine Branch: master Commit: e91300a31859dd6bff624d16844d82b1e64553e3 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e91300a31859dd6bff624d1684...
Author: Józef Kucia joseph.kucia@gmail.com Date: Sun May 13 23:00:04 2012 +0200
d3dx9: Check the size of a DDS file in D3DXGetImageInfoFromFileInMemory.
---
dlls/d3dx9_36/surface.c | 53 ++++++++++++++++++++++++++++++++++++++++- dlls/d3dx9_36/tests/surface.c | 15 ++++++++--- 2 files changed, 63 insertions(+), 5 deletions(-)
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 7556ead..337b513 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -269,6 +269,29 @@ static D3DFORMAT dds_pixel_format_to_d3dformat(const struct dds_pixel_format *pi return D3DFMT_UNKNOWN; }
+static HRESULT calculate_dds_surface_size(const D3DXIMAGE_INFO *img_info, + UINT width, UINT height, UINT *pitch, UINT *size) +{ + const PixelFormatDesc *format_desc = get_format_info(img_info->Format); + if (format_desc->format == D3DFMT_UNKNOWN) + return E_NOTIMPL; + + if (format_desc->block_width != 1 || format_desc->block_height != 1) + { + *pitch = format_desc->block_byte_count + * max(1, (width + format_desc->block_width - 1) / format_desc->block_width); + *size = *pitch + * max(1, (height + format_desc->block_height - 1) / format_desc->block_height); + } + else + { + *pitch = width * format_desc->bytes_per_pixel; + *size = *pitch * height; + } + + return D3D_OK; +} + /************************************************************ * get_image_info_from_dds * @@ -285,9 +308,13 @@ static D3DFORMAT dds_pixel_format_to_d3dformat(const struct dds_pixel_format *pi * Failure: D3DXERR_INVALIDDATA * */ -static HRESULT get_image_info_from_dds(const void *buffer, DWORD length, D3DXIMAGE_INFO *info) +static HRESULT get_image_info_from_dds(const void *buffer, UINT length, D3DXIMAGE_INFO *info) { + UINT i; + UINT faces = 0; + UINT width, height; const struct dds_header *header = buffer; + UINT expected_length = 0;
if (length < sizeof(*header) || !info) return D3DXERR_INVALIDDATA; @@ -311,13 +338,37 @@ static HRESULT get_image_info_from_dds(const void *buffer, DWORD length, D3DXIMA } else if (header->caps2 & DDS_CAPS2_CUBEMAP) { + DWORD face; + for (face = DDS_CAPS2_CUBEMAP_POSITIVEX; face <= DDS_CAPS2_CUBEMAP_NEGATIVEZ; face <<= 1) + { + if (header->caps2 & face) + faces++; + } info->ResourceType = D3DRTYPE_CUBETEXTURE; } else { + faces = 1; info->ResourceType = D3DRTYPE_TEXTURE; }
+ /* calculate the expected length */ + width = info->Width; + height = info->Height; + for (i = 0; i < info->MipLevels; i++) + { + UINT pitch, size = 0; + calculate_dds_surface_size(info, width, height, &pitch, &size); + expected_length += size; + width = max(1, width / 2); + height = max(1, width / 2); + } + + expected_length *= faces; + expected_length += sizeof(*header); + if (length < expected_length) + return D3DXERR_INVALIDDATA; + info->ImageFileFormat = D3DXIFF_DDS;
return D3D_OK; diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c index 3d8ad24..48b1c57 100644 --- a/dlls/d3dx9_36/tests/surface.c +++ b/dlls/d3dx9_36/tests/surface.c @@ -404,10 +404,17 @@ static void test_D3DXGetImageInfo(void) check_dds_pixel_format(DDS_PF_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0, 0, D3DFMT_V8U8); check_dds_pixel_format(DDS_PF_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0, 0, D3DFMT_V16U16);
- todo_wine { - hr = D3DXGetImageInfoFromFileInMemory(dds_16bit, sizeof(dds_16bit) - 1, &info); - ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); - } + hr = D3DXGetImageInfoFromFileInMemory(dds_16bit, sizeof(dds_16bit) - 1, &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromFileInMemory(dds_24bit, sizeof(dds_24bit) - 1, &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromFileInMemory(dds_cube_map, sizeof(dds_cube_map) - 1, &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromFileInMemory(dds_volume_map, sizeof(dds_volume_map) - 1, &info); + todo_wine ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA);
/* cleanup */