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