wmiutils: Implement IWbemPath::GetNamespaceAt.
[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 CONTAINING_RECORD(iface, IDirectDrawSurfaceImpl, IDirectDrawSurface4_iface);
46 }
47
48 static HRESULT WINAPI IDirectDrawSurface4Impl_QueryInterface(IDirectDrawSurface4 *iface,
49         REFIID riid, void **obj)
50 {
51     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
52
53     *obj = NULL;
54
55     if(!riid)
56         return DDERR_INVALIDPARAMS;
57
58     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),obj);
59     if (IsEqualGUID(riid, &IID_IUnknown)
60      || IsEqualGUID(riid, &IID_IDirectDrawSurface4) )
61     {
62         *obj = &This->IDirectDrawSurface4_iface;
63         IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
64         TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj);
65         return S_OK;
66     }
67     else if( IsEqualGUID(riid, &IID_IDirectDrawSurface3)
68           || IsEqualGUID(riid, &IID_IDirectDrawSurface2)
69           || IsEqualGUID(riid, &IID_IDirectDrawSurface) )
70     {
71         *obj = &This->IDirectDrawSurface3_iface;
72         IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
73         TRACE("(%p) returning IDirectDrawSurface3 interface at %p\n", This, *obj);
74         return S_OK;
75     }
76     else if( IsEqualGUID(riid, &IID_IDirectDrawGammaControl) )
77     {
78         FIXME("Implement IDirectDrawGammaControl in ddrawex\n");
79     }
80     else if( IsEqualGUID(riid, &IID_IDirect3DHALDevice)||
81              IsEqualGUID(riid, &IID_IDirect3DRGBDevice) )
82     {
83         /* Most likely not supported */
84         FIXME("Test IDirect3DDevice in ddrawex\n");
85     }
86     else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
87              IsEqualGUID( &IID_IDirect3DTexture2, riid ))
88     {
89         FIXME("Implement IDirect3dTexture in ddrawex\n");
90     }
91     else
92     {
93         WARN("No interface\n");
94     }
95
96     return E_NOINTERFACE;
97 }
98
99 static HRESULT WINAPI IDirectDrawSurface3Impl_QueryInterface(IDirectDrawSurface3 *iface,
100         REFIID riid, void **obj)
101 {
102     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
103     TRACE("(%p)->(%s,%p): Thunking to IDirectDrawSurface4\n",This,debugstr_guid(riid),obj);
104     return IDirectDrawSurface4_QueryInterface(&This->IDirectDrawSurface4_iface, riid, obj);
105 }
106
107 static ULONG WINAPI IDirectDrawSurface4Impl_AddRef(IDirectDrawSurface4 *iface)
108 {
109     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
110     ULONG ref = InterlockedIncrement(&This->ref);
111
112     TRACE("(%p) : incrementing refcount from %u.\n", This, ref - 1);
113
114     return ref;
115 }
116
117 static ULONG WINAPI IDirectDrawSurface3Impl_AddRef(IDirectDrawSurface3 *iface)
118 {
119     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
120     TRACE("(%p): Thunking to IDirectDrawSurface4\n", This);
121     return IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface);
122 }
123
124 static ULONG WINAPI IDirectDrawSurface4Impl_Release(IDirectDrawSurface4 *iface)
125 {
126     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
127     ULONG ref = InterlockedDecrement(&This->ref);
128
129     TRACE("(%p) : decrementing refcount to %u.\n", This, ref);
130
131     if(ref == 0)
132     {
133         TRACE("Destroying object\n");
134         IDirectDrawSurface4_FreePrivateData(This->parent, &IID_DDrawexPriv);
135         IDirectDrawSurface4_Release(This->parent);
136         HeapFree(GetProcessHeap(), 0, This);
137     }
138     return ref;
139 }
140
141 static ULONG WINAPI IDirectDrawSurface3Impl_Release(IDirectDrawSurface3 *iface)
142 {
143     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
144     TRACE("(%p): Thunking to IDirectDrawSurface4\n", This);
145     return IDirectDrawSurface4_Release(&This->IDirectDrawSurface4_iface);
146 }
147
148 static HRESULT WINAPI IDirectDrawSurface4Impl_AddAttachedSurface(IDirectDrawSurface4 *iface,
149         IDirectDrawSurface4 *Attach_iface)
150 {
151     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
152     IDirectDrawSurfaceImpl *attach = unsafe_impl_from_IDirectDrawSurface4(Attach_iface);
153     TRACE("(%p)->(%p)\n", This, attach);
154     return IDirectDrawSurface4_AddAttachedSurface(This->parent, attach->parent);
155 }
156
157 static HRESULT WINAPI IDirectDrawSurface3Impl_AddAttachedSurface(IDirectDrawSurface3 *iface,
158         IDirectDrawSurface3 *Attach_iface)
159 {
160     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
161     IDirectDrawSurfaceImpl *attach = unsafe_impl_from_IDirectDrawSurface3(Attach_iface);
162     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, attach);
163     return IDirectDrawSurface4_AddAttachedSurface(&This->IDirectDrawSurface4_iface,
164             attach ? &attach->IDirectDrawSurface4_iface : NULL);
165 }
166
167 static HRESULT WINAPI IDirectDrawSurface4Impl_AddOverlayDirtyRect(IDirectDrawSurface4 *iface,
168         RECT *Rect)
169 {
170     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
171     TRACE("(%p)->(%p)\n", This, Rect);
172     return IDirectDrawSurface4_AddOverlayDirtyRect(This->parent, Rect);
173 }
174
175 static HRESULT WINAPI IDirectDrawSurface3Impl_AddOverlayDirtyRect(IDirectDrawSurface3 *iface,
176         RECT *Rect)
177 {
178     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
179     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Rect);
180     return IDirectDrawSurface4_AddOverlayDirtyRect(&This->IDirectDrawSurface4_iface, Rect);
181 }
182
183 static HRESULT WINAPI IDirectDrawSurface4Impl_Blt(IDirectDrawSurface4 *iface, RECT *DestRect,
184         IDirectDrawSurface4 *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx)
185 {
186     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
187     IDirectDrawSurfaceImpl *Src = unsafe_impl_from_IDirectDrawSurface4(SrcSurface);
188     TRACE("(%p)->(%p,%p,%p,0x%08x,%p)\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
189     return IDirectDrawSurface4_Blt(This->parent, DestRect, Src ? Src->parent : NULL,
190                                    SrcRect, Flags, DDBltFx);
191 }
192
193 static HRESULT WINAPI IDirectDrawSurface3Impl_Blt(IDirectDrawSurface3 *iface, RECT *DestRect,
194         IDirectDrawSurface3 *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx)
195 {
196     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
197     IDirectDrawSurfaceImpl *Src = unsafe_impl_from_IDirectDrawSurface3(SrcSurface);
198     TRACE("(%p)->(%p,%p,%p,0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
199     return IDirectDrawSurface4_Blt(&This->IDirectDrawSurface4_iface, DestRect,
200             Src ? &Src->IDirectDrawSurface4_iface : NULL, SrcRect, Flags, DDBltFx);
201 }
202
203 static HRESULT WINAPI IDirectDrawSurface4Impl_BltBatch(IDirectDrawSurface4 *iface,
204         DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
205 {
206     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
207     TRACE("(%p)->(%p,%u,0x%08x)\n", This, Batch, Count, Flags);
208     return IDirectDrawSurface4_BltBatch(This->parent, Batch, Count, Flags);
209 }
210
211 static HRESULT WINAPI IDirectDrawSurface3Impl_BltBatch(IDirectDrawSurface3 *iface,
212         DDBLTBATCH *Batch, DWORD Count, DWORD Flags)
213 {
214     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
215     TRACE("(%p)->(%p,%u,0x%08x): Thunking to IDirectDrawSurface4\n", This, Batch, Count, Flags);
216     return IDirectDrawSurface4_BltBatch(&This->IDirectDrawSurface4_iface, Batch, Count, Flags);
217 }
218
219 static HRESULT WINAPI IDirectDrawSurface4Impl_BltFast(IDirectDrawSurface4 *iface, DWORD dstx,
220         DWORD dsty, IDirectDrawSurface4 *Source, RECT *rsrc, DWORD trans)
221 {
222     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
223     IDirectDrawSurfaceImpl *Src = unsafe_impl_from_IDirectDrawSurface4(Source);
224     TRACE("(%p)->(%u,%u,%p,%p,0x%08x)\n", This, dstx, dsty, Src, rsrc, trans);
225     return IDirectDrawSurface4_BltFast(This->parent, dstx, dsty, Src ? Src->parent : NULL,
226                                        rsrc, trans);
227 }
228
229 static HRESULT WINAPI IDirectDrawSurface3Impl_BltFast(IDirectDrawSurface3 *iface, DWORD dstx,
230         DWORD dsty, IDirectDrawSurface3 *Source, RECT *rsrc, DWORD trans)
231 {
232     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
233     IDirectDrawSurfaceImpl *Src = unsafe_impl_from_IDirectDrawSurface3(Source);
234     TRACE("(%p)->(%u,%u,%p,%p,0x%08x): Thunking to IDirectDrawSurface4\n", This, dstx, dsty, Src, rsrc, trans);
235     return IDirectDrawSurface4_BltFast(&This->IDirectDrawSurface4_iface, dstx, dsty,
236             Src ? &Src->IDirectDrawSurface4_iface : NULL, rsrc, trans);
237 }
238
239 static HRESULT WINAPI IDirectDrawSurface4Impl_DeleteAttachedSurface(IDirectDrawSurface4 *iface,
240         DWORD Flags, IDirectDrawSurface4 *Attach)
241 {
242     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
243     IDirectDrawSurfaceImpl *Att = unsafe_impl_from_IDirectDrawSurface4(Attach);
244     TRACE("(%p)->(0x%08x,%p)\n", This, Flags, Att);
245     return IDirectDrawSurface4_DeleteAttachedSurface(This->parent, Flags,
246                                                      Att ? Att->parent : NULL);
247 }
248
249 static HRESULT WINAPI IDirectDrawSurface3Impl_DeleteAttachedSurface(IDirectDrawSurface3 *iface,
250         DWORD Flags, IDirectDrawSurface3 *Attach)
251 {
252     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
253     IDirectDrawSurfaceImpl *Att = unsafe_impl_from_IDirectDrawSurface3(Attach);
254     TRACE("(%p)->(0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, Flags, Att);
255     return IDirectDrawSurface4_DeleteAttachedSurface(&This->IDirectDrawSurface4_iface, Flags,
256             Att ? &Att->IDirectDrawSurface4_iface : NULL);
257 }
258
259 struct enumsurfaces_wrap
260 {
261     LPDDENUMSURFACESCALLBACK2 orig_cb;
262     void *orig_ctx;
263 };
264
265 static HRESULT WINAPI
266 enumsurfaces_wrap_cb(IDirectDrawSurface4 *surf, DDSURFACEDESC2 *desc, void *vctx)
267 {
268     struct enumsurfaces_wrap *ctx = vctx;
269     IDirectDrawSurface4 *outer = dds_get_outer(surf);
270
271     TRACE("Returning outer surface %p for inner surface %p\n", outer, surf);
272     IDirectDrawSurface4_AddRef(outer);
273     IDirectDrawSurface4_Release(surf);
274     return ctx->orig_cb(outer, desc, vctx);
275 }
276
277 static HRESULT WINAPI IDirectDrawSurface4Impl_EnumAttachedSurfaces(IDirectDrawSurface4 *iface,
278         void *context, LPDDENUMSURFACESCALLBACK2 cb)
279 {
280     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
281     struct enumsurfaces_wrap ctx;
282     TRACE("(%p)->(%p,%p)\n", This, context, cb);
283
284     ctx.orig_cb = cb;
285     ctx.orig_ctx = context;
286     return IDirectDrawSurface4_EnumAttachedSurfaces(This->parent, &ctx, enumsurfaces_wrap_cb);
287 }
288
289 struct enumsurfaces_thunk
290 {
291     LPDDENUMSURFACESCALLBACK orig_cb;
292     void *orig_ctx;
293 };
294
295 static HRESULT WINAPI enumsurfaces_thunk_cb(IDirectDrawSurface4 *surf, DDSURFACEDESC2 *desc2,
296         void *vctx)
297 {
298     IDirectDrawSurfaceImpl *This = unsafe_impl_from_IDirectDrawSurface4(surf);
299     struct enumsurfaces_thunk *ctx = vctx;
300     DDSURFACEDESC desc;
301
302     TRACE("Thunking back to IDirectDrawSurface3\n");
303     IDirectDrawSurface3_AddRef(&This->IDirectDrawSurface3_iface);
304     IDirectDrawSurface3_Release(surf);
305     DDSD2_to_DDSD(desc2, &desc);
306     return ctx->orig_cb((IDirectDrawSurface *)&This->IDirectDrawSurface3_iface, &desc,
307             ctx->orig_ctx);
308 }
309
310 static HRESULT WINAPI IDirectDrawSurface3Impl_EnumAttachedSurfaces(IDirectDrawSurface3 *iface,
311         void *context, LPDDENUMSURFACESCALLBACK cb)
312 {
313     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
314     struct enumsurfaces_thunk ctx;
315     TRACE("(%p)->(%p,%p): Thunking to IDirectDraw4\n", This, context, cb);
316
317     ctx.orig_cb = cb;
318     ctx.orig_ctx = context;
319     return IDirectDrawSurface4_EnumAttachedSurfaces(&This->IDirectDrawSurface4_iface, &ctx,
320             enumsurfaces_thunk_cb);
321 }
322
323 static HRESULT WINAPI IDirectDrawSurface4Impl_EnumOverlayZOrders(IDirectDrawSurface4 *iface,
324         DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK2 cb)
325 {
326     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
327     struct enumsurfaces_wrap ctx;
328     TRACE("(%p)->(0x%08x,%p,%p)\n", This, Flags, context, cb);
329
330     ctx.orig_cb = cb;
331     ctx.orig_ctx = context;
332     return IDirectDrawSurface4_EnumOverlayZOrders(This->parent, Flags, &ctx, enumsurfaces_wrap_cb);
333 }
334
335 static HRESULT WINAPI IDirectDrawSurface3Impl_EnumOverlayZOrders(IDirectDrawSurface3 *iface,
336         DWORD Flags, void *context, LPDDENUMSURFACESCALLBACK cb)
337 {
338     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
339     struct enumsurfaces_thunk ctx;
340     TRACE("(%p)->(0x%08x,%p,%p): Thunking to IDirectDraw4\n", This, Flags, context, cb);
341
342     ctx.orig_cb = cb;
343     ctx.orig_ctx = context;
344     return IDirectDrawSurface4_EnumOverlayZOrders(&This->IDirectDrawSurface4_iface, Flags, &ctx,
345             enumsurfaces_thunk_cb);
346 }
347
348 static HRESULT WINAPI IDirectDrawSurface4Impl_Flip(IDirectDrawSurface4 *iface,
349         IDirectDrawSurface4 *DestOverride, DWORD Flags)
350 {
351     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
352     IDirectDrawSurfaceImpl *Dest = unsafe_impl_from_IDirectDrawSurface4(DestOverride);
353     TRACE("(%p)->(%p,0x%08x)\n", This, Dest, Flags);
354     return IDirectDrawSurface4_Flip(This->parent, Dest ? Dest->parent : NULL, Flags);
355 }
356
357 static HRESULT WINAPI IDirectDrawSurface3Impl_Flip(IDirectDrawSurface3 *iface,
358         IDirectDrawSurface3 *DestOverride, DWORD Flags)
359 {
360     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
361     IDirectDrawSurfaceImpl *Dest = unsafe_impl_from_IDirectDrawSurface3(DestOverride);
362     TRACE("(%p)->(%p,0x%08x): Thunking to IDirectDrawSurface4\n", This, Dest, Flags);
363     return IDirectDrawSurface4_Flip(&This->IDirectDrawSurface4_iface,
364             Dest ? &Dest->IDirectDrawSurface4_iface : NULL, Flags);
365 }
366
367 static HRESULT WINAPI IDirectDrawSurface4Impl_GetAttachedSurface(IDirectDrawSurface4 *iface,
368         DDSCAPS2 *Caps, IDirectDrawSurface4 **Surface)
369 {
370     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
371     IDirectDrawSurface4 *inner = NULL;
372     HRESULT hr;
373     TRACE("(%p)->(%p,%p)\n", This, Caps, Surface);
374
375     hr = IDirectDrawSurface4_GetAttachedSurface(This->parent, Caps, &inner);
376     if(SUCCEEDED(hr))
377     {
378         *Surface = dds_get_outer(inner);
379         IDirectDrawSurface4_AddRef(*Surface);
380         IDirectDrawSurface4_Release(inner);
381     }
382     else
383     {
384         *Surface = NULL;
385     }
386     return hr;
387 }
388
389 static HRESULT WINAPI IDirectDrawSurface3Impl_GetAttachedSurface(IDirectDrawSurface3 *iface,
390         DDSCAPS *Caps, IDirectDrawSurface3 **Surface)
391 {
392     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
393     IDirectDrawSurface4 *surf4;
394     DDSCAPS2 caps2;
395     HRESULT hr;
396     TRACE("(%p)->(%p,%p): Thunking to IDirectDrawSurface4\n", This, Caps, Surface);
397
398     memset(&caps2, 0, sizeof(caps2));
399     caps2.dwCaps = Caps->dwCaps;
400     hr = IDirectDrawSurface4_GetAttachedSurface(&This->IDirectDrawSurface4_iface, &caps2, &surf4);
401     if(SUCCEEDED(hr))
402     {
403         IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface3, (void **) Surface);
404         IDirectDrawSurface4_Release(surf4);
405     }
406     else
407     {
408         *Surface = NULL;
409     }
410     return hr;
411 }
412
413 static HRESULT WINAPI IDirectDrawSurface4Impl_GetBltStatus(IDirectDrawSurface4 *iface, DWORD Flags)
414 {
415     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
416     TRACE("(%p)->(0x%08x)\n", This, Flags);
417     return IDirectDrawSurface4_GetBltStatus(This->parent, Flags);
418 }
419
420 static HRESULT WINAPI IDirectDrawSurface3Impl_GetBltStatus(IDirectDrawSurface3 *iface, DWORD Flags)
421 {
422     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
423     TRACE("(%p)->(0x%08x): Thunking to IDirectDrawSurface4\n", This, Flags);
424     return IDirectDrawSurface4_GetBltStatus(&This->IDirectDrawSurface4_iface, Flags);
425 }
426
427 static HRESULT WINAPI IDirectDrawSurface4Impl_GetCaps(IDirectDrawSurface4 *iface, DDSCAPS2 *Caps)
428 {
429     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
430     TRACE("(%p)->(%p)\n", This, Caps);
431     return IDirectDrawSurface4_GetCaps(This->parent, Caps);
432 }
433
434 static HRESULT WINAPI IDirectDrawSurface3Impl_GetCaps(IDirectDrawSurface3 *iface, DDSCAPS *Caps)
435 {
436     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
437     DDSCAPS2 caps2;
438     HRESULT hr;
439     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Caps);
440
441     memset(&caps2, 0, sizeof(caps2));
442     memset(Caps, 0, sizeof(*Caps));
443     hr = IDirectDrawSurface4_GetCaps(&This->IDirectDrawSurface4_iface, &caps2);
444     Caps->dwCaps = caps2.dwCaps;
445     return hr;
446 }
447
448 static HRESULT WINAPI IDirectDrawSurface4Impl_GetClipper(IDirectDrawSurface4 *iface,
449         IDirectDrawClipper **Clipper)
450 {
451     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
452     TRACE("(%p)->(%p)\n", This, Clipper);
453     return IDirectDrawSurface4_GetClipper(This->parent, Clipper);
454 }
455
456 static HRESULT WINAPI IDirectDrawSurface3Impl_GetClipper(IDirectDrawSurface3 *iface,
457         IDirectDrawClipper **Clipper)
458 {
459     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
460     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Clipper);
461     return IDirectDrawSurface4_GetClipper(&This->IDirectDrawSurface4_iface, Clipper);
462 }
463
464 static HRESULT WINAPI IDirectDrawSurface4Impl_GetColorKey(IDirectDrawSurface4 *iface, DWORD Flags,
465         DDCOLORKEY *CKey)
466 {
467     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
468     TRACE("(%p)->(0x%08x,%p)\n", This, Flags, CKey);
469     return IDirectDrawSurface4_GetColorKey(This->parent, Flags, CKey);
470 }
471
472 static HRESULT WINAPI IDirectDrawSurface3Impl_GetColorKey(IDirectDrawSurface3 *iface, DWORD Flags,
473         DDCOLORKEY *CKey)
474 {
475     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
476     TRACE("(%p)->(0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, Flags, CKey);
477     return IDirectDrawSurface4_GetColorKey(&This->IDirectDrawSurface4_iface, Flags, CKey);
478 }
479
480 static HRESULT WINAPI IDirectDrawSurface4Impl_GetDC(IDirectDrawSurface4 *iface, HDC *hdc)
481 {
482     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
483     TRACE("(%p)->(%p)\n", This, hdc);
484     if(This->permanent_dc)
485     {
486         TRACE("Returning stored dc %p\n", This->hdc);
487         *hdc = This->hdc;
488         return DD_OK;
489     }
490     else
491     {
492         return IDirectDrawSurface4_GetDC(This->parent, hdc);
493     }
494 }
495
496 static HRESULT WINAPI IDirectDrawSurface3Impl_GetDC(IDirectDrawSurface3 *iface, HDC *hdc)
497 {
498     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
499     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, hdc);
500     return IDirectDrawSurface4_GetDC(&This->IDirectDrawSurface4_iface, hdc);
501 }
502
503 static HRESULT WINAPI IDirectDrawSurface4Impl_GetFlipStatus(IDirectDrawSurface4 *iface, DWORD Flags)
504 {
505     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
506     TRACE("(%p)->(0x%08x)\n", This, Flags);
507     return IDirectDrawSurface4_GetFlipStatus(This->parent, Flags);
508 }
509
510 static HRESULT WINAPI IDirectDrawSurface3Impl_GetFlipStatus(IDirectDrawSurface3 *iface, DWORD Flags)
511 {
512     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
513     TRACE("(%p)->(0x%08x): Thunking to IDirectDrawSurface4\n", This, Flags);
514     return IDirectDrawSurface4_GetFlipStatus(&This->IDirectDrawSurface4_iface, Flags);
515 }
516
517 static HRESULT WINAPI IDirectDrawSurface4Impl_GetOverlayPosition(IDirectDrawSurface4 *iface,
518         LONG *X, LONG *Y)
519 {
520     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
521     TRACE("(%p)->(%p,%p)\n", This, X, Y);
522     return IDirectDrawSurface4_GetOverlayPosition(This->parent, X, Y);
523 }
524
525 static HRESULT WINAPI IDirectDrawSurface3Impl_GetOverlayPosition(IDirectDrawSurface3 *iface,
526         LONG *X, LONG *Y)
527 {
528     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
529     TRACE("(%p)->(%p,%p): Thunking to IDirectDrawSurface4\n", This, X, Y);
530     return IDirectDrawSurface4_GetOverlayPosition(&This->IDirectDrawSurface4_iface, X, Y);
531 }
532
533 static HRESULT WINAPI IDirectDrawSurface4Impl_GetPalette(IDirectDrawSurface4 *iface,
534         IDirectDrawPalette **Pal)
535 {
536     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
537     TRACE("(%p)->(%p)\n", This, Pal);
538     return IDirectDrawSurface4_GetPalette(This->parent, Pal);
539 }
540
541 static HRESULT WINAPI IDirectDrawSurface3Impl_GetPalette(IDirectDrawSurface3 *iface,
542         IDirectDrawPalette **Pal)
543 {
544     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
545     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Pal);
546     return IDirectDrawSurface4_GetPalette(&This->IDirectDrawSurface4_iface, Pal);
547 }
548
549 static HRESULT WINAPI IDirectDrawSurface4Impl_GetPixelFormat(IDirectDrawSurface4 *iface,
550         DDPIXELFORMAT *PixelFormat)
551 {
552     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
553     TRACE("(%p)->(%p)\n", This, PixelFormat);
554     return IDirectDrawSurface4_GetPixelFormat(This->parent, PixelFormat);
555 }
556
557 static HRESULT WINAPI IDirectDrawSurface3Impl_GetPixelFormat(IDirectDrawSurface3 *iface,
558         DDPIXELFORMAT *PixelFormat)
559 {
560     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
561     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, PixelFormat);
562     return IDirectDrawSurface4_GetPixelFormat(&This->IDirectDrawSurface4_iface, PixelFormat);
563 }
564
565 static HRESULT WINAPI IDirectDrawSurface4Impl_GetSurfaceDesc(IDirectDrawSurface4 *iface,
566         DDSURFACEDESC2 *DDSD)
567 {
568     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
569     HRESULT hr;
570     TRACE("(%p)->(%p)\n", This, DDSD);
571     hr = IDirectDrawSurface4_GetSurfaceDesc(This->parent, DDSD);
572
573     if(SUCCEEDED(hr) && This->permanent_dc)
574     {
575         DDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
576         DDSD->ddsCaps.dwCaps &= ~DDSCAPS_OWNDC;
577     }
578
579     return hr;
580 }
581
582 static HRESULT WINAPI IDirectDrawSurface3Impl_GetSurfaceDesc(IDirectDrawSurface3 *iface,
583         DDSURFACEDESC *DDSD)
584 {
585     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
586     DDSURFACEDESC2 ddsd2;
587     HRESULT hr;
588     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, DDSD);
589
590     memset(&ddsd2, 0, sizeof(ddsd2));
591     ddsd2.dwSize = sizeof(ddsd2);
592     hr = IDirectDrawSurface4_GetSurfaceDesc(&This->IDirectDrawSurface4_iface, &ddsd2);
593     DDSD2_to_DDSD(&ddsd2, DDSD);
594     return hr;
595 }
596
597 static HRESULT WINAPI IDirectDrawSurface4Impl_Initialize(IDirectDrawSurface4 *iface,
598         IDirectDraw *DD, DDSURFACEDESC2 *DDSD)
599 {
600     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
601     IDirectDraw4 *outer_DD4;
602     IDirectDraw4 *inner_DD4;
603     IDirectDraw *inner_DD;
604     HRESULT hr;
605     TRACE("(%p)->(%p,%p)\n", This, DD, DDSD);
606
607     IDirectDraw_QueryInterface(DD, &IID_IDirectDraw4, (void **) &outer_DD4);
608     inner_DD4 = dd_get_inner(outer_DD4);
609     IDirectDraw4_Release(outer_DD4);
610     IDirectDraw4_QueryInterface(inner_DD4, &IID_IDirectDraw4, (void **) &inner_DD);
611     hr = IDirectDrawSurface4_Initialize(This->parent, inner_DD, DDSD);
612     IDirectDraw_Release(inner_DD);
613     return hr;
614 }
615
616 static HRESULT WINAPI IDirectDrawSurface3Impl_Initialize(IDirectDrawSurface3 *iface,
617         IDirectDraw *DD, DDSURFACEDESC *DDSD)
618 {
619     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
620     DDSURFACEDESC2 ddsd2;
621     TRACE("(%p)->(%p,%p): Thunking to IDirectDrawSurface4\n", This, DD, DDSD);
622     DDSD_to_DDSD2(DDSD, &ddsd2);
623     return IDirectDrawSurface4_Initialize(&This->IDirectDrawSurface4_iface, DD, &ddsd2);
624 }
625
626 static HRESULT WINAPI IDirectDrawSurface4Impl_IsLost(IDirectDrawSurface4 *iface)
627 {
628     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
629     TRACE("(%p)\n", This);
630     return IDirectDrawSurface4_IsLost(This->parent);
631 }
632
633 static HRESULT WINAPI IDirectDrawSurface3Impl_IsLost(IDirectDrawSurface3 *iface)
634 {
635     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
636     TRACE("(%p): Thunking to IDirectDrawSurface4\n", This);
637     return IDirectDrawSurface4_IsLost(&This->IDirectDrawSurface4_iface);
638 }
639
640 static HRESULT WINAPI IDirectDrawSurface4Impl_Lock(IDirectDrawSurface4 *iface, RECT *Rect,
641         DDSURFACEDESC2 *DDSD, DWORD Flags, HANDLE h)
642 {
643     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
644     HRESULT hr;
645     TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, Rect, DDSD, Flags, h);
646     hr = IDirectDrawSurface4_Lock(This->parent, Rect, DDSD, Flags, h);
647
648     if(SUCCEEDED(hr) && This->permanent_dc)
649     {
650         DDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
651         DDSD->ddsCaps.dwCaps &= ~DDSCAPS_OWNDC;
652     }
653
654     return hr;
655 }
656
657 static HRESULT WINAPI IDirectDrawSurface3Impl_Lock(IDirectDrawSurface3 *iface, RECT *Rect,
658         DDSURFACEDESC *DDSD, DWORD Flags, HANDLE h)
659 {
660     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
661     DDSURFACEDESC2 ddsd2;
662     HRESULT hr;
663     TRACE("(%p)->(%p,%p,0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, Rect, DDSD, Flags, h);
664     memset(&ddsd2, 0, sizeof(ddsd2));
665     ddsd2.dwSize = sizeof(ddsd2);
666     hr = IDirectDrawSurface4_Lock(&This->IDirectDrawSurface4_iface, Rect, &ddsd2, Flags, h);
667     DDSD2_to_DDSD(&ddsd2, DDSD);
668     return hr;
669 }
670
671 static HRESULT WINAPI IDirectDrawSurface4Impl_ReleaseDC(IDirectDrawSurface4 *iface, HDC hdc)
672 {
673     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
674     TRACE("(%p)->(%p)\n", This, hdc);
675     if(This->permanent_dc)
676     {
677         TRACE("Surface has a permanent DC, not doing anything\n");
678         return DD_OK;
679     }
680     else
681     {
682         return IDirectDrawSurface4_ReleaseDC(This->parent, hdc);
683     }
684 }
685
686 static HRESULT WINAPI IDirectDrawSurface3Impl_ReleaseDC(IDirectDrawSurface3 *iface, HDC hdc)
687 {
688     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
689     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, hdc);
690     return IDirectDrawSurface4_ReleaseDC(&This->IDirectDrawSurface4_iface, hdc);
691 }
692
693 static HRESULT WINAPI IDirectDrawSurface4Impl_Restore(IDirectDrawSurface4 *iface)
694 {
695     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
696     TRACE("(%p)\n", This);
697     return IDirectDrawSurface4_Restore(This->parent);
698 }
699
700 static HRESULT WINAPI IDirectDrawSurface3Impl_Restore(IDirectDrawSurface3 *iface)
701 {
702     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
703     TRACE("(%p): Thunking to IDirectDrawSurface4\n", This);
704     return IDirectDrawSurface4_Restore(&This->IDirectDrawSurface4_iface);
705 }
706
707 static HRESULT WINAPI IDirectDrawSurface4Impl_SetClipper(IDirectDrawSurface4 *iface,
708         IDirectDrawClipper *Clipper)
709 {
710     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
711     TRACE("(%p)->(%p)\n", This, Clipper);
712     return IDirectDrawSurface4_SetClipper(This->parent, Clipper);
713 }
714
715 static HRESULT WINAPI IDirectDrawSurface3Impl_SetClipper(IDirectDrawSurface3 *iface,
716         IDirectDrawClipper *Clipper)
717 {
718     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
719     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Clipper);
720     return IDirectDrawSurface4_SetClipper(&This->IDirectDrawSurface4_iface, Clipper);
721 }
722
723 static HRESULT WINAPI IDirectDrawSurface4Impl_SetColorKey(IDirectDrawSurface4 *iface, DWORD Flags,
724         DDCOLORKEY *CKey)
725 {
726     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
727     TRACE("(%p)->(0x%08x,%p)\n", This, Flags, CKey);
728     return IDirectDrawSurface4_SetColorKey(This->parent, Flags, CKey);
729 }
730
731 static HRESULT WINAPI IDirectDrawSurface3Impl_SetColorKey(IDirectDrawSurface3 *iface, DWORD Flags,
732         DDCOLORKEY *CKey)
733 {
734     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
735     TRACE("(%p)->(0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, Flags, CKey);
736     return IDirectDrawSurface4_SetColorKey(&This->IDirectDrawSurface4_iface, Flags, CKey);
737 }
738
739 static HRESULT WINAPI IDirectDrawSurface4Impl_SetOverlayPosition(IDirectDrawSurface4 *iface,
740         LONG X, LONG Y)
741 {
742     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
743     TRACE("(%p)->(%u,%u)\n", This, X, Y);
744     return IDirectDrawSurface4_SetOverlayPosition(This->parent, X, Y);
745 }
746
747 static HRESULT WINAPI IDirectDrawSurface3Impl_SetOverlayPosition(IDirectDrawSurface3 *iface,
748         LONG X, LONG Y)
749 {
750     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
751     TRACE("(%p)->(%u,%u): Thunking to IDirectDrawSurface4\n", This, X, Y);
752     return IDirectDrawSurface4_SetOverlayPosition(&This->IDirectDrawSurface4_iface, X, Y);
753 }
754
755 static HRESULT WINAPI IDirectDrawSurface4Impl_SetPalette(IDirectDrawSurface4 *iface,
756         IDirectDrawPalette *Pal)
757 {
758     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
759     TRACE("(%p)->(%p)\n", This, Pal);
760     return IDirectDrawSurface4_SetPalette(This->parent, Pal);
761 }
762
763 static HRESULT WINAPI IDirectDrawSurface3Impl_SetPalette(IDirectDrawSurface3 *iface,
764         IDirectDrawPalette *Pal)
765 {
766     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
767     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, Pal);
768     return IDirectDrawSurface4_SetPalette(&This->IDirectDrawSurface4_iface, Pal);
769 }
770
771 static HRESULT WINAPI IDirectDrawSurface4Impl_Unlock(IDirectDrawSurface4 *iface, RECT *pRect)
772 {
773     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
774     TRACE("(%p)->(%p)\n", This, pRect);
775     return IDirectDrawSurface4_Unlock(This->parent, pRect);
776 }
777
778 static HRESULT WINAPI IDirectDrawSurface3Impl_Unlock(IDirectDrawSurface3 *iface, void *data)
779 {
780     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
781     TRACE("(%p)->(%p): Thunking to IDirectDrawSurface4\n", This, data);
782     return IDirectDrawSurface4_Unlock(&This->IDirectDrawSurface4_iface, NULL);
783 }
784
785 static HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlay(IDirectDrawSurface4 *iface,
786         RECT *SrcRect, IDirectDrawSurface4 *DstSurface, RECT *DstRect, DWORD Flags,
787         DDOVERLAYFX *FX)
788 {
789     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
790     IDirectDrawSurfaceImpl *Dst = unsafe_impl_from_IDirectDrawSurface4(DstSurface);
791     TRACE("(%p)->(%p,%p,%p,0x%08x,%p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
792     return IDirectDrawSurface4_UpdateOverlay(This->parent, SrcRect, Dst ? Dst->parent : NULL,
793                                              DstRect, Flags, FX);
794 }
795
796 static HRESULT WINAPI IDirectDrawSurface3Impl_UpdateOverlay(IDirectDrawSurface3 *iface,
797         RECT *SrcRect, IDirectDrawSurface3 *DstSurface, RECT *DstRect, DWORD Flags,
798         DDOVERLAYFX *FX)
799 {
800     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
801     IDirectDrawSurfaceImpl *Dst = unsafe_impl_from_IDirectDrawSurface3(DstSurface);
802     TRACE("(%p)->(%p,%p,%p,0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, SrcRect, Dst, DstRect, Flags, FX);
803     return IDirectDrawSurface4_UpdateOverlay(&This->IDirectDrawSurface4_iface, SrcRect,
804             Dst ? &Dst->IDirectDrawSurface4_iface : NULL, DstRect, Flags, FX);
805 }
806
807 static HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayDisplay(IDirectDrawSurface4 *iface,
808         DWORD Flags)
809 {
810     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
811     TRACE("(%p)->(0x%08x)\n", This, Flags);
812     return IDirectDrawSurface4_UpdateOverlayDisplay(This->parent, Flags);
813 }
814
815 static HRESULT WINAPI IDirectDrawSurface3Impl_UpdateOverlayDisplay(IDirectDrawSurface3 *iface,
816         DWORD Flags)
817 {
818     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
819     TRACE("(%p)->(0x%08x): Thunking to IDirectDrawSurface4\n", This, Flags);
820     return IDirectDrawSurface4_UpdateOverlayDisplay(&This->IDirectDrawSurface4_iface, Flags);
821 }
822
823 static HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayZOrder(IDirectDrawSurface4 *iface,
824         DWORD Flags, IDirectDrawSurface4 *DDSRef)
825 {
826     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface);
827     IDirectDrawSurfaceImpl *Ref = unsafe_impl_from_IDirectDrawSurface4(DDSRef);
828     TRACE("(%p)->(0x%08x,%p)\n", This, Flags, Ref);
829     return IDirectDrawSurface4_UpdateOverlayZOrder(This->parent, Flags, Ref ? Ref->parent : NULL);
830 }
831
832 static HRESULT WINAPI IDirectDrawSurface3Impl_UpdateOverlayZOrder(IDirectDrawSurface3 *iface,
833         DWORD Flags, IDirectDrawSurface3 *DDSRef)
834 {
835     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface3(iface);
836     IDirectDrawSurfaceImpl *Ref = unsafe_impl_from_IDirectDrawSurface3(DDSRef);
837     TRACE("(%p)->(0x%08x,%p): Thunking to IDirectDrawSurface4\n", This, Flags, Ref);
838     return IDirectDrawSurface4_UpdateOverlayZOrder(&This->IDirectDrawSurface4_iface, Flags,
839             Ref ? &Ref->IDirectDrawSurface4_iface : NULL);
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(&This->IDirectDrawSurface4_iface, 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(&This->IDirectDrawSurface4_iface, 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(&This->IDirectDrawSurface4_iface, &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 impl_from_IDirectDrawSurface4(iface);
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_iface.lpVtbl = &IDirectDrawSurface4_Vtbl;
1113         IDirectDrawSurface4_AddRef(inner);
1114         impl->parent = inner;
1115
1116         outer = &impl->IDirectDrawSurface4_iface;
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 }