ddraw: Get rid of the surfaces field in IDirectDrawImpl.
[wine] / dlls / ddraw / surface.c
1 /* DirectDraw Surface Implementation
2  *
3  * Copyright (c) 1997-2000 Marcus Meissner
4  * Copyright (c) 1998-2000 Lionel Ulmer
5  * Copyright (c) 2000-2001 TransGaming Technologies Inc.
6  * Copyright (c) 2006 Stefan Dösinger
7  * Copyright (c) 2011 Ričardas Barkauskas for CodeWeavers
8  *
9  * This file contains the (internal) driver registration functions,
10  * driver enumeration APIs and DirectDraw creation functions.
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include "wine/port.h"
29
30 #include "ddraw_private.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
33
34 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface);
35 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface);
36
37 static inline IDirectDrawSurfaceImpl *impl_from_IDirectDrawGammaControl(IDirectDrawGammaControl *iface)
38 {
39     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawGammaControl_iface);
40 }
41
42 /*****************************************************************************
43  * IUnknown parts follow
44  *****************************************************************************/
45
46 /*****************************************************************************
47  * IDirectDrawSurface7::QueryInterface
48  *
49  * A normal QueryInterface implementation. For QueryInterface rules
50  * see ddraw.c, IDirectDraw7::QueryInterface. This method
51  * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
52  * in all versions, the IDirectDrawGammaControl interface and it can
53  * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
54  *
55  * Params:
56  *  riid: The interface id queried for
57  *  obj: Address to write the pointer to
58  *
59  * Returns:
60  *  S_OK on success
61  *  E_NOINTERFACE if the requested interface wasn't found
62  *
63  *****************************************************************************/
64 static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, REFIID riid, void **obj)
65 {
66     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
67
68     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
69
70     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
71     *obj = NULL;
72
73     if(!riid)
74         return DDERR_INVALIDPARAMS;
75
76     if (IsEqualGUID(riid, &IID_IUnknown)
77      || IsEqualGUID(riid, &IID_IDirectDrawSurface7) )
78     {
79         IDirectDrawSurface7_AddRef(iface);
80         *obj = iface;
81         TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
82         return S_OK;
83     }
84     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface4))
85     {
86         IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
87         *obj = &This->IDirectDrawSurface4_iface;
88         TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
89         return S_OK;
90     }
91     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface3))
92     {
93         IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
94         *obj = &This->IDirectDrawSurface3_iface;
95         TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
96         return S_OK;
97     }
98     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface2))
99     {
100         IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface);
101         *obj = &This->IDirectDrawSurface2_iface;
102         TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj);
103         return S_OK;
104     }
105     else if (IsEqualGUID(riid, &IID_IDirectDrawSurface))
106     {
107         IDirectDrawSurface_AddRef(&This->IDirectDrawSurface_iface);
108         *obj = &This->IDirectDrawSurface_iface;
109         TRACE("(%p) returning IDirectDrawSurface interface at %p\n", This, *obj);
110         return S_OK;
111     }
112     else if( IsEqualGUID(riid, &IID_IDirectDrawGammaControl) )
113     {
114         IDirectDrawGammaControl_AddRef(&This->IDirectDrawGammaControl_iface);
115         *obj = &This->IDirectDrawGammaControl_iface;
116         TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
117         return S_OK;
118     }
119     else if( IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D) ||
120              IsEqualGUID(riid, &IID_IDirect3DHALDevice)||
121              IsEqualGUID(riid, &IID_IDirect3DRGBDevice) )
122     {
123         IDirect3DDevice7 *d3d;
124
125         /* Call into IDirect3D7 for creation */
126         IDirect3D7_CreateDevice(&This->ddraw->IDirect3D7_iface, riid, &This->IDirectDrawSurface7_iface,
127                 &d3d);
128
129         if (d3d)
130         {
131             *obj = (IDirect3DDevice *)&((IDirect3DDeviceImpl *)d3d)->IDirect3DDevice_vtbl;
132             TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
133             return S_OK;
134         }
135
136         WARN("Unable to create a IDirect3DDevice instance, returning E_NOINTERFACE\n");
137         return E_NOINTERFACE;
138     }
139     else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
140              IsEqualGUID( &IID_IDirect3DTexture2, riid ))
141     {
142         if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
143         {
144             *obj = &This->IDirect3DTexture_iface;
145             TRACE(" returning Direct3DTexture interface at %p.\n", *obj);
146         }
147         else
148         {
149             *obj = &This->IDirect3DTexture2_iface;
150             TRACE(" returning Direct3DTexture2 interface at %p.\n", *obj);
151         }
152         IUnknown_AddRef( (IUnknown *) *obj);
153         return S_OK;
154     }
155
156     ERR("No interface\n");
157     return E_NOINTERFACE;
158 }
159
160 static HRESULT WINAPI ddraw_surface4_QueryInterface(IDirectDrawSurface4 *iface, REFIID riid, void **object)
161 {
162     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
163     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
164
165     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
166 }
167
168 static HRESULT WINAPI ddraw_surface3_QueryInterface(IDirectDrawSurface3 *iface, REFIID riid, void **object)
169 {
170     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
171     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
172
173     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
174 }
175
176 static HRESULT WINAPI ddraw_surface2_QueryInterface(IDirectDrawSurface2 *iface, REFIID riid, void **object)
177 {
178     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
179     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
180
181     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
182 }
183
184 static HRESULT WINAPI ddraw_surface1_QueryInterface(IDirectDrawSurface *iface, REFIID riid, void **object)
185 {
186     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
187     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
188
189     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
190 }
191
192 static HRESULT WINAPI ddraw_gamma_control_QueryInterface(IDirectDrawGammaControl *iface,
193         REFIID riid, void **object)
194 {
195     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawGammaControl(iface);
196
197     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
198
199     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
200 }
201
202 static HRESULT WINAPI d3d_texture2_QueryInterface(IDirect3DTexture2 *iface, REFIID riid, void **object)
203 {
204     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture2(iface);
205     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
206
207     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
208 }
209
210 static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFIID riid, void **object)
211 {
212     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
213     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
214
215     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
216 }
217
218 static void ddraw_surface_add_iface(IDirectDrawSurfaceImpl *This)
219 {
220     ULONG iface_count = InterlockedIncrement(&This->iface_count);
221     TRACE("%p increasing iface count to %u.\n", This, iface_count);
222
223     if (iface_count == 1)
224     {
225         EnterCriticalSection(&ddraw_cs);
226         if (This->wined3d_surface)
227             wined3d_surface_incref(This->wined3d_surface);
228         if (This->wined3d_texture)
229             wined3d_texture_incref(This->wined3d_texture);
230         LeaveCriticalSection(&ddraw_cs);
231     }
232 }
233
234 /*****************************************************************************
235  * IDirectDrawSurface7::AddRef
236  *
237  * A normal addref implementation
238  *
239  * Returns:
240  *  The new refcount
241  *
242  *****************************************************************************/
243 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
244 {
245     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
246     ULONG refcount = InterlockedIncrement(&This->ref7);
247
248     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
249
250     if (refcount == 1)
251     {
252         ddraw_surface_add_iface(This);
253     }
254
255     return refcount;
256 }
257
258 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface)
259 {
260     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
261     ULONG refcount = InterlockedIncrement(&This->ref4);
262
263     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
264
265     if (refcount == 1)
266     {
267         ddraw_surface_add_iface(This);
268     }
269
270     return refcount;
271 }
272
273 static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface)
274 {
275     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
276     ULONG refcount = InterlockedIncrement(&This->ref3);
277
278     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
279
280     if (refcount == 1)
281     {
282         ddraw_surface_add_iface(This);
283     }
284
285     return refcount;
286 }
287
288 static ULONG WINAPI ddraw_surface2_AddRef(IDirectDrawSurface2 *iface)
289 {
290     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
291     ULONG refcount = InterlockedIncrement(&This->ref2);
292
293     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
294
295     if (refcount == 1)
296     {
297         ddraw_surface_add_iface(This);
298     }
299
300     return refcount;
301 }
302
303 static ULONG WINAPI ddraw_surface1_AddRef(IDirectDrawSurface *iface)
304 {
305     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
306     ULONG refcount = InterlockedIncrement(&This->ref1);
307
308     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
309
310     if (refcount == 1)
311     {
312         ddraw_surface_add_iface(This);
313     }
314
315     return refcount;
316 }
317
318 static ULONG WINAPI ddraw_gamma_control_AddRef(IDirectDrawGammaControl *iface)
319 {
320     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawGammaControl(iface);
321     ULONG refcount = InterlockedIncrement(&This->gamma_count);
322
323     TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
324
325     if (refcount == 1)
326     {
327         ddraw_surface_add_iface(This);
328     }
329
330     return refcount;
331 }
332
333 static ULONG WINAPI d3d_texture2_AddRef(IDirect3DTexture2 *iface)
334 {
335     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture2(iface);
336     TRACE("iface %p.\n", iface);
337
338     return ddraw_surface1_AddRef(&This->IDirectDrawSurface_iface);
339 }
340
341 static ULONG WINAPI d3d_texture1_AddRef(IDirect3DTexture *iface)
342 {
343     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
344     TRACE("iface %p.\n", iface);
345
346     return ddraw_surface1_AddRef(&This->IDirectDrawSurface_iface);
347 }
348
349 /*****************************************************************************
350  * ddraw_surface_destroy
351  *
352  * A helper function for IDirectDrawSurface7::Release
353  *
354  * Frees the surface, regardless of its refcount.
355  *  See IDirectDrawSurface7::Release for more information
356  *
357  * Params:
358  *  This: Surface to free
359  *
360  *****************************************************************************/
361 void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This)
362 {
363     TRACE("surface %p.\n", This);
364
365     /* Check the iface count and give a warning */
366     if(This->iface_count > 1)
367     {
368         /* This can happen when a complex surface is destroyed,
369          * because the 2nd surface was addref()ed when the app
370          * called GetAttachedSurface
371          */
372         WARN("(%p): Destroying surface with refcounts 7: %d 4: %d 3: %d 2: %d 1: %d\n",
373                 This, This->ref7, This->ref4, This->ref3, This->ref2, This->ref1);
374     }
375
376     if (This->wined3d_surface)
377         wined3d_surface_decref(This->wined3d_surface);
378 }
379
380 static void ddraw_surface_cleanup(IDirectDrawSurfaceImpl *surface)
381 {
382     IDirectDrawSurfaceImpl *surf;
383     IUnknown *ifaceToRelease;
384     UINT i;
385
386     TRACE("surface %p.\n", surface);
387
388     if (surface->wined3d_swapchain)
389     {
390         IDirectDrawImpl *ddraw = surface->ddraw;
391
392         /* If it's the render target, destroy the D3D device. */
393         if (ddraw->d3d_initialized && surface == ddraw->d3d_target)
394         {
395             TRACE("Destroying the render target, uninitializing D3D.\n");
396
397             for (i = 0; i < ddraw->numConvertedDecls; ++i)
398             {
399                 wined3d_vertex_declaration_decref(ddraw->decls[i].decl);
400             }
401             HeapFree(GetProcessHeap(), 0, ddraw->decls);
402             ddraw->numConvertedDecls = 0;
403
404             if (FAILED(wined3d_device_uninit_3d(ddraw->wined3d_device)))
405             {
406                 ERR("Failed to uninit 3D.\n");
407             }
408             else
409             {
410                 /* Free the d3d window if one was created. */
411                 if (ddraw->d3d_window && ddraw->d3d_window != ddraw->dest_window)
412                 {
413                     TRACE("Destroying the hidden render window %p.\n", ddraw->d3d_window);
414                     DestroyWindow(ddraw->d3d_window);
415                     ddraw->d3d_window = 0;
416                 }
417             }
418
419             ddraw->d3d_initialized = FALSE;
420             ddraw->d3d_target = NULL;
421         }
422         else
423         {
424             wined3d_device_uninit_gdi(ddraw->wined3d_device);
425         }
426
427         surface->wined3d_swapchain = NULL;
428
429         TRACE("D3D unloaded.\n");
430     }
431
432     /* The refcount test shows that the palette is detached when the surface
433      * is destroyed. */
434     IDirectDrawSurface7_SetPalette(&surface->IDirectDrawSurface7_iface, NULL);
435
436     /* Loop through all complex attached surfaces and destroy them.
437      *
438      * Yet again, only the root can have more than one complexly attached
439      * surface, all the others have a total of one. */
440     for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
441     {
442         if (!surface->complex_array[i])
443             break;
444
445         surf = surface->complex_array[i];
446         surface->complex_array[i] = NULL;
447         while (surf)
448         {
449             IDirectDrawSurfaceImpl *destroy = surf;
450             surf = surf->complex_array[0];              /* Iterate through the "tree" */
451             ddraw_surface_destroy(destroy);             /* Destroy it */
452         }
453     }
454
455     ifaceToRelease = surface->ifaceToRelease;
456
457     /* Destroy the root surface. */
458     ddraw_surface_destroy(surface);
459
460     /* Reduce the ddraw refcount */
461     if (ifaceToRelease)
462         IUnknown_Release(ifaceToRelease);
463 }
464
465 ULONG ddraw_surface_release_iface(IDirectDrawSurfaceImpl *This)
466 {
467     ULONG iface_count = InterlockedDecrement(&This->iface_count);
468     TRACE("%p decreasing iface count to %u.\n", This, iface_count);
469
470     if (iface_count == 0)
471     {
472         /* Complex attached surfaces are destroyed implicitly when the root is released */
473         EnterCriticalSection(&ddraw_cs);
474         if(!This->is_complex_root)
475         {
476             WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
477             LeaveCriticalSection(&ddraw_cs);
478             return iface_count;
479         }
480         if (This->wined3d_texture) /* If it's a texture, destroy the wined3d texture. */
481             wined3d_texture_decref(This->wined3d_texture);
482         else
483             ddraw_surface_cleanup(This);
484         LeaveCriticalSection(&ddraw_cs);
485     }
486
487     return iface_count;
488 }
489
490 /*****************************************************************************
491  * IDirectDrawSurface7::Release
492  *
493  * Reduces the surface's refcount by 1. If the refcount falls to 0, the
494  * surface is destroyed.
495  *
496  * Destroying the surface is a bit tricky. For the connection between
497  * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
498  * It has a nice graph explaining the connection.
499  *
500  * What happens here is basically this:
501  * When a surface is destroyed, its WineD3DSurface is released,
502  * and the refcount of the DirectDraw interface is reduced by 1. If it has
503  * complex surfaces attached to it, then these surfaces are destroyed too,
504  * regardless of their refcount. If any surface being destroyed has another
505  * surface attached to it (with a "soft" attachment, not complex), then
506  * this surface is detached with DeleteAttachedSurface.
507  *
508  * When the surface is a texture, the WineD3DTexture is released.
509  * If the surface is the Direct3D render target, then the D3D
510  * capabilities of the WineD3DDevice are uninitialized, which causes the
511  * swapchain to be released.
512  *
513  * When a complex sublevel falls to ref zero, then this is ignored.
514  *
515  * Returns:
516  *  The new refcount
517  *
518  *****************************************************************************/
519 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
520 {
521     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
522     ULONG refcount = InterlockedDecrement(&This->ref7);
523
524     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
525
526     if (refcount == 0)
527     {
528         ddraw_surface_release_iface(This);
529     }
530
531     return refcount;
532 }
533
534 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface)
535 {
536     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
537     ULONG refcount = InterlockedDecrement(&This->ref4);
538
539     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
540
541     if (refcount == 0)
542     {
543         ddraw_surface_release_iface(This);
544     }
545
546     return refcount;
547 }
548
549 static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface)
550 {
551     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
552     ULONG refcount = InterlockedDecrement(&This->ref3);
553
554     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
555
556     if (refcount == 0)
557     {
558         ddraw_surface_release_iface(This);
559     }
560
561     return refcount;
562 }
563
564 static ULONG WINAPI ddraw_surface2_Release(IDirectDrawSurface2 *iface)
565 {
566     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
567     ULONG refcount = InterlockedDecrement(&This->ref2);
568
569     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
570
571     if (refcount == 0)
572     {
573         ddraw_surface_release_iface(This);
574     }
575
576     return refcount;
577 }
578
579 static ULONG WINAPI ddraw_surface1_Release(IDirectDrawSurface *iface)
580 {
581     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
582     ULONG refcount = InterlockedDecrement(&This->ref1);
583
584     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
585
586     if (refcount == 0)
587     {
588         ddraw_surface_release_iface(This);
589     }
590
591     return refcount;
592 }
593
594 static ULONG WINAPI ddraw_gamma_control_Release(IDirectDrawGammaControl *iface)
595 {
596     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawGammaControl(iface);
597     ULONG refcount = InterlockedDecrement(&This->gamma_count);
598
599     TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
600
601     if (refcount == 0)
602     {
603         ddraw_surface_release_iface(This);
604     }
605
606     return refcount;
607 }
608
609 static ULONG WINAPI d3d_texture2_Release(IDirect3DTexture2 *iface)
610 {
611     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture2(iface);
612     TRACE("iface %p.\n", iface);
613
614     return ddraw_surface1_Release(&This->IDirectDrawSurface_iface);
615 }
616
617 static ULONG WINAPI d3d_texture1_Release(IDirect3DTexture *iface)
618 {
619     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
620     TRACE("iface %p.\n", iface);
621
622     return ddraw_surface1_Release(&This->IDirectDrawSurface_iface);
623 }
624
625 /*****************************************************************************
626  * IDirectDrawSurface7::GetAttachedSurface
627  *
628  * Returns an attached surface with the requested caps. Surface attachment
629  * and complex surfaces are not clearly described by the MSDN or sdk,
630  * so this method is tricky and likely to contain problems.
631  * This implementation searches the complex list first, then the
632  * attachment chain.
633  *
634  * The chains are searched from This down to the last surface in the chain,
635  * not from the first element in the chain. The first surface found is
636  * returned. The MSDN says that this method fails if more than one surface
637  * matches the caps, but it is not sure if that is right. The attachment
638  * structure may not even allow two matching surfaces.
639  *
640  * The found surface is AddRef-ed before it is returned.
641  *
642  * Params:
643  *  Caps: Pointer to a DDCAPS2 structure describing the caps asked for
644  *  Surface: Address to store the found surface
645  *
646  * Returns:
647  *  DD_OK on success
648  *  DDERR_INVALIDPARAMS if Caps or Surface is NULL
649  *  DDERR_NOTFOUND if no surface was found
650  *
651  *****************************************************************************/
652 static HRESULT WINAPI ddraw_surface7_GetAttachedSurface(IDirectDrawSurface7 *iface,
653         DDSCAPS2 *Caps, IDirectDrawSurface7 **Surface)
654 {
655     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
656     IDirectDrawSurfaceImpl *surf;
657     DDSCAPS2 our_caps;
658     int i;
659
660     TRACE("iface %p, caps %p, attachment %p.\n", iface, Caps, Surface);
661
662     EnterCriticalSection(&ddraw_cs);
663
664     if(This->version < 7)
665     {
666         /* Earlier dx apps put garbage into these members, clear them */
667         our_caps.dwCaps = Caps->dwCaps;
668         our_caps.dwCaps2 = 0;
669         our_caps.dwCaps3 = 0;
670         our_caps.dwCaps4 = 0;
671     }
672     else
673     {
674         our_caps = *Caps;
675     }
676
677     TRACE("(%p): Looking for caps: %x,%x,%x,%x\n", This, our_caps.dwCaps, our_caps.dwCaps2, our_caps.dwCaps3, our_caps.dwCaps4); /* FIXME: Better debugging */
678
679     for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
680     {
681         surf = This->complex_array[i];
682         if(!surf) break;
683
684         if (TRACE_ON(ddraw))
685         {
686             TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
687                    surf->surface_desc.ddsCaps.dwCaps,
688                    surf->surface_desc.ddsCaps.dwCaps2,
689                    surf->surface_desc.ddsCaps.dwCaps3,
690                    surf->surface_desc.ddsCaps.dwCaps4);
691         }
692
693         if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
694             ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
695
696             /* MSDN: "This method fails if more than one surface is attached
697              * that matches the capabilities requested."
698              *
699              * Not sure how to test this.
700              */
701
702             TRACE("(%p): Returning surface %p\n", This, surf);
703             TRACE("(%p): mipmapcount=%d\n", This, surf->mipmap_level);
704             *Surface = &surf->IDirectDrawSurface7_iface;
705             ddraw_surface7_AddRef(*Surface);
706             LeaveCriticalSection(&ddraw_cs);
707             return DD_OK;
708         }
709     }
710
711     /* Next, look at the attachment chain */
712     surf = This;
713
714     while( (surf = surf->next_attached) )
715     {
716         if (TRACE_ON(ddraw))
717         {
718             TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
719                    surf->surface_desc.ddsCaps.dwCaps,
720                    surf->surface_desc.ddsCaps.dwCaps2,
721                    surf->surface_desc.ddsCaps.dwCaps3,
722                    surf->surface_desc.ddsCaps.dwCaps4);
723         }
724
725         if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
726             ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
727
728             TRACE("(%p): Returning surface %p\n", This, surf);
729             *Surface = &surf->IDirectDrawSurface7_iface;
730             ddraw_surface7_AddRef(*Surface);
731             LeaveCriticalSection(&ddraw_cs);
732             return DD_OK;
733         }
734     }
735
736     TRACE("(%p) Didn't find a valid surface\n", This);
737     LeaveCriticalSection(&ddraw_cs);
738
739     *Surface = NULL;
740     return DDERR_NOTFOUND;
741 }
742
743 static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *iface,
744         DDSCAPS2 *caps, IDirectDrawSurface4 **attachment)
745 {
746     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
747     IDirectDrawSurface7 *attachment7;
748     IDirectDrawSurfaceImpl *attachment_impl;
749     HRESULT hr;
750
751     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
752
753     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
754             caps, &attachment7);
755     if (FAILED(hr))
756     {
757         *attachment = NULL;
758         return hr;
759     }
760     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
761     *attachment = &attachment_impl->IDirectDrawSurface4_iface;
762     ddraw_surface4_AddRef(*attachment);
763     ddraw_surface7_Release(attachment7);
764
765     return hr;
766 }
767
768 static HRESULT WINAPI ddraw_surface3_GetAttachedSurface(IDirectDrawSurface3 *iface,
769         DDSCAPS *caps, IDirectDrawSurface3 **attachment)
770 {
771     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
772     IDirectDrawSurface7 *attachment7;
773     IDirectDrawSurfaceImpl *attachment_impl;
774     DDSCAPS2 caps2;
775     HRESULT hr;
776
777     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
778
779     caps2.dwCaps  = caps->dwCaps;
780     caps2.dwCaps2 = 0;
781     caps2.dwCaps3 = 0;
782     caps2.dwCaps4 = 0;
783
784     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
785             &caps2, &attachment7);
786     if (FAILED(hr))
787     {
788         *attachment = NULL;
789         return hr;
790     }
791     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
792     *attachment = &attachment_impl->IDirectDrawSurface3_iface;
793     ddraw_surface3_AddRef(*attachment);
794     ddraw_surface7_Release(attachment7);
795
796     return hr;
797 }
798
799 static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *iface,
800         DDSCAPS *caps, IDirectDrawSurface2 **attachment)
801 {
802     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
803     IDirectDrawSurface7 *attachment7;
804     IDirectDrawSurfaceImpl *attachment_impl;
805     DDSCAPS2 caps2;
806     HRESULT hr;
807
808     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
809
810     caps2.dwCaps  = caps->dwCaps;
811     caps2.dwCaps2 = 0;
812     caps2.dwCaps3 = 0;
813     caps2.dwCaps4 = 0;
814
815     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
816             &caps2, &attachment7);
817     if (FAILED(hr))
818     {
819         *attachment = NULL;
820         return hr;
821     }
822     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
823     *attachment = &attachment_impl->IDirectDrawSurface2_iface;
824     ddraw_surface2_AddRef(*attachment);
825     ddraw_surface7_Release(attachment7);
826
827     return hr;
828 }
829
830 static HRESULT WINAPI ddraw_surface1_GetAttachedSurface(IDirectDrawSurface *iface,
831         DDSCAPS *caps, IDirectDrawSurface **attachment)
832 {
833     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
834     IDirectDrawSurface7 *attachment7;
835     IDirectDrawSurfaceImpl *attachment_impl;
836     DDSCAPS2 caps2;
837     HRESULT hr;
838
839     TRACE("iface %p, caps %p, attachment %p.\n", iface, caps, attachment);
840
841     caps2.dwCaps  = caps->dwCaps;
842     caps2.dwCaps2 = 0;
843     caps2.dwCaps3 = 0;
844     caps2.dwCaps4 = 0;
845
846     hr = ddraw_surface7_GetAttachedSurface(&This->IDirectDrawSurface7_iface,
847             &caps2, &attachment7);
848     if (FAILED(hr))
849     {
850         *attachment = NULL;
851         return hr;
852     }
853     attachment_impl = impl_from_IDirectDrawSurface7(attachment7);
854     *attachment = &attachment_impl->IDirectDrawSurface_iface;
855     ddraw_surface1_AddRef(*attachment);
856     ddraw_surface7_Release(attachment7);
857
858     return hr;
859 }
860
861 /*****************************************************************************
862  * IDirectDrawSurface7::Lock
863  *
864  * Locks the surface and returns a pointer to the surface's memory
865  *
866  * Params:
867  *  Rect: Rectangle to lock. If NULL, the whole surface is locked
868  *  DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
869  *  Flags: Locking flags, e.g Read only or write only
870  *  h: An event handle that's not used and must be NULL
871  *
872  * Returns:
873  *  DD_OK on success
874  *  DDERR_INVALIDPARAMS if DDSD is NULL
875  *  For more details, see IWineD3DSurface::LockRect
876  *
877  *****************************************************************************/
878 static HRESULT surface_lock(IDirectDrawSurfaceImpl *This,
879         RECT *Rect, DDSURFACEDESC2 *DDSD, DWORD Flags, HANDLE h)
880 {
881     WINED3DLOCKED_RECT LockedRect;
882     HRESULT hr;
883
884     TRACE("This %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
885             This, wine_dbgstr_rect(Rect), DDSD, Flags, h);
886
887     /* This->surface_desc.dwWidth and dwHeight are changeable, thus lock */
888     EnterCriticalSection(&ddraw_cs);
889
890     /* Should I check for the handle to be NULL?
891      *
892      * The DDLOCK flags and the D3DLOCK flags are equal
893      * for the supported values. The others are ignored by WineD3D
894      */
895
896     /* Windows zeroes this if the rect is invalid */
897     DDSD->lpSurface = 0;
898
899     if (Rect)
900     {
901         if ((Rect->left < 0)
902                 || (Rect->top < 0)
903                 || (Rect->left > Rect->right)
904                 || (Rect->top > Rect->bottom)
905                 || (Rect->right > This->surface_desc.dwWidth)
906                 || (Rect->bottom > This->surface_desc.dwHeight))
907         {
908             WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
909             LeaveCriticalSection(&ddraw_cs);
910             return DDERR_INVALIDPARAMS;
911         }
912     }
913
914     hr = wined3d_surface_map(This->wined3d_surface, &LockedRect, Rect, Flags);
915     if (FAILED(hr))
916     {
917         LeaveCriticalSection(&ddraw_cs);
918         switch(hr)
919         {
920             /* D3D8 and D3D9 return the general D3DERR_INVALIDCALL error, but ddraw has a more
921              * specific error. But since IWineD3DSurface::LockRect returns that error in this
922              * only occasion, keep d3d8 and d3d9 free from the return value override. There are
923              * many different places where d3d8/9 would have to catch the DDERR_SURFACEBUSY, it
924              * is much easier to do it in one place in ddraw
925              */
926             case WINED3DERR_INVALIDCALL:    return DDERR_SURFACEBUSY;
927             default:                        return hr;
928         }
929     }
930
931     /* Override the memory area. The pitch should be set already. Strangely windows
932      * does not set the LPSURFACE flag on locked surfaces !?!.
933      * DDSD->dwFlags |= DDSD_LPSURFACE;
934      */
935     This->surface_desc.lpSurface = LockedRect.pBits;
936     DD_STRUCT_COPY_BYSIZE(DDSD,&(This->surface_desc));
937
938     TRACE("locked surface returning description :\n");
939     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
940
941     LeaveCriticalSection(&ddraw_cs);
942     return DD_OK;
943 }
944
945 static HRESULT WINAPI ddraw_surface7_Lock(IDirectDrawSurface7 *iface,
946         RECT *rect, DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
947 {
948     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
949     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
950             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
951
952     if (!surface_desc) return DDERR_INVALIDPARAMS;
953     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
954             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
955     {
956         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
957         return DDERR_INVALIDPARAMS;
958     }
959     return surface_lock(This, rect, surface_desc, flags, h);
960 }
961
962 static HRESULT WINAPI ddraw_surface4_Lock(IDirectDrawSurface4 *iface, RECT *rect,
963         DDSURFACEDESC2 *surface_desc, DWORD flags, HANDLE h)
964 {
965     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
966     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
967             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
968
969     if (!surface_desc) return DDERR_INVALIDPARAMS;
970     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
971             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
972     {
973         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
974         return DDERR_INVALIDPARAMS;
975     }
976     return surface_lock(This, rect, surface_desc, flags, h);
977 }
978
979 static HRESULT WINAPI ddraw_surface3_Lock(IDirectDrawSurface3 *iface, RECT *rect,
980         DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
981 {
982     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
983     DDSURFACEDESC2 surface_desc2;
984     HRESULT hr;
985     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
986             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
987
988     if (!surface_desc) return DDERR_INVALIDPARAMS;
989     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
990             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
991     {
992         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
993         return DDERR_INVALIDPARAMS;
994     }
995
996     surface_desc2.dwSize = surface_desc->dwSize;
997     hr = surface_lock(This, rect, &surface_desc2, flags, h);
998     DDSD2_to_DDSD(&surface_desc2, surface_desc);
999     surface_desc->dwSize = surface_desc2.dwSize;
1000     return hr;
1001 }
1002
1003 static HRESULT WINAPI ddraw_surface2_Lock(IDirectDrawSurface2 *iface, RECT *rect,
1004         DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1005 {
1006     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1007     DDSURFACEDESC2 surface_desc2;
1008     HRESULT hr;
1009     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1010             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1011
1012     if (!surface_desc) return DDERR_INVALIDPARAMS;
1013     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1014             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1015     {
1016         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1017         return DDERR_INVALIDPARAMS;
1018     }
1019
1020     surface_desc2.dwSize = surface_desc->dwSize;
1021     hr = surface_lock(This, rect, &surface_desc2, flags, h);
1022     DDSD2_to_DDSD(&surface_desc2, surface_desc);
1023     surface_desc->dwSize = surface_desc2.dwSize;
1024     return hr;
1025 }
1026
1027 static HRESULT WINAPI ddraw_surface1_Lock(IDirectDrawSurface *iface, RECT *rect,
1028         DDSURFACEDESC *surface_desc, DWORD flags, HANDLE h)
1029 {
1030     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1031     DDSURFACEDESC2 surface_desc2;
1032     HRESULT hr;
1033     TRACE("iface %p, rect %s, surface_desc %p, flags %#x, h %p.\n",
1034             iface, wine_dbgstr_rect(rect), surface_desc, flags, h);
1035
1036     if (!surface_desc) return DDERR_INVALIDPARAMS;
1037     if (surface_desc->dwSize != sizeof(DDSURFACEDESC) &&
1038             surface_desc->dwSize != sizeof(DDSURFACEDESC2))
1039     {
1040         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", surface_desc->dwSize);
1041         return DDERR_INVALIDPARAMS;
1042     }
1043
1044     surface_desc2.dwSize = surface_desc->dwSize;
1045     hr = surface_lock(This, rect, &surface_desc2, flags, h);
1046     DDSD2_to_DDSD(&surface_desc2, surface_desc);
1047     surface_desc->dwSize = surface_desc2.dwSize;
1048     return hr;
1049 }
1050
1051 /*****************************************************************************
1052  * IDirectDrawSurface7::Unlock
1053  *
1054  * Unlocks an locked surface
1055  *
1056  * Params:
1057  *  Rect: Not used by this implementation
1058  *
1059  * Returns:
1060  *  D3D_OK on success
1061  *  For more details, see IWineD3DSurface::UnlockRect
1062  *
1063  *****************************************************************************/
1064 static HRESULT WINAPI ddraw_surface7_Unlock(IDirectDrawSurface7 *iface, RECT *pRect)
1065 {
1066     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1067     HRESULT hr;
1068
1069     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(pRect));
1070
1071     EnterCriticalSection(&ddraw_cs);
1072     hr = wined3d_surface_unmap(This->wined3d_surface);
1073     if (SUCCEEDED(hr))
1074     {
1075         This->surface_desc.lpSurface = NULL;
1076     }
1077     LeaveCriticalSection(&ddraw_cs);
1078     return hr;
1079 }
1080
1081 static HRESULT WINAPI ddraw_surface4_Unlock(IDirectDrawSurface4 *iface, RECT *pRect)
1082 {
1083     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1084     TRACE("iface %p, rect %p.\n", iface, pRect);
1085
1086     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, pRect);
1087 }
1088
1089 static HRESULT WINAPI ddraw_surface3_Unlock(IDirectDrawSurface3 *iface, void *data)
1090 {
1091     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1092     TRACE("iface %p, data %p.\n", iface, data);
1093
1094     /* data might not be the LPRECT of later versions, so drop it. */
1095     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, NULL);
1096 }
1097
1098 static HRESULT WINAPI ddraw_surface2_Unlock(IDirectDrawSurface2 *iface, void *data)
1099 {
1100     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1101     TRACE("iface %p, data %p.\n", iface, data);
1102
1103     /* data might not be the LPRECT of later versions, so drop it. */
1104     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, NULL);
1105 }
1106
1107 static HRESULT WINAPI ddraw_surface1_Unlock(IDirectDrawSurface *iface, void *data)
1108 {
1109     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1110     TRACE("iface %p, data %p.\n", iface, data);
1111
1112     /* data might not be the LPRECT of later versions, so drop it. */
1113     return ddraw_surface7_Unlock(&This->IDirectDrawSurface7_iface, NULL);
1114 }
1115
1116 /*****************************************************************************
1117  * IDirectDrawSurface7::Flip
1118  *
1119  * Flips a surface with the DDSCAPS_FLIP flag. The flip is relayed to
1120  * IWineD3DSurface::Flip. Because WineD3D doesn't handle attached surfaces,
1121  * the flip target is passed to WineD3D, even if the app didn't specify one
1122  *
1123  * Params:
1124  *  DestOverride: Specifies the surface that will become the new front
1125  *                buffer. If NULL, the current back buffer is used
1126  *  Flags: some DirectDraw flags, see include/ddraw.h
1127  *
1128  * Returns:
1129  *  DD_OK on success
1130  *  DDERR_NOTFLIPPABLE if no flip target could be found
1131  *  DDERR_INVALIDOBJECT if the surface isn't a front buffer
1132  *  For more details, see IWineD3DSurface::Flip
1133  *
1134  *****************************************************************************/
1135 static HRESULT WINAPI ddraw_surface7_Flip(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *DestOverride, DWORD Flags)
1136 {
1137     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1138     IDirectDrawSurfaceImpl *Override = unsafe_impl_from_IDirectDrawSurface7(DestOverride);
1139     IDirectDrawSurface7 *Override7;
1140     HRESULT hr;
1141
1142     TRACE("iface %p, dst %p, flags %#x.\n", iface, DestOverride, Flags);
1143
1144     /* Flip has to be called from a front buffer
1145      * What about overlay surfaces, AFAIK they can flip too?
1146      */
1147     if( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_OVERLAY)) )
1148         return DDERR_INVALIDOBJECT; /* Unchecked */
1149
1150     EnterCriticalSection(&ddraw_cs);
1151
1152     /* WineD3D doesn't keep track of attached surface, so find the target */
1153     if(!Override)
1154     {
1155         DDSCAPS2 Caps;
1156
1157         memset(&Caps, 0, sizeof(Caps));
1158         Caps.dwCaps |= DDSCAPS_BACKBUFFER;
1159         hr = ddraw_surface7_GetAttachedSurface(iface, &Caps, &Override7);
1160         if(hr != DD_OK)
1161         {
1162             ERR("Can't find a flip target\n");
1163             LeaveCriticalSection(&ddraw_cs);
1164             return DDERR_NOTFLIPPABLE; /* Unchecked */
1165         }
1166         Override = impl_from_IDirectDrawSurface7(Override7);
1167
1168         /* For the GetAttachedSurface */
1169         ddraw_surface7_Release(Override7);
1170     }
1171
1172     hr = wined3d_surface_flip(This->wined3d_surface, Override->wined3d_surface, Flags);
1173     LeaveCriticalSection(&ddraw_cs);
1174     return hr;
1175 }
1176
1177 static HRESULT WINAPI ddraw_surface4_Flip(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *dst, DWORD flags)
1178 {
1179     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1180     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst);
1181     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1182
1183     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
1184             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1185 }
1186
1187 static HRESULT WINAPI ddraw_surface3_Flip(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *dst, DWORD flags)
1188 {
1189     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1190     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst);
1191     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1192
1193     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
1194             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1195 }
1196
1197 static HRESULT WINAPI ddraw_surface2_Flip(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *dst, DWORD flags)
1198 {
1199     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1200     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst);
1201     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1202
1203     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
1204             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1205 }
1206
1207 static HRESULT WINAPI ddraw_surface1_Flip(IDirectDrawSurface *iface, IDirectDrawSurface *dst, DWORD flags)
1208 {
1209     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1210     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst);
1211     TRACE("iface %p, dst %p, flags %#x.\n", iface, dst, flags);
1212
1213     return ddraw_surface7_Flip(&This->IDirectDrawSurface7_iface,
1214             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, flags);
1215 }
1216
1217 /*****************************************************************************
1218  * IDirectDrawSurface7::Blt
1219  *
1220  * Performs a blit on the surface
1221  *
1222  * Params:
1223  *  DestRect: Destination rectangle, can be NULL
1224  *  SrcSurface: Source surface, can be NULL
1225  *  SrcRect: Source rectangle, can be NULL
1226  *  Flags: Blt flags
1227  *  DDBltFx: Some extended blt parameters, connected to the flags
1228  *
1229  * Returns:
1230  *  D3D_OK on success
1231  *  See IWineD3DSurface::Blt for more details
1232  *
1233  *****************************************************************************/
1234 static HRESULT WINAPI ddraw_surface7_Blt(IDirectDrawSurface7 *iface, RECT *DestRect,
1235         IDirectDrawSurface7 *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx)
1236 {
1237     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1238     IDirectDrawSurfaceImpl *Src = unsafe_impl_from_IDirectDrawSurface7(SrcSurface);
1239     HRESULT hr;
1240
1241     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1242             iface, wine_dbgstr_rect(DestRect), SrcSurface, wine_dbgstr_rect(SrcRect), Flags, DDBltFx);
1243
1244     /* Check for validity of the flags here. WineD3D Has the software-opengl selection path and would have
1245      * to check at 2 places, and sometimes do double checks. This also saves the call to wined3d :-)
1246      */
1247     if((Flags & DDBLT_KEYSRCOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYSRC)) {
1248         WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
1249         return DDERR_INVALIDPARAMS;
1250     }
1251
1252     if((Flags & DDBLT_KEYDESTOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYDEST)) {
1253         WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
1254         return DDERR_INVALIDPARAMS;
1255     }
1256
1257     EnterCriticalSection(&ddraw_cs);
1258
1259     if(Flags & DDBLT_KEYSRC && (!Src || !(Src->surface_desc.dwFlags & DDSD_CKSRCBLT))) {
1260         WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
1261         LeaveCriticalSection(&ddraw_cs);
1262         return DDERR_INVALIDPARAMS;
1263     }
1264
1265     /* TODO: Check if the DDBltFx contains any ddraw surface pointers. If it
1266      * does, copy the struct, and replace the ddraw surfaces with the wined3d
1267      * surfaces. So far no blitting operations using surfaces in the bltfx
1268      * struct are supported anyway. */
1269     hr = wined3d_surface_blt(This->wined3d_surface, DestRect, Src ? Src->wined3d_surface : NULL,
1270             SrcRect, Flags, (WINEDDBLTFX *)DDBltFx, WINED3DTEXF_LINEAR);
1271
1272     LeaveCriticalSection(&ddraw_cs);
1273     switch(hr)
1274     {
1275         case WINED3DERR_NOTAVAILABLE:       return DDERR_UNSUPPORTED;
1276         case WINED3DERR_WRONGTEXTUREFORMAT: return DDERR_INVALIDPIXELFORMAT;
1277         default:                            return hr;
1278     }
1279 }
1280
1281 static HRESULT WINAPI ddraw_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect,
1282         IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1283 {
1284     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1285     IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface4(src_surface);
1286     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1287             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1288
1289     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
1290             src ? &src->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1291 }
1292
1293 static HRESULT WINAPI ddraw_surface3_Blt(IDirectDrawSurface3 *iface, RECT *dst_rect,
1294         IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1295 {
1296     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1297     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
1298     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1299             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1300
1301     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
1302             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1303 }
1304
1305 static HRESULT WINAPI ddraw_surface2_Blt(IDirectDrawSurface2 *iface, RECT *dst_rect,
1306         IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1307 {
1308     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1309     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
1310     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1311             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1312
1313     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
1314             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1315 }
1316
1317 static HRESULT WINAPI ddraw_surface1_Blt(IDirectDrawSurface *iface, RECT *dst_rect,
1318         IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
1319 {
1320     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1321     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
1322     TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
1323             iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);
1324
1325     return ddraw_surface7_Blt(&This->IDirectDrawSurface7_iface, dst_rect,
1326             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags, fx);
1327 }
1328
1329 /*****************************************************************************
1330  * IDirectDrawSurface7::AddAttachedSurface
1331  *
1332  * Attaches a surface to another surface. How the surface attachments work
1333  * is not totally understood yet, and this method is prone to problems.
1334  * he surface that is attached is AddRef-ed.
1335  *
1336  * Tests with complex surfaces suggest that the surface attachments form a
1337  * tree, but no method to test this has been found yet.
1338  *
1339  * The attachment list consists of a first surface (first_attached) and
1340  * for each surface a pointer to the next attached surface (next_attached).
1341  * For the first surface, and a surface that has no attachments
1342  * first_attached points to the surface itself. A surface that has
1343  * no successors in the chain has next_attached set to NULL.
1344  *
1345  * Newly attached surfaces are attached right after the root surface.
1346  * If a surface is attached to a complex surface compound, it's attached to
1347  * the surface that the app requested, not the complex root. See
1348  * GetAttachedSurface for a description how surfaces are found.
1349  *
1350  * This is how the current implementation works, and it was coded by looking
1351  * at the needs of the applications.
1352  *
1353  * So far only Z-Buffer attachments are tested, and they are activated in
1354  * WineD3D. Mipmaps could be tricky to activate in WineD3D.
1355  * Back buffers should work in 2D mode, but they are not tested(They can be
1356  * attached in older iface versions). Rendering to the front buffer and
1357  * switching between that and double buffering is not yet implemented in
1358  * WineD3D, so for 3D it might have unexpected results.
1359  *
1360  * ddraw_surface_attach_surface is the real thing,
1361  * ddraw_surface7_AddAttachedSurface is a wrapper around it that
1362  * performs additional checks. Version 7 of this interface is much more restrictive
1363  * than its predecessors.
1364  *
1365  * Params:
1366  *  Attach: Surface to attach to iface
1367  *
1368  * Returns:
1369  *  DD_OK on success
1370  *  DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
1371  *
1372  *****************************************************************************/
1373 static HRESULT ddraw_surface_attach_surface(IDirectDrawSurfaceImpl *This, IDirectDrawSurfaceImpl *Surf)
1374 {
1375     TRACE("surface %p, attachment %p.\n", This, Surf);
1376
1377     if(Surf == This)
1378         return DDERR_CANNOTATTACHSURFACE; /* unchecked */
1379
1380     EnterCriticalSection(&ddraw_cs);
1381
1382     /* Check if the surface is already attached somewhere */
1383     if (Surf->next_attached || Surf->first_attached != Surf)
1384     {
1385         /* TODO: Test for the structure of the manual attachment. Is it a
1386          * chain or a list? What happens if one surface is attached to 2
1387          * different surfaces? */
1388         WARN("Surface %p is already attached somewhere. next_attached %p, first_attached %p.\n",
1389                 Surf, Surf->next_attached, Surf->first_attached);
1390
1391         LeaveCriticalSection(&ddraw_cs);
1392         return DDERR_SURFACEALREADYATTACHED;
1393     }
1394
1395     /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
1396     Surf->next_attached = This->next_attached;
1397     Surf->first_attached = This->first_attached;
1398     This->next_attached = Surf;
1399
1400     /* Check if the WineD3D depth stencil needs updating */
1401     if(This->ddraw->d3ddevice)
1402     {
1403         IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
1404     }
1405
1406     LeaveCriticalSection(&ddraw_cs);
1407     return DD_OK;
1408 }
1409
1410 static HRESULT WINAPI ddraw_surface7_AddAttachedSurface(IDirectDrawSurface7 *iface, IDirectDrawSurface7 *Attach)
1411 {
1412     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1413     IDirectDrawSurfaceImpl *Surf = unsafe_impl_from_IDirectDrawSurface7(Attach);
1414     HRESULT hr;
1415
1416     TRACE("iface %p, attachment %p.\n", iface, Attach);
1417
1418     /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
1419     if(!(Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
1420     {
1421
1422         WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
1423               Surf->surface_desc.ddsCaps.dwCaps);
1424         return DDERR_CANNOTATTACHSURFACE;
1425     }
1426
1427     hr = ddraw_surface_attach_surface(This, Surf);
1428     if (FAILED(hr))
1429     {
1430         return hr;
1431     }
1432     ddraw_surface7_AddRef(Attach);
1433     return hr;
1434 }
1435
1436 static HRESULT WINAPI ddraw_surface4_AddAttachedSurface(IDirectDrawSurface4 *iface, IDirectDrawSurface4 *attachment)
1437 {
1438     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1439     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
1440     HRESULT hr;
1441
1442     TRACE("iface %p, attachment %p.\n", iface, attachment);
1443
1444     hr = ddraw_surface7_AddAttachedSurface(&This->IDirectDrawSurface7_iface,
1445             attachment_impl ? &attachment_impl->IDirectDrawSurface7_iface : NULL);
1446     if (FAILED(hr))
1447     {
1448         return hr;
1449     }
1450     ddraw_surface4_AddRef(attachment);
1451     ddraw_surface7_Release(&attachment_impl->IDirectDrawSurface7_iface);
1452     return hr;
1453 }
1454 static HRESULT WINAPI ddraw_surface3_AddAttachedSurface(IDirectDrawSurface3 *iface, IDirectDrawSurface3 *attachment)
1455 {
1456     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1457     IDirectDrawSurfaceImpl *attach_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
1458     HRESULT hr;
1459
1460     TRACE("iface %p, attachment %p.\n", iface, attachment);
1461
1462     /* Tests suggest that
1463      * -> offscreen plain surfaces can be attached to other offscreen plain surfaces
1464      * -> offscreen plain surfaces can be attached to primaries
1465      * -> primaries can be attached to offscreen plain surfaces
1466      * -> z buffers can be attached to primaries */
1467     if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN)
1468             && attach_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_OFFSCREENPLAIN))
1469     {
1470         /* Sizes have to match */
1471         if (attach_impl->surface_desc.dwWidth != This->surface_desc.dwWidth
1472                 || attach_impl->surface_desc.dwHeight != This->surface_desc.dwHeight)
1473         {
1474             WARN("Surface sizes do not match.\n");
1475             return DDERR_CANNOTATTACHSURFACE;
1476         }
1477         /* OK */
1478     }
1479     else if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE)
1480             && attach_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER))
1481     {
1482         /* OK */
1483     }
1484     else
1485     {
1486         WARN("Invalid attachment combination.\n");
1487         return DDERR_CANNOTATTACHSURFACE;
1488     }
1489
1490     hr = ddraw_surface_attach_surface(This, attach_impl);
1491     if (FAILED(hr))
1492     {
1493         return hr;
1494     }
1495     ddraw_surface3_AddRef(attachment);
1496     return hr;
1497 }
1498
1499 static HRESULT WINAPI ddraw_surface2_AddAttachedSurface(IDirectDrawSurface2 *iface, IDirectDrawSurface2 *attachment)
1500 {
1501     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1502     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
1503     HRESULT hr;
1504
1505     TRACE("iface %p, attachment %p.\n", iface, attachment);
1506
1507     hr = ddraw_surface3_AddAttachedSurface(&This->IDirectDrawSurface3_iface,
1508             attachment_impl ? &attachment_impl->IDirectDrawSurface3_iface : NULL);
1509     if (FAILED(hr))
1510     {
1511         return hr;
1512     }
1513     ddraw_surface2_AddRef(attachment);
1514     ddraw_surface3_Release(&attachment_impl->IDirectDrawSurface3_iface);
1515     return hr;
1516 }
1517
1518 static HRESULT WINAPI ddraw_surface1_AddAttachedSurface(IDirectDrawSurface *iface, IDirectDrawSurface *attachment)
1519 {
1520     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1521     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
1522     HRESULT hr;
1523
1524     TRACE("iface %p, attachment %p.\n", iface, attachment);
1525
1526     hr = ddraw_surface3_AddAttachedSurface(&This->IDirectDrawSurface3_iface,
1527             attachment_impl ? &attachment_impl->IDirectDrawSurface3_iface : NULL);
1528     if (FAILED(hr))
1529     {
1530         return hr;
1531     }
1532     ddraw_surface1_AddRef(attachment);
1533     ddraw_surface3_Release(&attachment_impl->IDirectDrawSurface3_iface);
1534     return hr;
1535 }
1536
1537 /*****************************************************************************
1538  * IDirectDrawSurface7::DeleteAttachedSurface
1539  *
1540  * Removes a surface from the attachment chain. The surface's refcount
1541  * is decreased by one after it has been removed
1542  *
1543  * Params:
1544  *  Flags: Some flags, not used by this implementation
1545  *  Attach: Surface to detach
1546  *
1547  * Returns:
1548  *  DD_OK on success
1549  *  DDERR_SURFACENOTATTACHED if the surface isn't attached to
1550  *
1551  *****************************************************************************/
1552 static HRESULT ddraw_surface_delete_attached_surface(IDirectDrawSurfaceImpl *This,
1553         IDirectDrawSurfaceImpl *Surf)
1554 {
1555     IDirectDrawSurfaceImpl *Prev = This;
1556
1557     TRACE("surface %p, attachment %p.\n", This, Surf);
1558
1559     EnterCriticalSection(&ddraw_cs);
1560     if (!Surf || (Surf->first_attached != This) || (Surf == This) )
1561     {
1562         LeaveCriticalSection(&ddraw_cs);
1563         return DDERR_CANNOTDETACHSURFACE;
1564     }
1565
1566     /* Remove MIPMAPSUBLEVEL if this seemed to be one */
1567     if (This->surface_desc.ddsCaps.dwCaps &
1568         Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
1569     {
1570         Surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
1571         /* FIXME: we should probably also subtract from dwMipMapCount of this
1572          * and all parent surfaces */
1573     }
1574
1575     /* Find the predecessor of the detached surface */
1576     while(Prev)
1577     {
1578         if(Prev->next_attached == Surf) break;
1579         Prev = Prev->next_attached;
1580     }
1581
1582     /* There must be a surface, otherwise there's a bug */
1583     assert(Prev != NULL);
1584
1585     /* Unchain the surface */
1586     Prev->next_attached = Surf->next_attached;
1587     Surf->next_attached = NULL;
1588     Surf->first_attached = Surf;
1589
1590     /* Check if the WineD3D depth stencil needs updating */
1591     if(This->ddraw->d3ddevice)
1592     {
1593         IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
1594     }
1595     LeaveCriticalSection(&ddraw_cs);
1596     return DD_OK;
1597 }
1598
1599 static HRESULT WINAPI ddraw_surface7_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
1600         DWORD flags, IDirectDrawSurface7 *attachment)
1601 {
1602     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1603     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface7(attachment);
1604     HRESULT hr;
1605
1606     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1607
1608     hr = ddraw_surface_delete_attached_surface(This, attachment_impl);
1609     if (FAILED(hr))
1610     {
1611         return hr;
1612     }
1613     ddraw_surface7_Release(attachment);
1614     return hr;
1615 }
1616
1617 static HRESULT WINAPI ddraw_surface4_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
1618         DWORD flags, IDirectDrawSurface4 *attachment)
1619 {
1620     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1621     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface4(attachment);
1622     HRESULT hr;
1623
1624     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1625
1626     hr = ddraw_surface_delete_attached_surface(This, attachment_impl);
1627     if (FAILED(hr))
1628     {
1629         return hr;
1630     }
1631     ddraw_surface4_Release(attachment);
1632     return hr;
1633 }
1634
1635 static HRESULT WINAPI ddraw_surface3_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
1636         DWORD flags, IDirectDrawSurface3 *attachment)
1637 {
1638     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1639     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface3(attachment);
1640     HRESULT hr;
1641     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1642
1643     hr = ddraw_surface_delete_attached_surface(This, attachment_impl);
1644     if (FAILED(hr))
1645     {
1646         return hr;
1647     }
1648     ddraw_surface3_Release(attachment);
1649     return hr;
1650 }
1651
1652 static HRESULT WINAPI ddraw_surface2_DeleteAttachedSurface(IDirectDrawSurface2 *iface,
1653         DWORD flags, IDirectDrawSurface2 *attachment)
1654 {
1655     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1656     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface2(attachment);
1657     HRESULT hr;
1658     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1659
1660     hr = ddraw_surface_delete_attached_surface(This, attachment_impl);
1661     if (FAILED(hr))
1662     {
1663         return hr;
1664     }
1665     ddraw_surface2_Release(attachment);
1666     return hr;
1667 }
1668
1669 static HRESULT WINAPI ddraw_surface1_DeleteAttachedSurface(IDirectDrawSurface *iface,
1670         DWORD flags, IDirectDrawSurface *attachment)
1671 {
1672     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1673     IDirectDrawSurfaceImpl *attachment_impl = unsafe_impl_from_IDirectDrawSurface(attachment);
1674     HRESULT hr;
1675     TRACE("iface %p, flags %#x, attachment %p.\n", iface, flags, attachment);
1676
1677     hr = ddraw_surface_delete_attached_surface(This, attachment_impl);
1678     if (FAILED(hr))
1679     {
1680         return hr;
1681     }
1682     ddraw_surface1_Release(attachment);
1683     return hr;
1684 }
1685
1686 /*****************************************************************************
1687  * IDirectDrawSurface7::AddOverlayDirtyRect
1688  *
1689  * "This method is not currently implemented"
1690  *
1691  * Params:
1692  *  Rect: ?
1693  *
1694  * Returns:
1695  *  DDERR_UNSUPPORTED
1696  *
1697  *****************************************************************************/
1698 static HRESULT WINAPI ddraw_surface7_AddOverlayDirtyRect(IDirectDrawSurface7 *iface, RECT *Rect)
1699 {
1700     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(Rect));
1701
1702     return DDERR_UNSUPPORTED; /* unchecked */
1703 }
1704
1705 static HRESULT WINAPI ddraw_surface4_AddOverlayDirtyRect(IDirectDrawSurface4 *iface, RECT *rect)
1706 {
1707     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1708     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1709
1710     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
1711 }
1712
1713 static HRESULT WINAPI ddraw_surface3_AddOverlayDirtyRect(IDirectDrawSurface3 *iface, RECT *rect)
1714 {
1715     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1716     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1717
1718     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
1719 }
1720
1721 static HRESULT WINAPI ddraw_surface2_AddOverlayDirtyRect(IDirectDrawSurface2 *iface, RECT *rect)
1722 {
1723     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1724     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1725
1726     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
1727 }
1728
1729 static HRESULT WINAPI ddraw_surface1_AddOverlayDirtyRect(IDirectDrawSurface *iface, RECT *rect)
1730 {
1731     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1732     TRACE("iface %p, rect %s.\n", iface, wine_dbgstr_rect(rect));
1733
1734     return ddraw_surface7_AddOverlayDirtyRect(&This->IDirectDrawSurface7_iface, rect);
1735 }
1736
1737 /*****************************************************************************
1738  * IDirectDrawSurface7::GetDC
1739  *
1740  * Returns a GDI device context for the surface
1741  *
1742  * Params:
1743  *  hdc: Address of a HDC variable to store the dc to
1744  *
1745  * Returns:
1746  *  DD_OK on success
1747  *  DDERR_INVALIDPARAMS if hdc is NULL
1748  *  For details, see IWineD3DSurface::GetDC
1749  *
1750  *****************************************************************************/
1751 static HRESULT WINAPI ddraw_surface7_GetDC(IDirectDrawSurface7 *iface, HDC *hdc)
1752 {
1753     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1754     HRESULT hr;
1755
1756     TRACE("iface %p, dc %p.\n", iface, hdc);
1757
1758     if(!hdc)
1759         return DDERR_INVALIDPARAMS;
1760
1761     EnterCriticalSection(&ddraw_cs);
1762     hr = wined3d_surface_getdc(This->wined3d_surface, hdc);
1763     LeaveCriticalSection(&ddraw_cs);
1764     switch(hr)
1765     {
1766         /* Some, but not all errors set *hdc to NULL. E.g. DCALREADYCREATED does not
1767          * touch *hdc
1768          */
1769         case WINED3DERR_INVALIDCALL:
1770             if(hdc) *hdc = NULL;
1771             return DDERR_INVALIDPARAMS;
1772
1773         default: return hr;
1774     }
1775 }
1776
1777 static HRESULT WINAPI ddraw_surface4_GetDC(IDirectDrawSurface4 *iface, HDC *dc)
1778 {
1779     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1780     TRACE("iface %p, dc %p.\n", iface, dc);
1781
1782     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
1783 }
1784
1785 static HRESULT WINAPI ddraw_surface3_GetDC(IDirectDrawSurface3 *iface, HDC *dc)
1786 {
1787     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1788     TRACE("iface %p, dc %p.\n", iface, dc);
1789
1790     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
1791 }
1792
1793 static HRESULT WINAPI ddraw_surface2_GetDC(IDirectDrawSurface2 *iface, HDC *dc)
1794 {
1795     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1796     TRACE("iface %p, dc %p.\n", iface, dc);
1797
1798     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
1799 }
1800
1801 static HRESULT WINAPI ddraw_surface1_GetDC(IDirectDrawSurface *iface, HDC *dc)
1802 {
1803     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1804     TRACE("iface %p, dc %p.\n", iface, dc);
1805
1806     return ddraw_surface7_GetDC(&This->IDirectDrawSurface7_iface, dc);
1807 }
1808
1809 /*****************************************************************************
1810  * IDirectDrawSurface7::ReleaseDC
1811  *
1812  * Releases the DC that was constructed with GetDC
1813  *
1814  * Params:
1815  *  hdc: HDC to release
1816  *
1817  * Returns:
1818  *  DD_OK on success
1819  *  For more details, see IWineD3DSurface::ReleaseDC
1820  *
1821  *****************************************************************************/
1822 static HRESULT WINAPI ddraw_surface7_ReleaseDC(IDirectDrawSurface7 *iface, HDC hdc)
1823 {
1824     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1825     HRESULT hr;
1826
1827     TRACE("iface %p, dc %p.\n", iface, hdc);
1828
1829     EnterCriticalSection(&ddraw_cs);
1830     hr = wined3d_surface_releasedc(This->wined3d_surface, hdc);
1831     LeaveCriticalSection(&ddraw_cs);
1832     return hr;
1833 }
1834
1835 static HRESULT WINAPI ddraw_surface4_ReleaseDC(IDirectDrawSurface4 *iface, HDC dc)
1836 {
1837     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1838     TRACE("iface %p, dc %p.\n", iface, dc);
1839
1840     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
1841 }
1842
1843 static HRESULT WINAPI ddraw_surface3_ReleaseDC(IDirectDrawSurface3 *iface, HDC dc)
1844 {
1845     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1846     TRACE("iface %p, dc %p.\n", iface, dc);
1847
1848     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
1849 }
1850
1851 static HRESULT WINAPI ddraw_surface2_ReleaseDC(IDirectDrawSurface2 *iface, HDC dc)
1852 {
1853     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1854     TRACE("iface %p, dc %p.\n", iface, dc);
1855
1856     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
1857 }
1858
1859 static HRESULT WINAPI ddraw_surface1_ReleaseDC(IDirectDrawSurface *iface, HDC dc)
1860 {
1861     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1862     TRACE("iface %p, dc %p.\n", iface, dc);
1863
1864     return ddraw_surface7_ReleaseDC(&This->IDirectDrawSurface7_iface, dc);
1865 }
1866
1867 /*****************************************************************************
1868  * IDirectDrawSurface7::GetCaps
1869  *
1870  * Returns the surface's caps
1871  *
1872  * Params:
1873  *  Caps: Address to write the caps to
1874  *
1875  * Returns:
1876  *  DD_OK on success
1877  *  DDERR_INVALIDPARAMS if Caps is NULL
1878  *
1879  *****************************************************************************/
1880 static HRESULT WINAPI ddraw_surface7_GetCaps(IDirectDrawSurface7 *iface, DDSCAPS2 *Caps)
1881 {
1882     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1883
1884     TRACE("iface %p, caps %p.\n", iface, Caps);
1885
1886     if(!Caps)
1887         return DDERR_INVALIDPARAMS;
1888
1889     *Caps = This->surface_desc.ddsCaps;
1890     return DD_OK;
1891 }
1892
1893 static HRESULT WINAPI ddraw_surface4_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *caps)
1894 {
1895     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
1896     TRACE("iface %p, caps %p.\n", iface, caps);
1897
1898     return ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, caps);
1899 }
1900
1901 static HRESULT WINAPI ddraw_surface3_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *caps)
1902 {
1903     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
1904     DDSCAPS2 caps2;
1905     HRESULT hr;
1906
1907     TRACE("iface %p, caps %p.\n", iface, caps);
1908
1909     hr = ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, &caps2);
1910     if (FAILED(hr)) return hr;
1911
1912     caps->dwCaps = caps2.dwCaps;
1913     return hr;
1914 }
1915
1916 static HRESULT WINAPI ddraw_surface2_GetCaps(IDirectDrawSurface2 *iface, DDSCAPS *caps)
1917 {
1918     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
1919     DDSCAPS2 caps2;
1920     HRESULT hr;
1921
1922     TRACE("iface %p, caps %p.\n", iface, caps);
1923
1924     hr = ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, &caps2);
1925     if (FAILED(hr)) return hr;
1926
1927     caps->dwCaps = caps2.dwCaps;
1928     return hr;
1929 }
1930
1931 static HRESULT WINAPI ddraw_surface1_GetCaps(IDirectDrawSurface *iface, DDSCAPS *caps)
1932 {
1933     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
1934     DDSCAPS2 caps2;
1935     HRESULT hr;
1936
1937     TRACE("iface %p, caps %p.\n", iface, caps);
1938
1939     hr = ddraw_surface7_GetCaps(&This->IDirectDrawSurface7_iface, &caps2);
1940     if (FAILED(hr)) return hr;
1941
1942     caps->dwCaps = caps2.dwCaps;
1943     return hr;
1944 }
1945
1946 /*****************************************************************************
1947  * IDirectDrawSurface7::SetPriority
1948  *
1949  * Sets a texture priority for managed textures.
1950  *
1951  * Params:
1952  *  Priority: The new priority
1953  *
1954  * Returns:
1955  *  DD_OK on success
1956  *  For more details, see IWineD3DSurface::SetPriority
1957  *
1958  *****************************************************************************/
1959 static HRESULT WINAPI ddraw_surface7_SetPriority(IDirectDrawSurface7 *iface, DWORD Priority)
1960 {
1961     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1962     HRESULT hr;
1963
1964     TRACE("iface %p, priority %u.\n", iface, Priority);
1965
1966     EnterCriticalSection(&ddraw_cs);
1967     hr = wined3d_surface_set_priority(This->wined3d_surface, Priority);
1968     LeaveCriticalSection(&ddraw_cs);
1969     return hr;
1970 }
1971
1972 /*****************************************************************************
1973  * IDirectDrawSurface7::GetPriority
1974  *
1975  * Returns the surface's priority
1976  *
1977  * Params:
1978  *  Priority: Address of a variable to write the priority to
1979  *
1980  * Returns:
1981  *  D3D_OK on success
1982  *  DDERR_INVALIDPARAMS if Priority == NULL
1983  *  For more details, see IWineD3DSurface::GetPriority
1984  *
1985  *****************************************************************************/
1986 static HRESULT WINAPI ddraw_surface7_GetPriority(IDirectDrawSurface7 *iface, DWORD *Priority)
1987 {
1988     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
1989
1990     TRACE("iface %p, priority %p.\n", iface, Priority);
1991
1992     if(!Priority)
1993     {
1994         return DDERR_INVALIDPARAMS;
1995     }
1996
1997     EnterCriticalSection(&ddraw_cs);
1998     *Priority = wined3d_surface_get_priority(This->wined3d_surface);
1999     LeaveCriticalSection(&ddraw_cs);
2000     return DD_OK;
2001 }
2002
2003 /*****************************************************************************
2004  * IDirectDrawSurface7::SetPrivateData
2005  *
2006  * Stores some data in the surface that is intended for the application's
2007  * use.
2008  *
2009  * Params:
2010  *  tag: GUID that identifies the data
2011  *  Data: Pointer to the private data
2012  *  Size: Size of the private data
2013  *  Flags: Some flags
2014  *
2015  * Returns:
2016  *  D3D_OK on success
2017  *  For more details, see IWineD3DSurface::SetPrivateData
2018  *
2019  *****************************************************************************/
2020 static HRESULT WINAPI ddraw_surface7_SetPrivateData(IDirectDrawSurface7 *iface,
2021         REFGUID tag, void *Data, DWORD Size, DWORD Flags)
2022 {
2023     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2024     struct wined3d_resource *resource;
2025     HRESULT hr;
2026
2027     TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2028             iface, debugstr_guid(tag), Data, Size, Flags);
2029
2030     EnterCriticalSection(&ddraw_cs);
2031     resource = wined3d_surface_get_resource(This->wined3d_surface);
2032     hr = wined3d_resource_set_private_data(resource, tag, Data, Size, Flags);
2033     LeaveCriticalSection(&ddraw_cs);
2034     switch(hr)
2035     {
2036         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
2037         default:                            return hr;
2038     }
2039 }
2040
2041 static HRESULT WINAPI ddraw_surface4_SetPrivateData(IDirectDrawSurface4 *iface,
2042         REFGUID tag, void *data, DWORD size, DWORD flags)
2043 {
2044     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2045     TRACE("iface %p, tag %s, data %p, data_size %u, flags %#x.\n",
2046                 iface, debugstr_guid(tag), data, size, flags);
2047
2048     return ddraw_surface7_SetPrivateData(&This->IDirectDrawSurface7_iface, tag, data, size, flags);
2049 }
2050
2051 /*****************************************************************************
2052  * IDirectDrawSurface7::GetPrivateData
2053  *
2054  * Returns the private data set with IDirectDrawSurface7::SetPrivateData
2055  *
2056  * Params:
2057  *  tag: GUID of the data to return
2058  *  Data: Address where to write the data to
2059  *  Size: Size of the buffer at Data
2060  *
2061  * Returns:
2062  *  DD_OK on success
2063  *  DDERR_INVALIDPARAMS if Data is NULL
2064  *  For more details, see IWineD3DSurface::GetPrivateData
2065  *
2066  *****************************************************************************/
2067 static HRESULT WINAPI ddraw_surface7_GetPrivateData(IDirectDrawSurface7 *iface, REFGUID tag, void *Data, DWORD *Size)
2068 {
2069     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2070     struct wined3d_resource *resource;
2071     HRESULT hr;
2072
2073     TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2074             iface, debugstr_guid(tag), Data, Size);
2075
2076     if(!Data)
2077         return DDERR_INVALIDPARAMS;
2078
2079     EnterCriticalSection(&ddraw_cs);
2080     resource = wined3d_surface_get_resource(This->wined3d_surface);
2081     hr = wined3d_resource_get_private_data(resource, tag, Data, Size);
2082     LeaveCriticalSection(&ddraw_cs);
2083     return hr;
2084 }
2085
2086 static HRESULT WINAPI ddraw_surface4_GetPrivateData(IDirectDrawSurface4 *iface, REFGUID tag, void *data, DWORD *size)
2087 {
2088     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2089     TRACE("iface %p, tag %s, data %p, data_size %p.\n",
2090                 iface, debugstr_guid(tag), data, size);
2091
2092     return ddraw_surface7_GetPrivateData(&This->IDirectDrawSurface7_iface, tag, data, size);
2093 }
2094
2095 /*****************************************************************************
2096  * IDirectDrawSurface7::FreePrivateData
2097  *
2098  * Frees private data stored in the surface
2099  *
2100  * Params:
2101  *  tag: Tag of the data to free
2102  *
2103  * Returns:
2104  *  D3D_OK on success
2105  *  For more details, see IWineD3DSurface::FreePrivateData
2106  *
2107  *****************************************************************************/
2108 static HRESULT WINAPI ddraw_surface7_FreePrivateData(IDirectDrawSurface7 *iface, REFGUID tag)
2109 {
2110     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2111     struct wined3d_resource *resource;
2112     HRESULT hr;
2113
2114     TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2115
2116     EnterCriticalSection(&ddraw_cs);
2117     resource = wined3d_surface_get_resource(This->wined3d_surface);
2118     hr = wined3d_resource_free_private_data(resource, tag);
2119     LeaveCriticalSection(&ddraw_cs);
2120     return hr;
2121 }
2122
2123 static HRESULT WINAPI ddraw_surface4_FreePrivateData(IDirectDrawSurface4 *iface, REFGUID tag)
2124 {
2125     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2126     TRACE("iface %p, tag %s.\n", iface, debugstr_guid(tag));
2127
2128     return ddraw_surface7_FreePrivateData(&This->IDirectDrawSurface7_iface, tag);
2129 }
2130
2131 /*****************************************************************************
2132  * IDirectDrawSurface7::PageLock
2133  *
2134  * Prevents a sysmem surface from being paged out
2135  *
2136  * Params:
2137  *  Flags: Not used, must be 0(unchecked)
2138  *
2139  * Returns:
2140  *  DD_OK, because it's a stub
2141  *
2142  *****************************************************************************/
2143 static HRESULT WINAPI ddraw_surface7_PageLock(IDirectDrawSurface7 *iface, DWORD Flags)
2144 {
2145     TRACE("iface %p, flags %#x.\n", iface, Flags);
2146
2147     /* This is Windows memory management related - we don't need this */
2148     return DD_OK;
2149 }
2150
2151 static HRESULT WINAPI ddraw_surface4_PageLock(IDirectDrawSurface4 *iface, DWORD flags)
2152 {
2153     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2154     TRACE("iface %p, flags %#x.\n", iface, flags);
2155
2156     return ddraw_surface7_PageLock(&This->IDirectDrawSurface7_iface, flags);
2157 }
2158
2159 static HRESULT WINAPI ddraw_surface3_PageLock(IDirectDrawSurface3 *iface, DWORD flags)
2160 {
2161     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2162     TRACE("iface %p, flags %#x.\n", iface, flags);
2163
2164     return ddraw_surface7_PageLock(&This->IDirectDrawSurface7_iface, flags);
2165 }
2166
2167 static HRESULT WINAPI ddraw_surface2_PageLock(IDirectDrawSurface2 *iface, DWORD flags)
2168 {
2169     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2170     TRACE("iface %p, flags %#x.\n", iface, flags);
2171
2172     return ddraw_surface7_PageLock(&This->IDirectDrawSurface7_iface, flags);
2173 }
2174
2175 /*****************************************************************************
2176  * IDirectDrawSurface7::PageUnlock
2177  *
2178  * Allows a sysmem surface to be paged out
2179  *
2180  * Params:
2181  *  Flags: Not used, must be 0(unchecked)
2182  *
2183  * Returns:
2184  *  DD_OK, because it's a stub
2185  *
2186  *****************************************************************************/
2187 static HRESULT WINAPI ddraw_surface7_PageUnlock(IDirectDrawSurface7 *iface, DWORD Flags)
2188 {
2189     TRACE("iface %p, flags %#x.\n", iface, Flags);
2190
2191     return DD_OK;
2192 }
2193
2194 static HRESULT WINAPI ddraw_surface4_PageUnlock(IDirectDrawSurface4 *iface, DWORD flags)
2195 {
2196     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2197     TRACE("iface %p, flags %#x.\n", iface, flags);
2198
2199     return ddraw_surface7_PageUnlock(&This->IDirectDrawSurface7_iface, flags);
2200 }
2201
2202 static HRESULT WINAPI ddraw_surface3_PageUnlock(IDirectDrawSurface3 *iface, DWORD flags)
2203 {
2204     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2205     TRACE("iface %p, flags %#x.\n", iface, flags);
2206
2207     return ddraw_surface7_PageUnlock(&This->IDirectDrawSurface7_iface, flags);
2208 }
2209
2210 static HRESULT WINAPI ddraw_surface2_PageUnlock(IDirectDrawSurface2 *iface, DWORD flags)
2211 {
2212     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2213     TRACE("iface %p, flags %#x.\n", iface, flags);
2214
2215     return ddraw_surface7_PageUnlock(&This->IDirectDrawSurface7_iface, flags);
2216 }
2217
2218 /*****************************************************************************
2219  * IDirectDrawSurface7::BltBatch
2220  *
2221  * An unimplemented function
2222  *
2223  * Params:
2224  *  ?
2225  *
2226  * Returns:
2227  *  DDERR_UNSUPPORTED
2228  *
2229  *****************************************************************************/
2230 static HRESULT WINAPI ddraw_surface7_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
2231 {
2232     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, Batch, Count, Flags);
2233
2234     /* MSDN: "not currently implemented" */
2235     return DDERR_UNSUPPORTED;
2236 }
2237
2238 static HRESULT WINAPI ddraw_surface4_BltBatch(IDirectDrawSurface4 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2239 {
2240     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2241     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2242
2243     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
2244 }
2245
2246 static HRESULT WINAPI ddraw_surface3_BltBatch(IDirectDrawSurface3 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2247 {
2248     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2249     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2250
2251     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
2252 }
2253
2254 static HRESULT WINAPI ddraw_surface2_BltBatch(IDirectDrawSurface2 *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2255 {
2256     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2257     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2258
2259     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
2260 }
2261
2262 static HRESULT WINAPI ddraw_surface1_BltBatch(IDirectDrawSurface *iface, DDBLTBATCH *batch, DWORD count, DWORD flags)
2263 {
2264     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2265     TRACE("iface %p, batch %p, count %u, flags %#x.\n", iface, batch, count, flags);
2266
2267     return ddraw_surface7_BltBatch(&This->IDirectDrawSurface7_iface, batch, count, flags);
2268 }
2269
2270 /*****************************************************************************
2271  * IDirectDrawSurface7::EnumAttachedSurfaces
2272  *
2273  * Enumerates all surfaces attached to this surface
2274  *
2275  * Params:
2276  *  context: Pointer to pass unmodified to the callback
2277  *  cb: Callback function to call for each surface
2278  *
2279  * Returns:
2280  *  DD_OK on success
2281  *  DDERR_INVALIDPARAMS if cb is NULL
2282  *
2283  *****************************************************************************/
2284 static HRESULT WINAPI ddraw_surface7_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
2285         void *context, LPDDENUMSURFACESCALLBACK7 cb)
2286 {
2287     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2288     IDirectDrawSurfaceImpl *surf;
2289     DDSURFACEDESC2 desc;
2290     int i;
2291
2292     /* Attached surfaces aren't handled in WineD3D */
2293     TRACE("iface %p, context %p, callback %p.\n", iface, context, cb);
2294
2295     if(!cb)
2296         return DDERR_INVALIDPARAMS;
2297
2298     EnterCriticalSection(&ddraw_cs);
2299     for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
2300     {
2301         surf = This->complex_array[i];
2302         if(!surf) break;
2303
2304         ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2305         desc = surf->surface_desc;
2306         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2307         if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2308         {
2309             LeaveCriticalSection(&ddraw_cs);
2310             return DD_OK;
2311         }
2312     }
2313
2314     for (surf = This->next_attached; surf != NULL; surf = surf->next_attached)
2315     {
2316         ddraw_surface7_AddRef(&surf->IDirectDrawSurface7_iface);
2317         desc = surf->surface_desc;
2318         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
2319         if (cb(&surf->IDirectDrawSurface7_iface, &desc, context) == DDENUMRET_CANCEL)
2320         {
2321             LeaveCriticalSection(&ddraw_cs);
2322             return DD_OK;
2323         }
2324     }
2325
2326     TRACE(" end of enumeration.\n");
2327
2328     LeaveCriticalSection(&ddraw_cs);
2329     return DD_OK;
2330 }
2331
2332 struct callback_info2
2333 {
2334     LPDDENUMSURFACESCALLBACK2 callback;
2335     void *context;
2336 };
2337
2338 struct callback_info
2339 {
2340     LPDDENUMSURFACESCALLBACK callback;
2341     void *context;
2342 };
2343
2344 static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2345 {
2346     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(surface);
2347     const struct callback_info2 *info = context;
2348
2349     ddraw_surface4_AddRef(&This->IDirectDrawSurface4_iface);
2350     ddraw_surface7_Release(surface);
2351
2352     return info->callback(&This->IDirectDrawSurface4_iface, surface_desc, info->context);
2353 }
2354
2355 static HRESULT CALLBACK EnumCallback(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *context)
2356 {
2357     IDirectDrawSurfaceImpl *surface_impl = impl_from_IDirectDrawSurface7(surface);
2358     const struct callback_info *info = context;
2359
2360     ddraw_surface1_AddRef(&surface_impl->IDirectDrawSurface_iface);
2361     ddraw_surface7_Release(surface);
2362
2363     /* FIXME: Check surface_test.dwSize */
2364     return info->callback(&surface_impl->IDirectDrawSurface_iface,
2365             (DDSURFACEDESC *)surface_desc, info->context);
2366 }
2367
2368 static HRESULT WINAPI ddraw_surface4_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
2369         void *context, LPDDENUMSURFACESCALLBACK2 callback)
2370 {
2371     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2372     struct callback_info2 info;
2373
2374     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2375
2376     info.callback = callback;
2377     info.context  = context;
2378
2379     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
2380             &info, EnumCallback2);
2381 }
2382
2383 static HRESULT WINAPI ddraw_surface3_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
2384         void *context, LPDDENUMSURFACESCALLBACK callback)
2385 {
2386     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2387     struct callback_info info;
2388
2389     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2390
2391     info.callback = callback;
2392     info.context  = context;
2393
2394     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
2395             &info, EnumCallback);
2396 }
2397
2398 static HRESULT WINAPI ddraw_surface2_EnumAttachedSurfaces(IDirectDrawSurface2 *iface,
2399         void *context, LPDDENUMSURFACESCALLBACK callback)
2400 {
2401     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2402     struct callback_info info;
2403
2404     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2405
2406     info.callback = callback;
2407     info.context  = context;
2408
2409     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
2410             &info, EnumCallback);
2411 }
2412
2413 static HRESULT WINAPI ddraw_surface1_EnumAttachedSurfaces(IDirectDrawSurface *iface,
2414         void *context, LPDDENUMSURFACESCALLBACK callback)
2415 {
2416     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2417     struct callback_info info;
2418
2419     TRACE("iface %p, context %p, callback %p.\n", iface, context, callback);
2420
2421     info.callback = callback;
2422     info.context  = context;
2423
2424     return ddraw_surface7_EnumAttachedSurfaces(&This->IDirectDrawSurface7_iface,
2425             &info, EnumCallback);
2426 }
2427
2428 /*****************************************************************************
2429  * IDirectDrawSurface7::EnumOverlayZOrders
2430  *
2431  * "Enumerates the overlay surfaces on the specified destination"
2432  *
2433  * Params:
2434  *  Flags: DDENUMOVERLAYZ_BACKTOFRONT  or DDENUMOVERLAYZ_FRONTTOBACK
2435  *  context: context to pass back to the callback
2436  *  cb: callback function to call for each enumerated surface
2437  *
2438  * Returns:
2439  *  DD_OK, because it's a stub
2440  *
2441  *****************************************************************************/
2442 static HRESULT WINAPI ddraw_surface7_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
2443         DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK7 cb)
2444 {
2445     FIXME("iface %p, flags %#x, context %p, callback %p stub!\n", iface, Flags, context, cb);
2446
2447     return DD_OK;
2448 }
2449
2450 static HRESULT WINAPI ddraw_surface4_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
2451         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK2 callback)
2452 {
2453     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2454     struct callback_info2 info;
2455
2456     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2457
2458     info.callback = callback;
2459     info.context  = context;
2460
2461     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
2462             flags, &info, EnumCallback2);
2463 }
2464
2465 static HRESULT WINAPI ddraw_surface3_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
2466         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2467 {
2468     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2469     struct callback_info info;
2470
2471     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2472
2473     info.callback = callback;
2474     info.context  = context;
2475
2476     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
2477             flags, &info, EnumCallback);
2478 }
2479
2480 static HRESULT WINAPI ddraw_surface2_EnumOverlayZOrders(IDirectDrawSurface2 *iface,
2481         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2482 {
2483     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2484     struct callback_info info;
2485
2486     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2487
2488     info.callback = callback;
2489     info.context  = context;
2490
2491     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
2492             flags, &info, EnumCallback);
2493 }
2494
2495 static HRESULT WINAPI ddraw_surface1_EnumOverlayZOrders(IDirectDrawSurface *iface,
2496         DWORD flags, void *context, LPDDENUMSURFACESCALLBACK callback)
2497 {
2498     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2499     struct callback_info info;
2500
2501     TRACE("iface %p, flags %#x, context %p, callback %p.\n", iface, flags, context, callback);
2502
2503     info.callback = callback;
2504     info.context  = context;
2505
2506     return ddraw_surface7_EnumOverlayZOrders(&This->IDirectDrawSurface7_iface,
2507             flags, &info, EnumCallback);
2508 }
2509
2510 /*****************************************************************************
2511  * IDirectDrawSurface7::GetBltStatus
2512  *
2513  * Returns the blitting status
2514  *
2515  * Params:
2516  *  Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
2517  *
2518  * Returns:
2519  *  See IWineD3DSurface::Blt
2520  *
2521  *****************************************************************************/
2522 static HRESULT WINAPI ddraw_surface7_GetBltStatus(IDirectDrawSurface7 *iface, DWORD Flags)
2523 {
2524     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2525     HRESULT hr;
2526
2527     TRACE("iface %p, flags %#x.\n", iface, Flags);
2528
2529     EnterCriticalSection(&ddraw_cs);
2530     hr = wined3d_surface_get_blt_status(This->wined3d_surface, Flags);
2531     LeaveCriticalSection(&ddraw_cs);
2532     switch(hr)
2533     {
2534         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
2535         default:                            return hr;
2536     }
2537 }
2538
2539 static HRESULT WINAPI ddraw_surface4_GetBltStatus(IDirectDrawSurface4 *iface, DWORD flags)
2540 {
2541     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2542     TRACE("iface %p, flags %#x.\n", iface, flags);
2543
2544     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
2545 }
2546
2547 static HRESULT WINAPI ddraw_surface3_GetBltStatus(IDirectDrawSurface3 *iface, DWORD flags)
2548 {
2549     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2550     TRACE("iface %p, flags %#x.\n", iface, flags);
2551
2552     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
2553 }
2554
2555 static HRESULT WINAPI ddraw_surface2_GetBltStatus(IDirectDrawSurface2 *iface, DWORD flags)
2556 {
2557     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2558     TRACE("iface %p, flags %#x.\n", iface, flags);
2559
2560     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
2561 }
2562
2563 static HRESULT WINAPI ddraw_surface1_GetBltStatus(IDirectDrawSurface *iface, DWORD flags)
2564 {
2565     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2566     TRACE("iface %p, flags %#x.\n", iface, flags);
2567
2568     return ddraw_surface7_GetBltStatus(&This->IDirectDrawSurface7_iface, flags);
2569 }
2570
2571 /*****************************************************************************
2572  * IDirectDrawSurface7::GetColorKey
2573  *
2574  * Returns the color key assigned to the surface
2575  *
2576  * Params:
2577  *  Flags: Some flags
2578  *  CKey: Address to store the key to
2579  *
2580  * Returns:
2581  *  DD_OK on success
2582  *  DDERR_INVALIDPARAMS if CKey is NULL
2583  *
2584  *****************************************************************************/
2585 static HRESULT WINAPI ddraw_surface7_GetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
2586 {
2587     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2588
2589     TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
2590
2591     if(!CKey)
2592         return DDERR_INVALIDPARAMS;
2593
2594     EnterCriticalSection(&ddraw_cs);
2595
2596     switch (Flags)
2597     {
2598     case DDCKEY_DESTBLT:
2599         if (!(This->surface_desc.dwFlags & DDSD_CKDESTBLT))
2600         {
2601             LeaveCriticalSection(&ddraw_cs);
2602             return DDERR_NOCOLORKEY;
2603         }
2604         *CKey = This->surface_desc.ddckCKDestBlt;
2605         break;
2606
2607     case DDCKEY_DESTOVERLAY:
2608         if (!(This->surface_desc.dwFlags & DDSD_CKDESTOVERLAY))
2609             {
2610             LeaveCriticalSection(&ddraw_cs);
2611             return DDERR_NOCOLORKEY;
2612             }
2613         *CKey = This->surface_desc.u3.ddckCKDestOverlay;
2614         break;
2615
2616     case DDCKEY_SRCBLT:
2617         if (!(This->surface_desc.dwFlags & DDSD_CKSRCBLT))
2618         {
2619             LeaveCriticalSection(&ddraw_cs);
2620             return DDERR_NOCOLORKEY;
2621         }
2622         *CKey = This->surface_desc.ddckCKSrcBlt;
2623         break;
2624
2625     case DDCKEY_SRCOVERLAY:
2626         if (!(This->surface_desc.dwFlags & DDSD_CKSRCOVERLAY))
2627         {
2628             LeaveCriticalSection(&ddraw_cs);
2629             return DDERR_NOCOLORKEY;
2630         }
2631         *CKey = This->surface_desc.ddckCKSrcOverlay;
2632         break;
2633
2634     default:
2635         LeaveCriticalSection(&ddraw_cs);
2636         return DDERR_INVALIDPARAMS;
2637     }
2638
2639     LeaveCriticalSection(&ddraw_cs);
2640     return DD_OK;
2641 }
2642
2643 static HRESULT WINAPI ddraw_surface4_GetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
2644 {
2645     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2646     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
2647
2648     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
2649 }
2650
2651 static HRESULT WINAPI ddraw_surface3_GetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
2652 {
2653     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2654     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
2655
2656     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
2657 }
2658
2659 static HRESULT WINAPI ddraw_surface2_GetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
2660 {
2661     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2662     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
2663
2664     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
2665 }
2666
2667 static HRESULT WINAPI ddraw_surface1_GetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
2668 {
2669     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2670     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
2671
2672     return ddraw_surface7_GetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
2673 }
2674
2675 /*****************************************************************************
2676  * IDirectDrawSurface7::GetFlipStatus
2677  *
2678  * Returns the flipping status of the surface
2679  *
2680  * Params:
2681  *  Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
2682  *
2683  * Returns:
2684  *  See IWineD3DSurface::GetFlipStatus
2685  *
2686  *****************************************************************************/
2687 static HRESULT WINAPI ddraw_surface7_GetFlipStatus(IDirectDrawSurface7 *iface, DWORD Flags)
2688 {
2689     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2690     HRESULT hr;
2691
2692     TRACE("iface %p, flags %#x.\n", iface, Flags);
2693
2694     EnterCriticalSection(&ddraw_cs);
2695     hr = wined3d_surface_get_flip_status(This->wined3d_surface, Flags);
2696     LeaveCriticalSection(&ddraw_cs);
2697     switch(hr)
2698     {
2699         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
2700         default:                            return hr;
2701     }
2702 }
2703
2704 static HRESULT WINAPI ddraw_surface4_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD flags)
2705 {
2706     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2707     TRACE("iface %p, flags %#x.\n", iface, flags);
2708
2709     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
2710 }
2711
2712 static HRESULT WINAPI ddraw_surface3_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD flags)
2713 {
2714     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2715     TRACE("iface %p, flags %#x.\n", iface, flags);
2716
2717     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
2718 }
2719
2720 static HRESULT WINAPI ddraw_surface2_GetFlipStatus(IDirectDrawSurface2 *iface, DWORD flags)
2721 {
2722     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2723     TRACE("iface %p, flags %#x.\n", iface, flags);
2724
2725     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
2726 }
2727
2728 static HRESULT WINAPI ddraw_surface1_GetFlipStatus(IDirectDrawSurface *iface, DWORD flags)
2729 {
2730     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2731     TRACE("iface %p, flags %#x.\n", iface, flags);
2732
2733     return ddraw_surface7_GetFlipStatus(&This->IDirectDrawSurface7_iface, flags);
2734 }
2735
2736 /*****************************************************************************
2737  * IDirectDrawSurface7::GetOverlayPosition
2738  *
2739  * Returns the display coordinates of a visible and active overlay surface
2740  *
2741  * Params:
2742  *  X
2743  *  Y
2744  *
2745  * Returns:
2746  *  DDERR_NOTAOVERLAYSURFACE, because it's a stub
2747  *****************************************************************************/
2748 static HRESULT WINAPI ddraw_surface7_GetOverlayPosition(IDirectDrawSurface7 *iface, LONG *X, LONG *Y)
2749 {
2750     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2751     HRESULT hr;
2752
2753     TRACE("iface %p, x %p, y %p.\n", iface, X, Y);
2754
2755     EnterCriticalSection(&ddraw_cs);
2756     hr = wined3d_surface_get_overlay_position(This->wined3d_surface, X, Y);
2757     LeaveCriticalSection(&ddraw_cs);
2758     return hr;
2759 }
2760
2761 static HRESULT WINAPI ddraw_surface4_GetOverlayPosition(IDirectDrawSurface4 *iface, LONG *x, LONG *y)
2762 {
2763     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2764     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
2765
2766     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
2767 }
2768
2769 static HRESULT WINAPI ddraw_surface3_GetOverlayPosition(IDirectDrawSurface3 *iface, LONG *x, LONG *y)
2770 {
2771     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2772     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
2773
2774     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
2775 }
2776
2777 static HRESULT WINAPI ddraw_surface2_GetOverlayPosition(IDirectDrawSurface2 *iface, LONG *x, LONG *y)
2778 {
2779     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2780     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
2781
2782     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
2783 }
2784
2785 static HRESULT WINAPI ddraw_surface1_GetOverlayPosition(IDirectDrawSurface *iface, LONG *x, LONG *y)
2786 {
2787     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2788     TRACE("iface %p, x %p, y %p.\n", iface, x, y);
2789
2790     return ddraw_surface7_GetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
2791 }
2792
2793 /*****************************************************************************
2794  * IDirectDrawSurface7::GetPixelFormat
2795  *
2796  * Returns the pixel format of the Surface
2797  *
2798  * Params:
2799  *  PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
2800  *               format should be written
2801  *
2802  * Returns:
2803  *  DD_OK on success
2804  *  DDERR_INVALIDPARAMS if PixelFormat is NULL
2805  *
2806  *****************************************************************************/
2807 static HRESULT WINAPI ddraw_surface7_GetPixelFormat(IDirectDrawSurface7 *iface, DDPIXELFORMAT *PixelFormat)
2808 {
2809     /* What is DDERR_INVALIDSURFACETYPE for here? */
2810     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2811
2812     TRACE("iface %p, pixel_format %p.\n", iface, PixelFormat);
2813
2814     if(!PixelFormat)
2815         return DDERR_INVALIDPARAMS;
2816
2817     EnterCriticalSection(&ddraw_cs);
2818     DD_STRUCT_COPY_BYSIZE(PixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
2819     LeaveCriticalSection(&ddraw_cs);
2820
2821     return DD_OK;
2822 }
2823
2824 static HRESULT WINAPI ddraw_surface4_GetPixelFormat(IDirectDrawSurface4 *iface, DDPIXELFORMAT *pixel_format)
2825 {
2826     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2827     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
2828
2829     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
2830 }
2831
2832 static HRESULT WINAPI ddraw_surface3_GetPixelFormat(IDirectDrawSurface3 *iface, DDPIXELFORMAT *pixel_format)
2833 {
2834     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2835     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
2836
2837     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
2838 }
2839
2840 static HRESULT WINAPI ddraw_surface2_GetPixelFormat(IDirectDrawSurface2 *iface, DDPIXELFORMAT *pixel_format)
2841 {
2842     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2843     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
2844
2845     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
2846 }
2847
2848 static HRESULT WINAPI ddraw_surface1_GetPixelFormat(IDirectDrawSurface *iface, DDPIXELFORMAT *pixel_format)
2849 {
2850     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2851     TRACE("iface %p, pixel_format %p.\n", iface, pixel_format);
2852
2853     return ddraw_surface7_GetPixelFormat(&This->IDirectDrawSurface7_iface, pixel_format);
2854 }
2855
2856 /*****************************************************************************
2857  * IDirectDrawSurface7::GetSurfaceDesc
2858  *
2859  * Returns the description of this surface
2860  *
2861  * Params:
2862  *  DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
2863  *        surface desc
2864  *
2865  * Returns:
2866  *  DD_OK on success
2867  *  DDERR_INVALIDPARAMS if DDSD is NULL
2868  *
2869  *****************************************************************************/
2870 static HRESULT WINAPI ddraw_surface7_GetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD)
2871 {
2872     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
2873
2874     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
2875
2876     if(!DDSD)
2877         return DDERR_INVALIDPARAMS;
2878
2879     if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
2880     {
2881         WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
2882         return DDERR_INVALIDPARAMS;
2883     }
2884
2885     EnterCriticalSection(&ddraw_cs);
2886     DD_STRUCT_COPY_BYSIZE(DDSD,&This->surface_desc);
2887     TRACE("Returning surface desc:\n");
2888     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
2889
2890     LeaveCriticalSection(&ddraw_cs);
2891     return DD_OK;
2892 }
2893
2894 static HRESULT WINAPI ddraw_surface4_GetSurfaceDesc(IDirectDrawSurface4 *iface, DDSURFACEDESC2 *DDSD)
2895 {
2896     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2897     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
2898
2899     return ddraw_surface7_GetSurfaceDesc(&This->IDirectDrawSurface7_iface, DDSD);
2900 }
2901
2902 static HRESULT WINAPI ddraw_surface3_GetSurfaceDesc(IDirectDrawSurface3 *iface, DDSURFACEDESC *surface_desc)
2903 {
2904     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2905
2906     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
2907
2908     if (!surface_desc) return DDERR_INVALIDPARAMS;
2909
2910     if (surface_desc->dwSize != sizeof(DDSURFACEDESC))
2911     {
2912         WARN("Incorrect structure size %u, returning DDERR_INVALIDPARAMS.\n", surface_desc->dwSize);
2913         return DDERR_INVALIDPARAMS;
2914     }
2915
2916     EnterCriticalSection(&ddraw_cs);
2917     DDSD2_to_DDSD(&This->surface_desc, surface_desc);
2918     TRACE("Returning surface desc:\n");
2919     if (TRACE_ON(ddraw))
2920     {
2921         /* DDRAW_dump_surface_desc handles the smaller size */
2922         DDRAW_dump_surface_desc((DDSURFACEDESC2 *)surface_desc);
2923     }
2924
2925     LeaveCriticalSection(&ddraw_cs);
2926     return DD_OK;
2927 }
2928
2929 static HRESULT WINAPI ddraw_surface2_GetSurfaceDesc(IDirectDrawSurface2 *iface, DDSURFACEDESC *DDSD)
2930 {
2931     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2932     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
2933
2934     return ddraw_surface3_GetSurfaceDesc(&This->IDirectDrawSurface3_iface, DDSD);
2935 }
2936
2937 static HRESULT WINAPI ddraw_surface1_GetSurfaceDesc(IDirectDrawSurface *iface, DDSURFACEDESC *DDSD)
2938 {
2939     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
2940     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
2941
2942     return ddraw_surface3_GetSurfaceDesc(&This->IDirectDrawSurface3_iface, DDSD);
2943 }
2944
2945 /*****************************************************************************
2946  * IDirectDrawSurface7::Initialize
2947  *
2948  * Initializes the surface. This is a no-op in Wine
2949  *
2950  * Params:
2951  *  DD: Pointer to an DirectDraw interface
2952  *  DDSD: Surface description for initialization
2953  *
2954  * Returns:
2955  *  DDERR_ALREADYINITIALIZED
2956  *
2957  *****************************************************************************/
2958 static HRESULT WINAPI ddraw_surface7_Initialize(IDirectDrawSurface7 *iface,
2959         IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
2960 {
2961     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
2962
2963     return DDERR_ALREADYINITIALIZED;
2964 }
2965
2966 static HRESULT WINAPI ddraw_surface4_Initialize(IDirectDrawSurface4 *iface,
2967         IDirectDraw *ddraw, DDSURFACEDESC2 *surface_desc)
2968 {
2969     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
2970     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
2971
2972     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
2973             ddraw, surface_desc);
2974 }
2975
2976 static HRESULT WINAPI ddraw_surface3_Initialize(IDirectDrawSurface3 *iface,
2977         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
2978 {
2979     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
2980     DDSURFACEDESC2 surface_desc2;
2981     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
2982
2983     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2984     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
2985             ddraw, surface_desc ? &surface_desc2 : NULL);
2986 }
2987
2988 static HRESULT WINAPI ddraw_surface2_Initialize(IDirectDrawSurface2 *iface,
2989         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
2990 {
2991     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
2992     DDSURFACEDESC2 surface_desc2;
2993     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
2994
2995     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
2996     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
2997             ddraw, surface_desc ? &surface_desc2 : NULL);
2998 }
2999
3000 static HRESULT WINAPI ddraw_surface1_Initialize(IDirectDrawSurface *iface,
3001         IDirectDraw *ddraw, DDSURFACEDESC *surface_desc)
3002 {
3003     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3004     DDSURFACEDESC2 surface_desc2;
3005     TRACE("iface %p, ddraw %p, surface_desc %p.\n", iface, ddraw, surface_desc);
3006
3007     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
3008     return ddraw_surface7_Initialize(&This->IDirectDrawSurface7_iface,
3009             ddraw, surface_desc ? &surface_desc2 : NULL);
3010 }
3011
3012 /*****************************************************************************
3013  * IDirect3DTexture1::Initialize
3014  *
3015  * The sdk says it's not implemented
3016  *
3017  * Params:
3018  *  ?
3019  *
3020  * Returns
3021  *  DDERR_UNSUPPORTED
3022  *
3023  *****************************************************************************/
3024 static HRESULT WINAPI d3d_texture1_Initialize(IDirect3DTexture *iface,
3025         IDirect3DDevice *device, IDirectDrawSurface *surface)
3026 {
3027     TRACE("iface %p, device %p, surface %p.\n", iface, device, surface);
3028
3029     return DDERR_UNSUPPORTED; /* Unchecked */
3030 }
3031
3032 /*****************************************************************************
3033  * IDirectDrawSurface7::IsLost
3034  *
3035  * Checks if the surface is lost
3036  *
3037  * Returns:
3038  *  DD_OK, if the surface is usable
3039  *  DDERR_ISLOST if the surface is lost
3040  *  See IWineD3DSurface::IsLost for more details
3041  *
3042  *****************************************************************************/
3043 static HRESULT WINAPI ddraw_surface7_IsLost(IDirectDrawSurface7 *iface)
3044 {
3045     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3046     HRESULT hr;
3047
3048     TRACE("iface %p.\n", iface);
3049
3050     EnterCriticalSection(&ddraw_cs);
3051     hr = wined3d_surface_is_lost(This->wined3d_surface);
3052     LeaveCriticalSection(&ddraw_cs);
3053     switch(hr)
3054     {
3055         /* D3D8 and 9 loose full devices, thus there's only a DEVICELOST error.
3056          * WineD3D uses the same error for surfaces
3057          */
3058         case WINED3DERR_DEVICELOST:         return DDERR_SURFACELOST;
3059         default:                            return hr;
3060     }
3061 }
3062
3063 static HRESULT WINAPI ddraw_surface4_IsLost(IDirectDrawSurface4 *iface)
3064 {
3065     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3066     TRACE("iface %p.\n", iface);
3067
3068     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
3069 }
3070
3071 static HRESULT WINAPI ddraw_surface3_IsLost(IDirectDrawSurface3 *iface)
3072 {
3073     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3074     TRACE("iface %p.\n", iface);
3075
3076     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
3077 }
3078
3079 static HRESULT WINAPI ddraw_surface2_IsLost(IDirectDrawSurface2 *iface)
3080 {
3081     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3082     TRACE("iface %p.\n", iface);
3083
3084     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
3085 }
3086
3087 static HRESULT WINAPI ddraw_surface1_IsLost(IDirectDrawSurface *iface)
3088 {
3089     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3090     TRACE("iface %p.\n", iface);
3091
3092     return ddraw_surface7_IsLost(&This->IDirectDrawSurface7_iface);
3093 }
3094
3095 /*****************************************************************************
3096  * IDirectDrawSurface7::Restore
3097  *
3098  * Restores a lost surface. This makes the surface usable again, but
3099  * doesn't reload its old contents
3100  *
3101  * Returns:
3102  *  DD_OK on success
3103  *  See IWineD3DSurface::Restore for more details
3104  *
3105  *****************************************************************************/
3106 static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
3107 {
3108     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3109     HRESULT hr;
3110
3111     TRACE("iface %p.\n", iface);
3112
3113     EnterCriticalSection(&ddraw_cs);
3114     hr = wined3d_surface_restore(This->wined3d_surface);
3115     LeaveCriticalSection(&ddraw_cs);
3116     return hr;
3117 }
3118
3119 static HRESULT WINAPI ddraw_surface4_Restore(IDirectDrawSurface4 *iface)
3120 {
3121     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3122     TRACE("iface %p.\n", iface);
3123
3124     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
3125 }
3126
3127 static HRESULT WINAPI ddraw_surface3_Restore(IDirectDrawSurface3 *iface)
3128 {
3129     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3130     TRACE("iface %p.\n", iface);
3131
3132     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
3133 }
3134
3135 static HRESULT WINAPI ddraw_surface2_Restore(IDirectDrawSurface2 *iface)
3136 {
3137     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3138     TRACE("iface %p.\n", iface);
3139
3140     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
3141 }
3142
3143 static HRESULT WINAPI ddraw_surface1_Restore(IDirectDrawSurface *iface)
3144 {
3145     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3146     TRACE("iface %p.\n", iface);
3147
3148     return ddraw_surface7_Restore(&This->IDirectDrawSurface7_iface);
3149 }
3150
3151 /*****************************************************************************
3152  * IDirectDrawSurface7::SetOverlayPosition
3153  *
3154  * Changes the display coordinates of an overlay surface
3155  *
3156  * Params:
3157  *  X:
3158  *  Y:
3159  *
3160  * Returns:
3161  *   DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
3162  *****************************************************************************/
3163 static HRESULT WINAPI ddraw_surface7_SetOverlayPosition(IDirectDrawSurface7 *iface, LONG X, LONG Y)
3164 {
3165     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3166     HRESULT hr;
3167
3168     TRACE("iface %p, x %d, y %d.\n", iface, X, Y);
3169
3170     EnterCriticalSection(&ddraw_cs);
3171     hr = wined3d_surface_set_overlay_position(This->wined3d_surface, X, Y);
3172     LeaveCriticalSection(&ddraw_cs);
3173     return hr;
3174 }
3175
3176 static HRESULT WINAPI ddraw_surface4_SetOverlayPosition(IDirectDrawSurface4 *iface, LONG x, LONG y)
3177 {
3178     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3179     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3180
3181     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
3182 }
3183
3184 static HRESULT WINAPI ddraw_surface3_SetOverlayPosition(IDirectDrawSurface3 *iface, LONG x, LONG y)
3185 {
3186     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3187     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3188
3189     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
3190 }
3191
3192 static HRESULT WINAPI ddraw_surface2_SetOverlayPosition(IDirectDrawSurface2 *iface, LONG x, LONG y)
3193 {
3194     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3195     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3196
3197     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
3198 }
3199
3200 static HRESULT WINAPI ddraw_surface1_SetOverlayPosition(IDirectDrawSurface *iface, LONG x, LONG y)
3201 {
3202     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3203     TRACE("iface %p, x %d, y %d.\n", iface, x, y);
3204
3205     return ddraw_surface7_SetOverlayPosition(&This->IDirectDrawSurface7_iface, x, y);
3206 }
3207
3208 /*****************************************************************************
3209  * IDirectDrawSurface7::UpdateOverlay
3210  *
3211  * Modifies the attributes of an overlay surface.
3212  *
3213  * Params:
3214  *  SrcRect: The section of the source being used for the overlay
3215  *  DstSurface: Address of the surface that is overlaid
3216  *  DstRect: Place of the overlay
3217  *  Flags: some DDOVER_* flags
3218  *
3219  * Returns:
3220  *  DDERR_UNSUPPORTED, because we don't support overlays
3221  *
3222  *****************************************************************************/
3223 static HRESULT WINAPI ddraw_surface7_UpdateOverlay(IDirectDrawSurface7 *iface, RECT *SrcRect,
3224         IDirectDrawSurface7 *DstSurface, RECT *DstRect, DWORD Flags, DDOVERLAYFX *FX)
3225 {
3226     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3227     IDirectDrawSurfaceImpl *Dst = unsafe_impl_from_IDirectDrawSurface7(DstSurface);
3228     HRESULT hr;
3229
3230     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3231             iface, wine_dbgstr_rect(SrcRect), DstSurface, wine_dbgstr_rect(DstRect), Flags, FX);
3232
3233     EnterCriticalSection(&ddraw_cs);
3234     hr = wined3d_surface_update_overlay(This->wined3d_surface, SrcRect,
3235             Dst ? Dst->wined3d_surface : NULL, DstRect, Flags, (WINEDDOVERLAYFX *)FX);
3236     LeaveCriticalSection(&ddraw_cs);
3237     switch(hr) {
3238         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
3239         case WINEDDERR_NOTAOVERLAYSURFACE:  return DDERR_NOTAOVERLAYSURFACE;
3240         case WINEDDERR_OVERLAYNOTVISIBLE:   return DDERR_OVERLAYNOTVISIBLE;
3241         default:
3242             return hr;
3243     }
3244 }
3245
3246 static HRESULT WINAPI ddraw_surface4_UpdateOverlay(IDirectDrawSurface4 *iface, RECT *src_rect,
3247         IDirectDrawSurface4 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3248 {
3249     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3250     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface4(dst_surface);
3251     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3252             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3253
3254     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
3255             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3256 }
3257
3258 static HRESULT WINAPI ddraw_surface3_UpdateOverlay(IDirectDrawSurface3 *iface, RECT *src_rect,
3259         IDirectDrawSurface3 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3260 {
3261     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3262     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface3(dst_surface);
3263     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3264             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3265
3266     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
3267             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3268 }
3269
3270 static HRESULT WINAPI ddraw_surface2_UpdateOverlay(IDirectDrawSurface2 *iface, RECT *src_rect,
3271         IDirectDrawSurface2 *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3272 {
3273     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3274     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface2(dst_surface);
3275     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3276             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3277
3278     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
3279             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3280 }
3281
3282 static HRESULT WINAPI ddraw_surface1_UpdateOverlay(IDirectDrawSurface *iface, RECT *src_rect,
3283         IDirectDrawSurface *dst_surface, RECT *dst_rect, DWORD flags, DDOVERLAYFX *fx)
3284 {
3285     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3286     IDirectDrawSurfaceImpl *dst_impl = unsafe_impl_from_IDirectDrawSurface(dst_surface);
3287     TRACE("iface %p, src_rect %s, dst_surface %p, dst_rect %s, flags %#x, fx %p.\n",
3288             iface, wine_dbgstr_rect(src_rect), dst_surface, wine_dbgstr_rect(dst_rect), flags, fx);
3289
3290     return ddraw_surface7_UpdateOverlay(&This->IDirectDrawSurface7_iface, src_rect,
3291             dst_impl ? &dst_impl->IDirectDrawSurface7_iface : NULL, dst_rect, flags, fx);
3292 }
3293
3294 /*****************************************************************************
3295  * IDirectDrawSurface7::UpdateOverlayDisplay
3296  *
3297  * The DX7 sdk says that it's not implemented
3298  *
3299  * Params:
3300  *  Flags: ?
3301  *
3302  * Returns: DDERR_UNSUPPORTED, because we don't support overlays
3303  *
3304  *****************************************************************************/
3305 static HRESULT WINAPI ddraw_surface7_UpdateOverlayDisplay(IDirectDrawSurface7 *iface, DWORD Flags)
3306 {
3307     TRACE("iface %p, flags %#x.\n", iface, Flags);
3308
3309     return DDERR_UNSUPPORTED;
3310 }
3311
3312 static HRESULT WINAPI ddraw_surface4_UpdateOverlayDisplay(IDirectDrawSurface4 *iface, DWORD flags)
3313 {
3314     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3315     TRACE("iface %p, flags %#x.\n", iface, flags);
3316
3317     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
3318 }
3319
3320 static HRESULT WINAPI ddraw_surface3_UpdateOverlayDisplay(IDirectDrawSurface3 *iface, DWORD flags)
3321 {
3322     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3323     TRACE("iface %p, flags %#x.\n", iface, flags);
3324
3325     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
3326 }
3327
3328 static HRESULT WINAPI ddraw_surface2_UpdateOverlayDisplay(IDirectDrawSurface2 *iface, DWORD flags)
3329 {
3330     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3331     TRACE("iface %p, flags %#x.\n", iface, flags);
3332
3333     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
3334 }
3335
3336 static HRESULT WINAPI ddraw_surface1_UpdateOverlayDisplay(IDirectDrawSurface *iface, DWORD flags)
3337 {
3338     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3339     TRACE("iface %p, flags %#x.\n", iface, flags);
3340
3341     return ddraw_surface7_UpdateOverlayDisplay(&This->IDirectDrawSurface7_iface, flags);
3342 }
3343
3344 /*****************************************************************************
3345  * IDirectDrawSurface7::UpdateOverlayZOrder
3346  *
3347  * Sets an overlay's Z order
3348  *
3349  * Params:
3350  *  Flags: DDOVERZ_* flags
3351  *  DDSRef: Defines the relative position in the overlay chain
3352  *
3353  * Returns:
3354  *  DDERR_NOTOVERLAYSURFACE, because we don't support overlays
3355  *
3356  *****************************************************************************/
3357 static HRESULT WINAPI ddraw_surface7_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
3358         DWORD Flags, IDirectDrawSurface7 *DDSRef)
3359 {
3360     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3361     IDirectDrawSurfaceImpl *Ref = unsafe_impl_from_IDirectDrawSurface7(DDSRef);
3362     HRESULT hr;
3363
3364     TRACE("iface %p, flags %#x, reference %p.\n", iface, Flags, DDSRef);
3365
3366     EnterCriticalSection(&ddraw_cs);
3367     hr = wined3d_surface_update_overlay_z_order(This->wined3d_surface,
3368             Flags, Ref ? Ref->wined3d_surface : NULL);
3369     LeaveCriticalSection(&ddraw_cs);
3370     return hr;
3371 }
3372
3373 static HRESULT WINAPI ddraw_surface4_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
3374         DWORD flags, IDirectDrawSurface4 *reference)
3375 {
3376     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3377     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface4(reference);
3378     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3379
3380     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
3381             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3382 }
3383
3384 static HRESULT WINAPI ddraw_surface3_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
3385         DWORD flags, IDirectDrawSurface3 *reference)
3386 {
3387     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3388     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface3(reference);
3389     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3390
3391     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
3392             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3393 }
3394
3395 static HRESULT WINAPI ddraw_surface2_UpdateOverlayZOrder(IDirectDrawSurface2 *iface,
3396         DWORD flags, IDirectDrawSurface2 *reference)
3397 {
3398     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3399     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface2(reference);
3400     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3401
3402     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
3403             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3404 }
3405
3406 static HRESULT WINAPI ddraw_surface1_UpdateOverlayZOrder(IDirectDrawSurface *iface,
3407         DWORD flags, IDirectDrawSurface *reference)
3408 {
3409     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3410     IDirectDrawSurfaceImpl *reference_impl = unsafe_impl_from_IDirectDrawSurface(reference);
3411     TRACE("iface %p, flags %#x, reference %p.\n", iface, flags, reference);
3412
3413     return ddraw_surface7_UpdateOverlayZOrder(&This->IDirectDrawSurface7_iface, flags,
3414             reference_impl ? &reference_impl->IDirectDrawSurface7_iface : NULL);
3415 }
3416
3417 /*****************************************************************************
3418  * IDirectDrawSurface7::GetDDInterface
3419  *
3420  * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
3421  * surface belongs to
3422  *
3423  * Params:
3424  *  DD: Address to write the interface pointer to
3425  *
3426  * Returns:
3427  *  DD_OK on success
3428  *  DDERR_INVALIDPARAMS if DD is NULL
3429  *
3430  *****************************************************************************/
3431 static HRESULT WINAPI ddraw_surface7_GetDDInterface(IDirectDrawSurface7 *iface, void **DD)
3432 {
3433     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3434
3435     TRACE("iface %p, ddraw %p.\n", iface, DD);
3436
3437     if(!DD)
3438         return DDERR_INVALIDPARAMS;
3439
3440     switch(This->version)
3441     {
3442         case 7:
3443             *DD = &This->ddraw->IDirectDraw7_iface;
3444             break;
3445
3446         case 4:
3447             *DD = &This->ddraw->IDirectDraw4_iface;
3448             break;
3449
3450         case 2:
3451             *DD = &This->ddraw->IDirectDraw2_iface;
3452             break;
3453
3454         case 1:
3455             *DD = &This->ddraw->IDirectDraw_iface;
3456             break;
3457
3458     }
3459     IUnknown_AddRef((IUnknown *)*DD);
3460
3461     return DD_OK;
3462 }
3463
3464 static HRESULT WINAPI ddraw_surface4_GetDDInterface(IDirectDrawSurface4 *iface, void **ddraw)
3465 {
3466     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3467     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3468
3469     return ddraw_surface7_GetDDInterface(&This->IDirectDrawSurface7_iface, ddraw);
3470 }
3471
3472 static HRESULT WINAPI ddraw_surface3_GetDDInterface(IDirectDrawSurface3 *iface, void **ddraw)
3473 {
3474     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3475     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3476
3477     return ddraw_surface7_GetDDInterface(&This->IDirectDrawSurface7_iface, ddraw);
3478 }
3479
3480 static HRESULT WINAPI ddraw_surface2_GetDDInterface(IDirectDrawSurface2 *iface, void **ddraw)
3481 {
3482     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3483     TRACE("iface %p, ddraw %p.\n", iface, ddraw);
3484
3485     return ddraw_surface7_GetDDInterface(&This->IDirectDrawSurface7_iface, ddraw);
3486 }
3487
3488 /* This seems also windows implementation specific - I don't think WineD3D needs this */
3489 static HRESULT WINAPI ddraw_surface7_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
3490 {
3491     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3492     volatile IDirectDrawSurfaceImpl* vThis = This;
3493
3494     TRACE("iface %p.\n", iface);
3495
3496     EnterCriticalSection(&ddraw_cs);
3497     /* A uniqueness value of 0 is apparently special.
3498      * This needs to be checked.
3499      * TODO: Write tests for this code and check if the volatile, interlocked stuff is really needed
3500      */
3501     while (1) {
3502         DWORD old_uniqueness_value = vThis->uniqueness_value;
3503         DWORD new_uniqueness_value = old_uniqueness_value+1;
3504
3505         if (old_uniqueness_value == 0) break;
3506         if (new_uniqueness_value == 0) new_uniqueness_value = 1;
3507
3508         if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
3509                                       old_uniqueness_value,
3510                                       new_uniqueness_value)
3511             == old_uniqueness_value)
3512             break;
3513     }
3514
3515     LeaveCriticalSection(&ddraw_cs);
3516     return DD_OK;
3517 }
3518
3519 static HRESULT WINAPI ddraw_surface4_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
3520 {
3521     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3522     TRACE("iface %p.\n", iface);
3523
3524     return ddraw_surface7_ChangeUniquenessValue(&This->IDirectDrawSurface7_iface);
3525 }
3526
3527 static HRESULT WINAPI ddraw_surface7_GetUniquenessValue(IDirectDrawSurface7 *iface, DWORD *pValue)
3528 {
3529     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3530
3531     TRACE("iface %p, value %p.\n", iface, pValue);
3532
3533     EnterCriticalSection(&ddraw_cs);
3534     *pValue = This->uniqueness_value;
3535     LeaveCriticalSection(&ddraw_cs);
3536     return DD_OK;
3537 }
3538
3539 static HRESULT WINAPI ddraw_surface4_GetUniquenessValue(IDirectDrawSurface4 *iface, DWORD *pValue)
3540 {
3541     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3542     TRACE("iface %p, value %p.\n", iface, pValue);
3543
3544     return ddraw_surface7_GetUniquenessValue(&This->IDirectDrawSurface7_iface, pValue);
3545 }
3546
3547 /*****************************************************************************
3548  * IDirectDrawSurface7::SetLOD
3549  *
3550  * Sets the level of detail of a texture
3551  *
3552  * Params:
3553  *  MaxLOD: LOD to set
3554  *
3555  * Returns:
3556  *  DD_OK on success
3557  *  DDERR_INVALIDOBJECT if the surface is invalid for this method
3558  *
3559  *****************************************************************************/
3560 static HRESULT WINAPI ddraw_surface7_SetLOD(IDirectDrawSurface7 *iface, DWORD MaxLOD)
3561 {
3562     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3563     HRESULT hr;
3564
3565     TRACE("iface %p, lod %u.\n", iface, MaxLOD);
3566
3567     EnterCriticalSection(&ddraw_cs);
3568     if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
3569     {
3570         LeaveCriticalSection(&ddraw_cs);
3571         return DDERR_INVALIDOBJECT;
3572     }
3573
3574     if (!This->wined3d_texture)
3575     {
3576         ERR("(%p) The DirectDraw texture has no WineD3DTexture!\n", This);
3577         LeaveCriticalSection(&ddraw_cs);
3578         return DDERR_INVALIDOBJECT;
3579     }
3580
3581     hr = wined3d_texture_set_lod(This->wined3d_texture, MaxLOD);
3582     LeaveCriticalSection(&ddraw_cs);
3583     return hr;
3584 }
3585
3586 /*****************************************************************************
3587  * IDirectDrawSurface7::GetLOD
3588  *
3589  * Returns the level of detail of a Direct3D texture
3590  *
3591  * Params:
3592  *  MaxLOD: Address to write the LOD to
3593  *
3594  * Returns:
3595  *  DD_OK on success
3596  *  DDERR_INVALIDPARAMS if MaxLOD is NULL
3597  *  DDERR_INVALIDOBJECT if the surface is invalid for this method
3598  *
3599  *****************************************************************************/
3600 static HRESULT WINAPI ddraw_surface7_GetLOD(IDirectDrawSurface7 *iface, DWORD *MaxLOD)
3601 {
3602     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3603
3604     TRACE("iface %p, lod %p.\n", iface, MaxLOD);
3605
3606     if(!MaxLOD)
3607         return DDERR_INVALIDPARAMS;
3608
3609     EnterCriticalSection(&ddraw_cs);
3610     if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
3611     {
3612         LeaveCriticalSection(&ddraw_cs);
3613         return DDERR_INVALIDOBJECT;
3614     }
3615
3616     *MaxLOD = wined3d_texture_get_lod(This->wined3d_texture);
3617     LeaveCriticalSection(&ddraw_cs);
3618     return DD_OK;
3619 }
3620
3621 /*****************************************************************************
3622  * IDirectDrawSurface7::BltFast
3623  *
3624  * Performs a fast Blit.
3625  *
3626  * Params:
3627  *  dstx: The x coordinate to blit to on the destination
3628  *  dsty: The y coordinate to blit to on the destination
3629  *  Source: The source surface
3630  *  rsrc: The source rectangle
3631  *  trans: Type of transfer. Some DDBLTFAST_* flags
3632  *
3633  * Returns:
3634  *  DD_OK on success
3635  *  For more details, see IWineD3DSurface::BltFast
3636  *
3637  *****************************************************************************/
3638 static HRESULT WINAPI ddraw_surface7_BltFast(IDirectDrawSurface7 *iface, DWORD dstx, DWORD dsty,
3639         IDirectDrawSurface7 *Source, RECT *rsrc, DWORD trans)
3640 {
3641     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3642     IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(Source);
3643     DWORD src_w, src_h, dst_w, dst_h;
3644     HRESULT hr;
3645
3646     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
3647             iface, dstx, dsty, Source, wine_dbgstr_rect(rsrc), trans);
3648
3649     dst_w = This->surface_desc.dwWidth;
3650     dst_h = This->surface_desc.dwHeight;
3651
3652     /* Source must be != NULL, This is not checked by windows. Windows happily throws a 0xc0000005
3653      * in that case
3654      */
3655     if(rsrc)
3656     {
3657         src_w = rsrc->right - rsrc->left;
3658         src_h = rsrc->bottom - rsrc->top;
3659     }
3660     else
3661     {
3662         src_w = src->surface_desc.dwWidth;
3663         src_h = src->surface_desc.dwHeight;
3664     }
3665
3666     if (src_w > dst_w || dstx > dst_w - src_w
3667             || src_h > dst_h || dsty > dst_h - src_h)
3668     {
3669         WARN("Destination area out of bounds, returning DDERR_INVALIDRECT.\n");
3670         return DDERR_INVALIDRECT;
3671     }
3672
3673     EnterCriticalSection(&ddraw_cs);
3674     hr = wined3d_surface_bltfast(This->wined3d_surface, dstx, dsty,
3675             src->wined3d_surface, rsrc, trans);
3676     LeaveCriticalSection(&ddraw_cs);
3677     switch(hr)
3678     {
3679         case WINED3DERR_NOTAVAILABLE:           return DDERR_UNSUPPORTED;
3680         case WINED3DERR_WRONGTEXTUREFORMAT:     return DDERR_INVALIDPIXELFORMAT;
3681         default:                                return hr;
3682     }
3683 }
3684
3685 static HRESULT WINAPI ddraw_surface4_BltFast(IDirectDrawSurface4 *iface, DWORD dst_x, DWORD dst_y,
3686         IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags)
3687 {
3688     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3689     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface4(src_surface);
3690     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
3691             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
3692
3693     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
3694             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
3695 }
3696
3697 static HRESULT WINAPI ddraw_surface3_BltFast(IDirectDrawSurface3 *iface, DWORD dst_x, DWORD dst_y,
3698         IDirectDrawSurface3 *src_surface, RECT *src_rect, DWORD flags)
3699 {
3700     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3701     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface3(src_surface);
3702     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
3703             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
3704
3705     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
3706             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
3707 }
3708
3709 static HRESULT WINAPI ddraw_surface2_BltFast(IDirectDrawSurface2 *iface, DWORD dst_x, DWORD dst_y,
3710         IDirectDrawSurface2 *src_surface, RECT *src_rect, DWORD flags)
3711 {
3712     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3713     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface2(src_surface);
3714     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
3715             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
3716
3717     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
3718             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
3719 }
3720
3721 static HRESULT WINAPI ddraw_surface1_BltFast(IDirectDrawSurface *iface, DWORD dst_x, DWORD dst_y,
3722         IDirectDrawSurface *src_surface, RECT *src_rect, DWORD flags)
3723 {
3724     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3725     IDirectDrawSurfaceImpl *src_impl = unsafe_impl_from_IDirectDrawSurface(src_surface);
3726     TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
3727             iface, dst_x, dst_y, src_surface, wine_dbgstr_rect(src_rect), flags);
3728
3729     return ddraw_surface7_BltFast(&This->IDirectDrawSurface7_iface, dst_x, dst_y,
3730             src_impl ? &src_impl->IDirectDrawSurface7_iface : NULL, src_rect, flags);
3731 }
3732
3733 /*****************************************************************************
3734  * IDirectDrawSurface7::GetClipper
3735  *
3736  * Returns the IDirectDrawClipper interface of the clipper assigned to this
3737  * surface
3738  *
3739  * Params:
3740  *  Clipper: Address to store the interface pointer at
3741  *
3742  * Returns:
3743  *  DD_OK on success
3744  *  DDERR_INVALIDPARAMS if Clipper is NULL
3745  *  DDERR_NOCLIPPERATTACHED if there's no clipper attached
3746  *
3747  *****************************************************************************/
3748 static HRESULT WINAPI ddraw_surface7_GetClipper(IDirectDrawSurface7 *iface, IDirectDrawClipper **Clipper)
3749 {
3750     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3751
3752     TRACE("iface %p, clipper %p.\n", iface, Clipper);
3753
3754     if(!Clipper)
3755     {
3756         LeaveCriticalSection(&ddraw_cs);
3757         return DDERR_INVALIDPARAMS;
3758     }
3759
3760     EnterCriticalSection(&ddraw_cs);
3761     if(This->clipper == NULL)
3762     {
3763         LeaveCriticalSection(&ddraw_cs);
3764         return DDERR_NOCLIPPERATTACHED;
3765     }
3766
3767     *Clipper = (IDirectDrawClipper *)This->clipper;
3768     IDirectDrawClipper_AddRef(*Clipper);
3769     LeaveCriticalSection(&ddraw_cs);
3770     return DD_OK;
3771 }
3772
3773 static HRESULT WINAPI ddraw_surface4_GetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper **clipper)
3774 {
3775     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3776     TRACE("iface %p, clipper %p.\n", iface, clipper);
3777
3778     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
3779 }
3780
3781 static HRESULT WINAPI ddraw_surface3_GetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper **clipper)
3782 {
3783     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3784     TRACE("iface %p, clipper %p.\n", iface, clipper);
3785
3786     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
3787 }
3788
3789 static HRESULT WINAPI ddraw_surface2_GetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper **clipper)
3790 {
3791     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3792     TRACE("iface %p, clipper %p.\n", iface, clipper);
3793
3794     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
3795 }
3796
3797 static HRESULT WINAPI ddraw_surface1_GetClipper(IDirectDrawSurface *iface, IDirectDrawClipper **clipper)
3798 {
3799     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3800     TRACE("iface %p, clipper %p.\n", iface, clipper);
3801
3802     return ddraw_surface7_GetClipper(&This->IDirectDrawSurface7_iface, clipper);
3803 }
3804
3805 /*****************************************************************************
3806  * IDirectDrawSurface7::SetClipper
3807  *
3808  * Sets a clipper for the surface
3809  *
3810  * Params:
3811  *  Clipper: IDirectDrawClipper interface of the clipper to set
3812  *
3813  * Returns:
3814  *  DD_OK on success
3815  *
3816  *****************************************************************************/
3817 static HRESULT WINAPI ddraw_surface7_SetClipper(IDirectDrawSurface7 *iface,
3818         IDirectDrawClipper *iclipper)
3819 {
3820     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3821     IDirectDrawClipperImpl *clipper = unsafe_impl_from_IDirectDrawClipper(iclipper);
3822     IDirectDrawClipperImpl *oldClipper = This->clipper;
3823     HWND clipWindow;
3824     HRESULT hr;
3825
3826     TRACE("iface %p, clipper %p.\n", iface, iclipper);
3827
3828     EnterCriticalSection(&ddraw_cs);
3829     if (clipper == This->clipper)
3830     {
3831         LeaveCriticalSection(&ddraw_cs);
3832         return DD_OK;
3833     }
3834
3835     This->clipper = clipper;
3836
3837     if (clipper != NULL)
3838         IDirectDrawClipper_AddRef(iclipper);
3839     if(oldClipper)
3840         IDirectDrawClipper_Release(&oldClipper->IDirectDrawClipper_iface);
3841
3842     hr = wined3d_surface_set_clipper(This->wined3d_surface,
3843             This->clipper ? This->clipper->wineD3DClipper : NULL);
3844
3845     if (This->wined3d_swapchain)
3846     {
3847         clipWindow = NULL;
3848         if(clipper) {
3849             IDirectDrawClipper_GetHWnd(iclipper, &clipWindow);
3850         }
3851
3852         if (clipWindow)
3853             wined3d_swapchain_set_window(This->wined3d_swapchain, clipWindow);
3854         else
3855             wined3d_swapchain_set_window(This->wined3d_swapchain, This->ddraw->d3d_window);
3856     }
3857
3858     LeaveCriticalSection(&ddraw_cs);
3859     return hr;
3860 }
3861
3862 static HRESULT WINAPI ddraw_surface4_SetClipper(IDirectDrawSurface4 *iface, IDirectDrawClipper *clipper)
3863 {
3864     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3865     TRACE("iface %p, clipper %p.\n", iface, clipper);
3866
3867     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
3868 }
3869
3870 static HRESULT WINAPI ddraw_surface3_SetClipper(IDirectDrawSurface3 *iface, IDirectDrawClipper *clipper)
3871 {
3872     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
3873     TRACE("iface %p, clipper %p.\n", iface, clipper);
3874
3875     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
3876 }
3877
3878 static HRESULT WINAPI ddraw_surface2_SetClipper(IDirectDrawSurface2 *iface, IDirectDrawClipper *clipper)
3879 {
3880     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
3881     TRACE("iface %p, clipper %p.\n", iface, clipper);
3882
3883     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
3884 }
3885
3886 static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDirectDrawClipper *clipper)
3887 {
3888     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
3889     TRACE("iface %p, clipper %p.\n", iface, clipper);
3890
3891     return ddraw_surface7_SetClipper(&This->IDirectDrawSurface7_iface, clipper);
3892 }
3893
3894 /*****************************************************************************
3895  * IDirectDrawSurface7::SetSurfaceDesc
3896  *
3897  * Sets the surface description. It can override the pixel format, the surface
3898  * memory, ...
3899  * It's not really tested.
3900  *
3901  * Params:
3902  * DDSD: Pointer to the new surface description to set
3903  * Flags: Some flags
3904  *
3905  * Returns:
3906  *  DD_OK on success
3907  *  DDERR_INVALIDPARAMS if DDSD is NULL
3908  *
3909  *****************************************************************************/
3910 static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
3911 {
3912     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
3913     enum wined3d_format_id newFormat = WINED3DFMT_UNKNOWN;
3914     HRESULT hr;
3915
3916     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
3917
3918     if (!DDSD)
3919     {
3920         WARN("DDSD is NULL, returning DDERR_INVALIDPARAMS\n");
3921         return DDERR_INVALIDPARAMS;
3922     }
3923     if (Flags)
3924     {
3925         WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags);
3926         return DDERR_INVALIDPARAMS;
3927     }
3928
3929     EnterCriticalSection(&ddraw_cs);
3930     if (DDSD->dwFlags & DDSD_PIXELFORMAT)
3931     {
3932         newFormat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
3933
3934         if(newFormat == WINED3DFMT_UNKNOWN)
3935         {
3936             ERR("Requested to set an unknown pixelformat\n");
3937             LeaveCriticalSection(&ddraw_cs);
3938             return DDERR_INVALIDPARAMS;
3939         }
3940         if(newFormat != PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat) )
3941         {
3942             hr = wined3d_surface_set_format(This->wined3d_surface, newFormat);
3943             if (FAILED(hr))
3944             {
3945                 LeaveCriticalSection(&ddraw_cs);
3946                 return hr;
3947             }
3948         }
3949     }
3950     if (DDSD->dwFlags & DDSD_CKDESTOVERLAY)
3951     {
3952         wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_DESTOVERLAY,
3953                 (WINEDDCOLORKEY *)&DDSD->u3.ddckCKDestOverlay);
3954     }
3955     if (DDSD->dwFlags & DDSD_CKDESTBLT)
3956     {
3957         wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_DESTBLT,
3958                 (WINEDDCOLORKEY *)&DDSD->ddckCKDestBlt);
3959     }
3960     if (DDSD->dwFlags & DDSD_CKSRCOVERLAY)
3961     {
3962         wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_SRCOVERLAY,
3963                 (WINEDDCOLORKEY *)&DDSD->ddckCKSrcOverlay);
3964     }
3965     if (DDSD->dwFlags & DDSD_CKSRCBLT)
3966     {
3967         wined3d_surface_set_color_key(This->wined3d_surface, DDCKEY_SRCBLT,
3968                 (WINEDDCOLORKEY *)&DDSD->ddckCKSrcBlt);
3969     }
3970     if (DDSD->dwFlags & DDSD_LPSURFACE && DDSD->lpSurface)
3971     {
3972         hr = wined3d_surface_set_mem(This->wined3d_surface, DDSD->lpSurface);
3973         if (FAILED(hr))
3974         {
3975             /* No need for a trace here, wined3d does that for us */
3976             switch(hr)
3977             {
3978                 case WINED3DERR_INVALIDCALL:
3979                     LeaveCriticalSection(&ddraw_cs);
3980                     return DDERR_INVALIDPARAMS;
3981                 default:
3982                     break; /* Go on */
3983             }
3984         }
3985     }
3986
3987     This->surface_desc = *DDSD;
3988
3989     LeaveCriticalSection(&ddraw_cs);
3990     return DD_OK;
3991 }
3992
3993 static HRESULT WINAPI ddraw_surface4_SetSurfaceDesc(IDirectDrawSurface4 *iface,
3994         DDSURFACEDESC2 *surface_desc, DWORD flags)
3995 {
3996     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
3997     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
3998
3999     return ddraw_surface7_SetSurfaceDesc(&This->IDirectDrawSurface7_iface,
4000             surface_desc, flags);
4001 }
4002
4003 static HRESULT WINAPI ddraw_surface3_SetSurfaceDesc(IDirectDrawSurface3 *iface,
4004         DDSURFACEDESC *surface_desc, DWORD flags)
4005 {
4006     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
4007     DDSURFACEDESC2 surface_desc2;
4008     TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, surface_desc, flags);
4009
4010     if (surface_desc) DDSD_to_DDSD2(surface_desc, &surface_desc2);
4011     return ddraw_surface7_SetSurfaceDesc(&This->IDirectDrawSurface7_iface,
4012             surface_desc ? &surface_desc2 : NULL, flags);
4013 }
4014
4015 /*****************************************************************************
4016  * IDirectDrawSurface7::GetPalette
4017  *
4018  * Returns the IDirectDrawPalette interface of the palette currently assigned
4019  * to the surface
4020  *
4021  * Params:
4022  *  Pal: Address to write the interface pointer to
4023  *
4024  * Returns:
4025  *  DD_OK on success
4026  *  DDERR_INVALIDPARAMS if Pal is NULL
4027  *
4028  *****************************************************************************/
4029 static HRESULT WINAPI ddraw_surface7_GetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette **Pal)
4030 {
4031     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
4032     struct wined3d_palette *wined3d_palette;
4033     HRESULT hr = DD_OK;
4034
4035     TRACE("iface %p, palette %p.\n", iface, Pal);
4036
4037     if(!Pal)
4038         return DDERR_INVALIDPARAMS;
4039
4040     EnterCriticalSection(&ddraw_cs);
4041     wined3d_palette = wined3d_surface_get_palette(This->wined3d_surface);
4042     if (wined3d_palette)
4043     {
4044         *Pal = wined3d_palette_get_parent(wined3d_palette);
4045         IDirectDrawPalette_AddRef(*Pal);
4046     }
4047     else
4048     {
4049         *Pal = NULL;
4050         hr = DDERR_NOPALETTEATTACHED;
4051     }
4052
4053     LeaveCriticalSection(&ddraw_cs);
4054     return hr;
4055 }
4056
4057 static HRESULT WINAPI ddraw_surface4_GetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette **palette)
4058 {
4059     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
4060     TRACE("iface %p, palette %p.\n", iface, palette);
4061
4062     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
4063 }
4064
4065 static HRESULT WINAPI ddraw_surface3_GetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette **palette)
4066 {
4067     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
4068     TRACE("iface %p, palette %p.\n", iface, palette);
4069
4070     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
4071 }
4072
4073 static HRESULT WINAPI ddraw_surface2_GetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette **palette)
4074 {
4075     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
4076     TRACE("iface %p, palette %p.\n", iface, palette);
4077
4078     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
4079 }
4080
4081 static HRESULT WINAPI ddraw_surface1_GetPalette(IDirectDrawSurface *iface, IDirectDrawPalette **palette)
4082 {
4083     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
4084     TRACE("iface %p, palette %p.\n", iface, palette);
4085
4086     return ddraw_surface7_GetPalette(&This->IDirectDrawSurface7_iface, palette);
4087 }
4088
4089 /*****************************************************************************
4090  * SetColorKeyEnum
4091  *
4092  * EnumAttachedSurface callback for SetColorKey. Used to set color keys
4093  * recursively in the surface tree
4094  *
4095  *****************************************************************************/
4096 struct SCKContext
4097 {
4098     HRESULT ret;
4099     WINEDDCOLORKEY *CKey;
4100     DWORD Flags;
4101 };
4102
4103 static HRESULT WINAPI
4104 SetColorKeyEnum(IDirectDrawSurface7 *surface,
4105                 DDSURFACEDESC2 *desc,
4106                 void *context)
4107 {
4108     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(surface);
4109     struct SCKContext *ctx = context;
4110     HRESULT hr;
4111
4112     hr = wined3d_surface_set_color_key(This->wined3d_surface, ctx->Flags, ctx->CKey);
4113     if (FAILED(hr))
4114     {
4115         WARN("IWineD3DSurface_SetColorKey failed, hr = %08x\n", hr);
4116         ctx->ret = hr;
4117     }
4118
4119     ddraw_surface7_EnumAttachedSurfaces(surface, context, SetColorKeyEnum);
4120     ddraw_surface7_Release(surface);
4121
4122     return DDENUMRET_OK;
4123 }
4124
4125 /*****************************************************************************
4126  * IDirectDrawSurface7::SetColorKey
4127  *
4128  * Sets the color keying options for the surface. Observations showed that
4129  * in case of complex surfaces the color key has to be assigned to all
4130  * sublevels.
4131  *
4132  * Params:
4133  *  Flags: DDCKEY_*
4134  *  CKey: The new color key
4135  *
4136  * Returns:
4137  *  DD_OK on success
4138  *  See IWineD3DSurface::SetColorKey for details
4139  *
4140  *****************************************************************************/
4141 static HRESULT WINAPI ddraw_surface7_SetColorKey(IDirectDrawSurface7 *iface, DWORD Flags, DDCOLORKEY *CKey)
4142 {
4143     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
4144     DDCOLORKEY FixedCKey;
4145     struct SCKContext ctx = { DD_OK, (WINEDDCOLORKEY *) (CKey ? &FixedCKey : NULL), Flags };
4146
4147     TRACE("iface %p, flags %#x, color_key %p.\n", iface, Flags, CKey);
4148
4149     EnterCriticalSection(&ddraw_cs);
4150     if (CKey)
4151     {
4152         FixedCKey = *CKey;
4153         /* Handle case where dwColorSpaceHighValue < dwColorSpaceLowValue */
4154         if (FixedCKey.dwColorSpaceHighValue < FixedCKey.dwColorSpaceLowValue)
4155             FixedCKey.dwColorSpaceHighValue = FixedCKey.dwColorSpaceLowValue;
4156
4157         switch (Flags & ~DDCKEY_COLORSPACE)
4158         {
4159         case DDCKEY_DESTBLT:
4160             This->surface_desc.ddckCKDestBlt = FixedCKey;
4161             This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
4162             break;
4163
4164         case DDCKEY_DESTOVERLAY:
4165             This->surface_desc.u3.ddckCKDestOverlay = FixedCKey;
4166             This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
4167             break;
4168
4169         case DDCKEY_SRCOVERLAY:
4170             This->surface_desc.ddckCKSrcOverlay = FixedCKey;
4171             This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
4172             break;
4173
4174         case DDCKEY_SRCBLT:
4175             This->surface_desc.ddckCKSrcBlt = FixedCKey;
4176             This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
4177             break;
4178
4179         default:
4180             LeaveCriticalSection(&ddraw_cs);
4181             return DDERR_INVALIDPARAMS;
4182         }
4183     }
4184     else
4185     {
4186         switch (Flags & ~DDCKEY_COLORSPACE)
4187         {
4188         case DDCKEY_DESTBLT:
4189             This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
4190             break;
4191
4192         case DDCKEY_DESTOVERLAY:
4193             This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
4194             break;
4195
4196         case DDCKEY_SRCOVERLAY:
4197             This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
4198             break;
4199
4200         case DDCKEY_SRCBLT:
4201             This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
4202             break;
4203
4204         default:
4205             LeaveCriticalSection(&ddraw_cs);
4206             return DDERR_INVALIDPARAMS;
4207         }
4208     }
4209     ctx.ret = wined3d_surface_set_color_key(This->wined3d_surface, Flags, ctx.CKey);
4210     ddraw_surface7_EnumAttachedSurfaces(iface, &ctx, SetColorKeyEnum);
4211     LeaveCriticalSection(&ddraw_cs);
4212     switch(ctx.ret)
4213     {
4214         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
4215         default:                            return ctx.ret;
4216     }
4217 }
4218
4219 static HRESULT WINAPI ddraw_surface4_SetColorKey(IDirectDrawSurface4 *iface, DWORD flags, DDCOLORKEY *color_key)
4220 {
4221     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
4222     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4223
4224     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
4225 }
4226
4227 static HRESULT WINAPI ddraw_surface3_SetColorKey(IDirectDrawSurface3 *iface, DWORD flags, DDCOLORKEY *color_key)
4228 {
4229     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
4230     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4231
4232     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
4233 }
4234
4235 static HRESULT WINAPI ddraw_surface2_SetColorKey(IDirectDrawSurface2 *iface, DWORD flags, DDCOLORKEY *color_key)
4236 {
4237     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
4238     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4239
4240     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
4241 }
4242
4243 static HRESULT WINAPI ddraw_surface1_SetColorKey(IDirectDrawSurface *iface, DWORD flags, DDCOLORKEY *color_key)
4244 {
4245     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
4246     TRACE("iface %p, flags %#x, color_key %p.\n", iface, flags, color_key);
4247
4248     return ddraw_surface7_SetColorKey(&This->IDirectDrawSurface7_iface, flags, color_key);
4249 }
4250
4251 /*****************************************************************************
4252  * IDirectDrawSurface7::SetPalette
4253  *
4254  * Assigns a DirectDrawPalette object to the surface
4255  *
4256  * Params:
4257  *  Pal: Interface to the palette to set
4258  *
4259  * Returns:
4260  *  DD_OK on success
4261  *
4262  *****************************************************************************/
4263 static HRESULT WINAPI ddraw_surface7_SetPalette(IDirectDrawSurface7 *iface, IDirectDrawPalette *Pal)
4264 {
4265     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
4266     IDirectDrawPalette *oldPal;
4267     IDirectDrawSurfaceImpl *surf;
4268     IDirectDrawPaletteImpl *PalImpl = (IDirectDrawPaletteImpl *)Pal;
4269     HRESULT hr;
4270
4271     TRACE("iface %p, palette %p.\n", iface, Pal);
4272
4273     if (!(This->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
4274             DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8))) {
4275         return DDERR_INVALIDPIXELFORMAT;
4276     }
4277
4278     if (This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
4279     {
4280         return DDERR_NOTONMIPMAPSUBLEVEL;
4281     }
4282
4283     /* Find the old palette */
4284     EnterCriticalSection(&ddraw_cs);
4285     hr = IDirectDrawSurface_GetPalette(iface, &oldPal);
4286     if(hr != DD_OK && hr != DDERR_NOPALETTEATTACHED)
4287     {
4288         LeaveCriticalSection(&ddraw_cs);
4289         return hr;
4290     }
4291     if(oldPal) IDirectDrawPalette_Release(oldPal);  /* For the GetPalette */
4292
4293     /* Set the new Palette */
4294     wined3d_surface_set_palette(This->wined3d_surface, PalImpl ? PalImpl->wineD3DPalette : NULL);
4295     /* AddRef the Palette */
4296     if(Pal) IDirectDrawPalette_AddRef(Pal);
4297
4298     /* Release the old palette */
4299     if(oldPal) IDirectDrawPalette_Release(oldPal);
4300
4301     /* If this is a front buffer, also update the back buffers
4302      * TODO: How do things work for palettized cube textures?
4303      */
4304     if(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
4305     {
4306         /* For primary surfaces the tree is just a list, so the simpler scheme fits too */
4307         DDSCAPS2 caps2 = { DDSCAPS_PRIMARYSURFACE, 0, 0, 0 };
4308
4309         surf = This;
4310         while(1)
4311         {
4312             IDirectDrawSurface7 *attach;
4313             HRESULT hr;
4314             hr = ddraw_surface7_GetAttachedSurface(&surf->IDirectDrawSurface7_iface, &caps2, &attach);
4315             if(hr != DD_OK)
4316             {
4317                 break;
4318             }
4319
4320             TRACE("Setting palette on %p\n", attach);
4321             ddraw_surface7_SetPalette(attach, Pal);
4322             surf = impl_from_IDirectDrawSurface7(attach);
4323             ddraw_surface7_Release(attach);
4324         }
4325     }
4326
4327     LeaveCriticalSection(&ddraw_cs);
4328     return DD_OK;
4329 }
4330
4331 static HRESULT WINAPI ddraw_surface4_SetPalette(IDirectDrawSurface4 *iface, IDirectDrawPalette *palette)
4332 {
4333     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
4334     TRACE("iface %p, palette %p.\n", iface, palette);
4335
4336     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
4337 }
4338
4339 static HRESULT WINAPI ddraw_surface3_SetPalette(IDirectDrawSurface3 *iface, IDirectDrawPalette *palette)
4340 {
4341     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
4342     TRACE("iface %p, palette %p.\n", iface, palette);
4343
4344     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
4345 }
4346
4347 static HRESULT WINAPI ddraw_surface2_SetPalette(IDirectDrawSurface2 *iface, IDirectDrawPalette *palette)
4348 {
4349     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface);
4350     TRACE("iface %p, palette %p.\n", iface, palette);
4351
4352     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
4353 }
4354
4355 static HRESULT WINAPI ddraw_surface1_SetPalette(IDirectDrawSurface *iface, IDirectDrawPalette *palette)
4356 {
4357     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface(iface);
4358     TRACE("iface %p, palette %p.\n", iface, palette);
4359
4360     return ddraw_surface7_SetPalette(&This->IDirectDrawSurface7_iface, palette);
4361 }
4362
4363 /**********************************************************
4364  * IDirectDrawGammaControl::GetGammaRamp
4365  *
4366  * Returns the current gamma ramp for a surface
4367  *
4368  * Params:
4369  *  flags: Ignored
4370  *  gamma_ramp: Address to write the ramp to
4371  *
4372  * Returns:
4373  *  DD_OK on success
4374  *  DDERR_INVALIDPARAMS if gamma_ramp is NULL
4375  *
4376  **********************************************************/
4377 static HRESULT WINAPI ddraw_gamma_control_GetGammaRamp(IDirectDrawGammaControl *iface,
4378         DWORD flags, DDGAMMARAMP *gamma_ramp)
4379 {
4380     IDirectDrawSurfaceImpl *surface = impl_from_IDirectDrawGammaControl(iface);
4381
4382     TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
4383
4384     if (!gamma_ramp)
4385     {
4386         WARN("Invalid gamma_ramp passed.\n");
4387         return DDERR_INVALIDPARAMS;
4388     }
4389
4390     EnterCriticalSection(&ddraw_cs);
4391     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4392     {
4393         /* Note: DDGAMMARAMP is compatible with WINED3DGAMMARAMP. */
4394         wined3d_device_get_gamma_ramp(surface->ddraw->wined3d_device, 0, (WINED3DGAMMARAMP *)gamma_ramp);
4395     }
4396     else
4397     {
4398         ERR("Not implemented for non-primary surfaces.\n");
4399     }
4400     LeaveCriticalSection(&ddraw_cs);
4401
4402     return DD_OK;
4403 }
4404
4405 /**********************************************************
4406  * IDirectDrawGammaControl::SetGammaRamp
4407  *
4408  * Sets the red, green and blue gamma ramps for
4409  *
4410  * Params:
4411  *  flags: Can be DDSGR_CALIBRATE to request calibration
4412  *  gamma_ramp: Structure containing the new gamma ramp
4413  *
4414  * Returns:
4415  *  DD_OK on success
4416  *  DDERR_INVALIDPARAMS if gamma_ramp is NULL
4417  *
4418  **********************************************************/
4419 static HRESULT WINAPI ddraw_gamma_control_SetGammaRamp(IDirectDrawGammaControl *iface,
4420         DWORD flags, DDGAMMARAMP *gamma_ramp)
4421 {
4422     IDirectDrawSurfaceImpl *surface = impl_from_IDirectDrawGammaControl(iface);
4423
4424     TRACE("iface %p, flags %#x, gamma_ramp %p.\n", iface, flags, gamma_ramp);
4425
4426     if (!gamma_ramp)
4427     {
4428         WARN("Invalid gamma_ramp passed.\n");
4429         return DDERR_INVALIDPARAMS;
4430     }
4431
4432     EnterCriticalSection(&ddraw_cs);
4433     if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
4434     {
4435         /* Note: DDGAMMARAMP is compatible with WINED3DGAMMARAMP */
4436         wined3d_device_set_gamma_ramp(surface->ddraw->wined3d_device, 0, flags, (WINED3DGAMMARAMP *)gamma_ramp);
4437     }
4438     else
4439     {
4440         ERR("Not implemented for non-primary surfaces.\n");
4441     }
4442     LeaveCriticalSection(&ddraw_cs);
4443
4444     return DD_OK;
4445 }
4446
4447 /*****************************************************************************
4448  * IDirect3DTexture2::PaletteChanged
4449  *
4450  * Informs the texture about a palette change
4451  *
4452  * Params:
4453  *  start: Start index of the change
4454  *  count: The number of changed entries
4455  *
4456  * Returns
4457  *  D3D_OK, because it's a stub
4458  *
4459  *****************************************************************************/
4460 static HRESULT WINAPI d3d_texture2_PaletteChanged(IDirect3DTexture2 *iface, DWORD start, DWORD count)
4461 {
4462     FIXME("iface %p, start %u, count %u stub!\n", iface, start, count);
4463
4464     return D3D_OK;
4465 }
4466
4467 static HRESULT WINAPI d3d_texture1_PaletteChanged(IDirect3DTexture *iface, DWORD start, DWORD count)
4468 {
4469     IDirectDrawSurfaceImpl *surface = impl_from_IDirect3DTexture(iface);
4470
4471     TRACE("iface %p, start %u, count %u.\n", iface, start, count);
4472
4473     return d3d_texture2_PaletteChanged(&surface->IDirect3DTexture2_iface, start, count);
4474 }
4475
4476 /*****************************************************************************
4477  * IDirect3DTexture::Unload
4478  *
4479  * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
4480  *
4481  *
4482  * Returns:
4483  *  DDERR_UNSUPPORTED
4484  *
4485  *****************************************************************************/
4486 static HRESULT WINAPI d3d_texture1_Unload(IDirect3DTexture *iface)
4487 {
4488     WARN("iface %p. Not implemented.\n", iface);
4489
4490     return DDERR_UNSUPPORTED;
4491 }
4492
4493 /*****************************************************************************
4494  * IDirect3DTexture2::GetHandle
4495  *
4496  * Returns handle for the texture. At the moment, the interface
4497  * to the IWineD3DTexture is used.
4498  *
4499  * Params:
4500  *  device: Device this handle is assigned to
4501  *  handle: Address to store the handle at.
4502  *
4503  * Returns:
4504  *  D3D_OK
4505  *
4506  *****************************************************************************/
4507 static HRESULT WINAPI d3d_texture2_GetHandle(IDirect3DTexture2 *iface,
4508         IDirect3DDevice2 *device, D3DTEXTUREHANDLE *handle)
4509 {
4510     IDirectDrawSurfaceImpl *surface = impl_from_IDirect3DTexture2(iface);
4511
4512     TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
4513
4514     EnterCriticalSection(&ddraw_cs);
4515
4516     if (!surface->Handle)
4517     {
4518         DWORD h = ddraw_allocate_handle(&device_from_device2(device)->handle_table, surface, DDRAW_HANDLE_SURFACE);
4519         if (h == DDRAW_INVALID_HANDLE)
4520         {
4521             ERR("Failed to allocate a texture handle.\n");
4522             LeaveCriticalSection(&ddraw_cs);
4523             return DDERR_OUTOFMEMORY;
4524         }
4525
4526         surface->Handle = h + 1;
4527     }
4528
4529     TRACE("Returning handle %08x.\n", surface->Handle);
4530     *handle = surface->Handle;
4531
4532     LeaveCriticalSection(&ddraw_cs);
4533
4534     return D3D_OK;
4535 }
4536
4537 static HRESULT WINAPI d3d_texture1_GetHandle(IDirect3DTexture *iface,
4538         IDirect3DDevice *device, D3DTEXTUREHANDLE *handle)
4539 {
4540     IDirectDrawSurfaceImpl *This = impl_from_IDirect3DTexture(iface);
4541     IDirect3DDevice2 *device2 = (IDirect3DDevice2 *)&device_from_device1(device)->IDirect3DDevice2_vtbl;
4542
4543     TRACE("iface %p, device %p, handle %p.\n", iface, device, handle);
4544
4545     return d3d_texture2_GetHandle(&This->IDirect3DTexture2_iface, device2, handle);
4546 }
4547
4548 /*****************************************************************************
4549  * get_sub_mimaplevel
4550  *
4551  * Helper function that returns the next mipmap level
4552  *
4553  * tex_ptr: Surface of which to return the next level
4554  *
4555  *****************************************************************************/
4556 static IDirectDrawSurfaceImpl *get_sub_mimaplevel(IDirectDrawSurfaceImpl *surface)
4557 {
4558     /* Now go down the mipmap chain to the next surface */
4559     static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, 0 };
4560     IDirectDrawSurface7 *next_level;
4561     HRESULT hr;
4562
4563     hr = ddraw_surface7_GetAttachedSurface(&surface->IDirectDrawSurface7_iface, &mipmap_caps, &next_level);
4564     if (FAILED(hr)) return NULL;
4565
4566     ddraw_surface7_Release(next_level);
4567
4568     return impl_from_IDirectDrawSurface7(next_level);
4569 }
4570
4571 /*****************************************************************************
4572  * IDirect3DTexture2::Load
4573  *
4574  * Loads a texture created with the DDSCAPS_ALLOCONLOAD
4575  *
4576  * This function isn't relayed to WineD3D because the whole interface is
4577  * implemented in DDraw only. For speed improvements a implementation which
4578  * takes OpenGL more into account could be placed into WineD3D.
4579  *
4580  * Params:
4581  *  src_texture: Address of the texture to load
4582  *
4583  * Returns:
4584  *  D3D_OK on success
4585  *  D3DERR_TEXTURE_LOAD_FAILED.
4586  *
4587  *****************************************************************************/
4588 static HRESULT WINAPI d3d_texture2_Load(IDirect3DTexture2 *iface, IDirect3DTexture2 *src_texture)
4589 {
4590     IDirectDrawSurfaceImpl *dst_surface = impl_from_IDirect3DTexture2(iface);
4591     IDirectDrawSurfaceImpl *src_surface = unsafe_impl_from_IDirect3DTexture2(src_texture);
4592     HRESULT hr;
4593
4594     TRACE("iface %p, src_texture %p.\n", iface, src_texture);
4595
4596     if (src_surface == dst_surface)
4597     {
4598         TRACE("copying surface %p to surface %p, why?\n", src_surface, dst_surface);
4599         return D3D_OK;
4600     }
4601
4602     EnterCriticalSection(&ddraw_cs);
4603
4604     if (((src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
4605             != (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP))
4606             || (src_surface->surface_desc.u2.dwMipMapCount != dst_surface->surface_desc.u2.dwMipMapCount))
4607     {
4608         ERR("Trying to load surfaces with different mip-map counts.\n");
4609     }
4610
4611     for (;;)
4612     {
4613         struct wined3d_palette *wined3d_dst_pal, *wined3d_src_pal;
4614         IDirectDrawPalette *dst_pal = NULL, *src_pal = NULL;
4615         DDSURFACEDESC *src_desc, *dst_desc;
4616
4617         TRACE("Copying surface %p to surface %p (mipmap level %d).\n",
4618                 src_surface, dst_surface, src_surface->mipmap_level);
4619
4620         /* Suppress the ALLOCONLOAD flag */
4621         dst_surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
4622
4623         /* Get the palettes */
4624         wined3d_dst_pal = wined3d_surface_get_palette(dst_surface->wined3d_surface);
4625         if (wined3d_dst_pal)
4626             dst_pal = wined3d_palette_get_parent(wined3d_dst_pal);
4627
4628         wined3d_src_pal = wined3d_surface_get_palette(src_surface->wined3d_surface);
4629         if (wined3d_src_pal)
4630             src_pal = wined3d_palette_get_parent(wined3d_src_pal);
4631
4632         if (src_pal)
4633         {
4634             PALETTEENTRY palent[256];
4635
4636             if (!dst_pal)
4637             {
4638                 LeaveCriticalSection(&ddraw_cs);
4639                 return DDERR_NOPALETTEATTACHED;
4640             }
4641             IDirectDrawPalette_GetEntries(src_pal, 0, 0, 256, palent);
4642             IDirectDrawPalette_SetEntries(dst_pal, 0, 0, 256, palent);
4643         }
4644
4645         /* Copy one surface on the other */
4646         dst_desc = (DDSURFACEDESC *)&(dst_surface->surface_desc);
4647         src_desc = (DDSURFACEDESC *)&(src_surface->surface_desc);
4648
4649         if ((src_desc->dwWidth != dst_desc->dwWidth) || (src_desc->dwHeight != dst_desc->dwHeight))
4650         {
4651             /* Should also check for same pixel format, u1.lPitch, ... */
4652             ERR("Error in surface sizes.\n");
4653             LeaveCriticalSection(&ddraw_cs);
4654             return D3DERR_TEXTURE_LOAD_FAILED;
4655         }
4656         else
4657         {
4658             WINED3DLOCKED_RECT src_rect, dst_rect;
4659
4660             /* Copy also the ColorKeying stuff */
4661             if (src_desc->dwFlags & DDSD_CKSRCBLT)
4662             {
4663                 dst_desc->dwFlags |= DDSD_CKSRCBLT;
4664                 dst_desc->ddckCKSrcBlt.dwColorSpaceLowValue = src_desc->ddckCKSrcBlt.dwColorSpaceLowValue;
4665                 dst_desc->ddckCKSrcBlt.dwColorSpaceHighValue = src_desc->ddckCKSrcBlt.dwColorSpaceHighValue;
4666             }
4667
4668             /* Copy the main memory texture into the surface that corresponds
4669              * to the OpenGL texture object. */
4670
4671             hr = wined3d_surface_map(src_surface->wined3d_surface, &src_rect, NULL, 0);
4672             if (FAILED(hr))
4673             {
4674                 ERR("Failed to lock source surface, hr %#x.\n", hr);
4675                 LeaveCriticalSection(&ddraw_cs);
4676                 return D3DERR_TEXTURE_LOAD_FAILED;
4677             }
4678
4679             hr = wined3d_surface_map(dst_surface->wined3d_surface, &dst_rect, NULL, 0);
4680             if (FAILED(hr))
4681             {
4682                 ERR("Failed to lock destination surface, hr %#x.\n", hr);
4683                 wined3d_surface_unmap(src_surface->wined3d_surface);
4684                 LeaveCriticalSection(&ddraw_cs);
4685                 return D3DERR_TEXTURE_LOAD_FAILED;
4686             }
4687
4688             if (dst_surface->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
4689                 memcpy(dst_rect.pBits, src_rect.pBits, src_surface->surface_desc.u1.dwLinearSize);
4690             else
4691                 memcpy(dst_rect.pBits, src_rect.pBits, src_rect.Pitch * src_desc->dwHeight);
4692
4693             wined3d_surface_unmap(src_surface->wined3d_surface);
4694             wined3d_surface_unmap(dst_surface->wined3d_surface);
4695         }
4696
4697         if (src_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
4698             src_surface = get_sub_mimaplevel(src_surface);
4699         else
4700             src_surface = NULL;
4701
4702         if (dst_surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
4703             dst_surface = get_sub_mimaplevel(dst_surface);
4704         else
4705             dst_surface = NULL;
4706
4707         if (!src_surface || !dst_surface)
4708         {
4709             if (src_surface != dst_surface)
4710                 ERR("Loading surface with different mipmap structure.\n");
4711             break;
4712         }
4713     }
4714
4715     LeaveCriticalSection(&ddraw_cs);
4716
4717     return hr;
4718 }
4719
4720 static HRESULT WINAPI d3d_texture1_Load(IDirect3DTexture *iface, IDirect3DTexture *src_texture)
4721 {
4722     IDirectDrawSurfaceImpl* This = impl_from_IDirect3DTexture(iface);
4723     IDirectDrawSurfaceImpl* src_surface = unsafe_impl_from_IDirect3DTexture(src_texture);
4724     TRACE("iface %p, src_texture %p.\n", iface, src_texture);
4725
4726     return d3d_texture2_Load(&This->IDirect3DTexture2_iface,
4727             src_surface ? &src_surface->IDirect3DTexture2_iface : NULL);
4728 }
4729
4730 /*****************************************************************************
4731  * The VTable
4732  *****************************************************************************/
4733
4734 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
4735 {
4736     /* IUnknown */
4737     ddraw_surface7_QueryInterface,
4738     ddraw_surface7_AddRef,
4739     ddraw_surface7_Release,
4740     /* IDirectDrawSurface */
4741     ddraw_surface7_AddAttachedSurface,
4742     ddraw_surface7_AddOverlayDirtyRect,
4743     ddraw_surface7_Blt,
4744     ddraw_surface7_BltBatch,
4745     ddraw_surface7_BltFast,
4746     ddraw_surface7_DeleteAttachedSurface,
4747     ddraw_surface7_EnumAttachedSurfaces,
4748     ddraw_surface7_EnumOverlayZOrders,
4749     ddraw_surface7_Flip,
4750     ddraw_surface7_GetAttachedSurface,
4751     ddraw_surface7_GetBltStatus,
4752     ddraw_surface7_GetCaps,
4753     ddraw_surface7_GetClipper,
4754     ddraw_surface7_GetColorKey,
4755     ddraw_surface7_GetDC,
4756     ddraw_surface7_GetFlipStatus,
4757     ddraw_surface7_GetOverlayPosition,
4758     ddraw_surface7_GetPalette,
4759     ddraw_surface7_GetPixelFormat,
4760     ddraw_surface7_GetSurfaceDesc,
4761     ddraw_surface7_Initialize,
4762     ddraw_surface7_IsLost,
4763     ddraw_surface7_Lock,
4764     ddraw_surface7_ReleaseDC,
4765     ddraw_surface7_Restore,
4766     ddraw_surface7_SetClipper,
4767     ddraw_surface7_SetColorKey,
4768     ddraw_surface7_SetOverlayPosition,
4769     ddraw_surface7_SetPalette,
4770     ddraw_surface7_Unlock,
4771     ddraw_surface7_UpdateOverlay,
4772     ddraw_surface7_UpdateOverlayDisplay,
4773     ddraw_surface7_UpdateOverlayZOrder,
4774     /* IDirectDrawSurface2 */
4775     ddraw_surface7_GetDDInterface,
4776     ddraw_surface7_PageLock,
4777     ddraw_surface7_PageUnlock,
4778     /* IDirectDrawSurface3 */
4779     ddraw_surface7_SetSurfaceDesc,
4780     /* IDirectDrawSurface4 */
4781     ddraw_surface7_SetPrivateData,
4782     ddraw_surface7_GetPrivateData,
4783     ddraw_surface7_FreePrivateData,
4784     ddraw_surface7_GetUniquenessValue,
4785     ddraw_surface7_ChangeUniquenessValue,
4786     /* IDirectDrawSurface7 */
4787     ddraw_surface7_SetPriority,
4788     ddraw_surface7_GetPriority,
4789     ddraw_surface7_SetLOD,
4790     ddraw_surface7_GetLOD,
4791 };
4792
4793 static const struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl =
4794 {
4795     /* IUnknown */
4796     ddraw_surface4_QueryInterface,
4797     ddraw_surface4_AddRef,
4798     ddraw_surface4_Release,
4799     /* IDirectDrawSurface */
4800     ddraw_surface4_AddAttachedSurface,
4801     ddraw_surface4_AddOverlayDirtyRect,
4802     ddraw_surface4_Blt,
4803     ddraw_surface4_BltBatch,
4804     ddraw_surface4_BltFast,
4805     ddraw_surface4_DeleteAttachedSurface,
4806     ddraw_surface4_EnumAttachedSurfaces,
4807     ddraw_surface4_EnumOverlayZOrders,
4808     ddraw_surface4_Flip,
4809     ddraw_surface4_GetAttachedSurface,
4810     ddraw_surface4_GetBltStatus,
4811     ddraw_surface4_GetCaps,
4812     ddraw_surface4_GetClipper,
4813     ddraw_surface4_GetColorKey,
4814     ddraw_surface4_GetDC,
4815     ddraw_surface4_GetFlipStatus,
4816     ddraw_surface4_GetOverlayPosition,
4817     ddraw_surface4_GetPalette,
4818     ddraw_surface4_GetPixelFormat,
4819     ddraw_surface4_GetSurfaceDesc,
4820     ddraw_surface4_Initialize,
4821     ddraw_surface4_IsLost,
4822     ddraw_surface4_Lock,
4823     ddraw_surface4_ReleaseDC,
4824     ddraw_surface4_Restore,
4825     ddraw_surface4_SetClipper,
4826     ddraw_surface4_SetColorKey,
4827     ddraw_surface4_SetOverlayPosition,
4828     ddraw_surface4_SetPalette,
4829     ddraw_surface4_Unlock,
4830     ddraw_surface4_UpdateOverlay,
4831     ddraw_surface4_UpdateOverlayDisplay,
4832     ddraw_surface4_UpdateOverlayZOrder,
4833     /* IDirectDrawSurface2 */
4834     ddraw_surface4_GetDDInterface,
4835     ddraw_surface4_PageLock,
4836     ddraw_surface4_PageUnlock,
4837     /* IDirectDrawSurface3 */
4838     ddraw_surface4_SetSurfaceDesc,
4839     /* IDirectDrawSurface4 */
4840     ddraw_surface4_SetPrivateData,
4841     ddraw_surface4_GetPrivateData,
4842     ddraw_surface4_FreePrivateData,
4843     ddraw_surface4_GetUniquenessValue,
4844     ddraw_surface4_ChangeUniquenessValue,
4845 };
4846
4847 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
4848 {
4849     /* IUnknown */
4850     ddraw_surface3_QueryInterface,
4851     ddraw_surface3_AddRef,
4852     ddraw_surface3_Release,
4853     /* IDirectDrawSurface */
4854     ddraw_surface3_AddAttachedSurface,
4855     ddraw_surface3_AddOverlayDirtyRect,
4856     ddraw_surface3_Blt,
4857     ddraw_surface3_BltBatch,
4858     ddraw_surface3_BltFast,
4859     ddraw_surface3_DeleteAttachedSurface,
4860     ddraw_surface3_EnumAttachedSurfaces,
4861     ddraw_surface3_EnumOverlayZOrders,
4862     ddraw_surface3_Flip,
4863     ddraw_surface3_GetAttachedSurface,
4864     ddraw_surface3_GetBltStatus,
4865     ddraw_surface3_GetCaps,
4866     ddraw_surface3_GetClipper,
4867     ddraw_surface3_GetColorKey,
4868     ddraw_surface3_GetDC,
4869     ddraw_surface3_GetFlipStatus,
4870     ddraw_surface3_GetOverlayPosition,
4871     ddraw_surface3_GetPalette,
4872     ddraw_surface3_GetPixelFormat,
4873     ddraw_surface3_GetSurfaceDesc,
4874     ddraw_surface3_Initialize,
4875     ddraw_surface3_IsLost,
4876     ddraw_surface3_Lock,
4877     ddraw_surface3_ReleaseDC,
4878     ddraw_surface3_Restore,
4879     ddraw_surface3_SetClipper,
4880     ddraw_surface3_SetColorKey,
4881     ddraw_surface3_SetOverlayPosition,
4882     ddraw_surface3_SetPalette,
4883     ddraw_surface3_Unlock,
4884     ddraw_surface3_UpdateOverlay,
4885     ddraw_surface3_UpdateOverlayDisplay,
4886     ddraw_surface3_UpdateOverlayZOrder,
4887     /* IDirectDrawSurface2 */
4888     ddraw_surface3_GetDDInterface,
4889     ddraw_surface3_PageLock,
4890     ddraw_surface3_PageUnlock,
4891     /* IDirectDrawSurface3 */
4892     ddraw_surface3_SetSurfaceDesc,
4893 };
4894
4895 static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
4896 {
4897     /* IUnknown */
4898     ddraw_surface2_QueryInterface,
4899     ddraw_surface2_AddRef,
4900     ddraw_surface2_Release,
4901     /* IDirectDrawSurface */
4902     ddraw_surface2_AddAttachedSurface,
4903     ddraw_surface2_AddOverlayDirtyRect,
4904     ddraw_surface2_Blt,
4905     ddraw_surface2_BltBatch,
4906     ddraw_surface2_BltFast,
4907     ddraw_surface2_DeleteAttachedSurface,
4908     ddraw_surface2_EnumAttachedSurfaces,
4909     ddraw_surface2_EnumOverlayZOrders,
4910     ddraw_surface2_Flip,
4911     ddraw_surface2_GetAttachedSurface,
4912     ddraw_surface2_GetBltStatus,
4913     ddraw_surface2_GetCaps,
4914     ddraw_surface2_GetClipper,
4915     ddraw_surface2_GetColorKey,
4916     ddraw_surface2_GetDC,
4917     ddraw_surface2_GetFlipStatus,
4918     ddraw_surface2_GetOverlayPosition,
4919     ddraw_surface2_GetPalette,
4920     ddraw_surface2_GetPixelFormat,
4921     ddraw_surface2_GetSurfaceDesc,
4922     ddraw_surface2_Initialize,
4923     ddraw_surface2_IsLost,
4924     ddraw_surface2_Lock,
4925     ddraw_surface2_ReleaseDC,
4926     ddraw_surface2_Restore,
4927     ddraw_surface2_SetClipper,
4928     ddraw_surface2_SetColorKey,
4929     ddraw_surface2_SetOverlayPosition,
4930     ddraw_surface2_SetPalette,
4931     ddraw_surface2_Unlock,
4932     ddraw_surface2_UpdateOverlay,
4933     ddraw_surface2_UpdateOverlayDisplay,
4934     ddraw_surface2_UpdateOverlayZOrder,
4935     /* IDirectDrawSurface2 */
4936     ddraw_surface2_GetDDInterface,
4937     ddraw_surface2_PageLock,
4938     ddraw_surface2_PageUnlock,
4939 };
4940
4941 static const struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
4942 {
4943     /* IUnknown */
4944     ddraw_surface1_QueryInterface,
4945     ddraw_surface1_AddRef,
4946     ddraw_surface1_Release,
4947     /* IDirectDrawSurface */
4948     ddraw_surface1_AddAttachedSurface,
4949     ddraw_surface1_AddOverlayDirtyRect,
4950     ddraw_surface1_Blt,
4951     ddraw_surface1_BltBatch,
4952     ddraw_surface1_BltFast,
4953     ddraw_surface1_DeleteAttachedSurface,
4954     ddraw_surface1_EnumAttachedSurfaces,
4955     ddraw_surface1_EnumOverlayZOrders,
4956     ddraw_surface1_Flip,
4957     ddraw_surface1_GetAttachedSurface,
4958     ddraw_surface1_GetBltStatus,
4959     ddraw_surface1_GetCaps,
4960     ddraw_surface1_GetClipper,
4961     ddraw_surface1_GetColorKey,
4962     ddraw_surface1_GetDC,
4963     ddraw_surface1_GetFlipStatus,
4964     ddraw_surface1_GetOverlayPosition,
4965     ddraw_surface1_GetPalette,
4966     ddraw_surface1_GetPixelFormat,
4967     ddraw_surface1_GetSurfaceDesc,
4968     ddraw_surface1_Initialize,
4969     ddraw_surface1_IsLost,
4970     ddraw_surface1_Lock,
4971     ddraw_surface1_ReleaseDC,
4972     ddraw_surface1_Restore,
4973     ddraw_surface1_SetClipper,
4974     ddraw_surface1_SetColorKey,
4975     ddraw_surface1_SetOverlayPosition,
4976     ddraw_surface1_SetPalette,
4977     ddraw_surface1_Unlock,
4978     ddraw_surface1_UpdateOverlay,
4979     ddraw_surface1_UpdateOverlayDisplay,
4980     ddraw_surface1_UpdateOverlayZOrder,
4981 };
4982
4983 static const struct IDirectDrawGammaControlVtbl ddraw_gamma_control_vtbl =
4984 {
4985     ddraw_gamma_control_QueryInterface,
4986     ddraw_gamma_control_AddRef,
4987     ddraw_gamma_control_Release,
4988     ddraw_gamma_control_GetGammaRamp,
4989     ddraw_gamma_control_SetGammaRamp,
4990 };
4991
4992 static const struct IDirect3DTexture2Vtbl d3d_texture2_vtbl =
4993 {
4994     d3d_texture2_QueryInterface,
4995     d3d_texture2_AddRef,
4996     d3d_texture2_Release,
4997     d3d_texture2_GetHandle,
4998     d3d_texture2_PaletteChanged,
4999     d3d_texture2_Load,
5000 };
5001
5002 static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
5003 {
5004     d3d_texture1_QueryInterface,
5005     d3d_texture1_AddRef,
5006     d3d_texture1_Release,
5007     d3d_texture1_Initialize,
5008     d3d_texture1_GetHandle,
5009     d3d_texture1_PaletteChanged,
5010     d3d_texture1_Load,
5011     d3d_texture1_Unload,
5012 };
5013
5014 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface7(IDirectDrawSurface7 *iface)
5015 {
5016     if (!iface) return NULL;
5017     assert(iface->lpVtbl == &ddraw_surface7_vtbl);
5018     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface7_iface);
5019 }
5020
5021 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface4(IDirectDrawSurface4 *iface)
5022 {
5023     if (!iface) return NULL;
5024     assert(iface->lpVtbl == &ddraw_surface4_vtbl);
5025     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface4_iface);
5026 }
5027
5028 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
5029 {
5030     if (!iface) return NULL;
5031     assert(iface->lpVtbl == &ddraw_surface3_vtbl);
5032     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface3_iface);
5033 }
5034
5035 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface2(IDirectDrawSurface2 *iface)
5036 {
5037     if (!iface) return NULL;
5038     assert(iface->lpVtbl == &ddraw_surface2_vtbl);
5039     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface2_iface);
5040 }
5041
5042 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface(IDirectDrawSurface *iface)
5043 {
5044     if (!iface) return NULL;
5045     assert(iface->lpVtbl == &ddraw_surface1_vtbl);
5046     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface_iface);
5047 }
5048
5049 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirect3DTexture2(IDirect3DTexture2 *iface)
5050 {
5051     if (!iface) return NULL;
5052     assert(iface->lpVtbl == &d3d_texture2_vtbl);
5053     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirect3DTexture2_iface);
5054 }
5055
5056 IDirectDrawSurfaceImpl *unsafe_impl_from_IDirect3DTexture(IDirect3DTexture *iface)
5057 {
5058     if (!iface) return NULL;
5059     assert(iface->lpVtbl == &d3d_texture1_vtbl);
5060     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirect3DTexture_iface);
5061 }
5062
5063 static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
5064 {
5065     IDirectDrawSurfaceImpl *surface = parent;
5066
5067     TRACE("surface %p.\n", surface);
5068
5069     /* Check for attached surfaces and detach them. */
5070     if (surface->first_attached != surface)
5071     {
5072         IDirectDrawSurface7 *root = &surface->first_attached->IDirectDrawSurface7_iface;
5073         IDirectDrawSurface7 *detach = &surface->IDirectDrawSurface7_iface;
5074
5075         /* Well, this shouldn't happen: The surface being attached is
5076          * referenced in AddAttachedSurface(), so it shouldn't be released
5077          * until DeleteAttachedSurface() is called, because the refcount is
5078          * held. It looks like the application released it often enough to
5079          * force this. */
5080         WARN("Surface is still attached to surface %p.\n", surface->first_attached);
5081
5082         /* The refcount will drop to -1 here */
5083         if (FAILED(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach)))
5084             ERR("DeleteAttachedSurface failed.\n");
5085     }
5086
5087     while (surface->next_attached)
5088     {
5089         IDirectDrawSurface7 *root = &surface->IDirectDrawSurface7_iface;
5090         IDirectDrawSurface7 *detach = &surface->next_attached->IDirectDrawSurface7_iface;
5091
5092         if (FAILED(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach)))
5093             ERR("DeleteAttachedSurface failed.\n");
5094     }
5095
5096     /* Having a texture handle set implies that the device still exists. */
5097     if (surface->Handle)
5098         ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
5099
5100     /* Reduce the ddraw surface count. */
5101     list_remove(&surface->surface_list_entry);
5102
5103     HeapFree(GetProcessHeap(), 0, surface);
5104 }
5105
5106 const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
5107 {
5108     ddraw_surface_wined3d_object_destroyed,
5109 };
5110
5111 static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
5112 {
5113     IDirectDrawSurfaceImpl *surface = parent;
5114
5115     TRACE("surface %p.\n", surface);
5116
5117     ddraw_surface_cleanup(surface);
5118 }
5119
5120 static const struct wined3d_parent_ops ddraw_texture_wined3d_parent_ops =
5121 {
5122     ddraw_texture_wined3d_object_destroyed,
5123 };
5124
5125 HRESULT ddraw_surface_create_texture(IDirectDrawSurfaceImpl *surface)
5126 {
5127     const DDSURFACEDESC2 *desc = &surface->surface_desc;
5128     enum wined3d_format_id format;
5129     WINED3DPOOL pool;
5130     UINT levels;
5131
5132     if (desc->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
5133         levels = desc->u2.dwMipMapCount;
5134     else
5135         levels = 1;
5136
5137     /* DDSCAPS_SYSTEMMEMORY textures are in WINED3DPOOL_SYSTEMMEM.
5138      * Should I forward the MANAGED cap to the managed pool? */
5139     if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
5140         pool = WINED3DPOOL_SYSTEMMEM;
5141     else
5142         pool = WINED3DPOOL_DEFAULT;
5143
5144     format = PixelFormat_DD2WineD3D(&surface->surface_desc.u4.ddpfPixelFormat);
5145     if (desc->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5146         return wined3d_texture_create_cube(surface->ddraw->wined3d_device, desc->dwWidth,
5147                 levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
5148     else
5149         return wined3d_texture_create_2d(surface->ddraw->wined3d_device, desc->dwWidth, desc->dwHeight,
5150                 levels, 0, format, pool, surface, &ddraw_texture_wined3d_parent_ops, &surface->wined3d_texture);
5151 }
5152
5153 HRESULT ddraw_surface_init(IDirectDrawSurfaceImpl *surface, IDirectDrawImpl *ddraw,
5154         DDSURFACEDESC2 *desc, UINT mip_level, UINT version)
5155 {
5156     WINED3DPOOL pool = WINED3DPOOL_DEFAULT;
5157     enum wined3d_format_id format;
5158     DWORD usage = 0;
5159     HRESULT hr;
5160
5161     if (!(desc->ddsCaps.dwCaps & (DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY))
5162             && !((desc->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
5163             && (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)))
5164     {
5165         /* Tests show surfaces without memory flags get these flags added
5166          * right after creation. */
5167         desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY;
5168     }
5169
5170     if (desc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
5171     {
5172         usage |= WINED3DUSAGE_RENDERTARGET;
5173         desc->ddsCaps.dwCaps |= DDSCAPS_VISIBLE;
5174     }
5175
5176     if ((desc->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) && !(desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
5177     {
5178         usage |= WINED3DUSAGE_RENDERTARGET;
5179     }
5180
5181     if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
5182     {
5183         usage |= WINED3DUSAGE_OVERLAY;
5184     }
5185
5186     if (desc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
5187         usage |= WINED3DUSAGE_DEPTHSTENCIL;
5188
5189     if (desc->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
5190     {
5191         pool = WINED3DPOOL_SYSTEMMEM;
5192     }
5193     else if (desc->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
5194     {
5195         pool = WINED3DPOOL_MANAGED;
5196         /* Managed textures have the system memory flag set. */
5197         desc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
5198     }
5199     else if (desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
5200     {
5201         /* Videomemory adds localvidmem. This is mutually exclusive with
5202          * systemmemory and texturemanage. */
5203         desc->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
5204     }
5205
5206     format = PixelFormat_DD2WineD3D(&desc->u4.ddpfPixelFormat);
5207     if (format == WINED3DFMT_UNKNOWN)
5208     {
5209         WARN("Unsupported / unknown pixelformat.\n");
5210         return DDERR_INVALIDPIXELFORMAT;
5211     }
5212
5213     surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl;
5214     surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl;
5215     surface->IDirectDrawSurface3_iface.lpVtbl = &ddraw_surface3_vtbl;
5216     surface->IDirectDrawSurface2_iface.lpVtbl = &ddraw_surface2_vtbl;
5217     surface->IDirectDrawSurface_iface.lpVtbl = &ddraw_surface1_vtbl;
5218     surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl;
5219     surface->IDirect3DTexture2_iface.lpVtbl = &d3d_texture2_vtbl;
5220     surface->IDirect3DTexture_iface.lpVtbl = &d3d_texture1_vtbl;
5221     surface->iface_count = 1;
5222     surface->version = version;
5223     surface->ddraw = ddraw;
5224
5225     if (version == 7)
5226     {
5227         surface->ref7 = 1;
5228     }
5229     else if (version == 4)
5230     {
5231         surface->ref4 = 1;
5232     }
5233     else
5234     {
5235         surface->ref1 = 1;
5236     }
5237
5238     copy_to_surfacedesc2(&surface->surface_desc, desc);
5239
5240     surface->first_attached = surface;
5241
5242     hr = wined3d_surface_create(ddraw->wined3d_device, desc->dwWidth, desc->dwHeight, format,
5243             TRUE /* Lockable */, FALSE /* Discard */, mip_level, usage, pool,
5244             WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, DefaultSurfaceType, surface,
5245             &ddraw_surface_wined3d_parent_ops, &surface->wined3d_surface);
5246     if (FAILED(hr))
5247     {
5248         WARN("Failed to create wined3d surface, hr %#x.\n", hr);
5249         return hr;
5250     }
5251
5252     /* Anno 1602 stores the pitch right after surface creation, so make sure
5253      * it's there. TODO: Test other fourcc formats. */
5254     if (format == WINED3DFMT_DXT1 || format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3
5255             || format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5)
5256     {
5257         surface->surface_desc.dwFlags |= DDSD_LINEARSIZE;
5258         if (format == WINED3DFMT_DXT1)
5259         {
5260             surface->surface_desc.u1.dwLinearSize = max(4, desc->dwWidth) * max(4, desc->dwHeight) / 2;
5261         }
5262         else
5263         {
5264             surface->surface_desc.u1.dwLinearSize = max(4, desc->dwWidth) * max(4, desc->dwHeight);
5265         }
5266     }
5267     else
5268     {
5269         surface->surface_desc.dwFlags |= DDSD_PITCH;
5270         surface->surface_desc.u1.lPitch = wined3d_surface_get_pitch(surface->wined3d_surface);
5271     }
5272
5273     if (desc->dwFlags & DDSD_CKDESTOVERLAY)
5274     {
5275         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_DESTOVERLAY,
5276                 (WINEDDCOLORKEY *)&desc->u3.ddckCKDestOverlay);
5277     }
5278     if (desc->dwFlags & DDSD_CKDESTBLT)
5279     {
5280         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_DESTBLT,
5281                 (WINEDDCOLORKEY *)&desc->ddckCKDestBlt);
5282     }
5283     if (desc->dwFlags & DDSD_CKSRCOVERLAY)
5284     {
5285         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_SRCOVERLAY,
5286                 (WINEDDCOLORKEY *)&desc->ddckCKSrcOverlay);
5287     }
5288     if (desc->dwFlags & DDSD_CKSRCBLT)
5289     {
5290         wined3d_surface_set_color_key(surface->wined3d_surface, DDCKEY_SRCBLT,
5291                 (WINEDDCOLORKEY *)&desc->ddckCKSrcBlt);
5292     }
5293     if (desc->dwFlags & DDSD_LPSURFACE)
5294     {
5295         hr = wined3d_surface_set_mem(surface->wined3d_surface, desc->lpSurface);
5296         if (FAILED(hr))
5297         {
5298             ERR("Failed to set surface memory, hr %#x.\n", hr);
5299             wined3d_surface_decref(surface->wined3d_surface);
5300             return hr;
5301         }
5302     }
5303
5304     return DD_OK;
5305 }