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