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