ddraw: COM cleanup for the IDirectDraw4 iface.
[wine] / dlls / ddraw / ddraw.c
1 /*
2  * Copyright 1997-2000 Marcus Meissner
3  * Copyright 1998-2000 Lionel Ulmer
4  * Copyright 2000-2001 TransGaming Technologies Inc.
5  * Copyright 2006 Stefan Dösinger
6  * Copyright 2008 Denver Gingerich
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include "ddraw_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
29
30 /* Device identifier. Don't relay it to WineD3D */
31 static const DDDEVICEIDENTIFIER2 deviceidentifier =
32 {
33     "display",
34     "DirectDraw HAL",
35     { { 0x00010001, 0x00010001 } },
36     0, 0, 0, 0,
37     /* a8373c10-7ac4-4deb-849a-009844d08b2d */
38     {0xa8373c10,0x7ac4,0x4deb, {0x84,0x9a,0x00,0x98,0x44,0xd0,0x8b,0x2d}},
39     0
40 };
41
42 static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {}
43
44 const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops =
45 {
46     ddraw_null_wined3d_object_destroyed,
47 };
48
49 static inline IDirectDrawImpl *impl_from_IDirectDraw(IDirectDraw *iface)
50 {
51     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw_iface);
52 }
53
54 static inline IDirectDrawImpl *impl_from_IDirectDraw2(IDirectDraw2 *iface)
55 {
56     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw2_iface);
57 }
58
59 static inline IDirectDrawImpl *impl_from_IDirectDraw3(IDirectDraw3 *iface)
60 {
61     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw3_iface);
62 }
63
64 static inline IDirectDrawImpl *impl_from_IDirectDraw4(IDirectDraw4 *iface)
65 {
66     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirectDraw4_iface);
67 }
68
69 static inline IDirectDrawImpl *impl_from_IDirect3D(IDirect3D *iface)
70 {
71     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D_iface);
72 }
73
74 static inline IDirectDrawImpl *impl_from_IDirect3D2(IDirect3D2 *iface)
75 {
76     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D2_iface);
77 }
78
79 static inline IDirectDrawImpl *impl_from_IDirect3D3(IDirect3D3 *iface)
80 {
81     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D3_iface);
82 }
83
84 static inline IDirectDrawImpl *impl_from_IDirect3D7(IDirect3D7 *iface)
85 {
86     return CONTAINING_RECORD(iface, IDirectDrawImpl, IDirect3D7_iface);
87 }
88
89 /*****************************************************************************
90  * IUnknown Methods
91  *****************************************************************************/
92
93 /*****************************************************************************
94  * IDirectDraw7::QueryInterface
95  *
96  * Queries different interfaces of the DirectDraw object. It can return
97  * IDirectDraw interfaces in version 1, 2, 4 and 7, and IDirect3D interfaces
98  * in version 1, 2, 3 and 7. An IDirect3DDevice can be created with this
99  * method.
100  * The returned interface is AddRef()-ed before it's returned
101  *
102  * Used for version 1, 2, 4 and 7
103  *
104  * Params:
105  *  refiid: Interface ID asked for
106  *  obj: Used to return the interface pointer
107  *
108  * Returns:
109  *  S_OK if an interface was found
110  *  E_NOINTERFACE if the requested interface wasn't found
111  *
112  *****************************************************************************/
113 static HRESULT WINAPI ddraw7_QueryInterface(IDirectDraw7 *iface, REFIID refiid, void **obj)
114 {
115     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
116
117     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
118
119     /* Can change surface impl type */
120     EnterCriticalSection(&ddraw_cs);
121
122     /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
123     *obj = NULL;
124
125     if(!refiid)
126     {
127         LeaveCriticalSection(&ddraw_cs);
128         return DDERR_INVALIDPARAMS;
129     }
130
131     /* Check DirectDraw Interfaces */
132     if ( IsEqualGUID( &IID_IUnknown, refiid ) ||
133          IsEqualGUID( &IID_IDirectDraw7, refiid ) )
134     {
135         *obj = This;
136         TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
137     }
138     else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
139     {
140         *obj = &This->IDirectDraw4_iface;
141         TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
142     }
143     else if ( IsEqualGUID( &IID_IDirectDraw3, refiid ) )
144     {
145         /* This Interface exists in ddrawex.dll, it is implemented in a wrapper */
146         WARN("IDirectDraw3 is not valid in ddraw.dll\n");
147         *obj = NULL;
148         LeaveCriticalSection(&ddraw_cs);
149         return E_NOINTERFACE;
150     }
151     else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
152     {
153         *obj = &This->IDirectDraw2_iface;
154         TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
155     }
156     else if ( IsEqualGUID( &IID_IDirectDraw, refiid ) )
157     {
158         *obj = &This->IDirectDraw_iface;
159         TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
160     }
161
162     /* Direct3D
163      * The refcount unit test revealed that an IDirect3D7 interface can only be queried
164      * from a DirectDraw object that was created as an IDirectDraw7 interface. No idea
165      * who had this idea and why. The older interfaces can query and IDirect3D version
166      * because they are all created as IDirectDraw(1). This isn't really crucial behavior,
167      * and messy to implement with the common creation function, so it has been left out here.
168      */
169     else if ( IsEqualGUID( &IID_IDirect3D  , refiid ) ||
170               IsEqualGUID( &IID_IDirect3D2 , refiid ) ||
171               IsEqualGUID( &IID_IDirect3D3 , refiid ) ||
172               IsEqualGUID( &IID_IDirect3D7 , refiid ) )
173     {
174         /* Check the surface implementation */
175         if(This->ImplType == SURFACE_UNKNOWN)
176         {
177             /* Apps may create the IDirect3D Interface before the primary surface.
178              * set the surface implementation */
179             This->ImplType = SURFACE_OPENGL;
180             TRACE("(%p) Choosing OpenGL surfaces because a Direct3D interface was requested\n", This);
181         }
182         else if(This->ImplType != SURFACE_OPENGL && DefaultSurfaceType == SURFACE_UNKNOWN)
183         {
184             ERR("(%p) The App is requesting a D3D device, but a non-OpenGL surface type was choosen. Prepare for trouble!\n", This);
185             ERR(" (%p) You may want to contact wine-devel for help\n", This);
186             /* Should I assert(0) here??? */
187         }
188         else if(This->ImplType != SURFACE_OPENGL)
189         {
190             WARN("The app requests a Direct3D interface, but non-opengl surfaces where set in winecfg\n");
191             /* Do not abort here, only reject 3D Device creation */
192         }
193
194         if ( IsEqualGUID( &IID_IDirect3D  , refiid ) )
195         {
196             This->d3dversion = 1;
197             *obj = &This->IDirect3D_iface;
198             TRACE(" returning Direct3D interface at %p.\n", *obj);
199         }
200         else if ( IsEqualGUID( &IID_IDirect3D2  , refiid ) )
201         {
202             This->d3dversion = 2;
203             *obj = &This->IDirect3D2_iface;
204             TRACE(" returning Direct3D2 interface at %p.\n", *obj);
205         }
206         else if ( IsEqualGUID( &IID_IDirect3D3  , refiid ) )
207         {
208             This->d3dversion = 3;
209             *obj = &This->IDirect3D3_iface;
210             TRACE(" returning Direct3D3 interface at %p.\n", *obj);
211         }
212         else if(IsEqualGUID( &IID_IDirect3D7  , refiid ))
213         {
214             This->d3dversion = 7;
215             *obj = &This->IDirect3D7_iface;
216             TRACE(" returning Direct3D7 interface at %p.\n", *obj);
217         }
218     }
219     else if (IsEqualGUID(refiid, &IID_IWineD3DDeviceParent))
220     {
221         *obj = &This->device_parent_vtbl;
222     }
223
224     /* Unknown interface */
225     else
226     {
227         ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
228         LeaveCriticalSection(&ddraw_cs);
229         return E_NOINTERFACE;
230     }
231
232     IUnknown_AddRef( (IUnknown *) *obj );
233     LeaveCriticalSection(&ddraw_cs);
234     return S_OK;
235 }
236
237 static HRESULT WINAPI ddraw4_QueryInterface(IDirectDraw4 *iface, REFIID riid, void **object)
238 {
239     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
240
241     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
242
243     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
244 }
245
246 static HRESULT WINAPI ddraw3_QueryInterface(IDirectDraw3 *iface, REFIID riid, void **object)
247 {
248     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
249
250     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
251
252     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
253 }
254
255 static HRESULT WINAPI ddraw2_QueryInterface(IDirectDraw2 *iface, REFIID riid, void **object)
256 {
257     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
258
259     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
260
261     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
262 }
263
264 static HRESULT WINAPI ddraw1_QueryInterface(IDirectDraw *iface, REFIID riid, void **object)
265 {
266     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
267
268     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
269
270     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
271 }
272
273 static HRESULT WINAPI d3d7_QueryInterface(IDirect3D7 *iface, REFIID riid, void **object)
274 {
275     IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
276
277     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
278
279     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
280 }
281
282 static HRESULT WINAPI d3d3_QueryInterface(IDirect3D3 *iface, REFIID riid, void **object)
283 {
284     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
285
286     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
287
288     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
289 }
290
291 static HRESULT WINAPI d3d2_QueryInterface(IDirect3D2 *iface, REFIID riid, void **object)
292 {
293     IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
294
295     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
296
297     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
298 }
299
300 static HRESULT WINAPI d3d1_QueryInterface(IDirect3D *iface, REFIID riid, void **object)
301 {
302     IDirectDrawImpl *This = impl_from_IDirect3D(iface);
303
304     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
305
306     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
307 }
308
309 /*****************************************************************************
310  * IDirectDraw7::AddRef
311  *
312  * Increases the interfaces refcount, basically
313  *
314  * DDraw refcounting is a bit tricky. The different DirectDraw interface
315  * versions have individual refcounts, but the IDirect3D interfaces do not.
316  * All interfaces are from one object, that means calling QueryInterface on an
317  * IDirectDraw7 interface for an IDirectDraw4 interface does not create a new
318  * IDirectDrawImpl object.
319  *
320  * That means all AddRef and Release implementations of IDirectDrawX work
321  * with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1),
322  * except of IDirect3D7 which thunks to IDirectDraw7
323  *
324  * Returns: The new refcount
325  *
326  *****************************************************************************/
327 static ULONG WINAPI ddraw7_AddRef(IDirectDraw7 *iface)
328 {
329     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
330     ULONG ref = InterlockedIncrement(&This->ref7);
331
332     TRACE("%p increasing refcount to %u.\n", This, ref);
333
334     if(ref == 1) InterlockedIncrement(&This->numIfaces);
335
336     return ref;
337 }
338
339 static ULONG WINAPI ddraw4_AddRef(IDirectDraw4 *iface)
340 {
341     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
342     ULONG ref = InterlockedIncrement(&This->ref4);
343
344     TRACE("%p increasing refcount to %u.\n", This, ref);
345
346     if (ref == 1) InterlockedIncrement(&This->numIfaces);
347
348     return ref;
349 }
350
351 static ULONG WINAPI ddraw3_AddRef(IDirectDraw3 *iface)
352 {
353     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
354     ULONG ref = InterlockedIncrement(&This->ref3);
355
356     TRACE("%p increasing refcount to %u.\n", This, ref);
357
358     if (ref == 1) InterlockedIncrement(&This->numIfaces);
359
360     return ref;
361 }
362
363 static ULONG WINAPI ddraw2_AddRef(IDirectDraw2 *iface)
364 {
365     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
366     ULONG ref = InterlockedIncrement(&This->ref2);
367
368     TRACE("%p increasing refcount to %u.\n", This, ref);
369
370     if (ref == 1) InterlockedIncrement(&This->numIfaces);
371
372     return ref;
373 }
374
375 static ULONG WINAPI ddraw1_AddRef(IDirectDraw *iface)
376 {
377     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
378     ULONG ref = InterlockedIncrement(&This->ref1);
379
380     TRACE("%p increasing refcount to %u.\n", This, ref);
381
382     if (ref == 1) InterlockedIncrement(&This->numIfaces);
383
384     return ref;
385 }
386
387 static ULONG WINAPI d3d7_AddRef(IDirect3D7 *iface)
388 {
389     IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
390
391     TRACE("iface %p.\n", iface);
392
393     return ddraw7_AddRef((IDirectDraw7 *)This);
394 }
395
396 static ULONG WINAPI d3d3_AddRef(IDirect3D3 *iface)
397 {
398     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
399
400     TRACE("iface %p.\n", iface);
401
402     return ddraw1_AddRef(&This->IDirectDraw_iface);
403 }
404
405 static ULONG WINAPI d3d2_AddRef(IDirect3D2 *iface)
406 {
407     IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
408
409     TRACE("iface %p.\n", iface);
410
411     return ddraw1_AddRef(&This->IDirectDraw_iface);
412 }
413
414 static ULONG WINAPI d3d1_AddRef(IDirect3D *iface)
415 {
416     IDirectDrawImpl *This = impl_from_IDirect3D(iface);
417
418     TRACE("iface %p.\n", iface);
419
420     return ddraw1_AddRef(&This->IDirectDraw_iface);
421 }
422
423 /*****************************************************************************
424  * ddraw_destroy
425  *
426  * Destroys a ddraw object if all refcounts are 0. This is to share code
427  * between the IDirectDrawX::Release functions
428  *
429  * Params:
430  *  This: DirectDraw object to destroy
431  *
432  *****************************************************************************/
433 static void ddraw_destroy(IDirectDrawImpl *This)
434 {
435     IDirectDraw7_SetCooperativeLevel((IDirectDraw7 *)This, NULL, DDSCL_NORMAL);
436     IDirectDraw7_RestoreDisplayMode((IDirectDraw7 *)This);
437
438     /* Destroy the device window if we created one */
439     if(This->devicewindow != 0)
440     {
441         TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow);
442         DestroyWindow(This->devicewindow);
443         This->devicewindow = 0;
444     }
445
446     EnterCriticalSection(&ddraw_cs);
447     list_remove(&This->ddraw_list_entry);
448     LeaveCriticalSection(&ddraw_cs);
449
450     /* Release the attached WineD3D stuff */
451     IWineD3DDevice_Release(This->wineD3DDevice);
452     IWineD3D_Release(This->wineD3D);
453
454     /* Now free the object */
455     HeapFree(GetProcessHeap(), 0, This);
456 }
457
458 /*****************************************************************************
459  * IDirectDraw7::Release
460  *
461  * Decreases the refcount. If the refcount falls to 0, the object is destroyed
462  *
463  * Returns: The new refcount
464  *****************************************************************************/
465 static ULONG WINAPI ddraw7_Release(IDirectDraw7 *iface)
466 {
467     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
468     ULONG ref = InterlockedDecrement(&This->ref7);
469
470     TRACE("%p decreasing refcount to %u.\n", This, ref);
471
472     if (!ref && !InterlockedDecrement(&This->numIfaces))
473         ddraw_destroy(This);
474
475     return ref;
476 }
477
478 static ULONG WINAPI ddraw4_Release(IDirectDraw4 *iface)
479 {
480     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
481     ULONG ref = InterlockedDecrement(&This->ref4);
482
483     TRACE("%p decreasing refcount to %u.\n", This, ref);
484
485     if (!ref && !InterlockedDecrement(&This->numIfaces))
486         ddraw_destroy(This);
487
488     return ref;
489 }
490
491 static ULONG WINAPI ddraw3_Release(IDirectDraw3 *iface)
492 {
493     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
494     ULONG ref = InterlockedDecrement(&This->ref3);
495
496     TRACE("%p decreasing refcount to %u.\n", This, ref);
497
498     if (!ref && !InterlockedDecrement(&This->numIfaces))
499         ddraw_destroy(This);
500
501     return ref;
502 }
503
504 static ULONG WINAPI ddraw2_Release(IDirectDraw2 *iface)
505 {
506     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
507     ULONG ref = InterlockedDecrement(&This->ref2);
508
509     TRACE("%p decreasing refcount to %u.\n", This, ref);
510
511     if (!ref && !InterlockedDecrement(&This->numIfaces))
512         ddraw_destroy(This);
513
514     return ref;
515 }
516
517 static ULONG WINAPI ddraw1_Release(IDirectDraw *iface)
518 {
519     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
520     ULONG ref = InterlockedDecrement(&This->ref1);
521
522     TRACE("%p decreasing refcount to %u.\n", This, ref);
523
524     if (!ref && !InterlockedDecrement(&This->numIfaces))
525         ddraw_destroy(This);
526
527     return ref;
528 }
529
530 static ULONG WINAPI d3d7_Release(IDirect3D7 *iface)
531 {
532     IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
533
534     TRACE("iface %p.\n", iface);
535
536     return ddraw7_Release((IDirectDraw7 *)This);
537 }
538
539 static ULONG WINAPI d3d3_Release(IDirect3D3 *iface)
540 {
541     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
542
543     TRACE("iface %p.\n", iface);
544
545     return ddraw1_Release(&This->IDirectDraw_iface);
546 }
547
548 static ULONG WINAPI d3d2_Release(IDirect3D2 *iface)
549 {
550     IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
551
552     TRACE("iface %p.\n", iface);
553
554     return ddraw1_Release(&This->IDirectDraw_iface);
555 }
556
557 static ULONG WINAPI d3d1_Release(IDirect3D *iface)
558 {
559     IDirectDrawImpl *This = impl_from_IDirect3D(iface);
560
561     TRACE("iface %p.\n", iface);
562
563     return ddraw1_Release(&This->IDirectDraw_iface);
564 }
565
566 /*****************************************************************************
567  * IDirectDraw methods
568  *****************************************************************************/
569
570 /*****************************************************************************
571  * IDirectDraw7::SetCooperativeLevel
572  *
573  * Sets the cooperative level for the DirectDraw object, and the window
574  * assigned to it. The cooperative level determines the general behavior
575  * of the DirectDraw application
576  *
577  * Warning: This is quite tricky, as it's not really documented which
578  * cooperative levels can be combined with each other. If a game fails
579  * after this function, try to check the cooperative levels passed on
580  * Windows, and if it returns something different.
581  *
582  * If you think that this function caused the failure because it writes a
583  * fixme, be sure to run again with a +ddraw trace.
584  *
585  * What is known about cooperative levels (See the ddraw modes test):
586  * DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN must be used with each other
587  * DDSCL_NORMAL is not compatible with DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN
588  * DDSCL_SETFOCUSWINDOW can be passed only in DDSCL_NORMAL mode, but after that
589  * DDSCL_FULLSCREEN can be activated
590  * DDSCL_SETFOCUSWINDOW may only be used with DDSCL_NOWINDOWCHANGES
591  *
592  * Handled flags: DDSCL_NORMAL, DDSCL_FULLSCREEN, DDSCL_EXCLUSIVE,
593  *                DDSCL_SETFOCUSWINDOW (partially),
594  *                DDSCL_MULTITHREADED (work in progress)
595  *
596  * Unhandled flags, which should be implemented
597  *  DDSCL_SETDEVICEWINDOW: Sets a window specially used for rendering (I don't
598  *  expect any difference to a normal window for wine)
599  *  DDSCL_CREATEDEVICEWINDOW: Tells ddraw to create its own window for
600  *  rendering (Possible test case: Half-Life)
601  *
602  * Unsure about these: DDSCL_FPUSETUP DDSCL_FPURESERVE
603  *
604  * These don't seem very important for wine:
605  *  DDSCL_ALLOWREBOOT, DDSCL_NOWINDOWCHANGES, DDSCL_ALLOWMODEX
606  *
607  * Returns:
608  *  DD_OK if the cooperative level was set successfully
609  *  DDERR_INVALIDPARAMS if the passed cooperative level combination is invalid
610  *  DDERR_HWNDALREADYSET if DDSCL_SETFOCUSWINDOW is passed in exclusive mode
611  *   (Probably others too, have to investigate)
612  *
613  *****************************************************************************/
614 static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND hwnd, DWORD cooplevel)
615 {
616     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
617     HWND window;
618
619     TRACE("iface %p, window %p, flags %#x.\n", iface, hwnd, cooplevel);
620     DDRAW_dump_cooperativelevel(cooplevel);
621
622     EnterCriticalSection(&ddraw_cs);
623
624     /* Get the old window */
625     window = This->dest_window;
626
627     /* Tests suggest that we need one of them: */
628     if(!(cooplevel & (DDSCL_SETFOCUSWINDOW |
629                       DDSCL_NORMAL         |
630                       DDSCL_EXCLUSIVE      )))
631     {
632         TRACE("Incorrect cooplevel flags, returning DDERR_INVALIDPARAMS\n");
633         LeaveCriticalSection(&ddraw_cs);
634         return DDERR_INVALIDPARAMS;
635     }
636
637     /* Handle those levels first which set various hwnds */
638     if(cooplevel & DDSCL_SETFOCUSWINDOW)
639     {
640         /* This isn't compatible with a lot of flags */
641         if(cooplevel & ( DDSCL_MULTITHREADED      |
642                          DDSCL_CREATEDEVICEWINDOW |
643                          DDSCL_FPUSETUP           |
644                          DDSCL_FPUPRESERVE        |
645                          DDSCL_ALLOWREBOOT        |
646                          DDSCL_ALLOWMODEX         |
647                          DDSCL_SETDEVICEWINDOW    |
648                          DDSCL_NORMAL             |
649                          DDSCL_EXCLUSIVE          |
650                          DDSCL_FULLSCREEN         ) )
651         {
652             TRACE("Called with incompatible flags, returning DDERR_INVALIDPARAMS\n");
653             LeaveCriticalSection(&ddraw_cs);
654             return DDERR_INVALIDPARAMS;
655         }
656
657         if( (This->cooperative_level & DDSCL_EXCLUSIVE) && window )
658         {
659             TRACE("Setting DDSCL_SETFOCUSWINDOW with an already set window, returning DDERR_HWNDALREADYSET\n");
660             LeaveCriticalSection(&ddraw_cs);
661             return DDERR_HWNDALREADYSET;
662         }
663
664         This->focuswindow = hwnd;
665         /* Won't use the hwnd param for anything else */
666         hwnd = NULL;
667
668         /* Use the focus window for drawing too */
669         This->dest_window = This->focuswindow;
670
671         /* Destroy the device window, if we have one */
672         if(This->devicewindow)
673         {
674             DestroyWindow(This->devicewindow);
675             This->devicewindow = NULL;
676         }
677
678         LeaveCriticalSection(&ddraw_cs);
679         return DD_OK;
680     }
681
682     if(cooplevel & DDSCL_EXCLUSIVE)
683     {
684         if( !(cooplevel & DDSCL_FULLSCREEN) || !hwnd )
685         {
686             TRACE("(%p) DDSCL_EXCLUSIVE needs DDSCL_FULLSCREEN and a window\n", This);
687             LeaveCriticalSection(&ddraw_cs);
688             return DDERR_INVALIDPARAMS;
689         }
690     }
691     else if( !(cooplevel & DDSCL_NORMAL) )
692     {
693         TRACE("(%p) SetCooperativeLevel needs at least SetFocusWindow or Exclusive or Normal mode\n", This);
694         LeaveCriticalSection(&ddraw_cs);
695         return DDERR_INVALIDPARAMS;
696     }
697
698     if ((This->cooperative_level & DDSCL_EXCLUSIVE)
699             && (hwnd != window || !(cooplevel & DDSCL_EXCLUSIVE)))
700         IWineD3DDevice_ReleaseFocusWindow(This->wineD3DDevice);
701
702     if ((cooplevel & DDSCL_FULLSCREEN) != (This->cooperative_level & DDSCL_FULLSCREEN) || hwnd != window)
703     {
704         if (This->cooperative_level & DDSCL_FULLSCREEN)
705         {
706             IWineD3DDevice_RestoreFullscreenWindow(This->wineD3DDevice, window);
707         }
708         if (cooplevel & DDSCL_FULLSCREEN)
709         {
710             WINED3DDISPLAYMODE display_mode;
711
712             IWineD3D_GetAdapterDisplayMode(This->wineD3D, WINED3DADAPTER_DEFAULT, &display_mode);
713             IWineD3DDevice_SetupFullscreenWindow(This->wineD3DDevice, hwnd, display_mode.Width, display_mode.Height);
714         }
715     }
716
717     if ((cooplevel & DDSCL_EXCLUSIVE)
718             && (hwnd != window || !(This->cooperative_level & DDSCL_EXCLUSIVE)))
719     {
720         HRESULT hr = IWineD3DDevice_AcquireFocusWindow(This->wineD3DDevice, hwnd);
721         if (FAILED(hr))
722         {
723             ERR("Failed to acquire focus window, hr %#x.\n", hr);
724             LeaveCriticalSection(&ddraw_cs);
725             return hr;
726         }
727     }
728
729     /* Don't override focus windows or private device windows */
730     if (hwnd && !This->focuswindow && !This->devicewindow && (hwnd != window))
731         This->dest_window = hwnd;
732
733     if(cooplevel & DDSCL_CREATEDEVICEWINDOW)
734     {
735         /* Don't create a device window if a focus window is set */
736         if( !(This->focuswindow) )
737         {
738             HWND devicewindow = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "DDraw device window",
739                     WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
740                     NULL, NULL, NULL, NULL);
741             if (!devicewindow)
742             {
743                 ERR("Failed to create window, last error %#x.\n", GetLastError());
744                 LeaveCriticalSection(&ddraw_cs);
745                 return E_FAIL;
746             }
747
748             ShowWindow(devicewindow, SW_SHOW);   /* Just to be sure */
749             TRACE("(%p) Created a DDraw device window. HWND=%p\n", This, devicewindow);
750
751             This->devicewindow = devicewindow;
752             This->dest_window = devicewindow;
753         }
754     }
755
756     if(cooplevel & DDSCL_MULTITHREADED && !(This->cooperative_level & DDSCL_MULTITHREADED))
757     {
758         /* Enable thread safety in wined3d */
759         IWineD3DDevice_SetMultithreaded(This->wineD3DDevice);
760     }
761
762     /* Unhandled flags */
763     if(cooplevel & DDSCL_ALLOWREBOOT)
764         WARN("(%p) Unhandled flag DDSCL_ALLOWREBOOT, harmless\n", This);
765     if(cooplevel & DDSCL_ALLOWMODEX)
766         WARN("(%p) Unhandled flag DDSCL_ALLOWMODEX, harmless\n", This);
767     if(cooplevel & DDSCL_FPUSETUP)
768         WARN("(%p) Unhandled flag DDSCL_FPUSETUP, harmless\n", This);
769
770     /* Store the cooperative_level */
771     This->cooperative_level = cooplevel;
772     TRACE("SetCooperativeLevel retuning DD_OK\n");
773     LeaveCriticalSection(&ddraw_cs);
774     return DD_OK;
775 }
776
777 static HRESULT WINAPI ddraw4_SetCooperativeLevel(IDirectDraw4 *iface, HWND window, DWORD flags)
778 {
779     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
780
781     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
782
783     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)This, window, flags);
784 }
785
786 static HRESULT WINAPI ddraw3_SetCooperativeLevel(IDirectDraw3 *iface, HWND window, DWORD flags)
787 {
788     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
789
790     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
791
792     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)This, window, flags);
793 }
794
795 static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND window, DWORD flags)
796 {
797     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
798
799     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
800
801     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)This, window, flags);
802 }
803
804 static HRESULT WINAPI ddraw1_SetCooperativeLevel(IDirectDraw *iface, HWND window, DWORD flags)
805 {
806     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
807
808     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
809
810     return ddraw7_SetCooperativeLevel((IDirectDraw7 *)This, window, flags);
811 }
812
813 /*****************************************************************************
814  *
815  * Helper function for SetDisplayMode and RestoreDisplayMode
816  *
817  * Implements DirectDraw's SetDisplayMode, but ignores the value of
818  * ForceRefreshRate, since it is already handled by
819  * ddraw7_SetDisplayMode.  RestoreDisplayMode can use this function
820  * without worrying that ForceRefreshRate will override the refresh rate.  For
821  * argument and return value documentation, see
822  * ddraw7_SetDisplayMode.
823  *
824  *****************************************************************************/
825 static HRESULT ddraw_set_display_mode(IDirectDrawImpl *ddraw, DWORD Width, DWORD Height,
826         DWORD BPP, DWORD RefreshRate, DWORD Flags)
827 {
828     WINED3DDISPLAYMODE Mode;
829     HRESULT hr;
830
831     TRACE("ddraw %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n", ddraw, Width,
832             Height, BPP, RefreshRate, Flags);
833
834     EnterCriticalSection(&ddraw_cs);
835     if( !Width || !Height )
836     {
837         ERR("Width %u, Height %u, what to do?\n", Width, Height);
838         /* It looks like Need for Speed Porsche Unleashed expects DD_OK here */
839         LeaveCriticalSection(&ddraw_cs);
840         return DD_OK;
841     }
842
843     /* Check the exclusive mode
844     if(!(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
845         return DDERR_NOEXCLUSIVEMODE;
846      * This is WRONG. Don't know if the SDK is completely
847      * wrong and if there are any conditions when DDERR_NOEXCLUSIVE
848      * is returned, but Half-Life 1.1.1.1 (Steam version)
849      * depends on this
850      */
851
852     Mode.Width = Width;
853     Mode.Height = Height;
854     Mode.RefreshRate = RefreshRate;
855     switch(BPP)
856     {
857         case 8:  Mode.Format = WINED3DFMT_P8_UINT;          break;
858         case 15: Mode.Format = WINED3DFMT_B5G5R5X1_UNORM;   break;
859         case 16: Mode.Format = WINED3DFMT_B5G6R5_UNORM;     break;
860         case 24: Mode.Format = WINED3DFMT_B8G8R8_UNORM;     break;
861         case 32: Mode.Format = WINED3DFMT_B8G8R8X8_UNORM;   break;
862     }
863
864     /* TODO: The possible return values from msdn suggest that
865      * the screen mode can't be changed if a surface is locked
866      * or some drawing is in progress
867      */
868
869     /* TODO: Lose the primary surface */
870     hr = IWineD3DDevice_SetDisplayMode(ddraw->wineD3DDevice, 0, &Mode);
871     IWineD3DDevice_RestoreFullscreenWindow(ddraw->wineD3DDevice, ddraw->dest_window);
872     IWineD3DDevice_SetupFullscreenWindow(ddraw->wineD3DDevice, ddraw->dest_window, Width, Height);
873     LeaveCriticalSection(&ddraw_cs);
874     switch(hr)
875     {
876         case WINED3DERR_NOTAVAILABLE:       return DDERR_UNSUPPORTED;
877         default:                            return hr;
878     }
879 }
880
881 /*****************************************************************************
882  * IDirectDraw7::SetDisplayMode
883  *
884  * Sets the display screen resolution, color depth and refresh frequency
885  * when in fullscreen mode (in theory).
886  * Possible return values listed in the SDK suggest that this method fails
887  * when not in fullscreen mode, but this is wrong. Windows 2000 happily sets
888  * the display mode in DDSCL_NORMAL mode without an hwnd specified.
889  * It seems to be valid to pass 0 for With and Height, this has to be tested
890  * It could mean that the current video mode should be left as-is. (But why
891  * call it then?)
892  *
893  * Params:
894  *  Height, Width: Screen dimension
895  *  BPP: Color depth in Bits per pixel
896  *  Refreshrate: Screen refresh rate
897  *  Flags: Other stuff
898  *
899  * Returns
900  *  DD_OK on success
901  *
902  *****************************************************************************/
903 static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD Width, DWORD Height,
904         DWORD BPP, DWORD RefreshRate, DWORD Flags)
905 {
906     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
907
908     TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
909             iface, Width, Height, BPP, RefreshRate, Flags);
910
911     if (force_refresh_rate != 0)
912     {
913         TRACE("ForceRefreshRate overriding passed-in refresh rate (%u Hz) to %u Hz\n",
914                 RefreshRate, force_refresh_rate);
915         RefreshRate = force_refresh_rate;
916     }
917
918     return ddraw_set_display_mode(This, Width, Height, BPP, RefreshRate, Flags);
919 }
920
921 static HRESULT WINAPI ddraw4_SetDisplayMode(IDirectDraw4 *iface, DWORD width, DWORD height,
922         DWORD bpp, DWORD refresh_rate, DWORD flags)
923 {
924     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
925
926     TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
927             iface, width, height, bpp, refresh_rate, flags);
928
929     return ddraw7_SetDisplayMode((IDirectDraw7 *)This, width, height, bpp, refresh_rate, flags);
930 }
931
932 static HRESULT WINAPI ddraw3_SetDisplayMode(IDirectDraw3 *iface, DWORD width, DWORD height,
933         DWORD bpp, DWORD refresh_rate, DWORD flags)
934 {
935     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
936
937     TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
938             iface, width, height, bpp, refresh_rate, flags);
939
940     return ddraw7_SetDisplayMode((IDirectDraw7 *)This, width, height, bpp, refresh_rate, flags);
941 }
942
943 static HRESULT WINAPI ddraw2_SetDisplayMode(IDirectDraw2 *iface,
944         DWORD width, DWORD height, DWORD bpp, DWORD refresh_rate, DWORD flags)
945 {
946     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
947
948     TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n",
949             iface, width, height, bpp, refresh_rate, flags);
950
951     return ddraw7_SetDisplayMode((IDirectDraw7 *)This, width, height, bpp, refresh_rate, flags);
952 }
953
954 static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWORD height, DWORD bpp)
955 {
956     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
957
958     TRACE("iface %p, width %u, height %u, bpp %u.\n", iface, width, height, bpp);
959
960     return ddraw7_SetDisplayMode((IDirectDraw7 *)This, width, height, bpp, 0, 0);
961 }
962
963 /*****************************************************************************
964  * IDirectDraw7::RestoreDisplayMode
965  *
966  * Restores the display mode to what it was at creation time. Basically.
967  *
968  * A problem arises when there are 2 DirectDraw objects using the same hwnd:
969  *  -> DD_1 finds the screen at 1400x1050x32 when created, sets it to 640x480x16
970  *  -> DD_2 is created, finds the screen at 640x480x16, sets it to 1024x768x32
971  *  -> DD_1 is released. The screen should be left at 1024x768x32.
972  *  -> DD_2 is released. The screen should be set to 1400x1050x32
973  * This case is unhandled right now, but Empire Earth does it this way.
974  * (But perhaps there is something in SetCooperativeLevel to prevent this)
975  *
976  * The msdn says that this method resets the display mode to what it was before
977  * SetDisplayMode was called. What if SetDisplayModes is called 2 times??
978  *
979  * Returns
980  *  DD_OK on success
981  *  DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
982  *
983  *****************************************************************************/
984 static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
985 {
986     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
987
988     TRACE("iface %p.\n", iface);
989
990     return ddraw_set_display_mode(This, This->orig_width, This->orig_height, This->orig_bpp, 0, 0);
991 }
992
993 static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
994 {
995     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
996
997     TRACE("iface %p.\n", iface);
998
999     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)This);
1000 }
1001
1002 static HRESULT WINAPI ddraw3_RestoreDisplayMode(IDirectDraw3 *iface)
1003 {
1004     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1005
1006     TRACE("iface %p.\n", iface);
1007
1008     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)This);
1009 }
1010
1011 static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
1012 {
1013     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1014
1015     TRACE("iface %p.\n", iface);
1016
1017     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)This);
1018 }
1019
1020 static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
1021 {
1022     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1023
1024     TRACE("iface %p.\n", iface);
1025
1026     return ddraw7_RestoreDisplayMode((IDirectDraw7 *)This);
1027 }
1028
1029 /*****************************************************************************
1030  * IDirectDraw7::GetCaps
1031  *
1032  * Returns the drives capabilities
1033  *
1034  * Used for version 1, 2, 4 and 7
1035  *
1036  * Params:
1037  *  DriverCaps: Structure to write the Hardware accelerated caps to
1038  *  HelCaps: Structure to write the emulation caps to
1039  *
1040  * Returns
1041  *  This implementation returns DD_OK only
1042  *
1043  *****************************************************************************/
1044 static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DDCAPS *HELCaps)
1045 {
1046     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1047     DDCAPS caps;
1048     WINED3DCAPS winecaps;
1049     HRESULT hr;
1050     DDSCAPS2 ddscaps = {0, 0, 0, 0};
1051
1052     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, DriverCaps, HELCaps);
1053
1054     /* One structure must be != NULL */
1055     if( (!DriverCaps) && (!HELCaps) )
1056     {
1057         ERR("(%p) Invalid params to ddraw7_GetCaps\n", This);
1058         return DDERR_INVALIDPARAMS;
1059     }
1060
1061     memset(&caps, 0, sizeof(caps));
1062     memset(&winecaps, 0, sizeof(winecaps));
1063     caps.dwSize = sizeof(caps);
1064     EnterCriticalSection(&ddraw_cs);
1065     hr = IWineD3DDevice_GetDeviceCaps(This->wineD3DDevice, &winecaps);
1066     if(FAILED(hr)) {
1067         WARN("IWineD3DDevice::GetDeviceCaps failed\n");
1068         LeaveCriticalSection(&ddraw_cs);
1069         return hr;
1070     }
1071
1072     hr = IDirectDraw7_GetAvailableVidMem(iface, &ddscaps, &caps.dwVidMemTotal, &caps.dwVidMemFree);
1073     LeaveCriticalSection(&ddraw_cs);
1074     if(FAILED(hr)) {
1075         WARN("IDirectDraw7::GetAvailableVidMem failed\n");
1076         return hr;
1077     }
1078
1079     caps.dwCaps = winecaps.DirectDrawCaps.Caps;
1080     caps.dwCaps2 = winecaps.DirectDrawCaps.Caps2;
1081     caps.dwCKeyCaps = winecaps.DirectDrawCaps.CKeyCaps;
1082     caps.dwFXCaps = winecaps.DirectDrawCaps.FXCaps;
1083     caps.dwPalCaps = winecaps.DirectDrawCaps.PalCaps;
1084     caps.ddsCaps.dwCaps = winecaps.DirectDrawCaps.ddsCaps;
1085     caps.dwSVBCaps = winecaps.DirectDrawCaps.SVBCaps;
1086     caps.dwSVBCKeyCaps = winecaps.DirectDrawCaps.SVBCKeyCaps;
1087     caps.dwSVBFXCaps = winecaps.DirectDrawCaps.SVBFXCaps;
1088     caps.dwVSBCaps = winecaps.DirectDrawCaps.VSBCaps;
1089     caps.dwVSBCKeyCaps = winecaps.DirectDrawCaps.VSBCKeyCaps;
1090     caps.dwVSBFXCaps = winecaps.DirectDrawCaps.VSBFXCaps;
1091     caps.dwSSBCaps = winecaps.DirectDrawCaps.SSBCaps;
1092     caps.dwSSBCKeyCaps = winecaps.DirectDrawCaps.SSBCKeyCaps;
1093     caps.dwSSBFXCaps = winecaps.DirectDrawCaps.SSBFXCaps;
1094
1095     /* Even if WineD3D supports 3D rendering, remove the cap if ddraw is configured
1096      * not to use it
1097      */
1098     if(DefaultSurfaceType == SURFACE_GDI) {
1099         caps.dwCaps &= ~DDCAPS_3D;
1100         caps.ddsCaps.dwCaps &= ~(DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER);
1101     }
1102     if(winecaps.DirectDrawCaps.StrideAlign != 0) {
1103         caps.dwCaps |= DDCAPS_ALIGNSTRIDE;
1104         caps.dwAlignStrideAlign = winecaps.DirectDrawCaps.StrideAlign;
1105     }
1106
1107     if(DriverCaps)
1108     {
1109         DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
1110         if (TRACE_ON(ddraw))
1111         {
1112             TRACE("Driver Caps :\n");
1113             DDRAW_dump_DDCAPS(DriverCaps);
1114         }
1115
1116     }
1117     if(HELCaps)
1118     {
1119         DD_STRUCT_COPY_BYSIZE(HELCaps, &caps);
1120         if (TRACE_ON(ddraw))
1121         {
1122             TRACE("HEL Caps :\n");
1123             DDRAW_dump_DDCAPS(HELCaps);
1124         }
1125     }
1126
1127     return DD_OK;
1128 }
1129
1130 static HRESULT WINAPI ddraw4_GetCaps(IDirectDraw4 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1131 {
1132     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1133
1134     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1135
1136     return ddraw7_GetCaps((IDirectDraw7 *)This, driver_caps, hel_caps);
1137 }
1138
1139 static HRESULT WINAPI ddraw3_GetCaps(IDirectDraw3 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1140 {
1141     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1142
1143     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1144
1145     return ddraw7_GetCaps((IDirectDraw7 *)This, driver_caps, hel_caps);
1146 }
1147
1148 static HRESULT WINAPI ddraw2_GetCaps(IDirectDraw2 *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1149 {
1150     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1151
1152     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1153
1154     return ddraw7_GetCaps((IDirectDraw7 *)This, driver_caps, hel_caps);
1155 }
1156
1157 static HRESULT WINAPI ddraw1_GetCaps(IDirectDraw *iface, DDCAPS *driver_caps, DDCAPS *hel_caps)
1158 {
1159     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1160
1161     TRACE("iface %p, driver_caps %p, hel_caps %p.\n", iface, driver_caps, hel_caps);
1162
1163     return ddraw7_GetCaps((IDirectDraw7 *)This, driver_caps, hel_caps);
1164 }
1165
1166 /*****************************************************************************
1167  * IDirectDraw7::Compact
1168  *
1169  * No idea what it does, MSDN says it's not implemented.
1170  *
1171  * Returns
1172  *  DD_OK, but this is unchecked
1173  *
1174  *****************************************************************************/
1175 static HRESULT WINAPI ddraw7_Compact(IDirectDraw7 *iface)
1176 {
1177     TRACE("iface %p.\n", iface);
1178
1179     return DD_OK;
1180 }
1181
1182 static HRESULT WINAPI ddraw4_Compact(IDirectDraw4 *iface)
1183 {
1184     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1185
1186     TRACE("iface %p.\n", iface);
1187
1188     return ddraw7_Compact((IDirectDraw7 *)This);
1189 }
1190
1191 static HRESULT WINAPI ddraw3_Compact(IDirectDraw3 *iface)
1192 {
1193     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1194
1195     TRACE("iface %p.\n", iface);
1196
1197     return ddraw7_Compact((IDirectDraw7 *)This);
1198 }
1199
1200 static HRESULT WINAPI ddraw2_Compact(IDirectDraw2 *iface)
1201 {
1202     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1203
1204     TRACE("iface %p.\n", iface);
1205
1206     return ddraw7_Compact((IDirectDraw7 *)This);
1207 }
1208
1209 static HRESULT WINAPI ddraw1_Compact(IDirectDraw *iface)
1210 {
1211     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1212
1213     TRACE("iface %p.\n", iface);
1214
1215     return ddraw7_Compact((IDirectDraw7 *)This);
1216 }
1217
1218 /*****************************************************************************
1219  * IDirectDraw7::GetDisplayMode
1220  *
1221  * Returns information about the current display mode
1222  *
1223  * Exists in Version 1, 2, 4 and 7
1224  *
1225  * Params:
1226  *  DDSD: Address of a surface description structure to write the info to
1227  *
1228  * Returns
1229  *  DD_OK
1230  *
1231  *****************************************************************************/
1232 static HRESULT WINAPI ddraw7_GetDisplayMode(IDirectDraw7 *iface, DDSURFACEDESC2 *DDSD)
1233 {
1234     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1235     HRESULT hr;
1236     WINED3DDISPLAYMODE Mode;
1237     DWORD Size;
1238
1239     TRACE("iface %p, surface_desc %p.\n", iface, DDSD);
1240
1241     EnterCriticalSection(&ddraw_cs);
1242     /* This seems sane */
1243     if (!DDSD)
1244     {
1245         LeaveCriticalSection(&ddraw_cs);
1246         return DDERR_INVALIDPARAMS;
1247     }
1248
1249     /* The necessary members of LPDDSURFACEDESC and LPDDSURFACEDESC2 are equal,
1250      * so one method can be used for all versions (Hopefully)
1251      */
1252     hr = IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1253                                       0 /* swapchain 0 */,
1254                                       &Mode);
1255     if( hr != D3D_OK )
1256     {
1257         ERR(" (%p) IWineD3DDevice::GetDisplayMode returned %08x\n", This, hr);
1258         LeaveCriticalSection(&ddraw_cs);
1259         return hr;
1260     }
1261
1262     Size = DDSD->dwSize;
1263     memset(DDSD, 0, Size);
1264
1265     DDSD->dwSize = Size;
1266     DDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE;
1267     DDSD->dwWidth = Mode.Width;
1268     DDSD->dwHeight = Mode.Height;
1269     DDSD->u2.dwRefreshRate = 60;
1270     DDSD->ddsCaps.dwCaps = 0;
1271     DDSD->u4.ddpfPixelFormat.dwSize = sizeof(DDSD->u4.ddpfPixelFormat);
1272     PixelFormat_WineD3DtoDD(&DDSD->u4.ddpfPixelFormat, Mode.Format);
1273     DDSD->u1.lPitch = Mode.Width * DDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount / 8;
1274
1275     if(TRACE_ON(ddraw))
1276     {
1277         TRACE("Returning surface desc :\n");
1278         DDRAW_dump_surface_desc(DDSD);
1279     }
1280
1281     LeaveCriticalSection(&ddraw_cs);
1282     return DD_OK;
1283 }
1284
1285 static HRESULT WINAPI ddraw4_GetDisplayMode(IDirectDraw4 *iface, DDSURFACEDESC2 *surface_desc)
1286 {
1287     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1288
1289     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1290
1291     return ddraw7_GetDisplayMode((IDirectDraw7 *)This, surface_desc);
1292 }
1293
1294 static HRESULT WINAPI ddraw3_GetDisplayMode(IDirectDraw3 *iface, DDSURFACEDESC *surface_desc)
1295 {
1296     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1297
1298     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1299
1300     return ddraw7_GetDisplayMode((IDirectDraw7 *)This, (DDSURFACEDESC2 *)surface_desc);
1301 }
1302
1303 static HRESULT WINAPI ddraw2_GetDisplayMode(IDirectDraw2 *iface, DDSURFACEDESC *surface_desc)
1304 {
1305     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1306
1307     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1308
1309     return ddraw7_GetDisplayMode((IDirectDraw7 *)This, (DDSURFACEDESC2 *)surface_desc);
1310 }
1311
1312 static HRESULT WINAPI ddraw1_GetDisplayMode(IDirectDraw *iface, DDSURFACEDESC *surface_desc)
1313 {
1314     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1315
1316     TRACE("iface %p, surface_desc %p.\n", iface, surface_desc);
1317
1318     return ddraw7_GetDisplayMode((IDirectDraw7 *)This, (DDSURFACEDESC2 *)surface_desc);
1319 }
1320
1321 /*****************************************************************************
1322  * IDirectDraw7::GetFourCCCodes
1323  *
1324  * Returns an array of supported FourCC codes.
1325  *
1326  * Exists in Version 1, 2, 4 and 7
1327  *
1328  * Params:
1329  *  NumCodes: Contains the number of Codes that Codes can carry. Returns the number
1330  *            of enumerated codes
1331  *  Codes: Pointer to an array of DWORDs where the supported codes are written
1332  *         to
1333  *
1334  * Returns
1335  *  Always returns DD_OK, as it's a stub for now
1336  *
1337  *****************************************************************************/
1338 static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes, DWORD *Codes)
1339 {
1340     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1341     static const enum wined3d_format_id formats[] =
1342     {
1343         WINED3DFMT_YUY2, WINED3DFMT_UYVY, WINED3DFMT_YV12,
1344         WINED3DFMT_DXT1, WINED3DFMT_DXT2, WINED3DFMT_DXT3, WINED3DFMT_DXT4, WINED3DFMT_DXT5,
1345         WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS
1346     };
1347     DWORD count = 0, i, outsize;
1348     HRESULT hr;
1349     WINED3DDISPLAYMODE d3ddm;
1350     WINED3DSURFTYPE type = This->ImplType;
1351
1352     TRACE("iface %p, codes_count %p, codes %p.\n", iface, NumCodes, Codes);
1353
1354     IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1355                                   0 /* swapchain 0 */,
1356                                   &d3ddm);
1357
1358     outsize = NumCodes && Codes ? *NumCodes : 0;
1359
1360     if(type == SURFACE_UNKNOWN) type = SURFACE_GDI;
1361
1362     for(i = 0; i < (sizeof(formats) / sizeof(formats[0])); i++) {
1363         hr = IWineD3D_CheckDeviceFormat(This->wineD3D,
1364                                         WINED3DADAPTER_DEFAULT,
1365                                         WINED3DDEVTYPE_HAL,
1366                                         d3ddm.Format /* AdapterFormat */,
1367                                         0 /* usage */,
1368                                         WINED3DRTYPE_SURFACE,
1369                                         formats[i],
1370                                         type);
1371         if(SUCCEEDED(hr)) {
1372             if(count < outsize) {
1373                 Codes[count] = formats[i];
1374             }
1375             count++;
1376         }
1377     }
1378     if(NumCodes) {
1379         TRACE("Returning %u FourCC codes\n", count);
1380         *NumCodes = count;
1381     }
1382
1383     return DD_OK;
1384 }
1385
1386 static HRESULT WINAPI ddraw4_GetFourCCCodes(IDirectDraw4 *iface, DWORD *codes_count, DWORD *codes)
1387 {
1388     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1389
1390     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1391
1392     return ddraw7_GetFourCCCodes((IDirectDraw7 *)This, codes_count, codes);
1393 }
1394
1395 static HRESULT WINAPI ddraw3_GetFourCCCodes(IDirectDraw3 *iface, DWORD *codes_count, DWORD *codes)
1396 {
1397     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1398
1399     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1400
1401     return ddraw7_GetFourCCCodes((IDirectDraw7 *)This, codes_count, codes);
1402 }
1403
1404 static HRESULT WINAPI ddraw2_GetFourCCCodes(IDirectDraw2 *iface, DWORD *codes_count, DWORD *codes)
1405 {
1406     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1407
1408     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1409
1410     return ddraw7_GetFourCCCodes((IDirectDraw7 *)This, codes_count, codes);
1411 }
1412
1413 static HRESULT WINAPI ddraw1_GetFourCCCodes(IDirectDraw *iface, DWORD *codes_count, DWORD *codes)
1414 {
1415     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1416
1417     TRACE("iface %p, codes_count %p, codes %p.\n", iface, codes_count, codes);
1418
1419     return ddraw7_GetFourCCCodes((IDirectDraw7 *)This, codes_count, codes);
1420 }
1421
1422 /*****************************************************************************
1423  * IDirectDraw7::GetMonitorFrequency
1424  *
1425  * Returns the monitor's frequency
1426  *
1427  * Exists in Version 1, 2, 4 and 7
1428  *
1429  * Params:
1430  *  Freq: Pointer to a DWORD to write the frequency to
1431  *
1432  * Returns
1433  *  Always returns DD_OK
1434  *
1435  *****************************************************************************/
1436 static HRESULT WINAPI ddraw7_GetMonitorFrequency(IDirectDraw7 *iface, DWORD *Freq)
1437 {
1438     FIXME("iface %p, frequency %p stub!\n", iface, Freq);
1439
1440     /* Ideally this should be in WineD3D, as it concerns the screen setup,
1441      * but for now this should make the games happy
1442      */
1443     *Freq = 60;
1444     return DD_OK;
1445 }
1446
1447 static HRESULT WINAPI ddraw4_GetMonitorFrequency(IDirectDraw4 *iface, DWORD *frequency)
1448 {
1449     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1450
1451     TRACE("iface %p, frequency %p.\n", iface, frequency);
1452
1453     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)This, frequency);
1454 }
1455
1456 static HRESULT WINAPI ddraw3_GetMonitorFrequency(IDirectDraw3 *iface, DWORD *frequency)
1457 {
1458     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1459
1460     TRACE("iface %p, frequency %p.\n", iface, frequency);
1461
1462     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)This, frequency);
1463 }
1464
1465 static HRESULT WINAPI ddraw2_GetMonitorFrequency(IDirectDraw2 *iface, DWORD *frequency)
1466 {
1467     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1468
1469     TRACE("iface %p, frequency %p.\n", iface, frequency);
1470
1471     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)This, frequency);
1472 }
1473
1474 static HRESULT WINAPI ddraw1_GetMonitorFrequency(IDirectDraw *iface, DWORD *frequency)
1475 {
1476     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1477
1478     TRACE("iface %p, frequency %p.\n", iface, frequency);
1479
1480     return ddraw7_GetMonitorFrequency((IDirectDraw7 *)This, frequency);
1481 }
1482
1483 /*****************************************************************************
1484  * IDirectDraw7::GetVerticalBlankStatus
1485  *
1486  * Returns the Vertical blank status of the monitor. This should be in WineD3D
1487  * too basically, but as it's a semi stub, I didn't create a function there
1488  *
1489  * Params:
1490  *  status: Pointer to a BOOL to be filled with the vertical blank status
1491  *
1492  * Returns
1493  *  DD_OK on success
1494  *  DDERR_INVALIDPARAMS if status is NULL
1495  *
1496  *****************************************************************************/
1497 static HRESULT WINAPI ddraw7_GetVerticalBlankStatus(IDirectDraw7 *iface, BOOL *status)
1498 {
1499     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1500
1501     TRACE("iface %p, status %p.\n", iface, status);
1502
1503     /* This looks sane, the MSDN suggests it too */
1504     EnterCriticalSection(&ddraw_cs);
1505     if(!status)
1506     {
1507         LeaveCriticalSection(&ddraw_cs);
1508         return DDERR_INVALIDPARAMS;
1509     }
1510
1511     *status = This->fake_vblank;
1512     This->fake_vblank = !This->fake_vblank;
1513     LeaveCriticalSection(&ddraw_cs);
1514     return DD_OK;
1515 }
1516
1517 static HRESULT WINAPI ddraw4_GetVerticalBlankStatus(IDirectDraw4 *iface, BOOL *status)
1518 {
1519     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1520
1521     TRACE("iface %p, status %p.\n", iface, status);
1522
1523     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)This, status);
1524 }
1525
1526 static HRESULT WINAPI ddraw3_GetVerticalBlankStatus(IDirectDraw3 *iface, BOOL *status)
1527 {
1528     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1529
1530     TRACE("iface %p, status %p.\n", iface, status);
1531
1532     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)This, status);
1533 }
1534
1535 static HRESULT WINAPI ddraw2_GetVerticalBlankStatus(IDirectDraw2 *iface, BOOL *status)
1536 {
1537     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1538
1539     TRACE("iface %p, status %p.\n", iface, status);
1540
1541     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)This, status);
1542 }
1543
1544 static HRESULT WINAPI ddraw1_GetVerticalBlankStatus(IDirectDraw *iface, BOOL *status)
1545 {
1546     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1547
1548     TRACE("iface %p, status %p.\n", iface, status);
1549
1550     return ddraw7_GetVerticalBlankStatus((IDirectDraw7 *)This, status);
1551 }
1552
1553 /*****************************************************************************
1554  * IDirectDraw7::GetAvailableVidMem
1555  *
1556  * Returns the total and free video memory
1557  *
1558  * Params:
1559  *  Caps: Specifies the memory type asked for
1560  *  total: Pointer to a DWORD to be filled with the total memory
1561  *  free: Pointer to a DWORD to be filled with the free memory
1562  *
1563  * Returns
1564  *  DD_OK on success
1565  *  DDERR_INVALIDPARAMS of free and total are NULL
1566  *
1567  *****************************************************************************/
1568 static HRESULT WINAPI ddraw7_GetAvailableVidMem(IDirectDraw7 *iface, DDSCAPS2 *Caps, DWORD *total, DWORD *free)
1569 {
1570     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1571
1572     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, Caps, total, free);
1573
1574     if(TRACE_ON(ddraw))
1575     {
1576         TRACE("(%p) Asked for memory with description: ", This);
1577         DDRAW_dump_DDSCAPS2(Caps);
1578     }
1579     EnterCriticalSection(&ddraw_cs);
1580
1581     /* Todo: System memory vs local video memory vs non-local video memory
1582      * The MSDN also mentions differences between texture memory and other
1583      * resources, but that's not important
1584      */
1585
1586     if( (!total) && (!free) )
1587     {
1588         LeaveCriticalSection(&ddraw_cs);
1589         return DDERR_INVALIDPARAMS;
1590     }
1591
1592     if(total) *total = This->total_vidmem;
1593     if(free) *free = IWineD3DDevice_GetAvailableTextureMem(This->wineD3DDevice);
1594
1595     LeaveCriticalSection(&ddraw_cs);
1596     return DD_OK;
1597 }
1598
1599 static HRESULT WINAPI ddraw4_GetAvailableVidMem(IDirectDraw4 *iface,
1600         DDSCAPS2 *caps, DWORD *total, DWORD *free)
1601 {
1602     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1603
1604     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1605
1606     return ddraw7_GetAvailableVidMem((IDirectDraw7 *)This, caps, total, free);
1607 }
1608
1609 static HRESULT WINAPI ddraw3_GetAvailableVidMem(IDirectDraw3 *iface, DDSCAPS *caps, DWORD *total,
1610         DWORD *free)
1611 {
1612     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1613     DDSCAPS2 caps2;
1614
1615     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1616
1617     DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
1618     return ddraw7_GetAvailableVidMem((IDirectDraw7 *)This, &caps2, total, free);
1619 }
1620
1621 static HRESULT WINAPI ddraw2_GetAvailableVidMem(IDirectDraw2 *iface,
1622         DDSCAPS *caps, DWORD *total, DWORD *free)
1623 {
1624     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1625     DDSCAPS2 caps2;
1626
1627     TRACE("iface %p, caps %p, total %p, free %p.\n", iface, caps, total, free);
1628
1629     DDRAW_Convert_DDSCAPS_1_To_2(caps, &caps2);
1630     return ddraw7_GetAvailableVidMem((IDirectDraw7 *)This, &caps2, total, free);
1631 }
1632
1633 /*****************************************************************************
1634  * IDirectDraw7::Initialize
1635  *
1636  * Initializes a DirectDraw interface.
1637  *
1638  * Params:
1639  *  GUID: Interface identifier. Well, don't know what this is really good
1640  *   for
1641  *
1642  * Returns
1643  *  Returns DD_OK on the first call,
1644  *  DDERR_ALREADYINITIALIZED on repeated calls
1645  *
1646  *****************************************************************************/
1647 static HRESULT WINAPI ddraw7_Initialize(IDirectDraw7 *iface, GUID *Guid)
1648 {
1649     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1650
1651     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(Guid));
1652
1653     if(This->initialized)
1654     {
1655         return DDERR_ALREADYINITIALIZED;
1656     }
1657     else
1658     {
1659         return DD_OK;
1660     }
1661 }
1662
1663 static HRESULT WINAPI ddraw4_Initialize(IDirectDraw4 *iface, GUID *guid)
1664 {
1665     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1666
1667     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1668
1669     return ddraw7_Initialize((IDirectDraw7 *)This, guid);
1670 }
1671
1672 static HRESULT WINAPI ddraw3_Initialize(IDirectDraw3 *iface, GUID *guid)
1673 {
1674     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1675
1676     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1677
1678     return ddraw7_Initialize((IDirectDraw7 *)This, guid);
1679 }
1680
1681 static HRESULT WINAPI ddraw2_Initialize(IDirectDraw2 *iface, GUID *guid)
1682 {
1683     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1684
1685     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1686
1687     return ddraw7_Initialize((IDirectDraw7 *)This, guid);
1688 }
1689
1690 static HRESULT WINAPI ddraw1_Initialize(IDirectDraw *iface, GUID *guid)
1691 {
1692     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1693
1694     TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
1695
1696     return ddraw7_Initialize((IDirectDraw7 *)This, guid);
1697 }
1698
1699 static HRESULT WINAPI d3d1_Initialize(IDirect3D *iface, REFIID riid)
1700 {
1701     TRACE("iface %p, riid %s.\n", iface, debugstr_guid(riid));
1702
1703     return D3D_OK;
1704 }
1705
1706 /*****************************************************************************
1707  * IDirectDraw7::FlipToGDISurface
1708  *
1709  * "Makes the surface that the GDI writes to the primary surface"
1710  * Looks like some windows specific thing we don't have to care about.
1711  * According to MSDN it permits GDI dialog boxes in FULLSCREEN mode. Good to
1712  * show error boxes ;)
1713  * Well, just return DD_OK.
1714  *
1715  * Returns:
1716  *  Always returns DD_OK
1717  *
1718  *****************************************************************************/
1719 static HRESULT WINAPI ddraw7_FlipToGDISurface(IDirectDraw7 *iface)
1720 {
1721     FIXME("iface %p stub!\n", iface);
1722
1723     return DD_OK;
1724 }
1725
1726 static HRESULT WINAPI ddraw4_FlipToGDISurface(IDirectDraw4 *iface)
1727 {
1728     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1729
1730     TRACE("iface %p.\n", iface);
1731
1732     return ddraw7_FlipToGDISurface((IDirectDraw7 *)This);
1733 }
1734
1735 static HRESULT WINAPI ddraw3_FlipToGDISurface(IDirectDraw3 *iface)
1736 {
1737     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1738
1739     TRACE("iface %p.\n", iface);
1740
1741     return ddraw7_FlipToGDISurface((IDirectDraw7 *)This);
1742 }
1743
1744 static HRESULT WINAPI ddraw2_FlipToGDISurface(IDirectDraw2 *iface)
1745 {
1746     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1747
1748     TRACE("iface %p.\n", iface);
1749
1750     return ddraw7_FlipToGDISurface((IDirectDraw7 *)This);
1751 }
1752
1753 static HRESULT WINAPI ddraw1_FlipToGDISurface(IDirectDraw *iface)
1754 {
1755     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1756
1757     TRACE("iface %p.\n", iface);
1758
1759     return ddraw7_FlipToGDISurface((IDirectDraw7 *)This);
1760 }
1761
1762 /*****************************************************************************
1763  * IDirectDraw7::WaitForVerticalBlank
1764  *
1765  * This method allows applications to get in sync with the vertical blank
1766  * interval.
1767  * The wormhole demo in the DirectX 7 sdk uses this call, and it doesn't
1768  * redraw the screen, most likely because of this stub
1769  *
1770  * Parameters:
1771  *  Flags: one of DDWAITVB_BLOCKBEGIN, DDWAITVB_BLOCKBEGINEVENT
1772  *         or DDWAITVB_BLOCKEND
1773  *  h: Not used, according to MSDN
1774  *
1775  * Returns:
1776  *  Always returns DD_OK
1777  *
1778  *****************************************************************************/
1779 static HRESULT WINAPI ddraw7_WaitForVerticalBlank(IDirectDraw7 *iface, DWORD Flags, HANDLE event)
1780 {
1781     static BOOL hide;
1782
1783     TRACE("iface %p, flags %#x, event %p.\n", iface, Flags, event);
1784
1785     /* This function is called often, so print the fixme only once */
1786     if(!hide)
1787     {
1788         FIXME("iface %p, flags %#x, event %p stub!\n", iface, Flags, event);
1789         hide = TRUE;
1790     }
1791
1792     /* MSDN says DDWAITVB_BLOCKBEGINEVENT is not supported */
1793     if(Flags & DDWAITVB_BLOCKBEGINEVENT)
1794         return DDERR_UNSUPPORTED; /* unchecked */
1795
1796     return DD_OK;
1797 }
1798
1799 static HRESULT WINAPI ddraw4_WaitForVerticalBlank(IDirectDraw4 *iface, DWORD flags, HANDLE event)
1800 {
1801     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1802
1803     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1804
1805     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)This, flags, event);
1806 }
1807
1808 static HRESULT WINAPI ddraw3_WaitForVerticalBlank(IDirectDraw3 *iface, DWORD flags, HANDLE event)
1809 {
1810     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1811
1812     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1813
1814     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)This, flags, event);
1815 }
1816
1817 static HRESULT WINAPI ddraw2_WaitForVerticalBlank(IDirectDraw2 *iface, DWORD flags, HANDLE event)
1818 {
1819     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1820
1821     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1822
1823     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)This, flags, event);
1824 }
1825
1826 static HRESULT WINAPI ddraw1_WaitForVerticalBlank(IDirectDraw *iface, DWORD flags, HANDLE event)
1827 {
1828     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1829
1830     TRACE("iface %p, flags %#x, event %p.\n", iface, flags, event);
1831
1832     return ddraw7_WaitForVerticalBlank((IDirectDraw7 *)This, flags, event);
1833 }
1834
1835 /*****************************************************************************
1836  * IDirectDraw7::GetScanLine
1837  *
1838  * Returns the scan line that is being drawn on the monitor
1839  *
1840  * Parameters:
1841  *  Scanline: Address to write the scan line value to
1842  *
1843  * Returns:
1844  *  Always returns DD_OK
1845  *
1846  *****************************************************************************/
1847 static HRESULT WINAPI ddraw7_GetScanLine(IDirectDraw7 *iface, DWORD *Scanline)
1848 {
1849     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1850     static BOOL hide = FALSE;
1851     WINED3DDISPLAYMODE Mode;
1852
1853     TRACE("iface %p, line %p.\n", iface, Scanline);
1854
1855     /* This function is called often, so print the fixme only once */
1856     EnterCriticalSection(&ddraw_cs);
1857     if(!hide)
1858     {
1859         FIXME("iface %p, line %p partial stub!\n", iface, Scanline);
1860         hide = TRUE;
1861     }
1862
1863     IWineD3DDevice_GetDisplayMode(This->wineD3DDevice,
1864                                   0,
1865                                   &Mode);
1866
1867     /* Fake the line sweeping of the monitor */
1868     /* FIXME: We should synchronize with a source to keep the refresh rate */
1869     *Scanline = This->cur_scanline++;
1870     /* Assume 20 scan lines in the vertical blank */
1871     if (This->cur_scanline >= Mode.Height + 20)
1872         This->cur_scanline = 0;
1873
1874     LeaveCriticalSection(&ddraw_cs);
1875     return DD_OK;
1876 }
1877
1878 static HRESULT WINAPI ddraw4_GetScanLine(IDirectDraw4 *iface, DWORD *line)
1879 {
1880     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1881
1882     TRACE("iface %p, line %p.\n", iface, line);
1883
1884     return ddraw7_GetScanLine((IDirectDraw7 *)This, line);
1885 }
1886
1887 static HRESULT WINAPI ddraw3_GetScanLine(IDirectDraw3 *iface, DWORD *line)
1888 {
1889     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
1890
1891     TRACE("iface %p, line %p.\n", iface, line);
1892
1893     return ddraw7_GetScanLine((IDirectDraw7 *)This, line);
1894 }
1895
1896 static HRESULT WINAPI ddraw2_GetScanLine(IDirectDraw2 *iface, DWORD *line)
1897 {
1898     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
1899
1900     TRACE("iface %p, line %p.\n", iface, line);
1901
1902     return ddraw7_GetScanLine((IDirectDraw7 *)This, line);
1903 }
1904
1905 static HRESULT WINAPI ddraw1_GetScanLine(IDirectDraw *iface, DWORD *line)
1906 {
1907     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
1908
1909     TRACE("iface %p, line %p.\n", iface, line);
1910
1911     return ddraw7_GetScanLine((IDirectDraw7 *)This, line);
1912 }
1913
1914 /*****************************************************************************
1915  * IDirectDraw7::TestCooperativeLevel
1916  *
1917  * Informs the application about the state of the video adapter, depending
1918  * on the cooperative level
1919  *
1920  * Returns:
1921  *  DD_OK if the device is in a sane state
1922  *  DDERR_NOEXCLUSIVEMODE or DDERR_EXCLUSIVEMODEALREADYSET
1923  *  if the state is not correct(See below)
1924  *
1925  *****************************************************************************/
1926 static HRESULT WINAPI ddraw7_TestCooperativeLevel(IDirectDraw7 *iface)
1927 {
1928     TRACE("iface %p.\n", iface);
1929
1930     return DD_OK;
1931 }
1932
1933 static HRESULT WINAPI ddraw4_TestCooperativeLevel(IDirectDraw4 *iface)
1934 {
1935     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
1936
1937     TRACE("iface %p.\n", iface);
1938
1939     return ddraw7_TestCooperativeLevel((IDirectDraw7 *)This);
1940 }
1941
1942 /*****************************************************************************
1943  * IDirectDraw7::GetGDISurface
1944  *
1945  * Returns the surface that GDI is treating as the primary surface.
1946  * For Wine this is the front buffer
1947  *
1948  * Params:
1949  *  GDISurface: Address to write the surface pointer to
1950  *
1951  * Returns:
1952  *  DD_OK if the surface was found
1953  *  DDERR_NOTFOUND if the GDI surface wasn't found
1954  *
1955  *****************************************************************************/
1956 static HRESULT WINAPI ddraw7_GetGDISurface(IDirectDraw7 *iface, IDirectDrawSurface7 **GDISurface)
1957 {
1958     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1959     IWineD3DSurface *Surf;
1960     IDirectDrawSurface7 *ddsurf;
1961     HRESULT hr;
1962     DDSCAPS2 ddsCaps;
1963
1964     TRACE("iface %p, surface %p.\n", iface, GDISurface);
1965
1966     /* Get the back buffer from the wineD3DDevice and search its
1967      * attached surfaces for the front buffer
1968      */
1969     EnterCriticalSection(&ddraw_cs);
1970     hr = IWineD3DDevice_GetBackBuffer(This->wineD3DDevice,
1971                                       0, /* SwapChain */
1972                                       0, /* first back buffer*/
1973                                       WINED3DBACKBUFFER_TYPE_MONO,
1974                                       &Surf);
1975
1976     if( (hr != D3D_OK) ||
1977         (!Surf) )
1978     {
1979         ERR("IWineD3DDevice::GetBackBuffer failed\n");
1980         LeaveCriticalSection(&ddraw_cs);
1981         return DDERR_NOTFOUND;
1982     }
1983
1984     ddsurf = IWineD3DSurface_GetParent(Surf);
1985     IWineD3DSurface_Release(Surf);
1986
1987     /* Find the front buffer */
1988     ddsCaps.dwCaps = DDSCAPS_FRONTBUFFER;
1989     hr = IDirectDrawSurface7_GetAttachedSurface(ddsurf,
1990                                                 &ddsCaps,
1991                                                 GDISurface);
1992     if(hr != DD_OK)
1993     {
1994         ERR("IDirectDrawSurface7::GetAttachedSurface failed, hr = %x\n", hr);
1995     }
1996
1997     /* The AddRef is OK this time */
1998     LeaveCriticalSection(&ddraw_cs);
1999     return hr;
2000 }
2001
2002 static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurface4 **surface)
2003 {
2004     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
2005
2006     TRACE("iface %p, surface %p.\n", iface, surface);
2007
2008     return ddraw7_GetGDISurface((IDirectDraw7 *)This, (IDirectDrawSurface7 **)surface);
2009 }
2010
2011 static HRESULT WINAPI ddraw3_GetGDISurface(IDirectDraw3 *iface, IDirectDrawSurface **surface)
2012 {
2013     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
2014     IDirectDrawSurface7 *surface7;
2015     HRESULT hr;
2016
2017     TRACE("iface %p, surface %p.\n", iface, surface);
2018
2019     hr = ddraw7_GetGDISurface((IDirectDraw7 *)This, &surface7);
2020     *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
2021
2022     return hr;
2023 }
2024
2025 static HRESULT WINAPI ddraw2_GetGDISurface(IDirectDraw2 *iface, IDirectDrawSurface **surface)
2026 {
2027     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
2028     IDirectDrawSurface7 *surface7;
2029     HRESULT hr;
2030
2031     TRACE("iface %p, surface %p.\n", iface, surface);
2032
2033     hr = ddraw7_GetGDISurface((IDirectDraw7 *)This, &surface7);
2034     *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
2035
2036     return hr;
2037 }
2038
2039 static HRESULT WINAPI ddraw1_GetGDISurface(IDirectDraw *iface, IDirectDrawSurface **surface)
2040 {
2041     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
2042     IDirectDrawSurface7 *surface7;
2043     HRESULT hr;
2044
2045     TRACE("iface %p, surface %p.\n", iface, surface);
2046
2047     hr = ddraw7_GetGDISurface((IDirectDraw7 *)This, &surface7);
2048     *surface = surface7 ? (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
2049
2050     return hr;
2051 }
2052
2053 struct displaymodescallback_context
2054 {
2055     LPDDENUMMODESCALLBACK func;
2056     void *context;
2057 };
2058
2059 static HRESULT CALLBACK EnumDisplayModesCallbackThunk(DDSURFACEDESC2 *surface_desc, void *context)
2060 {
2061     struct displaymodescallback_context *cbcontext = context;
2062     DDSURFACEDESC desc;
2063
2064     memcpy(&desc, surface_desc, sizeof(desc));
2065     desc.dwSize = sizeof(desc);
2066
2067     return cbcontext->func(&desc, cbcontext->context);
2068 }
2069
2070 /*****************************************************************************
2071  * IDirectDraw7::EnumDisplayModes
2072  *
2073  * Enumerates the supported Display modes. The modes can be filtered with
2074  * the DDSD parameter.
2075  *
2076  * Params:
2077  *  Flags: can be DDEDM_REFRESHRATES and DDEDM_STANDARDVGAMODES
2078  *  DDSD: Surface description to filter the modes
2079  *  Context: Pointer passed back to the callback function
2080  *  cb: Application-provided callback function
2081  *
2082  * Returns:
2083  *  DD_OK on success
2084  *  DDERR_INVALIDPARAMS if the callback wasn't set
2085  *
2086  *****************************************************************************/
2087 static HRESULT WINAPI ddraw7_EnumDisplayModes(IDirectDraw7 *iface, DWORD Flags,
2088         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMMODESCALLBACK2 cb)
2089 {
2090     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2091     unsigned int modenum, fmt;
2092     enum wined3d_format_id pixelformat = WINED3DFMT_UNKNOWN;
2093     WINED3DDISPLAYMODE mode;
2094     DDSURFACEDESC2 callback_sd;
2095     WINED3DDISPLAYMODE *enum_modes = NULL;
2096     unsigned enum_mode_count = 0, enum_mode_array_size = 0;
2097
2098     static const enum wined3d_format_id checkFormatList[] =
2099     {
2100         WINED3DFMT_B8G8R8X8_UNORM,
2101         WINED3DFMT_B5G6R5_UNORM,
2102         WINED3DFMT_P8_UINT,
2103     };
2104
2105     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2106             iface, Flags, DDSD, Context, cb);
2107
2108     EnterCriticalSection(&ddraw_cs);
2109     /* This looks sane */
2110     if(!cb)
2111     {
2112         LeaveCriticalSection(&ddraw_cs);
2113         return DDERR_INVALIDPARAMS;
2114     }
2115
2116     if(DDSD)
2117     {
2118         if ((DDSD->dwFlags & DDSD_PIXELFORMAT) && (DDSD->u4.ddpfPixelFormat.dwFlags & DDPF_RGB) )
2119             pixelformat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
2120     }
2121
2122     if(!(Flags & DDEDM_REFRESHRATES))
2123     {
2124         enum_mode_array_size = 16;
2125         enum_modes = HeapAlloc(GetProcessHeap(), 0, sizeof(WINED3DDISPLAYMODE) * enum_mode_array_size);
2126         if (!enum_modes)
2127         {
2128             ERR("Out of memory\n");
2129             LeaveCriticalSection(&ddraw_cs);
2130             return DDERR_OUTOFMEMORY;
2131         }
2132     }
2133
2134     for(fmt = 0; fmt < (sizeof(checkFormatList) / sizeof(checkFormatList[0])); fmt++)
2135     {
2136         if(pixelformat != WINED3DFMT_UNKNOWN && checkFormatList[fmt] != pixelformat)
2137         {
2138             continue;
2139         }
2140
2141         modenum = 0;
2142         while(IWineD3D_EnumAdapterModes(This->wineD3D,
2143                                         WINED3DADAPTER_DEFAULT,
2144                                         checkFormatList[fmt],
2145                                         modenum++,
2146                                         &mode) == WINED3D_OK)
2147         {
2148             if(DDSD)
2149             {
2150                 if(DDSD->dwFlags & DDSD_WIDTH && mode.Width != DDSD->dwWidth) continue;
2151                 if(DDSD->dwFlags & DDSD_HEIGHT && mode.Height != DDSD->dwHeight) continue;
2152             }
2153
2154             if(!(Flags & DDEDM_REFRESHRATES))
2155             {
2156                 /* DX docs state EnumDisplayMode should return only unique modes. If DDEDM_REFRESHRATES is not set, refresh
2157                  * rate doesn't matter when determining if the mode is unique. So modes only differing in refresh rate have
2158                  * to be reduced to a single unique result in such case.
2159                  */
2160                 BOOL found = FALSE;
2161                 unsigned i;
2162
2163                 for (i = 0; i < enum_mode_count; i++)
2164                 {
2165                     if(enum_modes[i].Width == mode.Width && enum_modes[i].Height == mode.Height &&
2166                        enum_modes[i].Format == mode.Format)
2167                     {
2168                         found = TRUE;
2169                         break;
2170                     }
2171                 }
2172
2173                 if(found) continue;
2174             }
2175
2176             memset(&callback_sd, 0, sizeof(callback_sd));
2177             callback_sd.dwSize = sizeof(callback_sd);
2178             callback_sd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
2179
2180             callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH;
2181             if(Flags & DDEDM_REFRESHRATES)
2182             {
2183                 callback_sd.dwFlags |= DDSD_REFRESHRATE;
2184                 callback_sd.u2.dwRefreshRate = mode.RefreshRate;
2185             }
2186
2187             callback_sd.dwWidth = mode.Width;
2188             callback_sd.dwHeight = mode.Height;
2189
2190             PixelFormat_WineD3DtoDD(&callback_sd.u4.ddpfPixelFormat, mode.Format);
2191
2192             /* Calc pitch and DWORD align like MSDN says */
2193             callback_sd.u1.lPitch = (callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount / 8) * mode.Width;
2194             callback_sd.u1.lPitch = (callback_sd.u1.lPitch + 3) & ~3;
2195
2196             TRACE("Enumerating %dx%dx%d @%d\n", callback_sd.dwWidth, callback_sd.dwHeight, callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
2197               callback_sd.u2.dwRefreshRate);
2198
2199             if(cb(&callback_sd, Context) == DDENUMRET_CANCEL)
2200             {
2201                 TRACE("Application asked to terminate the enumeration\n");
2202                 HeapFree(GetProcessHeap(), 0, enum_modes);
2203                 LeaveCriticalSection(&ddraw_cs);
2204                 return DD_OK;
2205             }
2206
2207             if(!(Flags & DDEDM_REFRESHRATES))
2208             {
2209                 if (enum_mode_count == enum_mode_array_size)
2210                 {
2211                     WINED3DDISPLAYMODE *new_enum_modes;
2212
2213                     enum_mode_array_size *= 2;
2214                     new_enum_modes = HeapReAlloc(GetProcessHeap(), 0, enum_modes, sizeof(WINED3DDISPLAYMODE) * enum_mode_array_size);
2215
2216                     if (!new_enum_modes)
2217                     {
2218                         ERR("Out of memory\n");
2219                         HeapFree(GetProcessHeap(), 0, enum_modes);
2220                         LeaveCriticalSection(&ddraw_cs);
2221                         return DDERR_OUTOFMEMORY;
2222                     }
2223
2224                     enum_modes = new_enum_modes;
2225                 }
2226
2227                 enum_modes[enum_mode_count++] = mode;
2228             }
2229         }
2230     }
2231
2232     TRACE("End of enumeration\n");
2233     HeapFree(GetProcessHeap(), 0, enum_modes);
2234     LeaveCriticalSection(&ddraw_cs);
2235     return DD_OK;
2236 }
2237
2238 static HRESULT WINAPI ddraw4_EnumDisplayModes(IDirectDraw4 *iface, DWORD flags,
2239         DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMMODESCALLBACK2 callback)
2240 {
2241     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
2242
2243     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2244             iface, flags, surface_desc, context, callback);
2245
2246     return ddraw7_EnumDisplayModes((IDirectDraw7 *)This, flags, surface_desc, context, callback);
2247 }
2248
2249 static HRESULT WINAPI ddraw3_EnumDisplayModes(IDirectDraw3 *iface, DWORD flags,
2250         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2251 {
2252     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
2253     struct displaymodescallback_context cbcontext;
2254
2255     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2256             iface, flags, surface_desc, context, callback);
2257
2258     cbcontext.func = callback;
2259     cbcontext.context = context;
2260
2261     return ddraw7_EnumDisplayModes((IDirectDraw7 *)This, flags,
2262             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumDisplayModesCallbackThunk);
2263 }
2264
2265 static HRESULT WINAPI ddraw2_EnumDisplayModes(IDirectDraw2 *iface, DWORD flags,
2266         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2267 {
2268     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
2269     struct displaymodescallback_context cbcontext;
2270
2271     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2272             iface, flags, surface_desc, context, callback);
2273
2274     cbcontext.func = callback;
2275     cbcontext.context = context;
2276
2277     return ddraw7_EnumDisplayModes((IDirectDraw7 *)This, flags,
2278             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumDisplayModesCallbackThunk);
2279 }
2280
2281 static HRESULT WINAPI ddraw1_EnumDisplayModes(IDirectDraw *iface, DWORD flags,
2282         DDSURFACEDESC *surface_desc, void *context, LPDDENUMMODESCALLBACK callback)
2283 {
2284     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
2285     struct displaymodescallback_context cbcontext;
2286
2287     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
2288             iface, flags, surface_desc, context, callback);
2289
2290     cbcontext.func = callback;
2291     cbcontext.context = context;
2292
2293     return ddraw7_EnumDisplayModes((IDirectDraw7 *)This, flags, (DDSURFACEDESC2 *)surface_desc,
2294             &cbcontext, EnumDisplayModesCallbackThunk);
2295 }
2296
2297 /*****************************************************************************
2298  * IDirectDraw7::EvaluateMode
2299  *
2300  * Used with IDirectDraw7::StartModeTest to test video modes.
2301  * EvaluateMode is used to pass or fail a mode, and continue with the next
2302  * mode
2303  *
2304  * Params:
2305  *  Flags: DDEM_MODEPASSED or DDEM_MODEFAILED
2306  *  Timeout: Returns the amount of seconds left before the mode would have
2307  *           been failed automatically
2308  *
2309  * Returns:
2310  *  This implementation always DD_OK, because it's a stub
2311  *
2312  *****************************************************************************/
2313 static HRESULT WINAPI ddraw7_EvaluateMode(IDirectDraw7 *iface, DWORD Flags, DWORD *Timeout)
2314 {
2315     FIXME("iface %p, flags %#x, timeout %p stub!\n", iface, Flags, Timeout);
2316
2317     /* When implementing this, implement it in WineD3D */
2318
2319     return DD_OK;
2320 }
2321
2322 /*****************************************************************************
2323  * IDirectDraw7::GetDeviceIdentifier
2324  *
2325  * Returns the device identifier, which gives information about the driver
2326  * Our device identifier is defined at the beginning of this file.
2327  *
2328  * Params:
2329  *  DDDI: Address for the returned structure
2330  *  Flags: Can be DDGDI_GETHOSTIDENTIFIER
2331  *
2332  * Returns:
2333  *  On success it returns DD_OK
2334  *  DDERR_INVALIDPARAMS if DDDI is NULL
2335  *
2336  *****************************************************************************/
2337 static HRESULT WINAPI ddraw7_GetDeviceIdentifier(IDirectDraw7 *iface,
2338         DDDEVICEIDENTIFIER2 *DDDI, DWORD Flags)
2339 {
2340     TRACE("iface %p, device_identifier %p, flags %#x.\n", iface, DDDI, Flags);
2341
2342     if(!DDDI)
2343         return DDERR_INVALIDPARAMS;
2344
2345     /* The DDGDI_GETHOSTIDENTIFIER returns the information about the 2D
2346      * host adapter, if there's a secondary 3D adapter. This doesn't apply
2347      * to any modern hardware, nor is it interesting for Wine, so ignore it.
2348      * Size of DDDEVICEIDENTIFIER2 may be aligned to 8 bytes and thus 4
2349      * bytes too long. So only copy the relevant part of the structure
2350      */
2351
2352     memcpy(DDDI, &deviceidentifier, FIELD_OFFSET(DDDEVICEIDENTIFIER2, dwWHQLLevel) + sizeof(DWORD));
2353     return DD_OK;
2354 }
2355
2356 static HRESULT WINAPI ddraw4_GetDeviceIdentifier(IDirectDraw4 *iface,
2357         DDDEVICEIDENTIFIER *identifier, DWORD flags)
2358 {
2359     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
2360     DDDEVICEIDENTIFIER2 identifier2;
2361     HRESULT hr;
2362
2363     TRACE("iface %p, identifier %p, flags %#x.\n", iface, identifier, flags);
2364
2365     hr = ddraw7_GetDeviceIdentifier((IDirectDraw7 *)This, &identifier2, flags);
2366     DDRAW_Convert_DDDEVICEIDENTIFIER_2_To_1(&identifier2, identifier);
2367
2368     return hr;
2369 }
2370
2371 /*****************************************************************************
2372  * IDirectDraw7::GetSurfaceFromDC
2373  *
2374  * Returns the Surface for a GDI device context handle.
2375  * Is this related to IDirectDrawSurface::GetDC ???
2376  *
2377  * Params:
2378  *  hdc: hdc to return the surface for
2379  *  Surface: Address to write the surface pointer to
2380  *
2381  * Returns:
2382  *  Always returns DD_OK because it's a stub
2383  *
2384  *****************************************************************************/
2385 static HRESULT WINAPI ddraw7_GetSurfaceFromDC(IDirectDraw7 *iface, HDC hdc, IDirectDrawSurface7 **Surface)
2386 {
2387     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
2388     IWineD3DSurface *wined3d_surface;
2389     HRESULT hr;
2390
2391     TRACE("iface %p, dc %p, surface %p.\n", iface, hdc, Surface);
2392
2393     if (!Surface) return E_INVALIDARG;
2394
2395     hr = IWineD3DDevice_GetSurfaceFromDC(This->wineD3DDevice, hdc, &wined3d_surface);
2396     if (FAILED(hr))
2397     {
2398         TRACE("No surface found for dc %p.\n", hdc);
2399         *Surface = NULL;
2400         return DDERR_NOTFOUND;
2401     }
2402
2403     *Surface = IWineD3DSurface_GetParent(wined3d_surface);
2404     IDirectDrawSurface7_AddRef(*Surface);
2405     TRACE("Returning surface %p.\n", Surface);
2406     return DD_OK;
2407 }
2408
2409 static HRESULT WINAPI ddraw4_GetSurfaceFromDC(IDirectDraw4 *iface, HDC dc,
2410         IDirectDrawSurface4 **surface)
2411 {
2412     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
2413     IDirectDrawSurface7 *surface7;
2414     HRESULT hr;
2415
2416     TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2417
2418     if (!surface) return E_INVALIDARG;
2419
2420     hr = ddraw7_GetSurfaceFromDC((IDirectDraw7 *)This, dc, &surface7);
2421     *surface = surface7 ? (IDirectDrawSurface4 *)&((IDirectDrawSurfaceImpl *)surface7)->IDirectDrawSurface3_vtbl : NULL;
2422
2423     return hr;
2424 }
2425
2426 static HRESULT WINAPI ddraw3_GetSurfaceFromDC(IDirectDraw3 *iface, HDC dc,
2427         IDirectDrawSurface **surface)
2428 {
2429     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
2430
2431     TRACE("iface %p, dc %p, surface %p.\n", iface, dc, surface);
2432
2433     return ddraw7_GetSurfaceFromDC((IDirectDraw7 *)This, dc, (IDirectDrawSurface7 **)surface);
2434 }
2435
2436 /*****************************************************************************
2437  * IDirectDraw7::RestoreAllSurfaces
2438  *
2439  * Calls the restore method of all surfaces
2440  *
2441  * Params:
2442  *
2443  * Returns:
2444  *  Always returns DD_OK because it's a stub
2445  *
2446  *****************************************************************************/
2447 static HRESULT WINAPI ddraw7_RestoreAllSurfaces(IDirectDraw7 *iface)
2448 {
2449     FIXME("iface %p stub!\n", iface);
2450
2451     /* This isn't hard to implement: Enumerate all WineD3D surfaces,
2452      * get their parent and call their restore method. Do not implement
2453      * it in WineD3D, as restoring a surface means re-creating the
2454      * WineD3DDSurface
2455      */
2456     return DD_OK;
2457 }
2458
2459 static HRESULT WINAPI ddraw4_RestoreAllSurfaces(IDirectDraw4 *iface)
2460 {
2461     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
2462
2463     TRACE("iface %p.\n", iface);
2464
2465     return ddraw7_RestoreAllSurfaces((IDirectDraw7 *)This);
2466 }
2467
2468 /*****************************************************************************
2469  * IDirectDraw7::StartModeTest
2470  *
2471  * Tests the specified video modes to update the system registry with
2472  * refresh rate information. StartModeTest starts the mode test,
2473  * EvaluateMode is used to fail or pass a mode. If EvaluateMode
2474  * isn't called within 15 seconds, the mode is failed automatically
2475  *
2476  * As refresh rates are handled by the X server, I don't think this
2477  * Method is important
2478  *
2479  * Params:
2480  *  Modes: An array of mode specifications
2481  *  NumModes: The number of modes in Modes
2482  *  Flags: Some flags...
2483  *
2484  * Returns:
2485  *  Returns DDERR_TESTFINISHED if flags contains DDSMT_ISTESTREQUIRED,
2486  *  if no modes are passed, DDERR_INVALIDPARAMS is returned,
2487  *  otherwise DD_OK
2488  *
2489  *****************************************************************************/
2490 static HRESULT WINAPI ddraw7_StartModeTest(IDirectDraw7 *iface, SIZE *Modes, DWORD NumModes, DWORD Flags)
2491 {
2492     FIXME("iface %p, modes %p, mode_count %u, flags %#x partial stub!\n",
2493             iface, Modes, NumModes, Flags);
2494
2495     /* This looks sane */
2496     if( (!Modes) || (NumModes == 0) ) return DDERR_INVALIDPARAMS;
2497
2498     /* DDSMT_ISTESTREQUIRED asks if a mode test is necessary.
2499      * As it is not, DDERR_TESTFINISHED is returned
2500      * (hopefully that's correct
2501      *
2502     if(Flags & DDSMT_ISTESTREQUIRED) return DDERR_TESTFINISHED;
2503      * well, that value doesn't (yet) exist in the wine headers, so ignore it
2504      */
2505
2506     return DD_OK;
2507 }
2508
2509 /*****************************************************************************
2510  * ddraw_recreate_surfaces_cb
2511  *
2512  * Enumeration callback for ddraw_recreate_surface.
2513  * It re-recreates the WineD3DSurface. It's pretty straightforward
2514  *
2515  *****************************************************************************/
2516 HRESULT WINAPI ddraw_recreate_surfaces_cb(IDirectDrawSurface7 *surf, DDSURFACEDESC2 *desc, void *Context)
2517 {
2518     IDirectDrawSurfaceImpl *surfImpl = (IDirectDrawSurfaceImpl *)surf;
2519     IDirectDrawImpl *This = surfImpl->ddraw;
2520     IWineD3DSurface *wineD3DSurface;
2521     IWineD3DSwapChain *swapchain;
2522     void *parent;
2523     HRESULT hr;
2524     IWineD3DClipper *clipper = NULL;
2525
2526     WINED3DSURFACE_DESC     Desc;
2527     enum wined3d_format_id Format;
2528     DWORD                   Usage;
2529     WINED3DPOOL             Pool;
2530
2531     WINED3DMULTISAMPLE_TYPE MultiSampleType;
2532     DWORD                   MultiSampleQuality;
2533     UINT                    Width;
2534     UINT                    Height;
2535
2536     TRACE("surface %p, surface_desc %p, context %p.\n",
2537             surf, desc, Context);
2538
2539     /* For the enumeration */
2540     IDirectDrawSurface7_Release(surf);
2541
2542     if(surfImpl->ImplType == This->ImplType) return DDENUMRET_OK; /* Continue */
2543
2544     /* Get the objects */
2545     swapchain = surfImpl->wineD3DSwapChain;
2546     surfImpl->wineD3DSwapChain = NULL;
2547     wineD3DSurface = surfImpl->WineD3DSurface;
2548
2549     /* get the clipper */
2550     IWineD3DSurface_GetClipper(wineD3DSurface, &clipper);
2551
2552     /* Get the surface properties */
2553     IWineD3DSurface_GetDesc(wineD3DSurface, &Desc);
2554
2555     Format = Desc.format;
2556     Usage = Desc.usage;
2557     Pool = Desc.pool;
2558     MultiSampleType = Desc.multisample_type;
2559     MultiSampleQuality = Desc.multisample_quality;
2560     Width = Desc.width;
2561     Height = Desc.height;
2562
2563     parent = IWineD3DSurface_GetParent(wineD3DSurface);
2564     hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, Width, Height, Format, TRUE /* Lockable */,
2565             FALSE /* Discard */, surfImpl->mipmap_level, Usage, Pool, MultiSampleType, MultiSampleQuality,
2566             This->ImplType, parent, &ddraw_null_wined3d_parent_ops, &surfImpl->WineD3DSurface);
2567     if (FAILED(hr))
2568     {
2569         surfImpl->WineD3DSurface = wineD3DSurface;
2570         return hr;
2571     }
2572
2573     IWineD3DSurface_SetClipper(surfImpl->WineD3DSurface, clipper);
2574
2575     /* TODO: Copy the surface content, except for render targets */
2576
2577     /* If there's a swapchain, it owns the wined3d surfaces. So Destroy
2578      * the swapchain
2579      */
2580     if(swapchain) {
2581         /* The backbuffers have the swapchain set as well, but the primary
2582          * owns it and destroys it
2583          */
2584         if(surfImpl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) {
2585             IWineD3DDevice_UninitGDI(This->wineD3DDevice, D3D7CB_DestroySwapChain);
2586         }
2587         surfImpl->isRenderTarget = FALSE;
2588     } else {
2589         if(IWineD3DSurface_Release(wineD3DSurface) == 0)
2590             TRACE("Surface released successful, next surface\n");
2591         else
2592             ERR("Something's still holding the old WineD3DSurface\n");
2593     }
2594
2595     surfImpl->ImplType = This->ImplType;
2596
2597     if(clipper)
2598     {
2599         IWineD3DClipper_Release(clipper);
2600     }
2601     return DDENUMRET_OK;
2602 }
2603
2604 /*****************************************************************************
2605  * ddraw_recreate_surfaces
2606  *
2607  * A function, that converts all wineD3DSurfaces to the new implementation type
2608  * It enumerates all surfaces with IWineD3DDevice::EnumSurfaces, creates a
2609  * new WineD3DSurface, copies the content and releases the old surface
2610  *
2611  *****************************************************************************/
2612 static HRESULT ddraw_recreate_surfaces(IDirectDrawImpl *This)
2613 {
2614     DDSURFACEDESC2 desc;
2615     TRACE("(%p): Switch to implementation %d\n", This, This->ImplType);
2616
2617     if(This->ImplType != SURFACE_OPENGL && This->d3d_initialized)
2618     {
2619         /* Should happen almost never */
2620         FIXME("(%p) Switching to non-opengl surfaces with d3d started. Is this a bug?\n", This);
2621         /* Shutdown d3d */
2622         IWineD3DDevice_Uninit3D(This->wineD3DDevice, D3D7CB_DestroySwapChain);
2623     }
2624     /* Contrary: D3D starting is handled by the caller, because it knows the render target */
2625
2626     memset(&desc, 0, sizeof(desc));
2627     desc.dwSize = sizeof(desc);
2628
2629     return IDirectDraw7_EnumSurfaces((IDirectDraw7 *)This, 0, &desc, This, ddraw_recreate_surfaces_cb);
2630 }
2631
2632 ULONG WINAPI D3D7CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain)
2633 {
2634     IUnknown *swapChainParent;
2635
2636     TRACE("swapchain %p.\n", pSwapChain);
2637
2638     swapChainParent = IWineD3DSwapChain_GetParent(pSwapChain);
2639     return IUnknown_Release(swapChainParent);
2640 }
2641
2642 /*****************************************************************************
2643  * ddraw_create_surface
2644  *
2645  * A helper function for IDirectDraw7::CreateSurface. It creates a new surface
2646  * with the passed parameters.
2647  *
2648  * Params:
2649  *  DDSD: Description of the surface to create
2650  *  Surf: Address to store the interface pointer at
2651  *
2652  * Returns:
2653  *  DD_OK on success
2654  *
2655  *****************************************************************************/
2656 static HRESULT ddraw_create_surface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD,
2657         IDirectDrawSurfaceImpl **ppSurf, UINT level)
2658 {
2659     WINED3DSURFTYPE ImplType = This->ImplType;
2660     HRESULT hr;
2661
2662     TRACE("ddraw %p, surface_desc %p, surface %p, level %u.\n",
2663             This, pDDSD, ppSurf, level);
2664
2665     if (TRACE_ON(ddraw))
2666     {
2667         TRACE(" (%p) Requesting surface desc :\n", This);
2668         DDRAW_dump_surface_desc(pDDSD);
2669     }
2670
2671     /* Select the surface type, if it wasn't choosen yet */
2672     if(ImplType == SURFACE_UNKNOWN)
2673     {
2674         /* Use GL Surfaces if a D3DDEVICE Surface is requested */
2675         if(pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2676         {
2677             TRACE("(%p) Choosing GL surfaces because a 3DDEVICE Surface was requested\n", This);
2678             ImplType = SURFACE_OPENGL;
2679         }
2680
2681         /* Otherwise use GDI surfaces for now */
2682         else
2683         {
2684             TRACE("(%p) Choosing GDI surfaces for 2D rendering\n", This);
2685             ImplType = SURFACE_GDI;
2686         }
2687
2688         /* Policy if all surface implementations are available:
2689          * First, check if a default type was set with winecfg. If not,
2690          * try Xrender surfaces, and use them if they work. Next, check if
2691          * accelerated OpenGL is available, and use GL surfaces in this
2692          * case. If all else fails, use GDI surfaces. If a 3DDEVICE surface
2693          * was created, always use OpenGL surfaces.
2694          *
2695          * (Note: Xrender surfaces are not implemented for now, the
2696          * unaccelerated implementation uses GDI to render in Software)
2697          */
2698
2699         /* Store the type. If it needs to be changed, all WineD3DSurfaces have to
2700          * be re-created. This could be done with IDirectDrawSurface7::Restore
2701          */
2702         This->ImplType = ImplType;
2703     }
2704     else
2705     {
2706         if ((pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2707                 && (This->ImplType != SURFACE_OPENGL)
2708                 && DefaultSurfaceType == SURFACE_UNKNOWN)
2709         {
2710             /* We have to change to OpenGL,
2711              * and re-create all WineD3DSurfaces
2712              */
2713             ImplType = SURFACE_OPENGL;
2714             This->ImplType = ImplType;
2715             TRACE("(%p) Re-creating all surfaces\n", This);
2716             ddraw_recreate_surfaces(This);
2717             TRACE("(%p) Done recreating all surfaces\n", This);
2718         }
2719         else if(This->ImplType != SURFACE_OPENGL && pDDSD->ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
2720         {
2721             WARN("The application requests a 3D capable surface, but a non-opengl surface was set in the registry\n");
2722             /* Do not fail surface creation, only fail 3D device creation */
2723         }
2724     }
2725
2726     /* Create the Surface object */
2727     *ppSurf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl));
2728     if(!*ppSurf)
2729     {
2730         ERR("(%p) Error allocating memory for a surface\n", This);
2731         return DDERR_OUTOFVIDEOMEMORY;
2732     }
2733
2734     hr = ddraw_surface_init(*ppSurf, This, pDDSD, level, ImplType);
2735     if (FAILED(hr))
2736     {
2737         WARN("Failed to initialize surface, hr %#x.\n", hr);
2738         HeapFree(GetProcessHeap(), 0, *ppSurf);
2739         return hr;
2740     }
2741
2742     /* Increase the surface counter, and attach the surface */
2743     InterlockedIncrement(&This->surfaces);
2744     list_add_head(&This->surface_list, &(*ppSurf)->surface_list_entry);
2745
2746     TRACE("Created surface %p.\n", *ppSurf);
2747
2748     return DD_OK;
2749 }
2750 /*****************************************************************************
2751  * CreateAdditionalSurfaces
2752  *
2753  * Creates a new mipmap chain.
2754  *
2755  * Params:
2756  *  root: Root surface to attach the newly created chain to
2757  *  count: number of surfaces to create
2758  *  DDSD: Description of the surface. Intentionally not a pointer to avoid side
2759  *        effects on the caller
2760  *  CubeFaceRoot: Whether the new surface is a root of a cube map face. This
2761  *                creates an additional surface without the mipmapping flags
2762  *
2763  *****************************************************************************/
2764 static HRESULT
2765 CreateAdditionalSurfaces(IDirectDrawImpl *This,
2766                          IDirectDrawSurfaceImpl *root,
2767                          UINT count,
2768                          DDSURFACEDESC2 DDSD,
2769                          BOOL CubeFaceRoot)
2770 {
2771     UINT i, j, level = 0;
2772     HRESULT hr;
2773     IDirectDrawSurfaceImpl *last = root;
2774
2775     for(i = 0; i < count; i++)
2776     {
2777         IDirectDrawSurfaceImpl *object2 = NULL;
2778
2779         /* increase the mipmap level, but only if a mipmap is created
2780          * In this case, also halve the size
2781          */
2782         if(DDSD.ddsCaps.dwCaps & DDSCAPS_MIPMAP && !CubeFaceRoot)
2783         {
2784             level++;
2785             if(DDSD.dwWidth > 1) DDSD.dwWidth /= 2;
2786             if(DDSD.dwHeight > 1) DDSD.dwHeight /= 2;
2787             /* Set the mipmap sublevel flag according to msdn */
2788             DDSD.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
2789         }
2790         else
2791         {
2792             DDSD.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
2793         }
2794         CubeFaceRoot = FALSE;
2795
2796         hr = ddraw_create_surface(This, &DDSD, &object2, level);
2797         if(hr != DD_OK)
2798         {
2799             return hr;
2800         }
2801
2802         /* Add the new surface to the complex attachment array */
2803         for(j = 0; j < MAX_COMPLEX_ATTACHED; j++)
2804         {
2805             if(last->complex_array[j]) continue;
2806             last->complex_array[j] = object2;
2807             break;
2808         }
2809         last = object2;
2810
2811         /* Remove the (possible) back buffer cap from the new surface description,
2812          * because only one surface in the flipping chain is a back buffer, one
2813          * is a front buffer, the others are just primary surfaces.
2814          */
2815         DDSD.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
2816     }
2817     return DD_OK;
2818 }
2819
2820 /* Must set all attached surfaces (e.g. mipmaps) versions as well */
2821 static void ddraw_set_surface_version(IDirectDrawSurfaceImpl *surface, UINT version)
2822 {
2823     unsigned int i;
2824
2825     TRACE("surface %p, version %u -> %u.\n", surface, surface->version, version);
2826
2827     surface->version = version;
2828     for (i = 0; i < MAX_COMPLEX_ATTACHED; ++i)
2829     {
2830         if (!surface->complex_array[i]) break;
2831         ddraw_set_surface_version(surface->complex_array[i], version);
2832     }
2833     while ((surface = surface->next_attached))
2834     {
2835         ddraw_set_surface_version(surface, version);
2836     }
2837 }
2838
2839 /*****************************************************************************
2840  * ddraw_attach_d3d_device
2841  *
2842  * Initializes the D3D capabilities of WineD3D
2843  *
2844  * Params:
2845  *  primary: The primary surface for D3D
2846  *
2847  * Returns
2848  *  DD_OK on success,
2849  *  DDERR_* otherwise
2850  *
2851  *****************************************************************************/
2852 static HRESULT ddraw_attach_d3d_device(IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *primary)
2853 {
2854     WINED3DPRESENT_PARAMETERS localParameters;
2855     HWND window = ddraw->dest_window;
2856     HRESULT hr;
2857
2858     TRACE("ddraw %p, primary %p.\n", ddraw, primary);
2859
2860     if (!window || window == GetDesktopWindow())
2861     {
2862         window = CreateWindowExA(0, DDRAW_WINDOW_CLASS_NAME, "Hidden D3D Window",
2863                 WS_DISABLED, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
2864                 NULL, NULL, NULL, NULL);
2865         if (!window)
2866         {
2867             ERR("Failed to create window, last error %#x.\n", GetLastError());
2868             return E_FAIL;
2869         }
2870
2871         ShowWindow(window, SW_HIDE);   /* Just to be sure */
2872         WARN("No window for the Direct3DDevice, created hidden window %p.\n", window);
2873     }
2874     else
2875     {
2876         TRACE("Using existing window %p for Direct3D rendering.\n", window);
2877     }
2878     ddraw->d3d_window = window;
2879
2880     /* Store the future Render Target surface */
2881     ddraw->d3d_target = primary;
2882
2883     /* Use the surface description for the device parameters, not the device
2884      * settings. The application might render to an offscreen surface. */
2885     localParameters.BackBufferWidth = primary->surface_desc.dwWidth;
2886     localParameters.BackBufferHeight = primary->surface_desc.dwHeight;
2887     localParameters.BackBufferFormat = PixelFormat_DD2WineD3D(&primary->surface_desc.u4.ddpfPixelFormat);
2888     localParameters.BackBufferCount = (primary->surface_desc.dwFlags & DDSD_BACKBUFFERCOUNT)
2889             ? primary->surface_desc.dwBackBufferCount : 0;
2890     localParameters.MultiSampleType = WINED3DMULTISAMPLE_NONE;
2891     localParameters.MultiSampleQuality = 0;
2892     localParameters.SwapEffect = WINED3DSWAPEFFECT_COPY;
2893     localParameters.hDeviceWindow = window;
2894     localParameters.Windowed = !(ddraw->cooperative_level & DDSCL_FULLSCREEN);
2895     localParameters.EnableAutoDepthStencil = TRUE;
2896     localParameters.AutoDepthStencilFormat = WINED3DFMT_D16_UNORM;
2897     localParameters.Flags = 0;
2898     localParameters.FullScreen_RefreshRateInHz = WINED3DPRESENT_RATE_DEFAULT;
2899     localParameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT;
2900
2901     /* Set this NOW, otherwise creating the depth stencil surface will cause a
2902      * recursive loop until ram or emulated video memory is full. */
2903     ddraw->d3d_initialized = TRUE;
2904     hr = IWineD3DDevice_Init3D(ddraw->wineD3DDevice, &localParameters);
2905     if (FAILED(hr))
2906     {
2907         ddraw->d3d_target = NULL;
2908         ddraw->d3d_initialized = FALSE;
2909         return hr;
2910     }
2911
2912     ddraw->declArraySize = 2;
2913     ddraw->decls = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ddraw->decls) * ddraw->declArraySize);
2914     if (!ddraw->decls)
2915     {
2916         ERR("Error allocating an array for the converted vertex decls.\n");
2917         ddraw->declArraySize = 0;
2918         hr = IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain);
2919         return E_OUTOFMEMORY;
2920     }
2921
2922     TRACE("Successfully initialized 3D.\n");
2923
2924     return DD_OK;
2925 }
2926
2927 static HRESULT ddraw_create_gdi_swapchain(IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *primary)
2928 {
2929     WINED3DPRESENT_PARAMETERS presentation_parameters;
2930     HWND window;
2931     HRESULT hr;
2932
2933     window = ddraw->dest_window;
2934
2935     memset(&presentation_parameters, 0, sizeof(presentation_parameters));
2936
2937     /* Use the surface description for the device parameters, not the device
2938      * settings. The application might render to an offscreen surface. */
2939     presentation_parameters.BackBufferWidth = primary->surface_desc.dwWidth;
2940     presentation_parameters.BackBufferHeight = primary->surface_desc.dwHeight;
2941     presentation_parameters.BackBufferFormat = PixelFormat_DD2WineD3D(&primary->surface_desc.u4.ddpfPixelFormat);
2942     presentation_parameters.BackBufferCount = (primary->surface_desc.dwFlags & DDSD_BACKBUFFERCOUNT)
2943             ? primary->surface_desc.dwBackBufferCount : 0;
2944     presentation_parameters.MultiSampleType = WINED3DMULTISAMPLE_NONE;
2945     presentation_parameters.MultiSampleQuality = 0;
2946     presentation_parameters.SwapEffect = WINED3DSWAPEFFECT_FLIP;
2947     presentation_parameters.hDeviceWindow = window;
2948     presentation_parameters.Windowed = !(ddraw->cooperative_level & DDSCL_FULLSCREEN);
2949     presentation_parameters.EnableAutoDepthStencil = FALSE; /* Not on GDI swapchains */
2950     presentation_parameters.AutoDepthStencilFormat = 0;
2951     presentation_parameters.Flags = 0;
2952     presentation_parameters.FullScreen_RefreshRateInHz = WINED3DPRESENT_RATE_DEFAULT;
2953     presentation_parameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT;
2954
2955     ddraw->d3d_target = primary;
2956     hr = IWineD3DDevice_InitGDI(ddraw->wineD3DDevice, &presentation_parameters);
2957     ddraw->d3d_target = NULL;
2958     if (FAILED(hr))
2959     {
2960         WARN("Failed to initialize GDI ddraw implementation, hr %#x.\n", hr);
2961         primary->wineD3DSwapChain = NULL;
2962     }
2963
2964     return hr;
2965 }
2966
2967 /*****************************************************************************
2968  * IDirectDraw7::CreateSurface
2969  *
2970  * Creates a new IDirectDrawSurface object and returns its interface.
2971  *
2972  * The surface connections with wined3d are a bit tricky. Basically it works
2973  * like this:
2974  *
2975  * |------------------------|               |-----------------|
2976  * | DDraw surface          |               | WineD3DSurface  |
2977  * |                        |               |                 |
2978  * |        WineD3DSurface  |-------------->|                 |
2979  * |        Child           |<------------->| Parent          |
2980  * |------------------------|               |-----------------|
2981  *
2982  * The DDraw surface is the parent of the wined3d surface, and it releases
2983  * the WineD3DSurface when the ddraw surface is destroyed.
2984  *
2985  * However, for all surfaces which can be in a container in WineD3D,
2986  * we have to do this. These surfaces are usually complex surfaces,
2987  * so this concerns primary surfaces with a front and a back buffer,
2988  * and textures.
2989  *
2990  * |------------------------|               |-----------------|
2991  * | DDraw surface          |               | Container       |
2992  * |                        |               |                 |
2993  * |                  Child |<------------->| Parent          |
2994  * |                Texture |<------------->|                 |
2995  * |         WineD3DSurface |<----|         |          Levels |<--|
2996  * | Complex connection     |     |         |                 |   |
2997  * |------------------------|     |         |-----------------|   |
2998  *  ^                             |                               |
2999  *  |                             |                               |
3000  *  |                             |                               |
3001  *  |    |------------------|     |         |-----------------|   |
3002  *  |    | IParent          |     |-------->| WineD3DSurface  |   |
3003  *  |    |                  |               |                 |   |
3004  *  |    |            Child |<------------->| Parent          |   |
3005  *  |    |                  |               |       Container |<--|
3006  *  |    |------------------|               |-----------------|   |
3007  *  |                                                             |
3008  *  |   |----------------------|                                  |
3009  *  |   | DDraw surface 2      |                                  |
3010  *  |   |                      |                                  |
3011  *  |<->| Complex root   Child |                                  |
3012  *  |   |              Texture |                                  |
3013  *  |   |       WineD3DSurface |<----|                            |
3014  *  |   |----------------------|     |                            |
3015  *  |                                |                            |
3016  *  |    |---------------------|     |      |-----------------|   |
3017  *  |    | IParent             |     |----->| WineD3DSurface  |   |
3018  *  |    |                     |            |                 |   |
3019  *  |    |               Child |<---------->| Parent          |   |
3020  *  |    |---------------------|            |       Container |<--|
3021  *  |                                       |-----------------|   |
3022  *  |                                                             |
3023  *  |             ---More surfaces can follow---                  |
3024  *
3025  * The reason is that the IWineD3DSwapchain(render target container)
3026  * and the IWineD3DTexure(Texture container) release the parents
3027  * of their surface's children, but by releasing the complex root
3028  * the surfaces which are complexly attached to it are destroyed
3029  * too. See IDirectDrawSurface::Release for a more detailed
3030  * explanation.
3031  *
3032  * Params:
3033  *  DDSD: Description of the surface to create
3034  *  Surf: Address to store the interface pointer at
3035  *  UnkOuter: Basically for aggregation support, but ddraw doesn't support
3036  *            aggregation, so it has to be NULL
3037  *
3038  * Returns:
3039  *  DD_OK on success
3040  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3041  *  DDERR_* if an error occurs
3042  *
3043  *****************************************************************************/
3044 static HRESULT CreateSurface(IDirectDrawImpl *ddraw, DDSURFACEDESC2 *DDSD,
3045         IDirectDrawSurface7 **Surf, IUnknown *UnkOuter)
3046 {
3047     IDirectDrawSurfaceImpl *object = NULL;
3048     HRESULT hr;
3049     LONG extra_surfaces = 0;
3050     DDSURFACEDESC2 desc2;
3051     WINED3DDISPLAYMODE Mode;
3052     const DWORD sysvidmem = DDSCAPS_VIDEOMEMORY | DDSCAPS_SYSTEMMEMORY;
3053
3054     TRACE("ddraw %p, surface_desc %p, surface %p, outer_unknown %p.\n", ddraw, DDSD, Surf, UnkOuter);
3055
3056     /* Some checks before we start */
3057     if (TRACE_ON(ddraw))
3058     {
3059         TRACE(" (%p) Requesting surface desc :\n", ddraw);
3060         DDRAW_dump_surface_desc(DDSD);
3061     }
3062     EnterCriticalSection(&ddraw_cs);
3063
3064     if (UnkOuter != NULL)
3065     {
3066         FIXME("(%p) : outer != NULL?\n", ddraw);
3067         LeaveCriticalSection(&ddraw_cs);
3068         return CLASS_E_NOAGGREGATION; /* unchecked */
3069     }
3070
3071     if (Surf == NULL)
3072     {
3073         FIXME("(%p) You want to get back a surface? Don't give NULL ptrs!\n", ddraw);
3074         LeaveCriticalSection(&ddraw_cs);
3075         return E_POINTER; /* unchecked */
3076     }
3077
3078     if (!(DDSD->dwFlags & DDSD_CAPS))
3079     {
3080         /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */
3081         DDSD->dwFlags |= DDSD_CAPS;
3082     }
3083
3084     if (DDSD->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD)
3085     {
3086         /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */
3087         DDSD->dwFlags &= ~DDSD_LPSURFACE;
3088     }
3089
3090     if ((DDSD->dwFlags & DDSD_LPSURFACE) && (DDSD->lpSurface == NULL))
3091     {
3092         /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */
3093         WARN("(%p) Null surface pointer specified, ignore it!\n", ddraw);
3094         DDSD->dwFlags &= ~DDSD_LPSURFACE;
3095     }
3096
3097     if((DDSD->ddsCaps.dwCaps & (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE) &&
3098        !(ddraw->cooperative_level & DDSCL_EXCLUSIVE))
3099     {
3100         TRACE("(%p): Attempt to create a flipable primary surface without DDSCL_EXCLUSIVE set\n",
3101                 ddraw);
3102         *Surf = NULL;
3103         LeaveCriticalSection(&ddraw_cs);
3104         return DDERR_NOEXCLUSIVEMODE;
3105     }
3106
3107     if((DDSD->ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER | DDSCAPS_PRIMARYSURFACE)) == (DDSCAPS_BACKBUFFER | DDSCAPS_PRIMARYSURFACE))
3108     {
3109         WARN("Application wanted to create back buffer primary surface\n");
3110         LeaveCriticalSection(&ddraw_cs);
3111         return DDERR_INVALIDCAPS;
3112     }
3113
3114     if((DDSD->ddsCaps.dwCaps & sysvidmem) == sysvidmem)
3115     {
3116         /* This is a special switch in ddrawex.dll, but not allowed in ddraw.dll */
3117         WARN("Application tries to put the surface in both system and video memory\n");
3118         LeaveCriticalSection(&ddraw_cs);
3119         *Surf = NULL;
3120         return DDERR_INVALIDCAPS;
3121     }
3122
3123     /* Check cube maps but only if the size includes them */
3124     if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
3125     {
3126         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES &&
3127            !(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
3128         {
3129             WARN("Cube map faces requested without cube map flag\n");
3130             LeaveCriticalSection(&ddraw_cs);
3131             return DDERR_INVALIDCAPS;
3132         }
3133         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
3134            (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) == 0)
3135         {
3136             WARN("Cube map without faces requested\n");
3137             LeaveCriticalSection(&ddraw_cs);
3138             return DDERR_INVALIDPARAMS;
3139         }
3140
3141         /* Quick tests confirm those can be created, but we don't do that yet */
3142         if(DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP &&
3143            (DDSD->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) != DDSCAPS2_CUBEMAP_ALLFACES)
3144         {
3145             FIXME("Partial cube maps not supported yet\n");
3146         }
3147     }
3148
3149     /* According to the msdn this flag is ignored by CreateSurface */
3150     if (DDSD->dwSize >= sizeof(DDSURFACEDESC2))
3151         DDSD->ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
3152
3153     /* Modify some flags */
3154     memset(&desc2, 0, sizeof(desc2));
3155     desc2.dwSize = sizeof(desc2);   /* For the struct copy */
3156     DD_STRUCT_COPY_BYSIZE(&desc2, DDSD);
3157     desc2.dwSize = sizeof(desc2);   /* To override a possibly smaller size */
3158     desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT); /* Just to be sure */
3159
3160     /* Get the video mode from WineD3D - we will need it */
3161     hr = IWineD3DDevice_GetDisplayMode(ddraw->wineD3DDevice, 0, &Mode);
3162     if(FAILED(hr))
3163     {
3164         ERR("Failed to read display mode from wined3d\n");
3165         switch(ddraw->orig_bpp)
3166         {
3167             case 8:
3168                 Mode.Format = WINED3DFMT_P8_UINT;
3169                 break;
3170
3171             case 15:
3172                 Mode.Format = WINED3DFMT_B5G5R5X1_UNORM;
3173                 break;
3174
3175             case 16:
3176                 Mode.Format = WINED3DFMT_B5G6R5_UNORM;
3177                 break;
3178
3179             case 24:
3180                 Mode.Format = WINED3DFMT_B8G8R8_UNORM;
3181                 break;
3182
3183             case 32:
3184                 Mode.Format = WINED3DFMT_B8G8R8X8_UNORM;
3185                 break;
3186         }
3187         Mode.Width = ddraw->orig_width;
3188         Mode.Height = ddraw->orig_height;
3189     }
3190
3191     /* No pixelformat given? Use the current screen format */
3192     if(!(desc2.dwFlags & DDSD_PIXELFORMAT))
3193     {
3194         desc2.dwFlags |= DDSD_PIXELFORMAT;
3195         desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
3196
3197         /* Wait: It could be a Z buffer */
3198         if(desc2.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
3199         {
3200             switch(desc2.u2.dwMipMapCount) /* Who had this glorious idea? */
3201             {
3202                 case 15:
3203                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_S1_UINT_D15_UNORM);
3204                     break;
3205                 case 16:
3206                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_D16_UNORM);
3207                     break;
3208                 case 24:
3209                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_X8D24_UNORM);
3210                     break;
3211                 case 32:
3212                     PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_D32_UNORM);
3213                     break;
3214                 default:
3215                     ERR("Unknown Z buffer bit depth\n");
3216             }
3217         }
3218         else
3219         {
3220             PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, Mode.Format);
3221         }
3222     }
3223
3224     /* No Width or no Height? Use the original screen size
3225      */
3226     if(!(desc2.dwFlags & DDSD_WIDTH) ||
3227        !(desc2.dwFlags & DDSD_HEIGHT) )
3228     {
3229         /* Invalid for non-render targets */
3230         if(!(desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
3231         {
3232             WARN("Creating a non-Primary surface without Width or Height info, returning DDERR_INVALIDPARAMS\n");
3233             *Surf = NULL;
3234             LeaveCriticalSection(&ddraw_cs);
3235             return DDERR_INVALIDPARAMS;
3236         }
3237
3238         desc2.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
3239         desc2.dwWidth = Mode.Width;
3240         desc2.dwHeight = Mode.Height;
3241     }
3242
3243     if (!desc2.dwWidth || !desc2.dwHeight)
3244     {
3245         LeaveCriticalSection(&ddraw_cs);
3246         return DDERR_INVALIDPARAMS;
3247     }
3248
3249     /* Mipmap count fixes */
3250     if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3251     {
3252         if(desc2.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
3253         {
3254             if(desc2.dwFlags & DDSD_MIPMAPCOUNT)
3255             {
3256                 /* Mipmap count is given, should not be 0 */
3257                 if( desc2.u2.dwMipMapCount == 0 )
3258                 {
3259                     LeaveCriticalSection(&ddraw_cs);
3260                     return DDERR_INVALIDPARAMS;
3261                 }
3262             }
3263             else
3264             {
3265                 /* Undocumented feature: Create sublevels until
3266                  * either the width or the height is 1
3267                  */
3268                 DWORD min = desc2.dwWidth < desc2.dwHeight ?
3269                             desc2.dwWidth : desc2.dwHeight;
3270                 desc2.u2.dwMipMapCount = 0;
3271                 while( min )
3272                 {
3273                     desc2.u2.dwMipMapCount += 1;
3274                     min >>= 1;
3275                 }
3276             }
3277         }
3278         else
3279         {
3280             /* Not-complex mipmap -> Mipmapcount = 1 */
3281             desc2.u2.dwMipMapCount = 1;
3282         }
3283         extra_surfaces = desc2.u2.dwMipMapCount - 1;
3284
3285         /* There's a mipmap count in the created surface in any case */
3286         desc2.dwFlags |= DDSD_MIPMAPCOUNT;
3287     }
3288     /* If no mipmap is given, the texture has only one level */
3289
3290     /* The first surface is a front buffer, the back buffer is created afterwards */
3291     if( (desc2.dwFlags & DDSD_CAPS) && (desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) )
3292     {
3293         desc2.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
3294     }
3295
3296     /* The root surface in a cube map is positive x */
3297     if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3298     {
3299         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
3300         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEX;
3301     }
3302
3303     /* Create the first surface */
3304     hr = ddraw_create_surface(ddraw, &desc2, &object, 0);
3305     if (FAILED(hr))
3306     {
3307         WARN("ddraw_create_surface failed, hr %#x.\n", hr);
3308         LeaveCriticalSection(&ddraw_cs);
3309         return hr;
3310     }
3311     object->is_complex_root = TRUE;
3312
3313     *Surf = (IDirectDrawSurface7 *)object;
3314
3315     /* Create Additional surfaces if necessary
3316      * This applies to Primary surfaces which have a back buffer count
3317      * set, but not to mipmap textures. In case of Mipmap textures,
3318      * wineD3D takes care of the creation of additional surfaces
3319      */
3320     if(DDSD->dwFlags & DDSD_BACKBUFFERCOUNT)
3321     {
3322         extra_surfaces = DDSD->dwBackBufferCount;
3323         desc2.ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER; /* It's not a front buffer */
3324         desc2.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
3325         desc2.dwBackBufferCount = 0;
3326     }
3327
3328     hr = DD_OK;
3329     if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3330     {
3331         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
3332         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEZ;
3333         hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE);
3334         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEZ;
3335         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEZ;
3336         hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE);
3337         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEZ;
3338         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEY;
3339         hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE);
3340         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEY;
3341         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEY;
3342         hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE);
3343         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_POSITIVEY;
3344         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_NEGATIVEX;
3345         hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces + 1, desc2, TRUE);
3346         desc2.ddsCaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_NEGATIVEX;
3347         desc2.ddsCaps.dwCaps2 |=  DDSCAPS2_CUBEMAP_POSITIVEX;
3348     }
3349
3350     hr |= CreateAdditionalSurfaces(ddraw, object, extra_surfaces, desc2, FALSE);
3351     if(hr != DD_OK)
3352     {
3353         /* This destroys and possibly created surfaces too */
3354         IDirectDrawSurface_Release((IDirectDrawSurface7 *)object);
3355         LeaveCriticalSection(&ddraw_cs);
3356         return hr;
3357     }
3358
3359     /* If the implementation is OpenGL and there's no d3ddevice, attach a d3ddevice
3360      * But attach the d3ddevice only if the currently created surface was
3361      * a primary surface (2D app in 3D mode) or a 3DDEVICE surface (3D app)
3362      * The only case I can think of where this doesn't apply is when a
3363      * 2D app was configured by the user to run with OpenGL and it didn't create
3364      * the render target as first surface. In this case the render target creation
3365      * will cause the 3D init.
3366      */
3367     if( (ddraw->ImplType == SURFACE_OPENGL) && !(ddraw->d3d_initialized) &&
3368         desc2.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE) )
3369     {
3370         IDirectDrawSurfaceImpl *target = object, *surface;
3371         struct list *entry;
3372
3373         /* Search for the primary to use as render target */
3374         LIST_FOR_EACH(entry, &ddraw->surface_list)
3375         {
3376             surface = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
3377             if((surface->surface_desc.ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER)) ==
3378                (DDSCAPS_PRIMARYSURFACE | DDSCAPS_FRONTBUFFER))
3379             {
3380                 /* found */
3381                 target = surface;
3382                 TRACE("Using primary %p as render target\n", target);
3383                 break;
3384             }
3385         }
3386
3387         TRACE("(%p) Attaching a D3DDevice, rendertarget = %p\n", ddraw, target);
3388         hr = ddraw_attach_d3d_device(ddraw, target);
3389         if (hr != D3D_OK)
3390         {
3391             IDirectDrawSurfaceImpl *release_surf;
3392             ERR("ddraw_attach_d3d_device failed, hr %#x\n", hr);
3393             *Surf = NULL;
3394
3395             /* The before created surface structures are in an incomplete state here.
3396              * WineD3D holds the reference on the IParents, and it released them on the failure
3397              * already. So the regular release method implementation would fail on the attempt
3398              * to destroy either the IParents or the swapchain. So free the surface here.
3399              * The surface structure here is a list, not a tree, because onscreen targets
3400              * cannot be cube textures
3401              */
3402             while(object)
3403             {
3404                 release_surf = object;
3405                 object = object->complex_array[0];
3406                 ddraw_surface_destroy(release_surf);
3407             }
3408             LeaveCriticalSection(&ddraw_cs);
3409             return hr;
3410         }
3411     }
3412     else if(!(ddraw->d3d_initialized) && desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
3413     {
3414         ddraw_create_gdi_swapchain(ddraw, object);
3415     }
3416
3417     /* Addref the ddraw interface to keep an reference for each surface */
3418     IDirectDraw7_AddRef((IDirectDraw7 *)ddraw);
3419     object->ifaceToRelease = (IUnknown *)ddraw;
3420
3421     /* Create a WineD3DTexture if a texture was requested */
3422     if(desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE)
3423     {
3424         enum wined3d_format_id Format;
3425         UINT levels;
3426         WINED3DPOOL Pool = WINED3DPOOL_DEFAULT;
3427
3428         ddraw->tex_root = object;
3429
3430         if(desc2.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
3431         {
3432             /* a mipmap is created, create enough levels */
3433             levels = desc2.u2.dwMipMapCount;
3434         }
3435         else
3436         {
3437             /* No mipmap is created, create one level */
3438             levels = 1;
3439         }
3440
3441         /* DDSCAPS_SYSTEMMEMORY textures are in WINED3DPOOL_SYSTEMMEM */
3442         if(DDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
3443         {
3444             Pool = WINED3DPOOL_SYSTEMMEM;
3445         }
3446         /* Should I forward the MANAGED cap to the managed pool ? */
3447
3448         /* Get the format. It's set already by CreateNewSurface */
3449         Format = PixelFormat_DD2WineD3D(&object->surface_desc.u4.ddpfPixelFormat);
3450
3451         /* The surfaces are already created, the callback only
3452          * passes the IWineD3DSurface to WineD3D
3453          */
3454         if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
3455         {
3456             hr = IWineD3DDevice_CreateCubeTexture(ddraw->wineD3DDevice, DDSD->dwWidth, levels, 0,
3457                     Format, Pool, object, &ddraw_null_wined3d_parent_ops,
3458                     (IWineD3DCubeTexture **)&object->wineD3DTexture);
3459         }
3460         else
3461         {
3462             hr = IWineD3DDevice_CreateTexture(ddraw->wineD3DDevice, DDSD->dwWidth, DDSD->dwHeight,
3463                     levels, 0, Format, Pool, object, &ddraw_null_wined3d_parent_ops,
3464                     (IWineD3DTexture **)&object->wineD3DTexture);
3465         }
3466         ddraw->tex_root = NULL;
3467     }
3468
3469     LeaveCriticalSection(&ddraw_cs);
3470     return hr;
3471 }
3472
3473 static HRESULT WINAPI ddraw7_CreateSurface(IDirectDraw7 *iface,
3474         DDSURFACEDESC2 *surface_desc, IDirectDrawSurface7 **surface, IUnknown *outer_unknown)
3475 {
3476     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3477
3478     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3479             iface, surface_desc, surface, outer_unknown);
3480
3481     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
3482     {
3483         WARN("Application supplied invalid surface descriptor\n");
3484         return DDERR_INVALIDPARAMS;
3485     }
3486
3487     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3488     {
3489         if (TRACE_ON(ddraw))
3490         {
3491             TRACE(" (%p) Requesting surface desc :\n", iface);
3492             DDRAW_dump_surface_desc(surface_desc);
3493         }
3494
3495         WARN("Application tried to create an explicit front or back buffer\n");
3496         return DDERR_INVALIDCAPS;
3497     }
3498
3499     return CreateSurface(This, surface_desc, surface, outer_unknown);
3500 }
3501
3502 static HRESULT WINAPI ddraw4_CreateSurface(IDirectDraw4 *iface,
3503         DDSURFACEDESC2 *surface_desc, IDirectDrawSurface4 **surface, IUnknown *outer_unknown)
3504 {
3505     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
3506     IDirectDrawSurfaceImpl *impl;
3507     HRESULT hr;
3508
3509     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3510             iface, surface_desc, surface, outer_unknown);
3511
3512     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC2))
3513     {
3514         WARN("Application supplied invalid surface descriptor\n");
3515         return DDERR_INVALIDPARAMS;
3516     }
3517
3518     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3519     {
3520         if (TRACE_ON(ddraw))
3521         {
3522             TRACE(" (%p) Requesting surface desc :\n", iface);
3523             DDRAW_dump_surface_desc(surface_desc);
3524         }
3525
3526         WARN("Application tried to create an explicit front or back buffer\n");
3527         return DDERR_INVALIDCAPS;
3528     }
3529
3530     hr = CreateSurface(This, surface_desc, (IDirectDrawSurface7 **)surface, outer_unknown);
3531     impl = (IDirectDrawSurfaceImpl *)*surface;
3532     if (SUCCEEDED(hr) && impl)
3533     {
3534         ddraw_set_surface_version(impl, 4);
3535         IDirectDraw7_Release((IDirectDraw7 *)This);
3536         IDirectDraw4_AddRef(iface);
3537         impl->ifaceToRelease = (IUnknown *)iface;
3538     }
3539
3540     return hr;
3541 }
3542
3543 static HRESULT WINAPI ddraw3_CreateSurface(IDirectDraw3 *iface, DDSURFACEDESC *surface_desc,
3544         IDirectDrawSurface **surface, IUnknown *outer_unknown)
3545 {
3546     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
3547     IDirectDrawSurface7 *surface7;
3548     IDirectDrawSurfaceImpl *impl;
3549     HRESULT hr;
3550
3551     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3552             iface, surface_desc, surface, outer_unknown);
3553
3554     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3555     {
3556         WARN("Application supplied invalid surface descriptor\n");
3557         return DDERR_INVALIDPARAMS;
3558     }
3559
3560     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3561     {
3562         if (TRACE_ON(ddraw))
3563         {
3564             TRACE(" (%p) Requesting surface desc :\n", iface);
3565             DDRAW_dump_surface_desc((LPDDSURFACEDESC2)surface_desc);
3566         }
3567
3568         WARN("Application tried to create an explicit front or back buffer\n");
3569         return DDERR_INVALIDCAPS;
3570     }
3571
3572     hr = CreateSurface(This, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3573     if (FAILED(hr))
3574     {
3575         *surface = NULL;
3576         return hr;
3577     }
3578
3579     impl = (IDirectDrawSurfaceImpl *)surface7;
3580     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3581     ddraw_set_surface_version(impl, 3);
3582     IDirectDraw7_Release((IDirectDraw7 *)This);
3583     IDirectDraw3_AddRef(iface);
3584     impl->ifaceToRelease = (IUnknown *)iface;
3585
3586     return hr;
3587 }
3588
3589 static HRESULT WINAPI ddraw2_CreateSurface(IDirectDraw2 *iface,
3590         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3591 {
3592     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
3593     IDirectDrawSurface7 *surface7;
3594     IDirectDrawSurfaceImpl *impl;
3595     HRESULT hr;
3596
3597     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3598             iface, surface_desc, surface, outer_unknown);
3599
3600     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3601     {
3602         WARN("Application supplied invalid surface descriptor\n");
3603         return DDERR_INVALIDPARAMS;
3604     }
3605
3606     if(surface_desc->ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))
3607     {
3608         if (TRACE_ON(ddraw))
3609         {
3610             TRACE(" (%p) Requesting surface desc :\n", iface);
3611             DDRAW_dump_surface_desc((LPDDSURFACEDESC2)surface_desc);
3612         }
3613
3614         WARN("Application tried to create an explicit front or back buffer\n");
3615         return DDERR_INVALIDCAPS;
3616     }
3617
3618     hr = CreateSurface(This, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3619     if (FAILED(hr))
3620     {
3621         *surface = NULL;
3622         return hr;
3623     }
3624
3625     impl = (IDirectDrawSurfaceImpl *)surface7;
3626     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3627     ddraw_set_surface_version(impl, 2);
3628     IDirectDraw7_Release((IDirectDraw7 *)This);
3629     impl->ifaceToRelease = NULL;
3630
3631     return hr;
3632 }
3633
3634 static HRESULT WINAPI ddraw1_CreateSurface(IDirectDraw *iface,
3635         DDSURFACEDESC *surface_desc, IDirectDrawSurface **surface, IUnknown *outer_unknown)
3636 {
3637     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
3638     IDirectDrawSurface7 *surface7;
3639     IDirectDrawSurfaceImpl *impl;
3640     HRESULT hr;
3641
3642     TRACE("iface %p, surface_desc %p, surface %p, outer_unknown %p.\n",
3643             iface, surface_desc, surface, outer_unknown);
3644
3645     if(surface_desc == NULL || surface_desc->dwSize != sizeof(DDSURFACEDESC))
3646     {
3647         WARN("Application supplied invalid surface descriptor\n");
3648         return DDERR_INVALIDPARAMS;
3649     }
3650
3651     /* Remove front buffer flag, this causes failure in v7, and its added to normal
3652      * primaries anyway. */
3653     surface_desc->ddsCaps.dwCaps &= ~DDSCAPS_FRONTBUFFER;
3654     hr = CreateSurface(This, (DDSURFACEDESC2 *)surface_desc, &surface7, outer_unknown);
3655     if (FAILED(hr))
3656     {
3657         *surface = NULL;
3658         return hr;
3659     }
3660
3661     impl = (IDirectDrawSurfaceImpl *)surface7;
3662     *surface = (IDirectDrawSurface *)&impl->IDirectDrawSurface3_vtbl;
3663     ddraw_set_surface_version(impl, 1);
3664     IDirectDraw7_Release((IDirectDraw7 *)This);
3665     impl->ifaceToRelease = NULL;
3666
3667     return hr;
3668 }
3669
3670 #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST)
3671 #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH)
3672
3673 static BOOL
3674 Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested,
3675                                     const DDPIXELFORMAT *provided)
3676 {
3677     /* Some flags must be present in both or neither for a match. */
3678     static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
3679         | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC
3680         | DDPF_ZBUFFER | DDPF_STENCILBUFFER;
3681
3682     if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3683         return FALSE;
3684
3685     if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match))
3686         return FALSE;
3687
3688     if (requested->dwFlags & DDPF_FOURCC)
3689         if (requested->dwFourCC != provided->dwFourCC)
3690             return FALSE;
3691
3692     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA
3693                               |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3694         if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount)
3695             return FALSE;
3696
3697     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3698                               |DDPF_LUMINANCE|DDPF_BUMPDUDV))
3699         if (requested->u2.dwRBitMask != provided->u2.dwRBitMask)
3700             return FALSE;
3701
3702     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV))
3703         if (requested->u3.dwGBitMask != provided->u3.dwGBitMask)
3704             return FALSE;
3705
3706     /* I could be wrong about the bumpmapping. MSDN docs are vague. */
3707     if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER
3708                               |DDPF_BUMPDUDV))
3709         if (requested->u4.dwBBitMask != provided->u4.dwBBitMask)
3710             return FALSE;
3711
3712     if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS))
3713         if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask)
3714             return FALSE;
3715
3716     return TRUE;
3717 }
3718
3719 static BOOL ddraw_match_surface_desc(const DDSURFACEDESC2 *requested, const DDSURFACEDESC2 *provided)
3720 {
3721     struct compare_info
3722     {
3723         DWORD flag;
3724         ptrdiff_t offset;
3725         size_t size;
3726     };
3727
3728 #define CMP(FLAG, FIELD)                                \
3729         { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
3730           sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
3731
3732     static const struct compare_info compare[] =
3733     {
3734         CMP(ALPHABITDEPTH, dwAlphaBitDepth),
3735         CMP(BACKBUFFERCOUNT, dwBackBufferCount),
3736         CMP(CAPS, ddsCaps),
3737         CMP(CKDESTBLT, ddckCKDestBlt),
3738         CMP(CKDESTOVERLAY, u3 /* ddckCKDestOverlay */),
3739         CMP(CKSRCBLT, ddckCKSrcBlt),
3740         CMP(CKSRCOVERLAY, ddckCKSrcOverlay),
3741         CMP(HEIGHT, dwHeight),
3742         CMP(LINEARSIZE, u1 /* dwLinearSize */),
3743         CMP(LPSURFACE, lpSurface),
3744         CMP(MIPMAPCOUNT, u2 /* dwMipMapCount */),
3745         CMP(PITCH, u1 /* lPitch */),
3746         /* PIXELFORMAT: manual */
3747         CMP(REFRESHRATE, u2 /* dwRefreshRate */),
3748         CMP(TEXTURESTAGE, dwTextureStage),
3749         CMP(WIDTH, dwWidth),
3750         /* ZBUFFERBITDEPTH: "obsolete" */
3751     };
3752
3753 #undef CMP
3754
3755     unsigned int i;
3756
3757     if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags)
3758         return FALSE;
3759
3760     for (i=0; i < sizeof(compare)/sizeof(compare[0]); i++)
3761     {
3762         if (requested->dwFlags & compare[i].flag
3763             && memcmp((const char *)provided + compare[i].offset,
3764                       (const char *)requested + compare[i].offset,
3765                       compare[i].size) != 0)
3766             return FALSE;
3767     }
3768
3769     if (requested->dwFlags & DDSD_PIXELFORMAT)
3770     {
3771         if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat,
3772                                                 &provided->u4.ddpfPixelFormat))
3773             return FALSE;
3774     }
3775
3776     return TRUE;
3777 }
3778
3779 #undef DDENUMSURFACES_SEARCHTYPE
3780 #undef DDENUMSURFACES_MATCHTYPE
3781
3782 struct surfacescallback_context
3783 {
3784     LPDDENUMSURFACESCALLBACK func;
3785     void *context;
3786 };
3787
3788 static HRESULT CALLBACK EnumSurfacesCallbackThunk(IDirectDrawSurface7 *surface,
3789         DDSURFACEDESC2 *surface_desc, void *context)
3790 {
3791     struct surfacescallback_context *cbcontext = context;
3792
3793     return cbcontext->func((IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)surface)->IDirectDrawSurface3_vtbl,
3794             (DDSURFACEDESC *)surface_desc, cbcontext->context);
3795 }
3796
3797 /*****************************************************************************
3798  * IDirectDraw7::EnumSurfaces
3799  *
3800  * Loops through all surfaces attached to this device and calls the
3801  * application callback. This can't be relayed to WineD3DDevice,
3802  * because some WineD3DSurfaces' parents are IParent objects
3803  *
3804  * Params:
3805  *  Flags: Some filtering flags. See IDirectDrawImpl_EnumSurfacesCallback
3806  *  DDSD: Description to filter for
3807  *  Context: Application-provided pointer, it's passed unmodified to the
3808  *           Callback function
3809  *  Callback: Address to call for each surface
3810  *
3811  * Returns:
3812  *  DDERR_INVALIDPARAMS if the callback is NULL
3813  *  DD_OK on success
3814  *
3815  *****************************************************************************/
3816 static HRESULT WINAPI ddraw7_EnumSurfaces(IDirectDraw7 *iface, DWORD Flags,
3817         DDSURFACEDESC2 *DDSD, void *Context, LPDDENUMSURFACESCALLBACK7 Callback)
3818 {
3819     /* The surface enumeration is handled by WineDDraw,
3820      * because it keeps track of all surfaces attached to
3821      * it. The filtering is done by our callback function,
3822      * because WineDDraw doesn't handle ddraw-like surface
3823      * caps structures
3824      */
3825     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
3826     IDirectDrawSurfaceImpl *surf;
3827     BOOL all, nomatch;
3828     DDSURFACEDESC2 desc;
3829     struct list *entry, *entry2;
3830
3831     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3832             iface, Flags, DDSD, Context, Callback);
3833
3834     all = Flags & DDENUMSURFACES_ALL;
3835     nomatch = Flags & DDENUMSURFACES_NOMATCH;
3836
3837     EnterCriticalSection(&ddraw_cs);
3838
3839     if(!Callback)
3840     {
3841         LeaveCriticalSection(&ddraw_cs);
3842         return DDERR_INVALIDPARAMS;
3843     }
3844
3845     /* Use the _SAFE enumeration, the app may destroy enumerated surfaces */
3846     LIST_FOR_EACH_SAFE(entry, entry2, &This->surface_list)
3847     {
3848         surf = LIST_ENTRY(entry, IDirectDrawSurfaceImpl, surface_list_entry);
3849         if (all || (nomatch != ddraw_match_surface_desc(DDSD, &surf->surface_desc)))
3850         {
3851             desc = surf->surface_desc;
3852             IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)surf);
3853             if (Callback((IDirectDrawSurface7 *)surf, &desc, Context) != DDENUMRET_OK)
3854             {
3855                 LeaveCriticalSection(&ddraw_cs);
3856                 return DD_OK;
3857             }
3858         }
3859     }
3860     LeaveCriticalSection(&ddraw_cs);
3861     return DD_OK;
3862 }
3863
3864 static HRESULT WINAPI ddraw4_EnumSurfaces(IDirectDraw4 *iface, DWORD flags,
3865         DDSURFACEDESC2 *surface_desc, void *context, LPDDENUMSURFACESCALLBACK2 callback)
3866 {
3867     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
3868
3869     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3870             iface, flags, surface_desc, context, callback);
3871
3872     return ddraw7_EnumSurfaces((IDirectDraw7 *)This, flags, surface_desc, context,
3873             (LPDDENUMSURFACESCALLBACK7)callback);
3874 }
3875
3876 static HRESULT WINAPI ddraw3_EnumSurfaces(IDirectDraw3 *iface, DWORD flags,
3877         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3878 {
3879     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
3880     struct surfacescallback_context cbcontext;
3881
3882     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3883             iface, flags, surface_desc, context, callback);
3884
3885     cbcontext.func = callback;
3886     cbcontext.context = context;
3887
3888     return ddraw7_EnumSurfaces((IDirectDraw7 *)This, flags,
3889             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3890 }
3891
3892 static HRESULT WINAPI ddraw2_EnumSurfaces(IDirectDraw2 *iface, DWORD flags,
3893         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3894 {
3895     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
3896     struct surfacescallback_context cbcontext;
3897
3898     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3899             iface, flags, surface_desc, context, callback);
3900
3901     cbcontext.func = callback;
3902     cbcontext.context = context;
3903
3904     return ddraw7_EnumSurfaces((IDirectDraw7 *)This, flags,
3905             (DDSURFACEDESC2 *)surface_desc, &cbcontext, EnumSurfacesCallbackThunk);
3906 }
3907
3908 static HRESULT WINAPI ddraw1_EnumSurfaces(IDirectDraw *iface, DWORD flags,
3909         DDSURFACEDESC *surface_desc, void *context, LPDDENUMSURFACESCALLBACK callback)
3910 {
3911     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
3912     struct surfacescallback_context cbcontext;
3913
3914     TRACE("iface %p, flags %#x, surface_desc %p, context %p, callback %p.\n",
3915             iface, flags, surface_desc, context, callback);
3916
3917     cbcontext.func = callback;
3918     cbcontext.context = context;
3919
3920     return ddraw7_EnumSurfaces((IDirectDraw7 *)This, flags, (DDSURFACEDESC2 *)surface_desc,
3921             &cbcontext, EnumSurfacesCallbackThunk);
3922 }
3923
3924 /*****************************************************************************
3925  * DirectDrawCreateClipper (DDRAW.@)
3926  *
3927  * Creates a new IDirectDrawClipper object.
3928  *
3929  * Params:
3930  *  Clipper: Address to write the interface pointer to
3931  *  UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
3932  *            NULL
3933  *
3934  * Returns:
3935  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
3936  *  E_OUTOFMEMORY if allocating the object failed
3937  *
3938  *****************************************************************************/
3939 HRESULT WINAPI
3940 DirectDrawCreateClipper(DWORD Flags,
3941                         LPDIRECTDRAWCLIPPER *Clipper,
3942                         IUnknown *UnkOuter)
3943 {
3944     IDirectDrawClipperImpl* object;
3945     HRESULT hr;
3946
3947     TRACE("flags %#x, clipper %p, outer_unknown %p.\n",
3948             Flags, Clipper, UnkOuter);
3949
3950     EnterCriticalSection(&ddraw_cs);
3951     if (UnkOuter != NULL)
3952     {
3953         LeaveCriticalSection(&ddraw_cs);
3954         return CLASS_E_NOAGGREGATION;
3955     }
3956
3957     if (!LoadWineD3D())
3958     {
3959         LeaveCriticalSection(&ddraw_cs);
3960         return DDERR_NODIRECTDRAWSUPPORT;
3961     }
3962
3963     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3964                      sizeof(IDirectDrawClipperImpl));
3965     if (object == NULL)
3966     {
3967         LeaveCriticalSection(&ddraw_cs);
3968         return E_OUTOFMEMORY;
3969     }
3970
3971     hr = ddraw_clipper_init(object);
3972     if (FAILED(hr))
3973     {
3974         WARN("Failed to initialize clipper, hr %#x.\n", hr);
3975         HeapFree(GetProcessHeap(), 0, object);
3976         LeaveCriticalSection(&ddraw_cs);
3977         return hr;
3978     }
3979
3980     TRACE("Created clipper %p.\n", object);
3981     *Clipper = (IDirectDrawClipper *) object;
3982     LeaveCriticalSection(&ddraw_cs);
3983     return DD_OK;
3984 }
3985
3986 /*****************************************************************************
3987  * IDirectDraw7::CreateClipper
3988  *
3989  * Creates a DDraw clipper. See DirectDrawCreateClipper for details
3990  *
3991  *****************************************************************************/
3992 static HRESULT WINAPI ddraw7_CreateClipper(IDirectDraw7 *iface, DWORD Flags,
3993         IDirectDrawClipper **Clipper, IUnknown *UnkOuter)
3994 {
3995     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
3996             iface, Flags, Clipper, UnkOuter);
3997
3998     return DirectDrawCreateClipper(Flags, Clipper, UnkOuter);
3999 }
4000
4001 static HRESULT WINAPI ddraw4_CreateClipper(IDirectDraw4 *iface, DWORD flags,
4002         IDirectDrawClipper **clipper, IUnknown *outer_unknown)
4003 {
4004     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
4005
4006     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
4007             iface, flags, clipper, outer_unknown);
4008
4009     return ddraw7_CreateClipper((IDirectDraw7 *)This, flags, clipper, outer_unknown);
4010 }
4011
4012 static HRESULT WINAPI ddraw3_CreateClipper(IDirectDraw3 *iface, DWORD flags,
4013         IDirectDrawClipper **clipper, IUnknown *outer_unknown)
4014 {
4015     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
4016
4017     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
4018             iface, flags, clipper, outer_unknown);
4019
4020     return ddraw7_CreateClipper((IDirectDraw7 *)This, flags, clipper, outer_unknown);
4021 }
4022
4023 static HRESULT WINAPI ddraw2_CreateClipper(IDirectDraw2 *iface,
4024         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
4025 {
4026     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
4027
4028     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
4029             iface, flags, clipper, outer_unknown);
4030
4031     return ddraw7_CreateClipper((IDirectDraw7 *)This, flags, clipper, outer_unknown);
4032 }
4033
4034 static HRESULT WINAPI ddraw1_CreateClipper(IDirectDraw *iface,
4035         DWORD flags, IDirectDrawClipper **clipper, IUnknown *outer_unknown)
4036 {
4037     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
4038
4039     TRACE("iface %p, flags %#x, clipper %p, outer_unknown %p.\n",
4040             iface, flags, clipper, outer_unknown);
4041
4042     return ddraw7_CreateClipper((IDirectDraw7 *)This, flags, clipper, outer_unknown);
4043 }
4044
4045 /*****************************************************************************
4046  * IDirectDraw7::CreatePalette
4047  *
4048  * Creates a new IDirectDrawPalette object
4049  *
4050  * Params:
4051  *  Flags: The flags for the new clipper
4052  *  ColorTable: Color table to assign to the new clipper
4053  *  Palette: Address to write the interface pointer to
4054  *  UnkOuter: For aggregation support, which ddraw doesn't have. Has to be
4055  *            NULL
4056  *
4057  * Returns:
4058  *  CLASS_E_NOAGGREGATION if UnkOuter != NULL
4059  *  E_OUTOFMEMORY if allocating the object failed
4060  *
4061  *****************************************************************************/
4062 static HRESULT WINAPI ddraw7_CreatePalette(IDirectDraw7 *iface, DWORD Flags,
4063         PALETTEENTRY *ColorTable, IDirectDrawPalette **Palette, IUnknown *pUnkOuter)
4064 {
4065     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
4066     IDirectDrawPaletteImpl *object;
4067     HRESULT hr;
4068
4069     TRACE("iface %p, flags %#x, color_table %p, palette %p, outer_unknown %p.\n",
4070             iface, Flags, ColorTable, Palette, pUnkOuter);
4071
4072     EnterCriticalSection(&ddraw_cs);
4073     if(pUnkOuter != NULL)
4074     {
4075         WARN("pUnkOuter is %p, returning CLASS_E_NOAGGREGATION\n", pUnkOuter);
4076         LeaveCriticalSection(&ddraw_cs);
4077         return CLASS_E_NOAGGREGATION;
4078     }
4079
4080     /* The refcount test shows that a cooplevel is required for this */
4081     if(!This->cooperative_level)
4082     {
4083         WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n");
4084         LeaveCriticalSection(&ddraw_cs);
4085         return DDERR_NOCOOPERATIVELEVELSET;
4086     }
4087
4088     object = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawPaletteImpl));
4089     if(!object)
4090     {
4091         ERR("Out of memory when allocating memory for a palette implementation\n");
4092         LeaveCriticalSection(&ddraw_cs);
4093         return E_OUTOFMEMORY;
4094     }
4095
4096     hr = ddraw_palette_init(object, This, Flags, ColorTable);
4097     if (FAILED(hr))
4098     {
4099         WARN("Failed to initialize palette, hr %#x.\n", hr);
4100         HeapFree(GetProcessHeap(), 0, object);
4101         LeaveCriticalSection(&ddraw_cs);
4102         return hr;
4103     }
4104
4105     TRACE("Created palette %p.\n", object);
4106     *Palette = (IDirectDrawPalette *)object;
4107     LeaveCriticalSection(&ddraw_cs);
4108     return DD_OK;
4109 }
4110
4111 static HRESULT WINAPI ddraw4_CreatePalette(IDirectDraw4 *iface, DWORD flags, PALETTEENTRY *entries,
4112         IDirectDrawPalette **palette, IUnknown *outer_unknown)
4113 {
4114     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
4115     HRESULT hr;
4116
4117     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4118             iface, flags, entries, palette, outer_unknown);
4119
4120     hr = ddraw7_CreatePalette((IDirectDraw7 *)This, flags, entries, palette, outer_unknown);
4121     if (SUCCEEDED(hr) && *palette)
4122     {
4123         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4124         IDirectDraw7_Release((IDirectDraw7 *)This);
4125         IDirectDraw4_AddRef(iface);
4126         impl->ifaceToRelease = (IUnknown *)iface;
4127     }
4128     return hr;
4129 }
4130
4131 static HRESULT WINAPI ddraw3_CreatePalette(IDirectDraw3 *iface, DWORD flags,
4132         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
4133 {
4134     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
4135     HRESULT hr;
4136
4137     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4138             iface, flags, entries, palette, outer_unknown);
4139
4140     hr = ddraw7_CreatePalette((IDirectDraw7 *)This, flags, entries, palette, outer_unknown);
4141     if (SUCCEEDED(hr) && *palette)
4142     {
4143         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4144         IDirectDraw7_Release((IDirectDraw7 *)This);
4145         IDirectDraw4_AddRef(iface);
4146         impl->ifaceToRelease = (IUnknown *)iface;
4147     }
4148
4149     return hr;
4150 }
4151
4152 static HRESULT WINAPI ddraw2_CreatePalette(IDirectDraw2 *iface, DWORD flags,
4153         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
4154 {
4155     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
4156     HRESULT hr;
4157
4158     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4159             iface, flags, entries, palette, outer_unknown);
4160
4161     hr = ddraw7_CreatePalette((IDirectDraw7 *)This, flags, entries, palette, outer_unknown);
4162     if (SUCCEEDED(hr) && *palette)
4163     {
4164         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4165         IDirectDraw7_Release((IDirectDraw7 *)This);
4166         impl->ifaceToRelease = NULL;
4167     }
4168
4169     return hr;
4170 }
4171
4172 static HRESULT WINAPI ddraw1_CreatePalette(IDirectDraw *iface, DWORD flags,
4173         PALETTEENTRY *entries, IDirectDrawPalette **palette, IUnknown *outer_unknown)
4174 {
4175     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
4176     HRESULT hr;
4177
4178     TRACE("iface %p, flags %#x, entries %p, palette %p, outer_unknown %p.\n",
4179             iface, flags, entries, palette, outer_unknown);
4180
4181     hr = ddraw7_CreatePalette((IDirectDraw7 *)This, flags, entries, palette, outer_unknown);
4182     if (SUCCEEDED(hr) && *palette)
4183     {
4184         IDirectDrawPaletteImpl *impl = (IDirectDrawPaletteImpl *)*palette;
4185         IDirectDraw7_Release((IDirectDraw7 *)This);
4186         impl->ifaceToRelease = NULL;
4187     }
4188
4189     return hr;
4190 }
4191
4192 /*****************************************************************************
4193  * IDirectDraw7::DuplicateSurface
4194  *
4195  * Duplicates a surface. The surface memory points to the same memory as
4196  * the original surface, and it's released when the last surface referencing
4197  * it is released. I guess that's beyond Wine's surface management right now
4198  * (Idea: create a new DDraw surface with the same WineD3DSurface. I need a
4199  * test application to implement this)
4200  *
4201  * Params:
4202  *  Src: Address of the source surface
4203  *  Dest: Address to write the new surface pointer to
4204  *
4205  * Returns:
4206  *  See IDirectDraw7::CreateSurface
4207  *
4208  *****************************************************************************/
4209 static HRESULT WINAPI ddraw7_DuplicateSurface(IDirectDraw7 *iface,
4210         IDirectDrawSurface7 *Src, IDirectDrawSurface7 **Dest)
4211 {
4212     IDirectDrawSurfaceImpl *Surf = (IDirectDrawSurfaceImpl *)Src;
4213
4214     FIXME("iface %p, src %p, dst %p partial stub!\n", iface, Src, Dest);
4215
4216     /* For now, simply create a new, independent surface */
4217     return IDirectDraw7_CreateSurface(iface,
4218                                       &Surf->surface_desc,
4219                                       Dest,
4220                                       NULL);
4221 }
4222
4223 static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSurface4 *src,
4224         IDirectDrawSurface4 **dst)
4225 {
4226     IDirectDrawImpl *This = impl_from_IDirectDraw4(iface);
4227
4228     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4229
4230     return ddraw7_DuplicateSurface((IDirectDraw7 *)This, (IDirectDrawSurface7 *)src,
4231             (IDirectDrawSurface7 **)dst);
4232 }
4233
4234 static HRESULT WINAPI ddraw3_DuplicateSurface(IDirectDraw3 *iface, IDirectDrawSurface *src,
4235         IDirectDrawSurface **dst)
4236 {
4237     IDirectDrawImpl *This = impl_from_IDirectDraw3(iface);
4238     IDirectDrawSurface7 *src7, *dst7;
4239     HRESULT hr;
4240
4241     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4242     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4243     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)This, src7, &dst7);
4244     if (FAILED(hr))
4245         return hr;
4246     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4247     return hr;
4248 }
4249
4250 static HRESULT WINAPI ddraw2_DuplicateSurface(IDirectDraw2 *iface,
4251         IDirectDrawSurface *src, IDirectDrawSurface **dst)
4252 {
4253     IDirectDrawImpl *This = impl_from_IDirectDraw2(iface);
4254     IDirectDrawSurface7 *src7, *dst7;
4255     HRESULT hr;
4256
4257     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4258     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4259     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)This, src7, &dst7);
4260     if (FAILED(hr))
4261         return hr;
4262     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4263     return hr;
4264 }
4265
4266 static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSurface *src,
4267         IDirectDrawSurface **dst)
4268 {
4269     IDirectDrawImpl *This = impl_from_IDirectDraw(iface);
4270     IDirectDrawSurface7 *src7, *dst7;
4271     HRESULT hr;
4272
4273     TRACE("iface %p, src %p, dst %p.\n", iface, src, dst);
4274     src7 = (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)src);
4275     hr = ddraw7_DuplicateSurface((IDirectDraw7 *)This, src7, &dst7);
4276     if (FAILED(hr))
4277         return hr;
4278     *dst = (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)dst7)->IDirectDrawSurface3_vtbl;
4279     return hr;
4280 }
4281
4282 /*****************************************************************************
4283  * IDirect3D7::EnumDevices
4284  *
4285  * The EnumDevices method for IDirect3D7. It enumerates all supported
4286  * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
4287  *
4288  * Params:
4289  *  callback: Function to call for each enumerated device
4290  *  context: Pointer to pass back to the app
4291  *
4292  * Returns:
4293  *  D3D_OK, or the return value of the GetCaps call
4294  *
4295  *****************************************************************************/
4296 static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBACK7 callback, void *context)
4297 {
4298     char interface_name_tnl[] = "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D";
4299     char device_name_tnl[] = "Wine D3D7 T&L HAL";
4300     char interface_name_hal[] = "WINE Direct3D7 Hardware acceleration using WineD3D";
4301     char device_name_hal[] = "Wine D3D7 HAL";
4302     char interface_name_rgb[] = "WINE Direct3D7 RGB Software Emulation using WineD3D";
4303     char device_name_rgb[] = "Wine D3D7 RGB";
4304
4305     IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
4306     D3DDEVICEDESC7 device_desc7;
4307     D3DDEVICEDESC device_desc1;
4308     HRESULT hr;
4309
4310     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4311
4312     EnterCriticalSection(&ddraw_cs);
4313
4314     hr = IDirect3DImpl_GetCaps(This->wineD3D, &device_desc1, &device_desc7);
4315     if (hr != D3D_OK)
4316     {
4317         LeaveCriticalSection(&ddraw_cs);
4318         return hr;
4319     }
4320     callback(interface_name_tnl, device_name_tnl, &device_desc7, context);
4321
4322     device_desc7.deviceGUID = IID_IDirect3DHALDevice;
4323     callback(interface_name_hal, device_name_hal, &device_desc7, context);
4324
4325     device_desc7.deviceGUID = IID_IDirect3DRGBDevice;
4326     callback(interface_name_rgb, device_name_rgb, &device_desc7, context);
4327
4328     TRACE("End of enumeration.\n");
4329
4330     LeaveCriticalSection(&ddraw_cs);
4331
4332     return D3D_OK;
4333 }
4334
4335 /*****************************************************************************
4336  * IDirect3D3::EnumDevices
4337  *
4338  * Enumerates all supported Direct3DDevice interfaces. This is the
4339  * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
4340  *
4341  * Version 1, 2 and 3
4342  *
4343  * Params:
4344  *  callback: Application-provided routine to call for each enumerated device
4345  *  Context: Pointer to pass to the callback
4346  *
4347  * Returns:
4348  *  D3D_OK on success,
4349  *  The result of IDirect3DImpl_GetCaps if it failed
4350  *
4351  *****************************************************************************/
4352 static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4353 {
4354     static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
4355
4356     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4357     D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
4358     D3DDEVICEDESC7 device_desc7;
4359     HRESULT hr;
4360
4361     /* Some games (Motoracer 2 demo) have the bad idea to modify the device
4362      * name string. Let's put the string in a sufficiently sized array in
4363      * writable memory. */
4364     char device_name[50];
4365     strcpy(device_name,"Direct3D HEL");
4366
4367     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4368
4369     EnterCriticalSection(&ddraw_cs);
4370
4371     hr = IDirect3DImpl_GetCaps(This->wineD3D, &device_desc1, &device_desc7);
4372     if (hr != D3D_OK)
4373     {
4374         LeaveCriticalSection(&ddraw_cs);
4375         return hr;
4376     }
4377
4378     /* Do I have to enumerate the reference id? Note from old d3d7:
4379      * "It seems that enumerating the reference IID on Direct3D 1 games
4380      * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
4381      *
4382      * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
4383      * EnumReference which enables / disables enumerating the reference
4384      * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
4385      * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
4386      * demo directory suggest this.
4387      *
4388      * Some games(GTA 2) seem to use the second enumerated device, so I have
4389      * to enumerate at least 2 devices. So enumerate the reference device to
4390      * have 2 devices.
4391      *
4392      * Other games (Rollcage) tell emulation and hal device apart by certain
4393      * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
4394      * limitation flag), and it refuses all devices that have the perspective
4395      * flag set. This way it refuses the emulation device, and HAL devices
4396      * never have POW2 unset in d3d7 on windows. */
4397     if (This->d3dversion != 1)
4398     {
4399         static CHAR reference_description[] = "RGB Direct3D emulation";
4400
4401         TRACE("Enumerating WineD3D D3DDevice interface.\n");
4402         hal_desc = device_desc1;
4403         hel_desc = device_desc1;
4404         /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
4405         hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4406                 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4407         hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4408                 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4409         hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
4410                 device_name, &hal_desc, &hel_desc, context);
4411         if (hr != D3DENUMRET_OK)
4412         {
4413             TRACE("Application cancelled the enumeration.\n");
4414             LeaveCriticalSection(&ddraw_cs);
4415             return D3D_OK;
4416         }
4417     }
4418
4419     strcpy(device_name,"Direct3D HAL");
4420
4421     TRACE("Enumerating HAL Direct3D device.\n");
4422     hal_desc = device_desc1;
4423     hel_desc = device_desc1;
4424     /* The hal device does not have the pow2 flag set in hel, but in hal. */
4425     hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4426             | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4427     hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
4428             | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
4429     hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
4430             device_name, &hal_desc, &hel_desc, context);
4431     if (hr != D3DENUMRET_OK)
4432     {
4433         TRACE("Application cancelled the enumeration.\n");
4434         LeaveCriticalSection(&ddraw_cs);
4435         return D3D_OK;
4436     }
4437
4438     TRACE("End of enumeration.\n");
4439
4440     LeaveCriticalSection(&ddraw_cs);
4441     return D3D_OK;
4442 }
4443
4444 static HRESULT WINAPI d3d2_EnumDevices(IDirect3D2 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4445 {
4446     IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4447
4448     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4449
4450     return d3d3_EnumDevices(&This->IDirect3D3_iface, callback, context);
4451 }
4452
4453 static HRESULT WINAPI d3d1_EnumDevices(IDirect3D *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
4454 {
4455     IDirectDrawImpl *This = impl_from_IDirect3D(iface);
4456
4457     TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
4458
4459     return d3d3_EnumDevices(&This->IDirect3D3_iface, callback, context);
4460 }
4461
4462 /*****************************************************************************
4463  * IDirect3D3::CreateLight
4464  *
4465  * Creates an IDirect3DLight interface. This interface is used in
4466  * Direct3D3 or earlier for lighting. In Direct3D7 it has been replaced
4467  * by the DIRECT3DLIGHT7 structure. Wine's Direct3DLight implementation
4468  * uses the IDirect3DDevice7 interface with D3D7 lights.
4469  *
4470  * Version 1, 2 and 3
4471  *
4472  * Params:
4473  *  light: Address to store the new interface pointer
4474  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4475  *                 Must be NULL
4476  *
4477  * Returns:
4478  *  D3D_OK on success
4479  *  DDERR_OUTOFMEMORY if memory allocation failed
4480  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
4481  *
4482  *****************************************************************************/
4483 static HRESULT WINAPI d3d3_CreateLight(IDirect3D3 *iface, IDirect3DLight **light,
4484         IUnknown *outer_unknown)
4485 {
4486     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4487     IDirect3DLightImpl *object;
4488
4489     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4490
4491     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4492
4493     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4494     if (!object)
4495     {
4496         ERR("Failed to allocate light memory.\n");
4497         return DDERR_OUTOFMEMORY;
4498     }
4499
4500     d3d_light_init(object, This);
4501
4502     TRACE("Created light %p.\n", object);
4503     *light = (IDirect3DLight *)object;
4504
4505     return D3D_OK;
4506 }
4507
4508 static HRESULT WINAPI d3d2_CreateLight(IDirect3D2 *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4509 {
4510     IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4511
4512     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4513
4514     return d3d3_CreateLight(&This->IDirect3D3_iface, light, outer_unknown);
4515 }
4516
4517 static HRESULT WINAPI d3d1_CreateLight(IDirect3D *iface, IDirect3DLight **light, IUnknown *outer_unknown)
4518 {
4519     IDirectDrawImpl *This = impl_from_IDirect3D(iface);
4520
4521     TRACE("iface %p, light %p, outer_unknown %p.\n", iface, light, outer_unknown);
4522
4523     return d3d3_CreateLight(&This->IDirect3D3_iface, light, outer_unknown);
4524 }
4525
4526 /*****************************************************************************
4527  * IDirect3D3::CreateMaterial
4528  *
4529  * Creates an IDirect3DMaterial interface. This interface is used by Direct3D3
4530  * and older versions. The IDirect3DMaterial implementation wraps its
4531  * functionality to IDirect3DDevice7::SetMaterial and friends.
4532  *
4533  * Version 1, 2 and 3
4534  *
4535  * Params:
4536  *  material: Address to store the new interface's pointer to
4537  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4538  *                 Must be NULL
4539  *
4540  * Returns:
4541  *  D3D_OK on success
4542  *  DDERR_OUTOFMEMORY if memory allocation failed
4543  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
4544  *
4545  *****************************************************************************/
4546 static HRESULT WINAPI d3d3_CreateMaterial(IDirect3D3 *iface, IDirect3DMaterial3 **material,
4547         IUnknown *outer_unknown)
4548 {
4549     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4550     IDirect3DMaterialImpl *object;
4551
4552     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4553
4554     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4555
4556     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4557     if (!object)
4558     {
4559         ERR("Failed to allocate material memory.\n");
4560         return DDERR_OUTOFMEMORY;
4561     }
4562
4563     d3d_material_init(object, This);
4564
4565     TRACE("Created material %p.\n", object);
4566     *material = (IDirect3DMaterial3 *)object;
4567
4568     return D3D_OK;
4569 }
4570
4571 static HRESULT WINAPI d3d2_CreateMaterial(IDirect3D2 *iface, IDirect3DMaterial2 **material, IUnknown *outer_unknown)
4572 {
4573     IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4574     IDirect3DMaterial3 *material3;
4575     HRESULT hr;
4576
4577     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4578
4579     hr = d3d3_CreateMaterial(&This->IDirect3D3_iface, &material3, outer_unknown);
4580     *material = material3 ? (IDirect3DMaterial2 *)&((IDirect3DMaterialImpl *)material3)->IDirect3DMaterial2_vtbl : NULL;
4581
4582     TRACE("Returning material %p.\n", *material);
4583
4584     return hr;
4585 }
4586
4587 static HRESULT WINAPI d3d1_CreateMaterial(IDirect3D *iface, IDirect3DMaterial **material, IUnknown *outer_unknown)
4588 {
4589     IDirect3DMaterial3 *material3;
4590     HRESULT hr;
4591
4592     IDirectDrawImpl *This = impl_from_IDirect3D(iface);
4593
4594     TRACE("iface %p, material %p, outer_unknown %p.\n", iface, material, outer_unknown);
4595
4596     hr = d3d3_CreateMaterial(&This->IDirect3D3_iface, &material3, outer_unknown);
4597     *material = material3 ? (IDirect3DMaterial *)&((IDirect3DMaterialImpl *)material3)->IDirect3DMaterial_vtbl : NULL;
4598
4599     TRACE("Returning material %p.\n", *material);
4600
4601     return hr;
4602 }
4603
4604 /*****************************************************************************
4605  * IDirect3D3::CreateViewport
4606  *
4607  * Creates an IDirect3DViewport interface. This interface is used
4608  * by Direct3D and earlier versions for Viewport management. In Direct3D7
4609  * it has been replaced by a viewport structure and
4610  * IDirect3DDevice7::*Viewport. Wine's IDirect3DViewport implementation
4611  * uses the IDirect3DDevice7 methods for its functionality
4612  *
4613  * Params:
4614  *  Viewport: Address to store the new interface pointer
4615  *  outer_unknown: Basically for aggregation, but ddraw doesn't support it.
4616  *                 Must be NULL
4617  *
4618  * Returns:
4619  *  D3D_OK on success
4620  *  DDERR_OUTOFMEMORY if memory allocation failed
4621  *  CLASS_E_NOAGGREGATION if outer_unknown != NULL
4622  *
4623  *****************************************************************************/
4624 static HRESULT WINAPI d3d3_CreateViewport(IDirect3D3 *iface, IDirect3DViewport3 **viewport,
4625         IUnknown *outer_unknown)
4626 {
4627     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4628     IDirect3DViewportImpl *object;
4629
4630     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4631
4632     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4633
4634     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4635     if (!object)
4636     {
4637         ERR("Failed to allocate viewport memory.\n");
4638         return DDERR_OUTOFMEMORY;
4639     }
4640
4641     d3d_viewport_init(object, This);
4642
4643     TRACE("Created viewport %p.\n", object);
4644     *viewport = (IDirect3DViewport3 *)object;
4645
4646     return D3D_OK;
4647 }
4648
4649 static HRESULT WINAPI d3d2_CreateViewport(IDirect3D2 *iface, IDirect3DViewport2 **viewport, IUnknown *outer_unknown)
4650 {
4651     IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4652
4653     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4654
4655     return d3d3_CreateViewport(&This->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4656             outer_unknown);
4657 }
4658
4659 static HRESULT WINAPI d3d1_CreateViewport(IDirect3D *iface, IDirect3DViewport **viewport, IUnknown *outer_unknown)
4660 {
4661     IDirectDrawImpl *This = impl_from_IDirect3D(iface);
4662
4663     TRACE("iface %p, viewport %p, outer_unknown %p.\n", iface, viewport, outer_unknown);
4664
4665     return d3d3_CreateViewport(&This->IDirect3D3_iface, (IDirect3DViewport3 **)viewport,
4666             outer_unknown);
4667 }
4668
4669 /*****************************************************************************
4670  * IDirect3D3::FindDevice
4671  *
4672  * This method finds a device with the requested properties and returns a
4673  * device description
4674  *
4675  * Verion 1, 2 and 3
4676  * Params:
4677  *  fds: Describes the requested device characteristics
4678  *  fdr: Returns the device description
4679  *
4680  * Returns:
4681  *  D3D_OK on success
4682  *  DDERR_INVALIDPARAMS if no device was found
4683  *
4684  *****************************************************************************/
4685 static HRESULT WINAPI d3d3_FindDevice(IDirect3D3 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4686 {
4687     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4688     D3DDEVICEDESC7 desc7;
4689     D3DDEVICEDESC desc1;
4690     HRESULT hr;
4691
4692     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4693
4694     if (!fds || !fdr) return DDERR_INVALIDPARAMS;
4695
4696     if (fds->dwSize != sizeof(D3DFINDDEVICESEARCH)
4697             || fdr->dwSize != sizeof(D3DFINDDEVICERESULT))
4698         return DDERR_INVALIDPARAMS;
4699
4700     if ((fds->dwFlags & D3DFDS_COLORMODEL)
4701             && fds->dcmColorModel != D3DCOLOR_RGB)
4702     {
4703         WARN("Trying to request a non-RGB D3D color model. Not supported.\n");
4704         return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
4705     }
4706
4707     if (fds->dwFlags & D3DFDS_GUID)
4708     {
4709         TRACE("Trying to match guid %s.\n", debugstr_guid(&(fds->guid)));
4710         if (!IsEqualGUID(&IID_D3DDEVICE_WineD3D, &fds->guid)
4711                 && !IsEqualGUID(&IID_IDirect3DHALDevice, &fds->guid)
4712                 && !IsEqualGUID(&IID_IDirect3DRGBDevice, &fds->guid))
4713         {
4714             WARN("No match for this GUID.\n");
4715             return DDERR_NOTFOUND;
4716         }
4717     }
4718
4719     /* Get the caps */
4720     hr = IDirect3DImpl_GetCaps(This->wineD3D, &desc1, &desc7);
4721     if (hr != D3D_OK) return hr;
4722
4723     /* Now return our own GUID */
4724     fdr->guid = IID_D3DDEVICE_WineD3D;
4725     fdr->ddHwDesc = desc1;
4726     fdr->ddSwDesc = desc1;
4727
4728     TRACE("Returning Wine's wined3d device with (undumped) capabilities.\n");
4729
4730     return D3D_OK;
4731 }
4732
4733 static HRESULT WINAPI d3d2_FindDevice(IDirect3D2 *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4734 {
4735     IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4736
4737     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4738
4739     return d3d3_FindDevice(&This->IDirect3D3_iface, fds, fdr);
4740 }
4741
4742 static HRESULT WINAPI d3d1_FindDevice(IDirect3D *iface, D3DFINDDEVICESEARCH *fds, D3DFINDDEVICERESULT *fdr)
4743 {
4744     IDirectDrawImpl *This = impl_from_IDirect3D(iface);
4745
4746     TRACE("iface %p, fds %p, fdr %p.\n", iface, fds, fdr);
4747
4748     return d3d3_FindDevice(&This->IDirect3D3_iface, fds, fdr);
4749 }
4750
4751 /*****************************************************************************
4752  * IDirect3D7::CreateDevice
4753  *
4754  * Creates an IDirect3DDevice7 interface.
4755  *
4756  * Version 2, 3 and 7. IDirect3DDevice 1 interfaces are interfaces to
4757  * DirectDraw surfaces and are created with
4758  * IDirectDrawSurface::QueryInterface. This method uses CreateDevice to
4759  * create the device object and QueryInterfaces for IDirect3DDevice
4760  *
4761  * Params:
4762  *  refiid: IID of the device to create
4763  *  Surface: Initial rendertarget
4764  *  Device: Address to return the interface pointer
4765  *
4766  * Returns:
4767  *  D3D_OK on success
4768  *  DDERR_OUTOFMEMORY if memory allocation failed
4769  *  DDERR_INVALIDPARAMS if a device exists already
4770  *
4771  *****************************************************************************/
4772 static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
4773         IDirectDrawSurface7 *surface, IDirect3DDevice7 **device)
4774 {
4775     IDirectDrawSurfaceImpl *target = (IDirectDrawSurfaceImpl *)surface;
4776     IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
4777     IDirect3DDeviceImpl *object;
4778     HRESULT hr;
4779
4780     TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
4781
4782     EnterCriticalSection(&ddraw_cs);
4783     *device = NULL;
4784
4785     /* Fail device creation if non-opengl surfaces are used. */
4786     if (This->ImplType != SURFACE_OPENGL)
4787     {
4788         ERR("The application wants to create a Direct3D device, but non-opengl surfaces are set in the registry.\n");
4789         ERR("Please set the surface implementation to opengl or autodetection to allow 3D rendering.\n");
4790
4791         /* We only hit this path if a default surface is set in the registry. Incorrect autodetection
4792          * is caught in CreateSurface or QueryInterface. */
4793         LeaveCriticalSection(&ddraw_cs);
4794         return DDERR_NO3D;
4795     }
4796
4797     if (This->d3ddevice)
4798     {
4799         FIXME("Only one Direct3D device per DirectDraw object supported.\n");
4800         LeaveCriticalSection(&ddraw_cs);
4801         return DDERR_INVALIDPARAMS;
4802     }
4803
4804     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4805     if (!object)
4806     {
4807         ERR("Failed to allocate device memory.\n");
4808         LeaveCriticalSection(&ddraw_cs);
4809         return DDERR_OUTOFMEMORY;
4810     }
4811
4812     hr = d3d_device_init(object, This, target);
4813     if (FAILED(hr))
4814     {
4815         WARN("Failed to initialize device, hr %#x.\n", hr);
4816         HeapFree(GetProcessHeap(), 0, object);
4817         LeaveCriticalSection(&ddraw_cs);
4818         return hr;
4819     }
4820
4821     TRACE("Created device %p.\n", object);
4822     *device = (IDirect3DDevice7 *)object;
4823
4824     LeaveCriticalSection(&ddraw_cs);
4825     return D3D_OK;
4826 }
4827
4828 static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
4829         IDirectDrawSurface4 *surface, IDirect3DDevice3 **device, IUnknown *outer_unknown)
4830 {
4831     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4832     HRESULT hr;
4833
4834     TRACE("iface %p, riid %s, surface %p, device %p, outer_unknown %p.\n",
4835             iface, debugstr_guid(riid), surface, device, outer_unknown);
4836
4837     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4838
4839     hr = d3d7_CreateDevice(&This->IDirect3D7_iface, riid, (IDirectDrawSurface7 *)surface,
4840             (IDirect3DDevice7 **)device);
4841     if (*device) *device = (IDirect3DDevice3 *)&((IDirect3DDeviceImpl *)*device)->IDirect3DDevice3_vtbl;
4842
4843     return hr;
4844 }
4845
4846 static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
4847         IDirectDrawSurface *surface, IDirect3DDevice2 **device)
4848 {
4849     IDirectDrawImpl *This = impl_from_IDirect3D2(iface);
4850     HRESULT hr;
4851
4852     TRACE("iface %p, riid %s, surface %p, device %p.\n",
4853             iface, debugstr_guid(riid), surface, device);
4854
4855     hr = d3d7_CreateDevice(&This->IDirect3D7_iface, riid,
4856             surface ? (IDirectDrawSurface7 *)surface_from_surface3((IDirectDrawSurface3 *)surface) : NULL,
4857             (IDirect3DDevice7 **)device);
4858     if (*device) *device = (IDirect3DDevice2 *)&((IDirect3DDeviceImpl *)*device)->IDirect3DDevice2_vtbl;
4859
4860     return hr;
4861 }
4862
4863 /*****************************************************************************
4864  * IDirect3D7::CreateVertexBuffer
4865  *
4866  * Creates a new vertex buffer object and returns a IDirect3DVertexBuffer7
4867  * interface.
4868  *
4869  * Version 3 and 7
4870  *
4871  * Params:
4872  *  desc: Requested Vertex buffer properties
4873  *  vertex_buffer: Address to return the interface pointer at
4874  *  flags: Some flags, should be 0
4875  *
4876  * Returns
4877  *  D3D_OK on success
4878  *  DDERR_OUTOFMEMORY if memory allocation failed
4879  *  The return value of IWineD3DDevice::CreateVertexBuffer if this call fails
4880  *  DDERR_INVALIDPARAMS if desc or vertex_buffer are NULL
4881  *
4882  *****************************************************************************/
4883 static HRESULT WINAPI d3d7_CreateVertexBuffer(IDirect3D7 *iface, D3DVERTEXBUFFERDESC *desc,
4884         IDirect3DVertexBuffer7 **vertex_buffer, DWORD flags)
4885 {
4886     IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
4887     IDirect3DVertexBufferImpl *object;
4888     HRESULT hr;
4889
4890     TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x.\n",
4891             iface, desc, vertex_buffer, flags);
4892
4893     if (!vertex_buffer || !desc) return DDERR_INVALIDPARAMS;
4894
4895     TRACE("Vertex buffer description:\n");
4896     TRACE("    dwSize %u\n", desc->dwSize);
4897     TRACE("    dwCaps %#x\n", desc->dwCaps);
4898     TRACE("    FVF %#x\n", desc->dwFVF);
4899     TRACE("    dwNumVertices %u\n", desc->dwNumVertices);
4900
4901     /* Now create the vertex buffer */
4902     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4903     if (!object)
4904     {
4905         ERR("Failed to allocate vertex buffer memory.\n");
4906         return DDERR_OUTOFMEMORY;
4907     }
4908
4909     hr = d3d_vertex_buffer_init(object, This, desc);
4910     if (FAILED(hr))
4911     {
4912         WARN("Failed to initialize vertex buffer, hr %#x.\n", hr);
4913         HeapFree(GetProcessHeap(), 0, object);
4914         return hr;
4915     }
4916
4917     TRACE("Created vertex buffer %p.\n", object);
4918     *vertex_buffer = (IDirect3DVertexBuffer7 *)object;
4919
4920     return D3D_OK;
4921 }
4922
4923 static HRESULT WINAPI d3d3_CreateVertexBuffer(IDirect3D3 *iface, D3DVERTEXBUFFERDESC *desc,
4924         IDirect3DVertexBuffer **vertex_buffer, DWORD flags, IUnknown *outer_unknown)
4925 {
4926     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
4927     HRESULT hr;
4928
4929     TRACE("iface %p, desc %p, vertex_buffer %p, flags %#x, outer_unknown %p.\n",
4930             iface, desc, vertex_buffer, flags, outer_unknown);
4931
4932     if (outer_unknown) return CLASS_E_NOAGGREGATION;
4933
4934     hr = d3d7_CreateVertexBuffer(&This->IDirect3D7_iface, desc,
4935             (IDirect3DVertexBuffer7 **)vertex_buffer, flags);
4936     if (*vertex_buffer)
4937         *vertex_buffer = (IDirect3DVertexBuffer *)&((IDirect3DVertexBufferImpl *)*vertex_buffer)->IDirect3DVertexBuffer_vtbl;
4938
4939     return hr;
4940 }
4941
4942 /*****************************************************************************
4943  * IDirect3D7::EnumZBufferFormats
4944  *
4945  * Enumerates all supported Z buffer pixel formats
4946  *
4947  * Version 3 and 7
4948  *
4949  * Params:
4950  *  device_iid:
4951  *  callback: callback to call for each pixel format
4952  *  context: Pointer to pass back to the callback
4953  *
4954  * Returns:
4955  *  D3D_OK on success
4956  *  DDERR_INVALIDPARAMS if callback is NULL
4957  *  For details, see IWineD3DDevice::EnumZBufferFormats
4958  *
4959  *****************************************************************************/
4960 static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device_iid,
4961         LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
4962 {
4963     IDirectDrawImpl *This = impl_from_IDirect3D7(iface);
4964     WINED3DDISPLAYMODE d3ddm;
4965     WINED3DDEVTYPE type;
4966     unsigned int i;
4967     HRESULT hr;
4968
4969     /* Order matters. Specifically, BattleZone II (full version) expects the
4970      * 16-bit depth formats to be listed before the 24 and 32 ones. */
4971     static const enum wined3d_format_id formats[] =
4972     {
4973         WINED3DFMT_S1_UINT_D15_UNORM,
4974         WINED3DFMT_D16_UNORM,
4975         WINED3DFMT_X8D24_UNORM,
4976         WINED3DFMT_S4X4_UINT_D24_UNORM,
4977         WINED3DFMT_D24_UNORM_S8_UINT,
4978         WINED3DFMT_D32_UNORM,
4979     };
4980
4981     TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
4982             iface, debugstr_guid(device_iid), callback, context);
4983
4984     if (!callback) return DDERR_INVALIDPARAMS;
4985
4986     if (IsEqualGUID(device_iid, &IID_IDirect3DHALDevice)
4987             || IsEqualGUID(device_iid, &IID_IDirect3DTnLHalDevice)
4988             || IsEqualGUID(device_iid, &IID_D3DDEVICE_WineD3D))
4989     {
4990         TRACE("Asked for HAL device.\n");
4991         type = WINED3DDEVTYPE_HAL;
4992     }
4993     else if (IsEqualGUID(device_iid, &IID_IDirect3DRGBDevice)
4994             || IsEqualGUID(device_iid, &IID_IDirect3DMMXDevice))
4995     {
4996         TRACE("Asked for SW device.\n");
4997         type = WINED3DDEVTYPE_SW;
4998     }
4999     else if (IsEqualGUID(device_iid, &IID_IDirect3DRefDevice))
5000     {
5001         TRACE("Asked for REF device.\n");
5002         type = WINED3DDEVTYPE_REF;
5003     }
5004     else if (IsEqualGUID(device_iid, &IID_IDirect3DNullDevice))
5005     {
5006         TRACE("Asked for NULLREF device.\n");
5007         type = WINED3DDEVTYPE_NULLREF;
5008     }
5009     else
5010     {
5011         FIXME("Unexpected device GUID %s.\n", debugstr_guid(device_iid));
5012         type = WINED3DDEVTYPE_HAL;
5013     }
5014
5015     EnterCriticalSection(&ddraw_cs);
5016     /* We need an adapter format from somewhere to please wined3d and WGL.
5017      * Use the current display mode. So far all cards offer the same depth
5018      * stencil format for all modes, but if some do not and applications do
5019      * not like that we'll have to find some workaround, like iterating over
5020      * all imaginable formats and collecting all the depth stencil formats we
5021      * can get. */
5022     hr = IWineD3DDevice_GetDisplayMode(This->wineD3DDevice, 0, &d3ddm);
5023
5024     for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
5025     {
5026         hr = IWineD3D_CheckDeviceFormat(This->wineD3D, WINED3DADAPTER_DEFAULT, type, d3ddm.Format,
5027                 WINED3DUSAGE_DEPTHSTENCIL, WINED3DRTYPE_SURFACE, formats[i], SURFACE_OPENGL);
5028         if (SUCCEEDED(hr))
5029         {
5030             DDPIXELFORMAT pformat;
5031
5032             memset(&pformat, 0, sizeof(pformat));
5033             pformat.dwSize = sizeof(pformat);
5034             PixelFormat_WineD3DtoDD(&pformat, formats[i]);
5035
5036             TRACE("Enumerating wined3d format %#x.\n", formats[i]);
5037             hr = callback(&pformat, context);
5038             if (hr != DDENUMRET_OK)
5039             {
5040                 TRACE("Format enumeration cancelled by application.\n");
5041                 LeaveCriticalSection(&ddraw_cs);
5042                 return D3D_OK;
5043             }
5044         }
5045     }
5046     TRACE("End of enumeration.\n");
5047
5048     LeaveCriticalSection(&ddraw_cs);
5049     return D3D_OK;
5050 }
5051
5052 static HRESULT WINAPI d3d3_EnumZBufferFormats(IDirect3D3 *iface, REFCLSID device_iid,
5053         LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
5054 {
5055     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
5056
5057     TRACE("iface %p, device_iid %s, callback %p, context %p.\n",
5058             iface, debugstr_guid(device_iid), callback, context);
5059
5060     return d3d7_EnumZBufferFormats(&This->IDirect3D7_iface, device_iid, callback, context);
5061 }
5062
5063 /*****************************************************************************
5064  * IDirect3D7::EvictManagedTextures
5065  *
5066  * Removes all managed textures (=surfaces with DDSCAPS2_TEXTUREMANAGE or
5067  * DDSCAPS2_D3DTEXTUREMANAGE caps) to be removed from video memory.
5068  *
5069  * Version 3 and 7
5070  *
5071  * Returns:
5072  *  D3D_OK, because it's a stub
5073  *
5074  *****************************************************************************/
5075 static HRESULT WINAPI d3d7_EvictManagedTextures(IDirect3D7 *iface)
5076 {
5077     FIXME("iface %p stub!\n", iface);
5078
5079     /* TODO: Just enumerate resources using IWineD3DDevice_EnumResources(),
5080      * then unload surfaces / textures. */
5081
5082     return D3D_OK;
5083 }
5084
5085 static HRESULT WINAPI d3d3_EvictManagedTextures(IDirect3D3 *iface)
5086 {
5087     IDirectDrawImpl *This = impl_from_IDirect3D3(iface);
5088
5089     TRACE("iface %p.\n", iface);
5090
5091     return d3d7_EvictManagedTextures(&This->IDirect3D7_iface);
5092 }
5093
5094 /*****************************************************************************
5095  * IDirect3DImpl_GetCaps
5096  *
5097  * This function retrieves the device caps from wined3d
5098  * and converts it into a D3D7 and D3D - D3D3 structure
5099  * This is a helper function called from various places in ddraw
5100  *
5101  * Params:
5102  *  wined3d: The interface to get the caps from
5103  *  desc1: Old D3D <3 structure to fill (needed)
5104  *  desc7: D3D7 device desc structure to fill (needed)
5105  *
5106  * Returns
5107  *  D3D_OK on success, or the return value of IWineD3D::GetCaps
5108  *
5109  *****************************************************************************/
5110 HRESULT IDirect3DImpl_GetCaps(IWineD3D *wined3d, D3DDEVICEDESC *desc1, D3DDEVICEDESC7 *desc7)
5111 {
5112     WINED3DCAPS wined3d_caps;
5113     HRESULT hr;
5114
5115     TRACE("wined3d %p, desc1 %p, desc7 %p.\n", wined3d, desc1, desc7);
5116
5117     memset(&wined3d_caps, 0, sizeof(wined3d_caps));
5118
5119     EnterCriticalSection(&ddraw_cs);
5120     hr = IWineD3D_GetDeviceCaps(wined3d, 0, WINED3DDEVTYPE_HAL, &wined3d_caps);
5121     LeaveCriticalSection(&ddraw_cs);
5122     if (FAILED(hr))
5123     {
5124         WARN("Failed to get device caps, hr %#x.\n", hr);
5125         return hr;
5126     }
5127
5128     /* Copy the results into the d3d7 and d3d3 structures */
5129     desc7->dwDevCaps = wined3d_caps.DevCaps;
5130     desc7->dpcLineCaps.dwMiscCaps = wined3d_caps.PrimitiveMiscCaps;
5131     desc7->dpcLineCaps.dwRasterCaps = wined3d_caps.RasterCaps;
5132     desc7->dpcLineCaps.dwZCmpCaps = wined3d_caps.ZCmpCaps;
5133     desc7->dpcLineCaps.dwSrcBlendCaps = wined3d_caps.SrcBlendCaps;
5134     desc7->dpcLineCaps.dwDestBlendCaps = wined3d_caps.DestBlendCaps;
5135     desc7->dpcLineCaps.dwAlphaCmpCaps = wined3d_caps.AlphaCmpCaps;
5136     desc7->dpcLineCaps.dwShadeCaps = wined3d_caps.ShadeCaps;
5137     desc7->dpcLineCaps.dwTextureCaps = wined3d_caps.TextureCaps;
5138     desc7->dpcLineCaps.dwTextureFilterCaps = wined3d_caps.TextureFilterCaps;
5139     desc7->dpcLineCaps.dwTextureAddressCaps = wined3d_caps.TextureAddressCaps;
5140
5141     desc7->dwMaxTextureWidth = wined3d_caps.MaxTextureWidth;
5142     desc7->dwMaxTextureHeight = wined3d_caps.MaxTextureHeight;
5143
5144     desc7->dwMaxTextureRepeat = wined3d_caps.MaxTextureRepeat;
5145     desc7->dwMaxTextureAspectRatio = wined3d_caps.MaxTextureAspectRatio;
5146     desc7->dwMaxAnisotropy = wined3d_caps.MaxAnisotropy;
5147     desc7->dvMaxVertexW = wined3d_caps.MaxVertexW;
5148
5149     desc7->dvGuardBandLeft = wined3d_caps.GuardBandLeft;
5150     desc7->dvGuardBandTop = wined3d_caps.GuardBandTop;
5151     desc7->dvGuardBandRight = wined3d_caps.GuardBandRight;
5152     desc7->dvGuardBandBottom = wined3d_caps.GuardBandBottom;
5153
5154     desc7->dvExtentsAdjust = wined3d_caps.ExtentsAdjust;
5155     desc7->dwStencilCaps = wined3d_caps.StencilCaps;
5156
5157     desc7->dwFVFCaps = wined3d_caps.FVFCaps;
5158     desc7->dwTextureOpCaps = wined3d_caps.TextureOpCaps;
5159
5160     desc7->dwVertexProcessingCaps = wined3d_caps.VertexProcessingCaps;
5161     desc7->dwMaxActiveLights = wined3d_caps.MaxActiveLights;
5162
5163     /* Remove all non-d3d7 caps */
5164     desc7->dwDevCaps &= (
5165         D3DDEVCAPS_FLOATTLVERTEX         | D3DDEVCAPS_SORTINCREASINGZ          | D3DDEVCAPS_SORTDECREASINGZ          |
5166         D3DDEVCAPS_SORTEXACT             | D3DDEVCAPS_EXECUTESYSTEMMEMORY      | D3DDEVCAPS_EXECUTEVIDEOMEMORY       |
5167         D3DDEVCAPS_TLVERTEXSYSTEMMEMORY  | D3DDEVCAPS_TLVERTEXVIDEOMEMORY      | D3DDEVCAPS_TEXTURESYSTEMMEMORY      |
5168         D3DDEVCAPS_TEXTUREVIDEOMEMORY    | D3DDEVCAPS_DRAWPRIMTLVERTEX         | D3DDEVCAPS_CANRENDERAFTERFLIP       |
5169         D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_DRAWPRIMITIVES2          | D3DDEVCAPS_SEPARATETEXTUREMEMORIES  |
5170         D3DDEVCAPS_DRAWPRIMITIVES2EX     | D3DDEVCAPS_HWTRANSFORMANDLIGHT      | D3DDEVCAPS_CANBLTSYSTONONLOCAL      |
5171         D3DDEVCAPS_HWRASTERIZATION);
5172
5173     desc7->dwStencilCaps &= (
5174         D3DSTENCILCAPS_KEEP              | D3DSTENCILCAPS_ZERO                 | D3DSTENCILCAPS_REPLACE              |
5175         D3DSTENCILCAPS_INCRSAT           | D3DSTENCILCAPS_DECRSAT              | D3DSTENCILCAPS_INVERT               |
5176         D3DSTENCILCAPS_INCR              | D3DSTENCILCAPS_DECR);
5177
5178     /* FVF caps ?*/
5179
5180     desc7->dwTextureOpCaps &= (
5181         D3DTEXOPCAPS_DISABLE             | D3DTEXOPCAPS_SELECTARG1             | D3DTEXOPCAPS_SELECTARG2             |
5182         D3DTEXOPCAPS_MODULATE            | D3DTEXOPCAPS_MODULATE2X             | D3DTEXOPCAPS_MODULATE4X             |
5183         D3DTEXOPCAPS_ADD                 | D3DTEXOPCAPS_ADDSIGNED              | D3DTEXOPCAPS_ADDSIGNED2X            |
5184         D3DTEXOPCAPS_SUBTRACT            | D3DTEXOPCAPS_ADDSMOOTH              | D3DTEXOPCAPS_BLENDTEXTUREALPHA      |
5185         D3DTEXOPCAPS_BLENDFACTORALPHA    | D3DTEXOPCAPS_BLENDTEXTUREALPHAPM    | D3DTEXOPCAPS_BLENDCURRENTALPHA      |
5186         D3DTEXOPCAPS_PREMODULATE         | D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5187         D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | D3DTEXOPCAPS_BUMPENVMAP    |
5188         D3DTEXOPCAPS_BUMPENVMAPLUMINANCE | D3DTEXOPCAPS_DOTPRODUCT3);
5189
5190     desc7->dwVertexProcessingCaps &= (
5191         D3DVTXPCAPS_TEXGEN               | D3DVTXPCAPS_MATERIALSOURCE7         | D3DVTXPCAPS_VERTEXFOG               |
5192         D3DVTXPCAPS_DIRECTIONALLIGHTS    | D3DVTXPCAPS_POSITIONALLIGHTS        | D3DVTXPCAPS_LOCALVIEWER);
5193
5194     desc7->dpcLineCaps.dwMiscCaps &= (
5195         D3DPMISCCAPS_MASKPLANES          | D3DPMISCCAPS_MASKZ                  | D3DPMISCCAPS_LINEPATTERNREP         |
5196         D3DPMISCCAPS_CONFORMANT          | D3DPMISCCAPS_CULLNONE               | D3DPMISCCAPS_CULLCW                 |
5197         D3DPMISCCAPS_CULLCCW);
5198
5199     desc7->dpcLineCaps.dwRasterCaps &= (
5200         D3DPRASTERCAPS_DITHER            | D3DPRASTERCAPS_ROP2                 | D3DPRASTERCAPS_XOR                  |
5201         D3DPRASTERCAPS_PAT               | D3DPRASTERCAPS_ZTEST                | D3DPRASTERCAPS_SUBPIXEL             |
5202         D3DPRASTERCAPS_SUBPIXELX         | D3DPRASTERCAPS_FOGVERTEX            | D3DPRASTERCAPS_FOGTABLE             |
5203         D3DPRASTERCAPS_STIPPLE           | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT |
5204         D3DPRASTERCAPS_ANTIALIASEDGES    | D3DPRASTERCAPS_MIPMAPLODBIAS        | D3DPRASTERCAPS_ZBIAS                |
5205         D3DPRASTERCAPS_ZBUFFERLESSHSR    | D3DPRASTERCAPS_FOGRANGE             | D3DPRASTERCAPS_ANISOTROPY           |
5206         D3DPRASTERCAPS_WBUFFER           | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT | D3DPRASTERCAPS_WFOG           |
5207         D3DPRASTERCAPS_ZFOG);
5208
5209     desc7->dpcLineCaps.dwZCmpCaps &= (
5210         D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
5211         D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
5212         D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
5213
5214     desc7->dpcLineCaps.dwSrcBlendCaps &= (
5215         D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
5216         D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
5217         D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
5218         D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
5219         D3DPBLENDCAPS_BOTHINVSRCALPHA);
5220
5221     desc7->dpcLineCaps.dwDestBlendCaps &= (
5222         D3DPBLENDCAPS_ZERO               | D3DPBLENDCAPS_ONE                   | D3DPBLENDCAPS_SRCCOLOR              |
5223         D3DPBLENDCAPS_INVSRCCOLOR        | D3DPBLENDCAPS_SRCALPHA              | D3DPBLENDCAPS_INVSRCALPHA           |
5224         D3DPBLENDCAPS_DESTALPHA          | D3DPBLENDCAPS_INVDESTALPHA          | D3DPBLENDCAPS_DESTCOLOR             |
5225         D3DPBLENDCAPS_INVDESTCOLOR       | D3DPBLENDCAPS_SRCALPHASAT           | D3DPBLENDCAPS_BOTHSRCALPHA          |
5226         D3DPBLENDCAPS_BOTHINVSRCALPHA);
5227
5228     desc7->dpcLineCaps.dwAlphaCmpCaps &= (
5229         D3DPCMPCAPS_NEVER                | D3DPCMPCAPS_LESS                    | D3DPCMPCAPS_EQUAL                   |
5230         D3DPCMPCAPS_LESSEQUAL            | D3DPCMPCAPS_GREATER                 | D3DPCMPCAPS_NOTEQUAL                |
5231         D3DPCMPCAPS_GREATEREQUAL         | D3DPCMPCAPS_ALWAYS);
5232
5233     desc7->dpcLineCaps.dwShadeCaps &= (
5234         D3DPSHADECAPS_COLORFLATMONO      | D3DPSHADECAPS_COLORFLATRGB          | D3DPSHADECAPS_COLORGOURAUDMONO      |
5235         D3DPSHADECAPS_COLORGOURAUDRGB    | D3DPSHADECAPS_COLORPHONGMONO        | D3DPSHADECAPS_COLORPHONGRGB         |
5236         D3DPSHADECAPS_SPECULARFLATMONO   | D3DPSHADECAPS_SPECULARFLATRGB       | D3DPSHADECAPS_SPECULARGOURAUDMONO   |
5237         D3DPSHADECAPS_SPECULARGOURAUDRGB | D3DPSHADECAPS_SPECULARPHONGMONO     | D3DPSHADECAPS_SPECULARPHONGRGB      |
5238         D3DPSHADECAPS_ALPHAFLATBLEND     | D3DPSHADECAPS_ALPHAFLATSTIPPLED     | D3DPSHADECAPS_ALPHAGOURAUDBLEND     |
5239         D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND     | D3DPSHADECAPS_ALPHAPHONGSTIPPLED    |
5240         D3DPSHADECAPS_FOGFLAT            | D3DPSHADECAPS_FOGGOURAUD            | D3DPSHADECAPS_FOGPHONG);
5241
5242     desc7->dpcLineCaps.dwTextureCaps &= (
5243         D3DPTEXTURECAPS_PERSPECTIVE      | D3DPTEXTURECAPS_POW2                | D3DPTEXTURECAPS_ALPHA               |
5244         D3DPTEXTURECAPS_TRANSPARENCY     | D3DPTEXTURECAPS_BORDER              | D3DPTEXTURECAPS_SQUAREONLY          |
5245         D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE| D3DPTEXTURECAPS_NONPOW2CONDITIONAL  |
5246         D3DPTEXTURECAPS_PROJECTED        | D3DPTEXTURECAPS_CUBEMAP             | D3DPTEXTURECAPS_COLORKEYBLEND);
5247
5248     desc7->dpcLineCaps.dwTextureFilterCaps &= (
5249         D3DPTFILTERCAPS_NEAREST          | D3DPTFILTERCAPS_LINEAR              | D3DPTFILTERCAPS_MIPNEAREST          |
5250         D3DPTFILTERCAPS_MIPLINEAR        | D3DPTFILTERCAPS_LINEARMIPNEAREST    | D3DPTFILTERCAPS_LINEARMIPLINEAR     |
5251         D3DPTFILTERCAPS_MINFPOINT        | D3DPTFILTERCAPS_MINFLINEAR          | D3DPTFILTERCAPS_MINFANISOTROPIC     |
5252         D3DPTFILTERCAPS_MIPFPOINT        | D3DPTFILTERCAPS_MIPFLINEAR          | D3DPTFILTERCAPS_MAGFPOINT           |
5253         D3DPTFILTERCAPS_MAGFLINEAR       | D3DPTFILTERCAPS_MAGFANISOTROPIC     | D3DPTFILTERCAPS_MAGFAFLATCUBIC      |
5254         D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC);
5255
5256     desc7->dpcLineCaps.dwTextureBlendCaps &= (
5257         D3DPTBLENDCAPS_DECAL             | D3DPTBLENDCAPS_MODULATE             | D3DPTBLENDCAPS_DECALALPHA           |
5258         D3DPTBLENDCAPS_MODULATEALPHA     | D3DPTBLENDCAPS_DECALMASK            | D3DPTBLENDCAPS_MODULATEMASK         |
5259         D3DPTBLENDCAPS_COPY              | D3DPTBLENDCAPS_ADD);
5260
5261     desc7->dpcLineCaps.dwTextureAddressCaps &= (
5262         D3DPTADDRESSCAPS_WRAP            | D3DPTADDRESSCAPS_MIRROR             | D3DPTADDRESSCAPS_CLAMP              |
5263         D3DPTADDRESSCAPS_BORDER          | D3DPTADDRESSCAPS_INDEPENDENTUV);
5264
5265     if (!(desc7->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2))
5266     {
5267         /* DirectX7 always has the np2 flag set, no matter what the card
5268          * supports. Some old games (Rollcage) check the caps incorrectly.
5269          * If wined3d supports nonpow2 textures it also has np2 conditional
5270          * support. */
5271         desc7->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
5272     }
5273
5274     /* Fill the missing members, and do some fixup */
5275     desc7->dpcLineCaps.dwSize = sizeof(desc7->dpcLineCaps);
5276     desc7->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_MODULATEMASK |
5277                                             D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL |
5278                                             D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
5279                                             D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA;
5280     desc7->dpcLineCaps.dwStippleWidth = 32;
5281     desc7->dpcLineCaps.dwStippleHeight = 32;
5282     /* Use the same for the TriCaps */
5283     desc7->dpcTriCaps = desc7->dpcLineCaps;
5284
5285     desc7->dwDeviceRenderBitDepth = DDBD_16 | DDBD_24 | DDBD_32;
5286     desc7->dwDeviceZBufferBitDepth = DDBD_16 | DDBD_24;
5287     desc7->dwMinTextureWidth = 1;
5288     desc7->dwMinTextureHeight = 1;
5289
5290     /* Convert DWORDs safely to WORDs */
5291     if (wined3d_caps.MaxTextureBlendStages > 0xffff) desc7->wMaxTextureBlendStages = 0xffff;
5292     else desc7->wMaxTextureBlendStages = (WORD)wined3d_caps.MaxTextureBlendStages;
5293     if (wined3d_caps.MaxSimultaneousTextures > 0xffff) desc7->wMaxSimultaneousTextures = 0xffff;
5294     else desc7->wMaxSimultaneousTextures = (WORD)wined3d_caps.MaxSimultaneousTextures;
5295
5296     if (wined3d_caps.MaxUserClipPlanes > 0xffff) desc7->wMaxUserClipPlanes = 0xffff;
5297     else desc7->wMaxUserClipPlanes = (WORD)wined3d_caps.MaxUserClipPlanes;
5298     if (wined3d_caps.MaxVertexBlendMatrices > 0xffff) desc7->wMaxVertexBlendMatrices = 0xffff;
5299     else desc7->wMaxVertexBlendMatrices = (WORD)wined3d_caps.MaxVertexBlendMatrices;
5300
5301     desc7->deviceGUID = IID_IDirect3DTnLHalDevice;
5302
5303     desc7->dwReserved1 = 0;
5304     desc7->dwReserved2 = 0;
5305     desc7->dwReserved3 = 0;
5306     desc7->dwReserved4 = 0;
5307
5308     /* Fill the old structure */
5309     memset(desc1, 0, sizeof(*desc1));
5310     desc1->dwSize = sizeof(D3DDEVICEDESC);
5311     desc1->dwFlags = D3DDD_COLORMODEL
5312             | D3DDD_DEVCAPS
5313             | D3DDD_TRANSFORMCAPS
5314             | D3DDD_BCLIPPING
5315             | D3DDD_LIGHTINGCAPS
5316             | D3DDD_LINECAPS
5317             | D3DDD_TRICAPS
5318             | D3DDD_DEVICERENDERBITDEPTH
5319             | D3DDD_DEVICEZBUFFERBITDEPTH
5320             | D3DDD_MAXBUFFERSIZE
5321             | D3DDD_MAXVERTEXCOUNT;
5322
5323     desc1->dcmColorModel = D3DCOLOR_RGB;
5324     desc1->dwDevCaps = desc7->dwDevCaps;
5325     desc1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
5326     desc1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
5327     desc1->bClipping = TRUE;
5328     desc1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
5329     desc1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL
5330             | D3DLIGHTCAPS_PARALLELPOINT
5331             | D3DLIGHTCAPS_POINT
5332             | D3DLIGHTCAPS_SPOT;
5333
5334     desc1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
5335     desc1->dlcLightingCaps.dwNumLights = desc7->dwMaxActiveLights;
5336
5337     desc1->dpcLineCaps.dwSize = sizeof(D3DPRIMCAPS);
5338     desc1->dpcLineCaps.dwMiscCaps = desc7->dpcLineCaps.dwMiscCaps;
5339     desc1->dpcLineCaps.dwRasterCaps = desc7->dpcLineCaps.dwRasterCaps;
5340     desc1->dpcLineCaps.dwZCmpCaps = desc7->dpcLineCaps.dwZCmpCaps;
5341     desc1->dpcLineCaps.dwSrcBlendCaps = desc7->dpcLineCaps.dwSrcBlendCaps;
5342     desc1->dpcLineCaps.dwDestBlendCaps = desc7->dpcLineCaps.dwDestBlendCaps;
5343     desc1->dpcLineCaps.dwShadeCaps = desc7->dpcLineCaps.dwShadeCaps;
5344     desc1->dpcLineCaps.dwTextureCaps = desc7->dpcLineCaps.dwTextureCaps;
5345     desc1->dpcLineCaps.dwTextureFilterCaps = desc7->dpcLineCaps.dwTextureFilterCaps;
5346     desc1->dpcLineCaps.dwTextureBlendCaps = desc7->dpcLineCaps.dwTextureBlendCaps;
5347     desc1->dpcLineCaps.dwTextureAddressCaps = desc7->dpcLineCaps.dwTextureAddressCaps;
5348     desc1->dpcLineCaps.dwStippleWidth = desc7->dpcLineCaps.dwStippleWidth;
5349     desc1->dpcLineCaps.dwAlphaCmpCaps = desc7->dpcLineCaps.dwAlphaCmpCaps;
5350
5351     desc1->dpcTriCaps.dwSize = sizeof(D3DPRIMCAPS);
5352     desc1->dpcTriCaps.dwMiscCaps = desc7->dpcTriCaps.dwMiscCaps;
5353     desc1->dpcTriCaps.dwRasterCaps = desc7->dpcTriCaps.dwRasterCaps;
5354     desc1->dpcTriCaps.dwZCmpCaps = desc7->dpcTriCaps.dwZCmpCaps;
5355     desc1->dpcTriCaps.dwSrcBlendCaps = desc7->dpcTriCaps.dwSrcBlendCaps;
5356     desc1->dpcTriCaps.dwDestBlendCaps = desc7->dpcTriCaps.dwDestBlendCaps;
5357     desc1->dpcTriCaps.dwShadeCaps = desc7->dpcTriCaps.dwShadeCaps;
5358     desc1->dpcTriCaps.dwTextureCaps = desc7->dpcTriCaps.dwTextureCaps;
5359     desc1->dpcTriCaps.dwTextureFilterCaps = desc7->dpcTriCaps.dwTextureFilterCaps;
5360     desc1->dpcTriCaps.dwTextureBlendCaps = desc7->dpcTriCaps.dwTextureBlendCaps;
5361     desc1->dpcTriCaps.dwTextureAddressCaps = desc7->dpcTriCaps.dwTextureAddressCaps;
5362     desc1->dpcTriCaps.dwStippleWidth = desc7->dpcTriCaps.dwStippleWidth;
5363     desc1->dpcTriCaps.dwAlphaCmpCaps = desc7->dpcTriCaps.dwAlphaCmpCaps;
5364
5365     desc1->dwDeviceRenderBitDepth = desc7->dwDeviceRenderBitDepth;
5366     desc1->dwDeviceZBufferBitDepth = desc7->dwDeviceZBufferBitDepth;
5367     desc1->dwMaxBufferSize = 0;
5368     desc1->dwMaxVertexCount = 65536;
5369     desc1->dwMinTextureWidth  = desc7->dwMinTextureWidth;
5370     desc1->dwMinTextureHeight = desc7->dwMinTextureHeight;
5371     desc1->dwMaxTextureWidth  = desc7->dwMaxTextureWidth;
5372     desc1->dwMaxTextureHeight = desc7->dwMaxTextureHeight;
5373     desc1->dwMinStippleWidth  = 1;
5374     desc1->dwMinStippleHeight = 1;
5375     desc1->dwMaxStippleWidth  = 32;
5376     desc1->dwMaxStippleHeight = 32;
5377     desc1->dwMaxTextureRepeat = desc7->dwMaxTextureRepeat;
5378     desc1->dwMaxTextureAspectRatio = desc7->dwMaxTextureAspectRatio;
5379     desc1->dwMaxAnisotropy = desc7->dwMaxAnisotropy;
5380     desc1->dvGuardBandLeft = desc7->dvGuardBandLeft;
5381     desc1->dvGuardBandRight = desc7->dvGuardBandRight;
5382     desc1->dvGuardBandTop = desc7->dvGuardBandTop;
5383     desc1->dvGuardBandBottom = desc7->dvGuardBandBottom;
5384     desc1->dvExtentsAdjust = desc7->dvExtentsAdjust;
5385     desc1->dwStencilCaps = desc7->dwStencilCaps;
5386     desc1->dwFVFCaps = desc7->dwFVFCaps;
5387     desc1->dwTextureOpCaps = desc7->dwTextureOpCaps;
5388     desc1->wMaxTextureBlendStages = desc7->wMaxTextureBlendStages;
5389     desc1->wMaxSimultaneousTextures = desc7->wMaxSimultaneousTextures;
5390
5391     return DD_OK;
5392 }
5393
5394 /*****************************************************************************
5395  * IDirectDraw7 VTable
5396  *****************************************************************************/
5397 static const struct IDirectDraw7Vtbl ddraw7_vtbl =
5398 {
5399     /* IUnknown */
5400     ddraw7_QueryInterface,
5401     ddraw7_AddRef,
5402     ddraw7_Release,
5403     /* IDirectDraw */
5404     ddraw7_Compact,
5405     ddraw7_CreateClipper,
5406     ddraw7_CreatePalette,
5407     ddraw7_CreateSurface,
5408     ddraw7_DuplicateSurface,
5409     ddraw7_EnumDisplayModes,
5410     ddraw7_EnumSurfaces,
5411     ddraw7_FlipToGDISurface,
5412     ddraw7_GetCaps,
5413     ddraw7_GetDisplayMode,
5414     ddraw7_GetFourCCCodes,
5415     ddraw7_GetGDISurface,
5416     ddraw7_GetMonitorFrequency,
5417     ddraw7_GetScanLine,
5418     ddraw7_GetVerticalBlankStatus,
5419     ddraw7_Initialize,
5420     ddraw7_RestoreDisplayMode,
5421     ddraw7_SetCooperativeLevel,
5422     ddraw7_SetDisplayMode,
5423     ddraw7_WaitForVerticalBlank,
5424     /* IDirectDraw2 */
5425     ddraw7_GetAvailableVidMem,
5426     /* IDirectDraw3 */
5427     ddraw7_GetSurfaceFromDC,
5428     /* IDirectDraw4 */
5429     ddraw7_RestoreAllSurfaces,
5430     ddraw7_TestCooperativeLevel,
5431     ddraw7_GetDeviceIdentifier,
5432     /* IDirectDraw7 */
5433     ddraw7_StartModeTest,
5434     ddraw7_EvaluateMode
5435 };
5436
5437 static const struct IDirectDraw4Vtbl ddraw4_vtbl =
5438 {
5439     /* IUnknown */
5440     ddraw4_QueryInterface,
5441     ddraw4_AddRef,
5442     ddraw4_Release,
5443     /* IDirectDraw */
5444     ddraw4_Compact,
5445     ddraw4_CreateClipper,
5446     ddraw4_CreatePalette,
5447     ddraw4_CreateSurface,
5448     ddraw4_DuplicateSurface,
5449     ddraw4_EnumDisplayModes,
5450     ddraw4_EnumSurfaces,
5451     ddraw4_FlipToGDISurface,
5452     ddraw4_GetCaps,
5453     ddraw4_GetDisplayMode,
5454     ddraw4_GetFourCCCodes,
5455     ddraw4_GetGDISurface,
5456     ddraw4_GetMonitorFrequency,
5457     ddraw4_GetScanLine,
5458     ddraw4_GetVerticalBlankStatus,
5459     ddraw4_Initialize,
5460     ddraw4_RestoreDisplayMode,
5461     ddraw4_SetCooperativeLevel,
5462     ddraw4_SetDisplayMode,
5463     ddraw4_WaitForVerticalBlank,
5464     /* IDirectDraw2 */
5465     ddraw4_GetAvailableVidMem,
5466     /* IDirectDraw3 */
5467     ddraw4_GetSurfaceFromDC,
5468     /* IDirectDraw4 */
5469     ddraw4_RestoreAllSurfaces,
5470     ddraw4_TestCooperativeLevel,
5471     ddraw4_GetDeviceIdentifier,
5472 };
5473
5474 static const struct IDirectDraw3Vtbl ddraw3_vtbl =
5475 {
5476     /* IUnknown */
5477     ddraw3_QueryInterface,
5478     ddraw3_AddRef,
5479     ddraw3_Release,
5480     /* IDirectDraw */
5481     ddraw3_Compact,
5482     ddraw3_CreateClipper,
5483     ddraw3_CreatePalette,
5484     ddraw3_CreateSurface,
5485     ddraw3_DuplicateSurface,
5486     ddraw3_EnumDisplayModes,
5487     ddraw3_EnumSurfaces,
5488     ddraw3_FlipToGDISurface,
5489     ddraw3_GetCaps,
5490     ddraw3_GetDisplayMode,
5491     ddraw3_GetFourCCCodes,
5492     ddraw3_GetGDISurface,
5493     ddraw3_GetMonitorFrequency,
5494     ddraw3_GetScanLine,
5495     ddraw3_GetVerticalBlankStatus,
5496     ddraw3_Initialize,
5497     ddraw3_RestoreDisplayMode,
5498     ddraw3_SetCooperativeLevel,
5499     ddraw3_SetDisplayMode,
5500     ddraw3_WaitForVerticalBlank,
5501     /* IDirectDraw2 */
5502     ddraw3_GetAvailableVidMem,
5503     /* IDirectDraw3 */
5504     ddraw3_GetSurfaceFromDC,
5505 };
5506
5507 static const struct IDirectDraw2Vtbl ddraw2_vtbl =
5508 {
5509     /* IUnknown */
5510     ddraw2_QueryInterface,
5511     ddraw2_AddRef,
5512     ddraw2_Release,
5513     /* IDirectDraw */
5514     ddraw2_Compact,
5515     ddraw2_CreateClipper,
5516     ddraw2_CreatePalette,
5517     ddraw2_CreateSurface,
5518     ddraw2_DuplicateSurface,
5519     ddraw2_EnumDisplayModes,
5520     ddraw2_EnumSurfaces,
5521     ddraw2_FlipToGDISurface,
5522     ddraw2_GetCaps,
5523     ddraw2_GetDisplayMode,
5524     ddraw2_GetFourCCCodes,
5525     ddraw2_GetGDISurface,
5526     ddraw2_GetMonitorFrequency,
5527     ddraw2_GetScanLine,
5528     ddraw2_GetVerticalBlankStatus,
5529     ddraw2_Initialize,
5530     ddraw2_RestoreDisplayMode,
5531     ddraw2_SetCooperativeLevel,
5532     ddraw2_SetDisplayMode,
5533     ddraw2_WaitForVerticalBlank,
5534     /* IDirectDraw2 */
5535     ddraw2_GetAvailableVidMem,
5536 };
5537
5538 static const struct IDirectDrawVtbl ddraw1_vtbl =
5539 {
5540     /* IUnknown */
5541     ddraw1_QueryInterface,
5542     ddraw1_AddRef,
5543     ddraw1_Release,
5544     /* IDirectDraw */
5545     ddraw1_Compact,
5546     ddraw1_CreateClipper,
5547     ddraw1_CreatePalette,
5548     ddraw1_CreateSurface,
5549     ddraw1_DuplicateSurface,
5550     ddraw1_EnumDisplayModes,
5551     ddraw1_EnumSurfaces,
5552     ddraw1_FlipToGDISurface,
5553     ddraw1_GetCaps,
5554     ddraw1_GetDisplayMode,
5555     ddraw1_GetFourCCCodes,
5556     ddraw1_GetGDISurface,
5557     ddraw1_GetMonitorFrequency,
5558     ddraw1_GetScanLine,
5559     ddraw1_GetVerticalBlankStatus,
5560     ddraw1_Initialize,
5561     ddraw1_RestoreDisplayMode,
5562     ddraw1_SetCooperativeLevel,
5563     ddraw1_SetDisplayMode,
5564     ddraw1_WaitForVerticalBlank,
5565 };
5566
5567 static const struct IDirect3D7Vtbl d3d7_vtbl =
5568 {
5569     /* IUnknown methods */
5570     d3d7_QueryInterface,
5571     d3d7_AddRef,
5572     d3d7_Release,
5573     /* IDirect3D7 methods */
5574     d3d7_EnumDevices,
5575     d3d7_CreateDevice,
5576     d3d7_CreateVertexBuffer,
5577     d3d7_EnumZBufferFormats,
5578     d3d7_EvictManagedTextures
5579 };
5580
5581 static const struct IDirect3D3Vtbl d3d3_vtbl =
5582 {
5583     /* IUnknown methods */
5584     d3d3_QueryInterface,
5585     d3d3_AddRef,
5586     d3d3_Release,
5587     /* IDirect3D3 methods */
5588     d3d3_EnumDevices,
5589     d3d3_CreateLight,
5590     d3d3_CreateMaterial,
5591     d3d3_CreateViewport,
5592     d3d3_FindDevice,
5593     d3d3_CreateDevice,
5594     d3d3_CreateVertexBuffer,
5595     d3d3_EnumZBufferFormats,
5596     d3d3_EvictManagedTextures
5597 };
5598
5599 static const struct IDirect3D2Vtbl d3d2_vtbl =
5600 {
5601     /* IUnknown methods */
5602     d3d2_QueryInterface,
5603     d3d2_AddRef,
5604     d3d2_Release,
5605     /* IDirect3D2 methods */
5606     d3d2_EnumDevices,
5607     d3d2_CreateLight,
5608     d3d2_CreateMaterial,
5609     d3d2_CreateViewport,
5610     d3d2_FindDevice,
5611     d3d2_CreateDevice
5612 };
5613
5614 static const struct IDirect3DVtbl d3d1_vtbl =
5615 {
5616     /* IUnknown methods */
5617     d3d1_QueryInterface,
5618     d3d1_AddRef,
5619     d3d1_Release,
5620     /* IDirect3D methods */
5621     d3d1_Initialize,
5622     d3d1_EnumDevices,
5623     d3d1_CreateLight,
5624     d3d1_CreateMaterial,
5625     d3d1_CreateViewport,
5626     d3d1_FindDevice
5627 };
5628
5629 /*****************************************************************************
5630  * ddraw_find_decl
5631  *
5632  * Finds the WineD3D vertex declaration for a specific fvf, and creates one
5633  * if none was found.
5634  *
5635  * This function is in ddraw.c and the DDraw object space because D3D7
5636  * vertex buffers are created using the IDirect3D interface to the ddraw
5637  * object, so they can be valid across D3D devices(theoretically. The ddraw
5638  * object also owns the wined3d device
5639  *
5640  * Parameters:
5641  *  This: Device
5642  *  fvf: Fvf to find the decl for
5643  *
5644  * Returns:
5645  *  NULL in case of an error, the IWineD3DVertexDeclaration interface for the
5646  *  fvf otherwise.
5647  *
5648  *****************************************************************************/
5649 IWineD3DVertexDeclaration *ddraw_find_decl(IDirectDrawImpl *This, DWORD fvf)
5650 {
5651     HRESULT hr;
5652     IWineD3DVertexDeclaration* pDecl = NULL;
5653     int p, low, high; /* deliberately signed */
5654     struct FvfToDecl *convertedDecls = This->decls;
5655
5656     TRACE("Searching for declaration for fvf %08x... ", fvf);
5657
5658     low = 0;
5659     high = This->numConvertedDecls - 1;
5660     while(low <= high) {
5661         p = (low + high) >> 1;
5662         TRACE("%d ", p);
5663         if(convertedDecls[p].fvf == fvf) {
5664             TRACE("found %p\n", convertedDecls[p].decl);
5665             return convertedDecls[p].decl;
5666         } else if(convertedDecls[p].fvf < fvf) {
5667             low = p + 1;
5668         } else {
5669             high = p - 1;
5670         }
5671     }
5672     TRACE("not found. Creating and inserting at position %d.\n", low);
5673
5674     hr = IWineD3DDevice_CreateVertexDeclarationFromFVF(This->wineD3DDevice,
5675             fvf, This, &ddraw_null_wined3d_parent_ops, &pDecl);
5676     if (hr != S_OK) return NULL;
5677
5678     if(This->declArraySize == This->numConvertedDecls) {
5679         int grow = max(This->declArraySize / 2, 8);
5680         convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
5681                                      sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
5682         if(!convertedDecls) {
5683             /* This will destroy it */
5684             IWineD3DVertexDeclaration_Release(pDecl);
5685             return NULL;
5686         }
5687         This->decls = convertedDecls;
5688         This->declArraySize += grow;
5689     }
5690
5691     memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(convertedDecls[0]) * (This->numConvertedDecls - low));
5692     convertedDecls[low].decl = pDecl;
5693     convertedDecls[low].fvf = fvf;
5694     This->numConvertedDecls++;
5695
5696     TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
5697     return pDecl;
5698 }
5699
5700 /* IWineD3DDeviceParent IUnknown methods */
5701
5702 static inline struct IDirectDrawImpl *ddraw_from_device_parent(IWineD3DDeviceParent *iface)
5703 {
5704     return (struct IDirectDrawImpl *)((char*)iface - FIELD_OFFSET(struct IDirectDrawImpl, device_parent_vtbl));
5705 }
5706
5707 static HRESULT STDMETHODCALLTYPE device_parent_QueryInterface(IWineD3DDeviceParent *iface, REFIID riid, void **object)
5708 {
5709     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5710     return ddraw7_QueryInterface((IDirectDraw7 *)This, riid, object);
5711 }
5712
5713 static ULONG STDMETHODCALLTYPE device_parent_AddRef(IWineD3DDeviceParent *iface)
5714 {
5715     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5716     return ddraw7_AddRef((IDirectDraw7 *)This);
5717 }
5718
5719 static ULONG STDMETHODCALLTYPE device_parent_Release(IWineD3DDeviceParent *iface)
5720 {
5721     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5722     return ddraw7_Release((IDirectDraw7 *)This);
5723 }
5724
5725 /* IWineD3DDeviceParent methods */
5726
5727 static void STDMETHODCALLTYPE device_parent_WineD3DDeviceCreated(IWineD3DDeviceParent *iface, IWineD3DDevice *device)
5728 {
5729     TRACE("iface %p, device %p\n", iface, device);
5730 }
5731
5732 static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParent *iface,
5733         IUnknown *superior, UINT width, UINT height, enum wined3d_format_id format, DWORD usage,
5734         WINED3DPOOL pool, UINT level, WINED3DCUBEMAP_FACES face, IWineD3DSurface **surface)
5735 {
5736     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5737     IDirectDrawSurfaceImpl *surf = NULL;
5738     UINT i = 0;
5739     DDSCAPS2 searchcaps = This->tex_root->surface_desc.ddsCaps;
5740
5741     TRACE("iface %p, superior %p, width %u, height %u, format %#x, usage %#x,\n"
5742             "\tpool %#x, level %u, face %u, surface %p\n",
5743             iface, superior, width, height, format, usage, pool, level, face, surface);
5744
5745     searchcaps.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
5746     switch(face)
5747     {
5748         case WINED3DCUBEMAP_FACE_POSITIVE_X:
5749             TRACE("Asked for positive x\n");
5750             if (searchcaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5751             {
5752                 searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEX;
5753             }
5754             surf = This->tex_root; break;
5755         case WINED3DCUBEMAP_FACE_NEGATIVE_X:
5756             TRACE("Asked for negative x\n");
5757             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEX; break;
5758         case WINED3DCUBEMAP_FACE_POSITIVE_Y:
5759             TRACE("Asked for positive y\n");
5760             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEY; break;
5761         case WINED3DCUBEMAP_FACE_NEGATIVE_Y:
5762             TRACE("Asked for negative y\n");
5763             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEY; break;
5764         case WINED3DCUBEMAP_FACE_POSITIVE_Z:
5765             TRACE("Asked for positive z\n");
5766             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_POSITIVEZ; break;
5767         case WINED3DCUBEMAP_FACE_NEGATIVE_Z:
5768             TRACE("Asked for negative z\n");
5769             searchcaps.dwCaps2 |= DDSCAPS2_CUBEMAP_NEGATIVEZ; break;
5770         default: {ERR("Unexpected cube face\n");} /* Stupid compiler */
5771     }
5772
5773     if (!surf)
5774     {
5775         IDirectDrawSurface7 *attached;
5776         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->tex_root, &searchcaps, &attached);
5777         surf = (IDirectDrawSurfaceImpl *)attached;
5778         IDirectDrawSurface7_Release(attached);
5779     }
5780     if (!surf) ERR("root search surface not found\n");
5781
5782     /* Find the wanted mipmap. There are enough mipmaps in the chain */
5783     while (i < level)
5784     {
5785         IDirectDrawSurface7 *attached;
5786         IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)surf, &searchcaps, &attached);
5787         if(!attached) ERR("Surface not found\n");
5788         surf = (IDirectDrawSurfaceImpl *)attached;
5789         IDirectDrawSurface7_Release(attached);
5790         ++i;
5791     }
5792
5793     /* Return the surface */
5794     *surface = surf->WineD3DSurface;
5795     IWineD3DSurface_AddRef(*surface);
5796
5797     TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, surf);
5798
5799     return D3D_OK;
5800 }
5801
5802 static HRESULT WINAPI findRenderTarget(IDirectDrawSurface7 *surface, DDSURFACEDESC2 *surface_desc, void *ctx)
5803 {
5804     IDirectDrawSurfaceImpl *s = (IDirectDrawSurfaceImpl *)surface;
5805     IDirectDrawSurfaceImpl **target = ctx;
5806
5807     if (!s->isRenderTarget)
5808     {
5809         *target = s;
5810         IDirectDrawSurface7_Release(surface);
5811         return DDENUMRET_CANCEL;
5812     }
5813
5814     /* Recurse into the surface tree */
5815     IDirectDrawSurface7_EnumAttachedSurfaces(surface, ctx, findRenderTarget);
5816
5817     IDirectDrawSurface7_Release(surface);
5818     if (*target) return DDENUMRET_CANCEL;
5819
5820     return DDENUMRET_OK;
5821 }
5822
5823 static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDeviceParent *iface,
5824         IUnknown *superior, UINT width, UINT height, enum wined3d_format_id format,
5825         WINED3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality, BOOL lockable,
5826         IWineD3DSurface **surface)
5827 {
5828     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5829     IDirectDrawSurfaceImpl *d3d_surface = This->d3d_target;
5830     IDirectDrawSurfaceImpl *target = NULL;
5831
5832     TRACE("iface %p, superior %p, width %u, height %u, format %#x, multisample_type %#x,\n"
5833             "\tmultisample_quality %u, lockable %u, surface %p\n",
5834             iface, superior, width, height, format, multisample_type, multisample_quality, lockable, surface);
5835
5836     if (d3d_surface->isRenderTarget)
5837     {
5838         IDirectDrawSurface7_EnumAttachedSurfaces((IDirectDrawSurface7 *)d3d_surface, &target, findRenderTarget);
5839     }
5840     else
5841     {
5842         target = d3d_surface;
5843     }
5844
5845     if (!target)
5846     {
5847         target = This->d3d_target;
5848         ERR(" (%p) : No DirectDrawSurface found to create the back buffer. Using the front buffer as back buffer. Uncertain consequences\n", This);
5849     }
5850
5851     /* TODO: Return failure if the dimensions do not match, but this shouldn't happen */
5852
5853     *surface = target->WineD3DSurface;
5854     IWineD3DSurface_AddRef(*surface);
5855     target->isRenderTarget = TRUE;
5856
5857     TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, d3d_surface);
5858
5859     return D3D_OK;
5860 }
5861
5862 static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3DDeviceParent *iface,
5863         UINT width, UINT height, enum wined3d_format_id format, WINED3DMULTISAMPLE_TYPE multisample_type,
5864         DWORD multisample_quality, BOOL discard, IWineD3DSurface **surface)
5865 {
5866     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5867     IDirectDrawSurfaceImpl *ddraw_surface;
5868     DDSURFACEDESC2 ddsd;
5869     HRESULT hr;
5870
5871     TRACE("iface %p, width %u, height %u, format %#x, multisample_type %#x,\n"
5872             "\tmultisample_quality %u, discard %u, surface %p\n",
5873             iface, width, height, format, multisample_type, multisample_quality, discard, surface);
5874
5875     *surface = NULL;
5876
5877     /* Create a DirectDraw surface */
5878     memset(&ddsd, 0, sizeof(ddsd));
5879     ddsd.dwSize = sizeof(ddsd);
5880     ddsd.u4.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
5881     ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5882     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
5883     ddsd.dwHeight = height;
5884     ddsd.dwWidth = width;
5885     if (format)
5886     {
5887         PixelFormat_WineD3DtoDD(&ddsd.u4.ddpfPixelFormat, format);
5888     }
5889     else
5890     {
5891         ddsd.dwFlags ^= DDSD_PIXELFORMAT;
5892     }
5893
5894     This->depthstencil = TRUE;
5895     hr = IDirectDraw7_CreateSurface((IDirectDraw7 *)This, &ddsd, (IDirectDrawSurface7 **)&ddraw_surface, NULL);
5896     This->depthstencil = FALSE;
5897     if(FAILED(hr))
5898     {
5899         ERR(" (%p) Creating a DepthStencil Surface failed, result = %x\n", This, hr);
5900         return hr;
5901     }
5902
5903     *surface = ddraw_surface->WineD3DSurface;
5904     IWineD3DSurface_AddRef(*surface);
5905     IDirectDrawSurface7_Release((IDirectDrawSurface7 *)ddraw_surface);
5906
5907     return D3D_OK;
5908 }
5909
5910 static HRESULT STDMETHODCALLTYPE device_parent_CreateVolume(IWineD3DDeviceParent *iface,
5911         IUnknown *superior, UINT width, UINT height, UINT depth, enum wined3d_format_id format,
5912         WINED3DPOOL pool, DWORD usage, IWineD3DVolume **volume)
5913 {
5914     TRACE("iface %p, superior %p, width %u, height %u, depth %u, format %#x, pool %#x, usage %#x, volume %p\n",
5915                 iface, superior, width, height, depth, format, pool, usage, volume);
5916
5917     ERR("Not implemented!\n");
5918
5919     return E_NOTIMPL;
5920 }
5921
5922 static HRESULT STDMETHODCALLTYPE device_parent_CreateSwapChain(IWineD3DDeviceParent *iface,
5923         WINED3DPRESENT_PARAMETERS *present_parameters, IWineD3DSwapChain **swapchain)
5924 {
5925     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
5926     IDirectDrawSurfaceImpl *iterator;
5927     IParentImpl *object;
5928     HRESULT hr;
5929
5930     TRACE("iface %p, present_parameters %p, swapchain %p\n", iface, present_parameters, swapchain);
5931
5932     object = HeapAlloc(GetProcessHeap(),  HEAP_ZERO_MEMORY, sizeof(IParentImpl));
5933     if (!object)
5934     {
5935         FIXME("Allocation of memory failed\n");
5936         *swapchain = NULL;
5937         return DDERR_OUTOFVIDEOMEMORY;
5938     }
5939
5940     ddraw_parent_init(object);
5941
5942     hr = IWineD3DDevice_CreateSwapChain(This->wineD3DDevice, present_parameters,
5943             This->ImplType, object, swapchain);
5944     if (FAILED(hr))
5945     {
5946         FIXME("(%p) CreateSwapChain failed, returning %#x\n", iface, hr);
5947         HeapFree(GetProcessHeap(), 0 , object);
5948         *swapchain = NULL;
5949         return hr;
5950     }
5951
5952     object->child = (IUnknown *)*swapchain;
5953     This->d3d_target->wineD3DSwapChain = *swapchain;
5954     iterator = This->d3d_target->complex_array[0];
5955     while (iterator)
5956     {
5957         iterator->wineD3DSwapChain = *swapchain;
5958         iterator = iterator->complex_array[0];
5959     }
5960
5961     return hr;
5962 }
5963
5964 static const IWineD3DDeviceParentVtbl ddraw_wined3d_device_parent_vtbl =
5965 {
5966     /* IUnknown methods */
5967     device_parent_QueryInterface,
5968     device_parent_AddRef,
5969     device_parent_Release,
5970     /* IWineD3DDeviceParent methods */
5971     device_parent_WineD3DDeviceCreated,
5972     device_parent_CreateSurface,
5973     device_parent_CreateRenderTarget,
5974     device_parent_CreateDepthStencilSurface,
5975     device_parent_CreateVolume,
5976     device_parent_CreateSwapChain,
5977 };
5978
5979 HRESULT ddraw_init(IDirectDrawImpl *ddraw, WINED3DDEVTYPE device_type)
5980 {
5981     HRESULT hr;
5982     HDC hDC;
5983
5984     ddraw->lpVtbl = &ddraw7_vtbl;
5985     ddraw->IDirectDraw_iface.lpVtbl = &ddraw1_vtbl;
5986     ddraw->IDirectDraw2_iface.lpVtbl = &ddraw2_vtbl;
5987     ddraw->IDirectDraw3_iface.lpVtbl = &ddraw3_vtbl;
5988     ddraw->IDirectDraw4_iface.lpVtbl = &ddraw4_vtbl;
5989     ddraw->IDirect3D_iface.lpVtbl = &d3d1_vtbl;
5990     ddraw->IDirect3D2_iface.lpVtbl = &d3d2_vtbl;
5991     ddraw->IDirect3D3_iface.lpVtbl = &d3d3_vtbl;
5992     ddraw->IDirect3D7_iface.lpVtbl = &d3d7_vtbl;
5993     ddraw->device_parent_vtbl = &ddraw_wined3d_device_parent_vtbl;
5994     ddraw->numIfaces = 1;
5995     ddraw->ref7 = 1;
5996
5997     /* See comments in IDirectDrawImpl_CreateNewSurface for a description of
5998      * this field. */
5999     ddraw->ImplType = DefaultSurfaceType;
6000
6001     /* Get the current screen settings. */
6002     hDC = GetDC(0);
6003     ddraw->orig_bpp = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
6004     ReleaseDC(0, hDC);
6005     ddraw->orig_width = GetSystemMetrics(SM_CXSCREEN);
6006     ddraw->orig_height = GetSystemMetrics(SM_CYSCREEN);
6007
6008     if (!LoadWineD3D())
6009     {
6010         ERR("Failed to load wined3d - broken OpenGL setup?\n");
6011         return DDERR_NODIRECTDRAWSUPPORT;
6012     }
6013
6014     ddraw->wineD3D = pWineDirect3DCreate(7, (IUnknown *)ddraw);
6015     if (!ddraw->wineD3D)
6016     {
6017         WARN("Failed to create a wined3d object.\n");
6018         return E_OUTOFMEMORY;
6019     }
6020
6021     hr = IWineD3D_CreateDevice(ddraw->wineD3D, WINED3DADAPTER_DEFAULT, device_type, NULL, 0,
6022             (IWineD3DDeviceParent *)&ddraw->device_parent_vtbl, &ddraw->wineD3DDevice);
6023     if (FAILED(hr))
6024     {
6025         WARN("Failed to create a wined3d device, hr %#x.\n", hr);
6026         IWineD3D_Release(ddraw->wineD3D);
6027         return hr;
6028     }
6029
6030     /* Get the amount of video memory */
6031     ddraw->total_vidmem = IWineD3DDevice_GetAvailableTextureMem(ddraw->wineD3DDevice);
6032
6033     list_init(&ddraw->surface_list);
6034
6035     return DD_OK;
6036 }