[PATCH 2/5] ddraw: Version 1 devices are aggregated by the surface that created them.

Henri Verbeet hverbeet at codeweavers.com
Thu Apr 5 12:55:35 CDT 2012


---
 dlls/ddraw/ddraw.c         |    6 +-
 dlls/ddraw/ddraw_private.h |    6 +-
 dlls/ddraw/device.c        |  268 +++++++++++++++++++++++--------------------
 dlls/ddraw/surface.c       |   24 +++--
 dlls/ddraw/tests/d3d.c     |    1 -
 5 files changed, 165 insertions(+), 140 deletions(-)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 9d68fc9..20df445 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -4426,7 +4426,7 @@ static HRESULT WINAPI d3d7_CreateDevice(IDirect3D7 *iface, REFCLSID riid,
     TRACE("iface %p, riid %s, surface %p, device %p.\n", iface, debugstr_guid(riid), surface, device);
 
     wined3d_mutex_lock();
-    hr = d3d_device_create(ddraw, target, 7, &object);
+    hr = d3d_device_create(ddraw, target, 7, &object, NULL);
     if (SUCCEEDED(hr))
         *device = &object->IDirect3DDevice7_iface;
     else
@@ -4454,7 +4454,7 @@ static HRESULT WINAPI d3d3_CreateDevice(IDirect3D3 *iface, REFCLSID riid,
         return CLASS_E_NOAGGREGATION;
 
     wined3d_mutex_lock();
-    hr = d3d_device_create(ddraw, surface_impl, 3, &device_impl);
+    hr = d3d_device_create(ddraw, surface_impl, 3, &device_impl, NULL);
     if (SUCCEEDED(hr))
         *device = &device_impl->IDirect3DDevice3_iface;
     else
@@ -4479,7 +4479,7 @@ static HRESULT WINAPI d3d2_CreateDevice(IDirect3D2 *iface, REFCLSID riid,
             iface, debugstr_guid(riid), surface, device);
 
     wined3d_mutex_lock();
-    hr = d3d_device_create(ddraw, surface_impl, 2, &device_impl);
+    hr = d3d_device_create(ddraw, surface_impl, 2, &device_impl, NULL);
     if (SUCCEEDED(hr))
         *device = &device_impl->IDirect3DDevice2_iface;
     else
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index d7873e8..3509f58 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -159,6 +159,7 @@ struct ddraw_surface
     struct ddraw *ddraw;
     struct wined3d_surface *wined3d_surface;
     struct wined3d_texture *wined3d_texture;
+    IDirect3DDeviceImpl *device1;
 
     /* This implementation handles attaching surfaces to other surfaces */
     struct ddraw_surface *next_attached;
@@ -278,10 +279,11 @@ struct IDirect3DDeviceImpl
     IDirect3DDevice3 IDirect3DDevice3_iface;
     IDirect3DDevice2 IDirect3DDevice2_iface;
     IDirect3DDevice IDirect3DDevice_iface;
+    IUnknown IUnknown_inner;
     LONG ref;
     UINT version;
 
-    /* Other object connections */
+    IUnknown *outer_unknown;
     struct wined3d_device *wined3d_device;
     struct ddraw *ddraw;
     struct wined3d_buffer *indexbuffer;
@@ -316,7 +318,7 @@ struct IDirect3DDeviceImpl
 };
 
 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
-        UINT version, IDirect3DDeviceImpl **device) DECLSPEC_HIDDEN;
+        UINT version, IDirect3DDeviceImpl **device, IUnknown *outer_unknown) DECLSPEC_HIDDEN;
 
 /* The IID */
 extern const GUID IID_D3DDEVICE_WineD3D DECLSPEC_HIDDEN;
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index e766940..47ee68a 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -75,178 +75,169 @@ static inline WORD d3d_fpu_setup(void)
     return oldcw;
 }
 
-/*****************************************************************************
- * IUnknown Methods. Common for Version 1, 2, 3 and 7
- *****************************************************************************/
-
-/*****************************************************************************
- * IDirect3DDevice7::QueryInterface
- *
- * Used to query other interfaces from a Direct3DDevice interface.
- * It can return interface pointers to all Direct3DDevice versions as well
- * as IDirectDraw and IDirect3D. For a link to QueryInterface
- * rules see ddraw.c, IDirectDraw7::QueryInterface
- *
- * Exists in Version 1, 2, 3 and 7
- *
- * Params:
- *  refiid: Interface ID queried for
- *  obj: Used to return the interface pointer
- *
- * Returns:
- *  D3D_OK or E_NOINTERFACE
- *
- *****************************************************************************/
-static HRESULT WINAPI
-IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
-                                     REFIID refiid,
-                                     void **obj)
+static inline IDirect3DDeviceImpl *impl_from_IUnknown(IUnknown *iface)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
+    return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IUnknown_inner);
+}
 
