ddrawex: COM cleanup for the IDirectDrawSurface3 iface.
[wine] / dlls / ddrawex / surface.c
1 /*
2  * Copyright 2008 Stefan Dösinger for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "wine/debug.h"
20
21 #define COBJMACROS
22
23 #include "winbase.h"
24 #include "wingdi.h"
25
26 #include "ddraw.h"
27 #include "d3d.h"
28
29 #include "ddrawex_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(ddrawex);
32
33 /******************************************************************************
34  * Helper functions for COM management
35  ******************************************************************************/
36 static IDirectDrawSurfaceImpl *impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
37 {
38     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface3_iface);
39 }
40
41 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface);
42
43 static IDirectDrawSurfaceImpl *impl_from_dds4(IDirectDrawSurface4 *iface)
44 {
45     if(!iface) return NULL;
46     return (IDirectDrawSurfaceImpl *)((char*)iface - FIELD_OFFSET(IDirectDrawSurfaceImpl, IDirectDrawSurface4_Vtbl));
47 }
48 static IDirectDrawSurface4 *dds4_from_impl(IDirectDrawSurfaceImpl *This)
49 {
50     if(!This) return NULL;
51     return (IDirectDrawSurface4 *) &This->IDirectDrawSurface4_Vtbl;
52 }
53
54 static HRESULT WINAPI
55 IDirectDrawSurface4Impl_QueryInterface(IDirectDrawSurface4 *iface,
56                                        REFIID riid,
57                                        void **obj)
58 {
59     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
60
61     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
62     *obj = NULL;
63
64     if(!riid)
65         return DDERR_INVALIDPARAMS;
66
67     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),obj);
68     if (IsEqualGUID(riid, &IID_IUnknown)
69      || IsEqualGUID(riid, &IID_IDirectDrawSurface4) )
70     {
71         *obj = dds4_from_impl(This);
72         IDirectDrawSurface4_AddRef((IDirectDrawSurface4 *) *obj);
73         TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
74         return S_OK;
75     }
76     else if( IsEqualGUID(riid, &IID_IDirectDrawSurface3)
77           || IsEqualGUID(riid, &IID_IDirectDrawSurface2)
78           || IsEqualGUID(riid, &IID_IDirectDrawSurface) )
79     {
80         *obj = &This->IDirectDrawSurface3_iface;
81         IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
82         TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
83         return S_OK;
84     }
85     else if( IsEqualGUID(riid, &IID_IDirectDrawGammaControl) )
86     {
87         FIXME("Implement IDirectDrawGammaControl in ddrawex\n");
88     }
89     else if( IsEqualGUID(riid, &IID_IDirect3DHALDevice)||
90              IsEqualGUID(riid, &IID_IDirect3DRGBDevice) )
91     {
92         /* Most likely not supported */
93         FIXME("Test IDirect3DDevice in ddrawex\n");
94     }
95     else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
96              IsEqualGUID( &IID_IDirect3DTexture2, riid ))
97     {
98         FIXME("Implement IDirect3dTexture in ddrawex\n");
99     }
100     else
101     {
102         WARN("No interface\n");
103     }
104
105     return E_NOINTERFACE;
106 }
107
108 static HRESULT WINAPI IDirectDrawSurface3Impl_QueryInterface(IDirectDrawSurface3 *iface,
109         REFIID riid, void **obj)
110 {
111     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
112     TRACE("(%p)->(%s,%p): Thunking to IDirectDrawSurface4\n",This,debugstr_guid(riid),obj);
113     return IDirectDrawSurface4_QueryInterface(dds4_from_impl(This), riid, obj);
114 }
115
116 static ULONG WINAPI
117 IDirectDrawSurface4Impl_AddRef(IDirectDrawSurface4 *iface)
118 {
119     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
120     ULONG ref = InterlockedIncrement(&This->ref);
121
122     TRACE("(%p) : incrementing refcount from %u.\n", This, ref - 1);
123
124     return ref;
125 }
126
127 static ULONG WINAPI IDirectDrawSurface3Impl_AddRef(IDirectDrawSurface3 *iface)
128 {
129     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
130     TRACE("(%p): Thunking to IDirectDrawSurface4\n", This);
131     return IDirectDrawSurface4_AddRef(dds4_from_impl(This));
132 }
133
134 static ULONG WINAPI
135 IDirectDrawSurface4Impl_Release(IDirectDrawSurface4 *iface)
136 {
137     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
138     ULONG ref = InterlockedDecrement(&This->ref);
139
140     TRACE("(%p) : decrementing refcount to %u.\n", This, ref);
141
142     if(ref == 0)
143     {
144         TRACE("Destroying object\n");
145         IDirectDrawSurface4_FreePrivateData(This->parent, &IID_DDrawexPriv);
146         IDirectDrawSurface4_Release(This->parent);
147         HeapFree(GetProcessHeap(), 0, This);
148     }
149     return ref;
150 }
151
152 static ULONG WINAPI IDirectDrawSurface3Impl_Release(IDirectDrawSurface3 *iface)
153 {
154     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
155     TRACE("(%p): Thunking to IDirectDrawSurface4\n", This);
156     return IDirectDrawSurface4_Release(dds4_from_impl(This));
157 }
158
159 static HRESULT WINAPI
160 IDirectDrawSurface4Impl_AddAttachedSurface(IDirectDrawSurface4 *iface,
161                                            IDirectDrawSurface4 *Attach_iface)
162 {
163     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
164     IDirectDrawSurfaceImpl *attach = impl_from_dds4(Attach_iface);
165     TRACE("(%p)->(%p)\n", This, attach);
166     return IDirectDrawSurface4_AddAttachedSurface(This->parent, attach->parent);
167 }
168
169 static HRESULT WINAPI IDirectDrawSurface3Impl_AddAttachedSurface(IDirectDrawSurface3 *iface,
170         IDirectDrawSurface3 *Attach_iface)
171 {
172     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
173     IDirectDrawSurfaceImpl *attach = unsafe_impl_from_IDirectDrawSurface3(Attach_iface);
174     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, attach);
175     return IDirectDrawSurface4_AddAttachedSurface(dds4_from_impl(This), dds4_from_impl(attach));
176 }
177
178 static HRESULT WINAPI
179 IDirectDrawSurface4Impl_AddOverlayDirtyRect(IDirectDrawSurface4 *iface,
180                                             RECT *Rect)
181 {
182     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
183     TRACE("(%p)->(%p)\n", This, Rect);
184     return IDirectDrawSurface4_AddOverlayDirtyRect(This->parent, Rect);
185 }
186
187 static HRESULT WINAPI IDirectDrawSurface3Impl_AddOverlayDirtyRect(IDirectDrawSurface3 *iface,
188         RECT *Rect)
189 {
190     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
191     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Rect);
192     return IDirectDrawSurface4_AddOverlayDirtyRect(dds4_from_impl(This), Rect);
193 }
194
195 static HRESULT WINAPI
196 IDirectDrawSurface4Impl_Blt(IDirectDrawSurface4 *iface,
197                             RECT *DestRect,
198                             IDirectDrawSurface4 *SrcSurface,
199                             RECT *SrcRect,
200                             DWORD Flags,
201                             DDBLTFX *DDBltFx)
202 {
203     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
204     IDirectDrawSurfaceImpl *Src = impl_from_dds4(SrcSurface);
205     TRACE("(%p)->(%p,%p,%p,0x%08x,%p)\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
206     return IDirectDrawSurface4_Blt(This->parent, DestRect, Src ? Src->parent : NULL,
207                                    SrcRect, Flags, DDBltFx);
208 }
209
210 static HRESULT WINAPI IDirectDrawSurface3Impl_Blt(IDirectDrawSurface3 *iface, RECT *DestRect,
211         IDirectDrawSurface3 *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx)
212 {
213     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
214     IDirectDrawSurfaceImpl *Src = unsafe_impl_from_IDirectDrawSurface3(SrcSurface);
215     TRACE("(%p)->(%p,%p,%p,0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
216     return IDirectDrawSurface4_Blt(dds4_from_impl(This), DestRect, dds4_from_impl(Src),
217                                    SrcRect, Flags, DDBltFx);
218 }
219
220 static HRESULT WINAPI
221 IDirectDrawSurface4Impl_BltBatch(IDirectDrawSurface4 *iface,
222                                  DDBLTBATCH *Batch,
223                                  DWORD Count,
224                                  DWORD Flags)
225 {
226     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
227     TRACE("(%p)->(%p,%u,0x%08x)\n", This, Batch, Count, Flags);
228     return IDirectDrawSurface4_BltBatch(This->parent, Batch, Count, Flags);
229 }
230
231 static HRESULT WINAPI IDirectDrawSurface3Impl_BltBatch(IDirectDrawSurface3 *iface,
232         DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
233 {
234     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
235     TRACE("(%p)->(%p,%u,0x%08x): Thunking to IDirectDrawSurface4\n", This, Batch, Count, Flags);
236     return IDirectDrawSurface4_BltBatch(dds4_from_impl(This), Batch, Count, Flags);
237 }
238
239 static HRESULT WINAPI
240 IDirectDrawSurface4Impl_BltFast(IDirectDrawSurface4 *iface,
241                                 DWORD dstx,
242                                 DWORD dsty,
243                                 IDirectDrawSurface4 *Source,
244                                 RECT *rsrc,
245                                 DWORD trans)
246 {
247     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
248     IDirectDrawSurfaceImpl *Src = impl_from_dds4(Source);
249     TRACE("(%p)->(%u,%u,%p,%p,0x%08x)\n", This, dstx, dsty, Src, rsrc, trans);
250     return IDirectDrawSurface4_BltFast(This->parent, dstx, dsty, Src ? Src->parent : NULL,
251                                        rsrc, trans);
252 }
253
254 static HRESULT WINAPI IDirectDrawSurface3Impl_BltFast(IDirectDrawSurface3 *iface, DWORD dstx,
255         DWORD dsty, IDirectDrawSurface3 *Source, RECT *rsrc, DWORD trans)
256 {
257     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
258     IDirectDrawSurfaceImpl *Src = unsafe_impl_from_IDirectDrawSurface3(Source);
259     TRACE("(%p)->(%u,%u,%p,%p,0x%08x): Thunking to IDirectDrawSurface4\n", This, dstx, dsty, Src, rsrc, trans);
260     return IDirectDrawSurface4_BltFast(dds4_from_impl(This), dstx, dsty, dds4_from_impl(Src),
261                                        rsrc, trans);
262 }
263
264 static HRESULT WINAPI
265 IDirectDrawSurface4Impl_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
266                                               DWORD Flags,
267                                               IDirectDrawSurface4 *Attach)
268 {
269     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
270     IDirectDrawSurfaceImpl *Att = impl_from_dds4(Attach);
271     TRACE("(%p)->(0x%08x,%p)\n", This, Flags, Att);
272     return IDirectDrawSurface4_DeleteAttachedSurface(This->parent, Flags,
273                                                      Att ? Att->parent : NULL);
274 }
275
276 static HRESULT WINAPI IDirectDrawSurface3Impl_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
277         DWORD Flags, IDirectDrawSurface3 *Attach)
278 {
279     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
280     IDirectDrawSurfaceImpl *Att = unsafe_impl_from_IDirectDrawSurface3(Attach);
281     TRACE("(%p)->(0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, Flags, Att);
282     return IDirectDrawSurface4_DeleteAttachedSurface(dds4_from_impl(This), Flags,
283                                                      dds4_from_impl(Att));
284 }
285
286 struct enumsurfaces_wrap
287 {
288     LPDDENUMSURFACESCALLBACK2 orig_cb;
289     void *orig_ctx;
290 };
291
292 static HRESULT WINAPI
293 enumsurfaces_wrap_cb(IDirectDrawSurface4 *surf, DDSURFACEDESC2 *desc, void *vctx)
294 {
295     struct enumsurfaces_wrap *ctx = vctx;
296     IDirectDrawSurface4 *outer = dds_get_outer(surf);
297
298     TRACE("Returning outer surface %p for inner surface %p\n", outer, surf);
299     IDirectDrawSurface4_AddRef(outer);
300     IDirectDrawSurface4_Release(surf);
301     return ctx->orig_cb(outer, desc, vctx);
302 }
303
304 static HRESULT WINAPI
305 IDirectDrawSurface4Impl_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
306                                              void *context,
307                                              LPDDENUMSURFACESCALLBACK2 cb)
308 {
309     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
310     struct enumsurfaces_wrap ctx;
311     TRACE("(%p)->(%p,%p)\n", This, context, cb);
312
313     ctx.orig_cb = cb;
314     ctx.orig_ctx = context;
315     return IDirectDrawSurface4_EnumAttachedSurfaces(This->parent, &ctx, enumsurfaces_wrap_cb);
316 }
317
318 struct enumsurfaces_thunk
319 {
320     LPDDENUMSURFACESCALLBACK orig_cb;
321     void *orig_ctx;
322 };
323
324 static HRESULT WINAPI
325 enumsurfaces_thunk_cb(IDirectDrawSurface4 *surf, DDSURFACEDESC2 *desc2, void *vctx)
326 {
327     IDirectDrawSurfaceImpl *This = impl_from_dds4(surf);
328     struct enumsurfaces_thunk *ctx = vctx;
329     DDSURFACEDESC desc;
330
331     TRACE("Thunking back to IDirectDrawSurface3\n");
332     IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
333     IDirectDrawSurface3_Release(surf);
334     DDSD2_to_DDSD(desc2, &desc);
335     return ctx->orig_cb((IDirectDrawSurface *)&This->IDirectDrawSurface3_iface, &desc,
336             ctx->orig_ctx);
337 }
338
339 static HRESULT WINAPI IDirectDrawSurface3Impl_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
340         void *context, LPDDENUMSURFACESCALLBACK cb)
341 {
342     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
343     struct enumsurfaces_thunk ctx;
344     TRACE("(%p)->(%p,%p): Thunking to IDirectDraw4\n", This, context, cb);
345
346     ctx.orig_cb = cb;
347     ctx.orig_ctx = context;
348     return IDirectDrawSurface4_EnumAttachedSurfaces(dds4_from_impl(This), &ctx, enumsurfaces_thunk_cb);
349 }
350
351 static HRESULT WINAPI
352 IDirectDrawSurface4Impl_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
353                                            DWORD Flags,
354                                            void *context,
355                                            LPDDENUMSURFACESCALLBACK2 cb)
356 {
357     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
358     struct enumsurfaces_wrap ctx;
359     TRACE("(%p)->(0x%08x,%p,%p)\n", This, Flags, context, cb);
360
361     ctx.orig_cb = cb;
362     ctx.orig_ctx = context;
363     return IDirectDrawSurface4_EnumOverlayZOrders(This->parent, Flags, &ctx, enumsurfaces_wrap_cb);
364 }
365
366 static HRESULT WINAPI IDirectDrawSurface3Impl_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
367         DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK cb)
368 {
369     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
370     struct enumsurfaces_thunk ctx;
371     TRACE("(%p)->(0x%08x,%p,%p): Thunking to IDirectDraw4\n", This, Flags, context, cb);
372
373     ctx.orig_cb = cb;
374     ctx.orig_ctx = context;
375     return IDirectDrawSurface4_EnumOverlayZOrders(dds4_from_impl(This), Flags, &ctx, enumsurfaces_thunk_cb);
376 }
377
378 static HRESULT WINAPI
379 IDirectDrawSurface4Impl_Flip(IDirectDrawSurface4 *iface,
380                              IDirectDrawSurface4 *DestOverride,
381                              DWORD Flags)
382 {
383     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
384     IDirectDrawSurfaceImpl *Dest = impl_from_dds4(DestOverride);
385     TRACE("(%p)->(%p,0x%08x)\n", This, Dest, Flags);
386     return IDirectDrawSurface4_Flip(This->parent, Dest ? Dest->parent : NULL, Flags);
387 }
388
389 static HRESULT WINAPI IDirectDrawSurface3Impl_Flip(IDirectDrawSurface3 *iface,
390         IDirectDrawSurface3 *DestOverride, DWORD Flags)
391 {
392     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
393     IDirectDrawSurfaceImpl *Dest = unsafe_impl_from_IDirectDrawSurface3(DestOverride);
394     TRACE("(%p)->(%p,0x%08x): Thunking to IDirectDrawSurface4\n", This, Dest, Flags);
395     return IDirectDrawSurface4_Flip(dds4_from_impl(This), dds4_from_impl(Dest), Flags);
396 }
397
398 static HRESULT WINAPI
399 IDirectDrawSurface4Impl_GetAttachedSurface(IDirectDrawSurface4 *iface,
400                                            DDSCAPS2 *Caps,
401                                            IDirectDrawSurface4 **Surface)
402 {
403     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
404     IDirectDrawSurface4 *inner = NULL;
405     HRESULT hr;
406     TRACE("(%p)->(%p,%p)\n", This, Caps, Surface);
407
408     hr = IDirectDrawSurface4_GetAttachedSurface(dds4_from_impl(This), Caps, &inner);
409     if(SUCCEEDED(hr))
410     {
411         *Surface = dds_get_outer(inner);
412         IDirectDrawSurface4_AddRef(*Surface);
413         IDirectDrawSurface4_Release(inner);
414     }
415     else
416     {
417         *Surface = NULL;
418     }
419     return hr;
420 }
421
422 static HRESULT WINAPI IDirectDrawSurface3Impl_GetAttachedSurface(IDirectDrawSurface3 *iface,
423         DDSCAPS *Caps, IDirectDrawSurface3 **Surface)
424 {
425     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
426     IDirectDrawSurface4 *surf4;
427     DDSCAPS2 caps2;
428     HRESULT hr;
429     TRACE("(%p)->(%p,%p): Thunking to IDirectDrawSurface4\n", This, Caps, Surface);
430
431     memset(&caps2, 0, sizeof(caps2));
432     caps2.dwCaps = Caps->dwCaps;
433     hr = IDirectDrawSurface4_GetAttachedSurface(dds4_from_impl(This), &caps2, &surf4);
434     if(SUCCEEDED(hr))
435     {
436         IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface3, (void **) Surface);
437         IDirectDrawSurface4_Release(surf4);
438     }
439     else
440     {
441         *Surface = NULL;
442     }
443     return hr;
444 }
445
446 static HRESULT WINAPI
447 IDirectDrawSurface4Impl_GetBltStatus(IDirectDrawSurface4 *iface,
448                                      DWORD Flags)
449 {
450     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
451     TRACE("(%p)->(0x%08x)\n", This, Flags);
452     return IDirectDrawSurface4_GetBltStatus(This->parent, Flags);
453 }
454
455 static HRESULT WINAPI IDirectDrawSurface3Impl_GetBltStatus(IDirectDrawSurface3 *iface, DWORD Flags)
456 {
457     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
458     TRACE("(%p)->(0x%08x): Thunking to IDirectDrawSurface4\n", This, Flags);
459     return IDirectDrawSurface4_GetBltStatus(dds4_from_impl(This), Flags);
460 }
461
462 static HRESULT WINAPI
463 IDirectDrawSurface4Impl_GetCaps(IDirectDrawSurface4 *iface,
464                                 DDSCAPS2 *Caps)
465 {
466     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
467     TRACE("(%p)->(%p)\n", This, Caps);
468     return IDirectDrawSurface4_GetCaps(This->parent, Caps);
469 }
470
471 static HRESULT WINAPI IDirectDrawSurface3Impl_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *Caps)
472 {
473     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
474     DDSCAPS2 caps2;
475     HRESULT hr;
476     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Caps);
477
478     memset(&caps2, 0, sizeof(caps2));
479     memset(Caps, 0, sizeof(*Caps));
480     hr = IDirectDrawSurface4_GetCaps(dds4_from_impl(This), &caps2);
481     Caps->dwCaps = caps2.dwCaps;
482     return hr;
483 }
484
485 static HRESULT WINAPI
486 IDirectDrawSurface4Impl_GetClipper(IDirectDrawSurface4 *iface,
487                                    IDirectDrawClipper **Clipper)
488 {
489     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
490     TRACE("(%p)->(%p)\n", This, Clipper);
491     return IDirectDrawSurface4_GetClipper(This->parent, Clipper);
492 }
493
494 static HRESULT WINAPI IDirectDrawSurface3Impl_GetClipper(IDirectDrawSurface3 *iface,
495         IDirectDrawClipper **Clipper)
496 {
497     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
498     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Clipper);
499     return IDirectDrawSurface4_GetClipper(dds4_from_impl(This), Clipper);
500 }
501
502 static HRESULT WINAPI
503 IDirectDrawSurface4Impl_GetColorKey(IDirectDrawSurface4 *iface,
504                                     DWORD Flags,
505                                     DDCOLORKEY *CKey)
506 {
507     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
508     TRACE("(%p)->(0x%08x,%p)\n", This, Flags, CKey);
509     return IDirectDrawSurface4_GetColorKey(This->parent, Flags, CKey);
510 }
511
512 static HRESULT WINAPI IDirectDrawSurface3Impl_GetColorKey(IDirectDrawSurface3 *iface, DWORD Flags,
513         DDCOLORKEY *CKey)
514 {
515     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
516     TRACE("(%p)->(0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, Flags, CKey);
517     return IDirectDrawSurface4_GetColorKey(dds4_from_impl(This), Flags, CKey);
518 }
519
520 static HRESULT WINAPI
521 IDirectDrawSurface4Impl_GetDC(IDirectDrawSurface4 *iface,
522                              HDC *hdc)
523 {
524     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
525     TRACE("(%p)->(%p)\n", This, hdc);
526     if(This->permanent_dc)
527     {
528         TRACE("Returning stored dc %p\n", This->hdc);
529         *hdc = This->hdc;
530         return DD_OK;
531     }
532     else
533     {
534         return IDirectDrawSurface4_GetDC(This->parent, hdc);
535     }
536 }
537
538 static HRESULT WINAPI IDirectDrawSurface3Impl_GetDC(IDirectDrawSurface3 *iface, HDC *hdc)
539 {
540     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
541     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, hdc);
542     return IDirectDrawSurface4_GetDC(dds4_from_impl(This), hdc);
543 }
544
545 static HRESULT WINAPI
546 IDirectDrawSurface4Impl_GetFlipStatus(IDirectDrawSurface4 *iface,
547                                       DWORD Flags)
548 {
549     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
550     TRACE("(%p)->(0x%08x)\n", This, Flags);
551     return IDirectDrawSurface4_GetFlipStatus(This->parent, Flags);
552 }
553
554 static HRESULT WINAPI IDirectDrawSurface3Impl_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD Flags)
555 {
556     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
557     TRACE("(%p)->(0x%08x): Thunking to IDirectDrawSurface4\n", This, Flags);
558     return IDirectDrawSurface4_GetFlipStatus(dds4_from_impl(This), Flags);
559 }
560
561 static HRESULT WINAPI
562 IDirectDrawSurface4Impl_GetOverlayPosition(IDirectDrawSurface4 *iface,
563                                            LONG *X,
564                                            LONG *Y)
565 {
566     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
567     TRACE("(%p)->(%p,%p)\n", This, X, Y);
568     return IDirectDrawSurface4_GetOverlayPosition(This->parent, X, Y);
569 }
570
571 static HRESULT WINAPI IDirectDrawSurface3Impl_GetOverlayPosition(IDirectDrawSurface3 *iface,
572         LONG *X, LONG *Y)
573 {
574     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
575     TRACE("(%p)->(%p,%p): Thunking to IDirectDrawSurface4\n", This, X, Y);
576     return IDirectDrawSurface4_GetOverlayPosition(dds4_from_impl(This), X, Y);
577 }
578
579 static HRESULT WINAPI
580 IDirectDrawSurface4Impl_GetPalette(IDirectDrawSurface4 *iface,
581                                    IDirectDrawPalette **Pal)
582 {
583     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
584     TRACE("(%p)->(%p)\n", This, Pal);
585     return IDirectDrawSurface4_GetPalette(This->parent, Pal);
586 }
587
588 static HRESULT WINAPI IDirectDrawSurface3Impl_GetPalette(IDirectDrawSurface3 *iface,
589         IDirectDrawPalette **Pal)
590 {
591     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
592     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Pal);
593     return IDirectDrawSurface4_GetPalette(dds4_from_impl(This), Pal);
594 }
595
596 static HRESULT WINAPI
597 IDirectDrawSurface4Impl_GetPixelFormat(IDirectDrawSurface4 *iface,
598                                        DDPIXELFORMAT *PixelFormat)
599 {
600     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
601     TRACE("(%p)->(%p)\n", This, PixelFormat);
602     return IDirectDrawSurface4_GetPixelFormat(This->parent, PixelFormat);
603 }
604
605 static HRESULT WINAPI IDirectDrawSurface3Impl_GetPixelFormat(IDirectDrawSurface3 *iface,
606         DDPIXELFORMAT *PixelFormat)
607 {
608     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
609     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, PixelFormat);
610     return IDirectDrawSurface4_GetPixelFormat(dds4_from_impl(This), PixelFormat);
611 }
612
613 static HRESULT WINAPI
614 IDirectDrawSurface4Impl_GetSurfaceDesc(IDirectDrawSurface4 *iface,
615                                        DDSURFACEDESC2 *DDSD)
616 {
617     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
618     HRESULT hr;
619     TRACE("(%p)->(%p)\n", This, DDSD);
620     hr = IDirectDrawSurface4_GetSurfaceDesc(This->parent, DDSD);
621
622     if(SUCCEEDED(hr) && This->permanent_dc)
623     {
624         DDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
625         DDSD->ddsCaps.dwCaps &= ~DDSCAPS_OWNDC;
626     }
627
628     return hr;
629 }
630
631 static HRESULT WINAPI IDirectDrawSurface3Impl_GetSurfaceDesc(IDirectDrawSurface3 *iface,
632         DDSURFACEDESC *DDSD)
633 {
634     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
635     DDSURFACEDESC2 ddsd2;
636     HRESULT hr;
637     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, DDSD);
638
639     memset(&ddsd2, 0, sizeof(ddsd2));
640     ddsd2.dwSize = sizeof(ddsd2);
641     hr = IDirectDrawSurface4_GetSurfaceDesc(dds4_from_impl(This), &ddsd2);
642     DDSD2_to_DDSD(&ddsd2, DDSD);
643     return hr;
644 }
645
646 static HRESULT WINAPI
647 IDirectDrawSurface4Impl_Initialize(IDirectDrawSurface4 *iface,
648                                    IDirectDraw *DD,
649                                    DDSURFACEDESC2 *DDSD)
650 {
651     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
652     IDirectDraw4 *outer_DD4;
653     IDirectDraw4 *inner_DD4;
654     IDirectDraw *inner_DD;
655     HRESULT hr;
656     TRACE("(%p)->(%p,%p)\n", This, DD, DDSD);
657
658     IDirectDraw_QueryInterface(DD, &IID_IDirectDraw4, (void **) &outer_DD4);
659     inner_DD4 = dd_get_inner(outer_DD4);
660     IDirectDraw4_Release(outer_DD4);
661     IDirectDraw4_QueryInterface(inner_DD4, &IID_IDirectDraw4, (void **) &inner_DD);
662     hr = IDirectDrawSurface4_Initialize(This->parent, inner_DD, DDSD);
663     IDirectDraw_Release(inner_DD);
664     return hr;
665 }
666
667 static HRESULT WINAPI IDirectDrawSurface3Impl_Initialize(IDirectDrawSurface3 *iface,
668         IDirectDraw *DD, DDSURFACEDESC *DDSD)
669 {
670     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
671     DDSURFACEDESC2 ddsd2;
672     TRACE("(%p)->(%p,%p): Thunking to IDirectDrawSurface4\n", This, DD, DDSD);
673     DDSD_to_DDSD2(DDSD, &ddsd2);
674     return IDirectDrawSurface4_Initialize(dds4_from_impl(This), DD, &ddsd2);
675 }
676
677 static HRESULT WINAPI
678 IDirectDrawSurface4Impl_IsLost(IDirectDrawSurface4 *iface)
679 {
680     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
681     TRACE("(%p)\n", This);
682     return IDirectDrawSurface4_IsLost(This->parent);
683 }
684
685 static HRESULT WINAPI IDirectDrawSurface3Impl_IsLost(IDirectDrawSurface3 *iface)
686 {
687     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
688     TRACE("(%p): Thunking to IDirectDrawSurface4\n", This);
689     return IDirectDrawSurface4_IsLost(dds4_from_impl(This));
690 }
691
692 static HRESULT WINAPI
693 IDirectDrawSurface4Impl_Lock(IDirectDrawSurface4 *iface,
694                              RECT *Rect,
695                              DDSURFACEDESC2 *DDSD,
696                              DWORD Flags,
697                              HANDLE h)
698 {
699     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
700     HRESULT hr;
701     TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, Rect, DDSD, Flags, h);
702     hr = IDirectDrawSurface4_Lock(This->parent, Rect, DDSD, Flags, h);
703
704     if(SUCCEEDED(hr) && This->permanent_dc)
705     {
706         DDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
707         DDSD->ddsCaps.dwCaps &= ~DDSCAPS_OWNDC;
708     }
709
710     return hr;
711 }
712
713 static HRESULT WINAPI IDirectDrawSurface3Impl_Lock(IDirectDrawSurface3 *iface, RECT *Rect,
714         DDSURFACEDESC *DDSD, DWORD Flags, HANDLE h)
715 {
716     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
717     DDSURFACEDESC2 ddsd2;
718     HRESULT hr;
719     TRACE("(%p)->(%p,%p,0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, Rect, DDSD, Flags, h);
720     memset(&ddsd2, 0, sizeof(ddsd2));
721     ddsd2.dwSize = sizeof(ddsd2);
722     hr = IDirectDrawSurface4_Lock(dds4_from_impl(This), Rect, &ddsd2, Flags, h);
723     DDSD2_to_DDSD(&ddsd2, DDSD);
724     return hr;
725 }
726
727 static HRESULT WINAPI
728 IDirectDrawSurface4Impl_ReleaseDC(IDirectDrawSurface4 *iface,
729                                   HDC hdc)
730 {
731     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
732     TRACE("(%p)->(%p)\n", This, hdc);
733     if(This->permanent_dc)
734     {
735         TRACE("Surface has a permanent DC, not doing anything\n");
736         return DD_OK;
737     }
738     else
739     {
740         return IDirectDrawSurface4_ReleaseDC(This->parent, hdc);
741     }
742 }
743
744 static HRESULT WINAPI IDirectDrawSurface3Impl_ReleaseDC(IDirectDrawSurface3 *iface, HDC hdc)
745 {
746     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
747     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, hdc);
748     return IDirectDrawSurface4_ReleaseDC(dds4_from_impl(This), hdc);
749 }
750
751 static HRESULT WINAPI
752 IDirectDrawSurface4Impl_Restore(IDirectDrawSurface4 *iface)
753 {
754     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
755     TRACE("(%p)\n", This);
756     return IDirectDrawSurface4_Restore(This->parent);
757 }
758
759 static HRESULT WINAPI IDirectDrawSurface3Impl_Restore(IDirectDrawSurface3 *iface)
760 {
761     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
762     TRACE("(%p): Thunking to IDirectDrawSurface4\n", This);
763     return IDirectDrawSurface4_Restore(dds4_from_impl(This));
764 }
765
766 static HRESULT WINAPI
767 IDirectDrawSurface4Impl_SetClipper(IDirectDrawSurface4 *iface,
768                                    IDirectDrawClipper *Clipper)
769 {
770     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
771     TRACE("(%p)->(%p)\n", This, Clipper);
772     return IDirectDrawSurface4_SetClipper(This->parent, Clipper);
773 }
774
775 static HRESULT WINAPI IDirectDrawSurface3Impl_SetClipper(IDirectDrawSurface3 *iface,
776         IDirectDrawClipper *Clipper)
777 {
778     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
779     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Clipper);
780     return IDirectDrawSurface4_SetClipper(dds4_from_impl(This), Clipper);
781 }
782
783 static HRESULT WINAPI
784 IDirectDrawSurface4Impl_SetColorKey(IDirectDrawSurface4 *iface,
785                                     DWORD Flags,
786                                     DDCOLORKEY *CKey)
787 {
788     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
789     TRACE("(%p)->(0x%08x,%p)\n", This, Flags, CKey);
790     return IDirectDrawSurface4_SetColorKey(This->parent, Flags, CKey);
791 }
792
793 static HRESULT WINAPI IDirectDrawSurface3Impl_SetColorKey(IDirectDrawSurface3 *iface, DWORD Flags,
794         DDCOLORKEY *CKey)
795 {
796     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
797     TRACE("(%p)->(0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, Flags, CKey);
798     return IDirectDrawSurface4_SetColorKey(dds4_from_impl(This), Flags, CKey);
799 }
800
801 static HRESULT WINAPI
802 IDirectDrawSurface4Impl_SetOverlayPosition(IDirectDrawSurface4 *iface,
803                                            LONG X,
804                                            LONG Y)
805 {
806     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
807     TRACE("(%p)->(%u,%u)\n", This, X, Y);
808     return IDirectDrawSurface4_SetOverlayPosition(This->parent, X, Y);
809 }
810
811 static HRESULT WINAPI IDirectDrawSurface3Impl_SetOverlayPosition(IDirectDrawSurface3 *iface,
812         LONG X, LONG Y)
813 {
814     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
815     TRACE("(%p)->(%u,%u): Thunking to IDirectDrawSurface4\n", This, X, Y);
816     return IDirectDrawSurface4_SetOverlayPosition(dds4_from_impl(This), X, Y);
817 }
818
819 static HRESULT WINAPI
820 IDirectDrawSurface4Impl_SetPalette(IDirectDrawSurface4 *iface,
821                                    IDirectDrawPalette *Pal)
822 {
823     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
824     TRACE("(%p)->(%p)\n", This, Pal);
825     return IDirectDrawSurface4_SetPalette(This->parent, Pal);
826 }
827
828 static HRESULT WINAPI IDirectDrawSurface3Impl_SetPalette(IDirectDrawSurface3 *iface,
829         IDirectDrawPalette *Pal)
830 {
831     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
832     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Pal);
833     return IDirectDrawSurface4_SetPalette(dds4_from_impl(This), Pal);
834 }
835
836 static HRESULT WINAPI
837 IDirectDrawSurface4Impl_Unlock(IDirectDrawSurface4 *iface,
838                                RECT *pRect)
839 {
840     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
841     TRACE("(%p)->(%p)\n", This, pRect);
842     return IDirectDrawSurface4_Unlock(This->parent, pRect);
843 }
844
845 static HRESULT WINAPI IDirectDrawSurface3Impl_Unlock(IDirectDrawSurface3 *iface, void *data)
846 {
847     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
848     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, data);
849     return IDirectDrawSurface4_Unlock(dds4_from_impl(This), NULL);
850 }
851
852 static HRESULT WINAPI
853 IDirectDrawSurface4Impl_UpdateOverlay(IDirectDrawSurface4 *iface,
854                                       LPRECT SrcRect,
855                                       IDirectDrawSurface4 *DstSurface,
856                                       LPRECT DstRect,
857                                       DWORD Flags,
858                                       LPDDOVERLAYFX FX)
859 {
860     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
861     IDirectDrawSurfaceImpl *Dst = impl_from_dds4(DstSurface);
862     TRACE("(%p)->(%p,%p,%p,0x%08x,%p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
863     return IDirectDrawSurface4_UpdateOverlay(This->parent, SrcRect, Dst ? Dst->parent : NULL,
864                                              DstRect, Flags, FX);
865 }
866
867 static HRESULT WINAPI IDirectDrawSurface3Impl_UpdateOverlay(IDirectDrawSurface3 *iface,
868         LPRECT SrcRect, IDirectDrawSurface3 *DstSurface, LPRECT DstRect, DWORD Flags,
869         LPDDOVERLAYFX FX)
870 {
871     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
872     IDirectDrawSurfaceImpl *Dst = unsafe_impl_from_IDirectDrawSurface3(DstSurface);
873     TRACE("(%p)->(%p,%p,%p,0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, SrcRect, Dst, DstRect, Flags, FX);
874     return IDirectDrawSurface4_UpdateOverlay(dds4_from_impl(This), SrcRect, dds4_from_impl(Dst),
875                                              DstRect, Flags, FX);
876 }
877
878 static HRESULT WINAPI
879 IDirectDrawSurface4Impl_UpdateOverlayDisplay(IDirectDrawSurface4 *iface,
880                                              DWORD Flags)
881 {
882     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
883     TRACE("(%p)->(0x%08x)\n", This, Flags);
884     return IDirectDrawSurface4_UpdateOverlayDisplay(This->parent, Flags);
885 }
886
887 static HRESULT WINAPI IDirectDrawSurface3Impl_UpdateOverlayDisplay(IDirectDrawSurface3 *iface,
888         DWORD Flags)
889 {
890     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
891     TRACE("(%p)->(0x%08x): Thunking to IDirectDrawSurface4\n", This, Flags);
892     return IDirectDrawSurface4_UpdateOverlayDisplay(dds4_from_impl(This), Flags);
893 }
894
895 static HRESULT WINAPI
896 IDirectDrawSurface4Impl_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
897                                             DWORD Flags,
898                                             IDirectDrawSurface4 *DDSRef)
899 {
900     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
901     IDirectDrawSurfaceImpl *Ref = impl_from_dds4(DDSRef);
902     TRACE("(%p)->(0x%08x,%p)\n", This, Flags, Ref);
903     return IDirectDrawSurface4_UpdateOverlayZOrder(This->parent, Flags, Ref ? Ref->parent : NULL);
904 }
905
906 static HRESULT WINAPI IDirectDrawSurface3Impl_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
907         DWORD Flags, IDirectDrawSurface3 *DDSRef)
908 {
909     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
910     IDirectDrawSurfaceImpl *Ref = unsafe_impl_from_IDirectDrawSurface3(DDSRef);
911     TRACE("(%p)->(0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, Flags, Ref);
912     return IDirectDrawSurface4_UpdateOverlayZOrder(dds4_from_impl(This), Flags, dds4_from_impl(Ref));
913 }
914
915 static HRESULT WINAPI
916 IDirectDrawSurface4Impl_GetDDInterface(IDirectDrawSurface4 *iface,
917                                        void **DD)
918 {
919     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
920     FIXME("(%p)->(%p)\n", This, DD);
921     /* This has to be implemented in ddrawex, DDraw's interface can't be used because it is pretty
922      * hard to tell which version of the DD interface is returned
923      */
924     *DD = NULL;
925     return E_FAIL;
926 }
927
928 static HRESULT WINAPI IDirectDrawSurface3Impl_GetDDInterface(IDirectDrawSurface3 *iface, void **DD)
929 {
930     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
931     FIXME("(%p)->(%p)\n", This, DD);
932     /* A thunk it pretty pointless because of the same reason relaying to ddraw.dll works badly
933      */
934     *DD = NULL;
935     return E_FAIL;
936 }
937
938 static HRESULT WINAPI
939 IDirectDrawSurface4Impl_PageLock(IDirectDrawSurface4 *iface,
940                                  DWORD Flags)
941 {
942     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
943     TRACE("(%p)->(%x)\n", iface, Flags);
944     return IDirectDrawSurface4_PageLock(This->parent, Flags);
945 }
946
947 static HRESULT WINAPI IDirectDrawSurface3Impl_PageLock(IDirectDrawSurface3 *iface, DWORD Flags)
948 {
949     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
950     TRACE("(%p)->(%x): Thunking to IDirectDrawSurface4\n", iface, Flags);
951     return IDirectDrawSurface4_PageLock(dds4_from_impl(This), Flags);
952 }
953
954 static HRESULT WINAPI
955 IDirectDrawSurface4Impl_PageUnlock(IDirectDrawSurface4 *iface,
956                                   DWORD Flags)
957 {
958     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
959     TRACE("(%p)->(%x)\n", iface, Flags);
960     return IDirectDrawSurface4_PageUnlock(This->parent, Flags);
961 }
962
963 static HRESULT WINAPI IDirectDrawSurface3Impl_PageUnlock(IDirectDrawSurface3 *iface, DWORD Flags)
964 {
965     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
966     TRACE("(%p)->(%x): Thunking to IDirectDrawSurface4\n", iface, Flags);
967     return IDirectDrawSurface4_PageUnlock(dds4_from_impl(This), Flags);
968 }
969
970 static HRESULT WINAPI
971 IDirectDrawSurface4Impl_SetSurfaceDesc(IDirectDrawSurface4 *iface,
972                                        DDSURFACEDESC2 *DDSD,
973                                        DWORD Flags)
974 {
975     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
976     TRACE("(%p)->(%p,0x%08x)\n", This, DDSD, Flags);
977     return IDirectDrawSurface4_SetSurfaceDesc(This->parent, DDSD, Flags);
978 }
979
980 static HRESULT WINAPI IDirectDrawSurface3Impl_SetSurfaceDesc(IDirectDrawSurface3 *iface,
981         DDSURFACEDESC *DDSD, DWORD Flags)
982 {
983     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
984     DDSURFACEDESC2 ddsd;
985     TRACE("(%p)->(%p,0x%08x): Thunking to IDirectDrawSurface4\n", This, DDSD, Flags);
986
987     DDSD_to_DDSD2(DDSD, &ddsd);
988     return IDirectDrawSurface4_SetSurfaceDesc(dds4_from_impl(This), &ddsd, Flags);
989 }
990
991 static HRESULT WINAPI
992 IDirectDrawSurface4Impl_SetPrivateData(IDirectDrawSurface4 *iface,
993                                        REFGUID tag,
994                                        void *Data,
995                                        DWORD Size,
996                                        DWORD Flags)
997 {
998     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
999     TRACE("(%p)->(%s,%p,%u,0x%08x)\n", iface, debugstr_guid(tag), Data, Size, Flags);
1000
1001     /* To completely avoid this we'd have to clone the private data API in ddrawex */
1002     if(IsEqualGUID(&IID_DDrawexPriv, tag)) {
1003         FIXME("Application uses ddrawex's private guid\n");
1004     }
1005
1006     return IDirectDrawSurface4_SetPrivateData(This->parent, tag, Data, Size, Flags);
1007 }
1008
1009 static HRESULT WINAPI
1010 IDirectDrawSurface4Impl_GetPrivateData(IDirectDrawSurface4 *iface,
1011                                        REFGUID tag,
1012                                        void *Data,
1013                                        DWORD *Size)
1014 {
1015     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
1016     TRACE("(%p)->(%s,%p,%p)\n", iface, debugstr_guid(tag), Data, Size);
1017
1018     /* To completely avoid this we'd have to clone the private data API in ddrawex */
1019     if(IsEqualGUID(&IID_DDrawexPriv, tag)) {
1020         FIXME("Application uses ddrawex's private guid\n");
1021     }
1022
1023     return IDirectDrawSurface4_GetPrivateData(This->parent, tag, Data, Size);
1024 }
1025
1026 static HRESULT WINAPI
1027 IDirectDrawSurface4Impl_FreePrivateData(IDirectDrawSurface4 *iface,
1028                                         REFGUID tag)
1029 {
1030     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
1031     TRACE("(%p)->(%s)\n", iface, debugstr_guid(tag));
1032
1033     /* To completely avoid this we'd have to clone the private data API in ddrawex */
1034     if(IsEqualGUID(&IID_DDrawexPriv, tag)) {
1035         FIXME("Application uses ddrawex's private guid\n");
1036     }
1037
1038     return IDirectDrawSurface4_FreePrivateData(This->parent, tag);
1039 }
1040
1041 static HRESULT WINAPI
1042 IDirectDrawSurface4Impl_GetUniquenessValue(IDirectDrawSurface4 *iface,
1043                                            LPDWORD pValue)
1044 {
1045     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
1046     TRACE("(%p)->(%p)\n", This, pValue);
1047     return IDirectDrawSurface4_GetUniquenessValue(This->parent, pValue);
1048 }
1049
1050 static HRESULT WINAPI
1051 IDirectDrawSurface4Impl_ChangeUniquenessValue(IDirectDrawSurface4 *iface)
1052 {
1053     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
1054     TRACE("(%p)\n", This);
1055     return IDirectDrawSurface4_ChangeUniquenessValue(This->parent);
1056 }
1057
1058 const IDirectDrawSurface3Vtbl IDirectDrawSurface3_Vtbl =
1059 {
1060     /* IUnknown */
1061     IDirectDrawSurface3Impl_QueryInterface,
1062     IDirectDrawSurface3Impl_AddRef,
1063     IDirectDrawSurface3Impl_Release,
1064     /* IDirectDrawSurface */
1065     IDirectDrawSurface3Impl_AddAttachedSurface,
1066     IDirectDrawSurface3Impl_AddOverlayDirtyRect,
1067     IDirectDrawSurface3Impl_Blt,
1068     IDirectDrawSurface3Impl_BltBatch,
1069     IDirectDrawSurface3Impl_BltFast,
1070     IDirectDrawSurface3Impl_DeleteAttachedSurface,
1071     IDirectDrawSurface3Impl_EnumAttachedSurfaces,
1072     IDirectDrawSurface3Impl_EnumOverlayZOrders,
1073     IDirectDrawSurface3Impl_Flip,
1074     IDirectDrawSurface3Impl_GetAttachedSurface,
1075     IDirectDrawSurface3Impl_GetBltStatus,
1076     IDirectDrawSurface3Impl_GetCaps,
1077     IDirectDrawSurface3Impl_GetClipper,
1078     IDirectDrawSurface3Impl_GetColorKey,
1079     IDirectDrawSurface3Impl_GetDC,
1080     IDirectDrawSurface3Impl_GetFlipStatus,
1081     IDirectDrawSurface3Impl_GetOverlayPosition,
1082     IDirectDrawSurface3Impl_GetPalette,
1083     IDirectDrawSurface3Impl_GetPixelFormat,
1084     IDirectDrawSurface3Impl_GetSurfaceDesc,
1085     IDirectDrawSurface3Impl_Initialize,
1086     IDirectDrawSurface3Impl_IsLost,
1087     IDirectDrawSurface3Impl_Lock,
1088     IDirectDrawSurface3Impl_ReleaseDC,
1089     IDirectDrawSurface3Impl_Restore,
1090     IDirectDrawSurface3Impl_SetClipper,
1091     IDirectDrawSurface3Impl_SetColorKey,
1092     IDirectDrawSurface3Impl_SetOverlayPosition,
1093     IDirectDrawSurface3Impl_SetPalette,
1094     IDirectDrawSurface3Impl_Unlock,
1095     IDirectDrawSurface3Impl_UpdateOverlay,
1096     IDirectDrawSurface3Impl_UpdateOverlayDisplay,
1097     IDirectDrawSurface3Impl_UpdateOverlayZOrder,
1098     /* IDirectDrawSurface 2 */
1099     IDirectDrawSurface3Impl_GetDDInterface,
1100     IDirectDrawSurface3Impl_PageLock,
1101     IDirectDrawSurface3Impl_PageUnlock,
1102     /* IDirectDrawSurface 3 */
1103     IDirectDrawSurface3Impl_SetSurfaceDesc
1104 };
1105
1106 const IDirectDrawSurface4Vtbl IDirectDrawSurface4_Vtbl =
1107 {
1108     /*** IUnknown ***/
1109     IDirectDrawSurface4Impl_QueryInterface,
1110     IDirectDrawSurface4Impl_AddRef,
1111     IDirectDrawSurface4Impl_Release,
1112     /*** IDirectDrawSurface ***/
1113     IDirectDrawSurface4Impl_AddAttachedSurface,
1114     IDirectDrawSurface4Impl_AddOverlayDirtyRect,
1115     IDirectDrawSurface4Impl_Blt,
1116     IDirectDrawSurface4Impl_BltBatch,
1117     IDirectDrawSurface4Impl_BltFast,
1118     IDirectDrawSurface4Impl_DeleteAttachedSurface,
1119     IDirectDrawSurface4Impl_EnumAttachedSurfaces,
1120     IDirectDrawSurface4Impl_EnumOverlayZOrders,
1121     IDirectDrawSurface4Impl_Flip,
1122     IDirectDrawSurface4Impl_GetAttachedSurface,
1123     IDirectDrawSurface4Impl_GetBltStatus,
1124     IDirectDrawSurface4Impl_GetCaps,
1125     IDirectDrawSurface4Impl_GetClipper,
1126     IDirectDrawSurface4Impl_GetColorKey,
1127     IDirectDrawSurface4Impl_GetDC,
1128     IDirectDrawSurface4Impl_GetFlipStatus,
1129     IDirectDrawSurface4Impl_GetOverlayPosition,
1130     IDirectDrawSurface4Impl_GetPalette,
1131     IDirectDrawSurface4Impl_GetPixelFormat,
1132     IDirectDrawSurface4Impl_GetSurfaceDesc,
1133     IDirectDrawSurface4Impl_Initialize,
1134     IDirectDrawSurface4Impl_IsLost,
1135     IDirectDrawSurface4Impl_Lock,
1136     IDirectDrawSurface4Impl_ReleaseDC,
1137     IDirectDrawSurface4Impl_Restore,
1138     IDirectDrawSurface4Impl_SetClipper,
1139     IDirectDrawSurface4Impl_SetColorKey,
1140     IDirectDrawSurface4Impl_SetOverlayPosition,
1141     IDirectDrawSurface4Impl_SetPalette,
1142     IDirectDrawSurface4Impl_Unlock,
1143     IDirectDrawSurface4Impl_UpdateOverlay,
1144     IDirectDrawSurface4Impl_UpdateOverlayDisplay,
1145     IDirectDrawSurface4Impl_UpdateOverlayZOrder,
1146     /*** IDirectDrawSurface2 ***/
1147     IDirectDrawSurface4Impl_GetDDInterface,
1148     IDirectDrawSurface4Impl_PageLock,
1149     IDirectDrawSurface4Impl_PageUnlock,
1150     /*** IDirectDrawSurface3 ***/
1151     IDirectDrawSurface4Impl_SetSurfaceDesc,
1152     /*** IDirectDrawSurface4 ***/
1153     IDirectDrawSurface4Impl_SetPrivateData,
1154     IDirectDrawSurface4Impl_GetPrivateData,
1155     IDirectDrawSurface4Impl_FreePrivateData,
1156     IDirectDrawSurface4Impl_GetUniquenessValue,
1157     IDirectDrawSurface4Impl_ChangeUniquenessValue,
1158 };
1159
1160 static IDirectDrawSurfaceImpl *unsafe_impl_from_IDirectDrawSurface3(IDirectDrawSurface3 *iface)
1161 {
1162     if (!iface) return NULL;
1163     if (iface->lpVtbl != &IDirectDrawSurface3_Vtbl) return NULL;
1164     return CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface3_iface);
1165 }
1166
1167 /* dds_get_outer
1168  *
1169  * Given a surface from ddraw.dll it retrieves the pointer to the ddrawex.dll wrapper around it
1170  *
1171  * Parameters:
1172  *  inner: ddraw.dll surface to retrieve the outer surface from
1173  *
1174  * Returns:
1175  *  The surface wrapper. If there is none yet, a new one is created
1176  */
1177 IDirectDrawSurface4 *dds_get_outer(IDirectDrawSurface4 *inner)
1178 {
1179     IDirectDrawSurface4 *outer = NULL;
1180     DWORD size = sizeof(outer);
1181     HRESULT hr;
1182     if(!inner) return NULL;
1183
1184     hr = IDirectDrawSurface4_GetPrivateData(inner,
1185                                             &IID_DDrawexPriv,
1186                                             &outer,
1187                                             &size);
1188     if(FAILED(hr) || outer == NULL)
1189     {
1190         IDirectDrawSurfaceImpl *impl;
1191
1192         TRACE("Creating new ddrawex surface wrapper for surface %p\n", inner);
1193         impl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*impl));
1194         impl->ref = 1;
1195         impl->IDirectDrawSurface3_iface.lpVtbl = &IDirectDrawSurface3_Vtbl;
1196         impl->IDirectDrawSurface4_Vtbl = &IDirectDrawSurface4_Vtbl;
1197         IDirectDrawSurface4_AddRef(inner);
1198         impl->parent = inner;
1199
1200         outer = dds4_from_impl(impl);
1201
1202         hr = IDirectDrawSurface4_SetPrivateData(inner,
1203                                                 &IID_DDrawexPriv,
1204                                                 &outer,
1205                                                 sizeof(outer),
1206                                                 0 /* Flags */);
1207         if(FAILED(hr))
1208         {
1209             ERR("IDirectDrawSurface4_SetPrivateData failed\n");
1210         }
1211     }
1212
1213     return outer;
1214 }
1215
1216 IDirectDrawSurface4 *dds_get_inner(IDirectDrawSurface4 *outer)
1217 {
1218     IDirectDrawSurfaceImpl *This = impl_from_dds4(outer);
1219     if(This == NULL) return NULL;
1220     return This->parent;
1221 }
1222
1223 HRESULT prepare_permanent_dc(IDirectDrawSurface4 *iface)
1224 {
1225     IDirectDrawSurfaceImpl *This = impl_from_dds4(iface);
1226     HRESULT hr;
1227     This->permanent_dc = TRUE;
1228
1229     hr = IDirectDrawSurface4_GetDC(This->parent, &This->hdc);
1230     if(FAILED(hr)) return hr;
1231     hr = IDirectDrawSurface4_ReleaseDC(This->parent, This->hdc);
1232     return hr;
1233 }