- Clean up all the D3D COM handling (but the underlaying code is still
[wine] / dlls / ddraw / direct3d / main.c
1 /*
2  * Copyright 2000 Marcus Meissner
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "config.h"
20
21 #include <assert.h>
22 #ifdef HAVE_UNISTD_H
23 # include <unistd.h>
24 #endif
25 #include <fcntl.h>
26 #include <string.h>
27 #include <stdio.h>
28
29 #include "winerror.h"
30 #include "ddraw.h"
31 #include "d3d.h"
32 #include "wine/debug.h"
33
34 #include "d3d_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37
38 HRESULT WINAPI
39 Main_IDirect3DImpl_7_3T_2T_1T_QueryInterface(LPDIRECT3D7 iface,
40                                              REFIID riid,
41                                              LPVOID* obp)
42 {
43     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
44
45     TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_guid(riid), obp);
46
47     /* By default, set the object pointer to NULL */
48     *obp = NULL;
49       
50     if (( IsEqualGUID( &IID_IDirectDraw,  riid ) ) ||
51         ( IsEqualGUID (&IID_IDirectDraw2, riid ) ) ||
52         ( IsEqualGUID (&IID_IDirectDraw4, riid ) ) ||
53         ( IsEqualGUID( &IID_IDirectDraw7, riid ) )
54     ) {
55         HRESULT ret;
56         TRACE("  Creating IDirectDrawX interface by calling DirectDraw function.\n");
57         ret = IDirectDraw_QueryInterface(ICOM_INTERFACE(This->ddraw,IDirectDraw), riid, obp);
58         if (ret == S_OK) {
59             IDirectDraw_Release(ICOM_INTERFACE(This->ddraw,IDirectDraw));
60             IDirect3D_AddRef(ICOM_INTERFACE(This,IDirect3D));
61         }
62         return ret;
63     }
64     if ( IsEqualGUID( &IID_IUnknown,  riid ) ) {
65         IDirect3D_AddRef(ICOM_INTERFACE(This,IDirect3D));
66         *obp = iface;
67         TRACE("  Creating IUnknown interface at %p.\n", *obp);
68         return S_OK;
69     }
70     if ( IsEqualGUID( &IID_IDirect3D, riid ) ) {
71         IDirect3D_AddRef(ICOM_INTERFACE(This,IDirect3D));
72         *obp = ICOM_INTERFACE(This, IDirect3D);
73         TRACE("  Creating IDirect3D interface %p\n", *obp);
74         return S_OK;
75     }
76     if ( IsEqualGUID( &IID_IDirect3D2, riid ) ) {
77         IDirect3D_AddRef(ICOM_INTERFACE(This,IDirect3D));
78         *obp = ICOM_INTERFACE(This, IDirect3D2);
79         TRACE("  Creating IDirect3D2 interface %p\n", *obp);
80         return S_OK;
81     }
82     if ( IsEqualGUID( &IID_IDirect3D3, riid ) ) {
83         IDirect3D_AddRef(ICOM_INTERFACE(This,IDirect3D));
84         *obp = ICOM_INTERFACE(This, IDirect3D3);
85         TRACE("  Creating IDirect3D3 interface %p\n", *obp);
86         return S_OK;
87     }
88     if ( IsEqualGUID( &IID_IDirect3D7, riid ) ) {
89         /* This is not 100 % true as we should not be able to QueryInterface a '7' version from another one.
90            But well, to factorize the code, why check for application bugs :-) ?
91          */
92         IDirect3D_AddRef(ICOM_INTERFACE(This,IDirect3D));
93         *obp = ICOM_INTERFACE(This, IDirect3D7);
94         TRACE("  Creating IDirect3D7 interface %p\n", *obp);
95         return S_OK;
96     }
97     FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
98     return OLE_E_ENUM_NOMORE;
99 }
100
101 ULONG WINAPI
102 Main_IDirect3DImpl_7_3T_2T_1T_AddRef(LPDIRECT3D7 iface)
103 {
104     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
105     TRACE("(%p/%p)->() incrementing from %lu.\n", This, iface, This->ref);
106
107     return ++(This->ref);
108 }
109
110 ULONG WINAPI
111 Main_IDirect3DImpl_7_3T_2T_1T_Release(LPDIRECT3D7 iface)
112 {
113     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
114     TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
115     if (--(This->ref) == 0) {
116         IDirectDraw_Release(ICOM_INTERFACE(This->ddraw, IDirectDraw));
117         HeapFree(GetProcessHeap(), 0, This);
118         return 0;
119     }
120     return This->ref;
121 }
122
123 HRESULT WINAPI
124 Main_IDirect3DImpl_1_Initialize(LPDIRECT3D iface,
125                                 REFIID riid)
126 {
127     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D, iface);
128     TRACE("(%p/%p)->(%s) no-op...\n", This, iface, debugstr_guid(riid));
129     return D3D_OK;
130 }
131
132 HRESULT WINAPI
133 Main_IDirect3DImpl_3_2T_1T_EnumDevices(LPDIRECT3D3 iface,
134                                        LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
135                                        LPVOID lpUserArg)
136 {
137     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
138     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lpEnumDevicesCallback, lpUserArg);
139     return D3D_OK;
140 }
141
142 HRESULT WINAPI
143 Main_IDirect3DImpl_3_2T_1T_CreateLight(LPDIRECT3D3 iface,
144                                        LPDIRECT3DLIGHT* lplpDirect3DLight,
145                                        IUnknown* pUnkOuter)
146 {
147     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
148     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDirect3DLight, pUnkOuter);
149     return D3D_OK;
150 }
151
152 HRESULT WINAPI
153 Main_IDirect3DImpl_3_2T_1T_CreateMaterial(LPDIRECT3D3 iface,
154                                           LPDIRECT3DMATERIAL3* lplpDirect3DMaterial3,
155                                           IUnknown* pUnkOuter)
156 {
157     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
158     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpDirect3DMaterial3, pUnkOuter);
159     return D3D_OK;
160 }
161
162 HRESULT WINAPI
163 Main_IDirect3DImpl_3_2T_1T_CreateViewport(LPDIRECT3D3 iface,
164                                           LPDIRECT3DVIEWPORT3* lplpD3DViewport3,
165                                           IUnknown* pUnkOuter)
166 {
167     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
168     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lplpD3DViewport3, pUnkOuter);
169     return D3D_OK;
170 }
171
172 HRESULT WINAPI
173 Main_IDirect3DImpl_1_FindDevice(LPDIRECT3D iface,
174                                 LPD3DFINDDEVICESEARCH lpD3DDFS,
175                                 LPD3DFINDDEVICERESULT lplpD3DDevice)
176 {
177     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D, iface);
178     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lpD3DDFS, lplpD3DDevice);
179     return D3D_OK;
180 }
181
182 HRESULT WINAPI
183 Main_IDirect3DImpl_3_2T_FindDevice(LPDIRECT3D3 iface,
184                                    LPD3DFINDDEVICESEARCH lpD3DDFS,
185                                    LPD3DFINDDEVICERESULT lpD3DFDR)
186 {
187     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
188     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lpD3DDFS, lpD3DFDR);
189     return D3D_OK;
190 }
191
192 HRESULT WINAPI
193 Main_IDirect3DImpl_2_CreateDevice(LPDIRECT3D2 iface,
194                                   REFCLSID rclsid,
195                                   LPDIRECTDRAWSURFACE lpDDS,
196                                   LPDIRECT3DDEVICE2* lplpD3DDevice2)
197 {
198     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D2, iface);
199     FIXME("(%p/%p)->(%s,%p,%p): stub!\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice2);
200     return D3D_OK;
201 }
202
203 HRESULT WINAPI
204 Main_IDirect3DImpl_3_CreateDevice(LPDIRECT3D3 iface,
205                                   REFCLSID rclsid,
206                                   LPDIRECTDRAWSURFACE4 lpDDS,
207                                   LPDIRECT3DDEVICE3* lplpD3DDevice3,
208                                   LPUNKNOWN lpUnk)
209 {
210     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D3, iface);
211     FIXME("(%p/%p)->(%s,%p,%p,%p): stub!\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice3, lpUnk);
212     return D3D_OK;
213 }
214
215 HRESULT WINAPI
216 Main_IDirect3DImpl_7_3T_EnumZBufferFormats(LPDIRECT3D7 iface,
217                                            REFCLSID riidDevice,
218                                            LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
219                                            LPVOID lpContext)
220 {
221     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
222     FIXME("(%p/%p)->(%s,%p,%p): stub!\n", This, iface, debugstr_guid(riidDevice), lpEnumCallback, lpContext);
223     return D3D_OK;
224 }
225
226 HRESULT WINAPI
227 Main_IDirect3DImpl_7_3T_EvictManagedTextures(LPDIRECT3D7 iface)
228 {
229     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
230     FIXME("(%p/%p)->(): stub!\n", This, iface);
231     return D3D_OK;
232 }
233
234 HRESULT WINAPI
235 Main_IDirect3DImpl_7_EnumDevices(LPDIRECT3D7 iface,
236                                  LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallback,
237                                  LPVOID lpUserArg)
238 {
239     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
240     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lpEnumDevicesCallback, lpUserArg);
241     return D3D_OK;
242 }
243
244 HRESULT WINAPI
245 Main_IDirect3DImpl_7_CreateDevice(LPDIRECT3D7 iface,
246                                   REFCLSID rclsid,
247                                   LPDIRECTDRAWSURFACE7 lpDDS,
248                                   LPDIRECT3DDEVICE7* lplpD3DDevice)
249 {
250     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
251     FIXME("(%p/%p)->(%s,%p,%p): stub!\n", This, iface, debugstr_guid(rclsid), lpDDS, lplpD3DDevice);
252     return D3D_OK;
253 }
254
255 HRESULT WINAPI
256 Main_IDirect3DImpl_7_3T_CreateVertexBuffer(LPDIRECT3D7 iface,
257                                            LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc,
258                                            LPDIRECT3DVERTEXBUFFER7* lplpD3DVertBuf,
259                                            DWORD dwFlags)
260 {
261     ICOM_THIS_FROM(IDirect3DImpl, IDirect3D7, iface);
262     FIXME("(%p/%p)->(%p,%p,%08lx): stub!\n", This, iface, lpD3DVertBufDesc, lplpD3DVertBuf, dwFlags);
263     return D3D_OK;
264 }
265
266 HRESULT WINAPI
267 Thunk_IDirect3DImpl_3_QueryInterface(LPDIRECT3D3 iface,
268                                      REFIID riid,
269                                      LPVOID* obp)
270 {
271     TRACE("(%p)->(%s,%p) thunking to IDirect3D7 interface.\n", iface, debugstr_guid(riid), obp);
272     return IDirect3D7_QueryInterface(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D3, IDirect3D7, iface),
273                                      riid,
274                                      obp);
275 }
276
277 HRESULT WINAPI
278 Thunk_IDirect3DImpl_2_QueryInterface(LPDIRECT3D2 iface,
279                                      REFIID riid,
280                                      LPVOID* obp)
281 {
282     TRACE("(%p)->(%s,%p) thunking to IDirect3D7 interface.\n", iface, debugstr_guid(riid), obp);
283     return IDirect3D7_QueryInterface(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D2, IDirect3D7, iface),
284                                      riid,
285                                      obp);
286 }
287
288 HRESULT WINAPI
289 Thunk_IDirect3DImpl_1_QueryInterface(LPDIRECT3D iface,
290                                      REFIID riid,
291                                      LPVOID* obp)
292 {
293     TRACE("(%p)->(%s,%p) thunking to IDirect3D7 interface.\n", iface, debugstr_guid(riid), obp);
294     return IDirect3D7_QueryInterface(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D, IDirect3D7, iface),
295                                      riid,
296                                      obp);
297 }
298
299 ULONG WINAPI
300 Thunk_IDirect3DImpl_3_AddRef(LPDIRECT3D3 iface)
301 {
302     TRACE("(%p)->() thunking to IDirect3D7 interface.\n", iface);
303     return IDirect3D7_AddRef(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D3, IDirect3D7, iface));
304 }
305
306 ULONG WINAPI
307 Thunk_IDirect3DImpl_2_AddRef(LPDIRECT3D2 iface)
308 {
309     TRACE("(%p)->() thunking to IDirect3D7 interface.\n", iface);
310     return IDirect3D7_AddRef(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D2, IDirect3D7, iface));
311 }
312
313 ULONG WINAPI
314 Thunk_IDirect3DImpl_1_AddRef(LPDIRECT3D iface)
315 {
316     TRACE("(%p)->() thunking to IDirect3D7 interface.\n", iface);
317     return IDirect3D7_AddRef(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D, IDirect3D7, iface));
318 }
319
320 ULONG WINAPI
321 Thunk_IDirect3DImpl_3_Release(LPDIRECT3D3 iface)
322 {
323     TRACE("(%p)->() thunking to IDirect3D7 interface.\n", iface);
324     return IDirect3D7_Release(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D3, IDirect3D7, iface));
325 }
326
327 ULONG WINAPI
328 Thunk_IDirect3DImpl_2_Release(LPDIRECT3D2 iface)
329 {
330     TRACE("(%p)->() thunking to IDirect3D7 interface.\n", iface);
331     return IDirect3D7_Release(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D2, IDirect3D7, iface));
332 }
333
334 ULONG WINAPI
335 Thunk_IDirect3DImpl_1_Release(LPDIRECT3D iface)
336 {
337     TRACE("(%p)->() thunking to IDirect3D7 interface.\n", iface);
338     return IDirect3D7_Release(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D, IDirect3D7, iface));
339 }
340
341 HRESULT WINAPI
342 Thunk_IDirect3DImpl_3_EnumZBufferFormats(LPDIRECT3D3 iface,
343                                          REFCLSID riidDevice,
344                                          LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
345                                          LPVOID lpContext)
346 {
347     TRACE("(%p)->(%s,%p,%p) thunking to IDirect3D7 interface.\n", iface, debugstr_guid(riidDevice), lpEnumCallback, lpContext);
348     return IDirect3D7_EnumZBufferFormats(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D3, IDirect3D7, iface),
349                                          riidDevice,
350                                          lpEnumCallback,
351                                          lpContext);
352 }
353
354 HRESULT WINAPI
355 Thunk_IDirect3DImpl_3_EvictManagedTextures(LPDIRECT3D3 iface)
356 {
357     TRACE("(%p)->() thunking to IDirect3D7 interface.\n", iface);
358     return IDirect3D7_EvictManagedTextures(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D3, IDirect3D7, iface));
359 }
360
361 HRESULT WINAPI
362 Thunk_IDirect3DImpl_2_EnumDevices(LPDIRECT3D2 iface,
363                                   LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
364                                   LPVOID lpUserArg)
365 {
366     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, lpEnumDevicesCallback, lpUserArg);
367     return IDirect3D3_EnumDevices(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D2, IDirect3D3, iface),
368                                   lpEnumDevicesCallback,
369                                   lpUserArg);
370 }
371
372 HRESULT WINAPI
373 Thunk_IDirect3DImpl_1_EnumDevices(LPDIRECT3D iface,
374                                   LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback,
375                                   LPVOID lpUserArg)
376 {
377     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, lpEnumDevicesCallback, lpUserArg);
378     return IDirect3D3_EnumDevices(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D, IDirect3D3, iface),
379                                   lpEnumDevicesCallback,
380                                   lpUserArg);
381 }
382
383 HRESULT WINAPI
384 Thunk_IDirect3DImpl_2_CreateLight(LPDIRECT3D2 iface,
385                                   LPDIRECT3DLIGHT* lplpDirect3DLight,
386                                   IUnknown* pUnkOuter)
387 {
388     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, lplpDirect3DLight, pUnkOuter);
389     return IDirect3D3_CreateLight(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D2, IDirect3D3, iface),
390                                   lplpDirect3DLight,
391                                   pUnkOuter);
392 }
393
394 HRESULT WINAPI
395 Thunk_IDirect3DImpl_1_CreateLight(LPDIRECT3D iface,
396                                   LPDIRECT3DLIGHT* lplpDirect3DLight,
397                                   IUnknown* pUnkOuter)
398 {
399     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, lplpDirect3DLight, pUnkOuter);
400     return IDirect3D3_CreateLight(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D, IDirect3D3, iface),
401                                   lplpDirect3DLight,
402                                   pUnkOuter);
403 }
404
405 HRESULT WINAPI
406 Thunk_IDirect3DImpl_2_FindDevice(LPDIRECT3D2 iface,
407                                  LPD3DFINDDEVICESEARCH lpD3DDFS,
408                                  LPD3DFINDDEVICERESULT lpD3DFDR)
409 {
410     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, lpD3DDFS, lpD3DFDR);
411     return IDirect3D3_FindDevice(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D2, IDirect3D3, iface),
412                                  lpD3DDFS,
413                                  lpD3DFDR);
414 }
415
416 HRESULT WINAPI
417 Thunk_IDirect3DImpl_1_CreateMaterial(LPDIRECT3D iface,
418                                      LPDIRECT3DMATERIAL* lplpDirect3DMaterial,
419                                      IUnknown* pUnkOuter)
420 {
421     HRESULT ret;
422     LPDIRECT3DMATERIAL3 ret_val;
423
424     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, lplpDirect3DMaterial, pUnkOuter);
425     ret = IDirect3D3_CreateMaterial(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D, IDirect3D3, iface),
426                                     &ret_val,
427                                     pUnkOuter);
428
429     *lplpDirect3DMaterial = COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial3, IDirect3DMaterial, &ret_val);
430
431     TRACE(" returning interface %p.\n", *lplpDirect3DMaterial);
432     
433     return ret;
434 }
435
436 HRESULT WINAPI
437 Thunk_IDirect3DImpl_1_CreateViewport(LPDIRECT3D iface,
438                                      LPDIRECT3DVIEWPORT* lplpD3DViewport,
439                                      IUnknown* pUnkOuter)
440 {
441     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, lplpD3DViewport, pUnkOuter);
442     return IDirect3D3_CreateViewport(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D, IDirect3D3, iface),
443                                     (LPDIRECT3DVIEWPORT3 *) lplpD3DViewport /* No need to cast here */,
444                                     pUnkOuter);
445 }
446
447 HRESULT WINAPI
448 Thunk_IDirect3DImpl_2_CreateMaterial(LPDIRECT3D2 iface,
449                                      LPDIRECT3DMATERIAL2* lplpDirect3DMaterial2,
450                                      IUnknown* pUnkOuter)
451 {
452     HRESULT ret;
453     LPDIRECT3DMATERIAL3 ret_val;
454
455     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, lplpDirect3DMaterial2, pUnkOuter);
456     ret = IDirect3D3_CreateMaterial(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D2, IDirect3D3, iface),
457                                     &ret_val,
458                                     pUnkOuter);
459
460     *lplpDirect3DMaterial2 = COM_INTERFACE_CAST(IDirect3DMaterialImpl, IDirect3DMaterial3, IDirect3DMaterial2, &ret_val);
461
462     TRACE(" returning interface %p.\n", *lplpDirect3DMaterial2);
463     
464     return ret;
465 }
466
467 HRESULT WINAPI
468 Thunk_IDirect3DImpl_2_CreateViewport(LPDIRECT3D2 iface,
469                                      LPDIRECT3DVIEWPORT* lplpD3DViewport2,
470                                      IUnknown* pUnkOuter)
471 {
472     TRACE("(%p)->(%p,%p) thunking to IDirect3D3 interface.\n", iface, lplpD3DViewport2, pUnkOuter);
473     return IDirect3D3_CreateViewport(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D2, IDirect3D3, iface),
474                                      (LPDIRECT3DVIEWPORT3 *) lplpD3DViewport2 /* No need to cast here */,
475                                      pUnkOuter);
476 }
477
478
479 HRESULT WINAPI
480 Thunk_IDirect3DImpl_3_CreateVertexBuffer(LPDIRECT3D3 iface,
481                                          LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc,
482                                          LPDIRECT3DVERTEXBUFFER* lplpD3DVertBuf,
483                                          DWORD dwFlags,
484                                          LPUNKNOWN lpUnk)
485 {
486     HRESULT ret;
487     LPDIRECT3DVERTEXBUFFER7 ret_val;
488
489     TRACE("(%p)->(%p,%p,%08lx,%p) thunking to IDirect3D7 interface.\n", iface, lpD3DVertBufDesc, lplpD3DVertBuf, dwFlags, lpUnk);
490     ret = IDirect3D7_CreateVertexBuffer(COM_INTERFACE_CAST(IDirect3DImpl, IDirect3D3, IDirect3D7, iface),
491                                         lpD3DVertBufDesc,
492                                         &ret_val,
493                                         dwFlags);
494
495     *lplpD3DVertBuf = COM_INTERFACE_CAST(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, IDirect3DVertexBuffer, ret_val);
496
497     TRACE(" returning interface %p.\n", *lplpD3DVertBuf);
498     
499     return ret;
500 }