ddrawex: Start some tests.
[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     TRACE("(%p)(%p, %p, %p)\n", This, DDSD, Surf, UnkOuter);
390
391     if(UnkOuter != NULL)
392     {
393         /* Handle this in this dll. Don't forward the UnkOuter to ddraw.dll */
394         FIXME("Implement aggregation for ddrawex surfaces\n");
395     }
396
397     return IDirectDraw4_CreateSurface(This->parent, DDSD, Surf, UnkOuter);
398 }
399
400 static void DDSD_to_DDSD2(const DDSURFACEDESC *in, DDSURFACEDESC2 *out)
401 {
402     memset(out, 0, sizeof(*out));
403     out->dwSize = sizeof(*out);
404     out->dwFlags = in->dwFlags;
405     if(in->dwFlags & DDSD_WIDTH) out->dwWidth = in->dwWidth;
406     if(in->dwFlags & DDSD_HEIGHT) out->dwHeight = in->dwHeight;
407     if(in->dwFlags & DDSD_PIXELFORMAT) out->ddpfPixelFormat = in->ddpfPixelFormat;
408     if(in->dwFlags & DDSD_CAPS) out->ddsCaps.dwCaps = in->ddsCaps.dwCaps;
409     if(in->dwFlags & DDSD_PITCH) out->lPitch = in->lPitch;
410     if(in->dwFlags & DDSD_BACKBUFFERCOUNT) out->dwBackBufferCount = in->dwBackBufferCount;
411     if(in->dwFlags & DDSD_ZBUFFERBITDEPTH) out->dwMipMapCount = in->dwZBufferBitDepth; /* same union */
412     if(in->dwFlags & DDSD_ALPHABITDEPTH) out->dwAlphaBitDepth = in->dwAlphaBitDepth;
413     if(in->dwFlags & DDSD_LPSURFACE) out->lpSurface = in->lpSurface;
414     if(in->dwFlags & DDSD_CKDESTOVERLAY) out->ddckCKDestOverlay = in->ddckCKDestOverlay;
415     if(in->dwFlags & DDSD_CKDESTBLT) out->ddckCKDestBlt = in->ddckCKDestBlt;
416     if(in->dwFlags & DDSD_CKSRCOVERLAY) out->ddckCKSrcOverlay = in->ddckCKSrcOverlay;
417     if(in->dwFlags & DDSD_CKSRCBLT) out->ddckCKSrcBlt = in->ddckCKSrcBlt;
418     if(in->dwFlags & DDSD_MIPMAPCOUNT) out->dwMipMapCount = in->dwMipMapCount;
419     if(in->dwFlags & DDSD_REFRESHRATE) out->dwRefreshRate = in->dwRefreshRate;
420     if(in->dwFlags & DDSD_LINEARSIZE) out->dwLinearSize = in->dwLinearSize;
421     /* Does not exist in DDSURFACEDESC:
422      * DDSD_TEXTURESTAGE, DDSD_FVF, DDSD_SRCVBHANDLE,
423      */
424 }
425
426 static void DDSD2_to_DDSD(const DDSURFACEDESC2 *in, DDSURFACEDESC *out)
427 {
428     memset(out, 0, sizeof(*out));
429     out->dwSize = sizeof(*out);
430     out->dwFlags = in->dwFlags;
431     if(in->dwFlags & DDSD_WIDTH) out->dwWidth = in->dwWidth;
432     if(in->dwFlags & DDSD_HEIGHT) out->dwHeight = in->dwHeight;
433     if(in->dwFlags & DDSD_PIXELFORMAT) out->ddpfPixelFormat = in->ddpfPixelFormat;
434     if(in->dwFlags & DDSD_CAPS) out->ddsCaps.dwCaps = in->ddsCaps.dwCaps;
435     if(in->dwFlags & DDSD_PITCH) out->lPitch = in->lPitch;
436     if(in->dwFlags & DDSD_BACKBUFFERCOUNT) out->dwBackBufferCount = in->dwBackBufferCount;
437     if(in->dwFlags & DDSD_ZBUFFERBITDEPTH) out->dwZBufferBitDepth = in->dwMipMapCount; /* same union */
438     if(in->dwFlags & DDSD_ALPHABITDEPTH) out->dwAlphaBitDepth = in->dwAlphaBitDepth;
439     if(in->dwFlags & DDSD_LPSURFACE) out->lpSurface = in->lpSurface;
440     if(in->dwFlags & DDSD_CKDESTOVERLAY) out->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->dwMipMapCount = in->dwMipMapCount;
445     if(in->dwFlags & DDSD_REFRESHRATE) out->dwRefreshRate = in->dwRefreshRate;
446     if(in->dwFlags & DDSD_LINEARSIZE) out->dwLinearSize = in->dwLinearSize;
447     /* Does not exist in DDSURFACEDESC:
448      * DDSD_TEXTURESTAGE, DDSD_FVF, DDSD_SRCVBHANDLE,
449      */
450     if(in->dwFlags & DDSD_TEXTURESTAGE) WARN("Does not exist in DDSURFACEDESC: DDSD_TEXTURESTAGE\n");
451     if(in->dwFlags & DDSD_FVF) WARN("Does not exist in DDSURFACEDESC: DDSD_FVF\n");
452     if(in->dwFlags & DDSD_SRCVBHANDLE) WARN("Does not exist in DDSURFACEDESC: DDSD_SRCVBHANDLE\n");
453     out->dwFlags &= ~(DDSD_TEXTURESTAGE | DDSD_FVF | DDSD_SRCVBHANDLE);
454 }
455
456 static HRESULT WINAPI
457 IDirectDraw3Impl_CreateSurface(IDirectDraw3 *iface,
458                                DDSURFACEDESC *DDSD,
459                                IDirectDrawSurface **Surf,
460                                IUnknown *UnkOuter)
461 {
462     IDirectDrawImpl *This = impl_from_dd3(iface);
463     DDSURFACEDESC2 ddsd2;
464     IDirectDrawSurface4 *surf4 = NULL;
465     HRESULT hr;
466     TRACE("Thunking to IDirectDraw4\n");
467
468     DDSD_to_DDSD2(DDSD, &ddsd2);
469
470     hr = IDirectDraw4_CreateSurface(dd4_from_impl(This), &ddsd2, &surf4, UnkOuter);
471     if(FAILED(hr))
472     {
473         *Surf = NULL;
474         return hr;
475     }
476
477     IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **) Surf);
478     IDirectDrawSurface4_Release(surf4);
479     return hr;
480 }
481
482 static HRESULT WINAPI
483 IDirectDraw2Impl_CreateSurface(IDirectDraw2 *iface,
484                                DDSURFACEDESC *DDSD,
485                                IDirectDrawSurface **Surf,
486                                IUnknown *UnkOuter)
487 {
488     IDirectDrawImpl *This = impl_from_dd2(iface);
489     TRACE("Thunking to IDirectDraw3\n");
490     return IDirectDraw3_CreateSurface(dd3_from_impl(This), DDSD, Surf, UnkOuter);
491 }
492
493 static HRESULT WINAPI
494 IDirectDrawImpl_CreateSurface(IDirectDraw *iface,
495                               DDSURFACEDESC *DDSD,
496                               IDirectDrawSurface **Surf,
497                               IUnknown *UnkOuter)
498 {
499     IDirectDrawImpl *This = impl_from_dd1(iface);
500     TRACE("Thunking to IDirectDraw3\n");
501     return IDirectDraw3_CreateSurface(dd3_from_impl(This), DDSD, Surf, UnkOuter);
502 }
503
504 static HRESULT WINAPI
505 IDirectDraw4Impl_DuplicateSurface(IDirectDraw4 *iface,
506                                   IDirectDrawSurface4 *src,
507                                   IDirectDrawSurface4 **dst)
508 {
509     IDirectDrawImpl *This = impl_from_dd4(iface);
510     TRACE("(%p)->(%p,%p)\n", This, src, dst);
511
512     return IDirectDraw4_DuplicateSurface(This->parent, src, dst);
513 }
514
515 static HRESULT WINAPI
516 IDirectDraw3Impl_DuplicateSurface(IDirectDraw3 *iface,
517                                   IDirectDrawSurface *src,
518                                   IDirectDrawSurface **dst)
519 {
520     IDirectDrawImpl *This = impl_from_dd3(iface);
521     IDirectDrawSurface4 *src_4;
522     IDirectDrawSurface4 *dst_4;
523     HRESULT hr;
524
525     TRACE("Thunking to IDirectDraw4\n");
526     IDirectDrawSurface_QueryInterface(src, &IID_IDirectDrawSurface4, (void **) &src_4);
527     hr = IDirectDraw4_DuplicateSurface(dd4_from_impl(This), src_4, &dst_4);
528     IDirectDrawSurface4_Release(src_4);
529
530     if(FAILED(hr))
531     {
532         *dst = NULL;
533         return hr;
534     }
535     IDirectDrawSurface4_QueryInterface(dst_4, &IID_IDirectDrawSurface, (void **) dst);
536     IDirectDrawSurface4_Release(dst_4);
537     return hr;
538 }
539
540 static HRESULT WINAPI
541 IDirectDraw2Impl_DuplicateSurface(IDirectDraw2 *iface,
542                                   IDirectDrawSurface *src,
543                                   IDirectDrawSurface **dst)
544 {
545     IDirectDrawImpl *This = impl_from_dd2(iface);
546     TRACE("Thunking to IDirectDraw3\n");
547     return IDirectDraw3_DuplicateSurface(dd3_from_impl(This), src, dst);
548 }
549
550 static HRESULT WINAPI
551 IDirectDrawImpl_DuplicateSurface(IDirectDraw *iface,
552                                  IDirectDrawSurface *src,
553                                  IDirectDrawSurface **dst)
554 {
555     IDirectDrawImpl *This = impl_from_dd1(iface);
556     TRACE("Thunking to IDirectDraw3\n");
557     return IDirectDraw3_DuplicateSurface(dd3_from_impl(This), src, dst);
558 }
559
560 static HRESULT WINAPI
561 IDirectDraw4Impl_EnumDisplayModes(IDirectDraw4 *iface,
562                                   DWORD Flags,
563                                   DDSURFACEDESC2 *DDSD,
564                                   void *Context,
565                                   LPDDENUMMODESCALLBACK2 cb)
566 {
567     IDirectDrawImpl *This = impl_from_dd4(iface);
568     TRACE("(%p)->(0x%08x,%p,%p,%p)\n", This, Flags, DDSD, Context, cb);
569
570     return IDirectDraw4_EnumDisplayModes(This->parent, Flags, DDSD, Context, cb);
571 }
572
573 struct enummodes_ctx
574 {
575     LPDDENUMMODESCALLBACK orig_cb;
576     void *orig_ctx;
577 };
578
579 static HRESULT WINAPI
580 enum_modes_cb2(DDSURFACEDESC2 *ddsd2, void *vctx)
581 {
582     struct enummodes_ctx *ctx = (struct enummodes_ctx *) vctx;
583     DDSURFACEDESC ddsd;
584
585     DDSD2_to_DDSD(ddsd2, &ddsd);
586     return ctx->orig_cb(&ddsd, ctx->orig_ctx);
587 }
588
589 static HRESULT WINAPI
590 IDirectDraw3Impl_EnumDisplayModes(IDirectDraw3 *iface,
591                                   DWORD Flags,
592                                   DDSURFACEDESC *DDSD,
593                                   void *Context,
594                                   LPDDENUMMODESCALLBACK cb)
595 {
596     IDirectDrawImpl *This = impl_from_dd3(iface);
597     DDSURFACEDESC2 ddsd2;
598     struct enummodes_ctx ctx;
599     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw4\n", This, Flags, DDSD, Context, cb);
600
601     DDSD_to_DDSD2(DDSD, &ddsd2);
602     ctx.orig_cb = cb;
603     ctx.orig_ctx = Context;
604     return IDirectDraw4_EnumDisplayModes(dd4_from_impl(This), Flags, &ddsd2, &ctx, enum_modes_cb2);
605 }
606
607 static HRESULT WINAPI
608 IDirectDraw2Impl_EnumDisplayModes(IDirectDraw2 *iface,
609                                   DWORD Flags,
610                                   DDSURFACEDESC *DDSD,
611                                   void *Context,
612                                   LPDDENUMMODESCALLBACK cb)
613 {
614     IDirectDrawImpl *This = impl_from_dd2(iface);
615     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw3\n", This, Flags, DDSD, Context, cb);
616     return IDirectDraw3_EnumDisplayModes(dd3_from_impl(This), Flags, DDSD, Context, cb);
617 }
618
619 static HRESULT WINAPI
620 IDirectDrawImpl_EnumDisplayModes(IDirectDraw *iface,
621                                  DWORD Flags,
622                                  DDSURFACEDESC *DDSD,
623                                  void *Context,
624                                  LPDDENUMMODESCALLBACK cb)
625 {
626     IDirectDrawImpl *This = impl_from_dd1(iface);
627     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw3\n", This, Flags, DDSD, Context, cb);
628     return IDirectDraw3_EnumDisplayModes(dd3_from_impl(This), Flags, DDSD, Context, cb);
629 }
630
631 static HRESULT WINAPI
632 IDirectDraw4Impl_EnumSurfaces(IDirectDraw4 *iface,
633                               DWORD Flags,
634                               DDSURFACEDESC2 *DDSD,
635                               void *Context,
636                               LPDDENUMSURFACESCALLBACK2 Callback)
637 {
638     IDirectDrawImpl *This = impl_from_dd4(iface);
639     TRACE("(%p)->(0x%08x,%p,%p,%p)\n", This, Flags, DDSD, Context, Callback);
640
641     return IDirectDraw4Impl_EnumSurfaces(This->parent, Flags, DDSD, Context, Callback);
642 }
643
644 struct enumsurfaces_ctx
645 {
646     LPDDENUMSURFACESCALLBACK orig_cb;
647     void *orig_ctx;
648 };
649
650 static HRESULT WINAPI
651 enum_surfaces_cb2(IDirectDrawSurface4 *surf4, DDSURFACEDESC2 *ddsd2, void *vctx)
652 {
653     struct enumsurfaces_ctx *ctx = (struct enumsurfaces_ctx *) vctx;
654     IDirectDrawSurface *surf1;
655     DDSURFACEDESC ddsd;
656
657     /* Keep the reference, it goes to the application */
658     IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **) &surf1);
659     /* Release the reference this function got */
660     IDirectDrawSurface4_Release(surf4);
661
662     DDSD2_to_DDSD(ddsd2, &ddsd);
663     return ctx->orig_cb(surf1, &ddsd, ctx->orig_ctx);
664 }
665
666 static HRESULT WINAPI
667 IDirectDraw3Impl_EnumSurfaces(IDirectDraw3 *iface,
668                               DWORD Flags,
669                               DDSURFACEDESC *DDSD,
670                               void *Context,
671                               LPDDENUMSURFACESCALLBACK Callback)
672 {
673     IDirectDrawImpl *This = impl_from_dd3(iface);
674     DDSURFACEDESC2 ddsd2;
675     struct enumsurfaces_ctx ctx;
676     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw4\n", This, Flags, DDSD, Context, Callback);
677
678     DDSD_to_DDSD2(DDSD, &ddsd2);
679     ctx.orig_cb = Callback;
680     ctx.orig_ctx = Context;
681     return IDirectDraw4_EnumSurfaces(dd4_from_impl(This), Flags, &ddsd2, &ctx, enum_surfaces_cb2);
682 }
683
684 static HRESULT WINAPI
685 IDirectDraw2Impl_EnumSurfaces(IDirectDraw2 *iface,
686                               DWORD Flags,
687                               DDSURFACEDESC *DDSD,
688                               void *Context,
689                               LPDDENUMSURFACESCALLBACK Callback)
690 {
691     IDirectDrawImpl *This = impl_from_dd2(iface);
692     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw3\n", This, Flags, DDSD, Context, Callback);
693     return IDirectDraw3_EnumSurfaces(dd3_from_impl(This), Flags, DDSD, Context, Callback);
694 }
695
696 static HRESULT WINAPI
697 IDirectDrawImpl_EnumSurfaces(IDirectDraw *iface,
698                              DWORD Flags,
699                              DDSURFACEDESC *DDSD,
700                              void *Context,
701                              LPDDENUMSURFACESCALLBACK Callback)
702 {
703     IDirectDrawImpl *This = impl_from_dd1(iface);
704     TRACE("(%p)->(0x%08x,%p,%p,%p): Thunking to IDirectDraw3\n", This, Flags, DDSD, Context, Callback);
705     return IDirectDraw3_EnumSurfaces(dd3_from_impl(This), Flags, DDSD, Context, Callback);
706 }
707
708 static HRESULT WINAPI
709 IDirectDraw4Impl_FlipToGDISurface(IDirectDraw4 *iface)
710 {
711     IDirectDrawImpl *This = impl_from_dd4(iface);
712     TRACE("(%p)\n", This);
713
714     return IDirectDraw4_FlipToGDISurface(This->parent);
715 }
716
717 static HRESULT WINAPI
718 IDirectDraw3Impl_FlipToGDISurface(IDirectDraw3 *iface)
719 {
720     IDirectDrawImpl *This = impl_from_dd3(iface);
721     TRACE("(%p). Thunking to IDirectDraw4\n", This);
722     return IDirectDraw4_FlipToGDISurface(dd4_from_impl(This));
723 }
724
725 static HRESULT WINAPI
726 IDirectDraw2Impl_FlipToGDISurface(IDirectDraw2 *iface)
727 {
728     IDirectDrawImpl *This = impl_from_dd2(iface);
729     TRACE("(%p). Thunking to IDirectDraw4\n", This);
730     return IDirectDraw4_FlipToGDISurface(dd4_from_impl(This));
731 }
732
733 static HRESULT WINAPI
734 IDirectDrawImpl_FlipToGDISurface(IDirectDraw *iface)
735 {
736     IDirectDrawImpl *This = impl_from_dd1(iface);
737     TRACE("(%p). Thunking to IDirectDraw4\n", This);
738     return IDirectDraw4_FlipToGDISurface(dd4_from_impl(This));
739 }
740
741 static HRESULT WINAPI
742 IDirectDraw4Impl_GetCaps(IDirectDraw4 *iface,
743                          DDCAPS *DriverCaps,
744                          DDCAPS *HELCaps)
745 {
746     IDirectDrawImpl *This = impl_from_dd4(iface);
747     TRACE("(%p)->(%p,%p)\n", This, DriverCaps, HELCaps);
748     return IDirectDraw4_GetCaps(This->parent, DriverCaps, HELCaps);
749 }
750
751 static HRESULT WINAPI
752 IDirectDraw3Impl_GetCaps(IDirectDraw3 *iface,
753                          DDCAPS *DriverCaps,
754                          DDCAPS *HELCaps)
755 {
756     IDirectDrawImpl *This = impl_from_dd3(iface);
757     TRACE("(%p)->(%p,%p). Thunking to IDirectDraw4\n", This, DriverCaps, HELCaps);
758     return IDirectDraw4_GetCaps(dd4_from_impl(This), DriverCaps, HELCaps);
759 }
760
761 static HRESULT WINAPI
762 IDirectDraw2Impl_GetCaps(IDirectDraw2 *iface,
763                          DDCAPS *DriverCaps,
764                          DDCAPS *HELCaps)
765 {
766     IDirectDrawImpl *This = impl_from_dd2(iface);
767     TRACE("(%p)->(%p,%p). Thunking to IDirectDraw4\n", This, DriverCaps, HELCaps);
768     return IDirectDraw4_GetCaps(dd4_from_impl(This), DriverCaps, HELCaps);
769 }
770
771 static HRESULT WINAPI
772 IDirectDrawImpl_GetCaps(IDirectDraw *iface,
773                         DDCAPS *DriverCaps,
774                         DDCAPS *HELCaps)
775 {
776     IDirectDrawImpl *This = impl_from_dd1(iface);
777     TRACE("(%p)->(%p,%p). Thunking to IDirectDraw4\n", This, DriverCaps, HELCaps);
778     return IDirectDraw4_GetCaps(dd4_from_impl(This), DriverCaps, HELCaps);
779 }
780
781 static HRESULT WINAPI
782 IDirectDraw4Impl_GetDisplayMode(IDirectDraw4 *iface,
783                                 DDSURFACEDESC2 *DDSD)
784 {
785     IDirectDrawImpl *This = impl_from_dd4(iface);
786     TRACE("(%p)->(%p)\n", This, DDSD);
787     return IDirectDraw4_GetDisplayMode(This->parent, DDSD);
788 }
789
790 static HRESULT WINAPI
791 IDirectDraw3Impl_GetDisplayMode(IDirectDraw3 *iface,
792                                 DDSURFACEDESC *DDSD)
793 {
794     IDirectDrawImpl *This = impl_from_dd3(iface);
795     DDSURFACEDESC2 ddsd2;
796     HRESULT hr;
797
798     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, DDSD);
799     hr = IDirectDraw4_GetDisplayMode(dd4_from_impl(This), &ddsd2);
800     DDSD2_to_DDSD(&ddsd2, DDSD);
801     return hr;
802 }
803
804 static HRESULT WINAPI
805 IDirectDraw2Impl_GetDisplayMode(IDirectDraw2 *iface,
806                                 DDSURFACEDESC *DDSD)
807 {
808     IDirectDrawImpl *This = impl_from_dd2(iface);
809     TRACE("(%p)->(%p): Thunking to IDirectDraw3\n", This, DDSD);
810     return IDirectDraw3_GetDisplayMode(dd3_from_impl(This), DDSD);
811 }
812
813 static HRESULT WINAPI
814 IDirectDrawImpl_GetDisplayMode(IDirectDraw *iface,
815                                DDSURFACEDESC *DDSD)
816 {
817     IDirectDrawImpl *This = impl_from_dd1(iface);
818     TRACE("(%p)->(%p): Thunking to IDirectDraw3\n", This, DDSD);
819     return IDirectDraw3_GetDisplayMode(dd3_from_impl(This), DDSD);
820 }
821
822 static HRESULT WINAPI
823 IDirectDraw4Impl_GetFourCCCodes(IDirectDraw4 *iface,
824                                 DWORD *NumCodes,
825                                 DWORD *Codes)
826 {
827     IDirectDrawImpl *This = impl_from_dd4(iface);
828     TRACE("(%p)->(%p, %p):\n", This, NumCodes, Codes);
829     return IDirectDraw4_GetFourCCCodes(This->parent, NumCodes, Codes);
830 }
831
832 static HRESULT WINAPI
833 IDirectDraw3Impl_GetFourCCCodes(IDirectDraw3 *iface,
834                                 DWORD *NumCodes,
835                                 DWORD *Codes)
836 {
837     IDirectDrawImpl *This = impl_from_dd3(iface);
838     TRACE("(%p)->(%p, %p): Thunking to IDirectDraw4\n", This, NumCodes, Codes);
839     return IDirectDraw4_GetFourCCCodes(dd4_from_impl(This), NumCodes, Codes);
840 }
841
842 static HRESULT WINAPI
843 IDirectDraw2Impl_GetFourCCCodes(IDirectDraw2 *iface,
844                                 DWORD *NumCodes,
845                                 DWORD *Codes)
846 {
847     IDirectDrawImpl *This = impl_from_dd2(iface);
848     TRACE("(%p)->(%p, %p): Thunking to IDirectDraw4\n", This, NumCodes, Codes);
849     return IDirectDraw4_GetFourCCCodes(dd4_from_impl(This), NumCodes, Codes);
850 }
851
852 static HRESULT WINAPI
853 IDirectDrawImpl_GetFourCCCodes(IDirectDraw *iface,
854                                DWORD *NumCodes,
855                                DWORD *Codes)
856 {
857     IDirectDrawImpl *This = impl_from_dd1(iface);
858     TRACE("(%p)->(%p, %p): Thunking to IDirectDraw4\n", This, NumCodes, Codes);
859     return IDirectDraw4_GetFourCCCodes(dd4_from_impl(This), NumCodes, Codes);
860 }
861
862 static HRESULT WINAPI
863 IDirectDraw4Impl_GetGDISurface(IDirectDraw4 *iface,
864                                IDirectDrawSurface4 **GDISurface)
865 {
866     IDirectDrawImpl *This = impl_from_dd4(iface);
867     TRACE("(%p)->(%p)\n", This, GDISurface);
868     return IDirectDraw4_GetGDISurface(This->parent, GDISurface);
869 }
870
871 static HRESULT WINAPI
872 IDirectDraw3Impl_GetGDISurface(IDirectDraw3 *iface,
873                                IDirectDrawSurface **GDISurface)
874 {
875     IDirectDrawImpl *This = impl_from_dd3(iface);
876     IDirectDrawSurface4 *surf4;
877     HRESULT hr;
878     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, GDISurface);
879
880     hr = IDirectDraw4_GetGDISurface(dd4_from_impl(This), &surf4);
881     if(FAILED(hr)) {
882         *GDISurface = NULL;
883         return hr;
884     }
885
886     /* Release the reference we got from the DDraw4 call, and pass a reference to the caller */
887     IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **) GDISurface);
888     IDirectDrawSurface4_Release(surf4);
889     return hr;
890 }
891
892 static HRESULT WINAPI
893 IDirectDraw2Impl_GetGDISurface(IDirectDraw2 *iface,
894                                IDirectDrawSurface **GDISurface)
895 {
896     IDirectDrawImpl *This = impl_from_dd2(iface);
897     TRACE("(%p)->(%p): Thunking to IDirectDraw3\n", This, GDISurface);
898     return IDirectDraw3_GetGDISurface(dd3_from_impl(This), GDISurface);
899 }
900
901 static HRESULT WINAPI
902 IDirectDrawImpl_GetGDISurface(IDirectDraw *iface,
903                               IDirectDrawSurface **GDISurface)
904 {
905     IDirectDrawImpl *This = impl_from_dd1(iface);
906     TRACE("(%p)->(%p): Thunking to IDirectDraw3\n", This, GDISurface);
907     return IDirectDraw3_GetGDISurface(dd3_from_impl(This), GDISurface);
908 }
909
910 static HRESULT WINAPI
911 IDirectDraw4Impl_GetMonitorFrequency(IDirectDraw4 *iface,
912                                      DWORD *Freq)
913 {
914     IDirectDrawImpl *This = impl_from_dd4(iface);
915     TRACE("(%p)->(%p)\n", This, Freq);
916     return IDirectDraw4_GetMonitorFrequency(This->parent, Freq);
917 }
918
919 static HRESULT WINAPI
920 IDirectDraw3Impl_GetMonitorFrequency(IDirectDraw3 *iface,
921                                      DWORD *Freq)
922 {
923     IDirectDrawImpl *This = impl_from_dd3(iface);
924     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Freq);
925     return IDirectDraw4_GetMonitorFrequency(dd4_from_impl(This), Freq);
926 }
927
928 static HRESULT WINAPI
929 IDirectDraw2Impl_GetMonitorFrequency(IDirectDraw2 *iface,
930                                      DWORD *Freq)
931 {
932     IDirectDrawImpl *This = impl_from_dd2(iface);
933     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Freq);
934     return IDirectDraw4_GetMonitorFrequency(dd4_from_impl(This), Freq);
935 }
936
937 static HRESULT WINAPI
938 IDirectDrawImpl_GetMonitorFrequency(IDirectDraw *iface,
939                                     DWORD *Freq)
940 {
941     IDirectDrawImpl *This = impl_from_dd1(iface);
942     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Freq);
943     return IDirectDraw4_GetMonitorFrequency(dd4_from_impl(This), Freq);
944 }
945
946 static HRESULT WINAPI
947 IDirectDraw4Impl_GetScanLine(IDirectDraw4 *iface,
948                              DWORD *Scanline)
949 {
950     IDirectDrawImpl *This = impl_from_dd4(iface);
951     TRACE("(%p)->(%p)\n", This, Scanline);
952     return IDirectDraw4_GetScanLine(This->parent, Scanline);
953 }
954
955 static HRESULT WINAPI
956 IDirectDraw3Impl_GetScanLine(IDirectDraw3 *iface,
957                              DWORD *Scanline)
958 {
959     IDirectDrawImpl *This = impl_from_dd3(iface);
960     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Scanline);
961     return IDirectDraw4_GetScanLine(dd4_from_impl(This), Scanline);
962 }
963
964 static HRESULT WINAPI
965 IDirectDraw2Impl_GetScanLine(IDirectDraw2 *iface,
966                              DWORD *Scanline)
967 {
968     IDirectDrawImpl *This = impl_from_dd2(iface);
969     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Scanline);
970     return IDirectDraw4_GetScanLine(dd4_from_impl(This), Scanline);
971 }
972
973 static HRESULT WINAPI
974 IDirectDrawImpl_GetScanLine(IDirectDraw *iface,
975                             DWORD *Scanline)
976 {
977     IDirectDrawImpl *This = impl_from_dd1(iface);
978     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, Scanline);
979     return IDirectDraw4_GetScanLine(dd4_from_impl(This), Scanline);
980 }
981
982 static HRESULT WINAPI
983 IDirectDraw4Impl_GetVerticalBlankStatus(IDirectDraw4 *iface,
984                                         BOOL *status)
985 {
986     IDirectDrawImpl *This = impl_from_dd4(iface);
987     TRACE("(%p)->(%p)\n", This, status);
988     return IDirectDraw4_GetVerticalBlankStatus(This->parent, status);
989 }
990
991 static HRESULT WINAPI
992 IDirectDraw3Impl_GetVerticalBlankStatus(IDirectDraw3 *iface,
993                                         BOOL *status)
994 {
995     IDirectDrawImpl *This = impl_from_dd3(iface);
996     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, status);
997     return IDirectDraw4_GetVerticalBlankStatus(dd4_from_impl(This), status);
998 }
999
1000 static HRESULT WINAPI
1001 IDirectDraw2Impl_GetVerticalBlankStatus(IDirectDraw2 *iface,
1002                                         BOOL *status)
1003 {
1004     IDirectDrawImpl *This = impl_from_dd2(iface);
1005     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, status);
1006     return IDirectDraw4_GetVerticalBlankStatus(dd4_from_impl(This), status);
1007 }
1008
1009 static HRESULT WINAPI
1010 IDirectDrawImpl_GetVerticalBlankStatus(IDirectDraw *iface,
1011                                        BOOL *status)
1012 {
1013     IDirectDrawImpl *This = impl_from_dd1(iface);
1014     TRACE("(%p)->(%p): Thunking to IDirectDraw4\n", This, status);
1015     return IDirectDraw4_GetVerticalBlankStatus(dd4_from_impl(This), status);
1016 }
1017
1018 static HRESULT WINAPI
1019 IDirectDraw4Impl_Initialize(IDirectDraw4 *iface,
1020                             GUID *Guid)
1021 {
1022     IDirectDrawImpl *This = impl_from_dd4(iface);
1023     TRACE("(%p)->(%s)\n", This, debugstr_guid(Guid));
1024     return IDirectDraw4_Initialize(This->parent, Guid);
1025 }
1026
1027 static HRESULT WINAPI
1028 IDirectDraw3Impl_Initialize(IDirectDraw3 *iface,
1029                             GUID *Guid)
1030 {
1031     IDirectDrawImpl *This = impl_from_dd3(iface);
1032     TRACE("(%p)->(%s): Thunking to IDirectDraw4\n", This, debugstr_guid(Guid));
1033     return IDirectDraw4_Initialize(dd4_from_impl(This), Guid);
1034 }
1035
1036 static HRESULT WINAPI
1037 IDirectDraw2Impl_Initialize(IDirectDraw2 *iface,
1038                             GUID *Guid)
1039 {
1040     IDirectDrawImpl *This = impl_from_dd2(iface);
1041     TRACE("(%p)->(%s): Thunking to IDirectDraw4\n", This, debugstr_guid(Guid));
1042     return IDirectDraw4_Initialize(dd4_from_impl(This), Guid);
1043 }
1044
1045 static HRESULT WINAPI
1046 IDirectDrawImpl_Initialize(IDirectDraw *iface,
1047                            GUID *Guid)
1048 {
1049     IDirectDrawImpl *This = impl_from_dd1(iface);
1050     TRACE("(%p)->(%s): Thunking to IDirectDraw4\n", This, debugstr_guid(Guid));
1051     return IDirectDraw4_Initialize(dd4_from_impl(This), Guid);
1052 }
1053
1054 static HRESULT WINAPI
1055 IDirectDraw4Impl_RestoreDisplayMode(IDirectDraw4 *iface)
1056 {
1057     IDirectDrawImpl *This = impl_from_dd4(iface);
1058     TRACE("(%p)\n", This);
1059     return IDirectDraw4_RestoreDisplayMode(This->parent);
1060 }
1061
1062 static HRESULT WINAPI
1063 IDirectDraw3Impl_RestoreDisplayMode(IDirectDraw3 *iface)
1064 {
1065     IDirectDrawImpl *This = impl_from_dd3(iface);
1066     TRACE("(%p): Thunking to IDirectDraw4\n", This);
1067     return IDirectDraw4_RestoreDisplayMode(dd4_from_impl(This));
1068 }
1069
1070 static HRESULT WINAPI
1071 IDirectDraw2Impl_RestoreDisplayMode(IDirectDraw2 *iface)
1072 {
1073     IDirectDrawImpl *This = impl_from_dd2(iface);
1074     TRACE("(%p): Thunking to IDirectDraw4\n", This);
1075     return IDirectDraw4_RestoreDisplayMode(dd4_from_impl(This));
1076 }
1077
1078 static HRESULT WINAPI
1079 IDirectDrawImpl_RestoreDisplayMode(IDirectDraw *iface)
1080 {
1081     IDirectDrawImpl *This = impl_from_dd1(iface);
1082     TRACE("(%p): Thunking to IDirectDraw4\n", This);
1083     return IDirectDraw4_RestoreDisplayMode(dd4_from_impl(This));
1084 }
1085
1086 static HRESULT WINAPI
1087 IDirectDraw4Impl_SetCooperativeLevel(IDirectDraw4 *iface,
1088                                      HWND hwnd,
1089                                      DWORD cooplevel)
1090 {
1091     IDirectDrawImpl *This = impl_from_dd4(iface);
1092     TRACE("(%p)->(%p, 0x%08x)\n", This, hwnd, cooplevel);
1093     return IDirectDraw4_SetCooperativeLevel(This->parent, hwnd, cooplevel);
1094 }
1095
1096 static HRESULT WINAPI
1097 IDirectDraw3Impl_SetCooperativeLevel(IDirectDraw3 *iface,
1098                                      HWND hwnd,
1099                                      DWORD cooplevel)
1100 {
1101     IDirectDrawImpl *This = impl_from_dd3(iface);
1102     TRACE("(%p)->(%p, 0x%08x): Thunking to IDirectDraw4\n", This, hwnd, cooplevel);
1103     return IDirectDraw4_SetCooperativeLevel(dd4_from_impl(This), hwnd, cooplevel);
1104 }
1105
1106 static HRESULT WINAPI
1107 IDirectDraw2Impl_SetCooperativeLevel(IDirectDraw2 *iface,
1108                                      HWND hwnd,
1109                                      DWORD cooplevel)
1110 {
1111     IDirectDrawImpl *This = impl_from_dd2(iface);
1112     TRACE("(%p)->(%p, 0x%08x): Thunking to IDirectDraw4\n", This, hwnd, cooplevel);
1113     return IDirectDraw4_SetCooperativeLevel(dd4_from_impl(This), hwnd, cooplevel);
1114 }
1115
1116 static HRESULT WINAPI
1117 IDirectDrawImpl_SetCooperativeLevel(IDirectDraw *iface,
1118                                     HWND hwnd,
1119                                     DWORD cooplevel)
1120 {
1121     IDirectDrawImpl *This = impl_from_dd1(iface);
1122     TRACE("(%p)->(%p, 0x%08x): Thunking to IDirectDraw4\n", This, hwnd, cooplevel);
1123     return IDirectDraw4_SetCooperativeLevel(dd4_from_impl(This), hwnd, cooplevel);
1124 }
1125
1126 static HRESULT WINAPI
1127 IDirectDraw4Impl_SetDisplayMode(IDirectDraw4 *iface,
1128                                 DWORD Width,
1129                                 DWORD Height,
1130                                 DWORD BPP,
1131                                 DWORD RefreshRate,
1132                                 DWORD Flags)
1133 {
1134     IDirectDrawImpl *This = impl_from_dd4(iface);
1135     TRACE("(%p)->(%u, %u, %u, %u, 0x%08x)\n", This, Width, Height, BPP, RefreshRate, Flags);
1136     return IDirectDraw4_SetDisplayMode(This->parent, Width, Height, BPP, RefreshRate, Flags);
1137 }
1138
1139 static HRESULT WINAPI
1140 IDirectDraw3Impl_SetDisplayMode(IDirectDraw3 *iface,
1141                                 DWORD Width,
1142                                 DWORD Height,
1143                                 DWORD BPP,
1144                                 DWORD RefreshRate,
1145                                 DWORD Flags)
1146 {
1147     IDirectDrawImpl *This = impl_from_dd3(iface);
1148     TRACE("(%p)->(%u, %u, %u, %u, 0x%08x): Thunking to IDirectDraw4\n", This, Width, Height, BPP, RefreshRate, Flags);
1149     return IDirectDraw3_SetDisplayMode(dd4_from_impl(This), Width, Height, BPP, RefreshRate, Flags);
1150 }
1151
1152 static HRESULT WINAPI
1153 IDirectDraw2Impl_SetDisplayMode(IDirectDraw2 *iface,
1154                                 DWORD Width,
1155                                 DWORD Height,
1156                                 DWORD BPP,
1157                                 DWORD RefreshRate,
1158                                 DWORD Flags)
1159 {
1160     IDirectDrawImpl *This = impl_from_dd2(iface);
1161     TRACE("(%p)->(%u, %u, %u, %u, 0x%08x): Thunking to IDirectDraw4\n", This, Width, Height, BPP, RefreshRate, Flags);
1162     return IDirectDraw3_SetDisplayMode(dd4_from_impl(This), Width, Height, BPP, RefreshRate, Flags);
1163 }
1164
1165 static HRESULT WINAPI
1166 IDirectDrawImpl_SetDisplayMode(IDirectDraw *iface,
1167                                DWORD Width,
1168                                DWORD Height,
1169                                DWORD BPP)
1170 {
1171     IDirectDrawImpl *This = impl_from_dd1(iface);
1172     TRACE("(%p)->(%u, %u, %u): Thunking to IDirectDraw4\n", This, Width, Height, BPP);
1173     return IDirectDraw3_SetDisplayMode(dd4_from_impl(This), Width, Height, BPP, 0, 0);
1174 }
1175
1176 static HRESULT WINAPI
1177 IDirectDraw4Impl_WaitForVerticalBlank(IDirectDraw4 *iface,
1178                                       DWORD Flags,
1179                                       HANDLE h)
1180 {
1181     IDirectDrawImpl *This = impl_from_dd4(iface);
1182     TRACE("(%p)->(0x%08x, %p)\n", This, Flags, h);
1183     return IDirectDraw4_WaitForVerticalBlank(This->parent, Flags, h);
1184 }
1185
1186 static HRESULT WINAPI
1187 IDirectDraw3Impl_WaitForVerticalBlank(IDirectDraw3 *iface,
1188                                       DWORD Flags,
1189                                       HANDLE h)
1190 {
1191     IDirectDrawImpl *This = impl_from_dd3(iface);
1192     TRACE("(%p)->(0x%08x, %p): Thunking to IDirectDraw4\n", This, Flags, h);
1193     return IDirectDraw4_WaitForVerticalBlank(dd4_from_impl(This), Flags, h);
1194 }
1195
1196 static HRESULT WINAPI
1197 IDirectDraw2Impl_WaitForVerticalBlank(IDirectDraw2 *iface,
1198                                       DWORD Flags,
1199                                       HANDLE h)
1200 {
1201     IDirectDrawImpl *This = impl_from_dd2(iface);
1202     TRACE("(%p)->(0x%08x, %p): Thunking to IDirectDraw4\n", This, Flags, h);
1203     return IDirectDraw4_WaitForVerticalBlank(dd4_from_impl(This), Flags, h);
1204 }
1205
1206 static HRESULT WINAPI
1207 IDirectDrawImpl_WaitForVerticalBlank(IDirectDraw *iface,
1208                                      DWORD Flags,
1209                                      HANDLE h)
1210 {
1211     IDirectDrawImpl *This = impl_from_dd1(iface);
1212     TRACE("(%p)->(0x%08x, %p): Thunking to IDirectDraw4\n", This, Flags, h);
1213     return IDirectDraw4_WaitForVerticalBlank(dd4_from_impl(This), Flags, h);
1214 }
1215
1216 static HRESULT WINAPI
1217 IDirectDraw4Impl_GetAvailableVidMem(IDirectDraw4 *iface,
1218                                     DDSCAPS2 *Caps,
1219                                     DWORD *total,
1220                                     DWORD *free)
1221 {
1222     IDirectDrawImpl *This = impl_from_dd4(iface);
1223     TRACE("(%p)->(%p, %p, %p)\n", This, Caps, total, free);
1224     return IDirectDraw4_GetAvailableVidMem(This->parent, Caps, total, free);
1225 }
1226
1227 static HRESULT WINAPI
1228 IDirectDraw3Impl_GetAvailableVidMem(IDirectDraw3 *iface,
1229                                     DDSCAPS *Caps,
1230                                     DWORD *total,
1231                                     DWORD *free)
1232 {
1233     IDirectDrawImpl *This = impl_from_dd3(iface);
1234     DDSCAPS2 caps2;
1235     TRACE("(%p)->(%p, %p, %p): Thunking to IDirectDraw4\n", This, Caps, total, free);
1236     memset(&caps2, 0, sizeof(caps2));
1237     caps2.dwCaps = Caps->dwCaps;
1238     return IDirectDraw4_GetAvailableVidMem(dd4_from_impl(This), &caps2, total, free);
1239 }
1240
1241 static HRESULT WINAPI
1242 IDirectDraw2Impl_GetAvailableVidMem(IDirectDraw2 *iface,
1243                                     DDSCAPS *Caps,
1244                                     DWORD *total,
1245                                     DWORD *free)
1246 {
1247     IDirectDrawImpl *This = impl_from_dd2(iface);
1248     DDSCAPS2 caps2;
1249     TRACE("(%p)->(%p, %p, %p): Thunking to IDirectDraw4\n", This, Caps, total, free);
1250     memset(&caps2, 0, sizeof(caps2));
1251     caps2.dwCaps = Caps->dwCaps;
1252     return IDirectDraw4_GetAvailableVidMem(dd4_from_impl(This), &caps2, total, free);
1253 }
1254
1255 static HRESULT WINAPI
1256 IDirectDraw4Impl_GetSurfaceFromDC(IDirectDraw4 *iface,
1257                                   HDC hdc,
1258                                   IDirectDrawSurface4 **Surface)
1259 {
1260     IDirectDrawImpl *This = impl_from_dd4(iface);
1261     TRACE("(%p)->(%p, %p)\n", This, hdc, Surface);
1262     return IDirectDraw4_GetSurfaceFromDC(This->parent,hdc, Surface);
1263 }
1264
1265 static HRESULT WINAPI
1266 IDirectDraw3Impl_GetSurfaceFromDC(IDirectDraw3 *iface,
1267                                   HDC hdc,
1268                                   IDirectDrawSurface **Surface)
1269 {
1270     IDirectDrawImpl *This = impl_from_dd3(iface);
1271     IDirectDrawSurface4 *surf4;
1272     HRESULT hr;
1273     TRACE("(%p)->(%p, %p): Thunking to IDirectDraw4\n", This, hdc, Surface);
1274
1275     hr = IDirectDraw4_GetSurfaceFromDC(dd4_from_impl(This), hdc, &surf4);
1276     if(FAILED(hr))
1277     {
1278         *Surface = NULL;
1279         return hr;
1280     }
1281     IDirectDrawSurface4_QueryInterface(surf4, &IID_IDirectDrawSurface, (void **) Surface);
1282     IDirectDrawSurface4_Release(surf4);
1283     return hr;
1284 }
1285
1286 static HRESULT WINAPI
1287 IDirectDraw4Impl_RestoreAllSurfaces(IDirectDraw4 *iface)
1288 {
1289     IDirectDrawImpl *This = impl_from_dd4(iface);
1290     TRACE("(%p)\n", This);
1291     return IDirectDraw4_RestoreAllSurfaces(This->parent);
1292 }
1293
1294 static HRESULT WINAPI
1295 IDirectDraw4Impl_TestCooperativeLevel(IDirectDraw4 *iface)
1296 {
1297     IDirectDrawImpl *This = impl_from_dd4(iface);
1298     TRACE("(%p)\n", This);
1299     return IDirectDraw4_TestCooperativeLevel(This->parent);
1300 }
1301
1302 static HRESULT WINAPI
1303 IDirectDraw4Impl_GetDeviceIdentifier(IDirectDraw4 *iface,
1304                                      DDDEVICEIDENTIFIER *DDDI,
1305                                      DWORD Flags)
1306 {
1307     IDirectDrawImpl *This = impl_from_dd4(iface);
1308     TRACE("(%p)->(%p,0x%08x)\n", This, DDDI, Flags);
1309     return IDirectDraw4_GetDeviceIdentifier(This->parent, DDDI, Flags);
1310 }
1311
1312 static const IDirectDrawVtbl IDirectDraw1_Vtbl =
1313 {
1314     IDirectDrawImpl_QueryInterface,
1315     IDirectDrawImpl_AddRef,
1316     IDirectDrawImpl_Release,
1317     IDirectDrawImpl_Compact,
1318     IDirectDrawImpl_CreateClipper,
1319     IDirectDrawImpl_CreatePalette,
1320     IDirectDrawImpl_CreateSurface,
1321     IDirectDrawImpl_DuplicateSurface,
1322     IDirectDrawImpl_EnumDisplayModes,
1323     IDirectDrawImpl_EnumSurfaces,
1324     IDirectDrawImpl_FlipToGDISurface,
1325     IDirectDrawImpl_GetCaps,
1326     IDirectDrawImpl_GetDisplayMode,
1327     IDirectDrawImpl_GetFourCCCodes,
1328     IDirectDrawImpl_GetGDISurface,
1329     IDirectDrawImpl_GetMonitorFrequency,
1330     IDirectDrawImpl_GetScanLine,
1331     IDirectDrawImpl_GetVerticalBlankStatus,
1332     IDirectDrawImpl_Initialize,
1333     IDirectDrawImpl_RestoreDisplayMode,
1334     IDirectDrawImpl_SetCooperativeLevel,
1335     IDirectDrawImpl_SetDisplayMode,
1336     IDirectDrawImpl_WaitForVerticalBlank,
1337 };
1338
1339 static const IDirectDraw2Vtbl IDirectDraw2_Vtbl =
1340 {
1341     IDirectDraw2Impl_QueryInterface,
1342     IDirectDraw2Impl_AddRef,
1343     IDirectDraw2Impl_Release,
1344     IDirectDraw2Impl_Compact,
1345     IDirectDraw2Impl_CreateClipper,
1346     IDirectDraw2Impl_CreatePalette,
1347     IDirectDraw2Impl_CreateSurface,
1348     IDirectDraw2Impl_DuplicateSurface,
1349     IDirectDraw2Impl_EnumDisplayModes,
1350     IDirectDraw2Impl_EnumSurfaces,
1351     IDirectDraw2Impl_FlipToGDISurface,
1352     IDirectDraw2Impl_GetCaps,
1353     IDirectDraw2Impl_GetDisplayMode,
1354     IDirectDraw2Impl_GetFourCCCodes,
1355     IDirectDraw2Impl_GetGDISurface,
1356     IDirectDraw2Impl_GetMonitorFrequency,
1357     IDirectDraw2Impl_GetScanLine,
1358     IDirectDraw2Impl_GetVerticalBlankStatus,
1359     IDirectDraw2Impl_Initialize,
1360     IDirectDraw2Impl_RestoreDisplayMode,
1361     IDirectDraw2Impl_SetCooperativeLevel,
1362     IDirectDraw2Impl_SetDisplayMode,
1363     IDirectDraw2Impl_WaitForVerticalBlank,
1364     IDirectDraw2Impl_GetAvailableVidMem
1365 };
1366
1367 static const IDirectDraw3Vtbl IDirectDraw3_Vtbl =
1368 {
1369     IDirectDraw3Impl_QueryInterface,
1370     IDirectDraw3Impl_AddRef,
1371     IDirectDraw3Impl_Release,
1372     IDirectDraw3Impl_Compact,
1373     IDirectDraw3Impl_CreateClipper,
1374     IDirectDraw3Impl_CreatePalette,
1375     IDirectDraw3Impl_CreateSurface,
1376     IDirectDraw3Impl_DuplicateSurface,
1377     IDirectDraw3Impl_EnumDisplayModes,
1378     IDirectDraw3Impl_EnumSurfaces,
1379     IDirectDraw3Impl_FlipToGDISurface,
1380     IDirectDraw3Impl_GetCaps,
1381     IDirectDraw3Impl_GetDisplayMode,
1382     IDirectDraw3Impl_GetFourCCCodes,
1383     IDirectDraw3Impl_GetGDISurface,
1384     IDirectDraw3Impl_GetMonitorFrequency,
1385     IDirectDraw3Impl_GetScanLine,
1386     IDirectDraw3Impl_GetVerticalBlankStatus,
1387     IDirectDraw3Impl_Initialize,
1388     IDirectDraw3Impl_RestoreDisplayMode,
1389     IDirectDraw3Impl_SetCooperativeLevel,
1390     IDirectDraw3Impl_SetDisplayMode,
1391     IDirectDraw3Impl_WaitForVerticalBlank,
1392     IDirectDraw3Impl_GetAvailableVidMem,
1393     IDirectDraw3Impl_GetSurfaceFromDC,
1394 };
1395
1396 static const IDirectDraw4Vtbl IDirectDraw4_Vtbl =
1397 {
1398     IDirectDraw4Impl_QueryInterface,
1399     IDirectDraw4Impl_AddRef,
1400     IDirectDraw4Impl_Release,
1401     IDirectDraw4Impl_Compact,
1402     IDirectDraw4Impl_CreateClipper,
1403     IDirectDraw4Impl_CreatePalette,
1404     IDirectDraw4Impl_CreateSurface,
1405     IDirectDraw4Impl_DuplicateSurface,
1406     IDirectDraw4Impl_EnumDisplayModes,
1407     IDirectDraw4Impl_EnumSurfaces,
1408     IDirectDraw4Impl_FlipToGDISurface,
1409     IDirectDraw4Impl_GetCaps,
1410     IDirectDraw4Impl_GetDisplayMode,
1411     IDirectDraw4Impl_GetFourCCCodes,
1412     IDirectDraw4Impl_GetGDISurface,
1413     IDirectDraw4Impl_GetMonitorFrequency,
1414     IDirectDraw4Impl_GetScanLine,
1415     IDirectDraw4Impl_GetVerticalBlankStatus,
1416     IDirectDraw4Impl_Initialize,
1417     IDirectDraw4Impl_RestoreDisplayMode,
1418     IDirectDraw4Impl_SetCooperativeLevel,
1419     IDirectDraw4Impl_SetDisplayMode,
1420     IDirectDraw4Impl_WaitForVerticalBlank,
1421     IDirectDraw4Impl_GetAvailableVidMem,
1422     IDirectDraw4Impl_GetSurfaceFromDC,
1423     IDirectDraw4Impl_RestoreAllSurfaces,
1424     IDirectDraw4Impl_TestCooperativeLevel,
1425     IDirectDraw4Impl_GetDeviceIdentifier
1426 };
1427
1428 /*******************************************************************************
1429  * IDirectDrawFactoryImpl_CreateDirectDraw
1430  *******************************************************************************/
1431 HRESULT WINAPI
1432 IDirectDrawFactoryImpl_CreateDirectDraw(IDirectDrawFactory* iface,
1433                                         GUID * pGUID,
1434                                         HWND hWnd,
1435                                         DWORD dwCoopLevelFlags,
1436                                         DWORD dwReserved,
1437                                         IUnknown *pUnkOuter,
1438                                         IDirectDraw **ppDirectDraw)
1439 {
1440     HRESULT hr;
1441     IDirectDrawImpl *object = NULL;
1442     IDirectDraw *parent = NULL;
1443
1444     TRACE("(%p)->(%s,%p,0x%08x,0x%08x,%p,%p)", iface, debugstr_guid(pGUID), hWnd, dwCoopLevelFlags,
1445           dwReserved, pUnkOuter, ppDirectDraw);
1446
1447     if(pUnkOuter)
1448     {
1449         FIXME("Implement aggregation in ddrawex's IDirectDraw interface\n");
1450     }
1451
1452     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1453     if(!object)
1454     {
1455         ERR("Out of memory\n");
1456         hr = E_OUTOFMEMORY;
1457         goto err;
1458     }
1459     object->ref = 1;
1460     object->IDirectDraw_Vtbl  = &IDirectDraw1_Vtbl;
1461     object->IDirectDraw2_Vtbl = &IDirectDraw2_Vtbl;
1462     object->IDirectDraw3_Vtbl = &IDirectDraw3_Vtbl;
1463     object->IDirectDraw4_Vtbl = &IDirectDraw4_Vtbl;
1464
1465     hr = DirectDrawCreate(pGUID, &parent, NULL);
1466     if (FAILED(hr)) goto err;
1467
1468     hr = IDirectDraw_QueryInterface(parent, &IID_IDirectDraw4, (void **) &object->parent);
1469     if(FAILED(hr)) goto err;
1470
1471     hr = IDirectDraw_SetCooperativeLevel(dd1_from_impl(object), hWnd, dwCoopLevelFlags);
1472     if (FAILED(hr)) goto err;
1473
1474     *ppDirectDraw = dd1_from_impl(object);
1475     IDirectDraw_Release(parent);
1476     return DD_OK;
1477
1478 err:
1479     if(object && object->parent) IDirectDraw4_Release(object->parent);
1480     if(parent) IDirectDraw_Release(parent);
1481     if(object) HeapFree(GetProcessHeap(), 0, object);
1482     *ppDirectDraw = NULL;
1483     return hr;
1484 }