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