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