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