=?UTF-8?Q?Stefan=20D=C3=B6singer=20?=: ddraw: Size handling fixes for IDirect3DDevice::GetCaps.

Alexandre Julliard julliard at winehq.org
Mon Dec 5 14:55:02 CST 2011


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

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Mon Dec  5 00:07:20 2011 +0100

ddraw: Size handling fixes for IDirect3DDevice::GetCaps.

---

 dlls/ddraw/device.c    |   49 ++++++++++++++++++++++++++-
 dlls/ddraw/tests/d3d.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index e9e7744..2c48ec1 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -500,21 +500,66 @@ IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
  *  D3DERR_* if a problem occurs. See WineD3D
  *
  *****************************************************************************/
+
+/* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
+ * Microsoft just expanded the existing structure without naming them
+ * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
+ * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
+ * one with 252 bytes.
+ *
+ * All 3 versions are allowed as parameters and only the specified amount of
+ * bytes is written.
+ *
+ * Note that Direct3D7 and earlier are not available in native Win64
+ * ddraw.dll builds, so possible size differences between 32 bit and
+ * 64 bit are a non-issue.
+ */
+static inline BOOL check_d3ddevicedesc_size(DWORD size)
+{
+    if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
+            || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
+            || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
+    return FALSE;
+}
+
 static HRESULT WINAPI
 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
                               D3DDEVICEDESC *HWDesc,
                               D3DDEVICEDESC *HelDesc)
 {
     IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
+    D3DDEVICEDESC oldDesc;
     D3DDEVICEDESC7 newDesc;
     HRESULT hr;
 
     TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
 
-    hr = IDirect3DImpl_GetCaps(This->ddraw->wined3d, HWDesc, &newDesc);
+    if (!HWDesc)
+    {
+        WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
+        return DDERR_INVALIDPARAMS;
+    }
+    if (!check_d3ddevicedesc_size(HWDesc->dwSize))
+    {
+        WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
+        return DDERR_INVALIDPARAMS;
+    }
+    if (!HelDesc)
+    {
+        WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
+        return DDERR_INVALIDPARAMS;
+    }
+    if (!check_d3ddevicedesc_size(HelDesc->dwSize))
+    {
+        WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
+        return DDERR_INVALIDPARAMS;
+    }
+
+    hr = IDirect3DImpl_GetCaps(This->ddraw->wined3d, &oldDesc, &newDesc);
     if(hr != D3D_OK) return hr;
 
-    *HelDesc = *HWDesc;
+    DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
+    DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
     return D3D_OK;
 }
 
diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c
index 153d39f..d94fd7e 100644
--- a/dlls/ddraw/tests/d3d.c
+++ b/dlls/ddraw/tests/d3d.c
@@ -4895,6 +4895,91 @@ static void test_coop_level_surf_create(void)
     IDirectDraw7_Release(ddraw7);
 }
 
