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