-    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
+static HRESULT WINAPI d3d_device_inner_QueryInterface(IUnknown *iface, REFIID riid, void **out)
+{
+    IDirect3DDeviceImpl *device = impl_from_IUnknown(iface);
 
-    /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
-    *obj = NULL;
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
 
-    if(!refiid)
+    if (!riid)
+    {
+        *out = NULL;
         return DDERR_INVALIDPARAMS;
+    }
 
-    if ( IsEqualGUID( &IID_IUnknown, refiid ) )
+    if (IsEqualGUID(&IID_IUnknown, riid))
     {
-        *obj = iface;
+        IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
+        *out = &device->IDirect3DDevice7_iface;
+        return S_OK;
     }
 
-    if (This->version == 7)
+    if (device->version == 7)
     {
-        if (IsEqualGUID(&IID_IDirect3DDevice7, refiid))
-            *obj = iface;
+        if (IsEqualGUID(&IID_IDirect3DDevice7, riid))
+        {
+            IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
+            *out = &device->IDirect3DDevice7_iface;
+            return S_OK;
+        }
     }
-    else if (IsEqualGUID(&IID_IDirect3DDevice3, refiid) && This->version == 3)
-        *obj = &This->IDirect3DDevice3_iface;
-    else if (IsEqualGUID(&IID_IDirect3DDevice2, refiid) && This->version >= 2)
-        *obj = &This->IDirect3DDevice2_iface;
-    else if (IsEqualGUID(&IID_IDirect3DDevice, refiid))
-        *obj = &This->IDirect3DDevice_iface;
-    else if (IsEqualGUID(&IID_IDirectDrawSurface, refiid) && This->version == 1)
-        *obj = &This->target->IDirectDrawSurface_iface;
     else
     {
-        WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(refiid));
-        return E_NOINTERFACE;
+        if (IsEqualGUID(&IID_IDirect3DDevice3, riid) && device->version == 3)
+        {
+            IDirect3DDevice3_AddRef(&device->IDirect3DDevice3_iface);
+            *out = &device->IDirect3DDevice3_iface;
+            return S_OK;
+        }
+
+        if (IsEqualGUID(&IID_IDirect3DDevice2, riid) && device->version >= 2)
+        {
+            IDirect3DDevice2_AddRef(&device->IDirect3DDevice2_iface);
+            *out = &device->IDirect3DDevice2_iface;
+            return S_OK;
+        }
+
+        if (IsEqualGUID(&IID_IDirect3DDevice, riid))
+        {
+            IDirect3DDevice_AddRef(&device->IDirect3DDevice_iface);
+            *out = &device->IDirect3DDevice_iface;
+            return S_OK;
+        }
     }
 
-    /* AddRef the returned interface */
-    IUnknown_AddRef( (IUnknown *) *obj);
-    return D3D_OK;
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return E_NOINTERFACE;
 }
 
-static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
-        void **obj)
+static HRESULT WINAPI IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface, REFIID riid, void **out)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
-    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice7(iface);
 
-    return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    return IUnknown_QueryInterface(device->outer_unknown, riid, out);
 }
 
-static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
-        void **obj)
+static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid, void **out)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
-    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice3(iface);
 
-    return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    return IUnknown_QueryInterface(device->outer_unknown, riid, out);
 }
 
-static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
-        void **obp)
+static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid, void **out)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
-    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice2(iface);
+
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
 
-    return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
+    return IUnknown_QueryInterface(device->outer_unknown, riid, out);
 }
 
-/*****************************************************************************
- * IDirect3DDevice7::AddRef
- *
- * Increases the refcount....
- * The most exciting Method, definitely
- *
- * Exists in Version 1, 2, 3 and 7
- *
- * Returns:
- *  The new refcount
- *
- *****************************************************************************/
-static ULONG WINAPI
-IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
+static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid, void **out)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
-    ULONG ref = InterlockedIncrement(&This->ref);
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice(iface);
 
