=?UTF-8?Q?J=C3=B3zef=20Kucia=20?=: d3dx9: Check the size of a DDS file in D3DXGetImageInfoFromFileInMemory.

Alexandre Julliard julliard at winehq.org
Mon May 14 14:26:05 CDT 2012


Module: wine
Branch: master
Commit: e91300a31859dd6bff624d16844d82b1e64553e3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e91300a31859dd6bff624d16844d82b1e64553e3

Author: Józef Kucia <joseph.kucia at 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 */




More information about the wine-cvs mailing list