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