ddraw: Avoid LPDIRECTDRAWSURFACE.
[wine] / dlls / ddraw / tests / dsurface.c
1 /*
2  * Unit tests for (a few) ddraw surface functions
3  *
4  * Copyright (C) 2005 Antoine Chavasse (a.chavasse@gmail.com)
5  * Copyright (C) 2005 Christian Costa
6  * Copyright 2005 Ivan Leo Puoti
7  * Copyright (C) 2007-2009, 2011 Stefan Dösinger for CodeWeavers
8  * Copyright (C) 2008 Alexander Dorofeyev
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 #define COBJMACROS
25
26 #include "wine/test.h"
27 #include "wine/exception.h"
28 #include "ddraw.h"
29 #include "d3d.h"
30 #include "unknwn.h"
31
32 static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *, void **, REFIID, IUnknown *);
33
34 static LPDIRECTDRAW lpDD = NULL;
35 static DDCAPS ddcaps;
36
37 static BOOL CreateDirectDraw(void)
38 {
39     HRESULT rc;
40
41     rc = DirectDrawCreate(NULL, &lpDD, NULL);
42     ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
43     if (!lpDD) {
44         trace("DirectDrawCreateEx() failed with an error %x\n", rc);
45         return FALSE;
46     }
47
48     rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
49     ok(rc==DD_OK,"SetCooperativeLevel returned: %x\n",rc);
50
51     return TRUE;
52 }
53
54
55 static void ReleaseDirectDraw(void)
56 {
57     if( lpDD != NULL )
58     {
59         IDirectDraw_Release(lpDD);
60         lpDD = NULL;
61     }
62 }
63
64 static void MipMapCreationTest(void)
65 {
66     IDirectDrawSurface *lpDDSMipMapTest;
67     DDSURFACEDESC ddsd;
68     HRESULT rc;
69
70     /* First mipmap creation test: create a surface with DDSCAPS_COMPLEX,
71        DDSCAPS_MIPMAP, and DDSD_MIPMAPCOUNT. This create the number of
72         requested mipmap levels. */
73     ddsd.dwSize = sizeof(ddsd);
74     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
75     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
76     U2(ddsd).dwMipMapCount = 3;
77     ddsd.dwWidth = 128;
78     ddsd.dwHeight = 32;
79     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
80     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
81     if (FAILED(rc))
82     {
83         skip("failed to create surface\n");
84         return;
85     }
86
87     /* Check the number of created mipmaps */
88     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
89     ddsd.dwSize = sizeof(ddsd);
90     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
91     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
92     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
93         "GetSurfaceDesc returned no mipmapcount.\n");
94     ok(U2(ddsd).dwMipMapCount == 3, "Incorrect mipmap count: %d.\n",
95         U2(ddsd).dwMipMapCount);
96
97     /* Destroy the surface. */
98     IDirectDrawSurface_Release(lpDDSMipMapTest);
99
100
101     /* Second mipmap creation test: create a surface without a mipmap
102        count, with DDSCAPS_MIPMAP and without DDSCAPS_COMPLEX.
103        This creates a single mipmap level. */
104     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
105     ddsd.dwSize = sizeof(ddsd);
106     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
107     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
108     ddsd.dwWidth = 128;
109     ddsd.dwHeight = 32;
110     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
111     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
112     if (FAILED(rc))
113     {
114         skip("failed to create surface\n");
115         return;
116     }
117     /* Check the number of created mipmaps */
118     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
119     ddsd.dwSize = sizeof(ddsd);
120     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
121     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
122     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
123         "GetSurfaceDesc returned no mipmapcount.\n");
124     ok(U2(ddsd).dwMipMapCount == 1, "Incorrect mipmap count: %d.\n",
125         U2(ddsd).dwMipMapCount);
126
127     /* Destroy the surface. */
128     IDirectDrawSurface_Release(lpDDSMipMapTest);
129
130
131     /* Third mipmap creation test: create a surface with DDSCAPS_MIPMAP,
132         DDSCAPS_COMPLEX and without DDSD_MIPMAPCOUNT.
133        It's an undocumented features where a chain of mipmaps, starting from
134        he specified size and down to the smallest size, is automatically
135        created.
136        Anarchy Online needs this feature to work. */
137     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
138     ddsd.dwSize = sizeof(ddsd);
139     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
140     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
141     ddsd.dwWidth = 128;
142     ddsd.dwHeight = 32;
143     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
144     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
145     if (FAILED(rc))
146     {
147         skip("failed to create surface\n");
148         return;
149     }
150
151     /* Check the number of created mipmaps */
152     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
153     ddsd.dwSize = sizeof(ddsd);
154     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
155     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
156     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
157         "GetSurfaceDesc returned no mipmapcount.\n");
158     ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %d.\n",
159         U2(ddsd).dwMipMapCount);
160
161     /* Destroy the surface. */
162     IDirectDrawSurface_Release(lpDDSMipMapTest);
163
164
165     /* Fourth mipmap creation test: same as above with a different texture
166        size.
167        The purpose is to verify that the number of generated mipmaps is
168        dependent on the smallest dimension. */
169     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
170     ddsd.dwSize = sizeof(ddsd);
171     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
172     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
173     ddsd.dwWidth = 32;
174     ddsd.dwHeight = 64;
175     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
176     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
177     if (FAILED(rc))
178     {
179         skip("failed to create surface\n");
180         return;
181     }
182
183     /* Check the number of created mipmaps */
184     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
185     ddsd.dwSize = sizeof(ddsd);
186     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
187     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
188     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
189         "GetSurfaceDesc returned no mipmapcount.\n");
190     ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %d.\n",
191         U2(ddsd).dwMipMapCount);
192
193     /* Destroy the surface. */
194     IDirectDrawSurface_Release(lpDDSMipMapTest);
195
196
197     /* Fifth mipmap creation test: try to create a surface with
198        DDSCAPS_COMPLEX, DDSCAPS_MIPMAP, DDSD_MIPMAPCOUNT,
199        where dwMipMapCount = 0. This should fail. */
200
201     ddsd.dwSize = sizeof(ddsd);
202     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
203     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
204     U2(ddsd).dwMipMapCount = 0;
205     ddsd.dwWidth = 128;
206     ddsd.dwHeight = 32;
207     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
208     ok(rc==DDERR_INVALIDPARAMS,"CreateSurface returned: %x\n",rc);
209
210     /* Destroy the surface. */
211     if( rc == DD_OK )
212         IDirectDrawSurface_Release(lpDDSMipMapTest);
213
214 }
215
216 static void SrcColorKey32BlitTest(void)
217 {
218     IDirectDrawSurface *lpSrc;
219     IDirectDrawSurface *lpDst;
220     DDSURFACEDESC ddsd, ddsd2, ddsd3;
221     DDCOLORKEY DDColorKey;
222     LPDWORD lpData;
223     HRESULT rc;
224     DDBLTFX fx;
225
226     ddsd2.dwSize = sizeof(ddsd2);
227     ddsd2.ddpfPixelFormat.dwSize = sizeof(ddsd2.ddpfPixelFormat);
228
229     ddsd.dwSize = sizeof(ddsd);
230     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
231     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
232     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
233     ddsd.dwWidth = 800;
234     ddsd.dwHeight = 600;
235     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
236     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
237     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
238     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
239     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
240     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL);
241     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
242     if (FAILED(rc))
243     {
244         skip("failed to create surface\n");
245         return;
246     }
247
248     ddsd.dwFlags |= DDSD_CKSRCBLT;
249     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0xFF00FF;
250     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0xFF00FF;
251     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL);
252     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
253     if (FAILED(rc))
254     {
255         skip("failed to create surface\n");
256         return;
257     }
258
259     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
260     ok(rc==DD_OK,"Lock returned: %x\n",rc);
261     lpData = ddsd2.lpSurface;
262     lpData[0] = 0xCCCCCCCC;
263     lpData[1] = 0xCCCCCCCC;
264     lpData[2] = 0xCCCCCCCC;
265     lpData[3] = 0xCCCCCCCC;
266
267     memset(&ddsd3, 0, sizeof(ddsd3));
268     ddsd3.dwSize = sizeof(ddsd3);
269     ddsd3.ddpfPixelFormat.dwSize = sizeof(ddsd3.ddpfPixelFormat);
270     rc = IDirectDrawSurface_GetSurfaceDesc(lpDst, &ddsd3);
271     ok(rc == DD_OK, "IDirectDrawSurface_GetSurfaceDesc between a lock/unlock pair returned %08x\n", rc);
272     ok(ddsd3.lpSurface == ddsd3.lpSurface, "lpSurface from GetSurfaceDesc(%p) differs from the one returned by Lock(%p)\n", ddsd3.lpSurface, ddsd2.lpSurface);
273
274     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
275     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
276
277     memset(&ddsd3, 0, sizeof(ddsd3));
278     ddsd3.dwSize = sizeof(ddsd3);
279     ddsd3.ddpfPixelFormat.dwSize = sizeof(ddsd3.ddpfPixelFormat);
280     rc = IDirectDrawSurface_GetSurfaceDesc(lpDst, &ddsd3);
281     ok(rc == DD_OK, "IDirectDrawSurface_GetSurfaceDesc between a lock/unlock pair returned %08x\n", rc);
282     ok(ddsd3.lpSurface == NULL, "lpSurface from GetSurfaceDesc(%p) is not NULL after unlock\n", ddsd3.lpSurface);
283
284     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
285     ok(rc==DD_OK,"Lock returned: %x\n",rc);
286     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
287     lpData = ddsd2.lpSurface;
288     lpData[0] = 0x77010203;
289     lpData[1] = 0x00010203;
290     lpData[2] = 0x77FF00FF;
291     lpData[3] = 0x00FF00FF;
292     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
293     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
294
295     IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, NULL);
296
297     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
298     ok(rc==DD_OK,"Lock returned: %x\n",rc);
299     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
300     lpData = ddsd2.lpSurface;
301     /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
302      * color keying, but copy it to the destination surface. Others apply it for color keying, but
303      * do not copy it into the destination surface.
304      */
305     if(lpData[0]==0x00010203) {
306         trace("X channel was not copied into the destination surface\n");
307         ok((lpData[0]==0x00010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0x00FF00FF)&&(lpData[3]==0xCCCCCCCC),
308            "Destination data after blitting is not correct\n");
309     } else {
310         ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC),
311            "Destination data after blitting is not correct\n");
312     }
313     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
314     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
315
316     /* Below we repeat the same test as above but now using BltFast instead of Blt. Before
317      * we can carry out the test we need to restore the color of the destination surface.
318      */
319     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
320     ok(rc==DD_OK,"Lock returned: %x\n",rc);
321     lpData = ddsd2.lpSurface;
322     lpData[0] = 0xCCCCCCCC;
323     lpData[1] = 0xCCCCCCCC;
324     lpData[2] = 0xCCCCCCCC;
325     lpData[3] = 0xCCCCCCCC;
326     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
327     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
328
329     IDirectDrawSurface_BltFast(lpDst, 0, 0, lpSrc, NULL, DDBLTFAST_SRCCOLORKEY);
330
331     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
332     ok(rc==DD_OK,"Lock returned: %x\n",rc);
333     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
334     lpData = ddsd2.lpSurface;
335     /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
336      * color keying, but copy it to the destination surface. Others apply it for color keying, but
337      * do not copy it into the destination surface.
338      */
339     if(lpData[0]==0x00010203) {
340         trace("X channel was not copied into the destination surface\n");
341         ok((lpData[0]==0x00010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0x00FF00FF)&&(lpData[3]==0xCCCCCCCC),
342            "Destination data after blitting is not correct\n");
343     } else {
344         ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC),
345            "Destination data after blitting is not correct\n");
346     }
347     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
348     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
349
350     /* Also test SetColorKey */
351     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
352     ok(DDColorKey.dwColorSpaceLowValue == 0xFF00FF && DDColorKey.dwColorSpaceHighValue == 0xFF00FF,
353        "GetColorKey does not return the colorkey used at surface creation\n");
354
355     DDColorKey.dwColorSpaceLowValue = 0x00FF00;
356     DDColorKey.dwColorSpaceHighValue = 0x00FF00;
357     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
358
359     DDColorKey.dwColorSpaceLowValue = 0;
360     DDColorKey.dwColorSpaceHighValue = 0;
361     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
362     ok(DDColorKey.dwColorSpaceLowValue == 0x00FF00 && DDColorKey.dwColorSpaceHighValue == 0x00FF00,
363        "GetColorKey does not return the colorkey set with SetColorKey\n");
364
365     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
366     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
367     IDirectDrawSurface_GetSurfaceDesc(lpSrc, &ddsd);
368     ok(ddsd.ddckCKSrcBlt.dwColorSpaceLowValue == 0x00FF00 && ddsd.ddckCKSrcBlt.dwColorSpaceHighValue == 0x00FF00,
369        "GetSurfaceDesc does not return the colorkey set with SetColorKey\n");
370
371     /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
372     DDColorKey.dwColorSpaceLowValue = 0x0000FF;
373     DDColorKey.dwColorSpaceHighValue = 0x000000;
374     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
375
376     DDColorKey.dwColorSpaceLowValue = 0;
377     DDColorKey.dwColorSpaceHighValue = 0;
378     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
379     ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF,
380        "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue);
381
382     DDColorKey.dwColorSpaceLowValue = 0x0000FF;
383     DDColorKey.dwColorSpaceHighValue = 0x000001;
384     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
385
386     DDColorKey.dwColorSpaceLowValue = 0;
387     DDColorKey.dwColorSpaceHighValue = 0;
388     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
389     ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF,
390        "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue);
391
392     DDColorKey.dwColorSpaceLowValue = 0x0000FF;
393     DDColorKey.dwColorSpaceHighValue = 0x0000FE;
394     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
395
396     DDColorKey.dwColorSpaceLowValue = 0;
397     DDColorKey.dwColorSpaceHighValue = 0;
398     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
399     ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF,
400        "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue);
401
402     IDirectDrawSurface_Release(lpSrc);
403     IDirectDrawSurface_Release(lpDst);
404
405     /* start with a new set of surfaces to test the color keying parameters to blit */
406     memset(&ddsd, 0, sizeof(ddsd));
407     ddsd.dwSize = sizeof(ddsd);
408     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
409     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT | DDSD_CKDESTBLT;
410     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
411     ddsd.dwWidth = 800;
412     ddsd.dwHeight = 600;
413     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
414     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
415     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
416     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
417     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
418     ddsd.ddckCKDestBlt.dwColorSpaceLowValue = 0xFF0000;
419     ddsd.ddckCKDestBlt.dwColorSpaceHighValue = 0xFF0000;
420     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00FF00;
421     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00FF00;
422     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL);
423     ok(rc==DD_OK || rc == DDERR_NOCOLORKEYHW,"CreateSurface returned: %x\n",rc);
424     if(FAILED(rc))
425     {
426         skip("Failed to create surface\n");
427         return;
428     }
429
430     /* start with a new set of surfaces to test the color keying parameters to blit */
431     memset(&ddsd, 0, sizeof(ddsd));
432     ddsd.dwSize = sizeof(ddsd);
433     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
434     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT | DDSD_CKDESTBLT;
435     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
436     ddsd.dwWidth = 800;
437     ddsd.dwHeight = 600;
438     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
439     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
440     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
441     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
442     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
443     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x0000FF;
444     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x0000FF;
445     ddsd.ddckCKDestBlt.dwColorSpaceLowValue = 0x000000;
446     ddsd.ddckCKDestBlt.dwColorSpaceHighValue = 0x000000;
447     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL);
448     ok(rc==DD_OK || rc == DDERR_NOCOLORKEYHW,"CreateSurface returned: %x\n",rc);
449     if(FAILED(rc))
450     {
451         skip("Failed to create surface\n");
452         IDirectDrawSurface_Release(lpDst);
453         return;
454     }
455
456     memset(&fx, 0, sizeof(fx));
457     fx.dwSize = sizeof(fx);
458     fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x110000;
459     fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x110000;
460     fx.ddckDestColorkey.dwColorSpaceHighValue = 0x001100;
461     fx.ddckDestColorkey.dwColorSpaceLowValue = 0x001100;
462
463     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
464     ok(rc==DD_OK,"Lock returned: %x\n",rc);
465     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
466     lpData = ddsd2.lpSurface;
467     lpData[0] = 0x000000FF; /* Applies to src blt key in src surface */
468     lpData[1] = 0x00000000; /* Applies to dst blt key in src surface */
469     lpData[2] = 0x00FF0000; /* Dst color key in dst surface */
470     lpData[3] = 0x0000FF00; /* Src color key in dst surface */
471     lpData[4] = 0x00001100; /* Src color key in ddbltfx */
472     lpData[5] = 0x00110000; /* Dst color key in ddbltfx */
473     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
474     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
475
476     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
477     ok(rc==DD_OK,"Lock returned: %x\n",rc);
478     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
479     lpData = ddsd2.lpSurface;
480     lpData[0] = 0x55555555;
481     lpData[1] = 0x55555555;
482     lpData[2] = 0x55555555;
483     lpData[3] = 0x55555555;
484     lpData[4] = 0x55555555;
485     lpData[5] = 0x55555555;
486     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
487     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
488
489     /* Test a blit without keying */
490     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, 0, &fx);
491     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
492
493     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
494     ok(rc==DD_OK,"Lock returned: %x\n",rc);
495     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
496     lpData = ddsd2.lpSurface;
497     /* Should have copied src data unmodified to dst */
498     ok(lpData[0] == 0x000000FF &&
499        lpData[1] == 0x00000000 &&
500        lpData[2] == 0x00FF0000 &&
501        lpData[3] == 0x0000FF00 &&
502        lpData[4] == 0x00001100 &&
503        lpData[5] == 0x00110000, "Surface data after unkeyed blit does not match\n");
504
505     lpData[0] = 0x55555555;
506     lpData[1] = 0x55555555;
507     lpData[2] = 0x55555555;
508     lpData[3] = 0x55555555;
509     lpData[4] = 0x55555555;
510     lpData[5] = 0x55555555;
511     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
512     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
513
514     /* Src key */
515     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, &fx);
516     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
517
518     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
519     ok(rc==DD_OK,"Lock returned: %x\n",rc);
520     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
521     lpData = ddsd2.lpSurface;
522
523     ok(lpData[0] == 0x55555555 && /* Here the src key applied */
524        lpData[1] == 0x00000000 &&
525        lpData[2] == 0x00FF0000 &&
526        lpData[3] == 0x0000FF00 &&
527        lpData[4] == 0x00001100 &&
528        lpData[5] == 0x00110000, "Surface data after srckey blit does not match\n");
529
530     lpData[0] = 0x55555555;
531     lpData[1] = 0x55555555;
532     lpData[2] = 0x55555555;
533     lpData[3] = 0x55555555;
534     lpData[4] = 0x55555555;
535     lpData[5] = 0x55555555;
536     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
537     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
538
539     /* Src override */
540     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
541     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
542
543     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
544     ok(rc==DD_OK,"Lock returned: %x\n",rc);
545     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
546     lpData = ddsd2.lpSurface;
547
548     ok(lpData[0] == 0x000000FF &&
549        lpData[1] == 0x00000000 &&
550        lpData[2] == 0x00FF0000 &&
551        lpData[3] == 0x0000FF00 &&
552        lpData[4] == 0x00001100 &&
553        lpData[5] == 0x55555555, /* Override key applies here */
554        "Surface data after src override key blit does not match\n");
555
556     lpData[0] = 0x55555555;
557     lpData[1] = 0x55555555;
558     lpData[2] = 0x55555555;
559     lpData[3] = 0x55555555;
560     lpData[4] = 0x55555555;
561     lpData[5] = 0x55555555;
562     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
563     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
564
565     /* Src override AND src key. That is not supposed to work */
566     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
567     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
568
569     /* Verify that the destination is unchanged */
570     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
571     ok(rc==DD_OK,"Lock returned: %x\n",rc);
572     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
573     lpData = ddsd2.lpSurface;
574
575     ok(lpData[0] == 0x55555555 &&
576        lpData[1] == 0x55555555 &&
577        lpData[2] == 0x55555555 &&
578        lpData[3] == 0x55555555 &&
579        lpData[4] == 0x55555555 &&
580        lpData[5] == 0x55555555, /* Override key applies here */
581        "Surface data after src key blit with override does not match\n");
582
583     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
584     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
585     lpData[2] = 0x00001100; /* Dest key in override */
586     lpData[3] = 0x00001100; /* Dest key in override */
587     lpData[4] = 0x00000000; /* Dest key in src surface */
588     lpData[5] = 0x00000000; /* Dest key in src surface */
589     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
590     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
591
592     /* Dest key blit */
593     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST, &fx);
594     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
595
596     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
597     ok(rc==DD_OK,"Lock returned: %x\n",rc);
598     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
599     lpData = ddsd2.lpSurface;
600
601     /* DirectDraw uses the dest blit key from the SOURCE surface ! */
602     ok(lpData[0] == 0x00ff0000 &&
603        lpData[1] == 0x00ff0000 &&
604        lpData[2] == 0x00001100 &&
605        lpData[3] == 0x00001100 &&
606        lpData[4] == 0x00001100 && /* Key applies here */
607        lpData[5] == 0x00110000,   /* Key applies here */
608        "Surface data after dest key blit does not match\n");
609
610     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
611     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
612     lpData[2] = 0x00001100; /* Dest key in override */
613     lpData[3] = 0x00001100; /* Dest key in override */
614     lpData[4] = 0x00000000; /* Dest key in src surface */
615     lpData[5] = 0x00000000; /* Dest key in src surface */
616     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
617     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
618
619     /* Dest override key blit */
620     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
621     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
622
623     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
624     ok(rc==DD_OK,"Lock returned: %x\n",rc);
625     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
626     lpData = ddsd2.lpSurface;
627
628     ok(lpData[0] == 0x00FF0000 &&
629        lpData[1] == 0x00FF0000 &&
630        lpData[2] == 0x00FF0000 && /* Key applies here */
631        lpData[3] == 0x0000FF00 && /* Key applies here */
632        lpData[4] == 0x00000000 &&
633        lpData[5] == 0x00000000,
634        "Surface data after dest key override blit does not match\n");
635
636     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
637     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
638     lpData[2] = 0x00001100; /* Dest key in override */
639     lpData[3] = 0x00001100; /* Dest key in override */
640     lpData[4] = 0x00000000; /* Dest key in src surface */
641     lpData[5] = 0x00000000; /* Dest key in src surface */
642     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
643     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
644
645     /* Dest override key blit. Supposed to fail too */
646     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
647     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
648
649     /* Check for unchanged data */
650     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
651     ok(rc==DD_OK,"Lock returned: %x\n",rc);
652     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
653     lpData = ddsd2.lpSurface;
654
655     ok(lpData[0] == 0x00FF0000 &&
656        lpData[1] == 0x00FF0000 &&
657        lpData[2] == 0x00001100 && /* Key applies here */
658        lpData[3] == 0x00001100 && /* Key applies here */
659        lpData[4] == 0x00000000 &&
660        lpData[5] == 0x00000000,
661        "Surface data with dest key and dest override does not match\n");
662
663     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
664     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
665     lpData[2] = 0x00001100; /* Dest key in override */
666     lpData[3] = 0x00001100; /* Dest key in override */
667     lpData[4] = 0x00000000; /* Dest key in src surface */
668     lpData[5] = 0x00000000; /* Dest key in src surface */
669     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
670     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
671
672     /* Modify the source data a bit to give some more conclusive results */
673     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
674     ok(rc==DD_OK,"Lock returned: %x\n",rc);
675     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
676     lpData = ddsd2.lpSurface;
677     lpData[5] = 0x000000FF; /* Applies to src blt key in src surface */
678     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
679     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
680
681     /* Source and destination key */
682     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
683     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
684
685     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
686     ok(rc==DD_OK,"Lock returned: %x\n",rc);
687     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
688     lpData = ddsd2.lpSurface;
689
690     ok(lpData[0] == 0x00FF0000 && /* Masked by Destination key */
691        lpData[1] == 0x00FF0000 && /* Masked by Destination key */
692        lpData[2] == 0x00001100 && /* Masked by Destination key */
693        lpData[3] == 0x00001100 && /* Masked by Destination key */
694        lpData[4] == 0x00001100 && /* Allowed by destination key, not masked by source key */
695        lpData[5] == 0x00000000,   /* Allowed by dst key, but masked by source key */
696        "Surface data with src key and dest key blit does not match\n");
697
698     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
699     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
700     lpData[2] = 0x00001100; /* Dest key in override */
701     lpData[3] = 0x00001100; /* Dest key in override */
702     lpData[4] = 0x00000000; /* Dest key in src surface */
703     lpData[5] = 0x00000000; /* Dest key in src surface */
704     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
705     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
706
707     /* Override keys without ddbltfx parameter fail */
708     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
709     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
710     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
711     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
712
713     /* Try blitting without keys in the source surface*/
714     rc = IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, NULL);
715     ok(rc == DD_OK, "SetColorKey returned %x\n", rc);
716     rc = IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_DESTBLT, NULL);
717     ok(rc == DD_OK, "SetColorKey returned %x\n", rc);
718
719     /* That fails now. Do not bother to check that the data is unmodified */
720     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, &fx);
721     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
722
723     /* Dest key blit still works. Which key is used this time??? */
724     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST, &fx);
725     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
726
727     /* With correctly passed override keys no key in the surface is needed.
728      * Again, the result was checked before, no need to do that again
729      */
730     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
731     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
732     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
733     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
734
735     IDirectDrawSurface_Release(lpSrc);
736     IDirectDrawSurface_Release(lpDst);
737 }
738
739 static void QueryInterface(void)
740 {
741     IDirectDrawSurface *dsurface;
742     DDSURFACEDESC surface;
743     LPVOID object;
744     HRESULT ret;
745
746     /* Create a surface */
747     ZeroMemory(&surface, sizeof(surface));
748     surface.dwSize = sizeof(surface);
749     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
750     surface.dwHeight = 10;
751     surface.dwWidth = 10;
752     ret = IDirectDraw_CreateSurface(lpDD, &surface, &dsurface, NULL);
753     if(ret != DD_OK)
754     {
755         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
756         return;
757     }
758
759     /* Call IUnknown::QueryInterface */
760     ret = IDirectDrawSurface_QueryInterface(dsurface, 0, &object);
761     ok(ret == DDERR_INVALIDPARAMS, "IDirectDrawSurface::QueryInterface returned %x\n", ret);
762
763     IDirectDrawSurface_Release(dsurface);
764 }
765
766 /* The following tests test which interface is returned by IDirectDrawSurfaceX::GetDDInterface.
767  * It uses refcounts to test that and compares the interface addresses. Partially fits here, and
768  * partially in the refcount test
769  */
770
771 static ULONG getref(IUnknown *iface)
772 {
773     IUnknown_AddRef(iface);
774     return IUnknown_Release(iface);
775 }
776
777 static void GetDDInterface_1(void)
778 {
779     IDirectDrawSurface2 *dsurface2;
780     IDirectDrawSurface *dsurface;
781     DDSURFACEDESC surface;
782     HRESULT ret;
783     IDirectDraw2 *dd2;
784     IDirectDraw4 *dd4;
785     IDirectDraw7 *dd7;
786     ULONG ref1, ref2, ref4, ref7;
787     void *dd;
788
789     /* Create a surface */
790     ZeroMemory(&surface, sizeof(surface));
791     surface.dwSize = sizeof(surface);
792     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
793     surface.dwHeight = 10;
794     surface.dwWidth = 10;
795     ret = IDirectDraw_CreateSurface(lpDD, &surface, &dsurface, NULL);
796     if(ret != DD_OK)
797     {
798         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
799         return;
800     }
801     ret = IDirectDrawSurface_QueryInterface(dsurface, &IID_IDirectDrawSurface2, (void **) &dsurface2);
802     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
803     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
804     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
805     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
806     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
807     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
808     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
809
810     ref1 = getref((IUnknown *) lpDD);
811     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
812     ref2 = getref((IUnknown *) dd2);
813     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
814     ref4 = getref((IUnknown *) dd4);
815     ok(ref4 == 1, "IDirectDraw4 refcount is %d\n", ref4);
816     ref7 = getref((IUnknown *) dd7);
817     ok(ref7 == 1, "IDirectDraw7 refcount is %d\n", ref7);
818
819
820     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, &dd);
821     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
822     ok(getref((IUnknown *) lpDD) == ref1 + 1, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
823     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
824     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
825     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
826
827     ok(dd == lpDD, "Returned interface pointer is not equal to the creation interface\n");
828     IUnknown_Release((IUnknown *) dd);
829
830     /* try a NULL pointer */
831     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, NULL);
832     ok(ret == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
833
834     IDirectDraw_Release(dd2);
835     IDirectDraw_Release(dd4);
836     IDirectDraw_Release(dd7);
837     IDirectDrawSurface2_Release(dsurface2);
838     IDirectDrawSurface_Release(dsurface);
839 }
840
841 static void GetDDInterface_2(void)
842 {
843     IDirectDrawSurface2 *dsurface2;
844     IDirectDrawSurface *dsurface;
845     DDSURFACEDESC surface;
846     HRESULT ret;
847     IDirectDraw2 *dd2;
848     IDirectDraw4 *dd4;
849     IDirectDraw7 *dd7;
850     ULONG ref1, ref2, ref4, ref7;
851     void *dd;
852
853     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
854     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
855     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
856     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
857     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
858     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
859
860     /* Create a surface */
861     ZeroMemory(&surface, sizeof(surface));
862     surface.dwSize = sizeof(surface);
863     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
864     surface.dwHeight = 10;
865     surface.dwWidth = 10;
866     ret = IDirectDraw2_CreateSurface(dd2, &surface, &dsurface, NULL);
867     if(ret != DD_OK)
868     {
869         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
870         return;
871     }
872     ret = IDirectDrawSurface_QueryInterface(dsurface, &IID_IDirectDrawSurface2, (void **) &dsurface2);
873     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
874
875     ref1 = getref((IUnknown *) lpDD);
876     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
877     ref2 = getref((IUnknown *) dd2);
878     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
879     ref4 = getref((IUnknown *) dd4);
880     ok(ref4 == 1, "IDirectDraw4 refcount is %d\n", ref4);
881     ref7 = getref((IUnknown *) dd7);
882     ok(ref7 == 1, "IDirectDraw7 refcount is %d\n", ref7);
883
884
885     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, &dd);
886     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
887     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
888     ok(getref((IUnknown *) dd2) == ref2 + 1, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
889     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
890     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
891
892     ok(dd == dd2, "Returned interface pointer is not equal to the creation interface\n");
893     IUnknown_Release((IUnknown *) dd);
894
895     IDirectDraw_Release(dd2);
896     IDirectDraw_Release(dd4);
897     IDirectDraw_Release(dd7);
898     IDirectDrawSurface2_Release(dsurface2);
899     IDirectDrawSurface_Release(dsurface);
900 }
901
902 static void GetDDInterface_4(void)
903 {
904     IDirectDrawSurface4 *dsurface4;
905     IDirectDrawSurface2 *dsurface2;
906     DDSURFACEDESC2 surface;
907     HRESULT ret;
908     IDirectDraw2 *dd2;
909     IDirectDraw4 *dd4;
910     IDirectDraw7 *dd7;
911     ULONG ref1, ref2, ref4, ref7;
912     void *dd;
913
914     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
915     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
916     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
917     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
918     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
919     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
920
921     /* Create a surface */
922     ZeroMemory(&surface, sizeof(surface));
923     surface.dwSize = sizeof(surface);
924     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
925     surface.dwHeight = 10;
926     surface.dwWidth = 10;
927     ret = IDirectDraw4_CreateSurface(dd4, &surface, &dsurface4, NULL);
928     if(ret != DD_OK)
929     {
930         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
931         return;
932     }
933     ret = IDirectDrawSurface4_QueryInterface(dsurface4, &IID_IDirectDrawSurface2, (void **) &dsurface2);
934     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
935
936     ref1 = getref((IUnknown *) lpDD);
937     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
938     ref2 = getref((IUnknown *) dd2);
939     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
940     ref4 = getref((IUnknown *) dd4);
941     ok(ref4 == 2, "IDirectDraw4 refcount is %d\n", ref4);
942     ref7 = getref((IUnknown *) dd7);
943     ok(ref7 == 1, "IDirectDraw7 refcount is %d\n", ref7);
944
945     ret = IDirectDrawSurface4_GetDDInterface(dsurface4, &dd);
946     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
947     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
948     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
949     ok(getref((IUnknown *) dd4) == ref4 + 1, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
950     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
951
952     ok(dd == dd4, "Returned interface pointer is not equal to the creation interface\n");
953     IUnknown_Release((IUnknown *) dd);
954
955     /* Now test what happens if we QI the surface for some other version - It should still return the creation interface */
956     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, &dd);
957     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
958     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
959     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
960     ok(getref((IUnknown *) dd4) == ref4 + 1, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
961     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
962
963     ok(dd == dd4, "Returned interface pointer is not equal to the creation interface\n");
964     IUnknown_Release((IUnknown *) dd);
965
966     IDirectDraw_Release(dd2);
967     IDirectDraw_Release(dd4);
968     IDirectDraw_Release(dd7);
969     IDirectDrawSurface4_Release(dsurface4);
970     IDirectDrawSurface2_Release(dsurface2);
971 }
972
973 static void GetDDInterface_7(void)
974 {
975     IDirectDrawSurface7 *dsurface7;
976     IDirectDrawSurface4 *dsurface4;
977     DDSURFACEDESC2 surface;
978     HRESULT ret;
979     IDirectDraw2 *dd2;
980     IDirectDraw4 *dd4;
981     IDirectDraw7 *dd7;
982     ULONG ref1, ref2, ref4, ref7;
983     void *dd;
984
985     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
986     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
987     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
988     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
989     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
990     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
991
992     /* Create a surface */
993     ZeroMemory(&surface, sizeof(surface));
994     surface.dwSize = sizeof(surface);
995     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
996     surface.dwHeight = 10;
997     surface.dwWidth = 10;
998     ret = IDirectDraw7_CreateSurface(dd7, &surface, &dsurface7, NULL);
999     if(ret != DD_OK)
1000     {
1001         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
1002         return;
1003     }
1004     ret = IDirectDrawSurface7_QueryInterface(dsurface7, &IID_IDirectDrawSurface4, (void **) &dsurface4);
1005     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
1006
1007     ref1 = getref((IUnknown *) lpDD);
1008     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
1009     ref2 = getref((IUnknown *) dd2);
1010     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
1011     ref4 = getref((IUnknown *) dd4);
1012     ok(ref4 == 1, "IDirectDraw4 refcount is %d\n", ref4);
1013     ref7 = getref((IUnknown *) dd7);
1014     ok(ref7 == 2, "IDirectDraw7 refcount is %d\n", ref7);
1015
1016     ret = IDirectDrawSurface7_GetDDInterface(dsurface7, &dd);
1017     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
1018     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
1019     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
1020     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
1021     ok(getref((IUnknown *) dd7) == ref7 + 1, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
1022
1023     ok(dd == dd7, "Returned interface pointer is not equal to the creation interface\n");
1024     IUnknown_Release((IUnknown *) dd);
1025
1026     /* Now test what happens if we QI the surface for some other version - It should still return the creation interface */
1027     ret = IDirectDrawSurface4_GetDDInterface(dsurface4, &dd);
1028     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
1029     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
1030     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
1031     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
1032     ok(getref((IUnknown *) dd7) == ref7 + 1, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
1033
1034     ok(dd == dd7, "Returned interface pointer is not equal to the creation interface\n");
1035     IUnknown_Release((IUnknown *) dd);
1036
1037     IDirectDraw_Release(dd2);
1038     IDirectDraw_Release(dd4);
1039     IDirectDraw_Release(dd7);
1040     IDirectDrawSurface4_Release(dsurface4);
1041     IDirectDrawSurface7_Release(dsurface7);
1042 }
1043
1044 static ULONG getRefcount(IUnknown *iface)
1045 {
1046     IUnknown_AddRef(iface);
1047     return IUnknown_Release(iface);
1048 }
1049
1050 #define MAXEXPECTED 8  /* Can match up to 8 expected surfaces */
1051 struct enumstruct
1052 {
1053     IDirectDrawSurface *expected[MAXEXPECTED];
1054     UINT count;
1055 };
1056
1057 static HRESULT WINAPI enumCB(IDirectDrawSurface *surf, DDSURFACEDESC *desc, void *ctx)
1058 {
1059     int i;
1060     BOOL found = FALSE;
1061
1062     for(i = 0; i < MAXEXPECTED; i++)
1063     {
1064         if(((struct enumstruct *)ctx)->expected[i] == surf) found = TRUE;
1065     }
1066
1067     ok(found, "Unexpected surface %p enumerated\n", surf);
1068     ((struct enumstruct *)ctx)->count++;
1069     IDirectDrawSurface_Release(surf);
1070     return DDENUMRET_OK;
1071 }
1072
1073 static void EnumTest(void)
1074 {
1075     HRESULT rc;
1076     DDSURFACEDESC ddsd;
1077     IDirectDrawSurface *surface;
1078     struct enumstruct ctx;
1079
1080     ddsd.dwSize = sizeof(ddsd);
1081     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
1082     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1083     U2(ddsd).dwMipMapCount = 3;
1084     ddsd.dwWidth = 32;
1085     ddsd.dwHeight = 32;
1086     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
1087     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
1088
1089     memset(&ctx, 0, sizeof(ctx));
1090     ctx.expected[0] = surface;
1091     rc = IDirectDrawSurface_GetAttachedSurface(ctx.expected[0], &ddsd.ddsCaps, &ctx.expected[1]);
1092     ok(rc == DD_OK, "GetAttachedSurface returned %08x\n", rc);
1093     rc = IDirectDrawSurface_GetAttachedSurface(ctx.expected[1], &ddsd.ddsCaps, &ctx.expected[2]);
1094     ok(rc == DD_OK, "GetAttachedSurface returned %08x\n", rc);
1095     rc = IDirectDrawSurface_GetAttachedSurface(ctx.expected[2], &ddsd.ddsCaps, &ctx.expected[3]);
1096     ok(rc == DDERR_NOTFOUND, "GetAttachedSurface returned %08x\n", rc);
1097     ok(!ctx.expected[3], "expected NULL pointer\n");
1098     ctx.count = 0;
1099
1100     rc = IDirectDraw_EnumSurfaces(lpDD, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, &ddsd, &ctx, enumCB);
1101     ok(rc == DD_OK, "IDirectDraw_EnumSurfaces returned %08x\n", rc);
1102     ok(ctx.count == 3, "%d surfaces enumerated, expected 3\n", ctx.count);
1103
1104     ctx.count = 0;
1105     rc = IDirectDraw_EnumSurfaces(lpDD, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, &ctx, enumCB);
1106     ok(rc == DD_OK, "IDirectDraw_EnumSurfaces returned %08x\n", rc);
1107     ok(ctx.count == 3, "%d surfaces enumerated, expected 3\n", ctx.count);
1108
1109     IDirectDrawSurface_Release(ctx.expected[2]);
1110     IDirectDrawSurface_Release(ctx.expected[1]);
1111     IDirectDrawSurface_Release(surface);
1112 }
1113
1114 static HRESULT WINAPI SurfaceCounter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1115 {
1116     UINT *num = context;
1117     (*num)++;
1118     IDirectDrawSurface_Release(surface);
1119     return DDENUMRET_OK;
1120 }
1121
1122 static void AttachmentTest7(void)
1123 {
1124     HRESULT hr;
1125     IDirectDraw7 *dd7;
1126     IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
1127     IDirectDrawSurface *surface1v1, *surface2v1;
1128     DDSURFACEDESC2 ddsd, ddsd2;
1129     DWORD ref;
1130     UINT num;
1131     DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, 0}, caps2 = {DDSCAPS_BACKBUFFER,0,0,0};
1132     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1133
1134     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
1135     ok(hr == DD_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
1136
1137     memset(&ddsd, 0, sizeof(ddsd));
1138     ddsd.dwSize = sizeof(ddsd);
1139     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
1140     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1141     U2(ddsd).dwMipMapCount = 3; /* Will create 128x128, 64x64, 32x32 */
1142     ddsd.dwWidth = 128;
1143     ddsd.dwHeight = 128;
1144     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1145     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1146
1147     /* ROOT */
1148     num = 0;
1149     IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &num, SurfaceCounter);
1150     ok(num == 1, "Mipmap root has %d surfaces attached, expected 1\n", num);
1151     /* DONE ROOT */
1152
1153     /* LEVEL 1 */
1154     hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
1155     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1156     num = 0;
1157     IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &num, SurfaceCounter);
1158     ok(num == 1, "First mip level has %d surfaces attached, expected 1\n", num);
1159     /* DONE LEVEL 1 */
1160
1161     /* LEVEL 2 */
1162     hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
1163     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1164     IDirectDrawSurface7_Release(surface2);
1165     num = 0;
1166     IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &num, SurfaceCounter);
1167     ok(num == 0, "Second mip level has %d surfaces attached, expected 1\n", num);
1168     /* Done level 2 */
1169     /* Mip level 3 is still needed */
1170     hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
1171     ok(hr == DDERR_NOTFOUND, "GetAttachedSurface returned %08x\n", hr);
1172     ok(!surface4, "expected NULL pointer\n");
1173
1174     /* Try to attach a 16x16 miplevel - Should not work as far I can see */
1175     memset(&ddsd, 0, sizeof(ddsd));
1176     ddsd.dwSize = sizeof(ddsd);
1177     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1178     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1179     ddsd.dwWidth = 16;
1180     ddsd.dwHeight = 16;
1181     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1182     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1183
1184     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1185     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 128x128 texture root returned %08x\n", hr);
1186     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
1187     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 texture returned %08x\n", hr);
1188     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
1189     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 32x32 texture mip level returned %08x\n", hr);
1190     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
1191     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 surface returned %08x\n", hr);
1192
1193     IDirectDrawSurface7_Release(surface2);
1194
1195     memset(&ddsd, 0, sizeof(ddsd));
1196     ddsd.dwSize = sizeof(ddsd);
1197     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1198     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
1199     ddsd.dwWidth = 16;
1200     ddsd.dwHeight = 16;
1201     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1202     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1203
1204     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1205     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr);
1206     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
1207     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr);
1208     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
1209     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr);
1210     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
1211     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 offscreen plain surface returned %08x\n", hr);
1212
1213     IDirectDrawSurface7_Release(surface3);
1214     IDirectDrawSurface7_Release(surface2);
1215     IDirectDrawSurface7_Release(surface1);
1216
1217     hr = IDirectDraw7_SetCooperativeLevel(dd7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1218     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1219
1220     memset(&ddsd, 0, sizeof(ddsd));
1221     ddsd.dwSize = sizeof(ddsd);
1222     ddsd.dwFlags = DDSD_BACKBUFFERCOUNT | DDSD_CAPS;
1223     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1224     ddsd.dwBackBufferCount = 2;
1225     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1226     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1227
1228     /* backbuffer surfaces must not have dwBackBufferCount set */
1229     ddsd2.dwSize = sizeof(ddsd2);
1230     hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps2, &surface2);
1231     ok(hr==DD_OK,"GetAttachedSurface returned: %x\n", hr);
1232     hr = IDirectDrawSurface7_GetSurfaceDesc(surface2, &ddsd2);
1233     ok(hr==DD_OK,"GetSurfaceDesc returned: %x\n", hr);
1234     ok(ddsd2.dwBackBufferCount==0,"backbuffer surface has dwBackBufferCount==%u\n", ddsd2.dwBackBufferCount);
1235
1236     num = 0;
1237     IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &num, SurfaceCounter);
1238     ok(num == 1, "Primary surface has %d surfaces attached, expected 1\n", num);
1239     IDirectDrawSurface7_Release(surface1);
1240
1241     /* Those are some invalid descriptions, no need to test attachments with them */
1242     memset(&ddsd, 0, sizeof(ddsd));
1243     ddsd.dwSize = sizeof(ddsd);
1244     ddsd.dwFlags = DDSD_CAPS;
1245     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER;
1246     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1247     ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr);
1248     memset(&ddsd, 0, sizeof(ddsd));
1249     ddsd.dwSize = sizeof(ddsd);
1250     ddsd.dwFlags = DDSD_CAPS;
1251     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER;
1252     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1253     ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr);
1254
1255     /* Try a single primary and two offscreen plain surfaces */
1256     memset(&ddsd, 0, sizeof(ddsd));
1257     ddsd.dwSize = sizeof(ddsd);
1258     ddsd.dwFlags = DDSD_CAPS;
1259     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1260     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1261     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1262
1263     memset(&ddsd, 0, sizeof(ddsd));
1264     ddsd.dwSize = sizeof(ddsd);
1265     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1266     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1267     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1268     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1269     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1270     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1271
1272     memset(&ddsd, 0, sizeof(ddsd));
1273     ddsd.dwSize = sizeof(ddsd);
1274     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1275     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1276     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1277     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1278     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface3, NULL);
1279     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1280
1281     /* This one has a different size */
1282     memset(&ddsd, 0, sizeof(ddsd));
1283     ddsd.dwSize = sizeof(ddsd);
1284     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1285     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1286     ddsd.dwWidth = 128;
1287     ddsd.dwHeight = 128;
1288     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface4, NULL);
1289     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1290
1291     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1292     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer returned %08x\n", hr);
1293     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
1294     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface returned %08x\n", hr);
1295     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
1296     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to another offscreen plain surface returned %08x\n", hr);
1297     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
1298     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer of different size returned %08x\n", hr);
1299     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
1300     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface of different size returned %08x\n", hr);
1301
1302     IDirectDrawSurface7_Release(surface4);
1303     IDirectDrawSurface7_Release(surface3);
1304     IDirectDrawSurface7_Release(surface2);
1305     IDirectDrawSurface7_Release(surface1);
1306
1307     /* Test DeleteAttachedSurface and automatic detachment of attached surfaces on release */
1308     memset(&ddsd, 0, sizeof(ddsd));
1309     ddsd.dwSize = sizeof(ddsd);
1310     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1311     ddsd.dwWidth = 64;
1312     ddsd.dwHeight = 64;
1313     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1314     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1315     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
1316     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1317     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1318     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1319     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1320
1321     memset(&ddsd2, 0, sizeof(ddsd2));
1322     ddsd2.dwSize = sizeof(ddsd2);
1323     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1324     ddsd2.dwWidth = ddsd.dwWidth;
1325     ddsd2.dwHeight = ddsd.dwHeight;
1326     ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1327     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
1328     U4(ddsd2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
1329     U1(U4(ddsd2).ddpfPixelFormat).dwZBufferBitDepth = 16;
1330     U3(U4(ddsd2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
1331
1332     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1333     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1334     if (SUCCEEDED(hr))
1335     {
1336         hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surface2, NULL);
1337         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1338         if (SUCCEEDED(hr))
1339         {
1340             hr = IDirectDrawSurface7_QueryInterface(surface1, &IID_IDirectDrawSurface, (void **)&surface1v1);
1341             ok(hr == DD_OK, "IDirectDrawSurface7_QueryInterface returned %08x\n", hr);
1342             hr = IDirectDrawSurface7_QueryInterface(surface2, &IID_IDirectDrawSurface, (void **)&surface2v1);
1343             ok(hr == DD_OK, "IDirectDrawSurface7_QueryInterface returned %08x\n", hr);
1344
1345             /* DeleteAttachedSurface when attaching via IDirectDrawSurface7 */
1346             hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1347             ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1348             if (SUCCEEDED(hr))
1349             {
1350                 ref = getRefcount((IUnknown *)surface2);
1351                 ok(ref == 2, "Got refcount %d, expected 2\n", ref);
1352                 ref = getRefcount((IUnknown *)surface2v1);
1353                 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
1354
1355                 /* Try reattach */
1356                 hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1357                 ok(hr == DDERR_SURFACEALREADYATTACHED, "AddAttachedSurface returned %08x\n", hr);
1358
1359                 /* Attachment / detachment on another interface */
1360                 hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
1361                 todo_wine ok(hr == DDERR_CANNOTATTACHSURFACE, "AddAttachedSurface returned %08x\n", hr);
1362                 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
1363                 ok(hr == DDERR_SURFACENOTATTACHED, "DeleteAttachedSurface returned %08x\n", hr);
1364
1365                 /* Attaching while already attached to other surface */
1366                 hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface3, NULL);
1367                 ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1368                 if (SUCCEEDED(hr))
1369                 {
1370                     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
1371                     todo_wine ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1372                     if (SUCCEEDED(hr))
1373                     {
1374                         hr = IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface2);
1375                         ok(hr == DD_OK, "DeleteAttachedSurface returned %08x\n", hr);
1376                     }
1377                     IDirectDrawSurface7_Release(surface3);
1378                 }
1379
1380                 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
1381                 ok(hr == DD_OK, "DeleteAttachedSurface returned %08x\n", hr);
1382                 ref = getRefcount((IUnknown *)surface2);
1383                 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
1384                 ref = getRefcount((IUnknown *)surface2v1);
1385                 ok(ref == 1, "Got refcount %d, expected 1\n", ref);
1386             }
1387
1388             /* DeleteAttachedSurface when attaching via IDirectDrawSurface */
1389             hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
1390             ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1391             if (SUCCEEDED(hr))
1392             {
1393                 hr = IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface2);
1394                 ok(hr == DDERR_SURFACENOTATTACHED, "DeleteAttachedSurface returned %08x\n", hr);
1395                 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1v1, 0, surface2v1);
1396                 ok(hr == DD_OK, "DeleteAttachedSurface returned %08x\n", hr);
1397             }
1398             ref = IDirectDrawSurface7_Release(surface2);
1399             ok(!ref, "Got refcount %d, expected 0\n", ref);
1400             ref = IDirectDrawSurface7_Release(surface1);
1401             ok(!ref, "Got refcount %d, expected 0\n", ref);
1402
1403             /* Automatic detachment on release */
1404             hr = IDirectDrawSurface_AddAttachedSurface(surface1v1, surface2v1);
1405             ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1406             ref = getRefcount((IUnknown *)surface2v1);
1407             ok(ref == 2, "Got refcount %d, expected 2\n", ref);
1408             ref = IDirectDrawSurface_Release(surface1v1);
1409             ok(!ref, "Got refcount %d, expected 0\n", ref);
1410             ref = getRefcount((IUnknown *)surface2v1);
1411             ok(ref == 1, "Got refcount %d, expected 1\n", ref);
1412             ref = IDirectDrawSurface_Release(surface2v1);
1413             ok(!ref, "Got refcount %d, expected 0\n", ref);
1414         }
1415         else
1416             IDirectDrawSurface7_Release(surface1);
1417     }
1418
1419     hr =IDirectDraw7_SetCooperativeLevel(dd7, NULL, DDSCL_NORMAL);
1420     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1421     IDirectDraw7_Release(dd7);
1422 }
1423
1424 static void AttachmentTest(void)
1425 {
1426     HRESULT hr;
1427     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
1428     DDSURFACEDESC ddsd, ddsd2;
1429     DWORD ref;
1430     DDSCAPS caps = {DDSCAPS_TEXTURE};
1431     BOOL refrast = FALSE;
1432     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1433
1434     memset(&ddsd, 0, sizeof(ddsd));
1435     ddsd.dwSize = sizeof(ddsd);
1436     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
1437     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1438     U2(ddsd).dwMipMapCount = 3; /* Will create 128x128, 64x64, 32x32 */
1439     ddsd.dwWidth = 128;
1440     ddsd.dwHeight = 128;
1441     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface1, NULL);
1442     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1443
1444     hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
1445     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1446     hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
1447     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1448
1449     /* Try to attach a 16x16 miplevel - Should not work as far I can see */
1450     memset(&ddsd, 0, sizeof(ddsd));
1451     ddsd.dwSize = sizeof(ddsd);
1452     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1453     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1454     ddsd.dwWidth = 16;
1455     ddsd.dwHeight = 16;
1456     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL);
1457     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1458
1459     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
1460     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 128x128 texture root returned %08x\n", hr);
1461     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
1462     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 texture returned %08x\n", hr);
1463     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
1464     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 32x32 texture mip level returned %08x\n", hr);
1465     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
1466     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 surface returned %08x\n", hr);
1467     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
1468     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 64x64 texture sublevel returned %08x\n", hr);
1469     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
1470     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 64x64 texture sublevel to a 16x16 texture returned %08x\n", hr);
1471
1472     IDirectDrawSurface7_Release(surface4);
1473
1474     memset(&ddsd, 0, sizeof(ddsd));
1475     ddsd.dwSize = sizeof(ddsd);
1476     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1477     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
1478     ddsd.dwWidth = 16;
1479     ddsd.dwHeight = 16;
1480     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface4, NULL);
1481     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1482
1483     if (SUCCEEDED(IDirectDrawSurface7_AddAttachedSurface(surface1, surface4)))
1484     {
1485         IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface4);
1486         refrast = TRUE;
1487     }
1488
1489     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4); /* Succeeds on refrast */
1490     if (refrast)
1491         ok(hr == S_OK, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr);
1492     else
1493         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr);
1494     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface4);
1495
1496     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);  /* Succeeds on refrast */
1497     if (refrast)
1498         ok(hr == S_OK, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr);
1499     else
1500         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr);
1501     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface1);
1502
1503     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);  /* Succeeds on refrast */
1504     if (refrast)
1505         ok(hr == S_OK, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr);
1506     else
1507         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr);
1508     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface4);
1509
1510     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
1511     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 offscreen plain surface returned %08x\n", hr);
1512     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface4, 0, surface3);
1513
1514     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);  /* Succeeds on refrast */
1515     if (refrast)
1516         ok(hr == S_OK, "Attaching a 16x16 offscreen plain surface to a 64x64 texture sublevel returned %08x\n", hr);
1517     else
1518         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 64x64 texture sublevel returned %08x\n", hr);
1519     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface2, 0, surface4);
1520
1521     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
1522     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 64x64 texture sublevel to a 16x16 offscreen plain surface returned %08x\n", hr);
1523     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface4, 0, surface2);
1524
1525     IDirectDrawSurface7_Release(surface4);
1526     IDirectDrawSurface7_Release(surface3);
1527     IDirectDrawSurface7_Release(surface2);
1528     IDirectDrawSurface7_Release(surface1);
1529
1530     hr = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1531     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1532
1533     /* Creating a back buffer as-is, is not allowed. No need to perform attachment tests */
1534     memset(&ddsd, 0, sizeof(ddsd));
1535     ddsd.dwSize = sizeof(ddsd);
1536     ddsd.dwFlags = DDSD_CAPS;
1537     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER;
1538     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL);
1539     ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr);
1540     /* This old ddraw version happily creates explicit front buffers */
1541     memset(&ddsd, 0, sizeof(ddsd));
1542     ddsd.dwSize = sizeof(ddsd);
1543     ddsd.dwFlags = DDSD_CAPS;
1544     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER;
1545     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL);
1546     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1547     IDirectDrawSurface_Release(surface1);
1548
1549     /* Try a single primary and two offscreen plain surfaces */
1550     memset(&ddsd, 0, sizeof(ddsd));
1551     ddsd.dwSize = sizeof(ddsd);
1552     ddsd.dwFlags = DDSD_CAPS;
1553     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1554     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL);
1555     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1556
1557     memset(&ddsd, 0, sizeof(ddsd));
1558     ddsd.dwSize = sizeof(ddsd);
1559     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1560     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1561     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1562     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1563     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL);
1564     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1565
1566     memset(&ddsd, 0, sizeof(ddsd));
1567     ddsd.dwSize = sizeof(ddsd);
1568     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1569     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1570     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1571     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1572     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface3, NULL);
1573     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1574
1575     /* This one has a different size */
1576     memset(&ddsd, 0, sizeof(ddsd));
1577     ddsd.dwSize = sizeof(ddsd);
1578     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1579     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1580     ddsd.dwWidth = 128;
1581     ddsd.dwHeight = 128;
1582     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL);
1583     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1584
1585     hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
1586     ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
1587        "Attaching an offscreen plain surface to a front buffer returned %08x\n", hr);
1588     if(SUCCEEDED(hr))
1589     {
1590         /* Try the reverse without detaching first */
1591         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
1592         ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
1593         hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
1594         ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
1595     }
1596     hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
1597     ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
1598        "Attaching a front buffer to an offscreen plain surface returned %08x\n", hr);
1599     if(SUCCEEDED(hr))
1600     {
1601         /* Try to detach reversed */
1602         hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
1603         ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
1604         /* Now the proper detach */
1605         hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
1606         ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
1607     }
1608     hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3); /* Fails on refrast */
1609     ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
1610        "Attaching an offscreen plain surface to another offscreen plain surface returned %08x\n", hr);
1611     if(SUCCEEDED(hr))
1612     {
1613         hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
1614         ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
1615     }
1616     hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
1617     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer of different size returned %08x\n", hr);
1618     hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
1619     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface of different size returned %08x\n", hr);
1620
1621     IDirectDrawSurface_Release(surface4);
1622     IDirectDrawSurface_Release(surface3);
1623     IDirectDrawSurface_Release(surface2);
1624     IDirectDrawSurface_Release(surface1);
1625
1626     /* Test DeleteAttachedSurface and automatic detachment of attached surfaces on release */
1627     memset(&ddsd, 0, sizeof(ddsd));
1628     ddsd.dwSize = sizeof(ddsd);
1629     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1630     ddsd.dwWidth = 64;
1631     ddsd.dwHeight = 64;
1632     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
1633     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1634     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; /* D3DFMT_R5G6B5 */
1635     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 16;
1636     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xF800;
1637     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x07E0;
1638     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x001F;
1639
1640     memset(&ddsd2, 0, sizeof(ddsd2));
1641     ddsd2.dwSize = sizeof(ddsd2);
1642     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1643     ddsd2.dwWidth = ddsd.dwWidth;
1644     ddsd2.dwHeight = ddsd.dwHeight;
1645     ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
1646     ddsd2.ddpfPixelFormat.dwSize = sizeof(ddsd2.ddpfPixelFormat);
1647     ddsd2.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
1648     U1(ddsd2.ddpfPixelFormat).dwZBufferBitDepth = 16;
1649     U3(ddsd2.ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
1650
1651     hr = IDirectDraw_CreateSurface(lpDD, (DDSURFACEDESC *)&ddsd, &surface1, NULL);
1652     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1653     if (SUCCEEDED(hr))
1654     {
1655         hr = IDirectDraw_CreateSurface(lpDD, (DDSURFACEDESC *)&ddsd2, &surface2, NULL);
1656         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1657         if (SUCCEEDED(hr))
1658         {
1659             /* DeleteAttachedSurface */
1660             hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
1661             ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1662             if (SUCCEEDED(hr))
1663             {
1664                 ref = getRefcount((IUnknown *)surface2);
1665                 ok(ref == 2, "Got refcount %d, expected 2\n", ref);
1666
1667                 /* Try reattach */
1668                 hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
1669                 ok(hr == DDERR_SURFACEALREADYATTACHED, "AddAttachedSurface returned %08x\n", hr);
1670
1671                 /* Attaching while already attached to other surface */
1672                 hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface3, NULL);
1673                 ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1674                 if (SUCCEEDED(hr))
1675                 {
1676                     hr = IDirectDrawSurface_AddAttachedSurface(surface3, surface2);
1677                     todo_wine ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1678                     if (SUCCEEDED(hr))
1679                     {
1680                         hr = IDirectDrawSurface_DeleteAttachedSurface(surface3, 0, surface2);
1681                         ok(hr == DD_OK, "DeleteAttachedSurface returned %08x\n", hr);
1682                     }
1683                     IDirectDrawSurface_Release(surface3);
1684                 }
1685
1686                 hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
1687                 ok(hr == DD_OK, "DeleteAttachedSurface returned %08x\n", hr);
1688                 ref = getRefcount((IUnknown *)surface2);
1689                 ok(ref == 1, "Got refcount %d, expected 2\n", ref);
1690             }
1691
1692             /* Automatic detachment on release */
1693             hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
1694             ok(hr == DD_OK, "AddAttachedSurface returned %08x\n", hr);
1695             ref = getRefcount((IUnknown *)surface2);
1696             ok(ref == 2, "Got refcount %d, expected 2\n", ref);
1697             ref = IDirectDrawSurface_Release(surface1);
1698             ok(!ref, "Got refcount %d, expected 0\n", ref);
1699             ref = getRefcount((IUnknown *)surface2);
1700             ok(ref == 1, "Got refcount %d, expected 1\n", ref);
1701             ref = IDirectDrawSurface_Release(surface2);
1702             ok(!ref, "Got refcount %d, expected 0\n", ref);
1703         }
1704         else
1705             IDirectDrawSurface_Release(surface1);
1706     }
1707
1708     hr =IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
1709     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1710
1711     DestroyWindow(window);
1712 }
1713
1714 struct compare
1715 {
1716     DWORD width, height;
1717     DWORD caps, caps2;
1718     UINT mips;
1719 };
1720
1721 static HRESULT WINAPI CubeTestPaletteEnum(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1722 {
1723     HRESULT hr;
1724
1725     hr = IDirectDrawSurface7_SetPalette(surface, context);
1726     if (desc->dwWidth == 64) /* This is for first mimpmap */
1727         ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "SetPalette returned: %x\n",hr);
1728     else
1729         ok(hr == DD_OK, "SetPalette returned: %x\n",hr);
1730
1731     IDirectDrawSurface7_Release(surface);
1732
1733     return DDENUMRET_OK;
1734 }
1735
1736 static HRESULT WINAPI CubeTestLvl2Enum(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1737 {
1738     UINT *mips = context;
1739
1740     (*mips)++;
1741     IDirectDrawSurface7_EnumAttachedSurfaces(surface,
1742                                              context,
1743                                              CubeTestLvl2Enum);
1744
1745     return DDENUMRET_OK;
1746 }
1747
1748 static HRESULT WINAPI CubeTestLvl1Enum(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1749 {
1750     UINT mips = 0;
1751     UINT *num = context;
1752     static const struct compare expected[] =
1753     {
1754         {
1755             128, 128,
1756             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1757             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ,
1758             7
1759         },
1760         {
1761             128, 128,
1762             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1763             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ,
1764             7
1765         },
1766         {
1767             128, 128,
1768             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1769             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY,
1770             7
1771         },
1772         {
1773             128, 128,
1774             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1775             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY,
1776             7
1777         },
1778         {
1779             128, 128,
1780             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1781             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX,
1782             7
1783         },
1784         {
1785             64, 64, /* This is the first mipmap */
1786             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1787             DDSCAPS2_MIPMAPSUBLEVEL | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX,
1788             6
1789         },
1790     };
1791
1792     mips = 0;
1793     IDirectDrawSurface7_EnumAttachedSurfaces(surface,
1794                                              &mips,
1795                                              CubeTestLvl2Enum);
1796
1797     ok(desc->dwWidth == expected[*num].width, "Surface width is %d expected %d\n", desc->dwWidth, expected[*num].width);
1798     ok(desc->dwHeight == expected[*num].height, "Surface height is %d expected %d\n", desc->dwHeight, expected[*num].height);
1799     ok(desc->ddsCaps.dwCaps == expected[*num].caps, "Surface caps are %08x expected %08x\n", desc->ddsCaps.dwCaps, expected[*num].caps);
1800     ok(desc->ddsCaps.dwCaps2 == expected[*num].caps2, "Surface caps2 are %08x expected %08x\n", desc->ddsCaps.dwCaps2, expected[*num].caps2);
1801     ok(mips == expected[*num].mips, "Surface has %d mipmaps, expected %d\n", mips, expected[*num].mips);
1802
1803     (*num)++;
1804
1805     IDirectDrawSurface7_Release(surface);
1806
1807     return DDENUMRET_OK;
1808 }
1809
1810 static void CubeMapTest(void)
1811 {
1812     IDirectDraw7 *dd7 = NULL;
1813     IDirectDrawSurface7 *cubemap = NULL;
1814     IDirectDrawPalette *palette = NULL;
1815     DDSURFACEDESC2 ddsd;
1816     HRESULT hr;
1817     PALETTEENTRY Table[256];
1818     int i;
1819     UINT num = 0;
1820     UINT ref;
1821     struct enumstruct ctx;
1822
1823     for(i=0; i<256; i++)
1824     {
1825         Table[i].peRed   = 0xff;
1826         Table[i].peGreen = 0;
1827         Table[i].peBlue  = 0;
1828         Table[i].peFlags = 0;
1829     }
1830
1831     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
1832     ok(hr == DD_OK, "IDirectDraw::QueryInterface returned %08x\n", hr);
1833     if (FAILED(hr)) goto err;
1834
1835     memset(&ddsd, 0, sizeof(ddsd));
1836     ddsd.dwSize = sizeof(ddsd);
1837     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1838     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1839     ddsd.dwWidth = 128;
1840     ddsd.dwHeight = 128;
1841     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1842     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1843
1844     /* D3DFMT_R5G6B5 */
1845     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1846     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1847     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1848     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1849     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1850
1851     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
1852     if (FAILED(hr))
1853     {
1854         skip("Can't create cubemap surface\n");
1855         goto err;
1856     }
1857
1858     hr = IDirectDrawSurface7_GetSurfaceDesc(cubemap, &ddsd);
1859     ok(hr == DD_OK, "IDirectDrawSurface7_GetSurfaceDesc returned %08x\n", hr);
1860     ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX),
1861        "Root Caps are %08x\n", ddsd.ddsCaps.dwCaps);
1862     ok(ddsd.ddsCaps.dwCaps2 == (DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP),
1863        "Root Caps2 are %08x\n", ddsd.ddsCaps.dwCaps2);
1864
1865     IDirectDrawSurface7_EnumAttachedSurfaces(cubemap,
1866                                              &num,
1867                                              CubeTestLvl1Enum);
1868     ok(num == 6, "Surface has %d attachments\n", num);
1869     IDirectDrawSurface7_Release(cubemap);
1870
1871     /* What happens if I do not specify any faces? */
1872     memset(&ddsd, 0, sizeof(ddsd));
1873     ddsd.dwSize = sizeof(ddsd);
1874     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1875     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1876     ddsd.dwWidth = 128;
1877     ddsd.dwHeight = 128;
1878     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1879     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP;
1880
1881     /* D3DFMT_R5G6B5 */
1882     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1883     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1884     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1885     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1886     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1887
1888     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
1889     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7::CreateSurface asking for a cube map without faces returned %08x\n", hr);
1890
1891     /* Cube map faces without a cube map? */
1892     memset(&ddsd, 0, sizeof(ddsd));
1893     ddsd.dwSize = sizeof(ddsd);
1894     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1895     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1896     ddsd.dwWidth = 128;
1897     ddsd.dwHeight = 128;
1898     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1899     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP_ALLFACES;
1900
1901     /* D3DFMT_R5G6B5 */
1902     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1903     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1904     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1905     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1906     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1907
1908     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
1909     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7::CreateSurface returned %08x\n", hr);
1910
1911     memset(&ddsd, 0, sizeof(ddsd));
1912     ddsd.dwSize = sizeof(ddsd);
1913     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1914     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1915     ddsd.dwWidth = 128;
1916     ddsd.dwHeight = 128;
1917     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1918     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP_POSITIVEX;
1919
1920     /* D3DFMT_R5G6B5 */
1921     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1922     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1923     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1924     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1925     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1926
1927     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
1928     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7::CreateSurface returned %08x\n", hr);
1929
1930     memset(&ddsd, 0, sizeof(ddsd));
1931     ddsd.dwSize = sizeof(ddsd);
1932     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1933     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1934     ddsd.dwWidth = 128;
1935     ddsd.dwHeight = 128;
1936     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1937     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1938
1939     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1940     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 8;
1941
1942     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
1943     if (FAILED(hr))
1944     {
1945         skip("Can't create palletized cubemap surface\n");
1946         goto err;
1947     }
1948
1949     hr = IDirectDraw7_CreatePalette(dd7, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL);
1950     ok(hr == DD_OK, "CreatePalette failed with %08x\n", hr);
1951
1952     hr = IDirectDrawSurface7_EnumAttachedSurfaces(cubemap, palette, CubeTestPaletteEnum);
1953     ok(hr == DD_OK, "EnumAttachedSurfaces failed\n");
1954
1955     ref = getRefcount((IUnknown *) palette);
1956     ok(ref == 6, "Refcount is %u, expected 1\n", ref);
1957
1958     IDirectDrawSurface7_Release(cubemap);
1959
1960     ref = getRefcount((IUnknown *) palette);
1961     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1962
1963     IDirectDrawPalette_Release(palette);
1964
1965     /* Make sure everything is cleaned up properly. Use the enumSurfaces test infrastructure */
1966     memset(&ctx, 0, sizeof(ctx));
1967     memset(&ddsd, 0, sizeof(ddsd));
1968     ddsd.dwSize = sizeof(DDSURFACEDESC);
1969     hr = IDirectDraw_EnumSurfaces(lpDD, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, (DDSURFACEDESC *) &ddsd, (void *) &ctx, enumCB);
1970     ok(hr == DD_OK, "IDirectDraw_EnumSurfaces returned %08x\n", hr);
1971     ok(ctx.count == 0, "%d surfaces enumerated, expected 0\n", ctx.count);
1972
1973     err:
1974     if (dd7) IDirectDraw7_Release(dd7);
1975 }
1976
1977 static void test_lockrect_invalid(void)
1978 {
1979     unsigned int i, j;
1980
1981     RECT valid[] = {
1982         {60, 60, 68, 68},
1983         {60, 60, 60, 68},
1984         {60, 60, 68, 60},
1985         {120, 60, 128, 68},
1986         {60, 120, 68, 128},
1987     };
1988
1989     RECT invalid[] = {
1990         {68, 60, 60, 68},       /* left > right */
1991         {60, 68, 68, 60},       /* top > bottom */
1992         {-8, 60,  0, 68},       /* left < surface */
1993         {60, -8, 68,  0},       /* top < surface */
1994         {-16, 60, -8, 68},      /* right < surface */
1995         {60, -16, 68, -8},      /* bottom < surface */
1996         {60, 60, 136, 68},      /* right > surface */
1997         {60, 60, 68, 136},      /* bottom > surface */
1998         {136, 60, 144, 68},     /* left > surface */
1999         {60, 136, 68, 144},     /* top > surface */
2000     };
2001
2002     const DWORD dds_caps[] = {
2003         DDSCAPS_OFFSCREENPLAIN
2004     };
2005
2006     for (j = 0; j < (sizeof(dds_caps) / sizeof(*dds_caps)); ++j)
2007     {
2008         IDirectDrawSurface *surface = 0;
2009         DDSURFACEDESC surface_desc = {0};
2010         DDSURFACEDESC locked_desc = {0};
2011         HRESULT hr;
2012
2013         surface_desc.dwSize = sizeof(surface_desc);
2014         surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
2015         surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2016         surface_desc.ddsCaps.dwCaps = dds_caps[j];
2017         surface_desc.dwWidth = 128;
2018         surface_desc.dwHeight = 128;
2019         surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
2020         U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
2021         U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xFF0000;
2022         U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x00FF00;
2023         U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000FF;
2024
2025         hr = IDirectDraw_CreateSurface(lpDD, &surface_desc, &surface, NULL);
2026         ok(SUCCEEDED(hr), "CreateSurface failed (0x%08x)\n", hr);
2027         if (FAILED(hr))
2028         {
2029             skip("failed to create surface\n");
2030             continue;
2031         }
2032
2033         hr = IDirectDrawSurface_Lock(surface, NULL, NULL, DDLOCK_WAIT, NULL);
2034         ok(hr == DDERR_INVALIDPARAMS, "Lock returned 0x%08x for NULL DDSURFACEDESC,"
2035                 " expected DDERR_INVALIDPARAMS (0x%08x)\n", hr, DDERR_INVALIDPARAMS);
2036
2037         for (i = 0; i < (sizeof(valid) / sizeof(*valid)); ++i)
2038         {
2039             RECT *rect = &valid[i];
2040
2041             memset(&locked_desc, 0, sizeof(locked_desc));
2042             locked_desc.dwSize = sizeof(locked_desc);
2043
2044             hr = IDirectDrawSurface_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
2045             ok(SUCCEEDED(hr), "Lock failed (0x%08x) for rect [%d, %d]->[%d, %d]\n",
2046                     hr, rect->left, rect->top, rect->right, rect->bottom);
2047
2048             hr = IDirectDrawSurface_Unlock(surface, NULL);
2049             ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2050         }
2051
2052         for (i = 0; i < (sizeof(invalid) / sizeof(*invalid)); ++i)
2053         {
2054             RECT *rect = &invalid[i];
2055
2056             memset(&locked_desc, 1, sizeof(locked_desc));
2057             locked_desc.dwSize = sizeof(locked_desc);
2058
2059             hr = IDirectDrawSurface_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
2060             ok(hr == DDERR_INVALIDPARAMS, "Lock returned 0x%08x for rect [%d, %d]->[%d, %d]"
2061                     ", expected DDERR_INVALIDPARAMS (0x%08x)\n", hr, rect->left, rect->top,
2062                     rect->right, rect->bottom, DDERR_INVALIDPARAMS);
2063             ok(!locked_desc.lpSurface, "IDirectDrawSurface_Lock did not set lpSurface in the surface desc to zero.\n");
2064         }
2065
2066         hr = IDirectDrawSurface_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
2067         ok(hr == DD_OK, "IDirectDrawSurface_Lock(rect = NULL) failed (0x%08x)\n", hr);
2068         hr = IDirectDrawSurface_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
2069         ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned 0x%08x\n", hr);
2070         if(SUCCEEDED(hr)) {
2071             hr = IDirectDrawSurface_Unlock(surface, NULL);
2072             ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2073         }
2074         hr = IDirectDrawSurface_Unlock(surface, NULL);
2075         ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2076
2077         memset(&locked_desc, 0, sizeof(locked_desc));
2078         locked_desc.dwSize = sizeof(locked_desc);
2079         hr = IDirectDrawSurface_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
2080         ok(hr == DD_OK, "IDirectDrawSurface_Lock(rect = [%d, %d]->[%d, %d]) failed (0x%08x)\n",
2081            valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
2082         hr = IDirectDrawSurface_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
2083         ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = [%d, %d]->[%d, %d]) failed (0x%08x)\n",
2084            valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
2085
2086         /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
2087          * Afterwards unlocking the surface fails(NULL rectangle, and both locked rectangles
2088          */
2089
2090         hr = IDirectDrawSurface_Unlock(surface, NULL);
2091         ok(hr == DD_OK, "Unlock returned (0x%08x)\n", hr);
2092
2093         IDirectDrawSurface_Release(surface);
2094     }
2095 }
2096
2097 static void CompressedTest(void)
2098 {
2099     HRESULT hr;
2100     IDirectDrawSurface7 *surface;
2101     DDSURFACEDESC2 ddsd, ddsd2;
2102     IDirectDraw7 *dd7 = NULL;
2103     RECT r = { 0, 0, 128, 128 };
2104     RECT r2 = { 32, 32, 64, 64 };
2105
2106     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
2107     ok(hr == DD_OK, "IDirectDraw::QueryInterface returned %08x\n", hr);
2108
2109     memset(&ddsd, 0, sizeof(ddsd));
2110     ddsd.dwSize = sizeof(ddsd);
2111     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2112     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
2113     ddsd.dwWidth = 128;
2114     ddsd.dwHeight = 128;
2115     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
2116     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
2117     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1');
2118
2119     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2120     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2121     if (FAILED(hr))
2122     {
2123         skip("failed to create surface\n");
2124         return;
2125     }
2126
2127     memset(&ddsd2, 0, sizeof(ddsd2));
2128     ddsd2.dwSize = sizeof(ddsd2);
2129     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2130     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2131     ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2132
2133     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2134        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2135     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2136     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2137     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2138        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2139     ok(U1(ddsd2).dwLinearSize == 8192, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2140     ok(ddsd2.ddsCaps.dwCaps2 == 0, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2);
2141     IDirectDrawSurface7_Release(surface);
2142
2143     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3');
2144     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2145     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2146     if (FAILED(hr))
2147     {
2148         skip("failed to create surface\n");
2149         return;
2150     }
2151
2152     memset(&ddsd2, 0, sizeof(ddsd2));
2153     ddsd2.dwSize = sizeof(ddsd2);
2154     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2155     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2156     ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2157
2158     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2159        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2160     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2161     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2162     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2163        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2164     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2165     IDirectDrawSurface7_Release(surface);
2166
2167     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5');
2168     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2169     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2170     if (FAILED(hr))
2171     {
2172         skip("failed to create surface\n");
2173         return;
2174     }
2175
2176     memset(&ddsd2, 0, sizeof(ddsd2));
2177     ddsd2.dwSize = sizeof(ddsd2);
2178     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2179     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2180     ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2181
2182     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2183        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2184     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2185     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2186     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2187        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2188     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2189     ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface);
2190
2191     memset(&ddsd2, 0, sizeof(ddsd2));
2192     ddsd2.dwSize = sizeof(ddsd2);
2193     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2194
2195     /* Show that the description is not changed when locking the surface. What is really interesting
2196      * about this is that DDSD_LPSURFACE isn't set.
2197      */
2198     hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0);
2199     ok(hr == DD_OK, "Lock returned %08x\n", hr);
2200
2201     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2202        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2203     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2204     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2205     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2206        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2207     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2208     ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2209
2210     hr = IDirectDrawSurface7_Unlock(surface, NULL);
2211     ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2212
2213     /* Now what about a locking rect?  */
2214     hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0);
2215     ok(hr == DD_OK, "Lock returned %08x\n", hr);
2216
2217     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2218        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2219     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2220     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2221     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2222        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2223     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2224     ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2225
2226     hr = IDirectDrawSurface7_Unlock(surface, &r);
2227     ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2228
2229     /* Now what about a different locking offset? */
2230     hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0);
2231     ok(hr == DD_OK, "Lock returned %08x\n", hr);
2232
2233     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2234        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2235     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2236     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2237     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2238        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2239     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2240     ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2241
2242     hr = IDirectDrawSurface7_Unlock(surface, &r2);
2243     ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2244     IDirectDrawSurface7_Release(surface);
2245
2246     /* Try this with video memory. A kind of surprise. It still has the LINEARSIZE flag set,
2247      * but seems to have a pitch instead.
2248      */
2249     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
2250     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1');
2251
2252     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2253     ok(hr == DD_OK || hr == DDERR_NOTEXTUREHW || hr == DDERR_INVALIDPARAMS ||
2254        broken(hr == DDERR_NODIRECTDRAWHW), "CreateSurface returned %08x\n", hr);
2255
2256     /* Not supported everywhere */
2257     if(SUCCEEDED(hr))
2258     {
2259         memset(&ddsd2, 0, sizeof(ddsd2));
2260         ddsd2.dwSize = sizeof(ddsd2);
2261         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2262         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2263         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2264
2265         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2266         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2267         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2268         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2269         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2270         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2271         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2272         ok(ddsd2.ddsCaps.dwCaps2 == 0, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2);
2273         IDirectDrawSurface7_Release(surface);
2274
2275         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3');
2276         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2277         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2278
2279         memset(&ddsd2, 0, sizeof(ddsd2));
2280         ddsd2.dwSize = sizeof(ddsd2);
2281         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2282         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2283         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2284
2285         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2286         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2287         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2288         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2289         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2290         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2291         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2292         IDirectDrawSurface7_Release(surface);
2293
2294         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5');
2295         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2296         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2297
2298         memset(&ddsd2, 0, sizeof(ddsd2));
2299         ddsd2.dwSize = sizeof(ddsd2);
2300         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2301         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2302         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2303
2304         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2305         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2306         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2307         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2308         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2309         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2310         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2311         ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface);
2312
2313         memset(&ddsd2, 0, sizeof(ddsd2));
2314         ddsd2.dwSize = sizeof(ddsd2);
2315         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2316
2317         /* Show that the description is not changed when locking the surface. What is really interesting
2318         * about this is that DDSD_LPSURFACE isn't set.
2319         */
2320         hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0);
2321         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2322
2323         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2324         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2325         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2326         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2327         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2328         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2329         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2330         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2331
2332         hr = IDirectDrawSurface7_Unlock(surface, NULL);
2333         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2334
2335         /* Now what about a locking rect?  */
2336         hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0);
2337         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2338
2339         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2340         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2341         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2342         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2343         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2344         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2345         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2346         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2347
2348         hr = IDirectDrawSurface7_Unlock(surface, &r);
2349         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2350
2351         /* Now what about a different locking offset? */
2352         hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0);
2353         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2354
2355         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2356         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2357         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2358         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2359         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2360         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2361         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2362         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2363
2364         hr = IDirectDrawSurface7_Unlock(surface, &r2);
2365         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2366
2367         IDirectDrawSurface7_Release(surface);
2368     }
2369     else
2370     {
2371         skip("Hardware DXTN textures not supported\n");
2372     }
2373
2374     /* What happens to managed textures? Interestingly, Windows reports them as being in system
2375      * memory. The linear size fits again.
2376      */
2377     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2378     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
2379     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1');
2380
2381     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2382     ok(hr == DD_OK || hr == DDERR_NOTEXTUREHW, "CreateSurface returned %08x\n", hr);
2383
2384     /* Not supported everywhere */
2385     if(SUCCEEDED(hr))
2386     {
2387         memset(&ddsd2, 0, sizeof(ddsd2));
2388         ddsd2.dwSize = sizeof(ddsd2);
2389         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2390         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2391         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2392
2393         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2394         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2395         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2396         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2397         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2398         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2399         ok(U1(ddsd2).dwLinearSize == 8192, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2400         ok(ddsd2.ddsCaps.dwCaps2 == DDSCAPS2_TEXTUREMANAGE, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2);
2401         IDirectDrawSurface7_Release(surface);
2402
2403         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3');
2404         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2405         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2406
2407         memset(&ddsd2, 0, sizeof(ddsd2));
2408         ddsd2.dwSize = sizeof(ddsd2);
2409         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2410         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2411         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2412
2413         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2414         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2415         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2416         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2417         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2418         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2419         ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2420         IDirectDrawSurface7_Release(surface);
2421
2422         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5');
2423         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2424         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2425
2426         memset(&ddsd2, 0, sizeof(ddsd2));
2427         ddsd2.dwSize = sizeof(ddsd2);
2428         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2429         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2430         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2431
2432         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2433         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2434         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2435         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2436         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2437         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2438         ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2439         ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface);
2440
2441         memset(&ddsd2, 0, sizeof(ddsd2));
2442         ddsd2.dwSize = sizeof(ddsd2);
2443         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2444
2445         /* Show that the description is not changed when locking the surface. What is really interesting
2446         * about this is that DDSD_LPSURFACE isn't set.
2447         */
2448         hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0);
2449         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2450
2451         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2452         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2453         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2454         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2455         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2456         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2457         ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2458         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2459
2460         hr = IDirectDrawSurface7_Unlock(surface, NULL);
2461         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2462
2463         /* Now what about a locking rect?  */
2464         hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0);
2465         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2466
2467         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2468         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2469         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2470         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2471         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2472         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2473         ok(U1(ddsd2).dwLinearSize == 16384, "\"Linear\" size is %d\n", U1(ddsd2).dwLinearSize);
2474         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2475
2476         hr = IDirectDrawSurface7_Unlock(surface, &r);
2477         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2478
2479         /* Now what about a different locking offset? */
2480         hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0);
2481         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2482
2483         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2484         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2485         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2486         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2487         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2488         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2489         ok(U1(ddsd2).dwLinearSize == 16384, "\"Linear\" size is %d\n", U1(ddsd2).dwLinearSize);
2490         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2491
2492         hr = IDirectDrawSurface7_Unlock(surface, &r2);
2493         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2494
2495         IDirectDrawSurface7_Release(surface);
2496     }
2497     else
2498     {
2499         skip("Hardware DXTN textures not supported\n");
2500     }
2501
2502     IDirectDraw7_Release(dd7);
2503 }
2504
2505 static void SizeTest(void)
2506 {
2507     IDirectDrawSurface *dsurface = NULL;
2508     DDSURFACEDESC desc;
2509     HRESULT ret;
2510     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2511
2512     /* Create an offscreen surface surface without a size */
2513     ZeroMemory(&desc, sizeof(desc));
2514     desc.dwSize = sizeof(desc);
2515     desc.dwFlags = DDSD_CAPS;
2516     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2517     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2518     ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without a size info returned %08x (dsurface=%p)\n", ret, dsurface);
2519     if(dsurface)
2520     {
2521         trace("Surface at %p\n", dsurface);
2522         IDirectDrawSurface_Release(dsurface);
2523         dsurface = NULL;
2524     }
2525
2526     /* Create an offscreen surface surface with only a width parameter */
2527     ZeroMemory(&desc, sizeof(desc));
2528     desc.dwSize = sizeof(desc);
2529     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH;
2530     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2531     desc.dwWidth = 128;
2532     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2533     ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without height info returned %08x\n", ret);
2534     if(dsurface)
2535     {
2536         IDirectDrawSurface_Release(dsurface);
2537         dsurface = NULL;
2538     }
2539
2540     /* Create an offscreen surface surface with only a height parameter */
2541     ZeroMemory(&desc, sizeof(desc));
2542     desc.dwSize = sizeof(desc);
2543     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT;
2544     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2545     desc.dwHeight = 128;
2546     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2547     ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without width info returned %08x\n", ret);
2548     if(dsurface)
2549     {
2550         IDirectDrawSurface_Release(dsurface);
2551         dsurface = NULL;
2552     }
2553
2554     /* Test 0 height. */
2555     memset(&desc, 0, sizeof(desc));
2556     desc.dwSize = sizeof(desc);
2557     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2558     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
2559     desc.dwWidth = 1;
2560     desc.dwHeight = 0;
2561     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2562     ok(ret == DDERR_INVALIDPARAMS, "Creating a 0 height surface returned %#x, expected DDERR_INVALIDPARAMS.\n", ret);
2563     if (SUCCEEDED(ret)) IDirectDrawSurface_Release(dsurface);
2564     dsurface = NULL;
2565
2566     /* Test 0 width. */
2567     memset(&desc, 0, sizeof(desc));
2568     desc.dwSize = sizeof(desc);
2569     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2570     desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
2571     desc.dwWidth = 0;
2572     desc.dwHeight = 1;
2573     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2574     ok(ret == DDERR_INVALIDPARAMS, "Creating a 0 width surface returned %#x, expected DDERR_INVALIDPARAMS.\n", ret);
2575     if (SUCCEEDED(ret)) IDirectDrawSurface_Release(dsurface);
2576     dsurface = NULL;
2577
2578     /* Sanity check */
2579     ZeroMemory(&desc, sizeof(desc));
2580     desc.dwSize = sizeof(desc);
2581     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2582     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2583     desc.dwHeight = 128;
2584     desc.dwWidth = 128;
2585     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2586     ok(ret == DD_OK, "Creating an offscreen plain surface with width and height info returned %08x\n", ret);
2587     if(dsurface)
2588     {
2589         IDirectDrawSurface_Release(dsurface);
2590         dsurface = NULL;
2591     }
2592
2593     /* Test a primary surface size */
2594     ret = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_NORMAL);
2595     ok(ret == DD_OK, "SetCooperativeLevel failed with %08x\n", ret);
2596
2597     ZeroMemory(&desc, sizeof(desc));
2598     desc.dwSize = sizeof(desc);
2599     desc.dwFlags = DDSD_CAPS;
2600     desc.ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE;
2601     desc.dwHeight = 128; /* Keep them set to  check what happens */
2602     desc.dwWidth = 128; /* Keep them set to  check what happens */
2603     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2604     ok(ret == DD_OK, "Creating a primary surface without width and height info returned %08x\n", ret);
2605     if(dsurface)
2606     {
2607         ret = IDirectDrawSurface_GetSurfaceDesc(dsurface, &desc);
2608         ok(ret == DD_OK, "GetSurfaceDesc returned %x\n", ret);
2609
2610         IDirectDrawSurface_Release(dsurface);
2611         dsurface = NULL;
2612
2613         ok(desc.dwFlags & DDSD_WIDTH, "Primary surface doesn't have width set\n");
2614         ok(desc.dwFlags & DDSD_HEIGHT, "Primary surface doesn't have height set\n");
2615         ok(desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Surface width differs from screen width\n");
2616         ok(desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Surface height differs from screen height\n");
2617     }
2618     ret = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
2619     ok(ret == DD_OK, "SetCooperativeLevel failed with %08x\n", ret);
2620 }
2621
2622 static void PrivateDataTest(void)
2623 {
2624     HRESULT hr;
2625     IDirectDrawSurface7 *surface7 = NULL;
2626     IDirectDrawSurface *surface = NULL;
2627     DDSURFACEDESC desc;
2628     ULONG ref, ref2;
2629     IUnknown *ptr;
2630     DWORD size = sizeof(IUnknown *);
2631
2632     ZeroMemory(&desc, sizeof(desc));
2633     desc.dwSize = sizeof(desc);
2634     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2635     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2636     desc.dwHeight = 128;
2637     desc.dwWidth = 128;
2638     hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface, NULL);
2639     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2640     if(!surface)
2641     {
2642         return;
2643     }
2644     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **) &surface7);
2645     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed with %08x\n", hr);
2646     if(!surface7)
2647     {
2648         IDirectDrawSurface_Release(surface);
2649         return;
2650     }
2651
2652     /* This fails */
2653     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, 0, DDSPD_IUNKNOWNPOINTER);
2654     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2655     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, 5, DDSPD_IUNKNOWNPOINTER);
2656     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2657     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, sizeof(IUnknown *) * 2, DDSPD_IUNKNOWNPOINTER);
2658     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2659
2660     ref = getref((IUnknown *) lpDD);
2661     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2662     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2663     ref2 = getref((IUnknown *) lpDD);
2664     ok(ref2 == ref + 1, "Object reference is %d, expected %d\n", ref2, ref + 1);
2665     hr = IDirectDrawSurface7_FreePrivateData(surface7, &IID_IDirectDrawSurface7);
2666     ok(SUCCEEDED(hr), "IDirectDrawSurface7_FreePrivateData returned %#x.\n", hr);
2667     ref2 = getref((IUnknown *) lpDD);
2668     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
2669
2670     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7, lpDD, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2671     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2672     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7, surface7, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2673     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2674     ref2 = getref((IUnknown *) lpDD);
2675     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
2676
2677     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7, lpDD, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2678     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2679     hr = IDirectDrawSurface7_GetPrivateData(surface7, &IID_IDirectDrawSurface7, &ptr, &size);
2680     ok(hr == DD_OK, "IDirectDrawSurface7_GetPrivateData failed with %08x\n", hr);
2681     ref2 = getref((IUnknown *) lpDD);
2682     /* Object is NOT being addrefed */
2683     ok(ptr == (IUnknown *) lpDD, "Returned interface pointer is %p, expected %p\n", ptr, lpDD);
2684     ok(ref2 == ref + 1, "Object reference is %d, expected %d. ptr at %p, orig at %p\n", ref2, ref + 1, ptr, lpDD);
2685
2686     IDirectDrawSurface_Release(surface);
2687     IDirectDrawSurface7_Release(surface7);
2688
2689     /* Destroying the surface frees the held reference */
2690     ref2 = getref((IUnknown *) lpDD);
2691     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
2692 }
2693
2694 static void BltParamTest(void)
2695 {
2696     IDirectDrawSurface *surface1 = NULL, *surface2 = NULL;
2697     DDSURFACEDESC desc;
2698     HRESULT hr;
2699     DDBLTFX BltFx;
2700     RECT valid = {10, 10, 20, 20};
2701     RECT invalid1 = {20, 10, 10, 20};
2702     RECT invalid2 = {20, 20, 20, 20};
2703     RECT invalid3 = {-1, -1, 20, 20};
2704     RECT invalid4 = {60, 60, 70, 70};
2705
2706     memset(&desc, 0, sizeof(desc));
2707     desc.dwSize = sizeof(desc);
2708     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2709     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2710     desc.dwHeight = 128;
2711     desc.dwWidth = 128;
2712     hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface1, NULL);
2713     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2714
2715     desc.dwHeight = 64;
2716     desc.dwWidth = 64;
2717     hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface2, NULL);
2718     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2719
2720     if(0)
2721     {
2722         /* This crashes */
2723         hr = IDirectDrawSurface_BltFast(surface1, 0, 0, NULL, NULL, 0);
2724         ok(hr == DD_OK, "BltFast from NULL surface returned %08x\n", hr);
2725     }
2726     hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface2, NULL, 0);
2727     ok(hr == DD_OK, "BltFast from smaller to bigger surface returned %08x\n", hr);
2728     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, NULL, 0);
2729     ok(hr == DDERR_INVALIDRECT, "BltFast from bigger to smaller surface returned %08x\n", hr);
2730     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &valid, 0);
2731     ok(hr == DD_OK, "BltFast from bigger to smaller surface using a valid rectangle returned %08x\n", hr);
2732     hr = IDirectDrawSurface_BltFast(surface2, 60, 60, surface1, &valid, 0);
2733     ok(hr == DDERR_INVALIDRECT, "BltFast with a rectangle resulting in an off-surface write returned %08x\n", hr);
2734     hr = IDirectDrawSurface_BltFast(surface1, 90, 90, surface2, NULL, 0);
2735     ok(hr == DDERR_INVALIDRECT, "BltFast with a rectangle resulting in an off-surface write returned %08x\n", hr);
2736
2737     hr = IDirectDrawSurface_BltFast(surface1, -10, 0, surface2, NULL, 0);
2738     ok(hr == DDERR_INVALIDRECT, "BltFast with an offset resulting in an off-surface write returned %08x\n", hr);
2739     hr = IDirectDrawSurface_BltFast(surface1, 0, -10, surface2, NULL, 0);
2740     ok(hr == DDERR_INVALIDRECT, "BltFast with an offset resulting in an off-surface write returned %08x\n", hr);
2741     hr = IDirectDrawSurface_BltFast(surface2, 20, 20, surface1, &valid, 0);
2742     ok(hr == DD_OK, "BltFast from bigger to smaller surface using a valid rectangle and offset returned %08x\n", hr);
2743
2744     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid1, 0);
2745     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 1 returned %08x\n", hr);
2746     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid2, 0);
2747     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 2 returned %08x\n", hr);
2748     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid3, 0);
2749     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 3 returned %08x\n", hr);
2750     hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface2, &invalid4, 0);
2751     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 3 returned %08x\n", hr);
2752     hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface1, NULL, 0);
2753     ok(hr == DD_OK, "BltFast blitting a surface onto itself returned %08x\n", hr);
2754
2755     /* Blt(non-fast) tests */
2756     memset(&BltFx, 0, sizeof(BltFx));
2757     BltFx.dwSize = sizeof(BltFx);
2758     U5(BltFx).dwFillColor = 0xaabbccdd;
2759
2760     hr = IDirectDrawSurface_Blt(surface1, &valid, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2761     ok(hr == DD_OK, "IDirectDrawSurface_Blt with a valid rectangle for color fill returned %08x\n", hr);
2762     hr = IDirectDrawSurface_Blt(surface1, &valid, NULL, &invalid3, DDBLT_COLORFILL, &BltFx);
2763     ok(hr == DD_OK, "IDirectDrawSurface_Blt with a invalid, unused rectangle returned %08x\n", hr);
2764     hr = IDirectDrawSurface_Blt(surface2, &invalid1, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2765     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 1 returned %08x\n", hr);
2766     hr = IDirectDrawSurface_Blt(surface2, &invalid2, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2767     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 2 returned %08x\n", hr);
2768     hr = IDirectDrawSurface_Blt(surface2, &invalid3, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2769     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 3 returned %08x\n", hr);
2770     hr = IDirectDrawSurface_Blt(surface2, &invalid4, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2771     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 4 returned %08x\n", hr);
2772
2773     /* Valid on surface 1 */
2774     hr = IDirectDrawSurface_Blt(surface1, &invalid4, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2775     ok(hr == DD_OK, "IDirectDrawSurface_Blt with a subrectangle fill returned %08x\n", hr);
2776
2777     /* Works - stretched blit */
2778     hr = IDirectDrawSurface_Blt(surface1, NULL, surface2, NULL, 0, NULL);
2779     ok(hr == DD_OK, "IDirectDrawSurface_Blt from a smaller to a bigger surface returned %08x\n", hr);
2780     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, NULL, 0, NULL);
2781     ok(hr == DD_OK, "IDirectDrawSurface_Blt from a bigger to a smaller surface %08x\n", hr);
2782
2783     /* Invalid dest rects in sourced blits */
2784     hr = IDirectDrawSurface_Blt(surface2, &invalid1, surface1, NULL, 0, NULL);
2785     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 1 returned %08x\n", hr);
2786     hr = IDirectDrawSurface_Blt(surface2, &invalid2, surface1, NULL, 0, NULL);
2787     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 2 returned %08x\n", hr);
2788     hr = IDirectDrawSurface_Blt(surface2, &invalid3, surface1, NULL, 0, NULL);
2789     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 3 returned %08x\n", hr);
2790     hr = IDirectDrawSurface_Blt(surface2, &invalid4, surface1, NULL, 0, NULL);
2791     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 4 returned %08x\n", hr);
2792
2793     /* Invalid src rects */
2794     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, &invalid1, 0, NULL);
2795     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 1 returned %08x\n", hr);
2796     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, &invalid2, 0, NULL);
2797     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 2 returned %08x\n", hr);
2798     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, &invalid3, 0, NULL);
2799     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 3 returned %08x\n", hr);
2800     hr = IDirectDrawSurface_Blt(surface1, NULL, surface2, &invalid4, 0, NULL);
2801     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 4 returned %08x\n", hr);
2802
2803     IDirectDrawSurface_Release(surface1);
2804     IDirectDrawSurface_Release(surface2);
2805 }
2806
2807 static void PaletteTest(void)
2808 {
2809     HRESULT hr;
2810     IDirectDrawSurface *lpSurf = NULL;
2811     IDirectDrawSurface *backbuffer = NULL;
2812     DDSCAPS ddscaps;
2813     DDSURFACEDESC ddsd;
2814     IDirectDrawPalette *palette = NULL;
2815     PALETTEENTRY Table[256];
2816     PALETTEENTRY palEntries[256];
2817     int i;
2818
2819     for(i=0; i<256; i++)
2820     {
2821         Table[i].peRed   = 0xff;
2822         Table[i].peGreen = 0;
2823         Table[i].peBlue  = 0;
2824         Table[i].peFlags = 0;
2825     }
2826
2827     /* Create a 8bit palette without DDPCAPS_ALLOW256 set */
2828     hr = IDirectDraw_CreatePalette(lpDD, DDPCAPS_8BIT, Table, &palette, NULL);
2829     ok(hr == DD_OK, "CreatePalette failed with %08x\n", hr);
2830     if (FAILED(hr)) goto err;
2831     /* Read back the palette and verify the entries. Without DDPCAPS_ALLOW256 set
2832     /  entry 0 and 255 should have been overwritten with black and white */
2833     hr = IDirectDrawPalette_GetEntries(palette , 0, 0, 256, &palEntries[0]);
2834     ok(hr == DD_OK, "GetEntries failed with %08x\n", hr);
2835     if(hr == DD_OK)
2836     {
2837         ok((palEntries[0].peRed == 0) && (palEntries[0].peGreen == 0) && (palEntries[0].peBlue == 0),
2838            "Palette entry 0 of a palette without DDPCAPS_ALLOW256 set should be (0,0,0) but it is (%d,%d,%d)\n",
2839            palEntries[0].peRed, palEntries[0].peGreen, palEntries[0].peBlue);
2840         ok((palEntries[255].peRed == 255) && (palEntries[255].peGreen == 255) && (palEntries[255].peBlue == 255),
2841            "Palette entry 255 of a palette without DDPCAPS_ALLOW256 set should be (255,255,255) but it is (%d,%d,%d)\n",
2842            palEntries[255].peRed, palEntries[255].peGreen, palEntries[255].peBlue);
2843
2844         /* Entry 1-254 should contain red */
2845         for(i=1; i<255; i++)
2846             ok((palEntries[i].peRed == 255) && (palEntries[i].peGreen == 0) && (palEntries[i].peBlue == 0),
2847                "Palette entry %d should have contained (255,0,0) but was set to %d,%d,%d)\n",
2848                i, palEntries[i].peRed, palEntries[i].peGreen, palEntries[i].peBlue);
2849     }
2850
2851     /* CreatePalette without DDPCAPS_ALLOW256 ignores entry 0 and 255,
2852     /  now check we are able to update the entries afterwards. */
2853     hr = IDirectDrawPalette_SetEntries(palette , 0, 0, 256, &Table[0]);
2854     ok(hr == DD_OK, "SetEntries failed with %08x\n", hr);
2855     hr = IDirectDrawPalette_GetEntries(palette , 0, 0, 256, &palEntries[0]);
2856     ok(hr == DD_OK, "GetEntries failed with %08x\n", hr);
2857     if(hr == DD_OK)
2858     {
2859         ok((palEntries[0].peRed == 0) && (palEntries[0].peGreen == 0) && (palEntries[0].peBlue == 0),
2860            "Palette entry 0 should have been set to (0,0,0) but it contains (%d,%d,%d)\n",
2861            palEntries[0].peRed, palEntries[0].peGreen, palEntries[0].peBlue);
2862         ok((palEntries[255].peRed == 255) && (palEntries[255].peGreen == 255) && (palEntries[255].peBlue == 255),
2863            "Palette entry 255 should have been set to (255,255,255) but it contains (%d,%d,%d)\n",
2864            palEntries[255].peRed, palEntries[255].peGreen, palEntries[255].peBlue);
2865     }
2866     IDirectDrawPalette_Release(palette);
2867
2868     /* Create a 8bit palette with DDPCAPS_ALLOW256 set */
2869     hr = IDirectDraw_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL);
2870     ok(hr == DD_OK, "CreatePalette failed with %08x\n", hr);
2871     if (FAILED(hr)) goto err;
2872
2873     hr = IDirectDrawPalette_GetEntries(palette , 0, 0, 256, &palEntries[0]);
2874     ok(hr == DD_OK, "GetEntries failed with %08x\n", hr);
2875     if(hr == DD_OK)
2876     {
2877         /* All entries should contain red */
2878         for(i=0; i<256; i++)
2879             ok((palEntries[i].peRed == 255) && (palEntries[i].peGreen == 0) && (palEntries[i].peBlue == 0),
2880                "Palette entry %d should have contained (255,0,0) but was set to %d,%d,%d)\n",
2881                i, palEntries[i].peRed, palEntries[i].peGreen, palEntries[i].peBlue);
2882     }
2883
2884     /* Try to set palette to a non-palettized surface */
2885     ddsd.dwSize = sizeof(ddsd);
2886     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
2887     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2888     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
2889     ddsd.dwWidth = 800;
2890     ddsd.dwHeight = 600;
2891     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
2892     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
2893     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
2894     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
2895     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
2896     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSurf, NULL);
2897     ok(hr==DD_OK, "CreateSurface returned: %x\n",hr);
2898     if (FAILED(hr))
2899     {
2900         skip("failed to create surface\n");
2901         goto err;
2902     }
2903
2904     hr = IDirectDrawSurface_SetPalette(lpSurf, palette);
2905     ok(hr == DDERR_INVALIDPIXELFORMAT, "CreateSurface returned: %x\n",hr);
2906
2907     IDirectDrawPalette_Release(palette);
2908     palette = NULL;
2909
2910     hr = IDirectDrawSurface_GetPalette(lpSurf, &palette);
2911     ok(hr == DDERR_NOPALETTEATTACHED, "CreateSurface returned: %x\n",hr);
2912
2913     err:
2914
2915     if (lpSurf) IDirectDrawSurface_Release(lpSurf);
2916     if (palette) IDirectDrawPalette_Release(palette);
2917
2918     hr = IDirectDraw_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL);
2919     ok(hr == DD_OK, "CreatePalette failed with %08x\n", hr);
2920
2921     ddsd.dwSize = sizeof(ddsd);
2922     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
2923     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_BACKBUFFERCOUNT;
2924     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
2925     ddsd.dwWidth = 64;
2926     ddsd.dwHeight = 64;
2927     ddsd.dwBackBufferCount = 1;
2928     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2929     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 8;
2930
2931     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSurf, NULL);
2932     ok(hr==DD_OK, "CreateSurface returned: %x\n",hr);
2933     if (FAILED(hr))
2934     {
2935         skip("failed to create surface\n");
2936         return;
2937     }
2938
2939     ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
2940     hr = IDirectDrawSurface_GetAttachedSurface(lpSurf, &ddscaps, &backbuffer);
2941     ok(hr == DD_OK, "GetAttachedSurface returned: %x\n",hr);
2942
2943     hr = IDirectDrawSurface_SetPalette(backbuffer, palette);
2944     ok(hr == DD_OK, "SetPalette returned: %x\n",hr);
2945
2946     IDirectDrawPalette_Release(palette);
2947     palette = NULL;
2948
2949     hr = IDirectDrawSurface_GetPalette(backbuffer, &palette);
2950     ok(hr == DD_OK, "CreateSurface returned: %x\n",hr);
2951
2952     IDirectDrawSurface_Release(backbuffer);
2953     IDirectDrawSurface_Release(lpSurf);
2954 }
2955
2956 static void StructSizeTest(void)
2957 {
2958     IDirectDrawSurface *surface1;
2959     IDirectDrawSurface7 *surface7;
2960     union {
2961         DDSURFACEDESC desc1;
2962         DDSURFACEDESC2 desc2;
2963         char blob[1024]; /* To get a bunch of writable memory */
2964     } desc;
2965     DDSURFACEDESC create;
2966     HRESULT hr;
2967
2968     memset(&desc, 0, sizeof(desc));
2969     memset(&create, 0, sizeof(create));
2970
2971     memset(&create, 0, sizeof(create));
2972     create.dwSize = sizeof(create);
2973     create.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2974     create.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2975     create.dwHeight = 128;
2976     create.dwWidth = 128;
2977     hr = IDirectDraw_CreateSurface(lpDD, &create, &surface1, NULL);
2978     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2979     hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface7, (void **) &surface7);
2980     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed with %08x\n", hr);
2981
2982     desc.desc1.dwSize = sizeof(DDSURFACEDESC);
2983     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
2984     ok(hr == DD_OK, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
2985     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
2986     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
2987
2988     desc.desc2.dwSize = sizeof(DDSURFACEDESC2);
2989     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
2990     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
2991     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
2992     ok(hr == DD_OK, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
2993
2994     desc.desc2.dwSize = 0;
2995     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
2996     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size 0 returned %08x\n", hr);
2997     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
2998     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size 0 returned %08x\n", hr);
2999
3000     desc.desc1.dwSize = sizeof(DDSURFACEDESC) + 1;
3001     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
3002     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
3003     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
3004     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
3005
3006     desc.desc2.dwSize = sizeof(DDSURFACEDESC2) + 1;
3007     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
3008     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
3009     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
3010     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
3011
3012     /* Tests for Lock() */
3013
3014     desc.desc1.dwSize = sizeof(DDSURFACEDESC);
3015     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
3016     ok(hr == DD_OK, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
3017     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
3018     ok(desc.desc1.dwSize == sizeof(DDSURFACEDESC), "Destination size was changed to %d\n", desc.desc1.dwSize);
3019     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
3020     ok(hr == DD_OK, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
3021     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
3022     ok(desc.desc2.dwSize == sizeof(DDSURFACEDESC), "Destination size was changed to %d\n", desc.desc1.dwSize);
3023
3024     desc.desc2.dwSize = sizeof(DDSURFACEDESC2);
3025     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
3026     ok(hr == DD_OK, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
3027     ok(desc.desc1.dwSize == sizeof(DDSURFACEDESC2), "Destination size was changed to %d\n", desc.desc1.dwSize);
3028     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
3029     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
3030     ok(hr == DD_OK, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
3031     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
3032     ok(desc.desc2.dwSize == sizeof(DDSURFACEDESC2), "Destination size was changed to %d\n", desc.desc1.dwSize);
3033
3034     desc.desc2.dwSize = 0;
3035     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
3036     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Lock with desc size 0 returned %08x\n", hr);
3037     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
3038     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
3039     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_Lock with desc size 0 returned %08x\n", hr);
3040     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
3041
3042     desc.desc1.dwSize = sizeof(DDSURFACEDESC) + 1;
3043     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
3044     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
3045     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
3046     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
3047     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
3048     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
3049
3050     desc.desc2.dwSize = sizeof(DDSURFACEDESC2) + 1;
3051     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
3052     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
3053     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
3054     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
3055     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
3056     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
3057
3058     IDirectDrawSurface7_Release(surface7);
3059     IDirectDrawSurface_Release(surface1);
3060 }
3061
3062 static void SurfaceCapsTest(void)
3063 {
3064     DDSURFACEDESC create;
3065     DDSURFACEDESC desc;
3066     HRESULT hr;
3067     IDirectDrawSurface *surface1 = NULL;
3068     DDSURFACEDESC2 create2, desc2;
3069     IDirectDrawSurface7 *surface7 = NULL;
3070     IDirectDraw7 *dd7 = NULL;
3071     DWORD create_caps[] = {
3072         DDSCAPS_OFFSCREENPLAIN,
3073         DDSCAPS_TEXTURE,
3074         DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
3075         0,
3076         DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD | DDSCAPS_SYSTEMMEMORY,
3077         DDSCAPS_PRIMARYSURFACE,
3078         DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY,
3079         DDSCAPS_3DDEVICE,
3080         DDSCAPS_ZBUFFER,
3081         DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN
3082     };
3083     DWORD expected_caps[] = {
3084         DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3085         DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3086         DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_ALLOCONLOAD,
3087         DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3088         DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD | DDSCAPS_SYSTEMMEMORY,
3089         DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_VISIBLE,
3090         DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_VISIBLE,
3091         DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
3092         DDSCAPS_ZBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY,
3093         DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM
3094     };
3095     UINT i;
3096
3097     /* Tests various surface flags, what changes do they undergo during surface creation. Forsaken
3098      * engine expects texture surfaces without memory flag to get a video memory flag right after
3099      * creation. Currently, Wine adds DDSCAPS_FRONTBUFFER to primary surface, but native doesn't do this
3100      * for single buffered primaries. Because of this primary surface creation tests are todo_wine. No real
3101      * app is known so far to care about this. */
3102
3103     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3104     {
3105         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3106         return ;
3107     }
3108
3109     for (i = 0; i < sizeof(create_caps) / sizeof(DWORD); i++)
3110     {
3111         memset(&create, 0, sizeof(create));
3112         create.dwSize = sizeof(create);
3113         create.ddsCaps.dwCaps = create_caps[i];
3114         create.dwFlags = DDSD_CAPS;
3115
3116         if (!(create.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
3117         {
3118             create.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH;
3119             create.dwHeight = 128;
3120             create.dwWidth = 128;
3121         }
3122
3123         if (create.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
3124         {
3125             create.dwFlags |= DDSD_PIXELFORMAT;
3126             create.ddpfPixelFormat.dwSize = sizeof(create.ddpfPixelFormat);
3127             create.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3128             U1(create.ddpfPixelFormat).dwZBufferBitDepth = 16;
3129             U3(create.ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3130         }
3131
3132         hr = IDirectDraw_CreateSurface(lpDD, &create, &surface1, NULL);
3133         ok(hr == DD_OK, "IDirectDraw_CreateSurface failed with %08x\n", hr);
3134
3135         if (SUCCEEDED(hr))
3136         {
3137             memset(&desc, 0, sizeof(desc));
3138             desc.dwSize = sizeof(DDSURFACEDESC);
3139             hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc);
3140             ok(hr == DD_OK, "IDirectDrawSurface_GetSurfaceDesc failed with %08x\n", hr);
3141
3142             if (!(create_caps[i] & DDSCAPS_PRIMARYSURFACE))
3143                 ok(desc.ddsCaps.dwCaps == expected_caps[i],
3144                     "GetSurfaceDesc test %d returned caps %x, expected %x\n", i,
3145                     desc.ddsCaps.dwCaps, expected_caps[i]);
3146             else
3147                 todo_wine ok(desc.ddsCaps.dwCaps == expected_caps[i],
3148                                 "GetSurfaceDesc test %d returned caps %x, expected %x\n", i,
3149                                 desc.ddsCaps.dwCaps, expected_caps[i]);
3150
3151             IDirectDrawSurface_Release(surface1);
3152         }
3153     }
3154
3155     /* Test for differences in ddraw 7 */
3156     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3157     ok(hr == DD_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
3158     if (FAILED(hr))
3159     {
3160         skip("Failed to get IDirectDraw7 interface, skipping tests\n");
3161     }
3162     else
3163     {
3164         for (i = 0; i < sizeof(create_caps) / sizeof(DWORD); i++)
3165         {
3166             memset(&create2, 0, sizeof(create2));
3167             create2.dwSize = sizeof(create2);
3168             create2.ddsCaps.dwCaps = create_caps[i];
3169             create2.dwFlags = DDSD_CAPS;
3170
3171             if (!(create2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
3172             {
3173                 create2.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH;
3174                 create2.dwHeight = 128;
3175                 create2.dwWidth = 128;
3176             }
3177
3178             if (create2.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
3179             {
3180                 create2.dwFlags |= DDSD_PIXELFORMAT;
3181                 U4(create2).ddpfPixelFormat.dwSize = sizeof(U4(create2).ddpfPixelFormat);
3182                 U4(create2).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
3183                 U1(U4(create2).ddpfPixelFormat).dwZBufferBitDepth = 16;
3184                 U3(U4(create2).ddpfPixelFormat).dwZBitMask = 0x0000FFFF;
3185             }
3186
3187             hr = IDirectDraw7_CreateSurface(dd7, &create2, &surface7, NULL);
3188             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3189
3190             if (SUCCEEDED(hr))
3191             {
3192                 memset(&desc2, 0, sizeof(desc2));
3193                 desc2.dwSize = sizeof(DDSURFACEDESC2);
3194                 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc2);
3195                 ok(hr == DD_OK, "IDirectDrawSurface_GetSurfaceDesc failed with %08x\n", hr);
3196
3197                 if (!(create_caps[i] & DDSCAPS_PRIMARYSURFACE))
3198                     ok(desc2.ddsCaps.dwCaps == expected_caps[i],
3199                         "GetSurfaceDesc test %d returned caps %x, expected %x\n", i,
3200                         desc2.ddsCaps.dwCaps, expected_caps[i]);
3201                 else
3202                     todo_wine ok(desc2.ddsCaps.dwCaps == expected_caps[i],
3203                                     "GetSurfaceDesc test %d returned caps %x, expected %x\n", i,
3204                                     desc2.ddsCaps.dwCaps, expected_caps[i]);
3205
3206                 IDirectDrawSurface7_Release(surface7);
3207             }
3208         }
3209
3210         IDirectDraw7_Release(dd7);
3211     }
3212
3213     memset(&create, 0, sizeof(create));
3214     create.dwSize = sizeof(create);
3215     create.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3216     create.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY;
3217     create.dwWidth = 64;
3218     create.dwHeight = 64;
3219     hr = IDirectDraw_CreateSurface(lpDD, &create, &surface1, NULL);
3220     ok(hr == DDERR_INVALIDCAPS, "Creating a SYSMEM | VIDMEM surface returned 0x%08x, expected DDERR_INVALIDCAPS\n", hr);
3221     if(surface1) IDirectDrawSurface_Release(surface1);
3222 }
3223
3224 static BOOL can_create_primary_surface(void)
3225 {
3226     DDSURFACEDESC ddsd;
3227     IDirectDrawSurface *surface;
3228     HRESULT hr;
3229
3230     memset(&ddsd, 0, sizeof(ddsd));
3231     ddsd.dwSize = sizeof(ddsd);
3232     ddsd.dwFlags = DDSD_CAPS;
3233     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3234     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
3235     if(FAILED(hr)) return FALSE;
3236     IDirectDrawSurface_Release(surface);
3237     return TRUE;
3238 }
3239
3240 static void dctest_surf(IDirectDrawSurface *surf, int ddsdver) {
3241     HRESULT hr;
3242     HDC dc, dc2 = (HDC) 0x1234;
3243     DDSURFACEDESC ddsd;
3244     DDSURFACEDESC2 ddsd2;
3245
3246     memset(&ddsd, 0, sizeof(ddsd));
3247     ddsd.dwSize = sizeof(ddsd);
3248     memset(&ddsd2, 0, sizeof(ddsd2));
3249     ddsd2.dwSize = sizeof(ddsd2);
3250
3251     hr = IDirectDrawSurface_GetDC(surf, &dc);
3252     ok(hr == DD_OK, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
3253
3254     hr = IDirectDrawSurface_GetDC(surf, &dc2);
3255     ok(hr == DDERR_DCALREADYCREATED, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
3256     ok(dc2 == (HDC) 0x1234, "The failed GetDC call changed the dc: %p\n", dc2);
3257
3258     hr = IDirectDrawSurface_Lock(surf, NULL, ddsdver == 1 ? &ddsd : ((DDSURFACEDESC *) &ddsd2), 0, NULL);
3259     ok(hr == DDERR_SURFACEBUSY, "IDirectDrawSurface_Lock returned 0x%08x, expected DDERR_ALREADYLOCKED\n", hr);
3260
3261     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
3262     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
3263     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
3264     ok(hr == DDERR_NODC, "IDirectDrawSurface_ReleaseDC returned 0x%08x, expected DDERR_NODC\n", hr);
3265 }
3266
3267 static void GetDCTest(void)
3268 {
3269     DDSURFACEDESC ddsd;
3270     DDSURFACEDESC2 ddsd2;
3271     IDirectDrawSurface *surf;
3272     IDirectDrawSurface2 *surf2;
3273     IDirectDrawSurface4 *surf4;
3274     IDirectDrawSurface7 *surf7;
3275     IDirectDrawSurface *tmp;
3276     IDirectDrawSurface7 *tmp7;
3277     HRESULT hr;
3278     IDirectDraw2 *dd2;
3279     IDirectDraw4 *dd4;
3280     IDirectDraw7 *dd7;
3281     HDC dc;
3282     ULONG ref;
3283
3284     memset(&ddsd, 0, sizeof(ddsd));
3285     ddsd.dwSize = sizeof(ddsd);
3286     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3287     ddsd.dwWidth = 64;
3288     ddsd.dwHeight = 64;
3289     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3290     memset(&ddsd2, 0, sizeof(ddsd2));
3291     ddsd2.dwSize = sizeof(ddsd2);
3292     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3293     ddsd2.dwWidth = 64;
3294     ddsd2.dwHeight = 64;
3295     ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3296
3297     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surf, NULL);
3298     ok(hr == DD_OK, "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3299     dctest_surf(surf, 1);
3300     IDirectDrawSurface_Release(surf);
3301
3302     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
3303     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3304
3305     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3306     ok(hr == DD_OK, "IDirectDraw2_CreateSurface failed: 0x%08x\n", hr);
3307     dctest_surf(surf, 1);
3308
3309     hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2);
3310     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed: 0x%08x\n", hr);
3311     dctest_surf((IDirectDrawSurface *) surf2, 1);
3312
3313     IDirectDrawSurface2_Release(surf2);
3314     IDirectDrawSurface_Release(surf);
3315     IDirectDraw2_Release(dd2);
3316
3317     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
3318     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3319
3320     surf = NULL;
3321     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3322     ok(hr == DD_OK, "IDirectDraw4_CreateSurface failed: 0x%08x\n", hr);
3323     dctest_surf((IDirectDrawSurface *) surf4, 2);
3324
3325     hr = IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **)&surf);
3326     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3327
3328     ref = getRefcount((IUnknown *) surf);
3329     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
3330     ref = getRefcount((IUnknown *) surf4);
3331     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
3332
3333     hr = IDirectDrawSurface4_GetDC(surf4, &dc);
3334     ok(SUCCEEDED(hr), "GetDC failed, hr %#x.\n", hr);
3335
3336     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, NULL);
3337     ok(hr == E_INVALIDARG, "Expected hr E_INVALIDARG, got %#x.\n", hr);
3338
3339     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, (IDirectDrawSurface4 **)&tmp);
3340     ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
3341     ok(tmp == surf, "Expected surface %p, got %p.\n\n", surf, tmp);
3342
3343     ref = getRefcount((IUnknown *) surf);
3344     ok(ref == 2, "Refcount is %u, expected 2\n", ref);
3345     ref = getRefcount((IUnknown *) tmp);
3346     ok(ref == 2, "Refcount is %u, expected 2\n", ref);
3347     ref = getRefcount((IUnknown *) surf4);
3348     ok(ref == 1, "Refcount is %u, expected 1\n", ref);
3349
3350     hr = IDirectDrawSurface4_ReleaseDC(surf4, dc);
3351     ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
3352
3353     IDirectDrawSurface_Release(tmp);
3354
3355     dc = CreateCompatibleDC(NULL);
3356     ok(!!dc, "CreateCompatibleDC failed.\n");
3357
3358     tmp = (IDirectDrawSurface *)0xdeadbeef;
3359     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, (IDirectDrawSurface4 **)&tmp);
3360     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3361     ok(!tmp, "Expected surface NULL, got %p.\n", tmp);
3362
3363     ok(DeleteDC(dc), "DeleteDC failed.\n");
3364
3365     tmp = (IDirectDrawSurface *)0xdeadbeef;
3366     hr = IDirectDraw4_GetSurfaceFromDC(dd4, NULL, (IDirectDrawSurface4 **)&tmp);
3367     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3368     ok(!tmp, "Expected surface NULL, got %p.\n", tmp);
3369
3370     IDirectDrawSurface4_Release(surf4);
3371     IDirectDrawSurface_Release(surf);
3372     IDirectDraw4_Release(dd4);
3373
3374     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3375     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3376
3377     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3378     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed: 0x%08x\n", hr);
3379     dctest_surf((IDirectDrawSurface *) surf7, 2);
3380
3381     hr = IDirectDrawSurface7_GetDC(surf7, &dc);
3382     ok(SUCCEEDED(hr), "GetDC failed, hr %#x.\n", hr);
3383
3384     hr = IDirectDraw7_GetSurfaceFromDC(dd7, dc, NULL);
3385     ok(hr == E_INVALIDARG, "Expected hr E_INVALIDARG, got %#x.\n", hr);
3386
3387     hr = IDirectDraw7_GetSurfaceFromDC(dd7, dc, &tmp7);
3388     ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
3389     ok(tmp7 == surf7, "Expected surface %p, got %p.\n\n", surf7, tmp7);
3390     IDirectDrawSurface7_Release(tmp7);
3391
3392     hr = IDirectDrawSurface7_ReleaseDC(surf7, dc);
3393     ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
3394
3395     dc = CreateCompatibleDC(NULL);
3396     ok(!!dc, "CreateCompatibleDC failed.\n");
3397
3398     tmp7 = (IDirectDrawSurface7 *)0xdeadbeef;
3399     hr = IDirectDraw7_GetSurfaceFromDC(dd7, dc, &tmp7);
3400     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3401     ok(!tmp7, "Expected surface NULL, got %p.\n", tmp7);
3402
3403     ok(DeleteDC(dc), "DeleteDC failed.\n");
3404
3405     tmp7 = (IDirectDrawSurface7 *)0xdeadbeef;
3406     hr = IDirectDraw7_GetSurfaceFromDC(dd7, NULL, (IDirectDrawSurface7 **)&tmp7);
3407     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3408     ok(!tmp7, "Expected surface NULL, got %p.\n", tmp7);
3409
3410     IDirectDrawSurface7_Release(surf7);
3411     IDirectDraw7_Release(dd7);
3412 }
3413
3414 static void GetDCFormatTest(void)
3415 {
3416     DDSURFACEDESC2 ddsd;
3417     unsigned int i;
3418     IDirectDrawSurface7 *surface;
3419     IDirectDraw7 *dd7;
3420     HRESULT hr;
3421     HDC dc;
3422
3423     struct
3424     {
3425         const char *name;
3426         DDPIXELFORMAT fmt;
3427         BOOL getdc_capable;
3428         HRESULT alt_result;
3429     } testdata[] = {
3430         {
3431             "D3DFMT_A8R8G8B8",
3432             {
3433                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3434                 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3435             },
3436             TRUE
3437         },
3438         {
3439             "D3DFMT_X8R8G8B8",
3440             {
3441                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3442                 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
3443             },
3444             TRUE
3445         },
3446         {
3447             "D3DFMT_X8B8G8R8",
3448             {
3449                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3450                 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
3451             },
3452             TRUE,
3453             DDERR_CANTCREATEDC /* Vista+ */
3454         },
3455         {
3456             "D3DFMT_X8B8G8R8",
3457             {
3458                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3459                        {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}
3460             },
3461             TRUE,
3462             DDERR_CANTCREATEDC /* Vista+ */
3463         },
3464         {
3465             "D3DFMT_A4R4G4B4",
3466             {
3467                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3468                        {16}, {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}
3469             },
3470             TRUE,
3471             DDERR_CANTCREATEDC /* Vista+ */
3472         },
3473         {
3474             "D3DFMT_X4R4G4B4",
3475             {
3476                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3477                        {16}, {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}
3478             },
3479             TRUE,
3480             DDERR_CANTCREATEDC /* Vista+ */
3481         },
3482         {
3483             "D3DFMT_R5G6B5",
3484             {
3485                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3486                        {16}, {0x0000F800}, {0x000007E0}, {0x0000001F}, {0x00000000}
3487             },
3488             TRUE
3489         },
3490         {
3491             "D3DFMT_A1R5G5B5",
3492             {
3493                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3494                        {16}, {0x00007C00}, {0x000003E0}, {0x0000001F}, {0x00008000}
3495             },
3496             TRUE
3497         },
3498         {
3499             "D3DFMT_X1R5G5B5",
3500             {
3501                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3502                        {16}, {0x00007C00}, {0x000003E0}, {0x0000001F}, {0x00000000}
3503             },
3504             TRUE
3505         },
3506         {
3507             "D3DFMT_R3G3B2",
3508             {
3509                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3510                        { 8}, {0x000000E0}, {0x0000001C}, {0x00000003}, {0x00000000}
3511             },
3512             FALSE
3513         },
3514         {
3515             /* Untested, windows test machine didn't support this format */
3516             "D3DFMT_A2R10G10B10",
3517             {
3518                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3519                        {32}, {0xC0000000}, {0x3FF00000}, {0x000FFC00}, {0x000003FF}
3520             },
3521             TRUE
3522         },
3523         /*
3524          * GetDC on a P8 surface fails unless the display mode is 8 bpp. This is not
3525          * implemented in wine yet, so disable the test for now. Succeeding P8 getDC
3526          * calls are tested in the ddraw.visual test.
3527          *
3528         {
3529             "D3DFMT_P8",
3530             {
3531                 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3532                 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3533             },
3534             FALSE
3535         },
3536          */
3537         {
3538             "D3DFMT_L8",
3539             {
3540                 sizeof(DDPIXELFORMAT), DDPF_LUMINANCE, 0,
3541                 {8 }, {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}
3542             },
3543             FALSE
3544         },
3545         {
3546             "D3DFMT_A8L8",
3547             {
3548                 sizeof(DDPIXELFORMAT), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0,
3549                 {16}, {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}
3550             },
3551             FALSE
3552         },
3553         {
3554             "D3DFMT_DXT1",
3555             {
3556                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'),
3557                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3558             },
3559             FALSE
3560         },
3561         {
3562             "D3DFMT_DXT2",
3563             {
3564                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'),
3565                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3566             },
3567             FALSE
3568         },
3569         {
3570             "D3DFMT_DXT3",
3571             {
3572                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'),
3573                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3574             },
3575             FALSE
3576         },
3577         {
3578             "D3DFMT_DXT4",
3579             {
3580                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'),
3581                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3582             },
3583             FALSE
3584         },
3585         {
3586             "D3DFMT_DXT5",
3587             {
3588                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'),
3589                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3590             },
3591             FALSE
3592         },
3593     };
3594
3595     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3596     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed, hr = 0x%08x\n", hr);
3597
3598     for(i = 0; i < (sizeof(testdata) / sizeof(testdata[0])); i++)
3599     {
3600         memset(&ddsd, 0, sizeof(ddsd));
3601         ddsd.dwSize = sizeof(ddsd);
3602         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3603         ddsd.dwWidth = 64;
3604         ddsd.dwHeight = 64;
3605         U4(ddsd).ddpfPixelFormat = testdata[i].fmt;
3606         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3607
3608         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
3609         if(FAILED(hr))
3610         {
3611             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
3612             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
3613             hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
3614             if(FAILED(hr))
3615             {
3616                 skip("IDirectDraw7_CreateSurface failed, hr = 0x%08x, format %s\n", hr, testdata[i].name);
3617                 continue;
3618             }
3619         }
3620
3621         dc = (void *) 0x1234;
3622         hr = IDirectDrawSurface7_GetDC(surface, &dc);
3623         if(testdata[i].getdc_capable)
3624         {
3625             ok(SUCCEEDED(hr) ||
3626                (testdata[i].alt_result && hr == testdata[i].alt_result),
3627                "GetDC on a %s surface failed(0x%08x), expected it to work\n",
3628                testdata[i].name, hr);
3629         }
3630         else
3631         {
3632             ok(FAILED(hr), "GetDC on a %s surface succeeded(0x%08x), expected it to fail\n",
3633                testdata[i].name, hr);
3634         }
3635
3636         if(SUCCEEDED(hr))
3637         {
3638             hr = IDirectDrawSurface7_ReleaseDC(surface, dc);
3639             ok(hr == DD_OK, "IDirectDrawSurface7_ReleaseDC failed, hr = 0x%08x\n", hr);
3640             dc = 0;
3641         }
3642         else
3643         {
3644             ok(dc == NULL, "After failed GetDC dc is %p\n", dc);
3645         }
3646
3647         IDirectDrawSurface7_Release(surface);
3648     }
3649
3650     IDirectDraw7_Release(dd7);
3651 }
3652
3653 static void BackBufferCreateSurfaceTest(void)
3654 {
3655     DDSURFACEDESC ddsd;
3656     DDSURFACEDESC created_ddsd;
3657     DDSURFACEDESC2 ddsd2;
3658     IDirectDrawSurface *surf;
3659     IDirectDrawSurface4 *surf4;
3660     IDirectDrawSurface7 *surf7;
3661     HRESULT hr;
3662     IDirectDraw2 *dd2;
3663     IDirectDraw4 *dd4;
3664     IDirectDraw7 *dd7;
3665
3666     const DWORD caps = DDSCAPS_BACKBUFFER;
3667     const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3668
3669     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3670     {
3671         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3672         return ;
3673     }
3674
3675     memset(&ddsd, 0, sizeof(ddsd));
3676     ddsd.dwSize = sizeof(ddsd);
3677     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3678     ddsd.dwWidth = 64;
3679     ddsd.dwHeight = 64;
3680     ddsd.ddsCaps.dwCaps = caps;
3681     memset(&ddsd2, 0, sizeof(ddsd2));
3682     ddsd2.dwSize = sizeof(ddsd2);
3683     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3684     ddsd2.dwWidth = 64;
3685     ddsd2.dwHeight = 64;
3686     ddsd2.ddsCaps.dwCaps = caps;
3687     memset(&created_ddsd, 0, sizeof(created_ddsd));
3688     created_ddsd.dwSize = sizeof(DDSURFACEDESC);
3689
3690     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surf, NULL);
3691     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3692     if (surf != NULL)
3693     {
3694         hr = IDirectDrawSurface_GetSurfaceDesc(surf, &created_ddsd);
3695         ok(SUCCEEDED(hr), "IDirectDraw_GetSurfaceDesc failed: 0x%08x\n", hr);
3696         ok(created_ddsd.ddsCaps.dwCaps == expected_caps,
3697            "GetSurfaceDesc returned caps %x, expected %x\n", created_ddsd.ddsCaps.dwCaps,
3698            expected_caps);
3699         IDirectDrawSurface_Release(surf);
3700     }
3701
3702     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
3703     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3704
3705     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3706     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw2_CreateSurface didn't return %x08x, but %x08x\n",
3707        DDERR_INVALIDCAPS, hr);
3708
3709     IDirectDraw2_Release(dd2);
3710
3711     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
3712     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3713
3714     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3715     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw4_CreateSurface didn't return %x08x, but %x08x\n",
3716        DDERR_INVALIDCAPS, hr);
3717
3718     IDirectDraw4_Release(dd4);
3719
3720     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3721     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3722
3723     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3724     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7_CreateSurface didn't return %x08x, but %x08x\n",
3725        DDERR_INVALIDCAPS, hr);
3726
3727     IDirectDraw7_Release(dd7);
3728 }
3729
3730 static void BackBufferAttachmentFlipTest(void)
3731 {
3732     HRESULT hr;
3733     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
3734     DDSURFACEDESC ddsd;
3735     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
3736
3737     hr = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3738     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3739
3740     /* Perform attachment tests on a back-buffer */
3741     memset(&ddsd, 0, sizeof(ddsd));
3742     ddsd.dwSize = sizeof(ddsd);
3743     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3744     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
3745     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3746     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3747     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL);
3748     ok(SUCCEEDED(hr), "CreateSurface returned: %x\n",hr);
3749
3750     if (surface2 != NULL)
3751     {
3752         /* Try a single primary and a two back buffers */
3753         memset(&ddsd, 0, sizeof(ddsd));
3754         ddsd.dwSize = sizeof(ddsd);
3755         ddsd.dwFlags = DDSD_CAPS;
3756         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3757         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL);
3758         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3759
3760         memset(&ddsd, 0, sizeof(ddsd));
3761         ddsd.dwSize = sizeof(ddsd);
3762         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3763         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
3764         ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3765         ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3766         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface3, NULL);
3767         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3768
3769         /* This one has a different size */
3770         memset(&ddsd, 0, sizeof(ddsd));
3771         ddsd.dwSize = sizeof(ddsd);
3772         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3773         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
3774         ddsd.dwWidth = 128;
3775         ddsd.dwHeight = 128;
3776         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL);
3777         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3778
3779         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
3780         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3781            "Attaching a back buffer to a front buffer returned %08x\n", hr);
3782         if(SUCCEEDED(hr))
3783         {
3784             /* Try flipping the surfaces */
3785             hr = IDirectDrawSurface_Flip(surface1, NULL, DDFLIP_WAIT);
3786             todo_wine ok(hr == DD_OK, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3787             hr = IDirectDrawSurface_Flip(surface2, NULL, DDFLIP_WAIT);
3788             todo_wine ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3789
3790             /* Try the reverse without detaching first */
3791             hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3792             ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
3793             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3794             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3795         }
3796         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3797         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3798            "Attaching a front buffer to a back buffer returned %08x\n", hr);
3799         if(SUCCEEDED(hr))
3800         {
3801             /* Try flipping the surfaces */
3802             hr = IDirectDrawSurface_Flip(surface1, NULL, DDFLIP_WAIT);
3803             todo_wine ok(hr == DD_OK, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3804             hr = IDirectDrawSurface_Flip(surface2, NULL, DDFLIP_WAIT);
3805             todo_wine ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3806
3807             /* Try to detach reversed */
3808             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3809             ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
3810             /* Now the proper detach */
3811             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
3812             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3813         }
3814         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
3815         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3816            "Attaching a back buffer to another back buffer returned %08x\n", hr);
3817         if(SUCCEEDED(hr))
3818         {
3819             /* Try flipping the surfaces */
3820             hr = IDirectDrawSurface_Flip(surface3, NULL, DDFLIP_WAIT);
3821             todo_wine ok(hr == DD_OK, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3822             hr = IDirectDrawSurface_Flip(surface2, NULL, DDFLIP_WAIT);
3823             todo_wine ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3824             hr = IDirectDrawSurface_Flip(surface1, NULL, DDFLIP_WAIT);
3825             ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3826
3827             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
3828             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3829         }
3830         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
3831         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a back buffer to a front buffer of different size returned %08x\n", hr);
3832         hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
3833         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to a back buffer of different size returned %08x\n", hr);
3834
3835         IDirectDrawSurface_Release(surface4);
3836         IDirectDrawSurface_Release(surface3);
3837         IDirectDrawSurface_Release(surface2);
3838         IDirectDrawSurface_Release(surface1);
3839     }
3840
3841     hr =IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
3842     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3843
3844     DestroyWindow(window);
3845 }
3846
3847 static void CreateSurfaceBadCapsSizeTest(void)
3848 {
3849     DDSURFACEDESC ddsd_ok;
3850     DDSURFACEDESC ddsd_bad1;
3851     DDSURFACEDESC ddsd_bad2;
3852     DDSURFACEDESC ddsd_bad3;
3853     DDSURFACEDESC ddsd_bad4;
3854     DDSURFACEDESC2 ddsd2_ok;
3855     DDSURFACEDESC2 ddsd2_bad1;
3856     DDSURFACEDESC2 ddsd2_bad2;
3857     DDSURFACEDESC2 ddsd2_bad3;
3858     DDSURFACEDESC2 ddsd2_bad4;
3859     IDirectDrawSurface *surf;
3860     IDirectDrawSurface4 *surf4;
3861     IDirectDrawSurface7 *surf7;
3862     HRESULT hr;
3863     IDirectDraw2 *dd2;
3864     IDirectDraw4 *dd4;
3865     IDirectDraw7 *dd7;
3866
3867     const DWORD caps = DDSCAPS_OFFSCREENPLAIN;
3868
3869     memset(&ddsd_ok, 0, sizeof(ddsd_ok));
3870     ddsd_ok.dwSize = sizeof(ddsd_ok);
3871     ddsd_ok.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3872     ddsd_ok.dwWidth = 64;
3873     ddsd_ok.dwHeight = 64;
3874     ddsd_ok.ddsCaps.dwCaps = caps;
3875     memcpy(&ddsd_bad1, &ddsd_ok, sizeof(ddsd_bad1));
3876     ddsd_bad1.dwSize--;
3877     memcpy(&ddsd_bad2, &ddsd_ok, sizeof(ddsd_bad2));
3878     ddsd_bad2.dwSize++;
3879     memcpy(&ddsd_bad3, &ddsd_ok, sizeof(ddsd_bad3));
3880     ddsd_bad3.dwSize = 0;
3881     memcpy(&ddsd_bad4, &ddsd_ok, sizeof(ddsd_bad4));
3882     ddsd_bad4.dwSize = sizeof(DDSURFACEDESC2);
3883
3884     memset(&ddsd2_ok, 0, sizeof(ddsd2_ok));
3885     ddsd2_ok.dwSize = sizeof(ddsd2_ok);
3886     ddsd2_ok.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3887     ddsd2_ok.dwWidth = 64;
3888     ddsd2_ok.dwHeight = 64;
3889     ddsd2_ok.ddsCaps.dwCaps = caps;
3890     memcpy(&ddsd2_bad1, &ddsd2_ok, sizeof(ddsd2_bad1));
3891     ddsd2_bad1.dwSize--;
3892     memcpy(&ddsd2_bad2, &ddsd2_ok, sizeof(ddsd2_bad2));
3893     ddsd2_bad2.dwSize++;
3894     memcpy(&ddsd2_bad3, &ddsd2_ok, sizeof(ddsd2_bad3));
3895     ddsd2_bad3.dwSize = 0;
3896     memcpy(&ddsd2_bad4, &ddsd2_ok, sizeof(ddsd2_bad4));
3897     ddsd2_bad4.dwSize = sizeof(DDSURFACEDESC);
3898
3899     hr = IDirectDraw_CreateSurface(lpDD, &ddsd_ok, &surf, NULL);
3900     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3901     IDirectDrawSurface_Release(surf);
3902
3903     hr = IDirectDraw_CreateSurface(lpDD, &ddsd_bad1, &surf, NULL);
3904     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3905        DDERR_INVALIDPARAMS, hr);
3906     hr = IDirectDraw_CreateSurface(lpDD, &ddsd_bad2, &surf, NULL);
3907     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3908        DDERR_INVALIDPARAMS, hr);
3909     hr = IDirectDraw_CreateSurface(lpDD, &ddsd_bad3, &surf, NULL);
3910     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3911        DDERR_INVALIDPARAMS, hr);
3912     hr = IDirectDraw_CreateSurface(lpDD, &ddsd_bad4, &surf, NULL);
3913     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3914        DDERR_INVALIDPARAMS, hr);
3915     hr = IDirectDraw_CreateSurface(lpDD, NULL, &surf, NULL);
3916     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3917        DDERR_INVALIDPARAMS, hr);
3918
3919     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
3920     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3921
3922     hr = IDirectDraw2_CreateSurface(dd2, &ddsd_ok, &surf, NULL);
3923     ok(SUCCEEDED(hr), "IDirectDraw2_CreateSurface failed: 0x%08x\n", hr);
3924     IDirectDrawSurface_Release(surf);
3925
3926     hr = IDirectDraw2_CreateSurface(dd2, &ddsd_bad1, &surf, NULL);
3927     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw2_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3928        DDERR_INVALIDPARAMS, hr);
3929     hr = IDirectDraw2_CreateSurface(dd2, &ddsd_bad2, &surf, NULL);
3930     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw2_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3931        DDERR_INVALIDPARAMS, hr);
3932     hr = IDirectDraw2_CreateSurface(dd2, &ddsd_bad3, &surf, NULL);
3933     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw2_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3934        DDERR_INVALIDPARAMS, hr);
3935     hr = IDirectDraw2_CreateSurface(dd2, &ddsd_bad4, &surf, NULL);
3936     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw2_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3937        DDERR_INVALIDPARAMS, hr);
3938     hr = IDirectDraw2_CreateSurface(dd2, NULL, &surf, NULL);
3939     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw2_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3940        DDERR_INVALIDPARAMS, hr);
3941
3942     IDirectDraw2_Release(dd2);
3943
3944     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
3945     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3946
3947     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2_ok, &surf4, NULL);
3948     ok(SUCCEEDED(hr), "IDirectDraw4_CreateSurface failed: 0x%08x\n", hr);
3949     IDirectDrawSurface4_Release(surf4);
3950
3951     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2_bad1, &surf4, NULL);
3952     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw4_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3953        DDERR_INVALIDPARAMS, hr);
3954     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2_bad2, &surf4, NULL);
3955     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw4_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3956        DDERR_INVALIDPARAMS, hr);
3957     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2_bad3, &surf4, NULL);
3958     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw4_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3959        DDERR_INVALIDPARAMS, hr);
3960     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2_bad4, &surf4, NULL);
3961     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw4_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3962        DDERR_INVALIDPARAMS, hr);
3963     hr = IDirectDraw4_CreateSurface(dd4, NULL, &surf4, NULL);
3964     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw4_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3965        DDERR_INVALIDPARAMS, hr);
3966
3967     IDirectDraw4_Release(dd4);
3968
3969     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3970     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3971
3972     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2_ok, &surf7, NULL);
3973     ok(SUCCEEDED(hr), "IDirectDraw7_CreateSurface failed: 0x%08x\n", hr);
3974     IDirectDrawSurface7_Release(surf7);
3975
3976     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2_bad1, &surf7, NULL);
3977     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3978        DDERR_INVALIDPARAMS, hr);
3979     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2_bad2, &surf7, NULL);
3980     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3981        DDERR_INVALIDPARAMS, hr);
3982     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2_bad3, &surf7, NULL);
3983     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3984        DDERR_INVALIDPARAMS, hr);
3985     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2_bad4, &surf7, NULL);
3986     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3987        DDERR_INVALIDPARAMS, hr);
3988     hr = IDirectDraw7_CreateSurface(dd7, NULL, &surf7, NULL);
3989     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7_CreateSurface didn't return 0x%08x, but 0x%08x\n",
3990        DDERR_INVALIDPARAMS, hr);
3991
3992     IDirectDraw7_Release(dd7);
3993 }
3994
3995 static void reset_ddsd(DDSURFACEDESC *ddsd)
3996 {
3997     memset(ddsd, 0, sizeof(*ddsd));
3998     ddsd->dwSize = sizeof(*ddsd);
3999 }
4000
4001 static void no_ddsd_caps_test(void)
4002 {
4003     DDSURFACEDESC ddsd;
4004     HRESULT hr;
4005     IDirectDrawSurface *surface;
4006
4007     reset_ddsd(&ddsd);
4008     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
4009     ddsd.dwWidth = 128;
4010     ddsd.dwHeight = 128;
4011     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4012     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4013     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4014     reset_ddsd(&ddsd);
4015     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4016     IDirectDrawSurface_Release(surface);
4017     ok(ddsd.dwFlags & DDSD_CAPS, "DDSD_CAPS is not set\n");
4018     ok(ddsd.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN, "DDSCAPS_OFFSCREENPLAIN is not set\n");
4019
4020     reset_ddsd(&ddsd);
4021     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4022     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4023     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4024     reset_ddsd(&ddsd);
4025     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4026     IDirectDrawSurface_Release(surface);
4027     ok(ddsd.dwFlags & DDSD_CAPS, "DDSD_CAPS is not set\n");
4028     ok(ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE, "DDSCAPS_OFFSCREENPLAIN is not set\n");
4029
4030     reset_ddsd(&ddsd);
4031     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
4032     ddsd.dwWidth = 128;
4033     ddsd.dwHeight = 128;
4034     ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
4035     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4036     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw_CreateSurface returned %#x, expected DDERR_INVALIDCAPS.\n", hr);
4037 }
4038
4039 static void dump_format(const DDPIXELFORMAT *fmt)
4040 {
4041     trace("dwFlags %08x, FourCC %08x, dwZBufferBitDepth %u, stencil %u\n", fmt->dwFlags, fmt->dwFourCC,
4042           U1(*fmt).dwZBufferBitDepth, U2(*fmt).dwStencilBitDepth);
4043     trace("dwZBitMask %08x, dwStencilBitMask %08x, dwRGBZBitMask %08x\n", U3(*fmt).dwZBitMask,
4044           U4(*fmt).dwStencilBitMask, U5(*fmt).dwRGBZBitMask);
4045 }
4046
4047 static void zbufferbitdepth_test(void)
4048 {
4049     enum zfmt_succeed
4050     {
4051         ZFMT_SUPPORTED_ALWAYS,
4052         ZFMT_SUPPORTED_NEVER,
4053         ZFMT_SUPPORTED_HWDEPENDENT
4054     };
4055     struct
4056     {
4057         DWORD depth;
4058         enum zfmt_succeed supported;
4059         DDPIXELFORMAT pf;
4060     }
4061     test_data[] =
4062     {
4063         {
4064             16, ZFMT_SUPPORTED_ALWAYS,
4065             {
4066                 sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4067                 {16}, {0}, {0x0000ffff}, {0x00000000}, {0x00000000}
4068             }
4069         },
4070         {
4071             24, ZFMT_SUPPORTED_HWDEPENDENT,
4072             {
4073                 sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4074                 {24}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
4075             }
4076         },
4077         {
4078             32, ZFMT_SUPPORTED_HWDEPENDENT,
4079             {
4080                 sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
4081                 {32}, {0}, {0xffffffff}, {0x00000000}, {0x00000000}
4082             }
4083         },
4084         /* Returns DDERR_INVALIDPARAMS instead of DDERR_INVALIDPIXELFORMAT.
4085          * Disabled for now
4086         {
4087             0, ZFMT_SUPPORTED_NEVER
4088         },
4089         */
4090         {
4091             15, ZFMT_SUPPORTED_NEVER
4092         },
4093         {
4094             28, ZFMT_SUPPORTED_NEVER
4095         },
4096         {
4097             40, ZFMT_SUPPORTED_NEVER
4098         },
4099     };
4100
4101     DDSURFACEDESC ddsd;
4102     IDirectDrawSurface *surface;
4103     HRESULT hr;
4104     unsigned int i;
4105     DDCAPS caps;
4106
4107     memset(&caps, 0, sizeof(caps));
4108     caps.dwSize = sizeof(caps);
4109     hr = IDirectDraw_GetCaps(lpDD, &caps, NULL);
4110     ok(SUCCEEDED(hr), "IDirectDraw_GetCaps failed, hr %#x.\n", hr);
4111     if (!(caps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
4112     {
4113         skip("Z buffers not supported, skipping DDSD_ZBUFFERBITDEPTH test\n");
4114         return;
4115     }
4116
4117     for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++)
4118     {
4119         reset_ddsd(&ddsd);
4120         ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH;
4121         ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4122         ddsd.dwWidth = 256;
4123         ddsd.dwHeight = 256;
4124         U2(ddsd).dwZBufferBitDepth = test_data[i].depth;
4125
4126         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4127         if (test_data[i].supported == ZFMT_SUPPORTED_ALWAYS)
4128         {
4129             ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4130         }
4131         else if (test_data[i].supported == ZFMT_SUPPORTED_NEVER)
4132         {
4133             ok(hr == DDERR_INVALIDPIXELFORMAT, "IDirectDraw_CreateSurface returned %#x, expected %x.\n",
4134                hr, DDERR_INVALIDPIXELFORMAT);
4135         }
4136         if (!surface) continue;
4137
4138         reset_ddsd(&ddsd);
4139         hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4140         ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4141         IDirectDrawSurface_Release(surface);
4142
4143         ok(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH is not set\n");
4144         ok(!(ddsd.dwFlags & DDSD_PIXELFORMAT), "DDSD_PIXELFORMAT is set\n");
4145         /* Yet the ddpfPixelFormat member contains valid data */
4146         if (memcmp(&ddsd.ddpfPixelFormat, &test_data[i].pf, ddsd.ddpfPixelFormat.dwSize))
4147         {
4148             ok(0, "Unexpected format for depth %u\n", test_data[i].depth);
4149             dump_format(&ddsd.ddpfPixelFormat);
4150         }
4151     }
4152
4153     /* DDSD_ZBUFFERBITDEPTH vs DDSD_PIXELFORMAT? */
4154     reset_ddsd(&ddsd);
4155     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_ZBUFFERBITDEPTH;
4156     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4157     ddsd.dwWidth = 256;
4158     ddsd.dwHeight = 256;
4159     U2(ddsd).dwZBufferBitDepth = 24;
4160     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4161     ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4162     U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth = 16;
4163     U3(ddsd.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4164
4165     surface = NULL;
4166     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4167     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4168     if (!surface) return;
4169     reset_ddsd(&ddsd);
4170     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4171     ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4172     IDirectDrawSurface_Release(surface);
4173     ok(U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth == 16, "Expected a 16bpp depth buffer, got %ubpp\n",
4174        U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth);
4175     ok(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH is not set\n");
4176     ok(!(ddsd.dwFlags & DDSD_PIXELFORMAT), "DDSD_PIXELFORMAT is set\n");
4177     ok(U2(ddsd).dwZBufferBitDepth == 16, "Expected dwZBufferBitDepth=16, got %u\n",
4178        U2(ddsd).dwZBufferBitDepth);
4179
4180     /* DDSD_PIXELFORMAT vs invalid ZBUFFERBITDEPTH */
4181     reset_ddsd(&ddsd);
4182     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_PIXELFORMAT;
4183     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4184     ddsd.dwWidth = 256;
4185     ddsd.dwHeight = 256;
4186     U2(ddsd).dwZBufferBitDepth = 40;
4187     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4188     ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4189     U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth = 16;
4190     U3(ddsd.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4191     surface = NULL;
4192     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4193     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4194     if (surface) IDirectDrawSurface_Release(surface);
4195
4196     /* Create a PIXELFORMAT-only surface, see if ZBUFFERBITDEPTH is set */
4197     reset_ddsd(&ddsd);
4198     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4199     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4200     ddsd.dwWidth = 256;
4201     ddsd.dwHeight = 256;
4202     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4203     ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
4204     U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth = 16;
4205     U3(ddsd.ddpfPixelFormat).dwZBitMask = 0x0000ffff;
4206     surface = NULL;
4207     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4208     ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4209     reset_ddsd(&ddsd);
4210     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd);
4211     ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4212     IDirectDrawSurface_Release(surface);
4213     ok(U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth == 16, "Expected a 16bpp depth buffer, got %ubpp\n",
4214        U1(ddsd.ddpfPixelFormat).dwZBufferBitDepth);
4215     ok(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH is not set\n");
4216     ok(!(ddsd.dwFlags & DDSD_PIXELFORMAT), "DDSD_PIXELFORMAT is set\n");
4217     ok(U2(ddsd).dwZBufferBitDepth == 16, "Expected dwZBufferBitDepth=16, got %u\n",
4218        U2(ddsd).dwZBufferBitDepth);
4219 }
4220
4221 static void test_ddsd(DDSURFACEDESC *ddsd, BOOL expect_pf, BOOL expect_zd, const char *name, DWORD z_bit_depth)
4222 {
4223     IDirectDrawSurface *surface;
4224     IDirectDrawSurface7 *surface7;
4225     HRESULT hr;
4226     DDSURFACEDESC out;
4227     DDSURFACEDESC2 out2;
4228
4229     hr = IDirectDraw_CreateSurface(lpDD, ddsd, &surface, NULL);
4230     if (hr == DDERR_NOZBUFFERHW)
4231     {
4232         skip("Z buffers not supported, skipping Z flag test\n");
4233         return;
4234     }
4235     ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr);
4236     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **) &surface7);
4237     ok(SUCCEEDED(hr), "IDirectDrawSurface_QueryInterface failed, hr %#x.\n", hr);
4238
4239     reset_ddsd(&out);
4240     hr = IDirectDrawSurface_GetSurfaceDesc(surface, &out);
4241     ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4242     memset(&out2, 0, sizeof(out2));
4243     out2.dwSize = sizeof(out2);
4244     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &out2);
4245     ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4246
4247     if (expect_pf)
4248     {
4249         ok(out.dwFlags & DDSD_PIXELFORMAT, "%s surface: Expected DDSD_PIXELFORMAT to be set\n", name);
4250         ok(out2.dwFlags & DDSD_PIXELFORMAT,
4251                 "%s surface: Expected DDSD_PIXELFORMAT to be set in DDSURFACEDESC2\n", name);
4252     }
4253     else
4254     {
4255         ok(!(out.dwFlags & DDSD_PIXELFORMAT), "%s surface: Expected DDSD_PIXELFORMAT not to be set\n", name);
4256         ok(out2.dwFlags & DDSD_PIXELFORMAT,
4257                 "%s surface: Expected DDSD_PIXELFORMAT to be set in DDSURFACEDESC2\n", name);
4258     }
4259     if (expect_zd)
4260     {
4261         ok(out.dwFlags & DDSD_ZBUFFERBITDEPTH, "%s surface: Expected DDSD_ZBUFFERBITDEPTH to be set\n", name);
4262         ok(U2(out).dwZBufferBitDepth == z_bit_depth, "ZBufferBitDepth is %u, expected %u\n",
4263                 U2(out).dwZBufferBitDepth, z_bit_depth);
4264         ok(!(out2.dwFlags & DDSD_ZBUFFERBITDEPTH),
4265                 "%s surface: Did not expect DDSD_ZBUFFERBITDEPTH to be set in DDSURFACEDESC2\n", name);
4266         /* dwMipMapCount and dwZBufferBitDepth share the same union */
4267         ok(U2(out2).dwMipMapCount == 0, "dwMipMapCount is %u, expected 0\n", U2(out2).dwMipMapCount);
4268     }
4269     else
4270     {
4271         ok(!(out.dwFlags & DDSD_ZBUFFERBITDEPTH), "%s surface: Expected DDSD_ZBUFFERBITDEPTH not to be set\n", name);
4272         ok(U2(out).dwZBufferBitDepth == 0, "ZBufferBitDepth is %u, expected 0\n", U2(out).dwZBufferBitDepth);
4273         ok(!(out2.dwFlags & DDSD_ZBUFFERBITDEPTH),
4274                 "%s surface: Did not expect DDSD_ZBUFFERBITDEPTH to be set in DDSURFACEDESC2\n", name);
4275         ok(U2(out2).dwMipMapCount == 0, "dwMipMapCount is %u, expected 0\n", U2(out2).dwMipMapCount);
4276     }
4277
4278     reset_ddsd(&out);
4279     hr = IDirectDrawSurface_Lock(surface, NULL, &out, 0, NULL);
4280     if (SUCCEEDED(hr))
4281     {
4282         hr = IDirectDrawSurface_Unlock(surface, NULL);
4283         ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr);
4284
4285         /* DDSD_ZBUFFERBITDEPTH is never set on Nvidia, but follows GetSurfaceDesc rules on AMD */
4286         if (!expect_zd)
4287         {
4288             ok(!(out.dwFlags & DDSD_ZBUFFERBITDEPTH),
4289                 "Lock %s surface: Expected DDSD_ZBUFFERBITDEPTH not to be set\n", name);
4290         }
4291
4292         /* DDSD_PIXELFORMAT follows GetSurfaceDesc rules */
4293         if (expect_pf)
4294         {
4295             ok(out.dwFlags & DDSD_PIXELFORMAT, "%s surface: Expected DDSD_PIXELFORMAT to be set\n", name);
4296         }
4297         else
4298         {
4299             ok(!(out.dwFlags & DDSD_PIXELFORMAT),
4300                 "Lock %s surface: Expected DDSD_PIXELFORMAT not to be set\n", name);
4301         }
4302         if (out.dwFlags & DDSD_ZBUFFERBITDEPTH)
4303             ok(U2(out).dwZBufferBitDepth == z_bit_depth, "ZBufferBitDepth is %u, expected %u\n",
4304                     U2(out).dwZBufferBitDepth, z_bit_depth);
4305         else
4306             ok(U2(out).dwZBufferBitDepth == 0, "ZBufferBitDepth is %u, expected 0\n", U2(out).dwZBufferBitDepth);
4307     }
4308
4309     hr = IDirectDrawSurface7_Lock(surface7, NULL, &out2, 0, NULL);
4310     ok(SUCCEEDED(hr), "IDirectDrawSurface7_Lock failed, hr %#x.\n", hr);
4311     if (SUCCEEDED(hr))
4312     {
4313         hr = IDirectDrawSurface7_Unlock(surface7, NULL);
4314         ok(SUCCEEDED(hr), "IDirectDrawSurface7_Unlock failed, hr %#x.\n", hr);
4315         /* DDSD_PIXELFORMAT is always set, DDSD_ZBUFFERBITDEPTH never */
4316         ok(out2.dwFlags & DDSD_PIXELFORMAT,
4317                 "Lock %s surface: Expected DDSD_PIXELFORMAT to be set in DDSURFACEDESC2\n", name);
4318         ok(!(out2.dwFlags & DDSD_ZBUFFERBITDEPTH),
4319                 "Lock %s surface: Did not expect DDSD_ZBUFFERBITDEPTH to be set in DDSURFACEDESC2\n", name);
4320         ok(U2(out2).dwMipMapCount == 0, "dwMipMapCount is %u, expected 0\n", U2(out2).dwMipMapCount);
4321     }
4322
4323     IDirectDrawSurface7_Release(surface7);
4324     IDirectDrawSurface_Release(surface);
4325 }
4326
4327 static void pixelformat_flag_test(void)
4328 {
4329     DDSURFACEDESC ddsd;
4330     DDCAPS caps;
4331     HRESULT hr;
4332
4333     memset(&caps, 0, sizeof(caps));
4334     caps.dwSize = sizeof(caps);
4335     hr = IDirectDraw_GetCaps(lpDD, &caps, NULL);
4336     ok(SUCCEEDED(hr), "IDirectDraw_GetCaps failed, hr %#x.\n", hr);
4337     if (!(caps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
4338     {
4339         skip("Z buffers not supported, skipping DDSD_PIXELFORMAT test\n");
4340         return;
4341     }
4342
4343     reset_ddsd(&ddsd);
4344     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
4345     ddsd.dwWidth = 64;
4346     ddsd.dwHeight = 64;
4347     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
4348     test_ddsd(&ddsd, TRUE, FALSE, "offscreen plain", ~0U);
4349
4350     reset_ddsd(&ddsd);
4351     ddsd.dwFlags = DDSD_CAPS;
4352     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
4353     test_ddsd(&ddsd, TRUE, FALSE, "primary", ~0U);
4354
4355     reset_ddsd(&ddsd);
4356     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
4357     ddsd.dwWidth = 64;
4358     ddsd.dwHeight = 64;
4359     U2(ddsd).dwZBufferBitDepth = 16;
4360     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
4361     test_ddsd(&ddsd, FALSE, TRUE, "Z buffer", 16);
4362 }
4363
4364 static void set_surface_desc_test(void)
4365 {
4366     HRESULT hr;
4367     DDSURFACEDESC ddsd;
4368     IDirectDrawSurface *surface;
4369     IDirectDrawSurface3 *surface3;
4370     BYTE data[16*16*4];
4371
4372     reset_ddsd(&ddsd);
4373     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4374     ddsd.dwWidth = 8;
4375     ddsd.dwHeight = 8;
4376     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4377     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4378     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4379     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4380     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4381     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4382     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
4383
4384     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4385     ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4386
4387     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **) &surface3);
4388     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4389     IDirectDrawSurface_Release(surface);
4390
4391     reset_ddsd(&ddsd);
4392     ddsd.dwFlags = DDSD_LPSURFACE;
4393     ddsd.lpSurface = data;
4394     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4395     ok(SUCCEEDED(hr), "SetSurfaceDesc failed, hr %#x.\n", hr);
4396
4397     /* Redundantly setting the same lpSurface is not an error */
4398     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4399     ok(SUCCEEDED(hr), "SetSurfaceDesc failed, hr %#x.\n", hr);
4400
4401     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 1);
4402     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4403
4404     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, NULL, 0);
4405     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4406
4407     IDirectDrawSurface_Release(surface3);
4408
4409     reset_ddsd(&ddsd);
4410     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4411     ddsd.dwWidth = 8;
4412     ddsd.dwHeight = 8;
4413     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4414     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4415     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4416     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4417     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4418     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4419     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
4420
4421     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4422     ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
4423     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **) &surface3);
4424     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4425     IDirectDrawSurface_Release(surface);
4426     hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4427     ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
4428
4429     /* Setting the caps is an error. This also means the original description cannot be reapplied */
4430     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4431     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4432
4433     ddsd.dwFlags = DDSD_CAPS;
4434     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4435     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4436
4437     /* TODO: The INVALIDCAPS return value suggests that some caps can be set. */
4438     ddsd.dwFlags = DDSD_CAPS | DDSD_LPSURFACE;
4439     ddsd.lpSurface = data;
4440     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4441     ok(hr == DDERR_INVALIDCAPS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDCAPS);
4442     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
4443     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4444     ok(hr == DDERR_INVALIDCAPS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDCAPS);
4445
4446     /* Setting the height is allowed, but it cannot be set to 0, and only if LPSURFACE is set too */
4447     reset_ddsd(&ddsd);
4448     ddsd.dwFlags = DDSD_HEIGHT;
4449     ddsd.dwHeight = 16;
4450     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4451     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4452
4453     ddsd.lpSurface = data;
4454     ddsd.dwFlags = DDSD_HEIGHT | DDSD_LPSURFACE;
4455     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4456     ok(SUCCEEDED(hr), "SetSurfaceDesc failed, hr %#x.\n", hr);
4457
4458     ddsd.dwHeight = 0;
4459     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4460     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4461
4462     reset_ddsd(&ddsd);
4463     hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4464     ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
4465     ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
4466     ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
4467
4468     /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */
4469     reset_ddsd(&ddsd);
4470     ddsd.dwFlags = DDSD_PITCH;
4471     U1(ddsd).lPitch = 8 * 4;
4472     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4473     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4474
4475     ddsd.dwFlags = DDSD_WIDTH;
4476     ddsd.dwWidth = 16;
4477     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4478     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4479
4480     ddsd.dwFlags = DDSD_PITCH | DDSD_LPSURFACE;
4481     ddsd.lpSurface = data;
4482     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4483     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4484
4485     ddsd.dwFlags = DDSD_WIDTH | DDSD_LPSURFACE;
4486     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4487     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4488
4489     ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4490     U1(ddsd).lPitch = 16 * 4;
4491     ddsd.dwWidth = 16;
4492     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4493     ok(SUCCEEDED(hr), "SetSurfaceDesc failed, hr %#x.\n", hr);
4494
4495     reset_ddsd(&ddsd);
4496     hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
4497     ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
4498     ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
4499     ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
4500     ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
4501
4502     /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise
4503      *
4504      * VMware rejects those calls, but all real drivers accept it. Mark the VMware behavior broken. */
4505     ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4506     U1(ddsd).lPitch = 4 * 4;
4507     ddsd.lpSurface = data;
4508     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4509     ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "SetSurfaceDesc failed, hr %#x.\n", hr);
4510
4511     U1(ddsd).lPitch = 4;
4512     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4513     ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPARAMS), "SetSurfaceDesc failed, hr %#x.\n", hr);
4514
4515     U1(ddsd).lPitch = 16 * 4 + 1;
4516     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4517     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4518
4519     U1(ddsd).lPitch = 16 * 4 + 3;
4520     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4521     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4522
4523     U1(ddsd).lPitch = -4; /* lPitch is signed */
4524     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4525     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4526
4527     U1(ddsd).lPitch = 16 * 4;
4528     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4529     ok(SUCCEEDED(hr), "SetSurfaceDesc failed, hr %#x.\n", hr);
4530
4531     reset_ddsd(&ddsd);
4532     ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4533     U1(ddsd).lPitch = 0;
4534     ddsd.dwWidth = 16;
4535     ddsd.lpSurface = data;
4536     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4537     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4538
4539     ddsd.dwFlags = DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
4540     U1(ddsd).lPitch = 16 * 4;
4541     ddsd.dwWidth = 0;
4542     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4543     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4544
4545     /* Setting the pixelformat without lpsurface is an error, but with LPSURFACE it works */
4546     ddsd.dwFlags = DDSD_PIXELFORMAT;
4547     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4548     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4549     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4550     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4551     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4552     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4553     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4554     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4555
4556     ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_LPSURFACE;
4557     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4558     ok(hr == DD_OK, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DD_OK);
4559
4560     /* Can't set color keys */
4561     reset_ddsd(&ddsd);
4562     ddsd.dwFlags = DDSD_CKSRCBLT;
4563     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00ff0000;
4564     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00ff0000;
4565     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4566     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4567
4568     ddsd.dwFlags = DDSD_CKSRCBLT | DDSD_LPSURFACE;
4569     ddsd.lpSurface = data;
4570     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4571     ok(hr == DDERR_INVALIDPARAMS, "SetSurfaceDesc returned %#x, expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4572
4573     IDirectDrawSurface_Release(surface3);
4574
4575     /* Need systemmemory surfaces
4576      *
4577      * As a sidenote, fourcc surfaces aren't allowed in sysmem, thus testing DDSD_LINEARSIZE is moot */
4578     reset_ddsd(&ddsd);
4579     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
4580     ddsd.dwWidth = 8;
4581     ddsd.dwHeight = 8;
4582     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4583     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
4584     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
4585     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
4586     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
4587     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x000000ff;
4588     ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
4589
4590     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4591     ok(SUCCEEDED(hr) || hr == DDERR_NODIRECTDRAWHW, "CreateSurface failed, hr %#x.\n", hr);
4592     if (FAILED(hr))
4593     {
4594         skip("Cannot create a video memory surface, skipping vidmem SetSurfaceDesc test.\n");
4595         return;
4596     }
4597     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface3, (void **) &surface3);
4598     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4599     IDirectDrawSurface_Release(surface);
4600
4601     reset_ddsd(&ddsd);
4602     ddsd.dwFlags = DDSD_LPSURFACE;
4603     ddsd.lpSurface = data;
4604     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4605     ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc returned %#x, expected %#x.\n",
4606             hr, DDERR_INVALIDSURFACETYPE);
4607
4608     ddsd.dwFlags = DDSD_WIDTH;
4609     hr = IDirectDrawSurface3_SetSurfaceDesc(surface3, &ddsd, 0);
4610     ok(hr == DDERR_INVALIDSURFACETYPE, "SetSurfaceDesc returned %#x, expected %#x.\n",
4611             hr, DDERR_INVALIDSURFACETYPE);
4612
4613     IDirectDrawSurface3_Release(surface3);
4614 }
4615
4616 static BOOL fourcc_supported(DWORD fourcc, DWORD caps)
4617 {
4618     DDSURFACEDESC ddsd;
4619     HRESULT hr;
4620     IDirectDrawSurface *surface;
4621
4622     reset_ddsd(&ddsd);
4623     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
4624     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
4625     ddsd.dwWidth = 4;
4626     ddsd.dwHeight = 4;
4627     ddsd.ddsCaps.dwCaps = caps;
4628     ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4629     ddsd.ddpfPixelFormat.dwFourCC = fourcc;
4630     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
4631     if (FAILED(hr))
4632     {
4633         return FALSE;
4634     }
4635     IDirectDrawSurface_Release(surface);
4636     return TRUE;
4637 }
4638
4639 static void partial_block_lock_test(void)
4640 {
4641     IDirectDrawSurface7 *surface;
4642     HRESULT hr;
4643     DDSURFACEDESC2 ddsd;
4644     IDirectDraw7 *dd7;
4645     const struct
4646     {
4647         DWORD caps, caps2;
4648         const char *name;
4649         BOOL success;
4650     }
4651     pools[] =
4652     {
4653         {
4654             DDSCAPS_VIDEOMEMORY, 0,
4655             "D3DPOOL_DEFAULT", FALSE
4656         },
4657         {
4658             DDSCAPS_SYSTEMMEMORY, 0,
4659             "D3DPOOL_SYSTEMMEM", TRUE
4660         },
4661         {
4662             0, DDSCAPS2_TEXTUREMANAGE,
4663             "D3DPOOL_MANAGED", TRUE
4664         }
4665     };
4666     const struct
4667     {
4668         DWORD fourcc;
4669         DWORD caps;
4670         const char *name;
4671         unsigned int block_width;
4672         unsigned int block_height;
4673     }
4674     formats[] =
4675     {
4676         {MAKEFOURCC('D','X','T','1'), DDSCAPS_TEXTURE, "D3DFMT_DXT1", 4, 4},
4677         {MAKEFOURCC('D','X','T','2'), DDSCAPS_TEXTURE, "D3DFMT_DXT2", 4, 4},
4678         {MAKEFOURCC('D','X','T','3'), DDSCAPS_TEXTURE, "D3DFMT_DXT3", 4, 4},
4679         {MAKEFOURCC('D','X','T','4'), DDSCAPS_TEXTURE, "D3DFMT_DXT4", 4, 4},
4680         {MAKEFOURCC('D','X','T','5'), DDSCAPS_TEXTURE, "D3DFMT_DXT5", 4, 4},
4681         /* ATI2N surfaces aren't available in ddraw */
4682         {MAKEFOURCC('U','Y','V','Y'), DDSCAPS_OVERLAY, "D3DFMT_UYVY", 2, 1},
4683         {MAKEFOURCC('Y','U','Y','2'), DDSCAPS_OVERLAY, "D3DFMT_YUY2", 2, 1},
4684     };
4685     unsigned int i, j;
4686     RECT rect;
4687
4688     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
4689     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4690
4691     for (i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)
4692     {
4693         if (!fourcc_supported(formats[i].fourcc, formats[i].caps | DDSCAPS_VIDEOMEMORY))
4694         {
4695             skip("%s surfaces not supported, skipping partial block lock test\n", formats[i].name);
4696             continue;
4697         }
4698
4699         for (j = 0; j < (sizeof(pools) / sizeof(*pools)); j++)
4700         {
4701             if (formats[i].caps & DDSCAPS_OVERLAY && !(pools[j].caps & DDSCAPS_VIDEOMEMORY))
4702                 continue;
4703
4704             memset(&ddsd, 0, sizeof(ddsd));
4705             ddsd.dwSize = sizeof(ddsd);
4706             ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
4707             ddsd.dwWidth = 128;
4708             ddsd.dwHeight = 128;
4709             ddsd.ddsCaps.dwCaps = pools[j].caps | formats[i].caps;
4710             ddsd.ddsCaps.dwCaps2 = pools[j].caps2;
4711             U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
4712             U4(ddsd).ddpfPixelFormat.dwFourCC = formats[i].fourcc;
4713             hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
4714             ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x, format %s, pool %s\n",
4715                 hr, formats[i].name, pools[j].name);
4716
4717             /* All Windows versions allow partial block locks with DDSCAPS_SYSTEMMEMORY and
4718              * DDSCAPS2_TEXTUREMANAGE, just like in d3d8 and d3d9. Windows XP also allows those locks
4719              * with DDSCAPS_VIDEOMEMORY. Windows Vista and Windows 7 disallow partial locks of vidmem
4720              * surfaces, making the ddraw behavior consistent with d3d8 and 9.
4721              *
4722              * Mark the Windows XP behavior as broken until we find an application that needs it */
4723             if (formats[i].block_width > 1)
4724             {
4725                 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
4726                 hr = IDirectDrawSurface7_Lock(surface, &rect, &ddsd, 0, NULL);
4727                 ok(!SUCCEEDED(hr) == !pools[j].success || broken(SUCCEEDED(hr)),
4728                         "Partial block lock %s, expected %s, format %s, pool %s\n",
4729                         SUCCEEDED(hr) ? "succeeded" : "failed", pools[j].success ? "success" : "failure",
4730                         formats[i].name, pools[j].name);
4731                 if (SUCCEEDED(hr))
4732                 {
4733                     hr = IDirectDrawSurface7_Unlock(surface, NULL);
4734                     ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
4735                 }
4736
4737                 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
4738                 hr = IDirectDrawSurface7_Lock(surface, &rect, &ddsd, 0, NULL);
4739                 ok(!SUCCEEDED(hr) == !pools[j].success || broken(SUCCEEDED(hr)),
4740                         "Partial block lock %s, expected %s, format %s, pool %s\n",
4741                         SUCCEEDED(hr) ? "succeeded" : "failed", pools[j].success ? "success" : "failure",
4742                         formats[i].name, pools[j].name);
4743                 if (SUCCEEDED(hr))
4744                 {
4745                     hr = IDirectDrawSurface7_Unlock(surface, NULL);
4746                     ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
4747                 }
4748             }
4749
4750             if (formats[i].block_height > 1)
4751             {
4752                 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
4753                 hr = IDirectDrawSurface7_Lock(surface, &rect, &ddsd, 0, NULL);
4754                 ok(!SUCCEEDED(hr) == !pools[j].success || broken(SUCCEEDED(hr)),
4755                         "Partial block lock %s, expected %s, format %s, pool %s\n",
4756                         SUCCEEDED(hr) ? "succeeded" : "failed", pools[j].success ? "success" : "failure",
4757                         formats[i].name, pools[j].name);
4758                 if (SUCCEEDED(hr))
4759                 {
4760                     hr = IDirectDrawSurface7_Unlock(surface, NULL);
4761                     ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
4762                 }
4763
4764                 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
4765                 hr = IDirectDrawSurface7_Lock(surface, &rect, &ddsd, 0, NULL);
4766                 ok(!SUCCEEDED(hr) == !pools[j].success || broken(SUCCEEDED(hr)),
4767                         "Partial block lock %s, expected %s, format %s, pool %s\n",
4768                         SUCCEEDED(hr) ? "succeeded" : "failed", pools[j].success ? "success" : "failure",
4769                         formats[i].name, pools[j].name);
4770                 if (SUCCEEDED(hr))
4771                 {
4772                     hr = IDirectDrawSurface7_Unlock(surface, NULL);
4773                     ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
4774                 }
4775             }
4776
4777             SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
4778             hr = IDirectDrawSurface7_Lock(surface, &rect, &ddsd, 0, NULL);
4779             ok(SUCCEEDED(hr), "Full block lock returned %08x, expected %08x, format %s, pool %s\n",
4780                     hr, DD_OK, formats[i].name, pools[j].name);
4781             if (SUCCEEDED(hr))
4782             {
4783                 hr = IDirectDrawSurface7_Unlock(surface, NULL);
4784                 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
4785             }
4786
4787             IDirectDrawSurface7_Release(surface);
4788         }
4789     }
4790
4791     IDirectDraw7_Release(dd7);
4792 }
4793
4794 static void create_surface_test(void)
4795 {
4796     HRESULT hr;
4797     IDirectDraw2 *ddraw2;
4798     IDirectDraw4 *ddraw4;
4799     IDirectDraw7 *ddraw7;
4800     IDirectDrawSurface *surface;
4801     IDirectDrawSurface4 *surface4;
4802     IDirectDrawSurface7 *surface7;
4803
4804     hr = IDirectDraw_CreateSurface(lpDD, NULL, &surface, NULL);
4805     ok(hr == DDERR_INVALIDPARAMS, "CreateSurface(ddsd=NULL) returned %#x,"
4806             " expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4807
4808     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &ddraw2);
4809     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4810
4811     hr = IDirectDraw2_CreateSurface(ddraw2, NULL, &surface, NULL);
4812     ok(hr == DDERR_INVALIDPARAMS, "CreateSurface(ddsd=NULL) returned %#x,"
4813             " expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4814
4815     IDirectDraw2_Release(ddraw2);
4816
4817     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &ddraw4);
4818     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
4819
4820     hr = IDirectDraw4_CreateSurface(ddraw4, NULL, &surface4, NULL);
4821     ok(hr == DDERR_INVALIDPARAMS, "CreateSurface(ddsd=NULL) returned %#x,"
4822             " expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4823
4824     IDirectDraw4_Release(ddraw4);
4825
4826     if (!pDirectDrawCreateEx)
4827     {
4828         skip("DirectDrawCreateEx not available, skipping IDirectDraw7 tests.\n");
4829         return;
4830     }
4831     hr = pDirectDrawCreateEx(NULL, (void **) &ddraw7, &IID_IDirectDraw7, NULL);
4832     ok(SUCCEEDED(hr), "DirectDrawCreateEx failed, hr %#x.\n", hr);
4833
4834     hr = IDirectDraw7_CreateSurface(ddraw7, NULL, &surface7, NULL);
4835     ok(hr == DDERR_NOCOOPERATIVELEVELSET, "CreateSurface(ddsd=NULL, pre-SCL) returned %#x,"
4836             " expected %#x.\n", hr, DDERR_NOCOOPERATIVELEVELSET);
4837
4838     hr = IDirectDraw7_SetCooperativeLevel(ddraw7, NULL, DDSCL_NORMAL);
4839     ok(hr == DD_OK, "SetCooperativeLevel failed, hr %#x.\n", hr);
4840
4841     hr = IDirectDraw7_CreateSurface(ddraw7, NULL, &surface7, NULL);
4842     ok(hr == DDERR_INVALIDPARAMS, "CreateSurface(ddsd=NULL) returned %#x,"
4843             " expected %#x.\n", hr, DDERR_INVALIDPARAMS);
4844
4845     IDirectDraw7_Release(ddraw7);
4846 }
4847
4848 START_TEST(dsurface)
4849 {
4850     HRESULT ret;
4851     IDirectDraw4 *dd4;
4852
4853     HMODULE ddraw_mod = GetModuleHandleA("ddraw.dll");
4854     pDirectDrawCreateEx = (void *) GetProcAddress(ddraw_mod, "DirectDrawCreateEx");
4855
4856     if (!CreateDirectDraw())
4857         return;
4858
4859     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
4860     if (ret == E_NOINTERFACE)
4861     {
4862         win_skip("DirectDraw4 and higher are not supported\n");
4863         ReleaseDirectDraw();
4864         return;
4865     }
4866     IDirectDraw_Release(dd4);
4867
4868     if(!can_create_primary_surface())
4869     {
4870         skip("Unable to create primary surface\n");
4871         return;
4872     }
4873
4874     ddcaps.dwSize = sizeof(DDCAPS);
4875     ret = IDirectDraw_GetCaps(lpDD, &ddcaps, NULL);
4876     if (ret != DD_OK)
4877     {
4878         skip("IDirectDraw_GetCaps failed with %08x\n", ret);
4879         return;
4880     }
4881
4882     MipMapCreationTest();
4883     SrcColorKey32BlitTest();
4884     QueryInterface();
4885     GetDDInterface_1();
4886     GetDDInterface_2();
4887     GetDDInterface_4();
4888     GetDDInterface_7();
4889     EnumTest();
4890     AttachmentTest();
4891     AttachmentTest7();
4892     CubeMapTest();
4893     test_lockrect_invalid();
4894     CompressedTest();
4895     SizeTest();
4896     PrivateDataTest();
4897     BltParamTest();
4898     StructSizeTest();
4899     PaletteTest();
4900     SurfaceCapsTest();
4901     GetDCTest();
4902     GetDCFormatTest();
4903     BackBufferCreateSurfaceTest();
4904     BackBufferAttachmentFlipTest();
4905     CreateSurfaceBadCapsSizeTest();
4906     no_ddsd_caps_test();
4907     zbufferbitdepth_test();
4908     pixelformat_flag_test();
4909     set_surface_desc_test();
4910     partial_block_lock_test();
4911     create_surface_test();
4912     ReleaseDirectDraw();
4913 }