-    TRACE("%p increasing refcount to %u.\n", This, ref);
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    return IUnknown_QueryInterface(device->outer_unknown, riid, out);
+}
+
+static ULONG WINAPI d3d_device_inner_AddRef(IUnknown *iface)
+{
+    IDirect3DDeviceImpl *device = impl_from_IUnknown(iface);
+    ULONG ref = InterlockedIncrement(&device->ref);
+
+    TRACE("%p increasing refcount to %u.\n", device, ref);
 
     return ref;
 }
 
+static ULONG WINAPI IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
+{
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice7(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return IUnknown_AddRef(device->outer_unknown);
+}
+
 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice3(iface);
+
     TRACE("iface %p.\n", iface);
 
-    return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
+    return IUnknown_AddRef(device->outer_unknown);
 }
 
 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice2(iface);
+
     TRACE("iface %p.\n", iface);
 
-    return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
+    return IUnknown_AddRef(device->outer_unknown);
 }
 
 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice(iface);
+
     TRACE("iface %p.\n", iface);
 
-    return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
+    return IUnknown_AddRef(device->outer_unknown);
 }
 
-/*****************************************************************************
- * IDirect3DDevice7::Release
- *
- * Decreases the refcount of the interface
- * When the refcount is reduced to 0, the object is destroyed.
- *
- * Exists in Version 1, 2, 3 and 7
- *
- * Returns:d
- *  The new refcount
- *
- *****************************************************************************/
-static ULONG WINAPI
-IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
+static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
+    IDirect3DDeviceImpl *This = impl_from_IUnknown(iface);
     ULONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("%p decreasing refcount to %u.\n", This, ref);
 
-    /* This method doesn't destroy the WineD3DDevice, because it's still in use for
-     * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
-     * when the render target is released
-     */
-    if (ref == 0)
+    /* This method doesn't destroy the wined3d device, because it's still in
+     * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
+     * wined3d device when the render target is released. */
+    if (!ref)
     {
         DWORD i;
 
         wined3d_mutex_lock();
 
         /* There is no need to unset any resources here, wined3d will take
-         * care of that on Uninit3D(). */
+         * care of that on uninit_3d(). */
 
         /* Free the index buffer. */
         wined3d_buffer_decref(This->indexbuffer);
@@ -256,7 +247,7 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
         wined3d_device_set_render_target(This->wined3d_device, 0,
                 This->ddraw->wined3d_frontbuffer, TRUE);
 
-        /* Release the WineD3DDevice. This won't destroy it. */
+        /* Release the wined3d device. This won't destroy it. */
         if (!wined3d_device_decref(This->wined3d_device))
             ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
 
@@ -291,7 +282,7 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
                 {
                     /* No FIXME here because this might happen because of sloppy applications. */
                     WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
-                    IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
+                    IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
                     break;
                 }
 
@@ -312,10 +303,9 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
         ddraw_handle_table_destroy(&This->handle_table);
 
         TRACE("Releasing target %p.\n", This->target);
-        /* Release the render target and the WineD3D render target
-         * (See IDirect3D7::CreateDevice for more comments on this)
-         */
-        IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
+        /* Release the render target. */
+        if (This->version != 1)
+            IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
         TRACE("Target release done\n");
 
         This->ddraw->d3ddevice = NULL;
@@ -329,28 +319,40 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
     return ref;
 }
 
+static ULONG WINAPI IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
+{
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice7(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return IUnknown_Release(device->outer_unknown);
+}
+
 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice3(iface);
+
     TRACE("iface %p.\n", iface);
 
-    return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
+    return IUnknown_Release(device->outer_unknown);
 }
 
 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice2(iface);
+
     TRACE("iface %p.\n", iface);
 
