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