[D3DRM] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / reactos / dll / directx / wine / d3drm / d3drm.c
index b1d2e69..6724850 100644 (file)
@@ -44,7 +44,7 @@ struct d3drm
     IDirect3DRM IDirect3DRM_iface;
     IDirect3DRM2 IDirect3DRM2_iface;
     IDirect3DRM3 IDirect3DRM3_iface;
-    LONG ref;
+    LONG ref1, ref2, ref3, iface_count;
 };
 
 static inline struct d3drm *impl_from_IDirect3DRM(IDirect3DRM *iface)
@@ -62,6 +62,12 @@ static inline struct d3drm *impl_from_IDirect3DRM3(IDirect3DRM3 *iface)
     return CONTAINING_RECORD(iface, struct d3drm, IDirect3DRM3_iface);
 }
 
+static void d3drm_destroy(struct d3drm *d3drm)
+{
+    HeapFree(GetProcessHeap(), 0, d3drm);
+    TRACE("d3drm object %p is being destroyed.\n", d3drm);
+}
+
 static HRESULT WINAPI d3drm1_QueryInterface(IDirect3DRM *iface, REFIID riid, void **out)
 {
     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
@@ -84,8 +90,8 @@ static HRESULT WINAPI d3drm1_QueryInterface(IDirect3DRM *iface, REFIID riid, voi
     else
     {
         *out = NULL;
-        WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
-        return E_NOINTERFACE;
+        WARN("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(riid));
+        return CLASS_E_CLASSNOTAVAILABLE;
     }
 
     IUnknown_AddRef((IUnknown *)*out);
@@ -95,22 +101,25 @@ static HRESULT WINAPI d3drm1_QueryInterface(IDirect3DRM *iface, REFIID riid, voi
 static ULONG WINAPI d3drm1_AddRef(IDirect3DRM *iface)
 {
     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
-    ULONG refcount = InterlockedIncrement(&d3drm->ref);
+    ULONG refcount = InterlockedIncrement(&d3drm->ref1);
 
     TRACE("%p increasing refcount to %u.\n", iface, refcount);
 
+    if (refcount == 1)
+        InterlockedIncrement(&d3drm->iface_count);
+
     return refcount;
 }
 
 static ULONG WINAPI d3drm1_Release(IDirect3DRM *iface)
 {
     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
-    ULONG refcount = InterlockedDecrement(&d3drm->ref);
+    ULONG refcount = InterlockedDecrement(&d3drm->ref1);
 
     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
-    if (!refcount)
-        HeapFree(GetProcessHeap(), 0, d3drm);
+    if (!refcount && !InterlockedDecrement(&d3drm->iface_count))
+        d3drm_destroy(d3drm);
 
     return refcount;
 }
@@ -211,37 +220,125 @@ static HRESULT WINAPI d3drm1_CreateMaterial(IDirect3DRM *iface,
 static HRESULT WINAPI d3drm1_CreateDevice(IDirect3DRM *iface,
         DWORD width, DWORD height, IDirect3DRMDevice **device)
 {
+    struct d3drm_device *object;
+    HRESULT hr;
     FIXME("iface %p, width %u, height %u, device %p partial stub!\n", iface, width, height, device);
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice, (IUnknown **)device);
+    hr = d3drm_device_create(&object);
+    if (FAILED(hr))
+        return hr;
+
+    *device = IDirect3DRMDevice_from_impl(object);
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm1_CreateDeviceFromSurface(IDirect3DRM *iface, GUID *guid,
         IDirectDraw *ddraw, IDirectDrawSurface *backbuffer, IDirect3DRMDevice **device)
 {
-    FIXME("iface %p, guid %s, ddraw %p, backbuffer %p, device %p partial stub.\n",
+    struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
+    struct d3drm_device *object;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, ddraw %p, backbuffer %p, device %p.\n",
             iface, debugstr_guid(guid), ddraw, backbuffer, device);
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice, (IUnknown **)device);
+    if (!device)
+        return D3DRMERR_BADVALUE;
+    *device = NULL;
+
+    if (!backbuffer || !ddraw)
+        return D3DRMERR_BADDEVICE;
+
+    hr = d3drm_device_create(&object);
+    if (FAILED(hr))
+        return hr;
+
+    hr = d3drm_device_init(object, 1, &d3drm->IDirect3DRM_iface, ddraw, backbuffer, TRUE);
+    if (SUCCEEDED(hr))
+        *device = IDirect3DRMDevice_from_impl(object);
+    else
+        d3drm_device_destroy(object);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm1_CreateDeviceFromD3D(IDirect3DRM *iface,
         IDirect3D *d3d, IDirect3DDevice *d3d_device, IDirect3DRMDevice **device)
 {
-    FIXME("iface %p, d3d %p, d3d_device %p, device %p partial stub.\n",
+    struct d3drm_device *object;
+    HRESULT hr;
+    TRACE("iface %p, d3d %p, d3d_device %p, device %p.\n",
             iface, d3d, d3d_device, device);
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice, (IUnknown **)device);
+    if (!device)
+        return D3DRMERR_BADVALUE;
+    *device = NULL;
+    if (!d3d || !d3d_device)
+        return D3DRMERR_BADVALUE;
+
+    hr = d3drm_device_create(&object);
+    if (FAILED(hr))
+        return hr;
+
+    hr = d3drm_device_set_ddraw_device_d3d(object, iface, d3d, d3d_device);
+    if (FAILED(hr))
+    {
+        d3drm_device_destroy(object);
+        return hr;
+    }
+    *device = IDirect3DRMDevice_from_impl(object);
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm1_CreateDeviceFromClipper(IDirect3DRM *iface,
         IDirectDrawClipper *clipper, GUID *guid, int width, int height,
         IDirect3DRMDevice **device)
 {
-    FIXME("iface %p, clipper %p, guid %s, width %d, height %d, device %p.\n",
+    struct d3drm_device *object;
+    IDirectDraw *ddraw;
+    IDirectDrawSurface *render_target;
+    HRESULT hr;
+
+    TRACE("iface %p, clipper %p, guid %s, width %d, height %d, device %p.\n",
             iface, clipper, debugstr_guid(guid), width, height, device);
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice, (IUnknown **)device);
+    if (!device)
+        return D3DRMERR_BADVALUE;
+    *device = NULL;
+
+    if (!clipper || !width || !height)
+        return D3DRMERR_BADVALUE;
+
+    hr = DirectDrawCreate(NULL, &ddraw, NULL);
+    if (FAILED(hr))
+        return hr;
+
+    hr = d3drm_device_create(&object);
+    if (FAILED(hr))
+    {
+        IDirectDraw_Release(ddraw);
+        return hr;
+    }
+
+    hr = d3drm_device_create_surfaces_from_clipper(object, ddraw, clipper, width, height, &render_target);
+    if (FAILED(hr))
+    {
+        IDirectDraw_Release(ddraw);
+        d3drm_device_destroy(object);
+        return hr;
+    }
+
+    hr = d3drm_device_init(object, 1, iface, ddraw, render_target, TRUE);
+    IDirectDraw_Release(ddraw);
+    IDirectDrawSurface_Release(render_target);
+    if (FAILED(hr))
+        d3drm_device_destroy(object);
+    else
+        *device = IDirect3DRMDevice_from_impl(object);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm1_CreateTextureFromSurface(IDirect3DRM *iface,
@@ -444,15 +541,27 @@ static HRESULT WINAPI d3drm2_QueryInterface(IDirect3DRM2 *iface, REFIID riid, vo
 static ULONG WINAPI d3drm2_AddRef(IDirect3DRM2 *iface)
 {
     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
+    ULONG refcount = InterlockedIncrement(&d3drm->ref2);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    if (refcount == 1)
+        InterlockedIncrement(&d3drm->iface_count);
 
-    return d3drm1_AddRef(&d3drm->IDirect3DRM_iface);
+    return refcount;
 }
 
 static ULONG WINAPI d3drm2_Release(IDirect3DRM2 *iface)
 {
     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
+    ULONG refcount = InterlockedDecrement(&d3drm->ref2);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount && !InterlockedDecrement(&d3drm->iface_count))
+        d3drm_destroy(d3drm);
 
-    return d3drm1_Release(&d3drm->IDirect3DRM_iface);
+    return refcount;
 }
 
 static HRESULT WINAPI d3drm2_CreateObject(IDirect3DRM2 *iface,
@@ -551,37 +660,103 @@ static HRESULT WINAPI d3drm2_CreateMaterial(IDirect3DRM2 *iface,
 static HRESULT WINAPI d3drm2_CreateDevice(IDirect3DRM2 *iface,
         DWORD width, DWORD height, IDirect3DRMDevice2 **device)
 {
-    FIXME("iface %p, width %u, height %u, device %p.\n", iface, width, height, device);
+    struct d3drm_device *object;
+    HRESULT hr;
+    FIXME("iface %p, width %u, height %u, device %p partial stub!\n", iface, width, height, device);
+
+    hr = d3drm_device_create(&object);
+    if (FAILED(hr))
+        return hr;
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice2, (IUnknown **)device);
+    *device = IDirect3DRMDevice2_from_impl(object);
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm2_CreateDeviceFromSurface(IDirect3DRM2 *iface, GUID *guid,
         IDirectDraw *ddraw, IDirectDrawSurface *backbuffer, IDirect3DRMDevice2 **device)
 {
-    FIXME("iface %p, guid %s, ddraw %p, backbuffer %p, device %p partial stub.\n",
+    struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
+    IDirect3DRMDevice3 *device3;
+    HRESULT hr;
+    TRACE("iface %p, guid %s, ddraw %p, backbuffer %p, device %p.\n",
             iface, debugstr_guid(guid), ddraw, backbuffer, device);
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice2, (IUnknown **)device);
+    if (!device)
+        return D3DRMERR_BADVALUE;
+    *device = NULL;
+    hr = IDirect3DRM3_CreateDeviceFromSurface(&d3drm->IDirect3DRM3_iface, guid, ddraw, backbuffer, 0, &device3);
+    if (FAILED(hr))
+        return hr;
+
+    hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice2, (void**)device);
+    IDirect3DRMDevice3_Release(device3);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm2_CreateDeviceFromD3D(IDirect3DRM2 *iface,
-        IDirect3D2 *d3d, IDirect3DDevice2 *d3d_device, IDirect3DRMDevice2 **device)
+    IDirect3D2 *d3d, IDirect3DDevice2 *d3d_device, IDirect3DRMDevice2 **device)
 {
-    FIXME("iface %p, d3d %p, d3d_device %p, device %p partial stub.\n",
+    struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
+    IDirect3D *d3d1;
+    IDirect3DDevice *d3d_device1;
+    IDirect3DRMDevice *device1;
+    HRESULT hr;
+    TRACE("iface %p, d3d %p, d3d_device %p, device %p.\n",
             iface, d3d, d3d_device, device);
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice2, (IUnknown **)device);
+    if (!device)
+        return D3DRMERR_BADVALUE;
+    *device = NULL;
+    if (!d3d || !d3d_device)
+        return D3DRMERR_BADVALUE;
+
+    hr = IDirect3D2_QueryInterface(d3d, &IID_IDirect3D, (void **)&d3d1);
+    if (FAILED(hr))
+        return hr;
+
+    hr = IDirect3DDevice2_QueryInterface(d3d_device, &IID_IDirect3DDevice, (void **)&d3d_device1);
+    if (FAILED(hr))
+    {
+        IDirect3D_Release(d3d1);
+        return hr;
+    }
+
+    hr = IDirect3DRM_CreateDeviceFromD3D(&d3drm->IDirect3DRM_iface, d3d1, d3d_device1, &device1);
+    IDirect3D_Release(d3d1);
+    IDirect3DDevice_Release(d3d_device1);
+    if (FAILED(hr))
+        return hr;
+
+    hr = IDirect3DRMDevice_QueryInterface(device1, &IID_IDirect3DRMDevice2, (void **)device);
+    IDirect3DRMDevice_Release(device1);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm2_CreateDeviceFromClipper(IDirect3DRM2 *iface,
         IDirectDrawClipper *clipper, GUID *guid, int width, int height,
         IDirect3DRMDevice2 **device)
 {
-    FIXME("iface %p, clipper %p, guid %s, width %d, height %d, device %p partial stub.\n",
+    struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
+    IDirect3DRMDevice3 *device3;
+    HRESULT hr;
+
+    TRACE("iface %p, clipper %p, guid %s, width %d, height %d, device %p.\n",
             iface, clipper, debugstr_guid(guid), width, height, device);
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice2, (IUnknown **)device);
+    if (!device)
+        return D3DRMERR_BADVALUE;
+    *device = NULL;
+    hr = IDirect3DRM3_CreateDeviceFromClipper(&d3drm->IDirect3DRM3_iface, clipper, guid, width, height, &device3);
+    if (FAILED(hr))
+        return hr;
+
+    hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice2, (void**)device);
+    IDirect3DRMDevice3_Release(device3);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm2_CreateTextureFromSurface(IDirect3DRM2 *iface,
@@ -793,15 +968,27 @@ static HRESULT WINAPI d3drm3_QueryInterface(IDirect3DRM3 *iface, REFIID riid, vo
 static ULONG WINAPI d3drm3_AddRef(IDirect3DRM3 *iface)
 {
     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    ULONG refcount = InterlockedIncrement(&d3drm->ref3);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
 
-    return d3drm1_AddRef(&d3drm->IDirect3DRM_iface);
+    if (refcount == 1)
+        InterlockedIncrement(&d3drm->iface_count);
+
+    return refcount;
 }
 
 static ULONG WINAPI d3drm3_Release(IDirect3DRM3 *iface)
 {
     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    ULONG refcount = InterlockedDecrement(&d3drm->ref3);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
-    return d3drm1_Release(&d3drm->IDirect3DRM_iface);
+    if (!refcount && !InterlockedDecrement(&d3drm->iface_count))
+        d3drm_destroy(d3drm);
+
+    return refcount;
 }
 
 static HRESULT WINAPI d3drm3_CreateObject(IDirect3DRM3 *iface,
@@ -913,37 +1100,139 @@ static HRESULT WINAPI d3drm3_CreateMaterial(IDirect3DRM3 *iface,
 static HRESULT WINAPI d3drm3_CreateDevice(IDirect3DRM3 *iface,
         DWORD width, DWORD height, IDirect3DRMDevice3 **device)
 {
+    struct d3drm_device *object;
+    HRESULT hr;
     FIXME("iface %p, width %u, height %u, device %p partial stub!\n", iface, width, height, device);
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice3, (IUnknown **)device);
+    hr = d3drm_device_create(&object);
+    if (FAILED(hr))
+        return hr;
+
+    *device = IDirect3DRMDevice3_from_impl(object);
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm3_CreateDeviceFromSurface(IDirect3DRM3 *iface, GUID *guid,
-        IDirectDraw *ddraw, IDirectDrawSurface *backbuffer, IDirect3DRMDevice3 **device)
+        IDirectDraw *ddraw, IDirectDrawSurface *backbuffer, DWORD flags, IDirect3DRMDevice3 **device)
 {
-    FIXME("iface %p, guid %s, ddraw %p, backbuffer %p, device %p partial stub.\n",
-            iface, debugstr_guid(guid), ddraw, backbuffer, device);
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    struct d3drm_device *object;
+    BOOL use_z_surface;
+    HRESULT hr;
+
+    TRACE("iface %p, guid %s, ddraw %p, backbuffer %p, flags %#x, device %p.\n",
+            iface, debugstr_guid(guid), ddraw, backbuffer, flags, device);
+
+    if (!device)
+        return D3DRMERR_BADVALUE;
+    *device = NULL;
+
+    if (!backbuffer || !ddraw)
+        return D3DRMERR_BADDEVICE;
+
+    hr = d3drm_device_create(&object);
+    if (FAILED(hr))
+        return hr;
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice3, (IUnknown **)device);
+    use_z_surface = !(flags & D3DRMDEVICE_NOZBUFFER);
+
+    hr = d3drm_device_init(object, 3, &d3drm->IDirect3DRM_iface, ddraw, backbuffer, use_z_surface);
+    if (SUCCEEDED(hr))
+        *device = IDirect3DRMDevice3_from_impl(object);
+    else
+        d3drm_device_destroy(object);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm3_CreateDeviceFromD3D(IDirect3DRM3 *iface,
         IDirect3D2 *d3d, IDirect3DDevice2 *d3d_device, IDirect3DRMDevice3 **device)
 {
-    FIXME("iface %p, d3d %p, d3d_device %p, device %p partial stub.\n",
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    IDirect3D *d3d1;
+    IDirect3DDevice *d3d_device1;
+    IDirect3DRMDevice *device1;
+    HRESULT hr;
+    TRACE("iface %p, d3d %p, d3d_device %p, device %p.\n",
             iface, d3d, d3d_device, device);
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice3, (IUnknown **)device);
+    if (!device)
+        return D3DRMERR_BADVALUE;
+    *device = NULL;
+    if (!d3d || !d3d_device)
+        return D3DRMERR_BADVALUE;
+
+    hr = IDirect3D2_QueryInterface(d3d, &IID_IDirect3D, (void **)&d3d1);
+    if (FAILED(hr))
+        return hr;
+    hr = IDirect3DDevice2_QueryInterface(d3d_device, &IID_IDirect3DDevice, (void **)&d3d_device1);
+    if (FAILED(hr))
+    {
+        IDirect3D_Release(d3d1);
+        return hr;
+    }
+
+    hr = IDirect3DRM_CreateDeviceFromD3D(&d3drm->IDirect3DRM_iface, d3d1, d3d_device1, &device1);
+    IDirect3D_Release(d3d1);
+    IDirect3DDevice_Release(d3d_device1);
+    if (FAILED(hr))
+        return hr;
+
+    hr = IDirect3DRMDevice_QueryInterface(device1, &IID_IDirect3DRMDevice3, (void **)device);
+    IDirect3DRMDevice_Release(device1);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm3_CreateDeviceFromClipper(IDirect3DRM3 *iface,
         IDirectDrawClipper *clipper, GUID *guid, int width, int height,
         IDirect3DRMDevice3 **device)
 {
-    FIXME("iface %p, clipper %p, guid %s, width %d, height %d, device %p partial stub.\n",
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    struct d3drm_device *object;
+    IDirectDraw *ddraw;
+    IDirectDrawSurface *render_target;
+    HRESULT hr;
+
+    TRACE("iface %p, clipper %p, guid %s, width %d, height %d, device %p.\n",
             iface, clipper, debugstr_guid(guid), width, height, device);
 
-    return Direct3DRMDevice_create(&IID_IDirect3DRMDevice3, (IUnknown **)device);
+    if (!device)
+        return D3DRMERR_BADVALUE;
+    *device = NULL;
+
+    if (!clipper || !width || !height)
+        return D3DRMERR_BADVALUE;
+
+    hr = DirectDrawCreate(NULL, &ddraw, NULL);
+    if (FAILED(hr))
+        return hr;
+
+    hr = d3drm_device_create(&object);
+    if (FAILED(hr))
+    {
+        IDirectDraw_Release(ddraw);
+        return hr;
+    }
+
+    hr = d3drm_device_create_surfaces_from_clipper(object, ddraw, clipper, width, height, &render_target);
+    if (FAILED(hr))
+    {
+        IDirectDraw_Release(ddraw);
+        d3drm_device_destroy(object);
+        return hr;
+    }
+
+    hr = d3drm_device_init(object, 3, &d3drm->IDirect3DRM_iface, ddraw, render_target, TRUE);
+    IDirectDraw_Release(ddraw);
+    IDirectDrawSurface_Release(render_target);
+    if (FAILED(hr))
+        d3drm_device_destroy(object);
+    else
+        *device = IDirect3DRMDevice3_from_impl(object);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm3_CreateShadow(IDirect3DRM3 *iface, IUnknown *object, IDirect3DRMLight *light,
@@ -1162,32 +1451,29 @@ static HRESULT load_data(IDirect3DRM3 *iface, IDirectXFileData *data_object, IID
                     IDirectXFileDataReference *reference;
                     IDirectXFileBinary *binary;
 
-                    hr = IDirectXFileObject_QueryInterface(child, &IID_IDirectXFileBinary, (void **)&binary);
-                    if (SUCCEEDED(hr))
+                    if (SUCCEEDED(IDirectXFileObject_QueryInterface(child,
+                            &IID_IDirectXFileBinary, (void **)&binary)))
                     {
                         FIXME("Binary Object not supported yet\n");
                         IDirectXFileBinary_Release(binary);
-                        continue;
                     }
-
-                    hr = IDirectXFileObject_QueryInterface(child, &IID_IDirectXFileData, (void **)&data);
-                    if (SUCCEEDED(hr))
+                    else if (SUCCEEDED(IDirectXFileObject_QueryInterface(child,
+                            &IID_IDirectXFileData, (void **)&data)))
                     {
                         TRACE("Found Data Object\n");
                         hr = load_data(iface, data, GUIDs, nb_GUIDs, LoadProc, ArgLP, LoadTextureProc, ArgLTP, frame);
                         IDirectXFileData_Release(data);
-                        continue;
                     }
-                    hr = IDirectXFileObject_QueryInterface(child, &IID_IDirectXFileDataReference, (void **)&reference);
-                    if (SUCCEEDED(hr))
+                    else if (SUCCEEDED(IDirectXFileObject_QueryInterface(child,
+                            &IID_IDirectXFileDataReference, (void **)&reference)))
                     {
                         TRACE("Found Data Object Reference\n");
                         IDirectXFileDataReference_Resolve(reference, &data);
                         hr = load_data(iface, data, GUIDs, nb_GUIDs, LoadProc, ArgLP, LoadTextureProc, ArgLTP, frame);
                         IDirectXFileData_Release(data);
                         IDirectXFileDataReference_Release(reference);
-                        continue;
                     }
+                    IDirectXFileObject_Release(child);
                 }
 
                 if (hr != DXFILEERR_NOMOREOBJECTS)
@@ -1229,17 +1515,16 @@ static HRESULT load_data(IDirect3DRM3 *iface, IDirectXFileData *data_object, IID
         /* Cannot be requested */
         if (parent_frame)
         {
-            D3DRMMATRIX4D matrix;
+            D3DRMMATRIX4D *matrix;
             DWORD size;
 
             TRACE("Load Frame Transform Matrix data\n");
 
-            size = sizeof(matrix);
-            hr = IDirectXFileData_GetData(data_object, NULL, &size, (void**)matrix);
+            hr = IDirectXFileData_GetData(data_object, NULL, &size, (void**)&matrix);
             if ((hr != DXFILE_OK) || (size != sizeof(matrix)))
                 goto end;
 
-            hr = IDirect3DRMFrame3_AddTransform(parent_frame, D3DRMCOMBINE_REPLACE, matrix);
+            hr = IDirect3DRMFrame3_AddTransform(parent_frame, D3DRMCOMBINE_REPLACE, *matrix);
             if (FAILED(hr))
                 goto end;
         }
@@ -1481,9 +1766,25 @@ HRESULT WINAPI Direct3DRMCreate(IDirect3DRM **d3drm)
     object->IDirect3DRM_iface.lpVtbl = &d3drm1_vtbl;
     object->IDirect3DRM2_iface.lpVtbl = &d3drm2_vtbl;
     object->IDirect3DRM3_iface.lpVtbl = &d3drm3_vtbl;
-    object->ref = 1;
+    object->ref1 = 1;
+    object->iface_count = 1;
 
     *d3drm = &object->IDirect3DRM_iface;
 
     return S_OK;
 }
+
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+    return S_FALSE;
+}
+
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
+{
+    TRACE("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+
+    if(!ppv)
+        return E_INVALIDARG;
+
+    return CLASS_E_CLASSNOTAVAILABLE;
+}