ddraw: Some d3d-only code fixes.
[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 <assert.h>
30 #include <stdarg.h>
31 #include <string.h>
32 #include <stdlib.h>
33
34 #define COBJMACROS
35 #define NONAMELESSUNION
36
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winerror.h"
40 #include "wingdi.h"
41 #include "wine/exception.h"
42
43 #include "ddraw.h"
44 #include "d3d.h"
45
46 #include "ddraw_private.h"
47 #include "wine/debug.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
50
51 /*****************************************************************************
52  * IUnknown parts follow
53  *****************************************************************************/
54
55 /*****************************************************************************
56  * IDirectDrawSurface7::QueryInterface
57  *
58  * A normal QueryInterface implementation. For QueryInterface rules
59  * see ddraw.c, IDirectDraw7::QueryInterface. This method
60  * can Query IDirectDrawSurface interfaces in all version, IDirect3DTexture
61  * in all versions, the IDirectDrawGammaControl interface and it can
62  * create an IDirect3DDevice. (Uses IDirect3D7::CreateDevice)
63  *
64  * Params:
65  *  riid: The interface id queried for
66  *  obj: Address to write the pointer to
67  *
68  * Returns:
69  *  S_OK on success
70  *  E_NOINTERFACE if the requested interface wasn't found
71  *
72  *****************************************************************************/
73 static HRESULT WINAPI
74 IDirectDrawSurfaceImpl_QueryInterface(IDirectDrawSurface7 *iface,
75                                       REFIID riid,
76                                       void **obj)
77 {
78     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
79
80     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
81     *obj = NULL;
82
83     if(!riid)
84         return DDERR_INVALIDPARAMS;
85
86     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),obj);
87     if (IsEqualGUID(riid, &IID_IUnknown)
88      || IsEqualGUID(riid, &IID_IDirectDrawSurface7)
89      || IsEqualGUID(riid, &IID_IDirectDrawSurface4) )
90     {
91         IUnknown_AddRef(iface);
92         *obj = ICOM_INTERFACE(This, IDirectDrawSurface7);
93         TRACE("(%p) returning IDirectDrawSurface7 interface at %p\n", This, *obj);
94         return S_OK;
95     }
96     else if( IsEqualGUID(riid, &IID_IDirectDrawSurface3)
97           || IsEqualGUID(riid, &IID_IDirectDrawSurface2)
98           || IsEqualGUID(riid, &IID_IDirectDrawSurface) )
99     {
100         IUnknown_AddRef(iface);
101         *obj = ICOM_INTERFACE(This, IDirectDrawSurface3);
102         TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
103         return S_OK;
104     }
105     else if( IsEqualGUID(riid, &IID_IDirectDrawGammaControl) )
106     {
107         IUnknown_AddRef(iface);
108         *obj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
109         TRACE("(%p) returning IDirectDrawGammaControl interface at %p\n", This, *obj);
110         return S_OK;
111     }
112     else if( IsEqualGUID(riid, &IID_D3DDEVICE_WineD3D) ||
113              IsEqualGUID(riid, &IID_IDirect3DHALDevice)||
114              IsEqualGUID(riid, &IID_IDirect3DRGBDevice) )
115     {
116         IDirect3DDevice7 *d3d;
117
118         /* Call into IDirect3D7 for creation */
119         IDirect3D7_CreateDevice(ICOM_INTERFACE(This->ddraw, IDirect3D7),
120                                 riid,
121                                 ICOM_INTERFACE(This, IDirectDrawSurface7),
122                                 &d3d);
123
124         *obj = COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice7, IDirect3DDevice, d3d);
125         TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
126
127         return S_OK;
128     }
129     else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
130              IsEqualGUID( &IID_IDirect3DTexture2, riid ))
131     {
132         if (IsEqualGUID( &IID_IDirect3DTexture, riid ))
133         {
134             *obj = ICOM_INTERFACE(This, IDirect3DTexture);
135             TRACE(" returning Direct3DTexture interface at %p.\n", *obj);
136         }
137         else
138         {
139             *obj = ICOM_INTERFACE(This, IDirect3DTexture2);
140             TRACE(" returning Direct3DTexture2 interface at %p.\n", *obj);
141         }
142         IUnknown_AddRef( (IUnknown *) *obj);
143         return S_OK;
144     }
145
146     ERR("No interface\n");
147     return E_NOINTERFACE;
148 }
149
150 /*****************************************************************************
151  * IDirectDrawSurface7::AddRef
152  *
153  * A normal addref implementation
154  *
155  * Returns:
156  *  The new refcount
157  *
158  *****************************************************************************/
159 static ULONG WINAPI
160 IDirectDrawSurfaceImpl_AddRef(IDirectDrawSurface7 *iface)
161 {
162     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
163     ULONG refCount = InterlockedIncrement(&This->ref);
164
165     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
166     return refCount;
167 }
168
169 /*****************************************************************************
170  * IDirectDrawSurfaceImpl_Destroy
171  *
172  * A helper function for IDirectDrawSurface7::Release
173  *
174  * Frees the surface, regardless of its refcount.
175  *  See IDirectDrawSurface7::Release for more information
176  *
177  * Params:
178  *  This: Surface to free
179  *
180  *****************************************************************************/
181 static void IDirectDrawSurfaceImpl_Destroy(IDirectDrawSurfaceImpl *This)
182 {
183     TRACE("(%p)\n", This);
184
185     /* Check the refcount and give a warning */
186     if(This->ref > 1)
187     {
188         /* This can happen when a complex surface is destroyed,
189          * because the 2nd surface was addref()ed when the app
190          * called GetAttachedSurface
191          */
192         WARN("(%p): Destroying surface with refount %d\n", This, This->ref);
193     }
194
195     /* Check for attached surfaces and detach them */
196     if(This->first_attached != This)
197     {
198         /* Well, this shouldn't happen: The surface being attached is addref()ed
199           * in AddAttachedSurface, so it shouldn't be released until DeleteAttachedSurface
200           * is called, because the refcount is held. It looks like the app released()
201           * it often enough to force this
202           */
203         IDirectDrawSurface7 *root = ICOM_INTERFACE(This->first_attached, IDirectDrawSurface7);
204         IDirectDrawSurface7 *detach = ICOM_INTERFACE(This, IDirectDrawSurface7);
205
206         FIXME("(%p) Freeing a surface that is attached to surface %p\n", This, This->first_attached);
207
208         /* The refcount will drop to -1 here */
209         if(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach) != DD_OK)
210         {
211             ERR("(%p) DeleteAttachedSurface failed!\n", This);
212         }
213     }
214
215     while(This->next_attached != NULL)
216     {
217         IDirectDrawSurface7 *root = ICOM_INTERFACE(This, IDirectDrawSurface7);
218         IDirectDrawSurface7 *detach = ICOM_INTERFACE(This->next_attached, IDirectDrawSurface7);
219
220         if(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach) != DD_OK)
221         {
222             ERR("(%p) DeleteAttachedSurface failed!\n", This);
223             assert(0);
224         }
225     }
226
227     /* Now destroy the surface. Wait: It could have been released if we are a texture */
228     if(This->WineD3DSurface)
229         IWineD3DSurface_Release(This->WineD3DSurface);
230
231     /* Having a texture handle set implies that the device still exists */
232     if(This->Handle)
233     {
234         This->ddraw->d3ddevice->Handles[This->Handle - 1].ptr = NULL;
235         This->ddraw->d3ddevice->Handles[This->Handle - 1].type = DDrawHandle_Unknown;
236     }
237
238     /* Reduce the ddraw surface count */
239     InterlockedDecrement(&This->ddraw->surfaces);
240     list_remove(&This->surface_list_entry);
241
242     HeapFree(GetProcessHeap(), 0, This);
243 }
244
245 /*****************************************************************************
246  * IDirectDrawSurface7::Release
247  *
248  * Reduces the surface's refcount by 1. If the refcount falls to 0, the
249  * surface is destroyed.
250  *
251  * Destroying the surface is a bit tricky. For the connection between
252  * WineD3DSurfaces and DirectDrawSurfaces see IDirectDraw7::CreateSurface
253  * It has a nice graph explaining the connection.
254  *
255  * What happens here is basically this:
256  * When a surface is destroyed, its WineD3DSurface is released,
257  * and the refcount of the DirectDraw interface is reduced by 1. If it has
258  * complex surfaces attached to it, then these surfaces are destroyed too,
259  * regardless of their refcount. If any surface being destroyed has another
260  * surface attached to it (with a "soft" attachment, not complex), then
261  * this surface is detached with DeleteAttachedSurface.
262  *
263  * When the surface is a texture, the WineD3DTexture is released.
264  * If the surface is the Direct3D render target, then the D3D
265  * capabilities of the WineD3DDevice are uninitialized, which causes the
266  * swapchain to be released.
267  *
268  * When a complex sublevel falls to ref zero, then this is ignored.
269  *
270  * Returns:
271  *  The new refcount
272  *
273  *****************************************************************************/
274 static ULONG WINAPI
275 IDirectDrawSurfaceImpl_Release(IDirectDrawSurface7 *iface)
276 {
277     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
278     ULONG ref;
279     TRACE("(%p) : Releasing from %d\n", This, This->ref);
280     ref = InterlockedDecrement(&This->ref);
281
282     if (ref == 0)
283     {
284
285         IDirectDrawSurfaceImpl *surf;
286         IDirectDrawImpl *ddraw;
287         IUnknown *ifaceToRelease = This->ifaceToRelease;
288         int i;
289
290         /* Complex attached surfaces are destroyed implicitely when the root is released */
291         EnterCriticalSection(&ddraw_cs);
292         if(!This->is_complex_root)
293         {
294             WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
295             LeaveCriticalSection(&ddraw_cs);
296             return ref;
297         }
298         ddraw = This->ddraw;
299
300         /* If it's a texture, destroy the WineD3DTexture.
301          * WineD3D will destroy the IParent interfaces
302          * of the sublevels, which destroys the WineD3DSurfaces.
303          * Set the surfaces to NULL to avoid destroying them again later
304          */
305         if(This->wineD3DTexture)
306         {
307             IWineD3DBaseTexture_Release(This->wineD3DTexture);
308         }
309         /* If it's the RenderTarget, destroy the d3ddevice */
310         else if( (ddraw->d3d_initialized) && (This == ddraw->d3d_target))
311         {
312             TRACE("(%p) Destroying the render target, uninitializing D3D\n", This);
313
314             /* Unset any index buffer, just to be sure */
315             IWineD3DDevice_SetIndices(ddraw->wineD3DDevice, NULL);
316             IWineD3DDevice_SetDepthStencilSurface(ddraw->wineD3DDevice, NULL);
317             IWineD3DDevice_SetVertexDeclaration(ddraw->wineD3DDevice, NULL);
318             for(i = 0; i < ddraw->numConvertedDecls; i++)
319             {
320                 IWineD3DVertexDeclaration_Release(ddraw->decls[i].decl);
321             }
322             HeapFree(GetProcessHeap(), 0, ddraw->decls);
323             ddraw->numConvertedDecls = 0;
324
325             if(IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroyDepthStencilSurface, D3D7CB_DestroySwapChain) != D3D_OK)
326             {
327                 /* Not good */
328                 ERR("(%p) Failed to uninit 3D\n", This);
329             }
330             else
331             {
332                 /* Free the d3d window if one was created */
333                 if(ddraw->d3d_window != 0)
334                 {
335                     TRACE(" (%p) Destroying the hidden render window %p\n", This, ddraw->d3d_window);
336                     DestroyWindow(ddraw->d3d_window);
337                     ddraw->d3d_window = 0;
338                 }
339                 /* Unset the pointers */
340             }
341
342             ddraw->d3d_initialized = FALSE;
343             ddraw->d3d_target = NULL;
344
345             /* Reset to the default surface implementation type. This is needed if apps use
346              * non render target surfaces and expect blits to work after destroying the render
347              * target.
348              *
349              * TODO: Recreate existing offscreen surfaces
350              */
351             ddraw->ImplType = DefaultSurfaceType;
352
353             /* Write a trace because D3D unloading was the reason for many
354              * crashes during development.
355              */
356             TRACE("(%p) D3D unloaded\n", This);
357         }
358         else if(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE |
359                                                      DDSCAPS_3DDEVICE       |
360                                                      DDSCAPS_TEXTURE        ) )
361         {
362             /* It's a render target, but no swapchain was created.
363              * The IParent interfaces have to be released manually.
364              * The same applies for textures without an
365              * IWineD3DTexture object attached
366              */
367             IParent *Parent;
368
369             for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
370             {
371                 if(This->complex_array[i])
372                 {
373                     /* Only the topmost level can have more than 1 surfaces in the complex
374                      * attachment array(Cube texture roots), for all others there is only
375                      * one
376                      */
377                     surf = This->complex_array[i];
378                     while(surf)
379                     {
380                         IWineD3DSurface_GetParent(surf->WineD3DSurface,
381                                                   (IUnknown **) &Parent);
382                         IParent_Release(Parent);  /* For the getParent */
383                         IParent_Release(Parent);  /* To release it */
384                         surf = surf->complex_array[0];
385                     }
386                 }
387             }
388
389             /* Now the top-level surface */
390             IWineD3DSurface_GetParent(This->WineD3DSurface,
391                                       (IUnknown **) &Parent);
392             IParent_Release(Parent);  /* For the getParent */
393             IParent_Release(Parent);  /* To release it */
394         }
395
396         /* The refcount test shows that the palette is detached when the surface is destroyed */
397         IDirectDrawSurface7_SetPalette(ICOM_INTERFACE(This, IDirectDrawSurface7),
398                                                       NULL);
399
400         /* Loop through all complex attached surfaces,
401          * and destroy them.
402          *
403          * Yet again, only the root can have more than one complexly attached surface, all the others
404          * have a total of one;
405          */
406         for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
407         {
408             if(!This->complex_array[i]) break;
409
410             surf = This->complex_array[i];
411             This->complex_array[i] = NULL;
412             while(surf)
413             {
414                 IDirectDrawSurfaceImpl *destroy = surf;
415                 surf = surf->complex_array[0];              /* Iterate through the "tree" */
416                 IDirectDrawSurfaceImpl_Destroy(destroy);    /* Destroy it */
417             }
418         }
419
420         /* Destroy the root surface.
421          */
422         IDirectDrawSurfaceImpl_Destroy(This);
423
424         /* Reduce the ddraw refcount */
425         if(ifaceToRelease) IUnknown_Release(ifaceToRelease);
426         LeaveCriticalSection(&ddraw_cs);
427     }
428
429     return ref;
430 }
431
432 /*****************************************************************************
433  * IDirectDrawSurface7::GetAttachedSurface
434  *
435  * Returns an attached surface with the requested caps. Surface attachment
436  * and complex surfaces are not clearly described by the MSDN or sdk,
437  * so this method is tricky and likely to contain problems.
438  * This implementation searches the complex list first, then the
439  * attachment chain.
440  *
441  * The chains are searched from This down to the last surface in the chain,
442  * not from the first element in the chain. The first surface found is
443  * returned. The MSDN says that this method fails if more than one surface
444  * matches the caps, but it is not sure if that is right. The attachment
445  * structure may not even allow two matching surfaces.
446  *
447  * The found surface is AddRef-ed before it is returned.
448  *
449  * Params:
450  *  Caps: Pointer to a DDCAPS2 structure describing the caps asked for
451  *  Surface: Address to store the found surface
452  *
453  * Returns:
454  *  DD_OK on success
455  *  DDERR_INVALIDPARAMS if Caps or Surface is NULL
456  *  DDERR_NOTFOUND if no surface was found
457  *
458  *****************************************************************************/
459 static HRESULT WINAPI
460 IDirectDrawSurfaceImpl_GetAttachedSurface(IDirectDrawSurface7 *iface,
461                                           DDSCAPS2 *Caps,
462                                           IDirectDrawSurface7 **Surface)
463 {
464     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
465     IDirectDrawSurfaceImpl *surf;
466     DDSCAPS2 our_caps;
467     int i;
468
469     TRACE("(%p)->(%p,%p)\n", This, Caps, Surface);
470     EnterCriticalSection(&ddraw_cs);
471
472     our_caps = *Caps;
473
474     if(This->version < 7)
475     {
476         /* Earlier dx apps put garbage into these members, clear them */
477         our_caps.dwCaps2 = 0;
478         our_caps.dwCaps3 = 0;
479         our_caps.dwCaps4 = 0;
480     }
481
482     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 */
483
484     for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
485     {
486         surf = This->complex_array[i];
487         if(!surf) break;
488
489         if (TRACE_ON(ddraw))
490         {
491             TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
492                    surf->surface_desc.ddsCaps.dwCaps,
493                    surf->surface_desc.ddsCaps.dwCaps2,
494                    surf->surface_desc.ddsCaps.dwCaps3,
495                    surf->surface_desc.ddsCaps.dwCaps4);
496         }
497
498         if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
499             ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
500
501             /* MSDN: "This method fails if more than one surface is attached
502              * that matches the capabilities requested."
503              *
504              * Not sure how to test this.
505              */
506
507             TRACE("(%p): Returning surface %p\n", This, surf);
508             TRACE("(%p): mipmapcount=%d\n", This, surf->mipmap_level);
509             *Surface = ICOM_INTERFACE(surf, IDirectDrawSurface7);
510             IDirectDrawSurface7_AddRef(*Surface);
511             LeaveCriticalSection(&ddraw_cs);
512             return DD_OK;
513         }
514     }
515
516     /* Next, look at the attachment chain */
517     surf = This;
518
519     while( (surf = surf->next_attached) )
520     {
521         if (TRACE_ON(ddraw))
522         {
523             TRACE("Surface: (%p) caps: %x,%x,%x,%x\n", surf,
524                    surf->surface_desc.ddsCaps.dwCaps,
525                    surf->surface_desc.ddsCaps.dwCaps2,
526                    surf->surface_desc.ddsCaps.dwCaps3,
527                    surf->surface_desc.ddsCaps.dwCaps4);
528         }
529
530         if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
531             ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2)) {
532
533             TRACE("(%p): Returning surface %p\n", This, surf);
534             *Surface = ICOM_INTERFACE(surf, IDirectDrawSurface7);
535             IDirectDrawSurface7_AddRef(*Surface);
536             LeaveCriticalSection(&ddraw_cs);
537             return DD_OK;
538         }
539     }
540
541     TRACE("(%p) Didn't find a valid surface\n", This);
542     LeaveCriticalSection(&ddraw_cs);
543     return DDERR_NOTFOUND;
544 }
545
546 /*****************************************************************************
547  * IDirectDrawSurface7::Lock
548  *
549  * Locks the surface and returns a pointer to the surface's memory
550  *
551  * Params:
552  *  Rect: Rectangle to lock. If NULL, the whole surface is locked
553  *  DDSD: Pointer to a DDSURFACEDESC2 which shall receive the surface's desc.
554  *  Flags: Locking flags, e.g Read only or write only
555  *  h: An event handle that's not used and must be NULL
556  *
557  * Returns:
558  *  DD_OK on success
559  *  DDERR_INVALIDPARAMS if DDSD is NULL
560  *  For more details, see IWineD3DSurface::LockRect
561  *
562  *****************************************************************************/
563 static HRESULT WINAPI
564 IDirectDrawSurfaceImpl_Lock(IDirectDrawSurface7 *iface,
565                             RECT *Rect,
566                             DDSURFACEDESC2 *DDSD,
567                             DWORD Flags,
568                             HANDLE h)
569 {
570     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
571     WINED3DLOCKED_RECT LockedRect;
572     HRESULT hr;
573     TRACE("(%p)->(%p,%p,%x,%p)\n", This, Rect, DDSD, Flags, h);
574
575     if(!DDSD)
576         return DDERR_INVALIDPARAMS;
577
578     /* This->surface_desc.dwWidth and dwHeight are changeable, thus lock */
579     EnterCriticalSection(&ddraw_cs);
580     if (Rect)
581     {
582         if ((Rect->left < 0)
583                 || (Rect->top < 0)
584                 || (Rect->left > Rect->right)
585                 || (Rect->top > Rect->bottom)
586                 || (Rect->right > This->surface_desc.dwWidth)
587                 || (Rect->bottom > This->surface_desc.dwHeight))
588         {
589             WARN("Trying to lock an invalid rectangle, returning DDERR_INVALIDPARAMS\n");
590             LeaveCriticalSection(&ddraw_cs);
591             return DDERR_INVALIDPARAMS;
592         }
593     }
594
595     /* Should I check for the handle to be NULL?
596      *
597      * The DDLOCK flags and the D3DLOCK flags are equal
598      * for the supported values. The others are ignored by WineD3D
599      */
600
601     if(DDSD->dwSize != sizeof(DDSURFACEDESC) &&
602        DDSD->dwSize != sizeof(DDSURFACEDESC2))
603     {
604         WARN("Invalid structure size %d, returning DDERR_INVALIDPARAMS\n", DDERR_INVALIDPARAMS);
605         LeaveCriticalSection(&ddraw_cs);
606         return DDERR_INVALIDPARAMS;
607     }
608
609     hr = IWineD3DSurface_LockRect(This->WineD3DSurface,
610                                   &LockedRect,
611                                   Rect,
612                                   Flags);
613     if(hr != D3D_OK)
614     {
615         LeaveCriticalSection(&ddraw_cs);
616         return hr;
617     }
618
619     /* Override the memory area. The pitch should be set already. Strangely windows
620      * does not set the LPSURFACE flag on locked surfaces !?!.
621      * DDSD->dwFlags |= DDSD_LPSURFACE;
622      */
623     This->surface_desc.lpSurface = LockedRect.pBits;
624     DD_STRUCT_COPY_BYSIZE(DDSD,&(This->surface_desc));
625
626     TRACE("locked surface returning description :\n");
627     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
628
629     LeaveCriticalSection(&ddraw_cs);
630     return DD_OK;
631 }
632
633 /*****************************************************************************
634  * IDirectDrawSurface7::Unlock
635  *
636  * Unlocks an locked surface
637  *
638  * Params:
639  *  Rect: Not used by this implementation
640  *
641  * Returns:
642  *  D3D_OK on success
643  *  For more details, see IWineD3DSurface::UnlockRect
644  *
645  *****************************************************************************/
646 static HRESULT WINAPI
647 IDirectDrawSurfaceImpl_Unlock(IDirectDrawSurface7 *iface,
648                               RECT *pRect)
649 {
650     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
651     HRESULT hr;
652     TRACE("(%p)->(%p)\n", This, pRect);
653
654     EnterCriticalSection(&ddraw_cs);
655     hr = IWineD3DSurface_UnlockRect(This->WineD3DSurface);
656     if(SUCCEEDED(hr))
657     {
658         This->surface_desc.lpSurface = NULL;
659     }
660     LeaveCriticalSection(&ddraw_cs);
661     return hr;
662 }
663
664 /*****************************************************************************
665  * IDirectDrawSurface7::Flip
666  *
667  * Flips a surface with the DDSCAPS_FLIP flag. The flip is relayed to
668  * IWineD3DSurface::Flip. Because WineD3D doesn't handle attached surfaces,
669  * the flip target is passed to WineD3D, even if the app didn't specify one
670  *
671  * Params:
672  *  DestOverride: Specifies the surface that will become the new front
673  *                buffer. If NULL, the current back buffer is used
674  *  Flags: some DirectDraw flags, see include/ddraw.h
675  *
676  * Returns:
677  *  DD_OK on success
678  *  DDERR_NOTFLIPPABLE if no flip target could be found
679  *  DDERR_INVALIDOBJECT if the surface isn't a front buffer
680  *  For more details, see IWineD3DSurface::Flip
681  *
682  *****************************************************************************/
683 static HRESULT WINAPI
684 IDirectDrawSurfaceImpl_Flip(IDirectDrawSurface7 *iface,
685                             IDirectDrawSurface7 *DestOverride,
686                             DWORD Flags)
687 {
688     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
689     IDirectDrawSurfaceImpl *Override = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, DestOverride);
690     IDirectDrawSurface7 *Override7;
691     HRESULT hr;
692     TRACE("(%p)->(%p,%x)\n", This, DestOverride, Flags);
693
694     /* Flip has to be called from a front buffer
695      * What about overlay surfaces, AFAIK they can flip too?
696      */
697     if( !(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER) )
698         return DDERR_INVALIDOBJECT; /* Unckecked */
699
700     EnterCriticalSection(&ddraw_cs);
701
702     /* WineD3D doesn't keep track of attached surface, so find the target */
703     if(!Override)
704     {
705         DDSCAPS2 Caps;
706
707         memset(&Caps, 0, sizeof(Caps));
708         Caps.dwCaps |= DDSCAPS_BACKBUFFER;
709         hr = IDirectDrawSurface7_GetAttachedSurface(iface, &Caps, &Override7);
710         if(hr != DD_OK)
711         {
712             ERR("Can't find a flip target\n");
713             LeaveCriticalSection(&ddraw_cs);
714             return DDERR_NOTFLIPPABLE; /* Unchecked */
715         }
716         Override = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Override7);
717
718         /* For the GetAttachedSurface */
719         IDirectDrawSurface7_Release(Override7);
720     }
721
722     hr = IWineD3DSurface_Flip(This->WineD3DSurface,
723                               Override->WineD3DSurface,
724                               Flags);
725     LeaveCriticalSection(&ddraw_cs);
726     return hr;
727 }
728
729 /*****************************************************************************
730  * IDirectDrawSurface7::Blt
731  *
732  * Performs a blit on the surface
733  *
734  * Params:
735  *  DestRect: Destination rectangle, can be NULL
736  *  SrcSurface: Source surface, can be NULL
737  *  SrcRect: Source rectange, can be NULL
738  *  Flags: Blt flags
739  *  DDBltFx: Some extended blt parameters, connected to the flags
740  *
741  * Returns:
742  *  D3D_OK on success
743  *  See IWineD3DSurface::Blt for more details
744  *
745  *****************************************************************************/
746 static HRESULT WINAPI
747 IDirectDrawSurfaceImpl_Blt(IDirectDrawSurface7 *iface,
748                            RECT *DestRect,
749                            IDirectDrawSurface7 *SrcSurface,
750                            RECT *SrcRect,
751                            DWORD Flags,
752                            DDBLTFX *DDBltFx)
753 {
754     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
755     HRESULT hr;
756     IDirectDrawSurfaceImpl *Src = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, SrcSurface);
757     TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
758
759     /* Check for validity of the flags here. WineD3D Has the software-opengl selection path and would have
760      * to check at 2 places, and sometimes do double checks. This also saves the call to wined3d :-)
761      */
762     if((Flags & DDBLT_KEYSRCOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYSRC)) {
763         WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
764         return DDERR_INVALIDPARAMS;
765     }
766
767     if((Flags & DDBLT_KEYDESTOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYDEST)) {
768         WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
769         return DDERR_INVALIDPARAMS;
770     }
771
772     /* Sizes can change, therefore hold the lock when testing the rectangles */
773     EnterCriticalSection(&ddraw_cs);
774     if(DestRect)
775     {
776         if(DestRect->top >= DestRect->bottom || DestRect->left >= DestRect->right ||
777            DestRect->right > This->surface_desc.dwWidth ||
778            DestRect->bottom > This->surface_desc.dwHeight)
779         {
780             WARN("Source rectangle is invalid, returning DDERR_INVALIDRECT\n");
781             LeaveCriticalSection(&ddraw_cs);
782             return DDERR_INVALIDRECT;
783         }
784     }
785     if(Src && SrcRect)
786     {
787         if(SrcRect->top >= SrcRect->bottom || SrcRect->left >=SrcRect->right ||
788            SrcRect->right > Src->surface_desc.dwWidth ||
789            SrcRect->bottom > Src->surface_desc.dwHeight)
790         {
791             WARN("Source rectangle is invalid, returning DDERR_INVALIDRECT\n");
792             LeaveCriticalSection(&ddraw_cs);
793             return DDERR_INVALIDRECT;
794         }
795     }
796
797     if(Flags & DDBLT_KEYSRC && (!Src || !(Src->surface_desc.dwFlags & DDSD_CKSRCBLT))) {
798         WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
799         LeaveCriticalSection(&ddraw_cs);
800         return DDERR_INVALIDPARAMS;
801     }
802
803     /* TODO: Check if the DDBltFx contains any ddraw surface pointers. If it does, copy the struct,
804      * and replace the ddraw surfaces with the wined3d surfaces
805      * So far no blitting operations using surfaces in the bltfx struct are supported anyway.
806      */
807     hr = IWineD3DSurface_Blt(This->WineD3DSurface,
808                              DestRect,
809                              Src ? Src->WineD3DSurface : NULL,
810                              SrcRect,
811                              Flags,
812                              (WINEDDBLTFX *) DDBltFx,
813                              WINED3DTEXF_POINT);
814
815     LeaveCriticalSection(&ddraw_cs);
816     switch(hr)
817     {
818         case WINED3DERR_NOTAVAILABLE:       return DDERR_UNSUPPORTED;
819         case WINED3DERR_WRONGTEXTUREFORMAT: return DDERR_INVALIDPIXELFORMAT;
820         default:                            return hr;
821     }
822 }
823
824 /*****************************************************************************
825  * IDirectDrawSurface7::AddAttachedSurface
826  *
827  * Attaches a surface to another surface. How the surface attachments work
828  * is not totally understood yet, and this method is prone to problems.
829  * he surface that is attached is AddRef-ed.
830  *
831  * Tests with complex surfaces suggest that the surface attachments form a
832  * tree, but no method to test this has been found yet.
833  *
834  * The attachment list consists of a first surface (first_attached) and
835  * for each surface a pointer to the next attached surface (next_attached).
836  * For the first surface, and a surface that has no attachments
837  * first_attached points to the surface itself. A surface that has
838  * no successors in the chain has next_attached set to NULL.
839  *
840  * Newly attached surfaces are attached right after the root surface.
841  * If a surface is attached to a complex surface compound, it's attached to
842  * the surface that the app requested, not the complex root. See
843  * GetAttachedSurface for a description how surfaces are found.
844  *
845  * This is how the current implementation works, and it was coded by looking
846  * at the needs of the applications.
847  *
848  * So far only Z-Buffer attachments are tested, and they are activated in
849  * WineD3D. Mipmaps could be tricky to activate in WineD3D.
850  * Back buffers should work in 2D mode, but they are not tested(They can be
851  * attached in older iface versions). Rendering to the front buffer and
852  * switching between that and double buffering is not yet implemented in
853  * WineD3D, so for 3D it might have unexpected results.
854  *
855  * IDirectDrawSurfaceImpl_AddAttachedSurface is the real thing,
856  * IDirectDrawSurface7Impl_AddAttachedSurface is a wrapper around it that
857  * performs additional checks. Version 7 of this interface is much more restrictive
858  * than its predecessors.
859  *
860  * Params:
861  *  Attach: Surface to attach to iface
862  *
863  * Returns:
864  *  DD_OK on success
865  *  DDERR_CANNOTATTACHSURFACE if the surface can't be attached for some reason
866  *
867  *****************************************************************************/
868 HRESULT WINAPI
869 IDirectDrawSurfaceImpl_AddAttachedSurface(IDirectDrawSurfaceImpl *This,
870                                           IDirectDrawSurfaceImpl *Surf)
871 {
872     TRACE("(%p)->(%p)\n", This, Surf);
873
874     if(Surf == This)
875         return DDERR_CANNOTATTACHSURFACE; /* unchecked */
876
877     EnterCriticalSection(&ddraw_cs);
878
879     /* Check if the surface is already attached somewhere */
880     if( (Surf->next_attached != NULL) ||
881         (Surf->first_attached != Surf) )
882     {
883         /* TODO: Test for the structure of the manual attachment. Is it a chain or a list?
884          * What happens if one surface is attached to 2 different surfaces?
885          */
886         FIXME("(%p) The Surface %p is already attached somewhere else: next_attached = %p, first_attached = %p, can't handle by now\n", This, Surf, Surf->next_attached, Surf->first_attached);
887         LeaveCriticalSection(&ddraw_cs);
888         return DDERR_SURFACEALREADYATTACHED;
889     }
890
891     /* This inserts the new surface at the 2nd position in the chain, right after the root surface */
892     Surf->next_attached = This->next_attached;
893     Surf->first_attached = This->first_attached;
894     This->next_attached = Surf;
895
896     /* Check if the WineD3D depth stencil needs updating */
897     if(This->ddraw->d3ddevice)
898     {
899         IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
900     }
901
902     /* MSDN: 
903      * "This method increments the reference count of the surface being attached."
904      */
905     IDirectDrawSurface7_AddRef(ICOM_INTERFACE(Surf, IDirectDrawSurface7));
906     LeaveCriticalSection(&ddraw_cs);
907     return DD_OK;
908 }
909
910 static HRESULT WINAPI
911 IDirectDrawSurface7Impl_AddAttachedSurface(IDirectDrawSurface7 *iface,
912                                            IDirectDrawSurface7 *Attach)
913 {
914     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
915     IDirectDrawSurfaceImpl *Surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Attach);
916
917     /* Version 7 of this interface seems to refuse everything except z buffers, as per msdn */
918     if(!(Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
919     {
920
921         WARN("Application tries to attach a non Z buffer surface. caps %08x\n",
922               Surf->surface_desc.ddsCaps.dwCaps);
923         return DDERR_CANNOTATTACHSURFACE;
924     }
925
926     return IDirectDrawSurfaceImpl_AddAttachedSurface(This,
927                                                      Surf);
928 }
929 /*****************************************************************************
930  * IDirectDrawSurface7::DeleteAttachedSurface
931  *
932  * Removes a surface from the attachment chain. The surface's refcount
933  * is decreased by one after it has been removed
934  *
935  * Params:
936  *  Flags: Some flags, not used by this implementation
937  *  Attach: Surface to detach
938  *
939  * Returns:
940  *  DD_OK on success
941  *  DDERR_SURFACENOTATTACHED if the surface isn't attached to
942  *
943  *****************************************************************************/
944 static HRESULT WINAPI
945 IDirectDrawSurfaceImpl_DeleteAttachedSurface(IDirectDrawSurface7 *iface,
946                                              DWORD Flags,
947                                              IDirectDrawSurface7 *Attach)
948 {
949     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
950     IDirectDrawSurfaceImpl *Surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Attach);
951     IDirectDrawSurfaceImpl *Prev = This;
952     TRACE("(%p)->(%08x,%p)\n", This, Flags, Surf);
953
954     EnterCriticalSection(&ddraw_cs);
955     if (!Surf || (Surf->first_attached != This) || (Surf == This) )
956     {
957         LeaveCriticalSection(&ddraw_cs);
958         return DDERR_CANNOTDETACHSURFACE;
959     }
960
961     /* Remove MIPMAPSUBLEVEL if this seemed to be one */
962     if (This->surface_desc.ddsCaps.dwCaps &
963         Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
964     {
965         Surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
966         /* FIXME: we should probably also subtract from dwMipMapCount of this
967          * and all parent surfaces */
968     }
969
970     /* Find the predecessor of the detached surface */
971     while(Prev)
972     {
973         if(Prev->next_attached == Surf) break;
974         Prev = Prev->next_attached;
975     }
976
977     /* There must be a surface, otherwise there's a bug */
978     assert(Prev != NULL);
979
980     /* Unchain the surface */
981     Prev->next_attached = Surf->next_attached;
982     Surf->next_attached = NULL;
983     Surf->first_attached = Surf;
984
985     /* Check if the WineD3D depth stencil needs updating */
986     if(This->ddraw->d3ddevice)
987     {
988         IDirect3DDeviceImpl_UpdateDepthStencil(This->ddraw->d3ddevice);
989     }
990
991     IDirectDrawSurface7_Release(Attach);
992     LeaveCriticalSection(&ddraw_cs);
993     return DD_OK;
994 }
995
996 /*****************************************************************************
997  * IDirectDrawSurface7::AddOverlayDirtyRect
998  *
999  * "This method is not currently implemented"
1000  *
1001  * Params:
1002  *  Rect: ?
1003  *
1004  * Returns:
1005  *  DDERR_UNSUPPORTED
1006  *
1007  *****************************************************************************/
1008 static HRESULT WINAPI
1009 IDirectDrawSurfaceImpl_AddOverlayDirtyRect(IDirectDrawSurface7 *iface,
1010                                            LPRECT Rect)
1011 {
1012     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1013     TRACE("(%p)->(%p)\n",This,Rect);
1014
1015     /* MSDN says it's not implemented. I could forward it to WineD3D, 
1016      * then we'd implement it, but I don't think that's a good idea
1017      * (Stefan Dösinger)
1018      */
1019 #if 0
1020     return IWineD3DSurface_AddOverlayDirtyRect(This->WineD3DSurface, pRect);
1021 #endif
1022     return DDERR_UNSUPPORTED; /* unchecked */
1023 }
1024
1025 /*****************************************************************************
1026  * IDirectDrawSurface7::GetDC
1027  *
1028  * Returns a GDI device context for the surface
1029  *
1030  * Params:
1031  *  hdc: Address of a HDC variable to store the dc to
1032  *
1033  * Returns:
1034  *  DD_OK on success
1035  *  DDERR_INVALIDPARAMS if hdc is NULL
1036  *  For details, see IWineD3DSurface::GetDC
1037  *
1038  *****************************************************************************/
1039 static HRESULT WINAPI
1040 IDirectDrawSurfaceImpl_GetDC(IDirectDrawSurface7 *iface,
1041                              HDC *hdc)
1042 {
1043     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1044     HRESULT hr;
1045     TRACE("(%p)->(%p): Relay\n", This, hdc);
1046
1047     if(!hdc)
1048         return DDERR_INVALIDPARAMS;
1049
1050     EnterCriticalSection(&ddraw_cs);
1051     hr = IWineD3DSurface_GetDC(This->WineD3DSurface,
1052                                hdc);
1053     LeaveCriticalSection(&ddraw_cs);
1054     return hr;
1055 }
1056
1057 /*****************************************************************************
1058  * IDirectDrawSurface7::ReleaseDC
1059  *
1060  * Releases the DC that was constructed with GetDC
1061  *
1062  * Params:
1063  *  hdc: HDC to release
1064  *
1065  * Returns:
1066  *  DD_OK on success
1067  *  For more details, see IWineD3DSurface::ReleaseDC
1068  *
1069  *****************************************************************************/
1070 static HRESULT WINAPI
1071 IDirectDrawSurfaceImpl_ReleaseDC(IDirectDrawSurface7 *iface,
1072                                  HDC hdc)
1073 {
1074     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1075     HRESULT hr;
1076     TRACE("(%p)->(%p): Relay\n", This, hdc);
1077
1078     EnterCriticalSection(&ddraw_cs);
1079     hr = IWineD3DSurface_ReleaseDC(This->WineD3DSurface, hdc);
1080     LeaveCriticalSection(&ddraw_cs);
1081     return hr;
1082 }
1083
1084 /*****************************************************************************
1085  * IDirectDrawSurface7::GetCaps
1086  *
1087  * Returns the surface's caps
1088  *
1089  * Params:
1090  *  Caps: Address to write the caps to
1091  *
1092  * Returns:
1093  *  DD_OK on success
1094  *  DDERR_INVALIDPARAMS if Caps is NULL
1095  *
1096  *****************************************************************************/
1097 static HRESULT WINAPI
1098 IDirectDrawSurfaceImpl_GetCaps(IDirectDrawSurface7 *iface,
1099                                DDSCAPS2 *Caps)
1100 {
1101     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1102     TRACE("(%p)->(%p)\n",This,Caps);
1103
1104     if(!Caps)
1105         return DDERR_INVALIDPARAMS;
1106
1107     *Caps = This->surface_desc.ddsCaps;
1108     return DD_OK;
1109 }
1110
1111 /*****************************************************************************
1112  * IDirectDrawSurface7::SetPriority
1113  *
1114  * Sets a texture priority for managed textures.
1115  *
1116  * Params:
1117  *  Priority: The new priority
1118  *
1119  * Returns:
1120  *  DD_OK on success
1121  *  For more details, see IWineD3DSurface::SetPriority
1122  *
1123  *****************************************************************************/
1124 static HRESULT WINAPI
1125 IDirectDrawSurfaceImpl_SetPriority(IDirectDrawSurface7 *iface, DWORD Priority)
1126 {
1127     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1128     HRESULT hr;
1129     TRACE("(%p)->(%d): Relay!\n",This,Priority);
1130
1131     EnterCriticalSection(&ddraw_cs);
1132     hr = IWineD3DSurface_SetPriority(This->WineD3DSurface, Priority);
1133     LeaveCriticalSection(&ddraw_cs);
1134     return hr;
1135 }
1136
1137 /*****************************************************************************
1138  * IDirectDrawSurface7::GetPriority
1139  *
1140  * Returns the surface's priority
1141  *
1142  * Params:
1143  *  Priority: Address of a variable to write the priority to
1144  *
1145  * Returns:
1146  *  D3D_OK on success
1147  *  DDERR_INVALIDPARAMS if Priority == NULL
1148  *  For more details, see IWineD3DSurface::GetPriority
1149  *
1150  *****************************************************************************/
1151 static HRESULT WINAPI
1152 IDirectDrawSurfaceImpl_GetPriority(IDirectDrawSurface7 *iface,
1153                                    DWORD *Priority)
1154 {
1155     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1156     TRACE("(%p)->(%p): Relay\n",This,Priority);
1157
1158     if(!Priority)
1159     {
1160         return DDERR_INVALIDPARAMS;
1161     }
1162
1163     EnterCriticalSection(&ddraw_cs);
1164     *Priority = IWineD3DSurface_GetPriority(This->WineD3DSurface);
1165     LeaveCriticalSection(&ddraw_cs);
1166     return DD_OK;
1167 }
1168
1169 /*****************************************************************************
1170  * IDirectDrawSurface7::SetPrivateData
1171  *
1172  * Stores some data in the surface that is intended for the application's
1173  * use.
1174  *
1175  * Params:
1176  *  tag: GUID that identifies the data
1177  *  Data: Pointer to the private data
1178  *  Size: Size of the private data
1179  *  Flags: Some flags
1180  *
1181  * Returns:
1182  *  D3D_OK on success
1183  *  For more details, see IWineD3DSurface::SetPrivateData
1184  *
1185  *****************************************************************************/
1186 static HRESULT WINAPI
1187 IDirectDrawSurfaceImpl_SetPrivateData(IDirectDrawSurface7 *iface,
1188                                       REFGUID tag,
1189                                       void *Data,
1190                                       DWORD Size,
1191                                       DWORD Flags)
1192 {
1193     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1194     HRESULT hr;
1195     TRACE("(%p)->(%s,%p,%d,%x): Relay\n", This, debugstr_guid(tag), Data, Size, Flags);
1196
1197     EnterCriticalSection(&ddraw_cs);
1198     hr = IWineD3DSurface_SetPrivateData(This->WineD3DSurface,
1199                                         tag,
1200                                         Data,
1201                                         Size,
1202                                         Flags);
1203     LeaveCriticalSection(&ddraw_cs);
1204     switch(hr)
1205     {
1206         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
1207         default:                            return hr;
1208     }
1209 }
1210
1211 /*****************************************************************************
1212  * IDirectDrawSurface7::GetPrivateData
1213  *
1214  * Returns the private data set with IDirectDrawSurface7::SetPrivateData
1215  *
1216  * Params:
1217  *  tag: GUID of the data to return
1218  *  Data: Address where to write the data to
1219  *  Size: Size of the buffer at Data
1220  *
1221  * Returns:
1222  *  DD_OK on success
1223  *  DDERR_INVALIDPARAMS if Data is NULL
1224  *  For more details, see IWineD3DSurface::GetPrivateData
1225  *
1226  *****************************************************************************/
1227 static HRESULT WINAPI
1228 IDirectDrawSurfaceImpl_GetPrivateData(IDirectDrawSurface7 *iface,
1229                                       REFGUID tag,
1230                                       void *Data,
1231                                       DWORD *Size)
1232 {
1233     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1234     HRESULT hr;
1235     TRACE("(%p)->(%s,%p,%p): Relay\n", This, debugstr_guid(tag), Data, Size);
1236
1237     if(!Data)
1238         return DDERR_INVALIDPARAMS;
1239
1240     EnterCriticalSection(&ddraw_cs);
1241     hr = IWineD3DSurface_GetPrivateData(This->WineD3DSurface,
1242                                         tag,
1243                                         Data,
1244                                         Size);
1245     LeaveCriticalSection(&ddraw_cs);
1246     return hr;
1247 }
1248
1249 /*****************************************************************************
1250  * IDirectDrawSurface7::FreePrivateData
1251  *
1252  * Frees private data stored in the surface
1253  *
1254  * Params:
1255  *  tag: Tag of the data to free
1256  *
1257  * Returns:
1258  *  D3D_OK on success
1259  *  For more details, see IWineD3DSurface::FreePrivateData
1260  *
1261  *****************************************************************************/
1262 static HRESULT WINAPI
1263 IDirectDrawSurfaceImpl_FreePrivateData(IDirectDrawSurface7 *iface,
1264                                        REFGUID tag)
1265 {
1266     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1267     HRESULT hr;
1268     TRACE("(%p)->(%s): Relay\n", This, debugstr_guid(tag));
1269
1270     EnterCriticalSection(&ddraw_cs);
1271     hr = IWineD3DSurface_FreePrivateData(This->WineD3DSurface, tag);
1272     LeaveCriticalSection(&ddraw_cs);
1273     return hr;
1274 }
1275
1276 /*****************************************************************************
1277  * IDirectDrawSurface7::PageLock
1278  *
1279  * Prevents a sysmem surface from being paged out
1280  *
1281  * Params:
1282  *  Flags: Not used, must be 0(unchecked)
1283  *
1284  * Returns:
1285  *  DD_OK, because it's a stub
1286  *
1287  *****************************************************************************/
1288 static HRESULT WINAPI
1289 IDirectDrawSurfaceImpl_PageLock(IDirectDrawSurface7 *iface,
1290                                 DWORD Flags)
1291 {
1292     TRACE("(%p)->(%x)\n", iface, Flags);
1293
1294     /* This is Windows memory management related - we don't need this */
1295     return DD_OK;
1296 }
1297
1298 /*****************************************************************************
1299  * IDirectDrawSurface7::PageUnlock
1300  *
1301  * Allows a sysmem surface to be paged out
1302  *
1303  * Params:
1304  *  Flags: Not used, must be 0(unckeched)
1305  *
1306  * Returns:
1307  *  DD_OK, because it's a stub
1308  *
1309  *****************************************************************************/
1310 static HRESULT WINAPI
1311 IDirectDrawSurfaceImpl_PageUnlock(IDirectDrawSurface7 *iface,
1312                                   DWORD Flags)
1313 {
1314     TRACE("(%p)->(%x)\n", iface, Flags);
1315
1316     return DD_OK;
1317 }
1318
1319 /*****************************************************************************
1320  * IDirectDrawSurface7::BltBatch
1321  *
1322  * An unimplemented function
1323  *
1324  * Params:
1325  *  ?
1326  *
1327  * Returns:
1328  *  DDERR_UNSUPPORTED
1329  *
1330  *****************************************************************************/
1331 static HRESULT WINAPI IDirectDrawSurfaceImpl_BltBatch(IDirectDrawSurface7 *iface, DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
1332 {
1333     TRACE("(%p)->(%p,%d,%08x)\n",iface,Batch,Count,Flags);
1334
1335     /* MSDN: "not currently implemented" */
1336     return DDERR_UNSUPPORTED;
1337 }
1338
1339 /*****************************************************************************
1340  * IDirectDrawSurface7::EnumAttachedSurfaces
1341  *
1342  * Enumerates all surfaces attached to this surface
1343  *
1344  * Params:
1345  *  context: Pointer to pass unmodified to the callback
1346  *  cb: Callback function to call for each surface
1347  *
1348  * Returns:
1349  *  DD_OK on success
1350  *  DDERR_INVALIDPARAMS if cb is NULL
1351  *
1352  *****************************************************************************/
1353 static HRESULT WINAPI
1354 IDirectDrawSurfaceImpl_EnumAttachedSurfaces(IDirectDrawSurface7 *iface,
1355                                             void *context,
1356                                             LPDDENUMSURFACESCALLBACK7 cb)
1357 {
1358     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1359     IDirectDrawSurfaceImpl *surf;
1360     DDSURFACEDESC2 desc;
1361     int i;
1362
1363     /* Attached surfaces aren't handled in WineD3D */
1364     TRACE("(%p)->(%p,%p)\n",This,context,cb);
1365
1366     if(!cb)
1367         return DDERR_INVALIDPARAMS;
1368
1369     EnterCriticalSection(&ddraw_cs);
1370     for(i = 0; i < MAX_COMPLEX_ATTACHED; i++)
1371     {
1372         surf = This->complex_array[i];
1373         if(!surf) break;
1374
1375         IDirectDrawSurface7_AddRef(ICOM_INTERFACE(surf, IDirectDrawSurface7));
1376         desc = surf->surface_desc;
1377         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
1378         if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &desc, context) == DDENUMRET_CANCEL)
1379         {
1380             LeaveCriticalSection(&ddraw_cs);
1381             return DD_OK;
1382         }
1383     }
1384
1385     for (surf = This->next_attached; surf != NULL; surf = surf->next_attached)
1386     {
1387         IDirectDrawSurface7_AddRef(ICOM_INTERFACE(surf, IDirectDrawSurface7));
1388         desc = surf->surface_desc;
1389         /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
1390         if (cb( ICOM_INTERFACE(surf, IDirectDrawSurface7), &desc, context) == DDENUMRET_CANCEL)
1391         {
1392             LeaveCriticalSection(&ddraw_cs);
1393             return DD_OK;
1394         }
1395     }
1396
1397     TRACE(" end of enumeration.\n");
1398
1399     LeaveCriticalSection(&ddraw_cs);
1400     return DD_OK;
1401 }
1402
1403 /*****************************************************************************
1404  * IDirectDrawSurface7::EnumOverlayZOrders
1405  *
1406  * "Enumerates the overlay surfaces on the specified destination"
1407  *
1408  * Params:
1409  *  Flags: DDENUMOVERLAYZ_BACKTOFRONT  or DDENUMOVERLAYZ_FRONTTOBACK
1410  *  context: context to pass back to the callback
1411  *  cb: callback function to call for each enumerated surface
1412  *
1413  * Returns:
1414  *  DD_OK, because it's a stub
1415  *
1416  *****************************************************************************/
1417 static HRESULT WINAPI
1418 IDirectDrawSurfaceImpl_EnumOverlayZOrders(IDirectDrawSurface7 *iface,
1419                                           DWORD Flags,
1420                                           void *context,
1421                                           LPDDENUMSURFACESCALLBACK7 cb)
1422 {
1423      FIXME("(%p)->(%x,%p,%p): Stub!\n", iface, Flags, context, cb);
1424
1425     return DD_OK;
1426 }
1427
1428 /*****************************************************************************
1429  * IDirectDrawSurface7::GetBltStatus
1430  *
1431  * Returns the blitting status
1432  *
1433  * Params:
1434  *  Flags: DDGBS_CANBLT or DDGBS_ISBLTDONE
1435  *
1436  * Returns:
1437  *  See IWineD3DSurface::Blt
1438  *
1439  *****************************************************************************/
1440 static HRESULT WINAPI
1441 IDirectDrawSurfaceImpl_GetBltStatus(IDirectDrawSurface7 *iface,
1442                                     DWORD Flags)
1443 {
1444     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1445     HRESULT hr;
1446     TRACE("(%p)->(%x): Relay\n", This, Flags);
1447
1448     EnterCriticalSection(&ddraw_cs);
1449     hr = IWineD3DSurface_GetBltStatus(This->WineD3DSurface, Flags);
1450     LeaveCriticalSection(&ddraw_cs);
1451     switch(hr)
1452     {
1453         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
1454         default:                            return hr;
1455     }
1456 }
1457
1458 /*****************************************************************************
1459  * IDirectDrawSurface7::GetColorKey
1460  *
1461  * Returns the color key assigned to the surface
1462  *
1463  * Params:
1464  *  Flags: Some flags
1465  *  CKey: Address to store the key to
1466  *
1467  * Returns:
1468  *  DD_OK on success
1469  *  DDERR_INVALIDPARAMS if CKey is NULL
1470  *
1471  *****************************************************************************/
1472 static HRESULT WINAPI
1473 IDirectDrawSurfaceImpl_GetColorKey(IDirectDrawSurface7 *iface,
1474                                    DWORD Flags,
1475                                    DDCOLORKEY *CKey)
1476 {
1477     /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
1478      * isn't there? That's like saying that an int isn't there. (Which MS
1479      * has done in other docs.) */
1480     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1481     TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
1482
1483     if(!CKey)
1484         return DDERR_INVALIDPARAMS;
1485
1486     EnterCriticalSection(&ddraw_cs);
1487     switch (Flags)
1488     {
1489     case DDCKEY_DESTBLT:
1490         *CKey = This->surface_desc.ddckCKDestBlt;
1491         break;
1492
1493     case DDCKEY_DESTOVERLAY:
1494         *CKey = This->surface_desc.u3.ddckCKDestOverlay;
1495         break;
1496
1497     case DDCKEY_SRCBLT:
1498         *CKey = This->surface_desc.ddckCKSrcBlt;
1499         break;
1500
1501     case DDCKEY_SRCOVERLAY:
1502         *CKey = This->surface_desc.ddckCKSrcOverlay;
1503         break;
1504
1505     default:
1506         LeaveCriticalSection(&ddraw_cs);
1507         return DDERR_INVALIDPARAMS;
1508     }
1509
1510     LeaveCriticalSection(&ddraw_cs);
1511     return DD_OK;
1512 }
1513
1514 /*****************************************************************************
1515  * IDirectDrawSurface7::GetFlipStatus
1516  *
1517  * Returns the flipping status of the surface
1518  *
1519  * Params:
1520  *  Flags: DDGFS_CANFLIP of DDGFS_ISFLIPDONE
1521  *
1522  * Returns:
1523  *  See IWineD3DSurface::GetFlipStatus
1524  *
1525  *****************************************************************************/
1526 static HRESULT WINAPI
1527 IDirectDrawSurfaceImpl_GetFlipStatus(IDirectDrawSurface7 *iface,
1528                                      DWORD Flags)
1529 {
1530     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1531     HRESULT hr;
1532     TRACE("(%p)->(%x): Relay\n", This, Flags);
1533
1534     EnterCriticalSection(&ddraw_cs);
1535     hr = IWineD3DSurface_GetFlipStatus(This->WineD3DSurface, Flags);
1536     LeaveCriticalSection(&ddraw_cs);
1537     switch(hr)
1538     {
1539         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
1540         default:                            return hr;
1541     }
1542 }
1543
1544 /*****************************************************************************
1545  * IDirectDrawSurface7::GetOverlayPosition
1546  *
1547  * Returns the display coordinates of a visible and active overlay surface
1548  *
1549  * Params:
1550  *  X
1551  *  Y
1552  *
1553  * Returns:
1554  *  DDERR_NOTAOVERLAYSURFACE, because it's a stub
1555  *****************************************************************************/
1556 static HRESULT WINAPI
1557 IDirectDrawSurfaceImpl_GetOverlayPosition(IDirectDrawSurface7 *iface,
1558                                           LONG *X,
1559                                           LONG *Y) {
1560     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1561     HRESULT hr;
1562     TRACE("(%p)->(%p,%p): Relay\n", This, X, Y);
1563
1564     EnterCriticalSection(&ddraw_cs);
1565     hr = IWineD3DSurface_GetOverlayPosition(This->WineD3DSurface,
1566                                             X,
1567                                             Y);
1568     LeaveCriticalSection(&ddraw_cs);
1569     return hr;
1570 }
1571
1572 /*****************************************************************************
1573  * IDirectDrawSurface7::GetPixelFormat
1574  *
1575  * Returns the pixel format of the Surface
1576  *
1577  * Params:
1578  *  PixelFormat: Pointer to a DDPIXELFORMAT structure to which the pixel
1579  *               format should be written
1580  *
1581  * Returns:
1582  *  DD_OK on success
1583  *  DDERR_INVALIDPARAMS if PixelFormat is NULL
1584  *
1585  *****************************************************************************/
1586 static HRESULT WINAPI
1587 IDirectDrawSurfaceImpl_GetPixelFormat(IDirectDrawSurface7 *iface,
1588                                       DDPIXELFORMAT *PixelFormat)
1589 {
1590     /* What is DDERR_INVALIDSURFACETYPE for here? */
1591     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1592     TRACE("(%p)->(%p)\n",This,PixelFormat);
1593
1594     if(!PixelFormat)
1595         return DDERR_INVALIDPARAMS;
1596
1597     EnterCriticalSection(&ddraw_cs);
1598     DD_STRUCT_COPY_BYSIZE(PixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
1599     LeaveCriticalSection(&ddraw_cs);
1600
1601     return DD_OK;
1602 }
1603
1604
1605 /*****************************************************************************
1606  * IDirectDrawSurface7::GetSurfaceDesc
1607  *
1608  * Returns the description of this surface
1609  *
1610  * Params:
1611  *  DDSD: Address of a DDSURFACEDESC2 structure that is to be filled with the
1612  *        surface desc
1613  *
1614  * Returns:
1615  *  DD_OK on success
1616  *  DDERR_INVALIDPARAMS if DDSD is NULL
1617  *
1618  *****************************************************************************/
1619 static HRESULT WINAPI
1620 IDirectDrawSurfaceImpl_GetSurfaceDesc(IDirectDrawSurface7 *iface,
1621                                       DDSURFACEDESC2 *DDSD)
1622 {
1623     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1624
1625     TRACE("(%p)->(%p)\n",This,DDSD);
1626
1627     if(!DDSD)
1628         return DDERR_INVALIDPARAMS;
1629
1630     if (DDSD->dwSize != sizeof(DDSURFACEDESC2))
1631     {
1632         WARN("Incorrect struct size %d, returning DDERR_INVALIDPARAMS\n",DDSD->dwSize);
1633         return DDERR_INVALIDPARAMS;
1634     }
1635
1636     EnterCriticalSection(&ddraw_cs);
1637     DD_STRUCT_COPY_BYSIZE(DDSD,&This->surface_desc);
1638     TRACE("Returning surface desc:\n");
1639     if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD);
1640
1641     LeaveCriticalSection(&ddraw_cs);
1642     return DD_OK;
1643 }
1644
1645 /*****************************************************************************
1646  * IDirectDrawSurface7::Initialize
1647  *
1648  * Initializes the surface. This is a no-op in Wine
1649  *
1650  * Params:
1651  *  DD: Pointer to an DirectDraw interface
1652  *  DDSD: Surface description for initialization
1653  *
1654  * Returns:
1655  *  DDERR_ALREADYINITIALIZED
1656  *
1657  *****************************************************************************/
1658 static HRESULT WINAPI
1659 IDirectDrawSurfaceImpl_Initialize(IDirectDrawSurface7 *iface,
1660                                   IDirectDraw *DD,
1661                                   DDSURFACEDESC2 *DDSD)
1662 {
1663     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1664     IDirectDrawImpl *ddimpl = ICOM_OBJECT(IDirectDrawImpl, IDirectDraw, DD);
1665     TRACE("(%p)->(%p,%p)\n",This,ddimpl,DDSD);
1666
1667     return DDERR_ALREADYINITIALIZED;
1668 }
1669
1670 /*****************************************************************************
1671  * IDirectDrawSurface7::IsLost
1672  *
1673  * Checks if the surface is lost
1674  *
1675  * Returns:
1676  *  DD_OK, if the surface is useable
1677  *  DDERR_ISLOST if the surface is lost
1678  *  See IWineD3DSurface::IsLost for more details
1679  *
1680  *****************************************************************************/
1681 static HRESULT WINAPI
1682 IDirectDrawSurfaceImpl_IsLost(IDirectDrawSurface7 *iface)
1683 {
1684     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1685     HRESULT hr;
1686     TRACE("(%p)\n", This);
1687
1688     EnterCriticalSection(&ddraw_cs);
1689     /* We lose the surface if the implementation was changed */
1690     if(This->ImplType != This->ddraw->ImplType)
1691     {
1692         /* But this shouldn't happen. When we change the implementation,
1693          * all surfaces are re-created automatically, and their content
1694          * is copied
1695          */
1696         ERR(" (%p) Implementation was changed from %d to %d\n", This, This->ImplType, This->ddraw->ImplType);
1697         LeaveCriticalSection(&ddraw_cs);
1698         return DDERR_SURFACELOST;
1699     }
1700
1701     hr = IWineD3DSurface_IsLost(This->WineD3DSurface);
1702     LeaveCriticalSection(&ddraw_cs);
1703     switch(hr)
1704     {
1705         /* D3D8 and 9 loose full devices, thus there's only a DEVICELOST error.
1706          * WineD3D uses the same error for surfaces
1707          */
1708         case WINED3DERR_DEVICELOST:         return DDERR_SURFACELOST;
1709         default:                            return hr;
1710     }
1711 }
1712
1713 /*****************************************************************************
1714  * IDirectDrawSurface7::Restore
1715  *
1716  * Restores a lost surface. This makes the surface usable again, but
1717  * doesn't reload its old contents
1718  *
1719  * Returns:
1720  *  DD_OK on success
1721  *  See IWineD3DSurface::Restore for more details
1722  *
1723  *****************************************************************************/
1724 static HRESULT WINAPI
1725 IDirectDrawSurfaceImpl_Restore(IDirectDrawSurface7 *iface)
1726 {
1727     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1728     HRESULT hr;
1729     TRACE("(%p)\n", This);
1730
1731     EnterCriticalSection(&ddraw_cs);
1732     if(This->ImplType != This->ddraw->ImplType)
1733     {
1734         /* Call the recreation callback. Make sure to AddRef first */
1735         IDirectDrawSurface_AddRef(iface);
1736         IDirectDrawImpl_RecreateSurfacesCallback(iface,
1737                                                  &This->surface_desc,
1738                                                  NULL /* Not needed */);
1739     }
1740     hr = IWineD3DSurface_Restore(This->WineD3DSurface);
1741     LeaveCriticalSection(&ddraw_cs);
1742     return hr;
1743 }
1744
1745 /*****************************************************************************
1746  * IDirectDrawSurface7::SetOverlayPosition
1747  *
1748  * Changes the display coordinates of an overlay surface
1749  *
1750  * Params:
1751  *  X:
1752  *  Y:
1753  *
1754  * Returns:
1755  *   DDERR_NOTAOVERLAYSURFACE, because we don't support overlays right now
1756  *****************************************************************************/
1757 static HRESULT WINAPI
1758 IDirectDrawSurfaceImpl_SetOverlayPosition(IDirectDrawSurface7 *iface,
1759                                           LONG X,
1760                                           LONG Y)
1761 {
1762     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1763     HRESULT hr;
1764     TRACE("(%p)->(%d,%d): Relay\n", This, X, Y);
1765
1766     EnterCriticalSection(&ddraw_cs);
1767     hr = IWineD3DSurface_SetOverlayPosition(This->WineD3DSurface,
1768                                             X,
1769                                             Y);
1770     LeaveCriticalSection(&ddraw_cs);
1771     return hr;
1772 }
1773
1774 /*****************************************************************************
1775  * IDirectDrawSurface7::UpdateOverlay
1776  *
1777  * Modifies the attributes of an overlay surface.
1778  *
1779  * Params:
1780  *  SrcRect: The section of the source being used for the overlay
1781  *  DstSurface: Address of the surface that is overlaid
1782  *  DstRect: Place of the overlay
1783  *  Flags: some DDOVER_* flags
1784  *
1785  * Returns:
1786  *  DDERR_UNSUPPORTED, because we don't support overlays
1787  *
1788  *****************************************************************************/
1789 static HRESULT WINAPI
1790 IDirectDrawSurfaceImpl_UpdateOverlay(IDirectDrawSurface7 *iface,
1791                                      LPRECT SrcRect,
1792                                      IDirectDrawSurface7 *DstSurface,
1793                                      LPRECT DstRect,
1794                                      DWORD Flags,
1795                                      LPDDOVERLAYFX FX)
1796 {
1797     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1798     IDirectDrawSurfaceImpl *Dst = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, DstSurface);
1799     HRESULT hr;
1800     TRACE("(%p)->(%p,%p,%p,%x,%p): Relay\n", This, SrcRect, Dst, DstRect, Flags, FX);
1801
1802     EnterCriticalSection(&ddraw_cs);
1803     hr = IWineD3DSurface_UpdateOverlay(This->WineD3DSurface,
1804                                        SrcRect,
1805                                        Dst ? Dst->WineD3DSurface : NULL,
1806                                        DstRect,
1807                                        Flags,
1808                                        (WINEDDOVERLAYFX *) FX);
1809     LeaveCriticalSection(&ddraw_cs);
1810     return hr;
1811 }
1812
1813 /*****************************************************************************
1814  * IDirectDrawSurface7::UpdateOverlayDisplay
1815  *
1816  * The DX7 sdk says that it's not implemented
1817  *
1818  * Params:
1819  *  Flags: ?
1820  *
1821  * Returns: DDERR_UNSUPPORTED, because we don't support overlays
1822  *
1823  *****************************************************************************/
1824 static HRESULT WINAPI
1825 IDirectDrawSurfaceImpl_UpdateOverlayDisplay(IDirectDrawSurface7 *iface,
1826                                             DWORD Flags)
1827 {
1828     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1829     TRACE("(%p)->(%x)\n", This, Flags);
1830     return DDERR_UNSUPPORTED;
1831 }
1832
1833 /*****************************************************************************
1834  * IDirectDrawSurface7::UpdateOverlayZOrder
1835  *
1836  * Sets an overlay's Z order
1837  *
1838  * Params:
1839  *  Flags: DDOVERZ_* flags
1840  *  DDSRef: Defines the relative position in the overlay chain
1841  *
1842  * Returns:
1843  *  DDERR_NOTOVERLAYSURFACE, because we don't support overlays
1844  *
1845  *****************************************************************************/
1846 static HRESULT WINAPI
1847 IDirectDrawSurfaceImpl_UpdateOverlayZOrder(IDirectDrawSurface7 *iface,
1848                                            DWORD Flags,
1849                                            IDirectDrawSurface7 *DDSRef)
1850 {
1851     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1852     HRESULT hr;
1853     IDirectDrawSurfaceImpl *Ref = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, DDSRef);
1854
1855     TRACE("(%p)->(%x,%p): Relay\n", This, Flags, Ref);
1856     EnterCriticalSection(&ddraw_cs);
1857     hr =  IWineD3DSurface_UpdateOverlayZOrder(This->WineD3DSurface,
1858                                               Flags,
1859                                               Ref ? Ref->WineD3DSurface : NULL);
1860     LeaveCriticalSection(&ddraw_cs);
1861     return hr;
1862 }
1863
1864 /*****************************************************************************
1865  * IDirectDrawSurface7::GetDDInterface
1866  *
1867  * Returns the IDirectDraw7 interface pointer of the DirectDraw object this
1868  * surface belongs to
1869  *
1870  * Params:
1871  *  DD: Address to write the interface pointer to
1872  *
1873  * Returns:
1874  *  DD_OK on success
1875  *  DDERR_INVALIDPARAMS if DD is NULL
1876  *
1877  *****************************************************************************/
1878 static HRESULT WINAPI
1879 IDirectDrawSurfaceImpl_GetDDInterface(IDirectDrawSurface7 *iface,
1880                                       void **DD)
1881 {
1882     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1883
1884     TRACE("(%p)->(%p)\n",This,DD);
1885
1886     if(!DD)
1887         return DDERR_INVALIDPARAMS;
1888
1889     switch(This->version)
1890     {
1891         case 7:
1892             *((IDirectDraw7 **) DD) = ICOM_INTERFACE(This->ddraw, IDirectDraw7);
1893             IDirectDraw7_AddRef(*(IDirectDraw7 **) DD);
1894             break;
1895
1896         case 4:
1897             *((IDirectDraw4 **) DD) = ICOM_INTERFACE(This->ddraw, IDirectDraw4);
1898             IDirectDraw4_AddRef(*(IDirectDraw4 **) DD);
1899             break;
1900
1901         case 2:
1902             *((IDirectDraw2 **) DD) = ICOM_INTERFACE(This->ddraw, IDirectDraw2);
1903             IDirectDraw_AddRef( *(IDirectDraw2 **) DD);
1904             break;
1905
1906         case 1:
1907             *((IDirectDraw **) DD) = ICOM_INTERFACE(This->ddraw, IDirectDraw);
1908             IDirectDraw_AddRef( *(IDirectDraw **) DD);
1909             break;
1910
1911     }
1912
1913     return DD_OK;
1914 }
1915
1916 /* This seems also windows implementation specific - I don't think WineD3D needs this */
1917 static HRESULT WINAPI IDirectDrawSurfaceImpl_ChangeUniquenessValue(IDirectDrawSurface7 *iface)
1918 {
1919     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1920     volatile IDirectDrawSurfaceImpl* vThis = This;
1921
1922     TRACE("(%p)\n",This);
1923     EnterCriticalSection(&ddraw_cs);
1924     /* A uniqueness value of 0 is apparently special.
1925      * This needs to be checked.
1926      * TODO: Write tests for this code and check if the volatile, interlocked stuff is really needed
1927      */
1928     while (1) {
1929         DWORD old_uniqueness_value = vThis->uniqueness_value;
1930         DWORD new_uniqueness_value = old_uniqueness_value+1;
1931
1932         if (old_uniqueness_value == 0) break;
1933         if (new_uniqueness_value == 0) new_uniqueness_value = 1;
1934
1935         if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
1936                                       old_uniqueness_value,
1937                                       new_uniqueness_value)
1938             == old_uniqueness_value)
1939             break;
1940     }
1941
1942     LeaveCriticalSection(&ddraw_cs);
1943     return DD_OK;
1944 }
1945
1946 static HRESULT WINAPI IDirectDrawSurfaceImpl_GetUniquenessValue(IDirectDrawSurface7 *iface, LPDWORD pValue)
1947 {
1948     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1949
1950     TRACE("(%p)->(%p)\n",This,pValue);
1951     EnterCriticalSection(&ddraw_cs);
1952     *pValue = This->uniqueness_value;
1953     LeaveCriticalSection(&ddraw_cs);
1954     return DD_OK;
1955 }
1956
1957 /*****************************************************************************
1958  * IDirectDrawSurface7::SetLOD
1959  *
1960  * Sets the level of detail of a texture
1961  *
1962  * Params:
1963  *  MaxLOD: LOD to set
1964  *
1965  * Returns:
1966  *  DD_OK on success
1967  *  DDERR_INVALIDOBJECT if the surface is invalid for this method
1968  *
1969  *****************************************************************************/
1970 static HRESULT WINAPI
1971 IDirectDrawSurfaceImpl_SetLOD(IDirectDrawSurface7 *iface,
1972                               DWORD MaxLOD)
1973 {
1974     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
1975     HRESULT hr;
1976     TRACE("(%p)->(%d)\n", This, MaxLOD);
1977
1978     EnterCriticalSection(&ddraw_cs);
1979     if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
1980     {
1981         LeaveCriticalSection(&ddraw_cs);
1982         return DDERR_INVALIDOBJECT;
1983     }
1984
1985     if(!This->wineD3DTexture)
1986     {
1987         ERR("(%p) The DirectDraw texture has no WineD3DTexture!\n", This);
1988         LeaveCriticalSection(&ddraw_cs);
1989         return DDERR_INVALIDOBJECT;
1990     }
1991
1992     hr = IWineD3DBaseTexture_SetLOD(This->wineD3DTexture,
1993                                     MaxLOD);
1994     LeaveCriticalSection(&ddraw_cs);
1995     return hr;
1996 }
1997
1998 /*****************************************************************************
1999  * IDirectDrawSurface7::GetLOD
2000  *
2001  * Returns the level of detail of a Direct3D texture
2002  *
2003  * Params:
2004  *  MaxLOD: Address to write the LOD to
2005  *
2006  * Returns:
2007  *  DD_OK on success
2008  *  DDERR_INVALIDPARAMS if MaxLOD is NULL
2009  *  DDERR_INVALIDOBJECT if the surface is invalid for this method
2010  *
2011  *****************************************************************************/
2012 static HRESULT WINAPI
2013 IDirectDrawSurfaceImpl_GetLOD(IDirectDrawSurface7 *iface,
2014                               DWORD *MaxLOD)
2015 {
2016     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
2017     TRACE("(%p)->(%p)\n", This, MaxLOD);
2018
2019     if(!MaxLOD)
2020         return DDERR_INVALIDPARAMS;
2021
2022     EnterCriticalSection(&ddraw_cs);
2023     if (!(This->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
2024     {
2025         LeaveCriticalSection(&ddraw_cs);
2026         return DDERR_INVALIDOBJECT;
2027     }
2028
2029     *MaxLOD = IWineD3DBaseTexture_GetLOD(This->wineD3DTexture);
2030     LeaveCriticalSection(&ddraw_cs);
2031     return DD_OK;
2032 }
2033
2034 /*****************************************************************************
2035  * IDirectDrawSurface7::BltFast
2036  *
2037  * Performs a fast Blit.
2038  *
2039  * Params:
2040  *  dstx: The x coordinate to blit to on the destination
2041  *  dsty: The y coordinate to blit to on the destination
2042  *  Source: The source surface
2043  *  rsrc: The source rectangle
2044  *  trans: Type of transfer. Some DDBLTFAST_* flags
2045  *
2046  * Returns:
2047  *  DD_OK on success
2048  *  For more details, see IWineD3DSurface::BltFast
2049  *
2050  *****************************************************************************/
2051 static HRESULT WINAPI
2052 IDirectDrawSurfaceImpl_BltFast(IDirectDrawSurface7 *iface,
2053                                DWORD dstx,
2054                                DWORD dsty,
2055                                IDirectDrawSurface7 *Source,
2056                                RECT *rsrc,
2057                                DWORD trans)
2058 {
2059     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
2060     HRESULT hr;
2061     IDirectDrawSurfaceImpl *src = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, Source);
2062     TRACE("(%p)->(%d,%d,%p,%p,%d): Relay\n", This, dstx, dsty, Source, rsrc, trans);
2063
2064     /* Source must be != NULL, This is not checked by windows. Windows happily throws a 0xc0000005
2065      * in that case
2066      */
2067     if(rsrc)
2068     {
2069         if(rsrc->top > rsrc->bottom || rsrc->left > rsrc->right ||
2070            rsrc->right > src->surface_desc.dwWidth ||
2071            rsrc->bottom > src->surface_desc.dwHeight)
2072         {
2073             WARN("Source rectangle is invalid, returning DDERR_INVALIDRECT\n");
2074             return DDERR_INVALIDRECT;
2075         }
2076         if(dstx + rsrc->right - rsrc->left > This->surface_desc.dwWidth ||
2077            dsty + rsrc->bottom - rsrc->top > This->surface_desc.dwHeight)
2078         {
2079             WARN("Destination area out of bounds, returning DDERR_INVALIDRECT\n");
2080             return DDERR_INVALIDRECT;
2081         }
2082     }
2083     else
2084     {
2085         if(dstx + src->surface_desc.dwWidth > This->surface_desc.dwWidth ||
2086            dsty + src->surface_desc.dwHeight > This->surface_desc.dwHeight)
2087         {
2088             WARN("Destination area out of bounds, returning DDERR_INVALIDRECT\n");
2089             return DDERR_INVALIDRECT;
2090         }
2091     }
2092
2093     EnterCriticalSection(&ddraw_cs);
2094     hr = IWineD3DSurface_BltFast(This->WineD3DSurface,
2095                                  dstx, dsty,
2096                                  src ? src->WineD3DSurface : NULL,
2097                                  rsrc,
2098                                  trans);
2099     LeaveCriticalSection(&ddraw_cs);
2100     switch(hr)
2101     {
2102         case WINED3DERR_NOTAVAILABLE:           return DDERR_UNSUPPORTED;
2103         case WINED3DERR_WRONGTEXTUREFORMAT:     return DDERR_INVALIDPIXELFORMAT;
2104         default:                                return hr;
2105     }
2106 }
2107
2108 /*****************************************************************************
2109  * IDirectDrawSurface7::GetClipper
2110  *
2111  * Returns the IDirectDrawClipper interface of the clipper assigned to this
2112  * surface
2113  *
2114  * Params:
2115  *  Clipper: Address to store the interface pointer at
2116  *
2117  * Returns:
2118  *  DD_OK on success
2119  *  DDERR_INVALIDPARAMS if Clipper is NULL
2120  *  DDERR_NOCLIPPERATTACHED if there's no clipper attached
2121  *
2122  *****************************************************************************/
2123 static HRESULT WINAPI
2124 IDirectDrawSurfaceImpl_GetClipper(IDirectDrawSurface7 *iface,
2125                                   IDirectDrawClipper **Clipper)
2126 {
2127     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
2128     TRACE("(%p)->(%p)\n", This, Clipper);
2129
2130     if(!Clipper)
2131     {
2132         LeaveCriticalSection(&ddraw_cs);
2133         return DDERR_INVALIDPARAMS;
2134     }
2135
2136     EnterCriticalSection(&ddraw_cs);
2137     if(This->clipper == NULL)
2138     {
2139         LeaveCriticalSection(&ddraw_cs);
2140         return DDERR_NOCLIPPERATTACHED;
2141     }
2142
2143     *Clipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
2144     IDirectDrawClipper_AddRef(*Clipper);
2145     LeaveCriticalSection(&ddraw_cs);
2146     return DD_OK;
2147 }
2148
2149 /*****************************************************************************
2150  * IDirectDrawSurface7::SetClipper
2151  *
2152  * Sets a clipper for the surface
2153  *
2154  * Params:
2155  *  Clipper: IDirectDrawClipper interface of the clipper to set
2156  *
2157  * Returns:
2158  *  DD_OK on success
2159  *
2160  *****************************************************************************/
2161 static HRESULT WINAPI
2162 IDirectDrawSurfaceImpl_SetClipper(IDirectDrawSurface7 *iface,
2163                                   IDirectDrawClipper *Clipper)
2164 {
2165     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
2166     IDirectDrawClipperImpl *oldClipper = This->clipper;
2167     HRESULT hr;
2168     TRACE("(%p)->(%p)\n",This,Clipper);
2169
2170     EnterCriticalSection(&ddraw_cs);
2171     if (ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper, Clipper) == This->clipper)
2172     {
2173         LeaveCriticalSection(&ddraw_cs);
2174         return DD_OK;
2175     }
2176
2177     This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper, Clipper);
2178
2179     if (Clipper != NULL)
2180         IDirectDrawClipper_AddRef(Clipper);
2181     if(oldClipper)
2182         IDirectDrawClipper_Release(ICOM_INTERFACE(oldClipper, IDirectDrawClipper));
2183
2184     hr = IWineD3DSurface_SetClipper(This->WineD3DSurface, This->clipper ? This->clipper->wineD3DClipper : NULL);
2185     LeaveCriticalSection(&ddraw_cs);
2186     return hr;
2187 }
2188
2189 /*****************************************************************************
2190  * IDirectDrawSurface7::SetSurfaceDesc
2191  *
2192  * Sets the surface description. It can override the pixel format, the surface
2193  * memory, ...
2194  * It's not really tested.
2195  *
2196  * Params:
2197  * DDSD: Pointer to the new surface description to set
2198  * Flags: Some flags
2199  *
2200  * Returns:
2201  *  DD_OK on success
2202  *  DDERR_INVALIDPARAMS if DDSD is NULL
2203  *
2204  *****************************************************************************/
2205 static HRESULT WINAPI
2206 IDirectDrawSurfaceImpl_SetSurfaceDesc(IDirectDrawSurface7 *iface,
2207                                       DDSURFACEDESC2 *DDSD,
2208                                       DWORD Flags)
2209 {
2210     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
2211     WINED3DFORMAT newFormat = WINED3DFMT_UNKNOWN;
2212     HRESULT hr;
2213     TRACE("(%p)->(%p,%x)\n", This, DDSD, Flags);
2214
2215     if(!DDSD)
2216         return DDERR_INVALIDPARAMS;
2217
2218     EnterCriticalSection(&ddraw_cs);
2219     if (DDSD->dwFlags & DDSD_PIXELFORMAT)
2220     {
2221         newFormat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
2222
2223         if(newFormat == WINED3DFMT_UNKNOWN)
2224         {
2225             ERR("Requested to set an unknown pixelformat\n");
2226             LeaveCriticalSection(&ddraw_cs);
2227             return DDERR_INVALIDPARAMS;
2228         }
2229         if(newFormat != PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat) )
2230         {
2231             hr = IWineD3DSurface_SetFormat(This->WineD3DSurface,
2232                                            newFormat);
2233             if(hr != DD_OK)
2234             {
2235                 LeaveCriticalSection(&ddraw_cs);
2236                 return hr;
2237             }
2238         }
2239     }
2240     if (DDSD->dwFlags & DDSD_CKDESTOVERLAY)
2241     {
2242         IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2243                                     DDCKEY_DESTOVERLAY,
2244                                     (WINEDDCOLORKEY *) &DDSD->u3.ddckCKDestOverlay);
2245     }
2246     if (DDSD->dwFlags & DDSD_CKDESTBLT)
2247     {
2248         IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2249                                     DDCKEY_DESTBLT,
2250                                     (WINEDDCOLORKEY *) &DDSD->ddckCKDestBlt);
2251     }
2252     if (DDSD->dwFlags & DDSD_CKSRCOVERLAY)
2253     {
2254         IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2255                                     DDCKEY_SRCOVERLAY,
2256                                     (WINEDDCOLORKEY *) &DDSD->ddckCKSrcOverlay);
2257     }
2258     if (DDSD->dwFlags & DDSD_CKSRCBLT)
2259     {
2260         IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2261                                     DDCKEY_SRCBLT,
2262                                     (WINEDDCOLORKEY *) &DDSD->ddckCKSrcBlt);
2263     }
2264     if (DDSD->dwFlags & DDSD_LPSURFACE && DDSD->lpSurface)
2265     {
2266         hr = IWineD3DSurface_SetMem(This->WineD3DSurface, DDSD->lpSurface);
2267         if(hr != WINED3D_OK)
2268         {
2269             /* No need for a trace here, wined3d does that for us */
2270             LeaveCriticalSection(&ddraw_cs);
2271             switch(hr)
2272             {
2273                 case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
2274                 default:                            break; /* Go on */
2275             }
2276         }
2277
2278     }
2279
2280     This->surface_desc = *DDSD;
2281
2282     LeaveCriticalSection(&ddraw_cs);
2283     return DD_OK;
2284 }
2285
2286 /*****************************************************************************
2287  * IDirectDrawSurface7::GetPalette
2288  *
2289  * Returns the IDirectDrawPalette interface of the palette currently assigned
2290  * to the surface
2291  *
2292  * Params:
2293  *  Pal: Address to write the interface pointer to
2294  *
2295  * Returns:
2296  *  DD_OK on success
2297  *  DDERR_INVALIDPARAMS if Pal is NULL
2298  *
2299  *****************************************************************************/
2300 static HRESULT WINAPI
2301 IDirectDrawSurfaceImpl_GetPalette(IDirectDrawSurface7 *iface,
2302                                   IDirectDrawPalette **Pal)
2303 {
2304     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
2305     IWineD3DPalette *wPal;
2306     HRESULT hr;
2307     TRACE("(%p)->(%p): Relay\n", This, Pal);
2308
2309     if(!Pal)
2310         return DDERR_INVALIDPARAMS;
2311
2312     EnterCriticalSection(&ddraw_cs);
2313     hr = IWineD3DSurface_GetPalette(This->WineD3DSurface, &wPal);
2314     if(hr != DD_OK)
2315     {
2316         LeaveCriticalSection(&ddraw_cs);
2317         return hr;
2318     }
2319
2320     if(wPal)
2321     {
2322         hr = IWineD3DPalette_GetParent(wPal, (IUnknown **) Pal);
2323     }
2324     else
2325     {
2326         *Pal = NULL;
2327         hr = DDERR_NOPALETTEATTACHED;
2328     }
2329
2330     LeaveCriticalSection(&ddraw_cs);
2331     return hr;
2332 }
2333
2334 /*****************************************************************************
2335  * SetColorKeyEnum
2336  *
2337  * EnumAttachedSurface callback for SetColorKey. Used to set color keys
2338  * recursively in the surface tree
2339  *
2340  *****************************************************************************/
2341 struct SCKContext
2342 {
2343     HRESULT ret;
2344     WINEDDCOLORKEY *CKey;
2345     DWORD Flags;
2346 };
2347
2348 static HRESULT WINAPI
2349 SetColorKeyEnum(IDirectDrawSurface7 *surface,
2350                 DDSURFACEDESC2 *desc,
2351                 void *context)
2352 {
2353     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, surface);
2354     struct SCKContext *ctx = context;
2355     HRESULT hr;
2356
2357     hr = IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2358                                      ctx->Flags,
2359                                      ctx->CKey);
2360     if(hr != DD_OK)
2361     {
2362         WARN("IWineD3DSurface_SetColorKey failed, hr = %08x\n", hr);
2363         ctx->ret = hr;
2364     }
2365
2366     IDirectDrawSurface7_EnumAttachedSurfaces(surface,
2367                                              context,
2368                                              SetColorKeyEnum);
2369     IDirectDrawSurface7_Release(surface);
2370     return DDENUMRET_OK;
2371 }
2372
2373 /*****************************************************************************
2374  * IDirectDrawSurface7::SetColorKey
2375  *
2376  * Sets the color keying options for the surface. Observations showed that
2377  * in case of complex surfaces the color key has to be assigned to all
2378  * sublevels.
2379  *
2380  * Params:
2381  *  Flags: DDCKEY_*
2382  *  CKey: The new color key
2383  *
2384  * Returns:
2385  *  DD_OK on success
2386  *  See IWineD3DSurface::SetColorKey for details
2387  *
2388  *****************************************************************************/
2389 static HRESULT WINAPI
2390 IDirectDrawSurfaceImpl_SetColorKey(IDirectDrawSurface7 *iface,
2391                                    DWORD Flags,
2392                                    DDCOLORKEY *CKey)
2393 {
2394     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
2395     struct SCKContext ctx = { DD_OK, (WINEDDCOLORKEY *) CKey, Flags };
2396     TRACE("(%p)->(%x,%p)\n", This, Flags, CKey);
2397
2398     EnterCriticalSection(&ddraw_cs);
2399     if (CKey)
2400     {
2401         switch (Flags & ~DDCKEY_COLORSPACE)
2402         {
2403         case DDCKEY_DESTBLT:
2404             This->surface_desc.ddckCKDestBlt = *CKey;
2405             This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
2406             break;
2407
2408         case DDCKEY_DESTOVERLAY:
2409             This->surface_desc.u3.ddckCKDestOverlay = *CKey;
2410             This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
2411             break;
2412
2413         case DDCKEY_SRCOVERLAY:
2414             This->surface_desc.ddckCKSrcOverlay = *CKey;
2415             This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
2416             break;
2417
2418         case DDCKEY_SRCBLT:
2419             This->surface_desc.ddckCKSrcBlt = *CKey;
2420             This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
2421             break;
2422
2423         default:
2424             LeaveCriticalSection(&ddraw_cs);
2425             return DDERR_INVALIDPARAMS;
2426         }
2427     }
2428     else
2429     {
2430         switch (Flags & ~DDCKEY_COLORSPACE)
2431         {
2432         case DDCKEY_DESTBLT:
2433             This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
2434             break;
2435
2436         case DDCKEY_DESTOVERLAY:
2437             This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
2438             break;
2439
2440         case DDCKEY_SRCOVERLAY:
2441             This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
2442             break;
2443
2444         case DDCKEY_SRCBLT:
2445             This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
2446             break;
2447
2448         default:
2449             LeaveCriticalSection(&ddraw_cs);
2450             return DDERR_INVALIDPARAMS;
2451         }
2452     }
2453     ctx.ret = IWineD3DSurface_SetColorKey(This->WineD3DSurface,
2454                                           Flags,
2455                                           ctx.CKey);
2456     IDirectDrawSurface7_EnumAttachedSurfaces(iface,
2457                                              (void *) &ctx,
2458                                              SetColorKeyEnum);
2459     LeaveCriticalSection(&ddraw_cs);
2460     switch(ctx.ret)
2461     {
2462         case WINED3DERR_INVALIDCALL:        return DDERR_INVALIDPARAMS;
2463         default:                            return ctx.ret;
2464     }
2465 }
2466
2467 /*****************************************************************************
2468  * IDirectDrawSurface7::SetPalette
2469  *
2470  * Assigns a DirectDrawPalette object to the surface
2471  *
2472  * Params:
2473  *  Pal: Interface to the palette to set
2474  *
2475  * Returns:
2476  *  DD_OK on success
2477  *
2478  *****************************************************************************/
2479 static HRESULT WINAPI
2480 IDirectDrawSurfaceImpl_SetPalette(IDirectDrawSurface7 *iface,
2481                                   IDirectDrawPalette *Pal)
2482 {
2483     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
2484     IDirectDrawPalette *oldPal;
2485     IDirectDrawSurfaceImpl *surf;
2486     IDirectDrawPaletteImpl *PalImpl = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette, Pal);
2487     HRESULT hr;
2488     TRACE("(%p)->(%p)\n", This, Pal);
2489
2490     /* Find the old palette */
2491     EnterCriticalSection(&ddraw_cs);
2492     hr = IDirectDrawSurface_GetPalette(iface, &oldPal);
2493     if(hr != DD_OK && hr != DDERR_NOPALETTEATTACHED)
2494     {
2495         LeaveCriticalSection(&ddraw_cs);
2496         return hr;
2497     }
2498     if(oldPal) IDirectDrawPalette_Release(oldPal);  /* For the GetPalette */
2499
2500     /* Set the new Palette */
2501     IWineD3DSurface_SetPalette(This->WineD3DSurface,
2502                                PalImpl ? PalImpl->wineD3DPalette : NULL);
2503     /* AddRef the Palette */
2504     if(Pal) IDirectDrawPalette_AddRef(Pal);
2505
2506     /* Release the old palette */
2507     if(oldPal) IDirectDrawPalette_Release(oldPal);
2508
2509     /* If this is a front buffer, also update the back buffers
2510      * TODO: How do things work for palettized cube textures?
2511      */
2512     if(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER)
2513     {
2514         /* For primary surfaces the tree is just a list, so the simpler scheme fits too */
2515         DDSCAPS2 caps2 = { DDSCAPS_PRIMARYSURFACE, 0, 0, 0 };
2516
2517         surf = This;
2518         while(1)
2519         {
2520             IDirectDrawSurface7 *attach;
2521             HRESULT hr;
2522             hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(surf, IDirectDrawSurface7),
2523                                                         &caps2, &attach);
2524             if(hr != DD_OK)
2525             {
2526                 break;
2527             }
2528
2529             TRACE("Setting palette on %p\n", attach);
2530             IDirectDrawSurface7_SetPalette(attach,
2531                                            Pal);
2532             surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, attach);
2533             IDirectDrawSurface7_Release(attach);
2534         }
2535     }
2536
2537     LeaveCriticalSection(&ddraw_cs);
2538     return DD_OK;
2539 }
2540
2541 /*****************************************************************************
2542  * The VTable
2543  *****************************************************************************/
2544
2545 const IDirectDrawSurface7Vtbl IDirectDrawSurface7_Vtbl =
2546 {
2547     /*** IUnknown ***/
2548     IDirectDrawSurfaceImpl_QueryInterface,
2549     IDirectDrawSurfaceImpl_AddRef,
2550     IDirectDrawSurfaceImpl_Release,
2551     /*** IDirectDrawSurface ***/
2552     IDirectDrawSurface7Impl_AddAttachedSurface,
2553     IDirectDrawSurfaceImpl_AddOverlayDirtyRect,
2554     IDirectDrawSurfaceImpl_Blt,
2555     IDirectDrawSurfaceImpl_BltBatch,
2556     IDirectDrawSurfaceImpl_BltFast,
2557     IDirectDrawSurfaceImpl_DeleteAttachedSurface,
2558     IDirectDrawSurfaceImpl_EnumAttachedSurfaces,
2559     IDirectDrawSurfaceImpl_EnumOverlayZOrders,
2560     IDirectDrawSurfaceImpl_Flip,
2561     IDirectDrawSurfaceImpl_GetAttachedSurface,
2562     IDirectDrawSurfaceImpl_GetBltStatus,
2563     IDirectDrawSurfaceImpl_GetCaps,
2564     IDirectDrawSurfaceImpl_GetClipper,
2565     IDirectDrawSurfaceImpl_GetColorKey,
2566     IDirectDrawSurfaceImpl_GetDC,
2567     IDirectDrawSurfaceImpl_GetFlipStatus,
2568     IDirectDrawSurfaceImpl_GetOverlayPosition,
2569     IDirectDrawSurfaceImpl_GetPalette,
2570     IDirectDrawSurfaceImpl_GetPixelFormat,
2571     IDirectDrawSurfaceImpl_GetSurfaceDesc,
2572     IDirectDrawSurfaceImpl_Initialize,
2573     IDirectDrawSurfaceImpl_IsLost,
2574     IDirectDrawSurfaceImpl_Lock,
2575     IDirectDrawSurfaceImpl_ReleaseDC,
2576     IDirectDrawSurfaceImpl_Restore,
2577     IDirectDrawSurfaceImpl_SetClipper,
2578     IDirectDrawSurfaceImpl_SetColorKey,
2579     IDirectDrawSurfaceImpl_SetOverlayPosition,
2580     IDirectDrawSurfaceImpl_SetPalette,
2581     IDirectDrawSurfaceImpl_Unlock,
2582     IDirectDrawSurfaceImpl_UpdateOverlay,
2583     IDirectDrawSurfaceImpl_UpdateOverlayDisplay,
2584     IDirectDrawSurfaceImpl_UpdateOverlayZOrder,
2585     /*** IDirectDrawSurface2 ***/
2586     IDirectDrawSurfaceImpl_GetDDInterface,
2587     IDirectDrawSurfaceImpl_PageLock,
2588     IDirectDrawSurfaceImpl_PageUnlock,
2589     /*** IDirectDrawSurface3 ***/
2590     IDirectDrawSurfaceImpl_SetSurfaceDesc,
2591     /*** IDirectDrawSurface4 ***/
2592     IDirectDrawSurfaceImpl_SetPrivateData,
2593     IDirectDrawSurfaceImpl_GetPrivateData,
2594     IDirectDrawSurfaceImpl_FreePrivateData,
2595     IDirectDrawSurfaceImpl_GetUniquenessValue,
2596     IDirectDrawSurfaceImpl_ChangeUniquenessValue,
2597     /*** IDirectDrawSurface7 ***/
2598     IDirectDrawSurfaceImpl_SetPriority,
2599     IDirectDrawSurfaceImpl_GetPriority,
2600     IDirectDrawSurfaceImpl_SetLOD,
2601     IDirectDrawSurfaceImpl_GetLOD
2602 };