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