+static void test_get_caps1(void)
+{
+    D3DDEVICEDESC hw_caps, hel_caps;
+    HRESULT hr;
+    unsigned int i;
+
+    memset(&hw_caps, 0, sizeof(hw_caps));
+    hw_caps.dwSize = sizeof(hw_caps);
+    hw_caps.dwFlags = 0xdeadbeef;
+    memset(&hel_caps, 0, sizeof(hel_caps));
+    hel_caps.dwSize = sizeof(hel_caps);
+    hel_caps.dwFlags = 0xdeadc0de;
+
+    /* NULL pointers */
+    hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, NULL);
+    ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hel caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
+    ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
+    hr = IDirect3DDevice_GetCaps(Direct3DDevice1, NULL, &hel_caps);
+    ok(hr == DDERR_INVALIDPARAMS, "GetCaps with NULL hw caps returned hr %#x, expected INVALIDPARAMS.\n", hr);
+    ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
+
+    /* Successful call: Both are modified */
+    hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
+    ok(hr == D3D_OK, "GetCaps with correct size returned hr %#x, expected D3D_OK.\n", hr);
+    ok(hw_caps.dwFlags != 0xdeadbeef, "hw_caps.dwFlags was not modified: %#x.\n", hw_caps.dwFlags);
+    ok(hel_caps.dwFlags != 0xdeadc0de, "hel_caps.dwFlags was not modified: %#x.\n", hel_caps.dwFlags);
+
+    memset(&hw_caps, 0, sizeof(hw_caps));
+    hw_caps.dwSize = sizeof(hw_caps);
+    hw_caps.dwFlags = 0xdeadbeef;
+    memset(&hel_caps, 0, sizeof(hel_caps));
+    /* Keep dwSize at 0 */
+    hel_caps.dwFlags = 0xdeadc0de;
+
+    /* If one is invalid the call fails */
+    hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
+    ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hel_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
+    ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
+    ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
+    hel_caps.dwSize = sizeof(hel_caps);
+    hw_caps.dwSize = sizeof(hw_caps) + 1;
+    hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
+    ok(hr == DDERR_INVALIDPARAMS, "GetCaps with invalid hw_caps size returned hr %#x, expected INVALIDPARAMS.\n", hr);
+    ok(hw_caps.dwFlags == 0xdeadbeef, "hw_caps.dwFlags was modified: %#x.\n", hw_caps.dwFlags);
+    ok(hel_caps.dwFlags == 0xdeadc0de, "hel_caps.dwFlags was modified: %#x.\n", hel_caps.dwFlags);
+
+    for (i = 0; i < 1024; i++)
+    {
+        memset(&hw_caps, 0xfe, sizeof(hw_caps));
+        memset(&hel_caps, 0xfe, sizeof(hel_caps));
+        hw_caps.dwSize = hel_caps.dwSize = i;
+        hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
+        switch (i)
+        {
+            /* D3DDEVICEDESCSIZE in old sdk versions */
+            case FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth): /* 172, DirectX 3, IDirect3DDevice1 */
+                ok(hw_caps.dwMinTextureWidth == 0xfefefefe, "hw_caps.dwMinTextureWidth was modified: %#x.\n",
+                        hw_caps.dwMinTextureWidth);
+                ok(hel_caps.dwMinTextureWidth == 0xfefefefe, "hel_caps.dwMinTextureWidth was modified: %#x.\n",
+                        hel_caps.dwMinTextureWidth);
+                /* drop through */
+            case FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat): /* 204, DirectX 5, IDirect3DDevice2 */
+                ok(hw_caps.dwMaxTextureRepeat == 0xfefefefe, "hw_caps.dwMaxTextureRepeat was modified: %#x.\n",
+                        hw_caps.dwMaxTextureRepeat);
+                ok(hel_caps.dwMaxTextureRepeat == 0xfefefefe, "hel_caps.dwMaxTextureRepeat was modified: %#x.\n",
+                        hel_caps.dwMaxTextureRepeat);
+                /* drop through */
+            case sizeof(D3DDEVICEDESC): /* 252, DirectX 6, IDirect3DDevice3 */
+                ok(hr == D3D_OK, "GetCaps with size %u returned hr %#x, expected D3D_OK.\n", i, hr);
+                break;
+
+            default:
+                ok(hr == DDERR_INVALIDPARAMS,
+                        "GetCaps with size %u returned hr %#x, expected DDERR_INVALIDPARAMS.\n", i, hr);
+                break;
+        }
+    }
+
+    /* Different valid sizes are OK */
+    hw_caps.dwSize = 172;
+    hel_caps.dwSize = sizeof(D3DDEVICEDESC);
+    hr = IDirect3DDevice_GetCaps(Direct3DDevice1, &hw_caps, &hel_caps);
+    ok(hr == D3D_OK, "GetCaps with different sizes returned hr %#x, expected D3D_OK.\n", hr);
+}
+
 START_TEST(d3d)
 {
     init_function_pointers();
@@ -4934,6 +5019,7 @@ START_TEST(d3d)
         FindDevice();
         BackBuffer3DCreateSurfaceTest();
         BackBuffer3DAttachmentTest();
+        test_get_caps1();
         D3D1_releaseObjects();
     }
 




More information about the wine-cvs mailing list