-    return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
+    return IUnknown_Release(device->outer_unknown);
 }
 
 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
 {
-    IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
+    IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice(iface);
+
     TRACE("iface %p.\n", iface);
 
-    return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
+    return IUnknown_Release(device->outer_unknown);
 }
 
 /*****************************************************************************
@@ -6898,6 +6900,13 @@ static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
     IDirect3DDeviceImpl_1_GetDirect3D
 };
 
+static const struct IUnknownVtbl d3d_device_inner_vtbl =
+{
+    d3d_device_inner_QueryInterface,
+    d3d_device_inner_AddRef,
+    d3d_device_inner_Release,
+};
+
 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
 {
     if (!iface) return NULL;
@@ -6959,7 +6968,7 @@ enum wined3d_depth_buffer_type IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DD
 }
 
 static HRESULT d3d_device_init(IDirect3DDeviceImpl *device, struct ddraw *ddraw,
-        struct ddraw_surface *target, UINT version)
+        struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
 {
     static const D3DMATRIX ident =
     {
@@ -6978,8 +6987,15 @@ static HRESULT d3d_device_init(IDirect3DDeviceImpl *device, struct ddraw *ddraw,
     device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
     device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
     device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
+    device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
     device->ref = 1;
     device->version = version;
+
+    if (outer_unknown)
+        device->outer_unknown = outer_unknown;
+    else
+        device->outer_unknown = &device->IUnknown_inner;
+
     device->ddraw = ddraw;
     device->target = target;
     list_init(&device->viewport_list);
@@ -7028,7 +7044,8 @@ static HRESULT d3d_device_init(IDirect3DDeviceImpl *device, struct ddraw *ddraw,
      *
      * In most cases, those surfaces are the same anyway, but this will simply
      * add another ref which is released when the device is destroyed. */
-    IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
+    if (version != 1)
+        IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
 
     ddraw->d3ddevice = device;
 
@@ -7039,12 +7056,13 @@ static HRESULT d3d_device_init(IDirect3DDeviceImpl *device, struct ddraw *ddraw,
 }
 
 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
-        UINT version, IDirect3DDeviceImpl **device)
+        UINT version, IDirect3DDeviceImpl **device, IUnknown *outer_unknown)
 {
     IDirect3DDeviceImpl *object;
     HRESULT hr;
 
-    TRACE("ddraw %p, target %p, version %u, device %p.\n", ddraw, target, version, device);
+    TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
+            ddraw, target, version, device, outer_unknown);
 
     if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
     {
@@ -7067,7 +7085,7 @@ HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
         return DDERR_OUTOFMEMORY;
     }
 
-    hr = d3d_device_init(object, ddraw, target, version);
+    hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
     if (FAILED(hr))
     {
         WARN("Failed to initialize device, hr %#x.\n", hr);
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index 1d614ac..2475522 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -204,19 +204,23 @@ static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface,
                 || IsEqualGUID(riid, &IID_IDirect3DHALDevice)
                 || IsEqualGUID(riid, &IID_IDirect3DRGBDevice))
         {
-            IDirect3DDeviceImpl *device;
-            HRESULT hr;
-
             wined3d_mutex_lock();
-            hr = d3d_device_create(This->ddraw, This, 1, &device);
-            wined3d_mutex_unlock();
-            if (FAILED(hr))
+            if (!This->device1)
             {
-                WARN("Failed to create device, hr %#x.\n", hr);
-                return hr;
+                HRESULT hr = d3d_device_create(This->ddraw, This, 1, &This->device1,
+                        (IUnknown *)&This->IDirectDrawSurface_iface);
+                if (FAILED(hr))
+                {
+                    This->device1 = NULL;
+                    wined3d_mutex_unlock();
+                    WARN("Failed to create device, hr %#x.\n", hr);
+                    return hr;
+                }
             }
+            wined3d_mutex_unlock();
 
-            *obj = &device->IDirect3DDevice_iface;
+            IDirect3DDevice_AddRef(&This->device1->IDirect3DDevice_iface);
+            *obj = &This->device1->IDirect3DDevice_iface;
             return S_OK;
         }
 
@@ -502,6 +506,8 @@ static void ddraw_surface_cleanup(struct ddraw_surface *surface)
         }
     }
 
+    if (surface->device1)
+        IUnknown_Release(&surface->device1->IUnknown_inner);
     ifaceToRelease = surface->ifaceToRelease;
 
     /* Destroy the root surface. */
diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c
index fd91c77..bce9eca 100644
--- a/dlls/ddraw/tests/d3d.c
+++ b/dlls/ddraw/tests/d3d.c
@@ -3523,7 +3523,6 @@ static void FindDevice(void)
         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **)&d3dhal);
         /* Currently Wine only supports the creation of one Direct3D device
          * for a given DirectDraw instance. */
-        todo_wine
         ok(SUCCEEDED(hr) || broken(hr == DDERR_INVALIDPIXELFORMAT) /* XP/Win2003 Wow64 on VMware */,
            "Expected IDirectDrawSurface::QueryInterface to succeed, got 0x%08x\n", hr);
 
-- 
1.7.3.4




More information about the wine-patches mailing list