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