diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 1133bbdd07d..f229215a1f6 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -626,10 +626,10 @@ struct member_info /* Structure copy */ #define ME(x,f,e) { x, #x, (void (*)(const void *))(f), offsetof(STRUCT, e) } -#define DD_STRUCT_COPY_BYSIZE_(to,from,from_size) \ +#define DD_STRUCT_COPY_BYSIZE_(to,from,to_size,from_size) \ do { \ DWORD __size = (to)->dwSize; \ - DWORD __resetsize = min(__size, sizeof(*to)); \ + DWORD __resetsize = min(to_size, sizeof(*to)); \ DWORD __copysize = min(__resetsize, from_size); \ assert(to != from); \ memcpy(to, from, __copysize); \ @@ -637,7 +637,7 @@ struct member_info (to)->dwSize = __size; /* restore size */ \ } while (0) -#define DD_STRUCT_COPY_BYSIZE(to,from) DD_STRUCT_COPY_BYSIZE_(to,from,(from)->dwSize) +#define DD_STRUCT_COPY_BYSIZE(to,from) DD_STRUCT_COPY_BYSIZE_(to,from,(to)->dwSize,(from)->dwSize) HRESULT hr_ddraw_from_wined3d(HRESULT hr) DECLSPEC_HIDDEN; diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 4b53ac341d5..94f850b3770 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -954,14 +954,15 @@ static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *ifac * *****************************************************************************/ static HRESULT surface_lock(struct ddraw_surface *surface, - RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h) + RECT *rect, DDSURFACEDESC2 *surface_desc, unsigned int surface_desc_size, + DWORD flags, HANDLE h) { - struct wined3d_box box; struct wined3d_map_desc map_desc; + struct wined3d_box box; HRESULT hr = DD_OK; - TRACE("surface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", - surface, wine_dbgstr_rect(rect), surface_desc, flags, h); + TRACE("surface %p, rect %s, surface_desc %p, surface_desc_size %u, flags %#x, h %p.\n", + surface, wine_dbgstr_rect(rect), surface_desc, surface_desc_size, flags, h); /* surface->surface_desc.dwWidth and dwHeight are changeable, thus lock */ wined3d_mutex_lock(); @@ -1025,7 +1026,7 @@ static HRESULT surface_lock(struct ddraw_surface *surface, } /* Windows does not set DDSD_LPSURFACE on locked surfaces. */ - DD_STRUCT_COPY_BYSIZE(surface_desc, &surface->surface_desc); + DD_STRUCT_COPY_BYSIZE_(surface_desc, &surface->surface_desc, surface_desc_size, surface->surface_desc.dwSize); surface_desc->lpSurface = map_desc.data; TRACE("locked surface returning description :\n"); @@ -1037,63 +1038,80 @@ static HRESULT surface_lock(struct ddraw_surface *surface, return DD_OK; } +static BOOL surface_validate_lock_desc(struct ddraw_surface *surface, + const DDSURFACEDESC *desc, unsigned int *size) +{ + if (!desc) + return FALSE; + + if (desc->dwSize == sizeof(DDSURFACEDESC) || desc->dwSize == sizeof(DDSURFACEDESC2)) + { + *size = desc->dwSize; + return TRUE; + } + + if (surface->version == 7 + && surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE + && !(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) + { + if (desc->dwSize >= sizeof(DDSURFACEDESC2)) + *size = sizeof(DDSURFACEDESC2); + else + *size = sizeof(DDSURFACEDESC); + return TRUE; + } + + WARN("Invalid structure size %u.\n", desc->dwSize); + return FALSE; +} + static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface, RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h) { struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); + unsigned int surface_desc_size; TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", iface, wine_dbgstr_rect(rect), surface_desc, flags, h); - if (!surface_desc) return DDERR_INVALIDPARAMS; - if (surface_desc->dwSize != sizeof(DDSURFACEDESC) && - surface_desc->dwSize != sizeof(DDSURFACEDESC2)) - { - WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize); + if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size)) return DDERR_INVALIDPARAMS; - } - return surface_lock(surface, rect, surface_desc, flags, h); + + return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h); } static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h) { struct ddraw_surface *surface = impl_from_IDirectDrawSurface4(iface); + unsigned int surface_desc_size; TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", iface, wine_dbgstr_rect(rect), surface_desc, flags, h); - if (!surface_desc) return DDERR_INVALIDPARAMS; - if (surface_desc->dwSize != sizeof(DDSURFACEDESC) && - surface_desc->dwSize != sizeof(DDSURFACEDESC2)) - { - WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize); + if (!surface_validate_lock_desc(surface, (DDSURFACEDESC *)surface_desc, &surface_desc_size)) return DDERR_INVALIDPARAMS; - } - return surface_lock(surface, rect, surface_desc, flags, h); + + return surface_lock(surface, rect, surface_desc, surface_desc_size, flags, h); } static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect, DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h) { struct ddraw_surface *surface = impl_from_IDirectDrawSurface3(iface); + unsigned int surface_desc_size; DDSURFACEDESC2 surface_desc2; HRESULT hr; TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", iface, wine_dbgstr_rect(rect), surface_desc, flags, h); - if (!surface_desc) return DDERR_INVALIDPARAMS; - if (surface_desc->dwSize != sizeof(DDSURFACEDESC) && - surface_desc->dwSize != sizeof(DDSURFACEDESC2)) - { - WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize); + if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size)) return DDERR_INVALIDPARAMS; - } surface_desc2.dwSize = surface_desc->dwSize; surface_desc2.dwFlags = 0; - hr = surface_lock(surface, rect, &surface_desc2, flags, h); + hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h); DDSD2_to_DDSD(&surface_desc2, surface_desc); surface_desc->dwSize = surface_desc2.dwSize; return hr; @@ -1103,23 +1121,19 @@ static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h) { struct ddraw_surface *surface = impl_from_IDirectDrawSurface2(iface); + unsigned int surface_desc_size; DDSURFACEDESC2 surface_desc2; HRESULT hr; TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", iface, wine_dbgstr_rect(rect), surface_desc, flags, h); - if (!surface_desc) return DDERR_INVALIDPARAMS; - if (surface_desc->dwSize != sizeof(DDSURFACEDESC) && - surface_desc->dwSize != sizeof(DDSURFACEDESC2)) - { - WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize); + if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size)) return DDERR_INVALIDPARAMS; - } surface_desc2.dwSize = surface_desc->dwSize; surface_desc2.dwFlags = 0; - hr = surface_lock(surface, rect, &surface_desc2, flags, h); + hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h); DDSD2_to_DDSD(&surface_desc2, surface_desc); surface_desc->dwSize = surface_desc2.dwSize; return hr; @@ -1129,22 +1143,19 @@ static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect, DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h) { struct ddraw_surface *surface = impl_from_IDirectDrawSurface(iface); + unsigned int surface_desc_size; DDSURFACEDESC2 surface_desc2; HRESULT hr; + TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n", iface, wine_dbgstr_rect(rect), surface_desc, flags, h); - if (!surface_desc) return DDERR_INVALIDPARAMS; - if (surface_desc->dwSize != sizeof(DDSURFACEDESC) && - surface_desc->dwSize != sizeof(DDSURFACEDESC2)) - { - WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize); + if (!surface_validate_lock_desc(surface, surface_desc, &surface_desc_size)) return DDERR_INVALIDPARAMS; - } surface_desc2.dwSize = surface_desc->dwSize; surface_desc2.dwFlags = 0; - hr = surface_lock(surface, rect, &surface_desc2, flags, h); + hr = surface_lock(surface, rect, &surface_desc2, surface_desc_size, flags, h); DDSD2_to_DDSD(&surface_desc2, surface_desc); surface_desc->dwSize = surface_desc2.dwSize; return hr; diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 0139bfd36d8..d802a5922de 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -5891,7 +5891,6 @@ static void test_surface_lock(void) expected_hr = tests[i].caps & DDSCAPS_TEXTURE && !(tests[i].caps & DDSCAPS_VIDEOMEMORY) ? DD_OK : DDERR_INVALIDPARAMS; hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL); - todo_wine_if(expected_hr == D3D_OK) ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, tests[i].name); if (SUCCEEDED(hr)) { @@ -12321,7 +12320,6 @@ static void test_surface_desc_size(void) desc.blob[sizeof(DDSURFACEDESC2)] = 0xef; hr = IDirectDrawSurface_Lock(surface, NULL, &desc.desc1, 0, 0); expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS; - todo_wine_if(ignore_size && !valid_size) ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n", hr, expected_hr, desc_sizes[j], surface_caps[i].name); ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n", @@ -12348,7 +12346,6 @@ static void test_surface_desc_size(void) desc.blob[sizeof(DDSURFACEDESC2)] = 0xef; hr = IDirectDrawSurface3_Lock(surface3, NULL, &desc.desc1, 0, 0); expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS; - todo_wine_if(ignore_size && !valid_size) ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n", hr, expected_hr, desc_sizes[j], surface_caps[i].name); ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n", @@ -12375,7 +12372,6 @@ static void test_surface_desc_size(void) desc.blob[sizeof(DDSURFACEDESC2)] = 0xef; hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0); expected_hr = ignore_size || valid_size ? DD_OK : DDERR_INVALIDPARAMS; - todo_wine_if(ignore_size && !valid_size) ok(hr == expected_hr, "Got hr %#x, expected %#x, dwSize %u, type %s.\n", hr, expected_hr, desc_sizes[j], surface_caps[i].name); ok(desc.dwSize == desc_sizes[j], "dwSize was changed from %u to %u, type %s.\n",