gameux: Add stub of IGameStatisticsMgr implementation.
[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 Stefan Dösinger
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 <assert.h>
27 #include "wine/test.h"
28 #include "ddraw.h"
29 #include "d3d.h"
30 #include "unknwn.h"
31
32 static LPDIRECTDRAW lpDD = NULL;
33 static DDCAPS ddcaps;
34
35 static BOOL CreateDirectDraw(void)
36 {
37     HRESULT rc;
38
39     rc = DirectDrawCreate(NULL, &lpDD, NULL);
40     ok(rc==DD_OK || rc==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", rc);
41     if (!lpDD) {
42         trace("DirectDrawCreateEx() failed with an error %x\n", rc);
43         return FALSE;
44     }
45
46     rc = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
47     ok(rc==DD_OK,"SetCooperativeLevel returned: %x\n",rc);
48
49     return TRUE;
50 }
51
52
53 static void ReleaseDirectDraw(void)
54 {
55     if( lpDD != NULL )
56     {
57         IDirectDraw_Release(lpDD);
58         lpDD = NULL;
59     }
60 }
61
62 static void MipMapCreationTest(void)
63 {
64     LPDIRECTDRAWSURFACE lpDDSMipMapTest;
65     DDSURFACEDESC ddsd;
66     HRESULT rc;
67
68     /* First mipmap creation test: create a surface with DDSCAPS_COMPLEX,
69        DDSCAPS_MIPMAP, and DDSD_MIPMAPCOUNT. This create the number of
70         requested mipmap levels. */
71     ddsd.dwSize = sizeof(ddsd);
72     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
73     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
74     U2(ddsd).dwMipMapCount = 3;
75     ddsd.dwWidth = 128;
76     ddsd.dwHeight = 32;
77     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
78     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
79     if (FAILED(rc)) {
80         skip("failed to create surface\n");
81         return;
82     }
83
84     /* Check the number of created mipmaps */
85     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
86     ddsd.dwSize = sizeof(ddsd);
87     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
88     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
89     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
90         "GetSurfaceDesc returned no mipmapcount.\n");
91     ok(U2(ddsd).dwMipMapCount == 3, "Incorrect mipmap count: %d.\n",
92         U2(ddsd).dwMipMapCount);
93
94     /* Destroy the surface. */
95     IDirectDrawSurface_Release(lpDDSMipMapTest);
96
97
98     /* Second mipmap creation test: create a surface without a mipmap
99        count, with DDSCAPS_MIPMAP and without DDSCAPS_COMPLEX.
100        This creates a single mipmap level. */
101     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
102     ddsd.dwSize = sizeof(ddsd);
103     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
104     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
105     ddsd.dwWidth = 128;
106     ddsd.dwHeight = 32;
107     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
108     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
109     if (FAILED(rc)) {
110         skip("failed to create surface\n");
111         return;
112     }
113     /* Check the number of created mipmaps */
114     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
115     ddsd.dwSize = sizeof(ddsd);
116     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
117     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
118     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
119         "GetSurfaceDesc returned no mipmapcount.\n");
120     ok(U2(ddsd).dwMipMapCount == 1, "Incorrect mipmap count: %d.\n",
121         U2(ddsd).dwMipMapCount);
122
123     /* Destroy the surface. */
124     IDirectDrawSurface_Release(lpDDSMipMapTest);
125
126
127     /* Third mipmap creation test: create a surface with DDSCAPS_MIPMAP,
128         DDSCAPS_COMPLEX and without DDSD_MIPMAPCOUNT.
129        It's an undocumented features where a chain of mipmaps, starting from
130        he specified size and down to the smallest size, is automatically
131        created.
132        Anarchy Online needs this feature to work. */
133     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
134     ddsd.dwSize = sizeof(ddsd);
135     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
136     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
137     ddsd.dwWidth = 128;
138     ddsd.dwHeight = 32;
139     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
140     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
141     if (FAILED(rc)) {
142         skip("failed to create surface\n");
143         return;
144     }
145
146     /* Check the number of created mipmaps */
147     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
148     ddsd.dwSize = sizeof(ddsd);
149     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
150     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
151     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
152         "GetSurfaceDesc returned no mipmapcount.\n");
153     ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %d.\n",
154         U2(ddsd).dwMipMapCount);
155
156     /* Destroy the surface. */
157     IDirectDrawSurface_Release(lpDDSMipMapTest);
158
159
160     /* Fourth mipmap creation test: same as above with a different texture
161        size.
162        The purpose is to verify that the number of generated mipmaps is
163        dependent on the smallest dimension. */
164     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
165     ddsd.dwSize = sizeof(ddsd);
166     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
167     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
168     ddsd.dwWidth = 32;
169     ddsd.dwHeight = 64;
170     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
171     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
172     if (FAILED(rc)) {
173         skip("failed to create surface\n");
174         return;
175     }
176
177     /* Check the number of created mipmaps */
178     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
179     ddsd.dwSize = sizeof(ddsd);
180     rc = IDirectDrawSurface_GetSurfaceDesc(lpDDSMipMapTest, &ddsd);
181     ok(rc==DD_OK,"GetSurfaceDesc returned: %x\n",rc);
182     ok(ddsd.dwFlags & DDSD_MIPMAPCOUNT,
183         "GetSurfaceDesc returned no mipmapcount.\n");
184     ok(U2(ddsd).dwMipMapCount == 6, "Incorrect mipmap count: %d.\n",
185         U2(ddsd).dwMipMapCount);
186
187     /* Destroy the surface. */
188     IDirectDrawSurface_Release(lpDDSMipMapTest);
189
190
191     /* Fifth mipmap creation test: try to create a surface with
192        DDSCAPS_COMPLEX, DDSCAPS_MIPMAP, DDSD_MIPMAPCOUNT,
193        where dwMipMapCount = 0. This should fail. */
194
195     ddsd.dwSize = sizeof(ddsd);
196     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
197     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
198     U2(ddsd).dwMipMapCount = 0;
199     ddsd.dwWidth = 128;
200     ddsd.dwHeight = 32;
201     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDSMipMapTest, NULL);
202     ok(rc==DDERR_INVALIDPARAMS,"CreateSurface returned: %x\n",rc);
203
204     /* Destroy the surface. */
205     if( rc == DD_OK )
206         IDirectDrawSurface_Release(lpDDSMipMapTest);
207
208 }
209
210 static void SrcColorKey32BlitTest(void)
211 {
212     LPDIRECTDRAWSURFACE lpSrc;
213     LPDIRECTDRAWSURFACE lpDst;
214     DDSURFACEDESC ddsd, ddsd2, ddsd3;
215     DDCOLORKEY DDColorKey;
216     LPDWORD lpData;
217     HRESULT rc;
218     DDBLTFX fx;
219
220     ddsd2.dwSize = sizeof(ddsd2);
221     ddsd2.ddpfPixelFormat.dwSize = sizeof(ddsd2.ddpfPixelFormat);
222
223     ddsd.dwSize = sizeof(ddsd);
224     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
225     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
226     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
227     ddsd.dwWidth = 800;
228     ddsd.dwHeight = 600;
229     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
230     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
231     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
232     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
233     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
234     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL);
235     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
236     if (FAILED(rc)) {
237         skip("failed to create surface\n");
238         return;
239     }
240
241     ddsd.dwFlags |= DDSD_CKSRCBLT;
242     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0xFF00FF;
243     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0xFF00FF;
244     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL);
245     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
246     if (FAILED(rc)) {
247         skip("failed to create surface\n");
248         return;
249     }
250
251     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
252     ok(rc==DD_OK,"Lock returned: %x\n",rc);
253     lpData = ddsd2.lpSurface;
254     lpData[0] = 0xCCCCCCCC;
255     lpData[1] = 0xCCCCCCCC;
256     lpData[2] = 0xCCCCCCCC;
257     lpData[3] = 0xCCCCCCCC;
258
259     memset(&ddsd3, 0, sizeof(ddsd3));
260     ddsd3.dwSize = sizeof(ddsd3);
261     ddsd3.ddpfPixelFormat.dwSize = sizeof(ddsd3.ddpfPixelFormat);
262     rc = IDirectDrawSurface_GetSurfaceDesc(lpDst, &ddsd3);
263     ok(rc == DD_OK, "IDirectDrawSurface_GetSurfaceDesc between a lock/unlock pair returned %08x\n", rc);
264     ok(ddsd3.lpSurface == ddsd3.lpSurface, "lpSurface from GetSurfaceDesc(%p) differs from the one returned by Lock(%p)\n", ddsd3.lpSurface, ddsd2.lpSurface);
265
266     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
267     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
268
269     memset(&ddsd3, 0, sizeof(ddsd3));
270     ddsd3.dwSize = sizeof(ddsd3);
271     ddsd3.ddpfPixelFormat.dwSize = sizeof(ddsd3.ddpfPixelFormat);
272     rc = IDirectDrawSurface_GetSurfaceDesc(lpDst, &ddsd3);
273     ok(rc == DD_OK, "IDirectDrawSurface_GetSurfaceDesc between a lock/unlock pair returned %08x\n", rc);
274     ok(ddsd3.lpSurface == NULL, "lpSurface from GetSurfaceDesc(%p) is not NULL after unlock\n", ddsd3.lpSurface);
275
276     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
277     ok(rc==DD_OK,"Lock returned: %x\n",rc);
278     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
279     lpData = ddsd2.lpSurface;
280     lpData[0] = 0x77010203;
281     lpData[1] = 0x00010203;
282     lpData[2] = 0x77FF00FF;
283     lpData[3] = 0x00FF00FF;
284     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
285     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
286
287     IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, NULL);
288
289     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
290     ok(rc==DD_OK,"Lock returned: %x\n",rc);
291     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
292     lpData = ddsd2.lpSurface;
293     /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
294      * color keying, but copy it to the destination surface. Others apply it for color keying, but
295      * do not copy it into the destination surface.
296      */
297     if(lpData[0]==0x00010203) {
298         trace("X channel was not copied into the destination surface\n");
299         ok((lpData[0]==0x00010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0x00FF00FF)&&(lpData[3]==0xCCCCCCCC),
300            "Destination data after blitting is not correct\n");
301     } else {
302         ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC),
303            "Destination data after blitting is not correct\n");
304     }
305     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
306     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
307
308     /* Below we repeat the same test as above but now using BltFast instead of Blt. Before
309      * we can carry out the test we need to restore the color of the destination surface.
310      */
311     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
312     ok(rc==DD_OK,"Lock returned: %x\n",rc);
313     lpData = ddsd2.lpSurface;
314     lpData[0] = 0xCCCCCCCC;
315     lpData[1] = 0xCCCCCCCC;
316     lpData[2] = 0xCCCCCCCC;
317     lpData[3] = 0xCCCCCCCC;
318     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
319     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
320
321     IDirectDrawSurface_BltFast(lpDst, 0, 0, lpSrc, NULL, DDBLTFAST_SRCCOLORKEY);
322
323     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
324     ok(rc==DD_OK,"Lock returned: %x\n",rc);
325     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
326     lpData = ddsd2.lpSurface;
327     /* Different behavior on some drivers / windows versions. Some versions ignore the X channel when
328      * color keying, but copy it to the destination surface. Others apply it for color keying, but
329      * do not copy it into the destination surface.
330      */
331     if(lpData[0]==0x00010203) {
332         trace("X channel was not copied into the destination surface\n");
333         ok((lpData[0]==0x00010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0x00FF00FF)&&(lpData[3]==0xCCCCCCCC),
334            "Destination data after blitting is not correct\n");
335     } else {
336         ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC),
337            "Destination data after blitting is not correct\n");
338     }
339     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
340     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
341
342     /* Also test SetColorKey */
343     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
344     ok(DDColorKey.dwColorSpaceLowValue == 0xFF00FF && DDColorKey.dwColorSpaceHighValue == 0xFF00FF,
345        "GetColorKey does not return the colorkey used at surface creation\n");
346
347     DDColorKey.dwColorSpaceLowValue = 0x00FF00;
348     DDColorKey.dwColorSpaceHighValue = 0x00FF00;
349     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
350
351     DDColorKey.dwColorSpaceLowValue = 0;
352     DDColorKey.dwColorSpaceHighValue = 0;
353     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
354     ok(DDColorKey.dwColorSpaceLowValue == 0x00FF00 && DDColorKey.dwColorSpaceHighValue == 0x00FF00,
355        "GetColorKey does not return the colorkey set with SetColorKey\n");
356
357     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0;
358     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0;
359     IDirectDrawSurface_GetSurfaceDesc(lpSrc, &ddsd);
360     ok(ddsd.ddckCKSrcBlt.dwColorSpaceLowValue == 0x00FF00 && ddsd.ddckCKSrcBlt.dwColorSpaceHighValue == 0x00FF00,
361        "GetSurfaceDesc does not return the colorkey set with SetColorKey\n");
362
363     /* Test SetColorKey with dwColorSpaceHighValue < dwColorSpaceLowValue */
364     DDColorKey.dwColorSpaceLowValue = 0x0000FF;
365     DDColorKey.dwColorSpaceHighValue = 0x000000;
366     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
367
368     DDColorKey.dwColorSpaceLowValue = 0;
369     DDColorKey.dwColorSpaceHighValue = 0;
370     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
371     ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF,
372        "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue);
373
374     DDColorKey.dwColorSpaceLowValue = 0x0000FF;
375     DDColorKey.dwColorSpaceHighValue = 0x000001;
376     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
377
378     DDColorKey.dwColorSpaceLowValue = 0;
379     DDColorKey.dwColorSpaceHighValue = 0;
380     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
381     ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF,
382        "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue);
383
384     DDColorKey.dwColorSpaceLowValue = 0x0000FF;
385     DDColorKey.dwColorSpaceHighValue = 0x0000FE;
386     IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
387
388     DDColorKey.dwColorSpaceLowValue = 0;
389     DDColorKey.dwColorSpaceHighValue = 0;
390     IDirectDrawSurface_GetColorKey(lpSrc, DDCKEY_SRCBLT, &DDColorKey);
391     ok(DDColorKey.dwColorSpaceLowValue == 0x0000FF && DDColorKey.dwColorSpaceHighValue == 0x0000FF,
392        "GetColorKey does not return the colorkey set with SetColorKey (%x %x)\n", DDColorKey.dwColorSpaceLowValue, DDColorKey.dwColorSpaceHighValue);
393
394     IDirectDrawSurface_Release(lpSrc);
395     IDirectDrawSurface_Release(lpDst);
396
397     /* start with a new set of surfaces to test the color keying parameters to blit */
398     memset(&ddsd, 0, sizeof(ddsd));
399     ddsd.dwSize = sizeof(ddsd);
400     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
401     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT | DDSD_CKDESTBLT;
402     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
403     ddsd.dwWidth = 800;
404     ddsd.dwHeight = 600;
405     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
406     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
407     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
408     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
409     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
410     ddsd.ddckCKDestBlt.dwColorSpaceLowValue = 0xFF0000;
411     ddsd.ddckCKDestBlt.dwColorSpaceHighValue = 0xFF0000;
412     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00FF00;
413     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00FF00;
414     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL);
415     ok(rc==DD_OK || rc == DDERR_NOCOLORKEYHW,"CreateSurface returned: %x\n",rc);
416     if(FAILED(rc))
417     {
418         skip("Failed to create surface\n");
419         return;
420     }
421
422     /* start with a new set of surfaces to test the color keying parameters to blit */
423     memset(&ddsd, 0, sizeof(ddsd));
424     ddsd.dwSize = sizeof(ddsd);
425     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
426     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT | DDSD_CKDESTBLT;
427     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
428     ddsd.dwWidth = 800;
429     ddsd.dwHeight = 600;
430     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
431     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
432     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
433     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
434     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
435     ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x0000FF;
436     ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x0000FF;
437     ddsd.ddckCKDestBlt.dwColorSpaceLowValue = 0x000000;
438     ddsd.ddckCKDestBlt.dwColorSpaceHighValue = 0x000000;
439     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL);
440     ok(rc==DD_OK || rc == DDERR_NOCOLORKEYHW,"CreateSurface returned: %x\n",rc);
441     if(FAILED(rc))
442     {
443         skip("Failed to create surface\n");
444         IDirectDrawSurface_Release(lpDst);
445         return;
446     }
447
448     memset(&fx, 0, sizeof(fx));
449     fx.dwSize = sizeof(fx);
450     fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x110000;
451     fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x110000;
452     fx.ddckDestColorkey.dwColorSpaceHighValue = 0x001100;
453     fx.ddckDestColorkey.dwColorSpaceLowValue = 0x001100;
454
455     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
456     ok(rc==DD_OK,"Lock returned: %x\n",rc);
457     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
458     lpData = ddsd2.lpSurface;
459     lpData[0] = 0x000000FF; /* Applies to src blt key in src surface */
460     lpData[1] = 0x00000000; /* Applies to dst blt key in src surface */
461     lpData[2] = 0x00FF0000; /* Dst color key in dst surface */
462     lpData[3] = 0x0000FF00; /* Src color key in dst surface */
463     lpData[4] = 0x00001100; /* Src color key in ddbltfx */
464     lpData[5] = 0x00110000; /* Dst color key in ddbltfx */
465     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
466     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
467
468     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
469     ok(rc==DD_OK,"Lock returned: %x\n",rc);
470     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
471     lpData = ddsd2.lpSurface;
472     lpData[0] = 0x55555555;
473     lpData[1] = 0x55555555;
474     lpData[2] = 0x55555555;
475     lpData[3] = 0x55555555;
476     lpData[4] = 0x55555555;
477     lpData[5] = 0x55555555;
478     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
479     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
480
481     /* Test a blit without keying */
482     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, 0, &fx);
483     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
484
485     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
486     ok(rc==DD_OK,"Lock returned: %x\n",rc);
487     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
488     lpData = ddsd2.lpSurface;
489     /* Should have copied src data unmodified to dst */
490     ok(lpData[0] == 0x000000FF &&
491        lpData[1] == 0x00000000 &&
492        lpData[2] == 0x00FF0000 &&
493        lpData[3] == 0x0000FF00 &&
494        lpData[4] == 0x00001100 &&
495        lpData[5] == 0x00110000, "Surface data after unkeyed blit does not match\n");
496
497     lpData[0] = 0x55555555;
498     lpData[1] = 0x55555555;
499     lpData[2] = 0x55555555;
500     lpData[3] = 0x55555555;
501     lpData[4] = 0x55555555;
502     lpData[5] = 0x55555555;
503     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
504     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
505
506     /* Src key */
507     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, &fx);
508     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
509
510     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
511     ok(rc==DD_OK,"Lock returned: %x\n",rc);
512     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
513     lpData = ddsd2.lpSurface;
514
515     ok(lpData[0] == 0x55555555 && /* Here the src key applied */
516        lpData[1] == 0x00000000 &&
517        lpData[2] == 0x00FF0000 &&
518        lpData[3] == 0x0000FF00 &&
519        lpData[4] == 0x00001100 &&
520        lpData[5] == 0x00110000, "Surface data after srckey blit does not match\n");
521
522     lpData[0] = 0x55555555;
523     lpData[1] = 0x55555555;
524     lpData[2] = 0x55555555;
525     lpData[3] = 0x55555555;
526     lpData[4] = 0x55555555;
527     lpData[5] = 0x55555555;
528     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
529     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
530
531     /* Src override */
532     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
533     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
534
535     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
536     ok(rc==DD_OK,"Lock returned: %x\n",rc);
537     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
538     lpData = ddsd2.lpSurface;
539
540     ok(lpData[0] == 0x000000FF &&
541        lpData[1] == 0x00000000 &&
542        lpData[2] == 0x00FF0000 &&
543        lpData[3] == 0x0000FF00 &&
544        lpData[4] == 0x00001100 &&
545        lpData[5] == 0x55555555, /* Override key applies here */
546        "Surface data after src override key blit does not match\n");
547
548     lpData[0] = 0x55555555;
549     lpData[1] = 0x55555555;
550     lpData[2] = 0x55555555;
551     lpData[3] = 0x55555555;
552     lpData[4] = 0x55555555;
553     lpData[5] = 0x55555555;
554     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
555     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
556
557     /* Src override AND src key. That is not supposed to work */
558     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
559     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
560
561     /* Verify that the destination is unchanged */
562     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
563     ok(rc==DD_OK,"Lock returned: %x\n",rc);
564     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
565     lpData = ddsd2.lpSurface;
566
567     ok(lpData[0] == 0x55555555 &&
568        lpData[1] == 0x55555555 &&
569        lpData[2] == 0x55555555 &&
570        lpData[3] == 0x55555555 &&
571        lpData[4] == 0x55555555 &&
572        lpData[5] == 0x55555555, /* Override key applies here */
573        "Surface data after src key blit with override does not match\n");
574
575     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
576     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
577     lpData[2] = 0x00001100; /* Dest key in override */
578     lpData[3] = 0x00001100; /* Dest key in override */
579     lpData[4] = 0x00000000; /* Dest key in src surface */
580     lpData[5] = 0x00000000; /* Dest key in src surface */
581     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
582     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
583
584     /* Dest key blit */
585     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST, &fx);
586     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
587
588     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
589     ok(rc==DD_OK,"Lock returned: %x\n",rc);
590     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
591     lpData = ddsd2.lpSurface;
592
593     /* DirectDraw uses the dest blit key from the SOURCE surface ! */
594     ok(lpData[0] == 0x00ff0000 &&
595        lpData[1] == 0x00ff0000 &&
596        lpData[2] == 0x00001100 &&
597        lpData[3] == 0x00001100 &&
598        lpData[4] == 0x00001100 && /* Key applies here */
599        lpData[5] == 0x00110000,   /* Key applies here */
600        "Surface data after dest key blit does not match\n");
601
602     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
603     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
604     lpData[2] = 0x00001100; /* Dest key in override */
605     lpData[3] = 0x00001100; /* Dest key in override */
606     lpData[4] = 0x00000000; /* Dest key in src surface */
607     lpData[5] = 0x00000000; /* Dest key in src surface */
608     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
609     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
610
611     /* Dest override key blit */
612     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
613     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
614
615     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
616     ok(rc==DD_OK,"Lock returned: %x\n",rc);
617     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
618     lpData = ddsd2.lpSurface;
619
620     ok(lpData[0] == 0x00FF0000 &&
621        lpData[1] == 0x00FF0000 &&
622        lpData[2] == 0x00FF0000 && /* Key applies here */
623        lpData[3] == 0x0000FF00 && /* Key applies here */
624        lpData[4] == 0x00000000 &&
625        lpData[5] == 0x00000000,
626        "Surface data after dest key override blit does not match\n");
627
628     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
629     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
630     lpData[2] = 0x00001100; /* Dest key in override */
631     lpData[3] = 0x00001100; /* Dest key in override */
632     lpData[4] = 0x00000000; /* Dest key in src surface */
633     lpData[5] = 0x00000000; /* Dest key in src surface */
634     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
635     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
636
637     /* Dest override key blit. Supposed to fail too */
638     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
639     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
640
641     /* Check for unchanged data */
642     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
643     ok(rc==DD_OK,"Lock returned: %x\n",rc);
644     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
645     lpData = ddsd2.lpSurface;
646
647     ok(lpData[0] == 0x00FF0000 &&
648        lpData[1] == 0x00FF0000 &&
649        lpData[2] == 0x00001100 && /* Key applies here */
650        lpData[3] == 0x00001100 && /* Key applies here */
651        lpData[4] == 0x00000000 &&
652        lpData[5] == 0x00000000,
653        "Surface data with dest key and dest override does not match\n");
654
655     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
656     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
657     lpData[2] = 0x00001100; /* Dest key in override */
658     lpData[3] = 0x00001100; /* Dest key in override */
659     lpData[4] = 0x00000000; /* Dest key in src surface */
660     lpData[5] = 0x00000000; /* Dest key in src surface */
661     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
662     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
663
664     /* Modify the source data a bit to give some more conclusive results */
665     rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
666     ok(rc==DD_OK,"Lock returned: %x\n",rc);
667     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
668     lpData = ddsd2.lpSurface;
669     lpData[5] = 0x000000FF; /* Applies to src blt key in src surface */
670     rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
671     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
672
673     /* Source and destination key */
674     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
675     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
676
677     rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
678     ok(rc==DD_OK,"Lock returned: %x\n",rc);
679     ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n");
680     lpData = ddsd2.lpSurface;
681
682     ok(lpData[0] == 0x00FF0000 && /* Masked by Destination key */
683        lpData[1] == 0x00FF0000 && /* Masked by Destination key */
684        lpData[2] == 0x00001100 && /* Masked by Destination key */
685        lpData[3] == 0x00001100 && /* Masked by Destination key */
686        lpData[4] == 0x00001100 && /* Allowed by destination key, not masked by source key */
687        lpData[5] == 0x00000000,   /* Allowed by dst key, but masked by source key */
688        "Surface data with src key and dest key blit does not match\n");
689
690     lpData[0] = 0x00FF0000; /* Dest key in dst surface */
691     lpData[1] = 0x00FF0000; /* Dest key in dst surface */
692     lpData[2] = 0x00001100; /* Dest key in override */
693     lpData[3] = 0x00001100; /* Dest key in override */
694     lpData[4] = 0x00000000; /* Dest key in src surface */
695     lpData[5] = 0x00000000; /* Dest key in src surface */
696     rc = IDirectDrawSurface_Unlock(lpDst, NULL);
697     ok(rc==DD_OK,"Unlock returned: %x\n",rc);
698
699     /* Override keys without ddbltfx parameter fail */
700     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
701     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
702     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
703     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
704
705     /* Try blitting without keys in the source surface*/
706     rc = IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, NULL);
707     ok(rc == DD_OK, "SetColorKey returned %x\n", rc);
708     rc = IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_DESTBLT, NULL);
709     ok(rc == DD_OK, "SetColorKey returned %x\n", rc);
710
711     /* That fails now. Do not bother to check that the data is unmodified */
712     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, &fx);
713     ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
714
715     /* Dest key blit still works. Which key is used this time??? */
716     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST, &fx);
717     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
718
719     /* With correctly passed override keys no key in the surface is needed.
720      * Again, the result was checked before, no need to do that again
721      */
722     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
723     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
724     rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
725     ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
726
727     IDirectDrawSurface_Release(lpSrc);
728     IDirectDrawSurface_Release(lpDst);
729 }
730
731 static void QueryInterface(void)
732 {
733     LPDIRECTDRAWSURFACE dsurface;
734     DDSURFACEDESC surface;
735     LPVOID object;
736     HRESULT ret;
737
738     /* Create a surface */
739     ZeroMemory(&surface, sizeof(surface));
740     surface.dwSize = sizeof(surface);
741     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
742     surface.dwHeight = 10;
743     surface.dwWidth = 10;
744     ret = IDirectDraw_CreateSurface(lpDD, &surface, &dsurface, NULL);
745     if(ret != DD_OK)
746     {
747         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
748         return;
749     }
750
751     /* Call IUnknown::QueryInterface */
752     ret = IDirectDrawSurface_QueryInterface(dsurface, 0, &object);
753     ok(ret == DDERR_INVALIDPARAMS, "IDirectDrawSurface::QueryInterface returned %x\n", ret);
754
755     IDirectDrawSurface_Release(dsurface);
756 }
757
758 /* The following tests test which interface is returned by IDirectDrawSurfaceX::GetDDInterface.
759  * It uses refcounts to test that and compares the interface addresses. Partially fits here, and
760  * partially in the refcount test
761  */
762
763 static ULONG getref(IUnknown *iface)
764 {
765     IUnknown_AddRef(iface);
766     return IUnknown_Release(iface);
767 }
768
769 static void GetDDInterface_1(void)
770 {
771     LPDIRECTDRAWSURFACE dsurface;
772     LPDIRECTDRAWSURFACE2 dsurface2;
773     DDSURFACEDESC surface;
774     HRESULT ret;
775     IDirectDraw2 *dd2;
776     IDirectDraw4 *dd4;
777     IDirectDraw7 *dd7;
778     ULONG ref1, ref2, ref4, ref7;
779     void *dd;
780
781     /* Create a surface */
782     ZeroMemory(&surface, sizeof(surface));
783     surface.dwSize = sizeof(surface);
784     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
785     surface.dwHeight = 10;
786     surface.dwWidth = 10;
787     ret = IDirectDraw_CreateSurface(lpDD, &surface, &dsurface, NULL);
788     if(ret != DD_OK)
789     {
790         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
791         return;
792     }
793     ret = IDirectDrawSurface_QueryInterface(dsurface, &IID_IDirectDrawSurface2, (void **) &dsurface2);
794     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
795     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
796     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
797     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
798     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
799     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
800     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
801
802     ref1 = getref((IUnknown *) lpDD);
803     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
804     ref2 = getref((IUnknown *) dd2);
805     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
806     ref4 = getref((IUnknown *) dd4);
807     ok(ref4 == 1, "IDirectDraw4 refcount is %d\n", ref4);
808     ref7 = getref((IUnknown *) dd7);
809     ok(ref7 == 1, "IDirectDraw7 refcount is %d\n", ref7);
810
811
812     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, &dd);
813     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
814     ok(getref((IUnknown *) lpDD) == ref1 + 1, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
815     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
816     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
817     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
818
819     ok(dd == lpDD, "Returned interface pointer is not equal to the creation interface\n");
820     IUnknown_Release((IUnknown *) dd);
821
822     /* try a NULL pointer */
823     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, NULL);
824     ok(ret == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
825
826     IDirectDraw_Release(dd2);
827     IDirectDraw_Release(dd4);
828     IDirectDraw_Release(dd7);
829     IDirectDrawSurface2_Release(dsurface2);
830     IDirectDrawSurface_Release(dsurface);
831 }
832
833 static void GetDDInterface_2(void)
834 {
835     LPDIRECTDRAWSURFACE dsurface;
836     LPDIRECTDRAWSURFACE2 dsurface2;
837     DDSURFACEDESC surface;
838     HRESULT ret;
839     IDirectDraw2 *dd2;
840     IDirectDraw4 *dd4;
841     IDirectDraw7 *dd7;
842     ULONG ref1, ref2, ref4, ref7;
843     void *dd;
844
845     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
846     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
847     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
848     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
849     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
850     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
851
852     /* Create a surface */
853     ZeroMemory(&surface, sizeof(surface));
854     surface.dwSize = sizeof(surface);
855     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
856     surface.dwHeight = 10;
857     surface.dwWidth = 10;
858     ret = IDirectDraw2_CreateSurface(dd2, &surface, &dsurface, NULL);
859     if(ret != DD_OK)
860     {
861         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
862         return;
863     }
864     ret = IDirectDrawSurface_QueryInterface(dsurface, &IID_IDirectDrawSurface2, (void **) &dsurface2);
865     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
866
867     ref1 = getref((IUnknown *) lpDD);
868     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
869     ref2 = getref((IUnknown *) dd2);
870     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
871     ref4 = getref((IUnknown *) dd4);
872     ok(ref4 == 1, "IDirectDraw4 refcount is %d\n", ref4);
873     ref7 = getref((IUnknown *) dd7);
874     ok(ref7 == 1, "IDirectDraw7 refcount is %d\n", ref7);
875
876
877     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, &dd);
878     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
879     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
880     ok(getref((IUnknown *) dd2) == ref2 + 1, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
881     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
882     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
883
884     ok(dd == dd2, "Returned interface pointer is not equal to the creation interface\n");
885     IUnknown_Release((IUnknown *) dd);
886
887     IDirectDraw_Release(dd2);
888     IDirectDraw_Release(dd4);
889     IDirectDraw_Release(dd7);
890     IDirectDrawSurface2_Release(dsurface2);
891     IDirectDrawSurface_Release(dsurface);
892 }
893
894 static void GetDDInterface_4(void)
895 {
896     LPDIRECTDRAWSURFACE2 dsurface2;
897     LPDIRECTDRAWSURFACE4 dsurface4;
898     DDSURFACEDESC2 surface;
899     HRESULT ret;
900     IDirectDraw2 *dd2;
901     IDirectDraw4 *dd4;
902     IDirectDraw7 *dd7;
903     ULONG ref1, ref2, ref4, ref7;
904     void *dd;
905
906     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
907     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
908     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
909     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
910     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
911     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
912
913     /* Create a surface */
914     ZeroMemory(&surface, sizeof(surface));
915     surface.dwSize = sizeof(surface);
916     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
917     surface.dwHeight = 10;
918     surface.dwWidth = 10;
919     ret = IDirectDraw4_CreateSurface(dd4, &surface, &dsurface4, NULL);
920     if(ret != DD_OK)
921     {
922         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
923         return;
924     }
925     ret = IDirectDrawSurface4_QueryInterface(dsurface4, &IID_IDirectDrawSurface2, (void **) &dsurface2);
926     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
927
928     ref1 = getref((IUnknown *) lpDD);
929     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
930     ref2 = getref((IUnknown *) dd2);
931     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
932     ref4 = getref((IUnknown *) dd4);
933     ok(ref4 == 2, "IDirectDraw4 refcount is %d\n", ref4);
934     ref7 = getref((IUnknown *) dd7);
935     ok(ref7 == 1, "IDirectDraw7 refcount is %d\n", ref7);
936
937     ret = IDirectDrawSurface4_GetDDInterface(dsurface4, &dd);
938     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
939     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
940     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
941     ok(getref((IUnknown *) dd4) == ref4 + 1, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
942     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
943
944     ok(dd == dd4, "Returned interface pointer is not equal to the creation interface\n");
945     IUnknown_Release((IUnknown *) dd);
946
947     /* Now test what happens if we QI the surface for some other version - It should still return the creation interface */
948     ret = IDirectDrawSurface2_GetDDInterface(dsurface2, &dd);
949     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
950     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
951     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
952     ok(getref((IUnknown *) dd4) == ref4 + 1, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
953     ok(getref((IUnknown *) dd7) == ref7 + 0, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
954
955     ok(dd == dd4, "Returned interface pointer is not equal to the creation interface\n");
956     IUnknown_Release((IUnknown *) dd);
957
958     IDirectDraw_Release(dd2);
959     IDirectDraw_Release(dd4);
960     IDirectDraw_Release(dd7);
961     IDirectDrawSurface4_Release(dsurface4);
962     IDirectDrawSurface2_Release(dsurface2);
963 }
964
965 static void GetDDInterface_7(void)
966 {
967     LPDIRECTDRAWSURFACE4 dsurface4;
968     LPDIRECTDRAWSURFACE7 dsurface7;
969     DDSURFACEDESC2 surface;
970     HRESULT ret;
971     IDirectDraw2 *dd2;
972     IDirectDraw4 *dd4;
973     IDirectDraw7 *dd7;
974     ULONG ref1, ref2, ref4, ref7;
975     void *dd;
976
977     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
978     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
979     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
980     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
981     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
982     ok(ret == DD_OK, "IDirectDraw7_QueryInterface returned %08x\n", ret);
983
984     /* Create a surface */
985     ZeroMemory(&surface, sizeof(surface));
986     surface.dwSize = sizeof(surface);
987     surface.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
988     surface.dwHeight = 10;
989     surface.dwWidth = 10;
990     ret = IDirectDraw7_CreateSurface(dd7, &surface, &dsurface7, NULL);
991     if(ret != DD_OK)
992     {
993         ok(FALSE, "IDirectDraw::CreateSurface failed with error %x\n", ret);
994         return;
995     }
996     ret = IDirectDrawSurface7_QueryInterface(dsurface7, &IID_IDirectDrawSurface4, (void **) &dsurface4);
997     ok(ret == DD_OK, "IDirectDrawSurface_QueryInterface returned %08x\n", ret);
998
999     ref1 = getref((IUnknown *) lpDD);
1000     ok(ref1 == 1, "IDirectDraw refcount is %d\n", ref1);
1001     ref2 = getref((IUnknown *) dd2);
1002     ok(ref2 == 1, "IDirectDraw2 refcount is %d\n", ref2);
1003     ref4 = getref((IUnknown *) dd4);
1004     ok(ref4 == 1, "IDirectDraw4 refcount is %d\n", ref4);
1005     ref7 = getref((IUnknown *) dd7);
1006     ok(ref7 == 2, "IDirectDraw7 refcount is %d\n", ref7);
1007
1008     ret = IDirectDrawSurface7_GetDDInterface(dsurface7, &dd);
1009     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
1010     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
1011     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
1012     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
1013     ok(getref((IUnknown *) dd7) == ref7 + 1, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
1014
1015     ok(dd == dd7, "Returned interface pointer is not equal to the creation interface\n");
1016     IUnknown_Release((IUnknown *) dd);
1017
1018     /* Now test what happens if we QI the surface for some other version - It should still return the creation interface */
1019     ret = IDirectDrawSurface4_GetDDInterface(dsurface4, &dd);
1020     ok(ret == DD_OK, "IDirectDrawSurface7_GetDDInterface returned %08x\n", ret);
1021     ok(getref((IUnknown *) lpDD) == ref1 + 0, "IDirectDraw refcount was increased by %d\n", getref((IUnknown *) lpDD) - ref1);
1022     ok(getref((IUnknown *) dd2) == ref2 + 0, "IDirectDraw2 refcount was increased by %d\n", getref((IUnknown *) dd2) - ref2);
1023     ok(getref((IUnknown *) dd4) == ref4 + 0, "IDirectDraw4 refcount was increased by %d\n", getref((IUnknown *) dd4) - ref4);
1024     ok(getref((IUnknown *) dd7) == ref7 + 1, "IDirectDraw7 refcount was increased by %d\n", getref((IUnknown *) dd7) - ref7);
1025
1026     ok(dd == dd7, "Returned interface pointer is not equal to the creation interface\n");
1027     IUnknown_Release((IUnknown *) dd);
1028
1029     IDirectDraw_Release(dd2);
1030     IDirectDraw_Release(dd4);
1031     IDirectDraw_Release(dd7);
1032     IDirectDrawSurface4_Release(dsurface4);
1033     IDirectDrawSurface7_Release(dsurface7);
1034 }
1035
1036 static ULONG getRefcount(IUnknown *iface)
1037 {
1038     IUnknown_AddRef(iface);
1039     return IUnknown_Release(iface);
1040 }
1041
1042 static void IFaceRefCount(void)
1043 {
1044     LPDIRECTDRAWSURFACE surf;
1045     DDSURFACEDESC surface;
1046     HRESULT ret;
1047     IDirectDrawSurface2 *surf2;
1048     IDirectDrawSurface2 *surf2a;
1049     IDirectDrawSurface4 *surf4;
1050     IDirectDrawSurface7 *surf7a;
1051     IDirectDrawSurface7 *surf7b;
1052     IDirect3DTexture* tex;
1053     IDirect3DTexture2* tex2;
1054     IDirectDrawGammaControl* gamma;
1055     ULONG ref;
1056
1057     /* Create a surface */
1058     ZeroMemory(&surface, sizeof(surface));
1059     surface.dwSize = sizeof(surface);
1060     surface.dwFlags = DDSD_CAPS;
1061     surface.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1062     ret = IDirectDraw_CreateSurface(lpDD, &surface, &surf, NULL);
1063
1064     if (ret != DD_OK)
1065     {
1066         ok(FALSE, "Could not create surface, skipping test\n");
1067         return;
1068     }
1069
1070     ref = getRefcount((IUnknown *) surf);
1071     ok(ref == 1, "Refcount is %u, expected 1\n", ref); /* Check the ref count is one */
1072
1073     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2);
1074     ref = getRefcount((IUnknown *) surf);
1075     todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref); /* Check the ref count is one */
1076     ref = getRefcount((IUnknown *) surf2);
1077     todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref); /* This should also be one */
1078
1079     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2a);
1080     ref = getRefcount((IUnknown *) surf2);
1081     todo_wine ok(ref == 2, "Refcount is %u, expected 2\n", ref);   /* Surf2's refcount should be 2 now, but surf should be 1 */
1082     ref = getRefcount((IUnknown *) surf);
1083     todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1084
1085     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface4, (void **) &surf4);
1086     ref = getRefcount((IUnknown *) surf4);
1087     todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1088
1089     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface7, (void **) &surf7a);
1090     ref = getRefcount((IUnknown *) surf7a);
1091     todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1092
1093     IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface7, (void **) &surf7b);
1094     ref = getRefcount((IUnknown *) surf7b);
1095     todo_wine ok(ref == 2, "Refcount is %u, expected 2\n", ref);
1096
1097     /* IDirect3DTexture interface (unlike the others) alters the original IDirectDrawSurface ref count */
1098     ret = IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DTexture, (void **) &tex);
1099     if (SUCCEEDED(ret))
1100     {
1101         ref = getRefcount((IUnknown *) tex);
1102         todo_wine ok(ref == 2, "Refcount is %u, expected 2\n", ref);
1103         ref = getRefcount((IUnknown *) surf);
1104         todo_wine ok(ref == 2, "Refcount is %u, expected 2\n", ref);
1105
1106         IDirectDrawSurface_QueryInterface(surf, &IID_IDirect3DTexture2, (void **) &tex2);
1107         ref = getRefcount((IUnknown *) tex);
1108         todo_wine ok(ref == 3, "Refcount is %u, expected 3\n", ref);
1109         ref = getRefcount((IUnknown *) tex2);
1110         todo_wine ok(ref == 3, "Refcount is %u, expected 3\n", ref);
1111         ref = getRefcount((IUnknown *) surf);
1112         todo_wine ok(ref == 3, "Refcount is %u, expected 3\n", ref);
1113
1114         IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawGammaControl, (void **) &gamma);
1115         ref = getRefcount((IUnknown *) gamma);
1116         todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1117
1118         ref = IDirect3DTexture2_Release(tex2); /* Release the texture */
1119         todo_wine ok(ref == 2, "Refcount is %u, expected 2\n", ref);
1120         ref = getRefcount((IUnknown *) surf);
1121         todo_wine ok(ref == 2, "Refcount is %u, expected 2\n", ref);
1122
1123         ref = IDirect3DTexture_Release(tex); /* Release the texture */
1124         todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1125         ref = getRefcount((IUnknown *) surf);
1126         todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1127
1128         ref = IDirectDrawGammaControl_Release(gamma); /* Release the gamma control */
1129         todo_wine ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1130     }
1131
1132     ref = IDirectDrawSurface2_Release(surf2); /* Release one of the 2 surf2 interfaces */
1133     todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1134
1135     ref = IDirectDrawSurface2_Release(surf2a); /* Release the other */
1136     todo_wine ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1137
1138     ref = IDirectDrawSurface4_Release(surf4);
1139     todo_wine ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1140
1141     ref = IDirectDrawSurface7_Release(surf7a);
1142     todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref);
1143
1144     ref = IDirectDrawSurface7_Release(surf7b);
1145     todo_wine ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1146
1147     ref = IDirectDrawSurface_Release(surf);
1148     ok(ref == 0, "Refcount is %u, expected 0\n", ref);
1149 }
1150
1151 #define MAXEXPECTED 8  /* Can match up to 8 expected surfaces */
1152 struct enumstruct
1153 {
1154     IDirectDrawSurface *expected[MAXEXPECTED];
1155     UINT count;
1156 };
1157
1158 static HRESULT WINAPI enumCB(IDirectDrawSurface *surf, DDSURFACEDESC *desc, void *ctx)
1159 {
1160     int i;
1161     BOOL found = FALSE;
1162
1163     for(i = 0; i < MAXEXPECTED; i++)
1164     {
1165         if(((struct enumstruct *)ctx)->expected[i] == surf) found = TRUE;
1166     }
1167
1168     ok(found, "Unexpected surface %p enumerated\n", surf);
1169     ((struct enumstruct *)ctx)->count++;
1170     IDirectDrawSurface_Release(surf);
1171     return DDENUMRET_OK;
1172 }
1173
1174 static void EnumTest(void)
1175 {
1176     HRESULT rc;
1177     DDSURFACEDESC ddsd;
1178     IDirectDrawSurface *surface;
1179     struct enumstruct ctx;
1180
1181     ddsd.dwSize = sizeof(ddsd);
1182     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
1183     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1184     U2(ddsd).dwMipMapCount = 3;
1185     ddsd.dwWidth = 32;
1186     ddsd.dwHeight = 32;
1187     rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
1188     ok(rc==DD_OK,"CreateSurface returned: %x\n",rc);
1189
1190     memset(&ctx, 0, sizeof(ctx));
1191     ctx.expected[0] = surface;
1192     rc = IDirectDrawSurface_GetAttachedSurface(ctx.expected[0], &ddsd.ddsCaps, &ctx.expected[1]);
1193     ok(rc == DD_OK, "GetAttachedSurface returned %08x\n", rc);
1194     rc = IDirectDrawSurface_GetAttachedSurface(ctx.expected[1], &ddsd.ddsCaps, &ctx.expected[2]);
1195     ok(rc == DD_OK, "GetAttachedSurface returned %08x\n", rc);
1196     rc = IDirectDrawSurface_GetAttachedSurface(ctx.expected[2], &ddsd.ddsCaps, &ctx.expected[3]);
1197     ok(rc == DDERR_NOTFOUND, "GetAttachedSurface returned %08x\n", rc);
1198     ok(!ctx.expected[3], "expected NULL pointer\n");
1199     ctx.count = 0;
1200
1201     rc = IDirectDraw_EnumSurfaces(lpDD, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, &ddsd, &ctx, enumCB);
1202     ok(rc == DD_OK, "IDirectDraw_EnumSurfaces returned %08x\n", rc);
1203     ok(ctx.count == 3, "%d surfaces enumerated, expected 3\n", ctx.count);
1204
1205     IDirectDrawSurface_Release(ctx.expected[2]);
1206     IDirectDrawSurface_Release(ctx.expected[1]);
1207     IDirectDrawSurface_Release(surface);
1208 }
1209
1210 static HRESULT WINAPI SurfaceCounter(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1211 {
1212     UINT *num = context;
1213     (*num)++;
1214     IDirectDrawSurface_Release(surface);
1215     return DDENUMRET_OK;
1216 }
1217
1218 static void AttachmentTest7(void)
1219 {
1220     HRESULT hr;
1221     IDirectDraw7 *dd7;
1222     IDirectDrawSurface7 *surface1, *surface2, *surface3, *surface4;
1223     DDSURFACEDESC2 ddsd, ddsd2;
1224     UINT num;
1225     DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, 0}, caps2 = {DDSCAPS_BACKBUFFER,0,0,0};
1226     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1227
1228     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
1229     ok(hr == DD_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
1230
1231     memset(&ddsd, 0, sizeof(ddsd));
1232     ddsd.dwSize = sizeof(ddsd);
1233     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
1234     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1235     U2(ddsd).dwMipMapCount = 3; /* Will create 128x128, 64x64, 32x32 */
1236     ddsd.dwWidth = 128;
1237     ddsd.dwHeight = 128;
1238     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1239     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1240
1241     /* ROOT */
1242     num = 0;
1243     IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &num, SurfaceCounter);
1244     ok(num == 1, "Mipmap root has %d surfaces attached, expected 1\n", num);
1245     /* DONE ROOT */
1246
1247     /* LEVEL 1 */
1248     hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
1249     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1250     num = 0;
1251     IDirectDrawSurface7_EnumAttachedSurfaces(surface2, &num, SurfaceCounter);
1252     ok(num == 1, "First mip level has %d surfaces attached, expected 1\n", num);
1253     /* DONE LEVEL 1 */
1254
1255     /* LEVEL 2 */
1256     hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
1257     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1258     IDirectDrawSurface7_Release(surface2);
1259     num = 0;
1260     IDirectDrawSurface7_EnumAttachedSurfaces(surface3, &num, SurfaceCounter);
1261     ok(num == 0, "Second mip level has %d surfaces attached, expected 1\n", num);
1262     /* Done level 2 */
1263     /* Mip level 3 is still needed */
1264     hr = IDirectDrawSurface7_GetAttachedSurface(surface3, &caps, &surface4);
1265     ok(hr == DDERR_NOTFOUND, "GetAttachedSurface returned %08x\n", hr);
1266     ok(!surface4, "expected NULL pointer\n");
1267
1268     /* Try to attach a 16x16 miplevel - Should not work as far I can see */
1269     memset(&ddsd, 0, sizeof(ddsd));
1270     ddsd.dwSize = sizeof(ddsd);
1271     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1272     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1273     ddsd.dwWidth = 16;
1274     ddsd.dwHeight = 16;
1275     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1276     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1277
1278     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1279     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 128x128 texture root returned %08x\n", hr);
1280     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
1281     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 texture returned %08x\n", hr);
1282     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
1283     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 32x32 texture mip level returned %08x\n", hr);
1284     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
1285     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 surface returned %08x\n", hr);
1286
1287     IDirectDrawSurface7_Release(surface2);
1288
1289     memset(&ddsd, 0, sizeof(ddsd));
1290     ddsd.dwSize = sizeof(ddsd);
1291     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1292     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
1293     ddsd.dwWidth = 16;
1294     ddsd.dwHeight = 16;
1295     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1296     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1297
1298     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1299     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr);
1300     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
1301     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr);
1302     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface2);
1303     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr);
1304     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
1305     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 offscreen plain surface returned %08x\n", hr);
1306
1307     IDirectDrawSurface7_Release(surface3);
1308     IDirectDrawSurface7_Release(surface2);
1309     IDirectDrawSurface7_Release(surface1);
1310
1311     hr = IDirectDraw7_SetCooperativeLevel(dd7, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1312     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1313
1314     memset(&ddsd, 0, sizeof(ddsd));
1315     ddsd.dwSize = sizeof(ddsd);
1316     ddsd.dwFlags = DDSD_BACKBUFFERCOUNT | DDSD_CAPS;
1317     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
1318     ddsd.dwBackBufferCount = 2;
1319     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1320     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1321
1322     /* backbuffer surfaces must not have dwBackBufferCount set */
1323     ddsd2.dwSize = sizeof(ddsd2);
1324     hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps2, &surface2);
1325     ok(hr==DD_OK,"GetAttachedSurface returned: %x\n", hr);
1326     hr = IDirectDrawSurface7_GetSurfaceDesc(surface2, &ddsd2);
1327     ok(hr==DD_OK,"GetSurfaceDesc returned: %x\n", hr);
1328     ok(ddsd2.dwBackBufferCount==0,"backbuffer surface has dwBackBufferCount==%u\n", ddsd2.dwBackBufferCount);
1329
1330     num = 0;
1331     IDirectDrawSurface7_EnumAttachedSurfaces(surface1, &num, SurfaceCounter);
1332     ok(num == 1, "Primary surface has %d surfaces attached, expected 1\n", num);
1333     IDirectDrawSurface7_Release(surface1);
1334
1335     /* Those are some invalid descriptions, no need to test attachments with them */
1336     memset(&ddsd, 0, sizeof(ddsd));
1337     ddsd.dwSize = sizeof(ddsd);
1338     ddsd.dwFlags = DDSD_CAPS;
1339     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER;
1340     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1341     ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr);
1342     memset(&ddsd, 0, sizeof(ddsd));
1343     ddsd.dwSize = sizeof(ddsd);
1344     ddsd.dwFlags = DDSD_CAPS;
1345     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER;
1346     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1347     ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr);
1348
1349     /* Try a single primary and two offscreen plain surfaces */
1350     memset(&ddsd, 0, sizeof(ddsd));
1351     ddsd.dwSize = sizeof(ddsd);
1352     ddsd.dwFlags = DDSD_CAPS;
1353     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1354     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL);
1355     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1356
1357     memset(&ddsd, 0, sizeof(ddsd));
1358     ddsd.dwSize = sizeof(ddsd);
1359     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1360     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1361     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1362     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1363     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface2, NULL);
1364     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1365
1366     memset(&ddsd, 0, sizeof(ddsd));
1367     ddsd.dwSize = sizeof(ddsd);
1368     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1369     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1370     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1371     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1372     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface3, NULL);
1373     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1374
1375     /* This one has a different size */
1376     memset(&ddsd, 0, sizeof(ddsd));
1377     ddsd.dwSize = sizeof(ddsd);
1378     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1379     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1380     ddsd.dwWidth = 128;
1381     ddsd.dwHeight = 128;
1382     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface4, NULL);
1383     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1384
1385     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface2);
1386     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer returned %08x\n", hr);
1387     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface1);
1388     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface returned %08x\n", hr);
1389     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface3);
1390     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to another offscreen plain surface returned %08x\n", hr);
1391     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
1392     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer of different size returned %08x\n", hr);
1393     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
1394     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface of different size returned %08x\n", hr);
1395
1396     IDirectDrawSurface7_Release(surface4);
1397     IDirectDrawSurface7_Release(surface3);
1398     IDirectDrawSurface7_Release(surface2);
1399     IDirectDrawSurface7_Release(surface1);
1400
1401     hr =IDirectDraw7_SetCooperativeLevel(dd7, NULL, DDSCL_NORMAL);
1402     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1403     IDirectDraw7_Release(dd7);
1404 }
1405
1406 static void AttachmentTest(void)
1407 {
1408     HRESULT hr;
1409     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
1410     DDSURFACEDESC ddsd;
1411     DDSCAPS caps = {DDSCAPS_TEXTURE};
1412     BOOL refrast = FALSE;
1413     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1414
1415     memset(&ddsd, 0, sizeof(ddsd));
1416     ddsd.dwSize = sizeof(ddsd);
1417     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT;
1418     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
1419     U2(ddsd).dwMipMapCount = 3; /* Will create 128x128, 64x64, 32x32 */
1420     ddsd.dwWidth = 128;
1421     ddsd.dwHeight = 128;
1422     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface1, NULL);
1423     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1424
1425     hr = IDirectDrawSurface7_GetAttachedSurface(surface1, &caps, &surface2);
1426     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1427     hr = IDirectDrawSurface7_GetAttachedSurface(surface2, &caps, &surface3);
1428     ok(hr == DD_OK, "GetAttachedSurface returned %08x\n", hr);
1429
1430     /* Try to attach a 16x16 miplevel - Should not work as far I can see */
1431     memset(&ddsd, 0, sizeof(ddsd));
1432     ddsd.dwSize = sizeof(ddsd);
1433     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1434     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1435     ddsd.dwWidth = 16;
1436     ddsd.dwHeight = 16;
1437     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL);
1438     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1439
1440     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4);
1441     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 128x128 texture root returned %08x\n", hr);
1442     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);
1443     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 texture returned %08x\n", hr);
1444     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);
1445     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 32x32 texture mip level returned %08x\n", hr);
1446     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
1447     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 surface returned %08x\n", hr);
1448     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);
1449     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 surface to a 64x64 texture sublevel returned %08x\n", hr);
1450     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
1451     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 64x64 texture sublevel to a 16x16 texture returned %08x\n", hr);
1452
1453     IDirectDrawSurface7_Release(surface4);
1454
1455     memset(&ddsd, 0, sizeof(ddsd));
1456     ddsd.dwSize = sizeof(ddsd);
1457     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1458     ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
1459     ddsd.dwWidth = 16;
1460     ddsd.dwHeight = 16;
1461     hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface4, NULL);
1462     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1463
1464     if (SUCCEEDED(IDirectDrawSurface7_AddAttachedSurface(surface1, surface4)))
1465     {
1466         IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface4);
1467         refrast = TRUE;
1468     }
1469
1470     hr = IDirectDrawSurface7_AddAttachedSurface(surface1, surface4); /* Succeeds on refrast */
1471     if (refrast)
1472         ok(hr == S_OK, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr);
1473     else
1474         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 128x128 texture root returned %08x\n", hr);
1475     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface4);
1476
1477     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface1);  /* Succeeds on refrast */
1478     if (refrast)
1479         ok(hr == S_OK, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr);
1480     else
1481         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 128x128 texture root to a 16x16 offscreen plain surface returned %08x\n", hr);
1482     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface1, 0, surface1);
1483
1484     hr = IDirectDrawSurface7_AddAttachedSurface(surface3, surface4);  /* Succeeds on refrast */
1485     if (refrast)
1486         ok(hr == S_OK, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr);
1487     else
1488         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 32x32 texture mip level returned %08x\n", hr);
1489     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface3, 0, surface4);
1490
1491     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface3);
1492     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 32x32 texture mip level to a 16x16 offscreen plain surface returned %08x\n", hr);
1493     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface4, 0, surface3);
1494
1495     hr = IDirectDrawSurface7_AddAttachedSurface(surface2, surface4);  /* Succeeds on refrast */
1496     if (refrast)
1497         ok(hr == S_OK, "Attaching a 16x16 offscreen plain surface to a 64x64 texture sublevel returned %08x\n", hr);
1498     else
1499         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 16x16 offscreen plain surface to a 64x64 texture sublevel returned %08x\n", hr);
1500     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface2, 0, surface4);
1501
1502     hr = IDirectDrawSurface7_AddAttachedSurface(surface4, surface2);
1503     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a 64x64 texture sublevel to a 16x16 offscreen plain surface returned %08x\n", hr);
1504     if(SUCCEEDED(hr)) IDirectDrawSurface7_DeleteAttachedSurface(surface4, 0, surface2);
1505
1506     IDirectDrawSurface7_Release(surface4);
1507     IDirectDrawSurface7_Release(surface3);
1508     IDirectDrawSurface7_Release(surface2);
1509     IDirectDrawSurface7_Release(surface1);
1510
1511     hr = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
1512     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1513
1514     /* Creating a back buffer as-is, is not allowed. No need to perform attachment tests */
1515     memset(&ddsd, 0, sizeof(ddsd));
1516     ddsd.dwSize = sizeof(ddsd);
1517     ddsd.dwFlags = DDSD_CAPS;
1518     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER;
1519     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL);
1520     ok(hr==DDERR_INVALIDCAPS,"CreateSurface returned: %x\n",hr);
1521     /* This old ddraw version happily creates explicit front buffers */
1522     memset(&ddsd, 0, sizeof(ddsd));
1523     ddsd.dwSize = sizeof(ddsd);
1524     ddsd.dwFlags = DDSD_CAPS;
1525     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER;
1526     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL);
1527     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1528     IDirectDrawSurface_Release(surface1);
1529
1530     /* Try a single primary and two offscreen plain surfaces */
1531     memset(&ddsd, 0, sizeof(ddsd));
1532     ddsd.dwSize = sizeof(ddsd);
1533     ddsd.dwFlags = DDSD_CAPS;
1534     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1535     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL);
1536     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1537
1538     memset(&ddsd, 0, sizeof(ddsd));
1539     ddsd.dwSize = sizeof(ddsd);
1540     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1541     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1542     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1543     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1544     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL);
1545     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1546
1547     memset(&ddsd, 0, sizeof(ddsd));
1548     ddsd.dwSize = sizeof(ddsd);
1549     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
1550     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1551     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
1552     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
1553     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface3, NULL);
1554     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1555
1556     /* This one has a different size */
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 = 128;
1562     ddsd.dwHeight = 128;
1563     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL);
1564     ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
1565
1566     hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
1567     ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
1568        "Attaching an offscreen plain surface to a front buffer returned %08x\n", hr);
1569     if(SUCCEEDED(hr))
1570     {
1571         /* Try the reverse without detaching first */
1572         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
1573         ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
1574         hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
1575         ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
1576     }
1577     hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
1578     ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
1579        "Attaching a front buffer to an offscreen plain surface returned %08x\n", hr);
1580     if(SUCCEEDED(hr))
1581     {
1582         /* Try to detach reversed */
1583         hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
1584         ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
1585         /* Now the proper detach */
1586         hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
1587         ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
1588     }
1589     hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3); /* Fails on refrast */
1590     ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
1591        "Attaching an offscreen plain surface to another offscreen plain surface returned %08x\n", hr);
1592     if(SUCCEEDED(hr))
1593     {
1594         hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
1595         ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
1596     }
1597     hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
1598     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching an offscreen plain surface to a front buffer of different size returned %08x\n", hr);
1599     hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
1600     ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to an offscreen plain surface of different size returned %08x\n", hr);
1601
1602     IDirectDrawSurface_Release(surface4);
1603     IDirectDrawSurface_Release(surface3);
1604     IDirectDrawSurface_Release(surface2);
1605     IDirectDrawSurface_Release(surface1);
1606
1607     hr =IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
1608     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
1609
1610     DestroyWindow(window);
1611 }
1612
1613 struct compare
1614 {
1615     DWORD width, height;
1616     DWORD caps, caps2;
1617     UINT mips;
1618 };
1619
1620 static HRESULT WINAPI CubeTestLvl2Enum(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1621 {
1622     UINT *mips = context;
1623
1624     (*mips)++;
1625     IDirectDrawSurface7_EnumAttachedSurfaces(surface,
1626                                              context,
1627                                              CubeTestLvl2Enum);
1628
1629     return DDENUMRET_OK;
1630 }
1631
1632 static HRESULT WINAPI CubeTestLvl1Enum(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *desc, void *context)
1633 {
1634     UINT mips = 0;
1635     UINT *num = context;
1636     static const struct compare expected[] =
1637     {
1638         {
1639             128, 128,
1640             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1641             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ,
1642             7
1643         },
1644         {
1645             128, 128,
1646             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1647             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ,
1648             7
1649         },
1650         {
1651             128, 128,
1652             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1653             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY,
1654             7
1655         },
1656         {
1657             128, 128,
1658             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1659             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY,
1660             7
1661         },
1662         {
1663             128, 128,
1664             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1665             DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX,
1666             7
1667         },
1668         {
1669             64, 64, /* This is the first mipmap */
1670             DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX,
1671             DDSCAPS2_MIPMAPSUBLEVEL | DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX,
1672             6
1673         },
1674     };
1675
1676     mips = 0;
1677     IDirectDrawSurface7_EnumAttachedSurfaces(surface,
1678                                              &mips,
1679                                              CubeTestLvl2Enum);
1680
1681     ok(desc->dwWidth == expected[*num].width, "Surface width is %d expected %d\n", desc->dwWidth, expected[*num].width);
1682     ok(desc->dwHeight == expected[*num].height, "Surface height is %d expected %d\n", desc->dwHeight, expected[*num].height);
1683     ok(desc->ddsCaps.dwCaps == expected[*num].caps, "Surface caps are %08x expected %08x\n", desc->ddsCaps.dwCaps, expected[*num].caps);
1684     ok(desc->ddsCaps.dwCaps2 == expected[*num].caps2, "Surface caps2 are %08x expected %08x\n", desc->ddsCaps.dwCaps2, expected[*num].caps2);
1685     ok(mips == expected[*num].mips, "Surface has %d mipmaps, expected %d\n", mips, expected[*num].mips);
1686
1687     (*num)++;
1688
1689     IDirectDrawSurface7_Release(surface);
1690
1691     return DDENUMRET_OK;
1692 }
1693
1694 static void CubeMapTest(void)
1695 {
1696     IDirectDraw7 *dd7 = NULL;
1697     IDirectDrawSurface7 *cubemap = NULL;
1698     DDSURFACEDESC2 ddsd;
1699     HRESULT hr;
1700     UINT num = 0;
1701     struct enumstruct ctx;
1702
1703     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
1704     ok(hr == DD_OK, "IDirectDraw::QueryInterface returned %08x\n", hr);
1705     if (FAILED(hr)) goto err;
1706
1707     memset(&ddsd, 0, sizeof(ddsd));
1708     ddsd.dwSize = sizeof(ddsd);
1709     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1710     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1711     ddsd.dwWidth = 128;
1712     ddsd.dwHeight = 128;
1713     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1714     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
1715
1716     /* D3DFMT_R5G6B5 */
1717     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1718     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1719     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1720     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1721     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1722
1723     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
1724     if (FAILED(hr))
1725     {
1726         skip("Can't create cubemap surface\n");
1727         goto err;
1728     }
1729
1730     hr = IDirectDrawSurface7_GetSurfaceDesc(cubemap, &ddsd);
1731     ok(hr == DD_OK, "IDirectDrawSurface7_GetSurfaceDesc returned %08x\n", hr);
1732     ok(ddsd.ddsCaps.dwCaps == (DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX),
1733        "Root Caps are %08x\n", ddsd.ddsCaps.dwCaps);
1734     ok(ddsd.ddsCaps.dwCaps2 == (DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP),
1735        "Root Caps2 are %08x\n", ddsd.ddsCaps.dwCaps2);
1736
1737     IDirectDrawSurface7_EnumAttachedSurfaces(cubemap,
1738                                              &num,
1739                                              CubeTestLvl1Enum);
1740     ok(num == 6, "Surface has %d attachments\n", num);
1741     IDirectDrawSurface7_Release(cubemap);
1742
1743     /* What happens if I do not specify any faces? */
1744     memset(&ddsd, 0, sizeof(ddsd));
1745     ddsd.dwSize = sizeof(ddsd);
1746     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1747     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1748     ddsd.dwWidth = 128;
1749     ddsd.dwHeight = 128;
1750     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1751     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP;
1752
1753     /* D3DFMT_R5G6B5 */
1754     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1755     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1756     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1757     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1758     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1759
1760     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
1761     ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7::CreateSurface asking for a cube map without faces returned %08x\n", hr);
1762
1763     /* Cube map faces without a cube map? */
1764     memset(&ddsd, 0, sizeof(ddsd));
1765     ddsd.dwSize = sizeof(ddsd);
1766     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1767     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1768     ddsd.dwWidth = 128;
1769     ddsd.dwHeight = 128;
1770     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1771     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP_ALLFACES;
1772
1773     /* D3DFMT_R5G6B5 */
1774     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1775     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1776     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1777     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1778     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1779
1780     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
1781     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7::CreateSurface returned %08x\n", hr);
1782
1783     memset(&ddsd, 0, sizeof(ddsd));
1784     ddsd.dwSize = sizeof(ddsd);
1785     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1786     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1787     ddsd.dwWidth = 128;
1788     ddsd.dwHeight = 128;
1789     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_SYSTEMMEMORY;
1790     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP_POSITIVEX;
1791
1792     /* D3DFMT_R5G6B5 */
1793     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
1794     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16;
1795     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800;
1796     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0;
1797     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F;
1798
1799     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL);
1800     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7::CreateSurface returned %08x\n", hr);
1801
1802     /* Make sure everything is cleaned up properly. Use the enumSurfaces test infrastructure */
1803     memset(&ctx, 0, sizeof(ctx));
1804     memset(&ddsd, 0, sizeof(ddsd));
1805     ddsd.dwSize = sizeof(DDSURFACEDESC);
1806     hr = IDirectDraw_EnumSurfaces(lpDD, DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, (DDSURFACEDESC *) &ddsd, (void *) &ctx, enumCB);
1807     ok(hr == DD_OK, "IDirectDraw_EnumSurfaces returned %08x\n", hr);
1808     ok(ctx.count == 0, "%d surfaces enumerated, expected 0\n", ctx.count);
1809
1810     err:
1811     if (dd7) IDirectDraw7_Release(dd7);
1812 }
1813
1814 static void test_lockrect_invalid(void)
1815 {
1816     unsigned int i, j;
1817
1818     RECT valid[] = {
1819         {60, 60, 68, 68},
1820         {60, 60, 60, 68},
1821         {60, 60, 68, 60},
1822         {120, 60, 128, 68},
1823         {60, 120, 68, 128},
1824     };
1825
1826     RECT invalid[] = {
1827         {68, 60, 60, 68},       /* left > right */
1828         {60, 68, 68, 60},       /* top > bottom */
1829         {-8, 60,  0, 68},       /* left < surface */
1830         {60, -8, 68,  0},       /* top < surface */
1831         {-16, 60, -8, 68},      /* right < surface */
1832         {60, -16, 68, -8},      /* bottom < surface */
1833         {60, 60, 136, 68},      /* right > surface */
1834         {60, 60, 68, 136},      /* bottom > surface */
1835         {136, 60, 144, 68},     /* left > surface */
1836         {60, 136, 68, 144},     /* top > surface */
1837     };
1838
1839     const DWORD dds_caps[] = {
1840         DDSCAPS_OFFSCREENPLAIN
1841     };
1842
1843     for (j = 0; j < (sizeof(dds_caps) / sizeof(*dds_caps)); ++j)
1844     {
1845         IDirectDrawSurface *surface = 0;
1846         DDSURFACEDESC surface_desc = {0};
1847         DDSURFACEDESC locked_desc = {0};
1848         HRESULT hr;
1849
1850         surface_desc.dwSize = sizeof(surface_desc);
1851         surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
1852         surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
1853         surface_desc.ddsCaps.dwCaps = dds_caps[j];
1854         surface_desc.dwWidth = 128;
1855         surface_desc.dwHeight = 128;
1856         surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
1857         U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
1858         U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0xFF0000;
1859         U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x00FF00;
1860         U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x0000FF;
1861
1862         hr = IDirectDraw_CreateSurface(lpDD, &surface_desc, &surface, NULL);
1863         ok(SUCCEEDED(hr), "CreateSurface failed (0x%08x)\n", hr);
1864         if (FAILED(hr)) {
1865             skip("failed to create surface\n");
1866             continue;
1867         }
1868
1869         for (i = 0; i < (sizeof(valid) / sizeof(*valid)); ++i)
1870         {
1871             RECT *rect = &valid[i];
1872
1873             memset(&locked_desc, 0, sizeof(locked_desc));
1874             locked_desc.dwSize = sizeof(locked_desc);
1875
1876             hr = IDirectDrawSurface_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
1877             ok(SUCCEEDED(hr), "Lock failed (0x%08x) for rect [%d, %d]->[%d, %d]\n",
1878                     hr, rect->left, rect->top, rect->right, rect->bottom);
1879
1880             hr = IDirectDrawSurface_Unlock(surface, NULL);
1881             ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1882         }
1883
1884         for (i = 0; i < (sizeof(invalid) / sizeof(*invalid)); ++i)
1885         {
1886             RECT *rect = &invalid[i];
1887
1888             memset(&locked_desc, 1, sizeof(locked_desc));
1889             locked_desc.dwSize = sizeof(locked_desc);
1890
1891             hr = IDirectDrawSurface_Lock(surface, rect, &locked_desc, DDLOCK_WAIT, NULL);
1892             ok(hr == DDERR_INVALIDPARAMS, "Lock returned 0x%08x for rect [%d, %d]->[%d, %d]"
1893                     ", expected DDERR_INVALIDPARAMS (0x%08x)\n", hr, rect->left, rect->top,
1894                     rect->right, rect->bottom, DDERR_INVALIDPARAMS);
1895             ok(!locked_desc.lpSurface, "IDirectDrawSurface_Lock did not set lpSurface in the surface desc to zero.\n");
1896         }
1897
1898         hr = IDirectDrawSurface_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
1899         ok(hr == DD_OK, "IDirectDrawSurface_Lock(rect = NULL) failed (0x%08x)\n", hr);
1900         hr = IDirectDrawSurface_Lock(surface, NULL, &locked_desc, DDLOCK_WAIT, NULL);
1901         ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = NULL) returned 0x%08x\n", hr);
1902         if(SUCCEEDED(hr)) {
1903             hr = IDirectDrawSurface_Unlock(surface, NULL);
1904             ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1905         }
1906         hr = IDirectDrawSurface_Unlock(surface, NULL);
1907         ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1908
1909         memset(&locked_desc, 0, sizeof(locked_desc));
1910         locked_desc.dwSize = sizeof(locked_desc);
1911         hr = IDirectDrawSurface_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
1912         ok(hr == DD_OK, "IDirectDrawSurface_Lock(rect = [%d, %d]->[%d, %d]) failed (0x%08x)\n",
1913            valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
1914         hr = IDirectDrawSurface_Lock(surface, &valid[0], &locked_desc, DDLOCK_WAIT, NULL);
1915         ok(hr == DDERR_SURFACEBUSY, "Double lock(rect = [%d, %d]->[%d, %d]) failed (0x%08x)\n",
1916            valid[0].left, valid[0].top, valid[0].right, valid[0].bottom, hr);
1917
1918         /* Locking a different rectangle returns DD_OK, but it seems to break the surface.
1919          * Afterwards unlocking the surface fails(NULL rectangle, and both locked rectangles
1920          */
1921
1922         hr = IDirectDrawSurface_Unlock(surface, NULL);
1923         ok(hr == DD_OK, "Unlock returned (0x%08x)\n", hr);
1924
1925         IDirectDrawSurface_Release(surface);
1926     }
1927 }
1928
1929 static void CompressedTest(void)
1930 {
1931     HRESULT hr;
1932     IDirectDrawSurface7 *surface;
1933     DDSURFACEDESC2 ddsd, ddsd2;
1934     IDirectDraw7 *dd7 = NULL;
1935     RECT r = { 0, 0, 128, 128 };
1936     RECT r2 = { 32, 32, 64, 64 };
1937
1938     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
1939     ok(hr == DD_OK, "IDirectDraw::QueryInterface returned %08x\n", hr);
1940
1941     memset(&ddsd, 0, sizeof(ddsd));
1942     ddsd.dwSize = sizeof(ddsd);
1943     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1944     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
1945     ddsd.dwWidth = 128;
1946     ddsd.dwHeight = 128;
1947     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
1948     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC;
1949     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1');
1950
1951     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
1952     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1953     if (FAILED(hr)) {
1954         skip("failed to create surface\n");
1955         return;
1956     }
1957
1958     memset(&ddsd2, 0, sizeof(ddsd2));
1959     ddsd2.dwSize = sizeof(ddsd2);
1960     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
1961     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
1962     ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
1963
1964     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
1965        "Surface desc flags: %08x\n", ddsd2.dwFlags);
1966     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
1967     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
1968     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
1969        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
1970     ok(U1(ddsd2).dwLinearSize == 8192, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
1971     ok(ddsd2.ddsCaps.dwCaps2 == 0, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2);
1972     IDirectDrawSurface7_Release(surface);
1973
1974     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3');
1975     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
1976     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
1977     if (FAILED(hr)) {
1978         skip("failed to create surface\n");
1979         return;
1980     }
1981
1982     memset(&ddsd2, 0, sizeof(ddsd2));
1983     ddsd2.dwSize = sizeof(ddsd2);
1984     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
1985     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
1986     ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
1987
1988     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
1989        "Surface desc flags: %08x\n", ddsd2.dwFlags);
1990     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
1991     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
1992     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
1993        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
1994     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
1995     IDirectDrawSurface7_Release(surface);
1996
1997     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5');
1998     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
1999     ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2000     if (FAILED(hr)) {
2001         skip("failed to create surface\n");
2002         return;
2003     }
2004
2005     memset(&ddsd2, 0, sizeof(ddsd2));
2006     ddsd2.dwSize = sizeof(ddsd2);
2007     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2008     hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2009     ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2010
2011     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2012        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2013     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2014     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2015     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2016        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2017     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2018     ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface);
2019
2020     memset(&ddsd2, 0, sizeof(ddsd2));
2021     ddsd2.dwSize = sizeof(ddsd2);
2022     U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2023
2024     /* Show that the description is not changed when locking the surface. What is really interesting
2025      * about this is that DDSD_LPSURFACE isn't set.
2026      */
2027     hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0);
2028     ok(hr == DD_OK, "Lock returned %08x\n", hr);
2029
2030     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2031        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2032     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2033     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2034     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2035        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2036     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2037     ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2038
2039     hr = IDirectDrawSurface7_Unlock(surface, NULL);
2040     ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2041
2042     /* Now what about a locking rect?  */
2043     hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0);
2044     ok(hr == DD_OK, "Lock returned %08x\n", hr);
2045
2046     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2047        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2048     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2049     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2050     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2051        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2052     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2053     ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2054
2055     hr = IDirectDrawSurface7_Unlock(surface, &r);
2056     ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2057
2058     /* Now what about a different locking offset? */
2059     hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0);
2060     ok(hr == DD_OK, "Lock returned %08x\n", hr);
2061
2062     ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2063        "Surface desc flags: %08x\n", ddsd2.dwFlags);
2064     ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2065     ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2066     ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2067        "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2068     ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2069     ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2070
2071     hr = IDirectDrawSurface7_Unlock(surface, &r2);
2072     ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2073     IDirectDrawSurface7_Release(surface);
2074
2075     /* Try this with video memory. A kind of surprise. It still has the LINEARSIZE flag set,
2076      * but seems to have a pitch instead.
2077      */
2078     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
2079     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1');
2080
2081     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2082     ok(hr == DD_OK || hr == DDERR_NOTEXTUREHW || hr == DDERR_INVALIDPARAMS ||
2083        broken(hr == DDERR_NODIRECTDRAWHW), "CreateSurface returned %08x\n", hr);
2084
2085     /* Not supported everywhere */
2086     if(SUCCEEDED(hr))
2087     {
2088         memset(&ddsd2, 0, sizeof(ddsd2));
2089         ddsd2.dwSize = sizeof(ddsd2);
2090         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2091         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2092         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2093
2094         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2095         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2096         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2097         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2098         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2099         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2100         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2101         ok(ddsd2.ddsCaps.dwCaps2 == 0, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2);
2102         IDirectDrawSurface7_Release(surface);
2103
2104         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3');
2105         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2106         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2107
2108         memset(&ddsd2, 0, sizeof(ddsd2));
2109         ddsd2.dwSize = sizeof(ddsd2);
2110         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2111         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2112         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2113
2114         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2115         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2116         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2117         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2118         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2119         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2120         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2121         IDirectDrawSurface7_Release(surface);
2122
2123         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5');
2124         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2125         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
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_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2138         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2139         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2140         ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface);
2141
2142         memset(&ddsd2, 0, sizeof(ddsd2));
2143         ddsd2.dwSize = sizeof(ddsd2);
2144         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2145
2146         /* Show that the description is not changed when locking the surface. What is really interesting
2147         * about this is that DDSD_LPSURFACE isn't set.
2148         */
2149         hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0);
2150         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2151
2152         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2153         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2154         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2155         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2156         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2157         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2158         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2159         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2160
2161         hr = IDirectDrawSurface7_Unlock(surface, NULL);
2162         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2163
2164         /* Now what about a locking rect?  */
2165         hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0);
2166         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2167
2168         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2169         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2170         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2171         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2172         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2173         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2174         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2175         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2176
2177         hr = IDirectDrawSurface7_Unlock(surface, &r);
2178         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2179
2180         /* Now what about a different locking offset? */
2181         hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0);
2182         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2183
2184         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2185         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2186         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2187         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2188         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM),
2189         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2190         /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */
2191         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2192
2193         hr = IDirectDrawSurface7_Unlock(surface, &r2);
2194         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2195
2196         IDirectDrawSurface7_Release(surface);
2197     }
2198     else
2199     {
2200         skip("Hardware DXTN textures not supported\n");
2201     }
2202
2203     /* What happens to managed textures? Interestingly, Windows reports them as being in system
2204      * memory. The linear size fits again.
2205      */
2206     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
2207     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
2208     U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1');
2209
2210     hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2211     ok(hr == DD_OK || hr == DDERR_NOTEXTUREHW, "CreateSurface returned %08x\n", hr);
2212
2213     /* Not supported everywhere */
2214     if(SUCCEEDED(hr))
2215     {
2216         memset(&ddsd2, 0, sizeof(ddsd2));
2217         ddsd2.dwSize = sizeof(ddsd2);
2218         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2219         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2220         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2221
2222         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2223         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2224         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2225         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2226         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2227         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2228         ok(U1(ddsd2).dwLinearSize == 8192, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2229         ok(ddsd2.ddsCaps.dwCaps2 == DDSCAPS2_TEXTUREMANAGE, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2);
2230         IDirectDrawSurface7_Release(surface);
2231
2232         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3');
2233         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2234         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2235
2236         memset(&ddsd2, 0, sizeof(ddsd2));
2237         ddsd2.dwSize = sizeof(ddsd2);
2238         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2239         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2240         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2241
2242         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2243         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2244         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2245         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2246         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2247         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2248         ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2249         IDirectDrawSurface7_Release(surface);
2250
2251         U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5');
2252         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
2253         ok(hr == DD_OK, "CreateSurface returned %08x\n", hr);
2254
2255         memset(&ddsd2, 0, sizeof(ddsd2));
2256         ddsd2.dwSize = sizeof(ddsd2);
2257         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2258         hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2);
2259         ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr);
2260
2261         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2262         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2263         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2264         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2265         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2266         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2267         ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2268         ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface);
2269
2270         memset(&ddsd2, 0, sizeof(ddsd2));
2271         ddsd2.dwSize = sizeof(ddsd2);
2272         U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat);
2273
2274         /* Show that the description is not changed when locking the surface. What is really interesting
2275         * about this is that DDSD_LPSURFACE isn't set.
2276         */
2277         hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0);
2278         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2279
2280         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2281         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2282         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2283         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2284         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2285         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2286         ok(U1(ddsd2).dwLinearSize == 16384, "Linear size is %d\n", U1(ddsd2).dwLinearSize);
2287         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2288
2289         hr = IDirectDrawSurface7_Unlock(surface, NULL);
2290         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2291
2292         /* Now what about a locking rect?  */
2293         hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0);
2294         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2295
2296         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2297         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2298         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2299         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2300         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2301         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2302         ok(U1(ddsd2).dwLinearSize == 16384, "\"Linear\" size is %d\n", U1(ddsd2).dwLinearSize);
2303         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2304
2305         hr = IDirectDrawSurface7_Unlock(surface, &r);
2306         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2307
2308         /* Now what about a different locking offset? */
2309         hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0);
2310         ok(hr == DD_OK, "Lock returned %08x\n", hr);
2311
2312         ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE),
2313         "Surface desc flags: %08x\n", ddsd2.dwFlags);
2314         ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags);
2315         ok(U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount == 0, "RGB bitcount: %08x\n", U1(U4(ddsd2).ddpfPixelFormat).dwRGBBitCount);
2316         ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY),
2317         "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps);
2318         ok(U1(ddsd2).dwLinearSize == 16384, "\"Linear\" size is %d\n", U1(ddsd2).dwLinearSize);
2319         ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n");
2320
2321         hr = IDirectDrawSurface7_Unlock(surface, &r2);
2322         ok(hr == DD_OK, "Unlock returned %08x\n", hr);
2323
2324         IDirectDrawSurface7_Release(surface);
2325     }
2326     else
2327     {
2328         skip("Hardware DXTN textures not supported\n");
2329     }
2330
2331     IDirectDraw7_Release(dd7);
2332 }
2333
2334 static void SizeTest(void)
2335 {
2336     LPDIRECTDRAWSURFACE dsurface = NULL;
2337     DDSURFACEDESC desc;
2338     HRESULT ret;
2339     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2340
2341     /* Create an offscreen surface surface without a size */
2342     ZeroMemory(&desc, sizeof(desc));
2343     desc.dwSize = sizeof(desc);
2344     desc.dwFlags = DDSD_CAPS;
2345     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2346     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2347     ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without a size info returned %08x (dsurface=%p)\n", ret, dsurface);
2348     if(dsurface)
2349     {
2350         trace("Surface at %p\n", dsurface);
2351         IDirectDrawSurface_Release(dsurface);
2352         dsurface = NULL;
2353     }
2354
2355     /* Create an offscreen surface surface with only a width parameter */
2356     ZeroMemory(&desc, sizeof(desc));
2357     desc.dwSize = sizeof(desc);
2358     desc.dwFlags = DDSD_CAPS | DDSD_WIDTH;
2359     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2360     desc.dwWidth = 128;
2361     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2362     ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without hight info returned %08x\n", ret);
2363     if(dsurface)
2364     {
2365         IDirectDrawSurface_Release(dsurface);
2366         dsurface = NULL;
2367     }
2368
2369     /* Create an offscreen surface surface with only a height parameter */
2370     ZeroMemory(&desc, sizeof(desc));
2371     desc.dwSize = sizeof(desc);
2372     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT;
2373     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2374     desc.dwHeight = 128;
2375     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2376     ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without width info returned %08x\n", ret);
2377     if(dsurface)
2378     {
2379         IDirectDrawSurface_Release(dsurface);
2380         dsurface = NULL;
2381     }
2382
2383     /* Sanity check */
2384     ZeroMemory(&desc, sizeof(desc));
2385     desc.dwSize = sizeof(desc);
2386     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2387     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2388     desc.dwHeight = 128;
2389     desc.dwWidth = 128;
2390     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2391     ok(ret == DD_OK, "Creating an offscreen plain surface with width and height info returned %08x\n", ret);
2392     if(dsurface)
2393     {
2394         IDirectDrawSurface_Release(dsurface);
2395         dsurface = NULL;
2396     }
2397
2398     /* Test a primary surface size */
2399     ret = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_NORMAL);
2400     ok(ret == DD_OK, "SetCooperativeLevel failed with %08x\n", ret);
2401
2402     ZeroMemory(&desc, sizeof(desc));
2403     desc.dwSize = sizeof(desc);
2404     desc.dwFlags = DDSD_CAPS;
2405     desc.ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE;
2406     desc.dwHeight = 128; /* Keep them set to  check what happens */
2407     desc.dwWidth = 128; /* Keep them set to  check what happens */
2408     ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL);
2409     ok(ret == DD_OK, "Creating a primary surface without width and height info returned %08x\n", ret);
2410     if(dsurface)
2411     {
2412         ret = IDirectDrawSurface_GetSurfaceDesc(dsurface, &desc);
2413         ok(ret == DD_OK, "GetSurfaceDesc returned %x\n", ret);
2414
2415         IDirectDrawSurface_Release(dsurface);
2416         dsurface = NULL;
2417
2418         ok(desc.dwFlags & DDSD_WIDTH, "Primary surface doesn't have width set\n");
2419         ok(desc.dwFlags & DDSD_HEIGHT, "Primary surface doesn't have height set\n");
2420         ok(desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Surface width differs from screen width\n");
2421         ok(desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Surface height differs from screen height\n");
2422     }
2423     ret = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
2424     ok(ret == DD_OK, "SetCooperativeLevel failed with %08x\n", ret);
2425 }
2426
2427 static void PrivateDataTest(void)
2428 {
2429     HRESULT hr;
2430     IDirectDrawSurface7 *surface7 = NULL;
2431     IDirectDrawSurface *surface = NULL;
2432     DDSURFACEDESC desc;
2433     ULONG ref, ref2;
2434     IUnknown *ptr;
2435     DWORD size = sizeof(IUnknown *);
2436
2437     ZeroMemory(&desc, sizeof(desc));
2438     desc.dwSize = sizeof(desc);
2439     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2440     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2441     desc.dwHeight = 128;
2442     desc.dwWidth = 128;
2443     hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface, NULL);
2444     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2445     if(!surface)
2446     {
2447         return;
2448     }
2449     hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirectDrawSurface7, (void **) &surface7);
2450     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed with %08x\n", hr);
2451     if(!surface7)
2452     {
2453         IDirectDrawSurface_Release(surface);
2454         return;
2455     }
2456
2457     /* This fails */
2458     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, 0, DDSPD_IUNKNOWNPOINTER);
2459     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2460     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, 5, DDSPD_IUNKNOWNPOINTER);
2461     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2462     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, sizeof(IUnknown *) * 2, DDSPD_IUNKNOWNPOINTER);
2463     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2464
2465     ref = getref((IUnknown *) lpDD);
2466     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7 /* Abuse this tag */, lpDD, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2467     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2468     ref2 = getref((IUnknown *) lpDD);
2469     ok(ref2 == ref + 1, "Object reference is %d, expected %d\n", ref2, ref + 1);
2470     hr = IDirectDrawSurface7_FreePrivateData(surface7, &IID_IDirectDrawSurface7);
2471     ok(SUCCEEDED(hr), "IDirectDrawSurface7_FreePrivateData returned %#x.\n", hr);
2472     ref2 = getref((IUnknown *) lpDD);
2473     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
2474
2475     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7, lpDD, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2476     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2477     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7, surface7, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2478     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2479     ref2 = getref((IUnknown *) lpDD);
2480     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
2481
2482     hr = IDirectDrawSurface7_SetPrivateData(surface7, &IID_IDirectDrawSurface7, lpDD, sizeof(IUnknown *), DDSPD_IUNKNOWNPOINTER);
2483     ok(hr == DD_OK, "IDirectDrawSurface7_SetPrivateData failed with %08x\n", hr);
2484     hr = IDirectDrawSurface7_GetPrivateData(surface7, &IID_IDirectDrawSurface7, &ptr, &size);
2485     ok(hr == DD_OK, "IDirectDrawSurface7_GetPrivateData failed with %08x\n", hr);
2486     ref2 = getref((IUnknown *) lpDD);
2487     /* Object is NOT being addrefed */
2488     ok(ptr == (IUnknown *) lpDD, "Returned interface pointer is %p, expected %p\n", ptr, lpDD);
2489     ok(ref2 == ref + 1, "Object reference is %d, expected %d. ptr at %p, orig at %p\n", ref2, ref + 1, ptr, lpDD);
2490
2491     IDirectDrawSurface_Release(surface);
2492     IDirectDrawSurface7_Release(surface7);
2493
2494     /* Destroying the surface frees the held reference */
2495     ref2 = getref((IUnknown *) lpDD);
2496     ok(ref2 == ref, "Object reference is %d, expected %d\n", ref2, ref);
2497 }
2498
2499 static void BltParamTest(void)
2500 {
2501     IDirectDrawSurface *surface1 = NULL, *surface2 = NULL;
2502     DDSURFACEDESC desc;
2503     HRESULT hr;
2504     DDBLTFX BltFx;
2505     RECT valid = {10, 10, 20, 20};
2506     RECT invalid1 = {20, 10, 10, 20};
2507     RECT invalid2 = {20, 20, 20, 20};
2508     RECT invalid3 = {-1, -1, 20, 20};
2509     RECT invalid4 = {60, 60, 70, 70};
2510
2511     memset(&desc, 0, sizeof(desc));
2512     desc.dwSize = sizeof(desc);
2513     desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2514     desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2515     desc.dwHeight = 128;
2516     desc.dwWidth = 128;
2517     hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface1, NULL);
2518     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2519
2520     desc.dwHeight = 64;
2521     desc.dwWidth = 64;
2522     hr = IDirectDraw_CreateSurface(lpDD, &desc, &surface2, NULL);
2523     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2524
2525     if(0)
2526     {
2527         /* This crashes */
2528         hr = IDirectDrawSurface_BltFast(surface1, 0, 0, NULL, NULL, 0);
2529         ok(hr == DD_OK, "BltFast from NULL surface returned %08x\n", hr);
2530     }
2531     hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface2, NULL, 0);
2532     ok(hr == DD_OK, "BltFast from smaller to bigger surface returned %08x\n", hr);
2533     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, NULL, 0);
2534     ok(hr == DDERR_INVALIDRECT, "BltFast from bigger to smaller surface returned %08x\n", hr);
2535     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &valid, 0);
2536     ok(hr == DD_OK, "BltFast from bigger to smaller surface using a valid rectangle returned %08x\n", hr);
2537     hr = IDirectDrawSurface_BltFast(surface2, 60, 60, surface1, &valid, 0);
2538     ok(hr == DDERR_INVALIDRECT, "BltFast with a rectangle resulting in an off-surface write returned %08x\n", hr);
2539     hr = IDirectDrawSurface_BltFast(surface1, 90, 90, surface2, NULL, 0);
2540     ok(hr == DDERR_INVALIDRECT, "BltFast with a rectangle resulting in an off-surface write returned %08x\n", hr);
2541
2542     hr = IDirectDrawSurface_BltFast(surface1, -10, 0, surface2, NULL, 0);
2543     ok(hr == DDERR_INVALIDRECT, "BltFast with an offset resulting in an off-surface write returned %08x\n", hr);
2544     hr = IDirectDrawSurface_BltFast(surface1, 0, -10, surface2, NULL, 0);
2545     ok(hr == DDERR_INVALIDRECT, "BltFast with an offset resulting in an off-surface write returned %08x\n", hr);
2546     hr = IDirectDrawSurface_BltFast(surface2, 20, 20, surface1, &valid, 0);
2547     ok(hr == DD_OK, "BltFast from bigger to smaller surface using a valid rectangle and offset returned %08x\n", hr);
2548
2549     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid1, 0);
2550     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 1 returned %08x\n", hr);
2551     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid2, 0);
2552     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 2 returned %08x\n", hr);
2553     hr = IDirectDrawSurface_BltFast(surface2, 0, 0, surface1, &invalid3, 0);
2554     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 3 returned %08x\n", hr);
2555     hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface2, &invalid4, 0);
2556     ok(hr == DDERR_INVALIDRECT, "BltFast with invalid rectangle 3 returned %08x\n", hr);
2557     hr = IDirectDrawSurface_BltFast(surface1, 0, 0, surface1, NULL, 0);
2558     ok(hr == DD_OK, "BltFast blitting a surface onto itself returned %08x\n", hr);
2559
2560     /* Blt(non-fast) tests */
2561     memset(&BltFx, 0, sizeof(BltFx));
2562     BltFx.dwSize = sizeof(BltFx);
2563     U5(BltFx).dwFillColor = 0xaabbccdd;
2564
2565     hr = IDirectDrawSurface_Blt(surface1, &valid, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2566     ok(hr == DD_OK, "IDirectDrawSurface_Blt with a valid rectangle for color fill returned %08x\n", hr);
2567     hr = IDirectDrawSurface_Blt(surface1, &valid, NULL, &invalid3, DDBLT_COLORFILL, &BltFx);
2568     ok(hr == DD_OK, "IDirectDrawSurface_Blt with a invalid, unused rectangle returned %08x\n", hr);
2569     hr = IDirectDrawSurface_Blt(surface2, &invalid1, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2570     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 1 returned %08x\n", hr);
2571     hr = IDirectDrawSurface_Blt(surface2, &invalid2, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2572     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 2 returned %08x\n", hr);
2573     hr = IDirectDrawSurface_Blt(surface2, &invalid3, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2574     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 3 returned %08x\n", hr);
2575     hr = IDirectDrawSurface_Blt(surface2, &invalid4, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2576     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 4 returned %08x\n", hr);
2577
2578     /* Valid on surface 1 */
2579     hr = IDirectDrawSurface_Blt(surface1, &invalid4, NULL, NULL, DDBLT_COLORFILL, &BltFx);
2580     ok(hr == DD_OK, "IDirectDrawSurface_Blt with a subrectangle fill returned %08x\n", hr);
2581
2582     /* Works - stretched blit */
2583     hr = IDirectDrawSurface_Blt(surface1, NULL, surface2, NULL, 0, NULL);
2584     ok(hr == DD_OK, "IDirectDrawSurface_Blt from a smaller to a bigger surface returned %08x\n", hr);
2585     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, NULL, 0, NULL);
2586     ok(hr == DD_OK, "IDirectDrawSurface_Blt from a bigger to a smaller surface %08x\n", hr);
2587
2588     /* Invalid dest rects in sourced blits */
2589     hr = IDirectDrawSurface_Blt(surface2, &invalid1, surface1, NULL, 0, NULL);
2590     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 1 returned %08x\n", hr);
2591     hr = IDirectDrawSurface_Blt(surface2, &invalid2, surface1, NULL, 0, NULL);
2592     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 2 returned %08x\n", hr);
2593     hr = IDirectDrawSurface_Blt(surface2, &invalid3, surface1, NULL, 0, NULL);
2594     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 3 returned %08x\n", hr);
2595     hr = IDirectDrawSurface_Blt(surface2, &invalid4, surface1, NULL, 0, NULL);
2596     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 4 returned %08x\n", hr);
2597
2598     /* Invalid src rects */
2599     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, &invalid1, 0, NULL);
2600     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 1 returned %08x\n", hr);
2601     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, &invalid2, 0, NULL);
2602     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 2 returned %08x\n", hr);
2603     hr = IDirectDrawSurface_Blt(surface2, NULL, surface1, &invalid3, 0, NULL);
2604     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 3 returned %08x\n", hr);
2605     hr = IDirectDrawSurface_Blt(surface1, NULL, surface2, &invalid4, 0, NULL);
2606     ok(hr == DDERR_INVALIDRECT, "IDirectDrawSurface_Blt with a with invalid rectangle 4 returned %08x\n", hr);
2607
2608     IDirectDrawSurface_Release(surface1);
2609     IDirectDrawSurface_Release(surface2);
2610 }
2611
2612 static void PaletteTest(void)
2613 {
2614     HRESULT hr;
2615     LPDIRECTDRAWSURFACE lpSurf = NULL;
2616     DDSURFACEDESC ddsd;
2617     IDirectDrawPalette *palette = NULL;
2618     PALETTEENTRY Table[256];
2619     PALETTEENTRY palEntries[256];
2620     int i;
2621
2622     for(i=0; i<256; i++)
2623     {
2624         Table[i].peRed   = 0xff;
2625         Table[i].peGreen = 0;
2626         Table[i].peBlue  = 0;
2627         Table[i].peFlags = 0;
2628     }
2629
2630     /* Create a 8bit palette without DDPCAPS_ALLOW256 set */
2631     hr = IDirectDraw_CreatePalette(lpDD, DDPCAPS_8BIT, Table, &palette, NULL);
2632     ok(hr == DD_OK, "CreatePalette failed with %08x\n", hr);
2633     if (FAILED(hr)) goto err;
2634     /* Read back the palette and verify the entries. Without DDPCAPS_ALLOW256 set
2635     /  entry 0 and 255 should have been overwritten with black and white */
2636     IDirectDrawPalette_GetEntries(palette , 0, 0, 256, &palEntries[0]);
2637     ok(hr == DD_OK, "GetEntries failed with %08x\n", hr);
2638     if(hr == DD_OK)
2639     {
2640         ok((palEntries[0].peRed == 0) && (palEntries[0].peGreen == 0) && (palEntries[0].peBlue == 0),
2641            "Palette entry 0 of a palette without DDPCAPS_ALLOW256 set should be (0,0,0) but it is (%d,%d,%d)\n",
2642            palEntries[0].peRed, palEntries[0].peGreen, palEntries[0].peBlue);
2643         ok((palEntries[255].peRed == 255) && (palEntries[255].peGreen == 255) && (palEntries[255].peBlue == 255),
2644            "Palette entry 255 of a palette without DDPCAPS_ALLOW256 set should be (255,255,255) but it is (%d,%d,%d)\n",
2645            palEntries[255].peRed, palEntries[255].peGreen, palEntries[255].peBlue);
2646
2647         /* Entry 1-254 should contain red */
2648         for(i=1; i<255; i++)
2649             ok((palEntries[i].peRed == 255) && (palEntries[i].peGreen == 0) && (palEntries[i].peBlue == 0),
2650                "Palette entry %d should have contained (255,0,0) but was set to %d,%d,%d)\n",
2651                i, palEntries[i].peRed, palEntries[i].peGreen, palEntries[i].peBlue);
2652     }
2653
2654     /* CreatePalette without DDPCAPS_ALLOW256 ignores entry 0 and 255,
2655     /  now check we are able to update the entries afterwards. */
2656     IDirectDrawPalette_SetEntries(palette , 0, 0, 256, &Table[0]);
2657     ok(hr == DD_OK, "SetEntries failed with %08x\n", hr);
2658     IDirectDrawPalette_GetEntries(palette , 0, 0, 256, &palEntries[0]);
2659     ok(hr == DD_OK, "GetEntries failed with %08x\n", hr);
2660     if(hr == DD_OK)
2661     {
2662         ok((palEntries[0].peRed == 0) && (palEntries[0].peGreen == 0) && (palEntries[0].peBlue == 0),
2663            "Palette entry 0 should have been set to (0,0,0) but it contains (%d,%d,%d)\n",
2664            palEntries[0].peRed, palEntries[0].peGreen, palEntries[0].peBlue);
2665         ok((palEntries[255].peRed == 255) && (palEntries[255].peGreen == 255) && (palEntries[255].peBlue == 255),
2666            "Palette entry 255 should have been set to (255,255,255) but it contains (%d,%d,%d)\n",
2667            palEntries[255].peRed, palEntries[255].peGreen, palEntries[255].peBlue);
2668     }
2669     IDirectDrawPalette_Release(palette);
2670
2671     /* Create a 8bit palette with DDPCAPS_ALLOW256 set */
2672     hr = IDirectDraw_CreatePalette(lpDD, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL);
2673     ok(hr == DD_OK, "CreatePalette failed with %08x\n", hr);
2674     if (FAILED(hr)) goto err;
2675
2676     IDirectDrawPalette_GetEntries(palette , 0, 0, 256, &palEntries[0]);
2677     ok(hr == DD_OK, "GetEntries failed with %08x\n", hr);
2678     if(hr == DD_OK)
2679     {
2680         /* All entries should contain red */
2681         for(i=0; i<256; i++)
2682             ok((palEntries[i].peRed == 255) && (palEntries[i].peGreen == 0) && (palEntries[i].peBlue == 0),
2683                "Palette entry %d should have contained (255,0,0) but was set to %d,%d,%d)\n",
2684                i, palEntries[i].peRed, palEntries[i].peGreen, palEntries[i].peBlue);
2685     }
2686
2687     /* Try to set palette to a non-palettized surface */
2688     ddsd.dwSize = sizeof(ddsd);
2689     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
2690     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
2691     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
2692     ddsd.dwWidth = 800;
2693     ddsd.dwHeight = 600;
2694     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
2695     U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
2696     U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
2697     U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
2698     U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
2699     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSurf, NULL);
2700     ok(hr==DD_OK, "CreateSurface returned: %x\n",hr);
2701     if (FAILED(hr)) {
2702         skip("failed to create surface\n");
2703         goto err;
2704     }
2705
2706     hr = IDirectDrawSurface_SetPalette(lpSurf, palette);
2707     ok(hr == DDERR_INVALIDPIXELFORMAT, "CreateSurface returned: %x\n",hr);
2708
2709     IDirectDrawPalette_Release(palette);
2710     palette = NULL;
2711
2712     hr = IDirectDrawSurface_GetPalette(lpSurf, &palette);
2713     ok(hr == DDERR_NOPALETTEATTACHED, "CreateSurface returned: %x\n",hr);
2714
2715     err:
2716
2717     if (lpSurf) IDirectDrawSurface_Release(lpSurf);
2718     if (palette) IDirectDrawPalette_Release(palette);
2719 }
2720
2721 static void StructSizeTest(void)
2722 {
2723     IDirectDrawSurface *surface1;
2724     IDirectDrawSurface7 *surface7;
2725     union {
2726         DDSURFACEDESC desc1;
2727         DDSURFACEDESC2 desc2;
2728         char blob[1024]; /* To get a bunch of writable memory */
2729     } desc;
2730     DDSURFACEDESC create;
2731     HRESULT hr;
2732
2733     memset(&desc, 0, sizeof(desc));
2734     memset(&create, 0, sizeof(create));
2735
2736     memset(&create, 0, sizeof(create));
2737     create.dwSize = sizeof(create);
2738     create.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
2739     create.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
2740     create.dwHeight = 128;
2741     create.dwWidth = 128;
2742     hr = IDirectDraw_CreateSurface(lpDD, &create, &surface1, NULL);
2743     ok(hr == DD_OK, "Creating an offscreen plain surface failed with %08x\n", hr);
2744     hr = IDirectDrawSurface_QueryInterface(surface1, &IID_IDirectDrawSurface7, (void **) &surface7);
2745     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed with %08x\n", hr);
2746
2747     desc.desc1.dwSize = sizeof(DDSURFACEDESC);
2748     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
2749     ok(hr == DD_OK, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
2750     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
2751     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
2752
2753     desc.desc2.dwSize = sizeof(DDSURFACEDESC2);
2754     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
2755     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
2756     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
2757     ok(hr == DD_OK, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
2758
2759     desc.desc2.dwSize = 0;
2760     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
2761     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size 0 returned %08x\n", hr);
2762     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
2763     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size 0 returned %08x\n", hr);
2764
2765     desc.desc1.dwSize = sizeof(DDSURFACEDESC) + 1;
2766     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
2767     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
2768     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
2769     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
2770
2771     desc.desc2.dwSize = sizeof(DDSURFACEDESC2) + 1;
2772     hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc.desc1);
2773     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
2774     hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc.desc2);
2775     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_GetSurfaceDesc with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
2776
2777     /* Tests for Lock() */
2778
2779     desc.desc1.dwSize = sizeof(DDSURFACEDESC);
2780     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
2781     ok(hr == DD_OK, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
2782     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
2783     ok(desc.desc1.dwSize == sizeof(DDSURFACEDESC), "Destination size was changed to %d\n", desc.desc1.dwSize);
2784     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
2785     ok(hr == DD_OK, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC) returned %08x\n", hr);
2786     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
2787     ok(desc.desc2.dwSize == sizeof(DDSURFACEDESC), "Destination size was changed to %d\n", desc.desc1.dwSize);
2788
2789     desc.desc2.dwSize = sizeof(DDSURFACEDESC2);
2790     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
2791     ok(hr == DD_OK, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
2792     ok(desc.desc1.dwSize == sizeof(DDSURFACEDESC2), "Destination size was changed to %d\n", desc.desc1.dwSize);
2793     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
2794     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
2795     ok(hr == DD_OK, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC2) returned %08x\n", hr);
2796     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
2797     ok(desc.desc2.dwSize == sizeof(DDSURFACEDESC2), "Destination size was changed to %d\n", desc.desc1.dwSize);
2798
2799     desc.desc2.dwSize = 0;
2800     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
2801     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Lock with desc size 0 returned %08x\n", hr);
2802     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
2803     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
2804     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_Lock with desc size 0 returned %08x\n", hr);
2805     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
2806
2807     desc.desc1.dwSize = sizeof(DDSURFACEDESC) + 1;
2808     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
2809     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
2810     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
2811     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
2812     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC) + 1 returned %08x\n", hr);
2813     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
2814
2815     desc.desc2.dwSize = sizeof(DDSURFACEDESC2) + 1;
2816     hr = IDirectDrawSurface_Lock(surface1, NULL, &desc.desc1, 0, 0);
2817     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Lock with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
2818     if(SUCCEEDED(hr)) IDirectDrawSurface_Unlock(surface1, NULL);
2819     hr = IDirectDrawSurface7_Lock(surface7, NULL, &desc.desc2, 0, 0);
2820     ok(hr == DDERR_INVALIDPARAMS, "IDirectDrawSurface7_Lock with desc size sizeof(DDSURFACEDESC2) + 1returned %08x\n", hr);
2821     if(SUCCEEDED(hr)) IDirectDrawSurface7_Unlock(surface7, NULL);
2822
2823     IDirectDrawSurface7_Release(surface7);
2824     IDirectDrawSurface_Release(surface1);
2825 }
2826
2827 static void SurfaceCapsTest(void)
2828 {
2829     DDSURFACEDESC create;
2830     DDSURFACEDESC desc;
2831     HRESULT hr;
2832     IDirectDrawSurface *surface1 = NULL;
2833     DDSURFACEDESC2 create2, desc2;
2834     IDirectDrawSurface7 *surface7 = NULL;
2835     IDirectDraw7 *dd7 = NULL;
2836     DWORD create_caps[] = {
2837         DDSCAPS_OFFSCREENPLAIN,
2838         DDSCAPS_TEXTURE,
2839         DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD,
2840         0,
2841         DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD | DDSCAPS_SYSTEMMEMORY,
2842         DDSCAPS_PRIMARYSURFACE,
2843         DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY
2844     };
2845     DWORD expected_caps[] = {
2846         DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
2847         DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
2848         DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_ALLOCONLOAD,
2849         DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM,
2850         DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD | DDSCAPS_SYSTEMMEMORY,
2851         DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_VISIBLE,
2852         DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_VISIBLE
2853     };
2854     UINT i;
2855
2856     /* Tests various surface flags, what changes do they undergo during surface creation. Forsaken
2857      * engine expects texture surfaces without memory flag to get a video memory flag right after
2858      * creation. Currently, Wine adds DDSCAPS_FRONTBUFFER to primary surface, but native doesn't do this
2859      * for single buffered primaries. Because of this primary surface creation tests are todo_wine. No real
2860      * app is known so far to care about this. */
2861
2862     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
2863     {
2864         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
2865         return ;
2866     }
2867
2868     for (i = 0; i < sizeof(create_caps) / sizeof(DWORD); i++)
2869     {
2870         memset(&create, 0, sizeof(create));
2871         create.dwSize = sizeof(create);
2872         create.ddsCaps.dwCaps = create_caps[i];
2873         create.dwFlags = DDSD_CAPS;
2874
2875         if (!(create.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
2876         {
2877             create.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH;
2878             create.dwHeight = 128;
2879             create.dwWidth = 128;
2880         }
2881
2882         hr = IDirectDraw_CreateSurface(lpDD, &create, &surface1, NULL);
2883         ok(hr == DD_OK, "IDirectDraw_CreateSurface failed with %08x\n", hr);
2884
2885         if (SUCCEEDED(hr))
2886         {
2887             memset(&desc, 0, sizeof(desc));
2888             desc.dwSize = sizeof(DDSURFACEDESC);
2889             hr = IDirectDrawSurface_GetSurfaceDesc(surface1, &desc);
2890             ok(hr == DD_OK, "IDirectDrawSurface_GetSurfaceDesc failed with %08x\n", hr);
2891
2892             if (!(create_caps[i] & DDSCAPS_PRIMARYSURFACE))
2893                 ok(desc.ddsCaps.dwCaps == expected_caps[i],
2894                     "GetSurfaceDesc returned caps %x, expected %x\n", desc.ddsCaps.dwCaps,
2895                     expected_caps[i]);
2896             else
2897                 todo_wine ok(desc.ddsCaps.dwCaps == expected_caps[i],
2898                                 "GetSurfaceDesc returned caps %x, expected %x\n", desc.ddsCaps.dwCaps,
2899                                 expected_caps[i]);
2900
2901             IDirectDrawSurface_Release(surface1);
2902         }
2903     }
2904
2905     /* Test for differences in ddraw 7 */
2906     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
2907     ok(hr == DD_OK, "IDirectDraw_QueryInterface returned %08x\n", hr);
2908     if (FAILED(hr))
2909     {
2910         skip("Failed to get IDirectDraw7 interface, skipping tests\n");
2911     }
2912     else
2913     {
2914         for (i = 0; i < sizeof(create_caps) / sizeof(DWORD); i++)
2915         {
2916             memset(&create2, 0, sizeof(create2));
2917             create2.dwSize = sizeof(create2);
2918             create2.ddsCaps.dwCaps = create_caps[i];
2919             create2.dwFlags = DDSD_CAPS;
2920
2921             if (!(create2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
2922             {
2923                 create2.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH;
2924                 create2.dwHeight = 128;
2925                 create2.dwWidth = 128;
2926             }
2927
2928             hr = IDirectDraw7_CreateSurface(dd7, &create2, &surface7, NULL);
2929             ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
2930
2931             if (SUCCEEDED(hr))
2932             {
2933                 memset(&desc2, 0, sizeof(desc2));
2934                 desc2.dwSize = sizeof(DDSURFACEDESC2);
2935                 hr = IDirectDrawSurface7_GetSurfaceDesc(surface7, &desc2);
2936                 ok(hr == DD_OK, "IDirectDrawSurface_GetSurfaceDesc failed with %08x\n", hr);
2937
2938                 if (!(create_caps[i] & DDSCAPS_PRIMARYSURFACE))
2939                     ok(desc2.ddsCaps.dwCaps == expected_caps[i],
2940                         "GetSurfaceDesc returned caps %x, expected %x\n", desc2.ddsCaps.dwCaps,
2941                         expected_caps[i]);
2942                 else
2943                     todo_wine ok(desc2.ddsCaps.dwCaps == expected_caps[i],
2944                                     "GetSurfaceDesc returned caps %x, expected %x\n", desc2.ddsCaps.dwCaps,
2945                                     expected_caps[i]);
2946
2947                 IDirectDrawSurface7_Release(surface7);
2948             }
2949         }
2950
2951         IDirectDraw7_Release(dd7);
2952     }
2953
2954     memset(&create, 0, sizeof(create));
2955     create.dwSize = sizeof(create);
2956     create.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
2957     create.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY;
2958     create.dwWidth = 64;
2959     create.dwHeight = 64;
2960     hr = IDirectDraw_CreateSurface(lpDD, &create, &surface1, NULL);
2961     ok(hr == DDERR_INVALIDCAPS, "Creating a SYSMEM | VIDMEM surface returned 0x%08x, expected DDERR_INVALIDCAPS\n", hr);
2962     if(surface1) IDirectDrawSurface_Release(surface1);
2963 }
2964
2965 static BOOL can_create_primary_surface(void)
2966 {
2967     DDSURFACEDESC ddsd;
2968     IDirectDrawSurface *surface;
2969     HRESULT hr;
2970
2971     memset(&ddsd, 0, sizeof(ddsd));
2972     ddsd.dwSize = sizeof(ddsd);
2973     ddsd.dwFlags = DDSD_CAPS;
2974     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2975     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL);
2976     if(FAILED(hr)) return FALSE;
2977     IDirectDrawSurface_Release(surface);
2978     return TRUE;
2979 }
2980
2981 static void dctest_surf(IDirectDrawSurface *surf, int ddsdver) {
2982     HRESULT hr;
2983     HDC dc, dc2 = (HDC) 0x1234;
2984     DDSURFACEDESC ddsd;
2985     DDSURFACEDESC2 ddsd2;
2986
2987     memset(&ddsd, 0, sizeof(ddsd));
2988     ddsd.dwSize = sizeof(ddsd);
2989     memset(&ddsd2, 0, sizeof(ddsd2));
2990     ddsd2.dwSize = sizeof(ddsd2);
2991
2992     hr = IDirectDrawSurface_GetDC(surf, &dc);
2993     ok(hr == DD_OK, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
2994
2995     hr = IDirectDrawSurface_GetDC(surf, &dc2);
2996     ok(hr == DDERR_DCALREADYCREATED, "IDirectDrawSurface_GetDC failed: 0x%08x\n", hr);
2997     ok(dc2 == (HDC) 0x1234, "The failed GetDC call changed the dc: %p\n", dc2);
2998
2999     hr = IDirectDrawSurface_Lock(surf, NULL, ddsdver == 1 ? &ddsd : ((DDSURFACEDESC *) &ddsd2), 0, NULL);
3000     ok(hr == DDERR_SURFACEBUSY, "IDirectDrawSurface_Lock returned 0x%08x, expected DDERR_ALREADYLOCKED\n", hr);
3001
3002     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
3003     ok(hr == DD_OK, "IDirectDrawSurface_ReleaseDC failed: 0x%08x\n", hr);
3004     hr = IDirectDrawSurface_ReleaseDC(surf, dc);
3005     ok(hr == DDERR_NODC, "IDirectDrawSurface_ReleaseDC returned 0x%08x, expected DDERR_NODC\n", hr);
3006 }
3007
3008 static void GetDCTest(void)
3009 {
3010     DDSURFACEDESC ddsd;
3011     DDSURFACEDESC2 ddsd2;
3012     IDirectDrawSurface *surf;
3013     IDirectDrawSurface2 *surf2;
3014     IDirectDrawSurface4 *surf4;
3015     IDirectDrawSurface7 *surf7;
3016     IDirectDrawSurface *tmp;
3017     IDirectDrawSurface7 *tmp7;
3018     HRESULT hr;
3019     IDirectDraw2 *dd2;
3020     IDirectDraw4 *dd4;
3021     IDirectDraw7 *dd7;
3022     HDC dc;
3023
3024     memset(&ddsd, 0, sizeof(ddsd));
3025     ddsd.dwSize = sizeof(ddsd);
3026     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3027     ddsd.dwWidth = 64;
3028     ddsd.dwHeight = 64;
3029     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3030     memset(&ddsd2, 0, sizeof(ddsd2));
3031     ddsd2.dwSize = sizeof(ddsd2);
3032     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3033     ddsd2.dwWidth = 64;
3034     ddsd2.dwHeight = 64;
3035     ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3036
3037     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surf, NULL);
3038     ok(hr == DD_OK, "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3039     dctest_surf(surf, 1);
3040     IDirectDrawSurface_Release(surf);
3041
3042     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
3043     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3044
3045     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3046     ok(hr == DD_OK, "IDirectDraw2_CreateSurface failed: 0x%08x\n", hr);
3047     dctest_surf(surf, 1);
3048
3049     hr = IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2);
3050     ok(hr == DD_OK, "IDirectDrawSurface_QueryInterface failed: 0x%08x\n", hr);
3051     dctest_surf((IDirectDrawSurface *) surf2, 1);
3052
3053     IDirectDrawSurface2_Release(surf2);
3054     IDirectDrawSurface_Release(surf);
3055     IDirectDraw2_Release(dd2);
3056
3057     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
3058     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3059
3060     surf = NULL;
3061     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3062     ok(hr == DD_OK, "IDirectDraw4_CreateSurface failed: 0x%08x\n", hr);
3063     dctest_surf((IDirectDrawSurface *) surf4, 2);
3064
3065     hr = IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **)&surf);
3066     ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr);
3067
3068     hr = IDirectDrawSurface4_GetDC(surf4, &dc);
3069     ok(SUCCEEDED(hr), "GetDC failed, hr %#x.\n", hr);
3070
3071     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, NULL);
3072     ok(hr == E_INVALIDARG, "Expected hr E_INVALIDARG, got %#x.\n", hr);
3073
3074     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, (IDirectDrawSurface4 **)&tmp);
3075     ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
3076     ok(tmp == surf, "Expected surface %p, got %p.\n\n", surf, tmp);
3077
3078     hr = IDirectDrawSurface4_ReleaseDC(surf4, dc);
3079     ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
3080
3081     dc = CreateCompatibleDC(NULL);
3082     ok(!!dc, "CreateCompatibleDC failed.\n");
3083
3084     tmp = (IDirectDrawSurface *)0xdeadbeef;
3085     hr = IDirectDraw4_GetSurfaceFromDC(dd4, dc, (IDirectDrawSurface4 **)&tmp);
3086     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3087     ok(!tmp, "Expected surface NULL, got %p.\n", tmp);
3088
3089     ok(DeleteDC(dc), "DeleteDC failed.\n");
3090
3091     tmp = (IDirectDrawSurface *)0xdeadbeef;
3092     hr = IDirectDraw4_GetSurfaceFromDC(dd4, NULL, (IDirectDrawSurface4 **)&tmp);
3093     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3094     ok(!tmp, "Expected surface NULL, got %p.\n", tmp);
3095
3096     IDirectDrawSurface4_Release(surf4);
3097     IDirectDraw4_Release(dd4);
3098
3099     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3100     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3101     surf = NULL;
3102     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3103     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed: 0x%08x\n", hr);
3104     dctest_surf((IDirectDrawSurface *) surf7, 2);
3105
3106     hr = IDirectDrawSurface7_GetDC(surf7, &dc);
3107     ok(SUCCEEDED(hr), "GetDC failed, hr %#x.\n", hr);
3108
3109     hr = IDirectDraw7_GetSurfaceFromDC(dd7, dc, NULL);
3110     ok(hr == E_INVALIDARG, "Expected hr E_INVALIDARG, got %#x.\n", hr);
3111
3112     hr = IDirectDraw7_GetSurfaceFromDC(dd7, dc, &tmp7);
3113     ok(SUCCEEDED(hr), "GetSurfaceFromDC failed, hr %#x.\n", hr);
3114     ok(tmp7 == surf7, "Expected surface %p, got %p.\n\n", surf7, tmp7);
3115     IDirectDrawSurface7_Release(tmp7);
3116
3117     hr = IDirectDrawSurface7_ReleaseDC(surf7, dc);
3118     ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);
3119
3120     dc = CreateCompatibleDC(NULL);
3121     ok(!!dc, "CreateCompatibleDC failed.\n");
3122
3123     tmp7 = (IDirectDrawSurface7 *)0xdeadbeef;
3124     hr = IDirectDraw7_GetSurfaceFromDC(dd7, dc, &tmp7);
3125     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3126     ok(!tmp7, "Expected surface NULL, got %p.\n", tmp7);
3127
3128     ok(DeleteDC(dc), "DeleteDC failed.\n");
3129
3130     tmp7 = (IDirectDrawSurface7 *)0xdeadbeef;
3131     hr = IDirectDraw7_GetSurfaceFromDC(dd7, NULL, (IDirectDrawSurface7 **)&tmp7);
3132     ok(hr == DDERR_NOTFOUND, "GetSurfaceFromDC failed, hr %#x.\n", hr);
3133     ok(!tmp7, "Expected surface NULL, got %p.\n", tmp7);
3134
3135     IDirectDrawSurface7_Release(surf7);
3136     IDirectDraw7_Release(dd7);
3137 }
3138
3139 static void GetDCFormatTest(void)
3140 {
3141     DDSURFACEDESC2 ddsd;
3142     unsigned int i;
3143     IDirectDrawSurface7 *surface;
3144     IDirectDraw7 *dd7;
3145     HRESULT hr;
3146     HDC dc;
3147
3148     struct
3149     {
3150         const char *name;
3151         DDPIXELFORMAT fmt;
3152         BOOL getdc_capable;
3153         HRESULT alt_result;
3154     } testdata[] = {
3155         {
3156             "D3DFMT_A8R8G8B8",
3157             {
3158                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3159                 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0xff000000}
3160             },
3161             TRUE
3162         },
3163         {
3164             "D3DFMT_X8R8G8B8",
3165             {
3166                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3167                 {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
3168             },
3169             TRUE
3170         },
3171         {
3172             "D3DFMT_X8B8G8R8",
3173             {
3174                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3175                 {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0x00000000}
3176             },
3177             TRUE,
3178             DDERR_CANTCREATEDC /* Vista+ */
3179         },
3180         {
3181             "D3DFMT_X8B8G8R8",
3182             {
3183                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3184                        {32}, {0x000000ff}, {0x0000ff00}, {0x00ff0000}, {0xff000000}
3185             },
3186             TRUE,
3187             DDERR_CANTCREATEDC /* Vista+ */
3188         },
3189         {
3190             "D3DFMT_A4R4G4B4",
3191             {
3192                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3193                        {16}, {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x0000f000}
3194             },
3195             TRUE,
3196             DDERR_CANTCREATEDC /* Vista+ */
3197         },
3198         {
3199             "D3DFMT_X4R4G4B4",
3200             {
3201                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3202                        {16}, {0x00000f00}, {0x000000f0}, {0x0000000f}, {0x00000000}
3203             },
3204             TRUE,
3205             DDERR_CANTCREATEDC /* Vista+ */
3206         },
3207         {
3208             "D3DFMT_R5G6B5",
3209             {
3210                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3211                        {16}, {0x0000F800}, {0x000007E0}, {0x0000001F}, {0x00000000}
3212             },
3213             TRUE
3214         },
3215         {
3216             "D3DFMT_A1R5G5B5",
3217             {
3218                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3219                        {16}, {0x00007C00}, {0x000003E0}, {0x0000001F}, {0x00008000}
3220             },
3221             TRUE
3222         },
3223         {
3224             "D3DFMT_X1R5G5B5",
3225             {
3226                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3227                        {16}, {0x00007C00}, {0x000003E0}, {0x0000001F}, {0x00000000}
3228             },
3229             TRUE
3230         },
3231         {
3232             "D3DFMT_R3G3B2",
3233             {
3234                 sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
3235                        { 8}, {0x000000E0}, {0x0000001C}, {0x00000003}, {0x00000000}
3236             },
3237             FALSE
3238         },
3239         {
3240             /* Untested, windows test machine didn't support this format */
3241             "D3DFMT_A2R10G10B10",
3242             {
3243                 sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
3244                        {32}, {0xC0000000}, {0x3FF00000}, {0x000FFC00}, {0x000003FF}
3245             },
3246             TRUE
3247         },
3248         /*
3249          * GetDC on a P8 surface fails unless the display mode is 8 bpp. This is not
3250          * implemented in wine yet, so disable the test for now. Succeeding P8 getDC
3251          * calls are tested in the ddraw.visual test.
3252          *
3253         {
3254             "D3DFMT_P8",
3255             {
3256                 sizeof(DDPIXELFORMAT), DDPF_PALETTEINDEXED8 | DDPF_RGB, 0,
3257                 {8 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3258             },
3259             FALSE
3260         },
3261          */
3262         {
3263             "D3DFMT_L8",
3264             {
3265                 sizeof(DDPIXELFORMAT), DDPF_LUMINANCE, 0,
3266                 {8 }, {0x000000ff}, {0x00000000}, {0x00000000}, {0x00000000}
3267             },
3268             FALSE
3269         },
3270         {
3271             "D3DFMT_A8L8",
3272             {
3273                 sizeof(DDPIXELFORMAT), DDPF_ALPHAPIXELS | DDPF_LUMINANCE, 0,
3274                 {16}, {0x000000ff}, {0x00000000}, {0x00000000}, {0x0000ff00}
3275             },
3276             FALSE
3277         },
3278         {
3279             "D3DFMT_DXT1",
3280             {
3281                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','1'),
3282                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3283             },
3284             FALSE
3285         },
3286         {
3287             "D3DFMT_DXT2",
3288             {
3289                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','2'),
3290                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3291             },
3292             FALSE
3293         },
3294         {
3295             "D3DFMT_DXT3",
3296             {
3297                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','3'),
3298                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3299             },
3300             FALSE
3301         },
3302         {
3303             "D3DFMT_DXT4",
3304             {
3305                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','4'),
3306                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3307             },
3308             FALSE
3309         },
3310         {
3311             "D3DFMT_DXT5",
3312             {
3313                 sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D','X','T','5'),
3314                 {0 }, {0x00000000}, {0x00000000}, {0x00000000}, {0x00000000}
3315             },
3316             FALSE
3317         },
3318     };
3319
3320     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3321     ok(hr == DD_OK, "IDirectDraw_QueryInterface failed, hr = 0x%08x\n", hr);
3322
3323     for(i = 0; i < (sizeof(testdata) / sizeof(testdata[0])); i++)
3324     {
3325         memset(&ddsd, 0, sizeof(ddsd));
3326         ddsd.dwSize = sizeof(ddsd);
3327         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
3328         ddsd.dwWidth = 64;
3329         ddsd.dwHeight = 64;
3330         U4(ddsd).ddpfPixelFormat = testdata[i].fmt;
3331         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
3332
3333         hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
3334         if(FAILED(hr))
3335         {
3336             ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
3337             ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
3338             hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL);
3339             if(FAILED(hr))
3340             {
3341                 skip("IDirectDraw7_CreateSurface failed, hr = 0x%08x, format %s\n", hr, testdata[i].name);
3342                 continue;
3343             }
3344         }
3345
3346         dc = (void *) 0x1234;
3347         hr = IDirectDrawSurface7_GetDC(surface, &dc);
3348         if(testdata[i].getdc_capable)
3349         {
3350             ok(SUCCEEDED(hr) ||
3351                (testdata[i].alt_result && hr == testdata[i].alt_result),
3352                "GetDC on a %s surface failed(0x%08x), expected it to work\n",
3353                testdata[i].name, hr);
3354         }
3355         else
3356         {
3357             ok(FAILED(hr), "GetDC on a %s surface succeeded(0x%08x), expected it to fail\n",
3358                testdata[i].name, hr);
3359         }
3360
3361         if(SUCCEEDED(hr))
3362         {
3363             IDirectDrawSurface7_ReleaseDC(surface, dc);
3364             ok(hr == DD_OK, "IDirectDrawSurface7_ReleaseDC failed, hr = 0x%08x\n", hr);
3365             dc = 0;
3366         }
3367         else
3368         {
3369             ok(dc == NULL, "After failed GetDC dc is %p\n", dc);
3370         }
3371
3372         IDirectDrawSurface7_Release(surface);
3373     }
3374
3375     IDirectDraw7_Release(dd7);
3376 }
3377
3378 static void BackBufferCreateSurfaceTest(void)
3379 {
3380     DDSURFACEDESC ddsd;
3381     DDSURFACEDESC created_ddsd;
3382     DDSURFACEDESC2 ddsd2;
3383     IDirectDrawSurface *surf;
3384     IDirectDrawSurface4 *surf4;
3385     IDirectDrawSurface7 *surf7;
3386     HRESULT hr;
3387     IDirectDraw2 *dd2;
3388     IDirectDraw4 *dd4;
3389     IDirectDraw7 *dd7;
3390
3391     const DWORD caps = DDSCAPS_BACKBUFFER;
3392     const DWORD expected_caps = DDSCAPS_BACKBUFFER | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
3393
3394     if (!(ddcaps.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
3395     {
3396         skip("DDraw reported no VIDEOMEMORY cap. Broken video driver? Skipping surface caps tests.\n");
3397         return ;
3398     }
3399
3400     memset(&ddsd, 0, sizeof(ddsd));
3401     ddsd.dwSize = sizeof(ddsd);
3402     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3403     ddsd.dwWidth = 64;
3404     ddsd.dwHeight = 64;
3405     ddsd.ddsCaps.dwCaps = caps;
3406     memset(&ddsd2, 0, sizeof(ddsd2));
3407     ddsd2.dwSize = sizeof(ddsd2);
3408     ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3409     ddsd2.dwWidth = 64;
3410     ddsd2.dwHeight = 64;
3411     ddsd2.ddsCaps.dwCaps = caps;
3412     memset(&created_ddsd, 0, sizeof(created_ddsd));
3413     created_ddsd.dwSize = sizeof(DDSURFACEDESC);
3414
3415     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surf, NULL);
3416     todo_wine ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed: 0x%08x\n", hr);
3417     if (surf != NULL)
3418     {
3419         hr = IDirectDrawSurface_GetSurfaceDesc(surf, &created_ddsd);
3420         ok(SUCCEEDED(hr), "IDirectDraw_GetSurfaceDesc failed: 0x%08x\n", hr);
3421         ok(created_ddsd.ddsCaps.dwCaps == expected_caps,
3422            "GetSurfaceDesc returned caps %x, expected %x\n", created_ddsd.ddsCaps.dwCaps,
3423            expected_caps);
3424         IDirectDrawSurface_Release(surf);
3425     }
3426
3427     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2, (void **) &dd2);
3428     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3429
3430     hr = IDirectDraw2_CreateSurface(dd2, &ddsd, &surf, NULL);
3431     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw2_CreateSurface didn't return %x08x, but %x08x\n",
3432        DDERR_INVALIDCAPS, hr);
3433
3434     IDirectDraw2_Release(dd2);
3435
3436     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
3437     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3438
3439     hr = IDirectDraw4_CreateSurface(dd4, &ddsd2, &surf4, NULL);
3440     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw4_CreateSurface didn't return %x08x, but %x08x\n",
3441        DDERR_INVALIDCAPS, hr);
3442
3443     IDirectDraw4_Release(dd4);
3444
3445     hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7);
3446     ok(SUCCEEDED(hr), "IDirectDraw_QueryInterface failed: 0x%08x\n", hr);
3447
3448     hr = IDirectDraw7_CreateSurface(dd7, &ddsd2, &surf7, NULL);
3449     ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7_CreateSurface didn't return %x08x, but %x08x\n",
3450        DDERR_INVALIDCAPS, hr);
3451
3452     IDirectDraw7_Release(dd7);
3453 }
3454
3455 static void BackBufferAttachmentFlipTest(void)
3456 {
3457     HRESULT hr;
3458     IDirectDrawSurface *surface1, *surface2, *surface3, *surface4;
3459     DDSURFACEDESC ddsd;
3460     HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
3461
3462     hr = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
3463     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3464
3465     /* Perform attachment tests on a back-buffer */
3466     memset(&ddsd, 0, sizeof(ddsd));
3467     ddsd.dwSize = sizeof(ddsd);
3468     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3469     ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
3470     ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3471     ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3472     hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface2, NULL);
3473     todo_wine ok(SUCCEEDED(hr), "CreateSurface returned: %x\n",hr);
3474
3475     if (surface2 != NULL)
3476     {
3477         /* Try a single primary and a two back buffers */
3478         memset(&ddsd, 0, sizeof(ddsd));
3479         ddsd.dwSize = sizeof(ddsd);
3480         ddsd.dwFlags = DDSD_CAPS;
3481         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
3482         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface1, NULL);
3483         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3484
3485         memset(&ddsd, 0, sizeof(ddsd));
3486         ddsd.dwSize = sizeof(ddsd);
3487         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3488         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
3489         ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
3490         ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
3491         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface3, NULL);
3492         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3493
3494         /* This one has a different size */
3495         memset(&ddsd, 0, sizeof(ddsd));
3496         ddsd.dwSize = sizeof(ddsd);
3497         ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
3498         ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
3499         ddsd.dwWidth = 128;
3500         ddsd.dwHeight = 128;
3501         hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface4, NULL);
3502         ok(hr==DD_OK,"CreateSurface returned: %x\n",hr);
3503
3504         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface2);
3505         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3506            "Attaching a back buffer to a front buffer returned %08x\n", hr);
3507         if(SUCCEEDED(hr))
3508         {
3509             /* Try flipping the surfaces */
3510             hr = IDirectDrawSurface_Flip(surface1, NULL, DDFLIP_WAIT);
3511             todo_wine ok(hr == DD_OK, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3512             hr = IDirectDrawSurface_Flip(surface2, NULL, DDFLIP_WAIT);
3513             todo_wine ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3514
3515             /* Try the reverse without detaching first */
3516             hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3517             ok(hr == DDERR_SURFACEALREADYATTACHED, "Attaching an attached surface to its attachee returned %08x\n", hr);
3518             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3519             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3520         }
3521         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface1);
3522         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3523            "Attaching a front buffer to a back buffer returned %08x\n", hr);
3524         if(SUCCEEDED(hr))
3525         {
3526             /* Try flipping the surfaces */
3527             hr = IDirectDrawSurface_Flip(surface1, NULL, DDFLIP_WAIT);
3528             todo_wine ok(hr == DD_OK, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3529             hr = IDirectDrawSurface_Flip(surface2, NULL, DDFLIP_WAIT);
3530             todo_wine ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3531
3532             /* Try to detach reversed */
3533             hr = IDirectDrawSurface_DeleteAttachedSurface(surface1, 0, surface2);
3534             ok(hr == DDERR_CANNOTDETACHSURFACE, "DeleteAttachedSurface returned %08x\n", hr);
3535             /* Now the proper detach */
3536             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface1);
3537             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3538         }
3539         hr = IDirectDrawSurface_AddAttachedSurface(surface2, surface3);
3540         todo_wine ok(hr == DD_OK || broken(hr == DDERR_CANNOTATTACHSURFACE),
3541            "Attaching a back buffer to another back buffer returned %08x\n", hr);
3542         if(SUCCEEDED(hr))
3543         {
3544             /* Try flipping the surfaces */
3545             hr = IDirectDrawSurface_Flip(surface3, NULL, DDFLIP_WAIT);
3546             todo_wine ok(hr == DD_OK, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3547             hr = IDirectDrawSurface_Flip(surface2, NULL, DDFLIP_WAIT);
3548             todo_wine ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3549             hr = IDirectDrawSurface_Flip(surface1, NULL, DDFLIP_WAIT);
3550             ok(hr == DDERR_NOTFLIPPABLE, "IDirectDrawSurface_Flip returned 0x%08x\n", hr);
3551
3552             hr = IDirectDrawSurface_DeleteAttachedSurface(surface2, 0, surface3);
3553             ok(hr == DD_OK, "DeleteAttachedSurface failed with %08x\n", hr);
3554         }
3555         hr = IDirectDrawSurface_AddAttachedSurface(surface1, surface4);
3556         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a back buffer to a front buffer of different size returned %08x\n", hr);
3557         hr = IDirectDrawSurface_AddAttachedSurface(surface4, surface1);
3558         ok(hr == DDERR_CANNOTATTACHSURFACE, "Attaching a front buffer to a back buffer of different size returned %08x\n", hr);
3559
3560         IDirectDrawSurface_Release(surface4);
3561         IDirectDrawSurface_Release(surface3);
3562         IDirectDrawSurface_Release(surface2);
3563         IDirectDrawSurface_Release(surface1);
3564     }
3565
3566     hr =IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL);
3567     ok(hr == DD_OK, "SetCooperativeLevel returned %08x\n", hr);
3568
3569     DestroyWindow(window);
3570 }
3571
3572 START_TEST(dsurface)
3573 {
3574     HRESULT ret;
3575     IDirectDraw4 *dd4;
3576
3577     if (!CreateDirectDraw())
3578         return;
3579
3580     ret = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw4, (void **) &dd4);
3581     if (ret == E_NOINTERFACE)
3582     {
3583         win_skip("DirectDraw4 and higher are not supported\n");
3584         ReleaseDirectDraw();
3585         return;
3586     }
3587     IDirectDraw_Release(dd4);
3588
3589     if(!can_create_primary_surface())
3590     {
3591         skip("Unable to create primary surface\n");
3592         return;
3593     }
3594
3595     ddcaps.dwSize = sizeof(DDCAPS);
3596     ret = IDirectDraw_GetCaps(lpDD, &ddcaps, NULL);
3597     if (ret != DD_OK)
3598     {
3599         skip("IDirectDraw_GetCaps failed with %08x\n", ret);
3600         return;
3601     }
3602
3603     MipMapCreationTest();
3604     SrcColorKey32BlitTest();
3605     QueryInterface();
3606     GetDDInterface_1();
3607     GetDDInterface_2();
3608     GetDDInterface_4();
3609     GetDDInterface_7();
3610     IFaceRefCount();
3611     EnumTest();
3612     AttachmentTest();
3613     AttachmentTest7();
3614     CubeMapTest();
3615     test_lockrect_invalid();
3616     CompressedTest();
3617     SizeTest();
3618     PrivateDataTest();
3619     BltParamTest();
3620     StructSizeTest();
3621     PaletteTest();
3622     SurfaceCapsTest();
3623     GetDCTest();
3624     GetDCFormatTest();
3625     BackBufferCreateSurfaceTest();
3626     BackBufferAttachmentFlipTest();
3627     ReleaseDirectDraw();
3628 }