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