=?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