wineps.drv: Slightly simplify a PPD parser code snippet.
[wine] / dlls / ddrawex / ddraw.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 #define COBJMACROS
20 #define NONAMELESSUNION
21
22 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26
27 #include "ddraw.h"
28 #include "d3d.h"
29
30 #include "ddrawex_private.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(ddrawex);
34
35 /******************************************************************************
36  * Helper functions for COM management
37  ******************************************************************************/
38 static IDirectDrawImpl *impl_from_IDirectDraw(IDirectDraw *iface)
39 {
40     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw_iface);
41 }
42
43 static IDirectDrawImpl *impl_from_IDirectDraw2(IDirectDraw2 *iface)
44 {
45     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw2_iface);
46 }
47
48 static IDirectDrawImpl *impl_from_IDirectDraw3(IDirectDraw3 *iface)
49 {
50     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw3_iface);
51 }
52
53 static IDirectDrawImpl *impl_from_IDirectDraw4(IDirectDraw4 *iface)
54 {
55     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw4_iface);
56 }
57
58 /******************************************************************************
59  * IDirectDraw4 -> ddraw.dll wrappers
60  ******************************************************************************/
61 static HRESULT WINAPI IDirectDraw4Impl_QueryInterface(IDirectDraw4 *iface, REFIID refiid,
62         void **obj)
63 {
64     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
65
66     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj);
67     *obj = NULL;
68
69     if(!refiid)
70     {
71         return DDERR_INVALIDPARAMS;
72     }
73
74     if (IsEqualGUID( &IID_IDirectDraw7, refiid ) )
75     {
76         WARN("IDirectDraw7 not allowed in ddrawex.dll\n");
77         return E_NOINTERFACE;
78     }
79     else if ( IsEqualGUID( &IID_IUnknown, refiid ) ||
80               IsEqualGUID( &IID_IDirectDraw4, refiid ) )
81     {
82         *obj = &This->IDirectDraw4_iface;
83         TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
84         IDirectDraw4_AddRef(&This->IDirectDraw4_iface);
85     }
86     else if ( IsEqualGUID( &IID_IDirectDraw3, refiid ) )
87     {
88         *obj = &This->IDirectDraw3_iface;
89         TRACE("(%p) Returning IDirectDraw3 interface at %p\n", This, *obj);
90         IDirectDraw3_AddRef(&This->IDirectDraw3_iface);
91     }
92     else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
93     {
94         *obj = &This->IDirectDraw2_iface;
95         TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
96         IDirectDraw2_AddRef(&This->IDirectDraw2_iface);
97     }
98     else if ( IsEqualGUID( &IID_IDirectDraw, refiid ) )
99     {
100         *obj = &This->IDirectDraw_iface;
101         TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
102         IDirectDraw_AddRef(&This->IDirectDraw_iface);
103     }
104     else if ( IsEqualGUID( &IID_IDirect3D  , refiid ) ||
105               IsEqualGUID( &IID_IDirect3D2 , refiid ) ||
106               IsEqualGUID( &IID_IDirect3D3 , refiid ) ||
107               IsEqualGUID( &IID_IDirect3D7 , refiid ) )
108     {
109         WARN("Direct3D not allowed in ddrawex.dll\n");
110         return E_NOINTERFACE;
111     }
112     /* Unknown interface */
113     else
114     {
115         ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
116         return E_NOINTERFACE;
117     }
118     TRACE("Returning S_OK\n");
119     return S_OK;
120 }
121
122 static HRESULT WINAPI IDirectDraw3Impl_QueryInterface(IDirectDraw3 *iface, REFIID refiid,
123         void **obj)
124 {
125     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
126     TRACE("Thunking to IDirectDraw4\n");
127     return IDirectDraw4_QueryInterface(&This->IDirectDraw4_iface, refiid, obj);
128 }
129
130 static HRESULT WINAPI IDirectDraw2Impl_QueryInterface(IDirectDraw2 *iface, REFIID refiid,
131         void **obj)
132 {
133     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
134     TRACE("Thunking to IDirectDraw4\n");
135     return IDirectDraw4_QueryInterface(&This->IDirectDraw4_iface, refiid, obj);
136 }
137
138 static HRESULT WINAPI IDirectDrawImpl_QueryInterface(IDirectDraw *iface, REFIID refiid, void **obj)
139 {
140     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
141     TRACE("Thunking to IDirectDraw4\n");
142     return IDirectDraw4_QueryInterface(&This->IDirectDraw4_iface, refiid, obj);
143 }
144
145 static ULONG WINAPI IDirectDraw4Impl_AddRef(IDirectDraw4 *iface)
146 {
147     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
148     ULONG ref = InterlockedIncrement(&This->ref);
149
150     TRACE("(%p) : incrementing refcount from %u.\n", This, ref - 1);
151
152     return ref;
153 }
154
155 static ULONG WINAPI IDirectDraw3Impl_AddRef(IDirectDraw3 *iface)
156 {
157     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
158     TRACE("Thunking to IDirectDraw4\n");
159     return IDirectDraw4_AddRef(&This->IDirectDraw4_iface);
160 }
161
162 static ULONG WINAPI IDirectDraw2Impl_AddRef(IDirectDraw2 *iface)
163 {
164     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
165     TRACE("Thunking to IDirectDraw4\n");
166     return IDirectDraw4_AddRef(&This->IDirectDraw4_iface);
167 }
168
169 static ULONG WINAPI IDirectDrawImpl_AddRef(IDirectDraw *iface)
170 {
171     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
172     TRACE("Thunking to IDirectDraw4\n");
173     return IDirectDraw4_AddRef(&This->IDirectDraw4_iface);
174 }
175
176 static ULONG WINAPI IDirectDraw4Impl_Release(IDirectDraw4 *iface)
177 {
178     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
179     ULONG ref = InterlockedDecrement(&This->ref);
180
181     TRACE("(%p) : decrementing refcount to %u.\n", This, ref);
182
183     if(ref == 0)
184     {
185         TRACE("Destroying object\n");
186         IDirectDraw4_Release(This->parent);
187         HeapFree(GetProcessHeap(), 0, This);
188     }
189     return ref;
190 }
191
192 static ULONG WINAPI IDirectDraw3Impl_Release(IDirectDraw3 *iface)
193 {
194     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
195     TRACE("Thunking to IDirectDraw4\n");
196     return IDirectDraw4_Release(&This->IDirectDraw4_iface);
197 }
198
199 static ULONG WINAPI IDirectDraw2Impl_Release(IDirectDraw2 *iface)
200 {
201     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
202     TRACE("Thunking to IDirectDraw4\n");
203     return IDirectDraw4_Release(&This->IDirectDraw4_iface);
204 }
205
206 static ULONG WINAPI IDirectDrawImpl_Release(IDirectDraw *iface)
207 {
208     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
209     TRACE("Thunking to IDirectDraw4\n");
210     return IDirectDraw4_Release(&This->IDirectDraw4_iface);
211 }
212
213 static HRESULT WINAPI IDirectDraw4Impl_Compact(IDirectDraw4 *iface)
214 {
215     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
216     TRACE("(%p)\n", This);
217
218     return IDirectDraw4_Compact(This->parent);
219 }
220
221 static HRESULT WINAPI IDirectDraw3Impl_Compact(IDirectDraw3 *iface)
222 {
223     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
224     TRACE("Thunking to IDirectDraw4\n");
225     return IDirectDraw4_Compact(&This->IDirectDraw4_iface);
226 }
227
228 static HRESULT WINAPI IDirectDraw2Impl_Compact(IDirectDraw2 *iface)
229 {
230     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
231     TRACE("Thunking to IDirectDraw4\n");
232     return IDirectDraw4_Compact(&This->IDirectDraw4_iface);
233 }
234
235 static HRESULT WINAPI IDirectDrawImpl_Compact(IDirectDraw *iface)
236 {
237     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
238     TRACE("Thunking to IDirectDraw4\n");
239     return IDirectDraw4_Compact(&This->IDirectDraw4_iface);
240 }
241
242 static HRESULT WINAPI IDirectDraw4Impl_CreateClipper(IDirectDraw4 *iface, DWORD Flags,
243         IDirectDrawClipper **clipper, IUnknown *UnkOuter)
244 {
245     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
246     TRACE("(%p)->(0x%08x, %p, %p)\n", This, Flags, clipper, UnkOuter);
247
248     if(UnkOuter != NULL)
249     {
250         /* This may require a wrapper interface for clippers too which handles this */
251         FIXME("Test and implement Aggregation for ddrawex clippers\n");
252     }
253
254     return IDirectDraw4_CreateClipper(This->parent, Flags, clipper, UnkOuter);
255 }
256
257 static HRESULT WINAPI IDirectDraw3Impl_CreateClipper(IDirectDraw3 *iface, DWORD Flags,
258         IDirectDrawClipper **clipper, IUnknown *UnkOuter)
259 {
260     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
261     TRACE("Thunking to IDirectDraw4\n");
262     return IDirectDraw4_CreateClipper(&This->IDirectDraw4_iface, Flags, clipper, UnkOuter);
263 }
264
265 static HRESULT WINAPI IDirectDraw2Impl_CreateClipper(IDirectDraw2 *iface, DWORD Flags,
266         IDirectDrawClipper **clipper, IUnknown *UnkOuter)
267 {
268     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
269     TRACE("Thunking to IDirectDraw4\n");
270     return IDirectDraw4_CreateClipper(&This->IDirectDraw4_iface, Flags, clipper, UnkOuter);
271 }
272
273 static HRESULT WINAPI IDirectDrawImpl_CreateClipper(IDirectDraw *iface, DWORD Flags,
274         IDirectDrawClipper **clipper, IUnknown *UnkOuter)
275 {
276     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
277     TRACE("Thunking to IDirectDraw4\n");
278     return IDirectDraw4_CreateClipper(&This->IDirectDraw4_iface, Flags, clipper, UnkOuter);
279 }
280
281 static HRESULT WINAPI IDirectDraw4Impl_CreatePalette(IDirectDraw4 *iface, DWORD Flags,
282         PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *UnkOuter)
283 {
284     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
285     TRACE("(%p)(0x%08x,%p,%p,%p)\n", This, Flags, ColorTable, Palette, UnkOuter);
286
287     if(UnkOuter != NULL)
288     {
289         /* This may require a wrapper interface for palettes too which handles this */
290         FIXME("Test and implement Aggregation for ddrawex palettes\n");
291     }
292
293     return IDirectDraw4_CreatePalette(This->parent, Flags, ColorTable, Palette, UnkOuter);
294 }
295
296 static HRESULT WINAPI IDirectDraw3Impl_CreatePalette(IDirectDraw3 *iface, DWORD Flags,
297         PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *UnkOuter)
298 {
299     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
300     TRACE("Thunking to IDirectDraw4\n");
301     return IDirectDraw4_CreatePalette(&This->IDirectDraw4_iface, Flags, ColorTable, Palette,
302             UnkOuter);
303 }
304
305 static HRESULT WINAPI IDirectDraw2Impl_CreatePalette(IDirectDraw2 *iface, DWORD Flags,
306         PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *UnkOuter)
307 {
308     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
309     TRACE("Thunking to IDirectDraw4\n");
310     return IDirectDraw4_CreatePalette(&This->IDirectDraw4_iface, Flags, ColorTable, Palette,
311             UnkOuter);
312 }
313
314 static HRESULT WINAPI IDirectDrawImpl_CreatePalette(IDirectDraw *iface, DWORD Flags,
315         PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *UnkOuter)
316 {
317     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
318     TRACE("Thunking to IDirectDraw4\n");
319     return IDirectDraw4_CreatePalette(&This->IDirectDraw4_iface, Flags, ColorTable, Palette,
320             UnkOuter);
321 }
322
323 static HRESULT WINAPI IDirectDraw4Impl_CreateSurface(IDirectDraw4 *iface, DDSURFACEDESC2 *DDSD,
324         IDirectDrawSurface4 **Surf, IUnknown *UnkOuter)
325 {
326     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
327     HRESULT hr;
328     const DWORD perm_dc_flags = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
329     BOOL permanent_dc;
330     TRACE("(%p)(%p, %p, %p)\n", This, DDSD, Surf, UnkOuter);
331
332     if(UnkOuter != NULL)
333     {
334         /* Handle this in this dll. Don't forward the UnkOuter to ddraw.dll */
335         FIXME("Implement aggregation for ddrawex surfaces\n");
336     }
337
338     /* plain ddraw.dll refuses to create a surface that has both VIDMEM and SYSMEM flags
339      * set. In ddrawex this succeeds, and the GetDC() call changes the behavior. The DC
340      * is permanently valid, and the surface can be locked between GetDC() and ReleaseDC()
341      * calls. GetDC() can be called more than once too
342      */
343     if((DDSD->ddsCaps.dwCaps & perm_dc_flags) == perm_dc_flags)
344     {
345         permanent_dc = TRUE;
346         DDSD->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
347         DDSD->ddsCaps.dwCaps |= DDSCAPS_OWNDC;
348     }
349     else
350     {
351         permanent_dc = FALSE;
352     }
353
354     hr = IDirectDraw4_CreateSurface(This->parent, DDSD, Surf, UnkOuter);
355     *Surf = dds_get_outer(*Surf);
356     if(permanent_dc) prepare_permanent_dc(*Surf);
357     return hr;
358 }
359
360 void DDSD_to_DDSD2(const DDSURFACEDESC *in, DDSURFACEDESC2 *out)
361 {
362     memset(out, 0, sizeof(*out));
363     out->dwSize = sizeof(*out);
364     out->dwFlags = in->dwFlags;
365     if(in->dwFlags & DDSD_WIDTH) out->dwWidth = in->dwWidth;
366     if(in->dwFlags & DDSD_HEIGHT) out->dwHeight = in->dwHeight;
367     if(in->dwFlags & DDSD_PIXELFORMAT) out->u4.ddpfPixelFormat = in->ddpfPixelFormat;
368     if(in->dwFlags & DDSD_CAPS) out->ddsCaps.dwCaps = in->ddsCaps.dwCaps;
369     if(in->dwFlags & DDSD_PITCH) out->u1.lPitch = in->u1.lPitch;
370     if(in->dwFlags & DDSD_BACKBUFFERCOUNT) out->dwBackBufferCount = in->dwBackBufferCount;
371     if(in->dwFlags & DDSD_ZBUFFERBITDEPTH) out->u2.dwMipMapCount = in->u2.dwZBufferBitDepth; /* same union */
372     if(in->dwFlags & DDSD_ALPHABITDEPTH) out->dwAlphaBitDepth = in->dwAlphaBitDepth;
373     /* DDraw(native, and wine) does not set the DDSD_LPSURFACE, so always copy */
374     out->lpSurface = in->lpSurface;
375     if(in->dwFlags & DDSD_CKDESTOVERLAY) out->u3.ddckCKDestOverlay = in->ddckCKDestOverlay;
376     if(in->dwFlags & DDSD_CKDESTBLT) out->ddckCKDestBlt = in->ddckCKDestBlt;
377     if(in->dwFlags & DDSD_CKSRCOVERLAY) out->ddckCKSrcOverlay = in->ddckCKSrcOverlay;
378     if(in->dwFlags & DDSD_CKSRCBLT) out->ddckCKSrcBlt = in->ddckCKSrcBlt;
379     if(in->dwFlags & DDSD_MIPMAPCOUNT) out->u2.dwMipMapCount = in->u2.dwMipMapCount;
380     if(in->dwFlags & DDSD_REFRESHRATE) out->u2.dwRefreshRate = in->u2.dwRefreshRate;
381     if(in->dwFlags & DDSD_LINEARSIZE) out->u1.dwLinearSize = in->u1.dwLinearSize;
382     /* Does not exist in DDSURFACEDESC:
383      * DDSD_TEXTURESTAGE, DDSD_FVF, DDSD_SRCVBHANDLE,
384      */
385 }
386
387 void DDSD2_to_DDSD(const DDSURFACEDESC2 *in, DDSURFACEDESC *out)
388 {
389     memset(out, 0, sizeof(*out));
390     out->dwSize = sizeof(*out);
391     out->dwFlags = in->dwFlags;
392     if(in->dwFlags & DDSD_WIDTH) out->dwWidth = in->dwWidth;
393     if(in->dwFlags & DDSD_HEIGHT) out->dwHeight = in->dwHeight;
394     if(in->dwFlags & DDSD_PIXELFORMAT) out->ddpfPixelFormat = in->u4.ddpfPixelFormat;
395     if(in->dwFlags & DDSD_CAPS) out->ddsCaps.dwCaps = in->ddsCaps.dwCaps;
396     if(in->dwFlags & DDSD_PITCH) out->u1.lPitch = in->u1.lPitch;
397     if(in->dwFlags & DDSD_BACKBUFFERCOUNT) out->dwBackBufferCount = in->dwBackBufferCount;
398     if(in->dwFlags & DDSD_ZBUFFERBITDEPTH) out->u2.dwZBufferBitDepth = in->u2.dwMipMapCount; /* same union */
399     if(in->dwFlags & DDSD_ALPHABITDEPTH) out->dwAlphaBitDepth = in->dwAlphaBitDepth;
400     /* DDraw(native, and wine) does not set the DDSD_LPSURFACE, so always copy */
401     out->lpSurface = in->lpSurface;
402     if(in->dwFlags & DDSD_CKDESTOVERLAY) out->ddckCKDestOverlay = in->u3.ddckCKDestOverlay;
403     if(in->dwFlags & DDSD_CKDESTBLT) out->ddckCKDestBlt = in->ddckCKDestBlt;
404     if(in->dwFlags & DDSD_CKSRCOVERLAY) out->ddckCKSrcOverlay = in->ddckCKSrcOverlay;
405     if(in->dwFlags & DDSD_CKSRCBLT) out->ddckCKSrcBlt = in->ddckCKSrcBlt;
406     if(in->dwFlags & DDSD_MIPMAPCOUNT) out->u2.dwMipMapCount = in->u2.dwMipMapCount;
407     if(in->dwFlags & DDSD_REFRESHRATE) out->u2.dwRefreshRate = in->u2.dwRefreshRate;
408     if(in->dwFlags & DDSD_LINEARSIZE) out->u1.dwLinearSize = in->u1.dwLinearSize;
409     /* Does not exist in DDSURFACEDESC:
410      * DDSD_TEXTURESTAGE, DDSD_FVF, DDSD_SRCVBHANDLE,
411      */
412     if(in->dwFlags & DDSD_TEXTURESTAGE) WARN("Does not exist in DDSURFACEDESC: DDSD_TEXTURESTAGE\n");
413     if(in->dwFlags & DDSD_FVF) WARN("Does not exist in DDSURFACEDESC: DDSD_FVF\n");
414     if(in->dwFlags & DDSD_SRCVBHANDLE) WARN("Does not exist in DDSURFACEDESC: DDSD_SRCVBHANDLE\n");
415     out->dwFlags &= ~(DDSD_TEXTURESTAGE | DDSD_FVF | DDSD_SRCVBHANDLE);
416 }
417
418 static HRESULT WINAPI IDirectDraw3Impl_CreateSurface(IDirectDraw3 *iface, DDSURFACEDESC *DDSD,
419         IDirectDrawSurface **Surf, IUnknown *UnkOuter)
420 {
421     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
422     DDSURFACEDESC2 ddsd2;
423     IDirectDrawSurface4 *surf4 = NULL;
424     HRESULT hr;
425     TRACE("Thunking to IDirectDraw4\n");
426
427     DDSD_to_DDSD2(DDSD, &ddsd2);
428
429     hr = IDirectDraw4_CreateSurface(&This->IDirectDraw4_iface, &ddsd2, &surf4, UnkOuter);
430     if(FAILED(hr))
431     {
432         *Surf = NULL;
433         return hr;
434     }
435
436     TRACE("Got surface %p\n", surf4);
437     IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **) Surf);
438     IDirectDrawSurface4_Release(surf4);
439     return hr;
440 }
441
442 static HRESULT WINAPI IDirectDraw2Impl_CreateSurface(IDirectDraw2 *iface, DDSURFACEDESC *DDSD,
443         IDirectDrawSurface **Surf, IUnknown *UnkOuter)
444 {
445     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
446     TRACE("Thunking to IDirectDraw3\n");
447     return IDirectDraw3_CreateSurface(&This->IDirectDraw3_iface, DDSD, Surf, UnkOuter);
448 }
449
450 static HRESULT WINAPI IDirectDrawImpl_CreateSurface(IDirectDraw *iface, DDSURFACEDESC *DDSD,
451         IDirectDrawSurface **Surf, IUnknown *UnkOuter)
452 {
453     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
454     TRACE("Thunking to IDirectDraw3\n");
455     return IDirectDraw3_CreateSurface(&This->IDirectDraw3_iface, DDSD, Surf, UnkOuter);
456 }
457
458 static HRESULT WINAPI IDirectDraw4Impl_DuplicateSurface(IDirectDraw4 *iface,
459         IDirectDrawSurface4 *src, IDirectDrawSurface4 **dst)
460 {
461     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
462     IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface4(src);
463
464     FIXME("(%p)->(%p,%p). Create a wrapper surface\n", This, src, dst);
465
466     return IDirectDraw4_DuplicateSurface(This->parent, surf ? surf->parent : NULL, dst);
467 }
468
469 static HRESULT WINAPI IDirectDraw3Impl_DuplicateSurface(IDirectDraw3 *iface,
470         IDirectDrawSurface *src, IDirectDrawSurface **dst)
471 {
472     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
473     IDirectDrawSurface4 *src_4;
474     IDirectDrawSurface4 *dst_4;
475     HRESULT hr;
476
477     TRACE("Thunking to IDirectDraw4\n");
478     IDirectDrawSurface_QueryInterface(src, &IID_IDirectDrawSurface4, (void **) &src_4);
479     hr = IDirectDraw4_DuplicateSurface(&This->IDirectDraw4_iface, src_4, &dst_4);
480     IDirectDrawSurface4_Release(src_4);
481
482     if(FAILED(hr))
483     {
484         *dst = NULL;
485         return hr;
486     }
487     IDirectDrawSurface4_QueryInterface(dst_4, &IID_IDirectDrawSurface, (void **) dst);
488     IDirectDrawSurface4_Release(dst_4);
489     return hr;
490 }
491
492 static HRESULT WINAPI IDirectDraw2Impl_DuplicateSurface(IDirectDraw2 *iface,
493         IDirectDrawSurface *src, IDirectDrawSurface **dst)
494 {
495     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
496     TRACE("Thunking to IDirectDraw3\n");
497     return IDirectDraw3_DuplicateSurface(&This->IDirectDraw3_iface, src, dst);
498 }
499
500 static HRESULT WINAPI IDirectDrawImpl_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src,
501         IDirectDrawSurface **dst)
502 {
503     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
504     TRACE("Thunking to IDirectDraw3\n");
505     return IDirectDraw3_DuplicateSurface(&This->IDirectDraw3_iface, src, dst);
506 }
507
508 static HRESULT WINAPI IDirectDraw4Impl_EnumDisplayModes(IDirectDraw4 *iface, DWORD Flags,
509         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb)
510 {
511     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
512     TRACE("(%p)->(0x%08x,%p,%p,%p)\n", This, Flags, DDSD, Context, cb);
513
514     return IDirectDraw4_EnumDisplayModes(This->parent, Flags, DDSD, Context, cb);
515 }
516
517 struct enummodes_ctx
518 {
519     LPDDENUMMODESCALLBACK orig_cb;
520     void *orig_ctx;
521 };
522
523 static HRESULT WINAPI
524 enum_modes_cb2(DDSURFACEDESC2 *ddsd2, void *vctx)
525 {
526     struct enummodes_ctx *ctx = vctx;
527     DDSURFACEDESC ddsd;
528
529     DDSD2_to_DDSD(ddsd2, &ddsd);
530     return ctx->orig_cb(&ddsd, ctx->orig_ctx);
531 }
532
533 static HRESULT WINAPI IDirectDraw3Impl_EnumDisplayModes(IDirectDraw3 *iface, DWORD Flags,
534         DDSURFACEDESC *DDSD, void *Context, LPDDENUMMODESCALLBACK cb)
535 {
536     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
537     DDSURFACEDESC2 ddsd2;
538     struct enummodes_ctx ctx;
539     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw4\n", This, Flags, DDSD, Context, cb);
540
541     DDSD_to_DDSD2(DDSD, &ddsd2);
542     ctx.orig_cb = cb;
543     ctx.orig_ctx = Context;
544     return IDirectDraw4_EnumDisplayModes(&This->IDirectDraw4_iface, Flags, &ddsd2, &ctx,
545             enum_modes_cb2);
546 }
547
548 static HRESULT WINAPI IDirectDraw2Impl_EnumDisplayModes(IDirectDraw2 *iface, DWORD Flags,
549         DDSURFACEDESC *DDSD, void *Context, LPDDENUMMODESCALLBACK cb)
550 {
551     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
552     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw3\n", This, Flags, DDSD, Context, cb);
553     return IDirectDraw3_EnumDisplayModes(&This->IDirectDraw3_iface, Flags, DDSD, Context, cb);
554 }
555
556 static HRESULT WINAPI IDirectDrawImpl_EnumDisplayModes(IDirectDraw *iface, DWORD Flags,
557         DDSURFACEDESC *DDSD, void *Context, LPDDENUMMODESCALLBACK cb)
558 {
559     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
560     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw3\n", This, Flags, DDSD, Context, cb);
561     return IDirectDraw3_EnumDisplayModes(&This->IDirectDraw3_iface, Flags, DDSD, Context, cb);
562 }
563
564 struct enumsurfaces4_ctx
565 {
566     LPDDENUMSURFACESCALLBACK2 orig_cb;
567     void *orig_ctx;
568 };
569
570 static HRESULT WINAPI
571 enum_surfaces_wrapper(IDirectDrawSurface4 *surf4, DDSURFACEDESC2 *ddsd2, void *vctx)
572 {
573     struct enumsurfaces4_ctx *ctx = vctx;
574     IDirectDrawSurface4 *outer = dds_get_outer(surf4);
575     IDirectDrawSurface4_AddRef(outer);
576     IDirectDrawSurface4_Release(surf4);
577     TRACE("Returning wrapper surface %p for enumerated inner surface %p\n", outer, surf4);
578     return ctx->orig_cb(outer, ddsd2, ctx->orig_ctx);
579 }
580
581 static HRESULT WINAPI IDirectDraw4Impl_EnumSurfaces(IDirectDraw4 *iface, DWORD Flags,
582         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK2 Callback)
583 {
584     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
585     struct enumsurfaces4_ctx ctx;
586     TRACE("(%p)->(0x%08x,%p,%p,%p)\n", This, Flags, DDSD, Context, Callback);
587
588     ctx.orig_cb = Callback;
589     ctx.orig_ctx = Context;
590     return IDirectDraw4Impl_EnumSurfaces(This->parent, Flags, DDSD, &ctx, enum_surfaces_wrapper);
591 }
592
593 struct enumsurfaces_ctx
594 {
595     LPDDENUMSURFACESCALLBACK orig_cb;
596     void *orig_ctx;
597 };
598
599 static HRESULT WINAPI
600 enum_surfaces_cb2(IDirectDrawSurface4 *surf4, DDSURFACEDESC2 *ddsd2, void *vctx)
601 {
602     struct enumsurfaces_ctx *ctx = vctx;
603     IDirectDrawSurface *surf1;
604     DDSURFACEDESC ddsd;
605
606     /* Keep the reference, it goes to the application */
607     IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **) &surf1);
608     /* Release the reference this function got */
609     IDirectDrawSurface4_Release(surf4);
610
611     DDSD2_to_DDSD(ddsd2, &ddsd);
612     return ctx->orig_cb(surf1, &ddsd, ctx->orig_ctx);
613 }
614
615 static HRESULT WINAPI IDirectDraw3Impl_EnumSurfaces(IDirectDraw3 *iface, DWORD Flags,
616         DDSURFACEDESC *DDSD, void *Context, LPDDENUMSURFACESCALLBACK Callback)
617 {
618     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
619     DDSURFACEDESC2 ddsd2;
620     struct enumsurfaces_ctx ctx;
621     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw4\n", This, Flags, DDSD, Context, Callback);
622
623     DDSD_to_DDSD2(DDSD, &ddsd2);
624     ctx.orig_cb = Callback;
625     ctx.orig_ctx = Context;
626     return IDirectDraw4_EnumSurfaces(&This->IDirectDraw4_iface, Flags, &ddsd2, &ctx,
627             enum_surfaces_cb2);
628 }
629
630 static HRESULT WINAPI IDirectDraw2Impl_EnumSurfaces(IDirectDraw2 *iface, DWORD Flags,
631         DDSURFACEDESC *DDSD, void *Context, LPDDENUMSURFACESCALLBACK Callback)
632 {
633     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
634     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw3\n", This, Flags, DDSD, Context, Callback);
635     return IDirectDraw3_EnumSurfaces(&This->IDirectDraw3_iface, Flags, DDSD, Context, Callback);
636 }
637
638 static HRESULT WINAPI IDirectDrawImpl_EnumSurfaces(IDirectDraw *iface, DWORD Flags,
639         DDSURFACEDESC *DDSD, void *Context, LPDDENUMSURFACESCALLBACK Callback)
640 {
641     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
642     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw3\n", This, Flags, DDSD, Context, Callback);
643     return IDirectDraw3_EnumSurfaces(&This->IDirectDraw3_iface, Flags, DDSD, Context, Callback);
644 }
645
646 static HRESULT WINAPI IDirectDraw4Impl_FlipToGDISurface(IDirectDraw4 *iface)
647 {
648     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
649     TRACE("(%p)\n", This);
650
651     return IDirectDraw4_FlipToGDISurface(This->parent);
652 }
653
654 static HRESULT WINAPI IDirectDraw3Impl_FlipToGDISurface(IDirectDraw3 *iface)
655 {
656     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
657     TRACE("(%p). Thunking to IDirectDraw4\n", This);
658     return IDirectDraw4_FlipToGDISurface(&This->IDirectDraw4_iface);
659 }
660
661 static HRESULT WINAPI IDirectDraw2Impl_FlipToGDISurface(IDirectDraw2 *iface)
662 {
663     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
664     TRACE("(%p). Thunking to IDirectDraw4\n", This);
665     return IDirectDraw4_FlipToGDISurface(&This->IDirectDraw4_iface);
666 }
667
668 static HRESULT WINAPI IDirectDrawImpl_FlipToGDISurface(IDirectDraw *iface)
669 {
670     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
671     TRACE("(%p). Thunking to IDirectDraw4\n", This);
672     return IDirectDraw4_FlipToGDISurface(&This->IDirectDraw4_iface);
673 }
674
675 static HRESULT WINAPI IDirectDraw4Impl_GetCaps(IDirectDraw4 *iface, DDCAPS *DriverCaps,
676         DDCAPS *HELCaps)
677 {
678     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
679     TRACE("(%p)->(%p,%p)\n", This, DriverCaps, HELCaps);
680     return IDirectDraw4_GetCaps(This->parent, DriverCaps, HELCaps);
681 }
682
683 static HRESULT WINAPI IDirectDraw3Impl_GetCaps(IDirectDraw3 *iface, DDCAPS *DriverCaps,
684         DDCAPS *HELCaps)
685 {
686     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
687     TRACE("(%p)->(%p,%p). Thunking to IDirectDraw4\n", This, DriverCaps, HELCaps);
688     return IDirectDraw4_GetCaps(&This->IDirectDraw4_iface, DriverCaps, HELCaps);
689 }
690
691 static HRESULT WINAPI IDirectDraw2Impl_GetCaps(IDirectDraw2 *iface, DDCAPS *DriverCaps,
692         DDCAPS *HELCaps)
693 {
694     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
695     TRACE("(%p)->(%p,%p). Thunking to IDirectDraw4\n", This, DriverCaps, HELCaps);
696     return IDirectDraw4_GetCaps(&This->IDirectDraw4_iface, DriverCaps, HELCaps);
697 }
698
699 static HRESULT WINAPI IDirectDrawImpl_GetCaps(IDirectDraw *iface, DDCAPS *DriverCaps,
700         DDCAPS *HELCaps)
701 {
702     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
703     TRACE("(%p)->(%p,%p). Thunking to IDirectDraw4\n", This, DriverCaps, HELCaps);
704     return IDirectDraw4_GetCaps(&This->IDirectDraw4_iface, DriverCaps, HELCaps);
705 }
706
707 static HRESULT WINAPI IDirectDraw4Impl_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *DDSD)
708 {
709     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
710     TRACE("(%p)->(%p)\n", This, DDSD);
711     return IDirectDraw4_GetDisplayMode(This->parent, DDSD);
712 }
713
714 static HRESULT WINAPI IDirectDraw3Impl_GetDisplayMode(IDirectDraw3 *iface, DDSURFACEDESC *DDSD)
715 {
716     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
717     DDSURFACEDESC2 ddsd2;
718     HRESULT hr;
719
720     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, DDSD);
721     hr = IDirectDraw4_GetDisplayMode(&This->IDirectDraw4_iface, &ddsd2);
722     DDSD2_to_DDSD(&ddsd2, DDSD);
723     return hr;
724 }
725
726 static HRESULT WINAPI IDirectDraw2Impl_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *DDSD)
727 {
728     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
729     TRACE("(%p)->(%p): Thunking to IDirectDraw3\n", This, DDSD);
730     return IDirectDraw3_GetDisplayMode(&This->IDirectDraw3_iface, DDSD);
731 }
732
733 static HRESULT WINAPI IDirectDrawImpl_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *DDSD)
734 {
735     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
736     TRACE("(%p)->(%p): Thunking to IDirectDraw3\n", This, DDSD);
737     return IDirectDraw3_GetDisplayMode(&This->IDirectDraw3_iface, DDSD);
738 }
739
740 static HRESULT WINAPI IDirectDraw4Impl_GetFourCCCodes(IDirectDraw4 *iface, DWORD *NumCodes,
741         DWORD *Codes)
742 {
743     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
744     TRACE("(%p)->(%p, %p):\n", This, NumCodes, Codes);
745     return IDirectDraw4_GetFourCCCodes(This->parent, NumCodes, Codes);
746 }
747
748 static HRESULT WINAPI IDirectDraw3Impl_GetFourCCCodes(IDirectDraw3 *iface, DWORD *NumCodes,
749         DWORD *Codes)
750 {
751     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
752     TRACE("(%p)->(%p, %p): Thunking to IDirectDraw4\n", This, NumCodes, Codes);
753     return IDirectDraw4_GetFourCCCodes(&This->IDirectDraw4_iface, NumCodes, Codes);
754 }
755
756 static HRESULT WINAPI IDirectDraw2Impl_GetFourCCCodes(IDirectDraw2 *iface, DWORD *NumCodes,
757         DWORD *Codes)
758 {
759     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
760     TRACE("(%p)->(%p, %p): Thunking to IDirectDraw4\n", This, NumCodes, Codes);
761     return IDirectDraw4_GetFourCCCodes(&This->IDirectDraw4_iface, NumCodes, Codes);
762 }
763
764 static HRESULT WINAPI IDirectDrawImpl_GetFourCCCodes(IDirectDraw *iface, DWORD *NumCodes,
765         DWORD *Codes)
766 {
767     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
768     TRACE("(%p)->(%p, %p): Thunking to IDirectDraw4\n", This, NumCodes, Codes);
769     return IDirectDraw4_GetFourCCCodes(&This->IDirectDraw4_iface, NumCodes, Codes);
770 }
771
772 static HRESULT WINAPI IDirectDraw4Impl_GetGDISurface(IDirectDraw4 *iface,
773         IDirectDrawSurface4 **GDISurface)
774 {
775     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
776     IDirectDrawSurface4 *inner = NULL;
777     HRESULT hr;
778     TRACE("(%p)->(%p)\n", This, GDISurface);
779
780     hr = IDirectDraw4_GetGDISurface(This->parent, &inner);
781     if(SUCCEEDED(hr))
782     {
783         *GDISurface = dds_get_outer(inner);
784         IDirectDrawSurface4_AddRef(*GDISurface);
785         IDirectDrawSurface4_Release(inner);
786     }
787     else
788     {
789         *GDISurface = NULL;
790     }
791     return hr;
792 }
793
794 static HRESULT WINAPI IDirectDraw3Impl_GetGDISurface(IDirectDraw3 *iface,
795         IDirectDrawSurface **GDISurface)
796 {
797     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
798     IDirectDrawSurface4 *surf4;
799     HRESULT hr;
800     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, GDISurface);
801
802     hr = IDirectDraw4_GetGDISurface(&This->IDirectDraw4_iface, &surf4);
803     if(FAILED(hr)) {
804         *GDISurface = NULL;
805         return hr;
806     }
807
808     /* Release the reference we got from the DDraw4 call, and pass a reference to the caller */
809     IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **) GDISurface);
810     IDirectDrawSurface4_Release(surf4);
811     return hr;
812 }
813
814 static HRESULT WINAPI IDirectDraw2Impl_GetGDISurface(IDirectDraw2 *iface,
815         IDirectDrawSurface **GDISurface)
816 {
817     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
818     TRACE("(%p)->(%p): Thunking to IDirectDraw3\n", This, GDISurface);
819     return IDirectDraw3_GetGDISurface(&This->IDirectDraw3_iface, GDISurface);
820 }
821
822 static HRESULT WINAPI IDirectDrawImpl_GetGDISurface(IDirectDraw *iface,
823         IDirectDrawSurface **GDISurface)
824 {
825     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
826     TRACE("(%p)->(%p): Thunking to IDirectDraw3\n", This, GDISurface);
827     return IDirectDraw3_GetGDISurface(&This->IDirectDraw3_iface, GDISurface);
828 }
829
830 static HRESULT WINAPI IDirectDraw4Impl_GetMonitorFrequency(IDirectDraw4 *iface, DWORD *Freq)
831 {
832     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
833     TRACE("(%p)->(%p)\n", This, Freq);
834     return IDirectDraw4_GetMonitorFrequency(This->parent, Freq);
835 }
836
837 static HRESULT WINAPI IDirectDraw3Impl_GetMonitorFrequency(IDirectDraw3 *iface, DWORD *Freq)
838 {
839     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
840     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Freq);
841     return IDirectDraw4_GetMonitorFrequency(&This->IDirectDraw4_iface, Freq);
842 }
843
844 static HRESULT WINAPI IDirectDraw2Impl_GetMonitorFrequency(IDirectDraw2 *iface, DWORD *Freq)
845 {
846     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
847     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Freq);
848     return IDirectDraw4_GetMonitorFrequency(&This->IDirectDraw4_iface, Freq);
849 }
850
851 static HRESULT WINAPI IDirectDrawImpl_GetMonitorFrequency(IDirectDraw *iface, DWORD *Freq)
852 {
853     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
854     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Freq);
855     return IDirectDraw4_GetMonitorFrequency(&This->IDirectDraw4_iface, Freq);
856 }
857
858 static HRESULT WINAPI IDirectDraw4Impl_GetScanLine(IDirectDraw4 *iface, DWORD *Scanline)
859 {
860     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
861     TRACE("(%p)->(%p)\n", This, Scanline);
862     return IDirectDraw4_GetScanLine(This->parent, Scanline);
863 }
864
865 static HRESULT WINAPI IDirectDraw3Impl_GetScanLine(IDirectDraw3 *iface, DWORD *Scanline)
866 {
867     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
868     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Scanline);
869     return IDirectDraw4_GetScanLine(&This->IDirectDraw4_iface, Scanline);
870 }
871
872 static HRESULT WINAPI IDirectDraw2Impl_GetScanLine(IDirectDraw2 *iface, DWORD *Scanline)
873 {
874     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
875     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Scanline);
876     return IDirectDraw4_GetScanLine(&This->IDirectDraw4_iface, Scanline);
877 }
878
879 static HRESULT WINAPI IDirectDrawImpl_GetScanLine(IDirectDraw *iface, DWORD *Scanline)
880 {
881     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
882     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Scanline);
883     return IDirectDraw4_GetScanLine(&This->IDirectDraw4_iface, Scanline);
884 }
885
886 static HRESULT WINAPI IDirectDraw4Impl_GetVerticalBlankStatus(IDirectDraw4 *iface, BOOL *status)
887 {
888     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
889     TRACE("(%p)->(%p)\n", This, status);
890     return IDirectDraw4_GetVerticalBlankStatus(This->parent, status);
891 }
892
893 static HRESULT WINAPI IDirectDraw3Impl_GetVerticalBlankStatus(IDirectDraw3 *iface, BOOL *status)
894 {
895     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
896     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, status);
897     return IDirectDraw4_GetVerticalBlankStatus(&This->IDirectDraw4_iface, status);
898 }
899
900 static HRESULT WINAPI IDirectDraw2Impl_GetVerticalBlankStatus(IDirectDraw2 *iface, BOOL *status)
901 {
902     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
903     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, status);
904     return IDirectDraw4_GetVerticalBlankStatus(&This->IDirectDraw4_iface, status);
905 }
906
907 static HRESULT WINAPI IDirectDrawImpl_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *status)
908 {
909     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
910     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, status);
911     return IDirectDraw4_GetVerticalBlankStatus(&This->IDirectDraw4_iface, status);
912 }
913
914 static HRESULT WINAPI IDirectDraw4Impl_Initialize(IDirectDraw4 *iface, GUID *Guid)
915 {
916     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
917     TRACE("(%p)->(%s)\n", This, debugstr_guid(Guid));
918     return IDirectDraw4_Initialize(This->parent, Guid);
919 }
920
921 static HRESULT WINAPI IDirectDraw3Impl_Initialize(IDirectDraw3 *iface, GUID *Guid)
922 {
923     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
924     TRACE("(%p)->(%s): Thunking to IDirectDraw4\n", This, debugstr_guid(Guid));
925     return IDirectDraw4_Initialize(&This->IDirectDraw4_iface, Guid);
926 }
927
928 static HRESULT WINAPI IDirectDraw2Impl_Initialize(IDirectDraw2 *iface, GUID *Guid)
929 {
930     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
931     TRACE("(%p)->(%s): Thunking to IDirectDraw4\n", This, debugstr_guid(Guid));
932     return IDirectDraw4_Initialize(&This->IDirectDraw4_iface, Guid);
933 }
934
935 static HRESULT WINAPI IDirectDrawImpl_Initialize(IDirectDraw *iface, GUID *Guid)
936 {
937     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
938     TRACE("(%p)->(%s): Thunking to IDirectDraw4\n", This, debugstr_guid(Guid));
939     return IDirectDraw4_Initialize(&This->IDirectDraw4_iface, Guid);
940 }
941
942 static HRESULT WINAPI IDirectDraw4Impl_RestoreDisplayMode(IDirectDraw4 *iface)
943 {
944     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
945     TRACE("(%p)\n", This);
946     return IDirectDraw4_RestoreDisplayMode(This->parent);
947 }
948
949 static HRESULT WINAPI IDirectDraw3Impl_RestoreDisplayMode(IDirectDraw3 *iface)
950 {
951     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
952     TRACE("(%p): Thunking to IDirectDraw4\n", This);
953     return IDirectDraw4_RestoreDisplayMode(&This->IDirectDraw4_iface);
954 }
955
956 static HRESULT WINAPI IDirectDraw2Impl_RestoreDisplayMode(IDirectDraw2 *iface)
957 {
958     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
959     TRACE("(%p): Thunking to IDirectDraw4\n", This);
960     return IDirectDraw4_RestoreDisplayMode(&This->IDirectDraw4_iface);
961 }
962
963 static HRESULT WINAPI IDirectDrawImpl_RestoreDisplayMode(IDirectDraw *iface)
964 {
965     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
966     TRACE("(%p): Thunking to IDirectDraw4\n", This);
967     return IDirectDraw4_RestoreDisplayMode(&This->IDirectDraw4_iface);
968 }
969
970 static HRESULT WINAPI IDirectDraw4Impl_SetCooperativeLevel(IDirectDraw4 *iface, HWND hwnd,
971         DWORD cooplevel)
972 {
973     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
974     TRACE("(%p)->(%p, 0x%08x)\n", This, hwnd, cooplevel);
975     return IDirectDraw4_SetCooperativeLevel(This->parent, hwnd, cooplevel);
976 }
977
978 static HRESULT WINAPI IDirectDraw3Impl_SetCooperativeLevel(IDirectDraw3 *iface, HWND hwnd,
979         DWORD cooplevel)
980 {
981     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
982     TRACE("(%p)->(%p, 0x%08x): Thunking to IDirectDraw4\n", This, hwnd, cooplevel);
983     return IDirectDraw4_SetCooperativeLevel(&This->IDirectDraw4_iface, hwnd, cooplevel);
984 }
985
986 static HRESULT WINAPI IDirectDraw2Impl_SetCooperativeLevel(IDirectDraw2 *iface, HWND hwnd,
987         DWORD cooplevel)
988 {
989     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
990     TRACE("(%p)->(%p, 0x%08x): Thunking to IDirectDraw4\n", This, hwnd, cooplevel);
991     return IDirectDraw4_SetCooperativeLevel(&This->IDirectDraw4_iface, hwnd, cooplevel);
992 }
993
994 static HRESULT WINAPI IDirectDrawImpl_SetCooperativeLevel(IDirectDraw *iface, HWND hwnd,
995         DWORD cooplevel)
996 {
997     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
998     TRACE("(%p)->(%p, 0x%08x): Thunking to IDirectDraw4\n", This, hwnd, cooplevel);
999     return IDirectDraw4_SetCooperativeLevel(&This->IDirectDraw4_iface, hwnd, cooplevel);
1000 }
1001
1002 static HRESULT WINAPI IDirectDraw4Impl_SetDisplayMode(IDirectDraw4 *iface, DWORD Width,
1003         DWORD Height, DWORD BPP, DWORD RefreshRate, DWORD Flags)
1004 {
1005     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1006     TRACE("(%p)->(%u, %u, %u, %u, 0x%08x)\n", This, Width, Height, BPP, RefreshRate, Flags);
1007     return IDirectDraw4_SetDisplayMode(This->parent, Width, Height, BPP, RefreshRate, Flags);
1008 }
1009
1010 static HRESULT WINAPI IDirectDraw3Impl_SetDisplayMode(IDirectDraw3 *iface, DWORD Width,
1011         DWORD Height, DWORD BPP, DWORD RefreshRate, DWORD Flags)
1012 {
1013     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1014     TRACE("(%p)->(%u, %u, %u, %u, 0x%08x): Thunking to IDirectDraw4\n", This, Width, Height, BPP, RefreshRate, Flags);
1015     return IDirectDraw3_SetDisplayMode(&This->IDirectDraw4_iface, Width, Height, BPP, RefreshRate,
1016             Flags);
1017 }
1018
1019 static HRESULT WINAPI IDirectDraw2Impl_SetDisplayMode(IDirectDraw2 *iface, DWORD Width,
1020         DWORD Height, DWORD BPP, DWORD RefreshRate, DWORD Flags)
1021 {
1022     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1023     TRACE("(%p)->(%u, %u, %u, %u, 0x%08x): Thunking to IDirectDraw4\n", This, Width, Height, BPP, RefreshRate, Flags);
1024     return IDirectDraw3_SetDisplayMode(&This->IDirectDraw4_iface, Width, Height, BPP, RefreshRate,
1025             Flags);
1026 }
1027
1028 static HRESULT WINAPI IDirectDrawImpl_SetDisplayMode(IDirectDraw *iface, DWORD Width, DWORD Height,
1029         DWORD BPP)
1030 {
1031     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1032     TRACE("(%p)->(%u, %u, %u): Thunking to IDirectDraw4\n", This, Width, Height, BPP);
1033     return IDirectDraw3_SetDisplayMode(&This->IDirectDraw4_iface, Width, Height, BPP, 0, 0);
1034 }
1035
1036 static HRESULT WINAPI IDirectDraw4Impl_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD Flags,
1037         HANDLE h)
1038 {
1039     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1040     TRACE("(%p)->(0x%08x, %p)\n", This, Flags, h);
1041     return IDirectDraw4_WaitForVerticalBlank(This->parent, Flags, h);
1042 }
1043
1044 static HRESULT WINAPI IDirectDraw3Impl_WaitForVerticalBlank(IDirectDraw3 *iface, DWORD Flags,
1045         HANDLE h)
1046 {
1047     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1048     TRACE("(%p)->(0x%08x, %p): Thunking to IDirectDraw4\n", This, Flags, h);
1049     return IDirectDraw4_WaitForVerticalBlank(&This->IDirectDraw4_iface, Flags, h);
1050 }
1051
1052 static HRESULT WINAPI IDirectDraw2Impl_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD Flags,
1053         HANDLE h)
1054 {
1055     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1056     TRACE("(%p)->(0x%08x, %p): Thunking to IDirectDraw4\n", This, Flags, h);
1057     return IDirectDraw4_WaitForVerticalBlank(&This->IDirectDraw4_iface, Flags, h);
1058 }
1059
1060 static HRESULT WINAPI IDirectDrawImpl_WaitForVerticalBlank(IDirectDraw *iface, DWORD Flags,
1061         HANDLE h)
1062 {
1063     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1064     TRACE("(%p)->(0x%08x, %p): Thunking to IDirectDraw4\n", This, Flags, h);
1065     return IDirectDraw4_WaitForVerticalBlank(&This->IDirectDraw4_iface, Flags, h);
1066 }
1067
1068 static HRESULT WINAPI IDirectDraw4Impl_GetAvailableVidMem(IDirectDraw4 *iface, DDSCAPS2 *Caps,
1069         DWORD *total, DWORD *free)
1070 {
1071     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1072     TRACE("(%p)->(%p, %p, %p)\n", This, Caps, total, free);
1073     return IDirectDraw4_GetAvailableVidMem(This->parent, Caps, total, free);
1074 }
1075
1076 static HRESULT WINAPI IDirectDraw3Impl_GetAvailableVidMem(IDirectDraw3 *iface, DDSCAPS *Caps,
1077         DWORD *total, DWORD *free)
1078 {
1079     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1080     DDSCAPS2 caps2;
1081     TRACE("(%p)->(%p, %p, %p): Thunking to IDirectDraw4\n", This, Caps, total, free);
1082     memset(&caps2, 0, sizeof(caps2));
1083     caps2.dwCaps = Caps->dwCaps;
1084     return IDirectDraw4_GetAvailableVidMem(&This->IDirectDraw4_iface, &caps2, total, free);
1085 }
1086
1087 static HRESULT WINAPI IDirectDraw2Impl_GetAvailableVidMem(IDirectDraw2 *iface, DDSCAPS *Caps,
1088         DWORD *total, DWORD *free)
1089 {
1090     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1091     DDSCAPS2 caps2;
1092     TRACE("(%p)->(%p, %p, %p): Thunking to IDirectDraw4\n", This, Caps, total, free);
1093     memset(&caps2, 0, sizeof(caps2));
1094     caps2.dwCaps = Caps->dwCaps;
1095     return IDirectDraw4_GetAvailableVidMem(&This->IDirectDraw4_iface, &caps2, total, free);
1096 }
1097
1098 static HRESULT WINAPI IDirectDraw4Impl_GetSurfaceFromDC(IDirectDraw4 *iface, HDC hdc,
1099         IDirectDrawSurface4 **Surface)
1100 {
1101     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1102     HRESULT hr;
1103     TRACE("(%p)->(%p, %p)\n", This, hdc, Surface);
1104     hr = IDirectDraw4_GetSurfaceFromDC(This->parent,hdc, Surface);
1105
1106     return hr;
1107 }
1108
1109 static HRESULT WINAPI IDirectDraw3Impl_GetSurfaceFromDC(IDirectDraw3 *iface, HDC hdc,
1110         IDirectDrawSurface **Surface)
1111 {
1112     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1113     IDirectDrawSurface4 *surf4, *outer;
1114     IDirectDrawSurface *inner;
1115     HRESULT hr;
1116     TRACE("(%p)->(%p, %p): Thunking to IDirectDraw4\n", This, hdc, Surface);
1117
1118     if (!Surface) return E_POINTER;
1119
1120     hr = IDirectDraw4_GetSurfaceFromDC(This->parent, hdc, (IDirectDrawSurface4 **)&inner);
1121     if(FAILED(hr))
1122     {
1123         *Surface = NULL;
1124         return hr;
1125     }
1126
1127     hr = IDirectDrawSurface_QueryInterface(inner, &IID_IDirectDrawSurface4, (void **)&surf4);
1128     IDirectDrawSurface_Release(inner);
1129     if (FAILED(hr))
1130     {
1131         *Surface = NULL;
1132         return hr;
1133     }
1134
1135     outer = dds_get_outer(surf4);
1136     hr = IDirectDrawSurface4_QueryInterface(outer, &IID_IDirectDrawSurface, (void **)Surface);
1137     IDirectDrawSurface4_Release(surf4);
1138     return hr;
1139 }
1140
1141 static HRESULT WINAPI IDirectDraw4Impl_RestoreAllSurfaces(IDirectDraw4 *iface)
1142 {
1143     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1144     TRACE("(%p)\n", This);
1145     return IDirectDraw4_RestoreAllSurfaces(This->parent);
1146 }
1147
1148 static HRESULT WINAPI IDirectDraw4Impl_TestCooperativeLevel(IDirectDraw4 *iface)
1149 {
1150     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1151     TRACE("(%p)\n", This);
1152     return IDirectDraw4_TestCooperativeLevel(This->parent);
1153 }
1154
1155 static HRESULT WINAPI IDirectDraw4Impl_GetDeviceIdentifier(IDirectDraw4 *iface,
1156         DDDEVICEIDENTIFIER *DDDI, DWORD Flags)
1157 {
1158     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1159     TRACE("(%p)->(%p,0x%08x)\n", This, DDDI, Flags);
1160     return IDirectDraw4_GetDeviceIdentifier(This->parent, DDDI, Flags);
1161 }
1162
1163 static const IDirectDrawVtbl IDirectDraw1_Vtbl =
1164 {
1165     IDirectDrawImpl_QueryInterface,
1166     IDirectDrawImpl_AddRef,
1167     IDirectDrawImpl_Release,
1168     IDirectDrawImpl_Compact,
1169     IDirectDrawImpl_CreateClipper,
1170     IDirectDrawImpl_CreatePalette,
1171     IDirectDrawImpl_CreateSurface,
1172     IDirectDrawImpl_DuplicateSurface,
1173     IDirectDrawImpl_EnumDisplayModes,
1174     IDirectDrawImpl_EnumSurfaces,
1175     IDirectDrawImpl_FlipToGDISurface,
1176     IDirectDrawImpl_GetCaps,
1177     IDirectDrawImpl_GetDisplayMode,
1178     IDirectDrawImpl_GetFourCCCodes,
1179     IDirectDrawImpl_GetGDISurface,
1180     IDirectDrawImpl_GetMonitorFrequency,
1181     IDirectDrawImpl_GetScanLine,
1182     IDirectDrawImpl_GetVerticalBlankStatus,
1183     IDirectDrawImpl_Initialize,
1184     IDirectDrawImpl_RestoreDisplayMode,
1185     IDirectDrawImpl_SetCooperativeLevel,
1186     IDirectDrawImpl_SetDisplayMode,
1187     IDirectDrawImpl_WaitForVerticalBlank,
1188 };
1189
1190 static const IDirectDraw2Vtbl IDirectDraw2_Vtbl =
1191 {
1192     IDirectDraw2Impl_QueryInterface,
1193     IDirectDraw2Impl_AddRef,
1194     IDirectDraw2Impl_Release,
1195     IDirectDraw2Impl_Compact,
1196     IDirectDraw2Impl_CreateClipper,
1197     IDirectDraw2Impl_CreatePalette,
1198     IDirectDraw2Impl_CreateSurface,
1199     IDirectDraw2Impl_DuplicateSurface,
1200     IDirectDraw2Impl_EnumDisplayModes,
1201     IDirectDraw2Impl_EnumSurfaces,
1202     IDirectDraw2Impl_FlipToGDISurface,
1203     IDirectDraw2Impl_GetCaps,
1204     IDirectDraw2Impl_GetDisplayMode,
1205     IDirectDraw2Impl_GetFourCCCodes,
1206     IDirectDraw2Impl_GetGDISurface,
1207     IDirectDraw2Impl_GetMonitorFrequency,
1208     IDirectDraw2Impl_GetScanLine,
1209     IDirectDraw2Impl_GetVerticalBlankStatus,
1210     IDirectDraw2Impl_Initialize,
1211     IDirectDraw2Impl_RestoreDisplayMode,
1212     IDirectDraw2Impl_SetCooperativeLevel,
1213     IDirectDraw2Impl_SetDisplayMode,
1214     IDirectDraw2Impl_WaitForVerticalBlank,
1215     IDirectDraw2Impl_GetAvailableVidMem
1216 };
1217
1218 static const IDirectDraw3Vtbl IDirectDraw3_Vtbl =
1219 {
1220     IDirectDraw3Impl_QueryInterface,
1221     IDirectDraw3Impl_AddRef,
1222     IDirectDraw3Impl_Release,
1223     IDirectDraw3Impl_Compact,
1224     IDirectDraw3Impl_CreateClipper,
1225     IDirectDraw3Impl_CreatePalette,
1226     IDirectDraw3Impl_CreateSurface,
1227     IDirectDraw3Impl_DuplicateSurface,
1228     IDirectDraw3Impl_EnumDisplayModes,
1229     IDirectDraw3Impl_EnumSurfaces,
1230     IDirectDraw3Impl_FlipToGDISurface,
1231     IDirectDraw3Impl_GetCaps,
1232     IDirectDraw3Impl_GetDisplayMode,
1233     IDirectDraw3Impl_GetFourCCCodes,
1234     IDirectDraw3Impl_GetGDISurface,
1235     IDirectDraw3Impl_GetMonitorFrequency,
1236     IDirectDraw3Impl_GetScanLine,
1237     IDirectDraw3Impl_GetVerticalBlankStatus,
1238     IDirectDraw3Impl_Initialize,
1239     IDirectDraw3Impl_RestoreDisplayMode,
1240     IDirectDraw3Impl_SetCooperativeLevel,
1241     IDirectDraw3Impl_SetDisplayMode,
1242     IDirectDraw3Impl_WaitForVerticalBlank,
1243     IDirectDraw3Impl_GetAvailableVidMem,
1244     IDirectDraw3Impl_GetSurfaceFromDC,
1245 };
1246
1247 static const IDirectDraw4Vtbl IDirectDraw4_Vtbl =
1248 {
1249     IDirectDraw4Impl_QueryInterface,
1250     IDirectDraw4Impl_AddRef,
1251     IDirectDraw4Impl_Release,
1252     IDirectDraw4Impl_Compact,
1253     IDirectDraw4Impl_CreateClipper,
1254     IDirectDraw4Impl_CreatePalette,
1255     IDirectDraw4Impl_CreateSurface,
1256     IDirectDraw4Impl_DuplicateSurface,
1257     IDirectDraw4Impl_EnumDisplayModes,
1258     IDirectDraw4Impl_EnumSurfaces,
1259     IDirectDraw4Impl_FlipToGDISurface,
1260     IDirectDraw4Impl_GetCaps,
1261     IDirectDraw4Impl_GetDisplayMode,
1262     IDirectDraw4Impl_GetFourCCCodes,
1263     IDirectDraw4Impl_GetGDISurface,
1264     IDirectDraw4Impl_GetMonitorFrequency,
1265     IDirectDraw4Impl_GetScanLine,
1266     IDirectDraw4Impl_GetVerticalBlankStatus,
1267     IDirectDraw4Impl_Initialize,
1268     IDirectDraw4Impl_RestoreDisplayMode,
1269     IDirectDraw4Impl_SetCooperativeLevel,
1270     IDirectDraw4Impl_SetDisplayMode,
1271     IDirectDraw4Impl_WaitForVerticalBlank,
1272     IDirectDraw4Impl_GetAvailableVidMem,
1273     IDirectDraw4Impl_GetSurfaceFromDC,
1274     IDirectDraw4Impl_RestoreAllSurfaces,
1275     IDirectDraw4Impl_TestCooperativeLevel,
1276     IDirectDraw4Impl_GetDeviceIdentifier
1277 };
1278
1279 /*******************************************************************************
1280  * IDirectDrawFactoryImpl_CreateDirectDraw
1281  *******************************************************************************/
1282 HRESULT WINAPI
1283 IDirectDrawFactoryImpl_CreateDirectDraw(IDirectDrawFactory* iface,
1284                                         GUID * pGUID,
1285                                         HWND hWnd,
1286                                         DWORD dwCoopLevelFlags,
1287                                         DWORD dwReserved,
1288                                         IUnknown *pUnkOuter,
1289                                         IDirectDraw **ppDirectDraw)
1290 {
1291     HRESULT hr;
1292     IDirectDrawImpl *object = NULL;
1293     IDirectDraw *parent = NULL;
1294
1295     TRACE("(%p)->(%s,%p,0x%08x,0x%08x,%p,%p)\n", iface, debugstr_guid(pGUID), hWnd, dwCoopLevelFlags,
1296           dwReserved, pUnkOuter, ppDirectDraw);
1297
1298     if(pUnkOuter)
1299     {
1300         FIXME("Implement aggregation in ddrawex's IDirectDraw interface\n");
1301     }
1302
1303     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1304     if(!object)
1305     {
1306         ERR("Out of memory\n");
1307         hr = E_OUTOFMEMORY;
1308         goto err;
1309     }
1310     object->ref = 1;
1311     object->IDirectDraw_iface.lpVtbl = &IDirectDraw1_Vtbl;
1312     object->IDirectDraw2_iface.lpVtbl = &IDirectDraw2_Vtbl;
1313     object->IDirectDraw3_iface.lpVtbl = &IDirectDraw3_Vtbl;
1314     object->IDirectDraw4_iface.lpVtbl = &IDirectDraw4_Vtbl;
1315
1316     hr = DirectDrawCreate(pGUID, &parent, NULL);
1317     if (FAILED(hr)) goto err;
1318
1319     hr = IDirectDraw_QueryInterface(parent, &IID_IDirectDraw4, (void **) &object->parent);
1320     if(FAILED(hr)) goto err;
1321
1322     hr = IDirectDraw_SetCooperativeLevel(&object->IDirectDraw_iface, hWnd, dwCoopLevelFlags);
1323     if (FAILED(hr)) goto err;
1324
1325     *ppDirectDraw = &object->IDirectDraw_iface;
1326     IDirectDraw_Release(parent);
1327     return DD_OK;
1328
1329 err:
1330     if(object && object->parent) IDirectDraw4_Release(object->parent);
1331     if(parent) IDirectDraw_Release(parent);
1332     HeapFree(GetProcessHeap(), 0, object);
1333     *ppDirectDraw = NULL;
1334     return hr;
1335 }
1336
1337 IDirectDraw4 *dd_get_inner(IDirectDraw4 *outer)
1338 {
1339     IDirectDrawImpl *This = impl_from_IDirectDraw4(outer);
1340
1341     if (outer->lpVtbl != &IDirectDraw4_Vtbl) return NULL;
1342     return This->parent;
1343 }