Module: wine Branch: master Commit: cc06d182fb433c7009dfb640b33d4ecd27bbd4b6 URL: http://source.winehq.org/git/wine.git/?a=commit;h=cc06d182fb433c7009dfb640b3...
Author: Stefan Dösinger stefan@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(); }