xref: /reactos/dll/directx/wine/d3drm/d3drm.c (revision a6726659)
1 /*
2  * Implementation of IDirect3DRM Interface
3  *
4  * Copyright 2010, 2012 Christian Costa
5  * Copyright 2011 André Hentschel
6  * Copyright 2016 Aaryaman Vasishta
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 "d3drm_private.h"
27 
28 WINE_DEFAULT_DEBUG_CHANNEL(d3drm);
29 
30 static const char* get_IID_string(const GUID* guid)
31 {
32     if (IsEqualGUID(guid, &IID_IDirect3DRMFrame))
33         return "IID_IDirect3DRMFrame";
34     else if (IsEqualGUID(guid, &IID_IDirect3DRMFrame2))
35         return "IID_IDirect3DRMFrame2";
36     else if (IsEqualGUID(guid, &IID_IDirect3DRMFrame3))
37         return "IID_IDirect3DRMFrame3";
38     else if (IsEqualGUID(guid, &IID_IDirect3DRMMeshBuilder))
39         return "IID_IDirect3DRMMeshBuilder";
40     else if (IsEqualGUID(guid, &IID_IDirect3DRMMeshBuilder2))
41         return "IID_IDirect3DRMMeshBuilder2";
42     else if (IsEqualGUID(guid, &IID_IDirect3DRMMeshBuilder3))
43         return "IID_IDirect3DRMMeshBuilder3";
44 
45     return "?";
46 }
47 
48 static HRESULT d3drm_create_texture_object(void **object, IDirect3DRM *d3drm)
49 {
50     struct d3drm_texture *texture;
51     HRESULT hr;
52 
53     if (FAILED(hr = d3drm_texture_create(&texture, d3drm)))
54         return hr;
55 
56     *object = &texture->IDirect3DRMTexture_iface;
57 
58     return hr;
59 }
60 
61 static HRESULT d3drm_create_device_object(void **object, IDirect3DRM *d3drm)
62 {
63     struct d3drm_device *device;
64     HRESULT hr;
65 
66     if (FAILED(hr = d3drm_device_create(&device, d3drm)))
67         return hr;
68 
69     *object = &device->IDirect3DRMDevice_iface;
70 
71     return hr;
72 }
73 
74 static HRESULT d3drm_create_viewport_object(void **object, IDirect3DRM *d3drm)
75 {
76     struct d3drm_viewport *viewport;
77     HRESULT hr;
78 
79     if (FAILED(hr = d3drm_viewport_create(&viewport, d3drm)))
80         return hr;
81 
82     *object = &viewport->IDirect3DRMViewport_iface;
83 
84     return hr;
85 }
86 
87 static HRESULT d3drm_create_face_object(void **object, IDirect3DRM *d3drm)
88 {
89     struct d3drm_face *face;
90     HRESULT hr;
91 
92     if (FAILED(hr = d3drm_face_create(&face)))
93         return hr;
94 
95     *object = &face->IDirect3DRMFace_iface;
96 
97     return hr;
98 }
99 
100 static HRESULT d3drm_create_mesh_builder_object(void **object, IDirect3DRM *d3drm)
101 {
102     struct d3drm_mesh_builder *mesh_builder;
103     HRESULT hr;
104 
105     if (FAILED(hr = d3drm_mesh_builder_create(&mesh_builder, d3drm)))
106         return hr;
107 
108     *object = &mesh_builder->IDirect3DRMMeshBuilder2_iface;
109 
110     return hr;
111 }
112 
113 static HRESULT d3drm_create_frame_object(void **object, IDirect3DRM *d3drm)
114 {
115     struct d3drm_frame *frame;
116     HRESULT hr;
117 
118     if (FAILED(hr = d3drm_frame_create(&frame, NULL, d3drm)))
119         return hr;
120 
121     *object = &frame->IDirect3DRMFrame_iface;
122 
123     return hr;
124 }
125 
126 static HRESULT d3drm_create_light_object(void **object, IDirect3DRM *d3drm)
127 {
128     struct d3drm_light *light;
129     HRESULT hr;
130 
131     if (FAILED(hr = d3drm_light_create(&light, d3drm)))
132         return hr;
133 
134     *object = &light->IDirect3DRMLight_iface;
135 
136     return hr;
137 }
138 
139 static HRESULT d3drm_create_material_object(void **object, IDirect3DRM *d3drm)
140 {
141     struct d3drm_material *material;
142     HRESULT hr;
143 
144     if (FAILED(hr = d3drm_material_create(&material, d3drm)))
145         return hr;
146 
147     *object = &material->IDirect3DRMMaterial2_iface;
148 
149     return hr;
150 }
151 
152 static HRESULT d3drm_create_mesh_object(void **object, IDirect3DRM *d3drm)
153 {
154     struct d3drm_mesh *mesh;
155     HRESULT hr;
156 
157     if (FAILED(hr = d3drm_mesh_create(&mesh, d3drm)))
158         return hr;
159 
160     *object = &mesh->IDirect3DRMMesh_iface;
161 
162     return hr;
163 }
164 
165 static HRESULT d3drm_create_animation_object(void **object, IDirect3DRM *d3drm)
166 {
167     struct d3drm_animation *animation;
168     HRESULT hr;
169 
170     if (FAILED(hr = d3drm_animation_create(&animation, d3drm)))
171         return hr;
172 
173     *object = &animation->IDirect3DRMAnimation_iface;
174 
175     return hr;
176 }
177 
178 static HRESULT d3drm_create_wrap_object(void **object, IDirect3DRM *d3drm)
179 {
180     struct d3drm_wrap *wrap;
181     HRESULT hr;
182 
183     if (FAILED(hr = d3drm_wrap_create(&wrap, d3drm)))
184         return hr;
185 
186     *object = &wrap->IDirect3DRMWrap_iface;
187 
188     return hr;
189 }
190 
191 struct d3drm
192 {
193     IDirect3DRM IDirect3DRM_iface;
194     IDirect3DRM2 IDirect3DRM2_iface;
195     IDirect3DRM3 IDirect3DRM3_iface;
196     LONG ref1, ref2, ref3, iface_count;
197 };
198 
199 static inline struct d3drm *impl_from_IDirect3DRM(IDirect3DRM *iface)
200 {
201     return CONTAINING_RECORD(iface, struct d3drm, IDirect3DRM_iface);
202 }
203 
204 static inline struct d3drm *impl_from_IDirect3DRM2(IDirect3DRM2 *iface)
205 {
206     return CONTAINING_RECORD(iface, struct d3drm, IDirect3DRM2_iface);
207 }
208 
209 static inline struct d3drm *impl_from_IDirect3DRM3(IDirect3DRM3 *iface)
210 {
211     return CONTAINING_RECORD(iface, struct d3drm, IDirect3DRM3_iface);
212 }
213 
214 static void d3drm_destroy(struct d3drm *d3drm)
215 {
216     heap_free(d3drm);
217     TRACE("d3drm object %p is being destroyed.\n", d3drm);
218 }
219 
220 static HRESULT WINAPI d3drm1_QueryInterface(IDirect3DRM *iface, REFIID riid, void **out)
221 {
222     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
223 
224     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
225 
226     if (IsEqualGUID(riid, &IID_IDirect3DRM)
227             || IsEqualGUID(riid, &IID_IUnknown))
228     {
229         *out = &d3drm->IDirect3DRM_iface;
230     }
231     else if (IsEqualGUID(riid, &IID_IDirect3DRM2))
232     {
233         *out = &d3drm->IDirect3DRM2_iface;
234     }
235     else if (IsEqualGUID(riid, &IID_IDirect3DRM3))
236     {
237         *out = &d3drm->IDirect3DRM3_iface;
238     }
239     else
240     {
241         *out = NULL;
242         WARN("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(riid));
243         return CLASS_E_CLASSNOTAVAILABLE;
244     }
245 
246     IUnknown_AddRef((IUnknown *)*out);
247     return S_OK;
248 }
249 
250 static ULONG WINAPI d3drm1_AddRef(IDirect3DRM *iface)
251 {
252     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
253     ULONG refcount = InterlockedIncrement(&d3drm->ref1);
254 
255     TRACE("%p increasing refcount to %u.\n", iface, refcount);
256 
257     if (refcount == 1)
258         InterlockedIncrement(&d3drm->iface_count);
259 
260     return refcount;
261 }
262 
263 static ULONG WINAPI d3drm1_Release(IDirect3DRM *iface)
264 {
265     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
266     ULONG refcount = InterlockedDecrement(&d3drm->ref1);
267 
268     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
269 
270     if (!refcount && !InterlockedDecrement(&d3drm->iface_count))
271         d3drm_destroy(d3drm);
272 
273     return refcount;
274 }
275 
276 static HRESULT WINAPI d3drm1_CreateObject(IDirect3DRM *iface,
277         REFCLSID clsid, IUnknown *outer, REFIID iid, void **out)
278 {
279     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
280 
281     TRACE("iface %p, clsid %s, outer %p, iid %s, out %p.\n",
282             iface, debugstr_guid(clsid), outer, debugstr_guid(iid), out);
283 
284     return IDirect3DRM3_CreateObject(&d3drm->IDirect3DRM3_iface, clsid, outer, iid, out);
285 }
286 
287 static HRESULT WINAPI d3drm1_CreateFrame(IDirect3DRM *iface,
288         IDirect3DRMFrame *parent_frame, IDirect3DRMFrame **frame)
289 {
290     struct d3drm_frame *object;
291     HRESULT hr;
292 
293     TRACE("iface %p, parent_frame %p, frame %p.\n", iface, parent_frame, frame);
294 
295     if (FAILED(hr = d3drm_frame_create(&object, (IUnknown *)parent_frame, iface)))
296         return hr;
297 
298     *frame = &object->IDirect3DRMFrame_iface;
299 
300     return D3DRM_OK;
301 }
302 
303 static HRESULT WINAPI d3drm1_CreateMesh(IDirect3DRM *iface, IDirect3DRMMesh **mesh)
304 {
305     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
306 
307     TRACE("iface %p, mesh %p.\n", iface, mesh);
308 
309     return IDirect3DRM3_CreateMesh(&d3drm->IDirect3DRM3_iface, mesh);
310 }
311 
312 static HRESULT WINAPI d3drm1_CreateMeshBuilder(IDirect3DRM *iface, IDirect3DRMMeshBuilder **mesh_builder)
313 {
314     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
315 
316     TRACE("iface %p, mesh_builder %p.\n", iface, mesh_builder);
317 
318     return IDirect3DRM2_CreateMeshBuilder(&d3drm->IDirect3DRM2_iface, (IDirect3DRMMeshBuilder2 **)mesh_builder);
319 }
320 
321 static HRESULT WINAPI d3drm1_CreateFace(IDirect3DRM *iface, IDirect3DRMFace **face)
322 {
323     struct d3drm_face *object;
324     HRESULT hr;
325 
326     TRACE("iface %p, face %p.\n", iface, face);
327 
328     if (FAILED(hr = d3drm_face_create(&object)))
329         return hr;
330 
331     *face = &object->IDirect3DRMFace_iface;
332 
333     return S_OK;
334 }
335 
336 static HRESULT WINAPI d3drm1_CreateAnimation(IDirect3DRM *iface, IDirect3DRMAnimation **animation)
337 {
338     struct d3drm_animation *object;
339     HRESULT hr;
340 
341     TRACE("iface %p, animation %p.\n", iface, animation);
342 
343     if (!animation)
344         return D3DRMERR_BADVALUE;
345 
346     if (FAILED(hr = d3drm_animation_create(&object, iface)))
347         return hr;
348 
349     *animation = &object->IDirect3DRMAnimation_iface;
350 
351     return S_OK;
352 }
353 
354 static HRESULT WINAPI d3drm1_CreateAnimationSet(IDirect3DRM *iface, IDirect3DRMAnimationSet **set)
355 {
356     FIXME("iface %p, set %p stub!\n", iface, set);
357 
358     return E_NOTIMPL;
359 }
360 
361 static HRESULT WINAPI d3drm1_CreateTexture(IDirect3DRM *iface,
362         D3DRMIMAGE *image, IDirect3DRMTexture **texture)
363 {
364     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
365     IDirect3DRMTexture3 *texture3;
366     HRESULT hr;
367 
368     TRACE("iface %p, image %p, texture %p.\n", iface, image, texture);
369 
370     if (!texture)
371         return D3DRMERR_BADVALUE;
372 
373     if (FAILED(hr = IDirect3DRM3_CreateTexture(&d3drm->IDirect3DRM3_iface, image, &texture3)))
374     {
375         *texture = NULL;
376         return hr;
377     }
378 
379     hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture, (void **)texture);
380     IDirect3DRMTexture3_Release(texture3);
381 
382     return hr;
383 }
384 
385 static HRESULT WINAPI d3drm1_CreateLight(IDirect3DRM *iface,
386         D3DRMLIGHTTYPE type, D3DCOLOR color, IDirect3DRMLight **light)
387 {
388     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
389 
390     TRACE("iface %p, type %#x, color 0x%08x, light %p.\n", iface, type, color, light);
391 
392     return IDirect3DRM3_CreateLight(&d3drm->IDirect3DRM3_iface, type, color, light);
393 }
394 
395 static HRESULT WINAPI d3drm1_CreateLightRGB(IDirect3DRM *iface, D3DRMLIGHTTYPE type,
396         D3DVALUE red, D3DVALUE green, D3DVALUE blue, IDirect3DRMLight **light)
397 {
398     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
399 
400     TRACE("iface %p, type %#x, red %.8e, green %.8e, blue %.8e, light %p.\n",
401             iface, type, red, green, blue, light);
402 
403     return IDirect3DRM3_CreateLightRGB(&d3drm->IDirect3DRM3_iface, type, red, green, blue, light);
404 }
405 
406 static HRESULT WINAPI d3drm1_CreateMaterial(IDirect3DRM *iface,
407         D3DVALUE power, IDirect3DRMMaterial **material)
408 {
409     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
410 
411     TRACE("iface %p, power %.8e, material %p.\n", iface, power, material);
412 
413     return IDirect3DRM3_CreateMaterial(&d3drm->IDirect3DRM3_iface, power, (IDirect3DRMMaterial2 **)material);
414 }
415 
416 static HRESULT WINAPI d3drm1_CreateDevice(IDirect3DRM *iface,
417         DWORD width, DWORD height, IDirect3DRMDevice **device)
418 {
419     struct d3drm_device *object;
420     HRESULT hr;
421 
422     FIXME("iface %p, width %u, height %u, device %p partial stub!\n", iface, width, height, device);
423 
424     if (FAILED(hr = d3drm_device_create(&object, iface)))
425         return hr;
426 
427     *device = &object->IDirect3DRMDevice_iface;
428 
429     return D3DRM_OK;
430 }
431 
432 static HRESULT WINAPI d3drm1_CreateDeviceFromSurface(IDirect3DRM *iface, GUID *guid,
433         IDirectDraw *ddraw, IDirectDrawSurface *backbuffer, IDirect3DRMDevice **device)
434 {
435     struct d3drm_device *object;
436     HRESULT hr;
437 
438     TRACE("iface %p, guid %s, ddraw %p, backbuffer %p, device %p.\n",
439             iface, debugstr_guid(guid), ddraw, backbuffer, device);
440 
441     if (!device)
442         return D3DRMERR_BADVALUE;
443     *device = NULL;
444 
445     if (!backbuffer || !ddraw)
446         return D3DRMERR_BADDEVICE;
447 
448     if (FAILED(hr = d3drm_device_create(&object, iface)))
449         return hr;
450 
451     if (SUCCEEDED(hr = d3drm_device_init(object, 1, ddraw, backbuffer, TRUE)))
452         *device = &object->IDirect3DRMDevice_iface;
453     else
454         d3drm_device_destroy(object);
455 
456     return hr;
457 }
458 
459 static HRESULT WINAPI d3drm1_CreateDeviceFromD3D(IDirect3DRM *iface,
460         IDirect3D *d3d, IDirect3DDevice *d3d_device, IDirect3DRMDevice **device)
461 {
462     struct d3drm_device *object;
463     HRESULT hr;
464     TRACE("iface %p, d3d %p, d3d_device %p, device %p.\n",
465             iface, d3d, d3d_device, device);
466 
467     if (!device)
468         return D3DRMERR_BADVALUE;
469     *device = NULL;
470 
471     if (FAILED(hr = d3drm_device_create(&object, iface)))
472         return hr;
473 
474     if (FAILED(hr = IDirect3DRMDevice_InitFromD3D(&object->IDirect3DRMDevice_iface, d3d, d3d_device)))
475     {
476         d3drm_device_destroy(object);
477         return hr;
478     }
479     *device = &object->IDirect3DRMDevice_iface;
480 
481     return D3DRM_OK;
482 }
483 
484 static HRESULT WINAPI d3drm1_CreateDeviceFromClipper(IDirect3DRM *iface,
485         IDirectDrawClipper *clipper, GUID *guid, int width, int height,
486         IDirect3DRMDevice **device)
487 {
488     struct d3drm_device *object;
489     IDirectDraw *ddraw;
490     IDirectDrawSurface *render_target;
491     HRESULT hr;
492 
493     TRACE("iface %p, clipper %p, guid %s, width %d, height %d, device %p.\n",
494             iface, clipper, debugstr_guid(guid), width, height, device);
495 
496     if (!device)
497         return D3DRMERR_BADVALUE;
498     *device = NULL;
499 
500     if (!clipper || !width || !height)
501         return D3DRMERR_BADVALUE;
502 
503     hr = DirectDrawCreate(NULL, &ddraw, NULL);
504     if (FAILED(hr))
505         return hr;
506 
507     if (FAILED(hr = d3drm_device_create(&object, iface)))
508     {
509         IDirectDraw_Release(ddraw);
510         return hr;
511     }
512 
513     hr = d3drm_device_create_surfaces_from_clipper(object, ddraw, clipper, width, height, &render_target);
514     if (FAILED(hr))
515     {
516         IDirectDraw_Release(ddraw);
517         d3drm_device_destroy(object);
518         return hr;
519     }
520 
521     hr = d3drm_device_init(object, 1, ddraw, render_target, TRUE);
522     IDirectDraw_Release(ddraw);
523     IDirectDrawSurface_Release(render_target);
524     if (FAILED(hr))
525         d3drm_device_destroy(object);
526     else
527         *device = &object->IDirect3DRMDevice_iface;
528 
529     return hr;
530 }
531 
532 static HRESULT WINAPI d3drm1_CreateTextureFromSurface(IDirect3DRM *iface,
533         IDirectDrawSurface *surface, IDirect3DRMTexture **texture)
534 {
535     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
536     IDirect3DRMTexture3 *texture3;
537     HRESULT hr;
538 
539     TRACE("iface %p, surface %p, texture %p.\n", iface, surface, texture);
540 
541     if (!texture)
542         return D3DRMERR_BADVALUE;
543 
544     if (FAILED(hr = IDirect3DRM3_CreateTextureFromSurface(&d3drm->IDirect3DRM3_iface, surface, &texture3)))
545     {
546         *texture = NULL;
547         return hr;
548     }
549 
550     hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture, (void **)texture);
551     IDirect3DRMTexture3_Release(texture3);
552 
553     return hr;
554 }
555 
556 static HRESULT WINAPI d3drm1_CreateShadow(IDirect3DRM *iface, IDirect3DRMVisual *visual,
557         IDirect3DRMLight *light, D3DVALUE px, D3DVALUE py, D3DVALUE pz, D3DVALUE nx, D3DVALUE ny, D3DVALUE nz,
558         IDirect3DRMVisual **shadow)
559 {
560     FIXME("iface %p, visual %p, light %p, px %.8e, py %.8e, pz %.8e, nx %.8e, ny %.8e, nz %.8e, shadow %p stub!\n",
561             iface, visual, light, px, py, pz, nx, ny, nz, shadow);
562 
563     return E_NOTIMPL;
564 }
565 
566 static HRESULT WINAPI d3drm1_CreateViewport(IDirect3DRM *iface, IDirect3DRMDevice *device,
567         IDirect3DRMFrame *camera, DWORD x, DWORD y, DWORD width, DWORD height, IDirect3DRMViewport **viewport)
568 {
569     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
570     IDirect3DRMDevice3 *device3;
571     IDirect3DRMFrame3 *camera3;
572     IDirect3DRMViewport2 *viewport2;
573     HRESULT hr;
574 
575     TRACE("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u, viewport %p.\n",
576             iface, device, camera, x, y, width, height, viewport);
577 
578     if (!device || !camera)
579         return D3DRMERR_BADOBJECT;
580     if (!viewport)
581         return D3DRMERR_BADVALUE;
582 
583     if (FAILED(hr = IDirect3DRMDevice_QueryInterface(device, &IID_IDirect3DRMDevice3, (void **)&device3)))
584         return hr;
585 
586     if (FAILED(hr = IDirect3DRMFrame_QueryInterface(camera, &IID_IDirect3DRMFrame3, (void **)&camera3)))
587     {
588         IDirect3DRMDevice3_Release(device3);
589         return hr;
590     }
591 
592     hr = IDirect3DRM3_CreateViewport(&d3drm->IDirect3DRM3_iface, device3, camera3, x, y, width, height, &viewport2);
593     IDirect3DRMDevice3_Release(device3);
594     IDirect3DRMFrame3_Release(camera3);
595     if (FAILED(hr))
596         return hr;
597 
598     hr = IDirect3DRMViewport2_QueryInterface(viewport2, &IID_IDirect3DRMViewport, (void **)viewport);
599     IDirect3DRMViewport2_Release(viewport2);
600 
601     return hr;
602 }
603 
604 static HRESULT WINAPI d3drm1_CreateWrap(IDirect3DRM *iface, D3DRMWRAPTYPE type, IDirect3DRMFrame *frame,
605         D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
606         D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, D3DVALUE ou, D3DVALUE ov, D3DVALUE su, D3DVALUE sv,
607         IDirect3DRMWrap **wrap)
608 {
609     struct d3drm_wrap *object;
610     HRESULT hr;
611 
612     FIXME("iface %p, type %#x, frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, "
613             "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p, semi-stub.\n",
614             iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz, ou, ov, su, sv, wrap);
615 
616     if (!wrap)
617         return D3DRMERR_BADVALUE;
618 
619     if (FAILED(hr = d3drm_wrap_create(&object, iface)))
620         return hr;
621 
622     *wrap = &object->IDirect3DRMWrap_iface;
623 
624     return S_OK;
625 }
626 
627 static HRESULT WINAPI d3drm1_CreateUserVisual(IDirect3DRM *iface,
628         D3DRMUSERVISUALCALLBACK cb, void *ctx, IDirect3DRMUserVisual **visual)
629 {
630     FIXME("iface %p, cb %p, ctx %p visual %p stub!\n", iface, cb, ctx, visual);
631 
632     return E_NOTIMPL;
633 }
634 
635 static HRESULT WINAPI d3drm1_LoadTexture(IDirect3DRM *iface,
636         const char *filename, IDirect3DRMTexture **texture)
637 {
638     struct d3drm_texture *object;
639     HRESULT hr;
640 
641     TRACE("iface %p, filename %s, texture %p.\n", iface, debugstr_a(filename), texture);
642 
643     if (!texture)
644         return D3DRMERR_BADVALUE;
645 
646     if (FAILED(hr = d3drm_texture_create(&object, iface)))
647         return hr;
648 
649     *texture = &object->IDirect3DRMTexture_iface;
650     if (FAILED(hr = IDirect3DRMTexture_InitFromFile(*texture, filename)))
651     {
652         IDirect3DRMTexture_Release(*texture);
653         *texture = NULL;
654         if (!filename)
655             return D3DRMERR_BADVALUE;
656 
657         return hr == D3DRMERR_BADOBJECT ? D3DRMERR_FILENOTFOUND : hr;
658     }
659 
660     return D3DRM_OK;
661 }
662 
663 static HRESULT WINAPI d3drm1_LoadTextureFromResource(IDirect3DRM *iface,
664         HRSRC resource, IDirect3DRMTexture **texture)
665 {
666     struct d3drm_texture *object;
667     HRESULT hr;
668 
669     FIXME("iface %p, resource %p, texture %p stub!\n", iface, resource, texture);
670 
671     if (FAILED(hr = d3drm_texture_create(&object, iface)))
672         return hr;
673 
674     *texture = &object->IDirect3DRMTexture_iface;
675 
676     return D3DRM_OK;
677 }
678 
679 static HRESULT WINAPI d3drm1_SetSearchPath(IDirect3DRM *iface, const char *path)
680 {
681     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
682 
683     return E_NOTIMPL;
684 }
685 
686 static HRESULT WINAPI d3drm1_AddSearchPath(IDirect3DRM *iface, const char *path)
687 {
688     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
689 
690     return E_NOTIMPL;
691 }
692 
693 static HRESULT WINAPI d3drm1_GetSearchPath(IDirect3DRM *iface, DWORD *size, char *path)
694 {
695     FIXME("iface %p, size %p, path %p stub!\n", iface, size, path);
696 
697     return E_NOTIMPL;
698 }
699 
700 static HRESULT WINAPI d3drm1_SetDefaultTextureColors(IDirect3DRM *iface, DWORD color_count)
701 {
702     FIXME("iface %p, color_count %u stub!\n", iface, color_count);
703 
704     return E_NOTIMPL;
705 }
706 
707 static HRESULT WINAPI d3drm1_SetDefaultTextureShades(IDirect3DRM *iface, DWORD shade_count)
708 {
709     FIXME("iface %p, shade_count %u stub!\n", iface, shade_count);
710 
711     return E_NOTIMPL;
712 }
713 
714 static HRESULT WINAPI d3drm1_GetDevices(IDirect3DRM *iface, IDirect3DRMDeviceArray **array)
715 {
716     FIXME("iface %p, array %p stub!\n", iface, array);
717 
718     return E_NOTIMPL;
719 }
720 
721 static HRESULT WINAPI d3drm1_GetNamedObject(IDirect3DRM *iface,
722         const char *name, IDirect3DRMObject **object)
723 {
724     FIXME("iface %p, name %s, object %p stub!\n", iface, debugstr_a(name), object);
725 
726     return E_NOTIMPL;
727 }
728 
729 static HRESULT WINAPI d3drm1_EnumerateObjects(IDirect3DRM *iface, D3DRMOBJECTCALLBACK cb, void *ctx)
730 {
731     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
732 
733     return E_NOTIMPL;
734 }
735 
736 static HRESULT WINAPI d3drm1_Load(IDirect3DRM *iface, void *source, void *object_id, IID **iids,
737         DWORD iid_count, D3DRMLOADOPTIONS flags, D3DRMLOADCALLBACK load_cb, void *load_ctx,
738         D3DRMLOADTEXTURECALLBACK load_tex_cb, void *load_tex_ctx, IDirect3DRMFrame *parent_frame)
739 {
740     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
741     IDirect3DRMFrame3 *parent_frame3 = NULL;
742     HRESULT hr = D3DRM_OK;
743 
744     TRACE("iface %p, source %p, object_id %p, iids %p, iid_count %u, flags %#x, "
745             "load_cb %p, load_ctx %p, load_tex_cb %p, load_tex_ctx %p, parent_frame %p.\n",
746             iface, source, object_id, iids, iid_count, flags,
747             load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame);
748 
749     if (parent_frame)
750         hr = IDirect3DRMFrame_QueryInterface(parent_frame, &IID_IDirect3DRMFrame3, (void **)&parent_frame3);
751     if (SUCCEEDED(hr))
752         hr = IDirect3DRM3_Load(&d3drm->IDirect3DRM3_iface, source, object_id, iids, iid_count,
753                 flags, load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame3);
754     if (parent_frame3)
755         IDirect3DRMFrame3_Release(parent_frame3);
756 
757     return hr;
758 }
759 
760 static HRESULT WINAPI d3drm1_Tick(IDirect3DRM *iface, D3DVALUE tick)
761 {
762     FIXME("iface %p, tick %.8e stub!\n", iface, tick);
763 
764     return E_NOTIMPL;
765 }
766 
767 static const struct IDirect3DRMVtbl d3drm1_vtbl =
768 {
769     d3drm1_QueryInterface,
770     d3drm1_AddRef,
771     d3drm1_Release,
772     d3drm1_CreateObject,
773     d3drm1_CreateFrame,
774     d3drm1_CreateMesh,
775     d3drm1_CreateMeshBuilder,
776     d3drm1_CreateFace,
777     d3drm1_CreateAnimation,
778     d3drm1_CreateAnimationSet,
779     d3drm1_CreateTexture,
780     d3drm1_CreateLight,
781     d3drm1_CreateLightRGB,
782     d3drm1_CreateMaterial,
783     d3drm1_CreateDevice,
784     d3drm1_CreateDeviceFromSurface,
785     d3drm1_CreateDeviceFromD3D,
786     d3drm1_CreateDeviceFromClipper,
787     d3drm1_CreateTextureFromSurface,
788     d3drm1_CreateShadow,
789     d3drm1_CreateViewport,
790     d3drm1_CreateWrap,
791     d3drm1_CreateUserVisual,
792     d3drm1_LoadTexture,
793     d3drm1_LoadTextureFromResource,
794     d3drm1_SetSearchPath,
795     d3drm1_AddSearchPath,
796     d3drm1_GetSearchPath,
797     d3drm1_SetDefaultTextureColors,
798     d3drm1_SetDefaultTextureShades,
799     d3drm1_GetDevices,
800     d3drm1_GetNamedObject,
801     d3drm1_EnumerateObjects,
802     d3drm1_Load,
803     d3drm1_Tick,
804 };
805 
806 static HRESULT WINAPI d3drm2_QueryInterface(IDirect3DRM2 *iface, REFIID riid, void **out)
807 {
808     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
809 
810     return d3drm1_QueryInterface(&d3drm->IDirect3DRM_iface, riid, out);
811 }
812 
813 static ULONG WINAPI d3drm2_AddRef(IDirect3DRM2 *iface)
814 {
815     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
816     ULONG refcount = InterlockedIncrement(&d3drm->ref2);
817 
818     TRACE("%p increasing refcount to %u.\n", iface, refcount);
819 
820     if (refcount == 1)
821         InterlockedIncrement(&d3drm->iface_count);
822 
823     return refcount;
824 }
825 
826 static ULONG WINAPI d3drm2_Release(IDirect3DRM2 *iface)
827 {
828     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
829     ULONG refcount = InterlockedDecrement(&d3drm->ref2);
830 
831     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
832 
833     if (!refcount && !InterlockedDecrement(&d3drm->iface_count))
834         d3drm_destroy(d3drm);
835 
836     return refcount;
837 }
838 
839 static HRESULT WINAPI d3drm2_CreateObject(IDirect3DRM2 *iface,
840         REFCLSID clsid, IUnknown *outer, REFIID iid, void **out)
841 {
842     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
843 
844     TRACE("iface %p, clsid %s, outer %p, iid %s, out %p.\n",
845             iface, debugstr_guid(clsid), outer, debugstr_guid(iid), out);
846 
847     return IDirect3DRM3_CreateObject(&d3drm->IDirect3DRM3_iface, clsid, outer, iid, out);
848 }
849 
850 static HRESULT WINAPI d3drm2_CreateFrame(IDirect3DRM2 *iface,
851         IDirect3DRMFrame *parent_frame, IDirect3DRMFrame2 **frame)
852 {
853     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
854     struct d3drm_frame *object;
855     HRESULT hr;
856 
857     TRACE("iface %p, parent_frame %p, frame %p.\n", iface, parent_frame, frame);
858 
859     if (FAILED(hr = d3drm_frame_create(&object, (IUnknown *)parent_frame, &d3drm->IDirect3DRM_iface)))
860         return hr;
861 
862     *frame = &object->IDirect3DRMFrame2_iface;
863 
864     return D3DRM_OK;
865 }
866 
867 static HRESULT WINAPI d3drm2_CreateMesh(IDirect3DRM2 *iface, IDirect3DRMMesh **mesh)
868 {
869     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
870 
871     TRACE("iface %p, mesh %p.\n", iface, mesh);
872 
873     return IDirect3DRM3_CreateMesh(&d3drm->IDirect3DRM3_iface, mesh);
874 }
875 
876 static HRESULT WINAPI d3drm2_CreateMeshBuilder(IDirect3DRM2 *iface, IDirect3DRMMeshBuilder2 **mesh_builder)
877 {
878     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
879     struct d3drm_mesh_builder *object;
880     HRESULT hr;
881 
882     TRACE("iface %p, mesh_builder %p.\n", iface, mesh_builder);
883 
884     if (FAILED(hr = d3drm_mesh_builder_create(&object, &d3drm->IDirect3DRM_iface)))
885         return hr;
886 
887     *mesh_builder = &object->IDirect3DRMMeshBuilder2_iface;
888 
889     return S_OK;
890 }
891 
892 static HRESULT WINAPI d3drm2_CreateFace(IDirect3DRM2 *iface, IDirect3DRMFace **face)
893 {
894     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
895 
896     TRACE("iface %p, face %p.\n", iface, face);
897 
898     return IDirect3DRM_CreateFace(&d3drm->IDirect3DRM_iface, face);
899 }
900 
901 static HRESULT WINAPI d3drm2_CreateAnimation(IDirect3DRM2 *iface, IDirect3DRMAnimation **animation)
902 {
903     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
904 
905     TRACE("iface %p, animation %p.\n", iface, animation);
906 
907     return IDirect3DRM_CreateAnimation(&d3drm->IDirect3DRM_iface, animation);
908 }
909 
910 static HRESULT WINAPI d3drm2_CreateAnimationSet(IDirect3DRM2 *iface, IDirect3DRMAnimationSet **set)
911 {
912     FIXME("iface %p, set %p stub!\n", iface, set);
913 
914     return E_NOTIMPL;
915 }
916 
917 static HRESULT WINAPI d3drm2_CreateTexture(IDirect3DRM2 *iface,
918         D3DRMIMAGE *image, IDirect3DRMTexture2 **texture)
919 {
920     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
921     IDirect3DRMTexture3 *texture3;
922     HRESULT hr;
923 
924     TRACE("iface %p, image %p, texture %p.\n", iface, image, texture);
925 
926     if (!texture)
927         return D3DRMERR_BADVALUE;
928 
929     if (FAILED(hr = IDirect3DRM3_CreateTexture(&d3drm->IDirect3DRM3_iface, image, &texture3)))
930     {
931         *texture = NULL;
932         return hr;
933     }
934 
935     hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture2, (void **)texture);
936     IDirect3DRMTexture3_Release(texture3);
937 
938     return hr;
939 }
940 
941 static HRESULT WINAPI d3drm2_CreateLight(IDirect3DRM2 *iface,
942         D3DRMLIGHTTYPE type, D3DCOLOR color, IDirect3DRMLight **light)
943 {
944     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
945 
946     TRACE("iface %p, type %#x, color 0x%08x, light %p.\n", iface, type, color, light);
947 
948     return IDirect3DRM3_CreateLight(&d3drm->IDirect3DRM3_iface, type, color, light);
949 }
950 
951 static HRESULT WINAPI d3drm2_CreateLightRGB(IDirect3DRM2 *iface, D3DRMLIGHTTYPE type,
952         D3DVALUE red, D3DVALUE green, D3DVALUE blue, IDirect3DRMLight **light)
953 {
954     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
955 
956     TRACE("iface %p, type %#x, red %.8e, green %.8e, blue %.8e, light %p.\n",
957             iface, type, red, green, blue, light);
958 
959     return IDirect3DRM3_CreateLightRGB(&d3drm->IDirect3DRM3_iface, type, red, green, blue, light);
960 }
961 
962 static HRESULT WINAPI d3drm2_CreateMaterial(IDirect3DRM2 *iface,
963         D3DVALUE power, IDirect3DRMMaterial **material)
964 {
965     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
966 
967     TRACE("iface %p, power %.8e, material %p.\n", iface, power, material);
968 
969     return IDirect3DRM3_CreateMaterial(&d3drm->IDirect3DRM3_iface, power, (IDirect3DRMMaterial2 **)material);
970 }
971 
972 static HRESULT WINAPI d3drm2_CreateDevice(IDirect3DRM2 *iface,
973         DWORD width, DWORD height, IDirect3DRMDevice2 **device)
974 {
975     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
976     struct d3drm_device *object;
977     HRESULT hr;
978 
979     FIXME("iface %p, width %u, height %u, device %p partial stub!\n", iface, width, height, device);
980 
981     if (FAILED(hr = d3drm_device_create(&object, &d3drm->IDirect3DRM_iface)))
982         return hr;
983 
984     *device = &object->IDirect3DRMDevice2_iface;
985 
986     return D3DRM_OK;
987 }
988 
989 static HRESULT WINAPI d3drm2_CreateDeviceFromSurface(IDirect3DRM2 *iface, GUID *guid,
990         IDirectDraw *ddraw, IDirectDrawSurface *backbuffer, IDirect3DRMDevice2 **device)
991 {
992     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
993     IDirect3DRMDevice3 *device3;
994     HRESULT hr;
995     TRACE("iface %p, guid %s, ddraw %p, backbuffer %p, device %p.\n",
996             iface, debugstr_guid(guid), ddraw, backbuffer, device);
997 
998     if (!device)
999         return D3DRMERR_BADVALUE;
1000     *device = NULL;
1001     hr = IDirect3DRM3_CreateDeviceFromSurface(&d3drm->IDirect3DRM3_iface, guid, ddraw, backbuffer, 0, &device3);
1002     if (FAILED(hr))
1003         return hr;
1004 
1005     hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice2, (void**)device);
1006     IDirect3DRMDevice3_Release(device3);
1007 
1008     return hr;
1009 }
1010 
1011 static HRESULT WINAPI d3drm2_CreateDeviceFromD3D(IDirect3DRM2 *iface,
1012     IDirect3D2 *d3d, IDirect3DDevice2 *d3d_device, IDirect3DRMDevice2 **device)
1013 {
1014     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1015     IDirect3DRMDevice3 *device3;
1016     HRESULT hr;
1017 
1018     TRACE("iface %p, d3d %p, d3d_device %p, device %p.\n",
1019             iface, d3d, d3d_device, device);
1020 
1021     if (!device)
1022         return D3DRMERR_BADVALUE;
1023     *device = NULL;
1024 
1025     hr = IDirect3DRM3_CreateDeviceFromD3D(&d3drm->IDirect3DRM3_iface, d3d, d3d_device, &device3);
1026     if (FAILED(hr))
1027         return hr;
1028 
1029     hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice2, (void **)device);
1030     IDirect3DRMDevice3_Release(device3);
1031 
1032     return hr;
1033 }
1034 
1035 static HRESULT WINAPI d3drm2_CreateDeviceFromClipper(IDirect3DRM2 *iface,
1036         IDirectDrawClipper *clipper, GUID *guid, int width, int height,
1037         IDirect3DRMDevice2 **device)
1038 {
1039     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1040     IDirect3DRMDevice3 *device3;
1041     HRESULT hr;
1042 
1043     TRACE("iface %p, clipper %p, guid %s, width %d, height %d, device %p.\n",
1044             iface, clipper, debugstr_guid(guid), width, height, device);
1045 
1046     if (!device)
1047         return D3DRMERR_BADVALUE;
1048     *device = NULL;
1049     hr = IDirect3DRM3_CreateDeviceFromClipper(&d3drm->IDirect3DRM3_iface, clipper, guid, width, height, &device3);
1050     if (FAILED(hr))
1051         return hr;
1052 
1053     hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice2, (void**)device);
1054     IDirect3DRMDevice3_Release(device3);
1055 
1056     return hr;
1057 }
1058 
1059 static HRESULT WINAPI d3drm2_CreateTextureFromSurface(IDirect3DRM2 *iface,
1060         IDirectDrawSurface *surface, IDirect3DRMTexture2 **texture)
1061 {
1062     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1063     IDirect3DRMTexture3 *texture3;
1064     HRESULT hr;
1065 
1066     TRACE("iface %p, surface %p, texture %p.\n", iface, surface, texture);
1067 
1068     if (!texture)
1069         return D3DRMERR_BADVALUE;
1070 
1071     if (FAILED(hr = IDirect3DRM3_CreateTextureFromSurface(&d3drm->IDirect3DRM3_iface, surface, &texture3)))
1072     {
1073         *texture = NULL;
1074         return hr;
1075     }
1076 
1077     hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture, (void **)texture);
1078     IDirect3DRMTexture3_Release(texture3);
1079 
1080     return hr;
1081 }
1082 
1083 static HRESULT WINAPI d3drm2_CreateShadow(IDirect3DRM2 *iface, IDirect3DRMVisual *visual,
1084         IDirect3DRMLight *light, D3DVALUE px, D3DVALUE py, D3DVALUE pz, D3DVALUE nx, D3DVALUE ny, D3DVALUE nz,
1085         IDirect3DRMVisual **shadow)
1086 {
1087     FIXME("iface %p, visual %p, light %p, px %.8e, py %.8e, pz %.8e, nx %.8e, ny %.8e, nz %.8e, shadow %p stub!\n",
1088             iface, visual, light, px, py, pz, nx, ny, nz, shadow);
1089 
1090     return E_NOTIMPL;
1091 }
1092 
1093 static HRESULT WINAPI d3drm2_CreateViewport(IDirect3DRM2 *iface, IDirect3DRMDevice *device,
1094         IDirect3DRMFrame *camera, DWORD x, DWORD y, DWORD width, DWORD height, IDirect3DRMViewport **viewport)
1095 {
1096     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1097     IDirect3DRMDevice3 *device3;
1098     IDirect3DRMFrame3 *camera3;
1099     IDirect3DRMViewport2 *viewport2;
1100     HRESULT hr;
1101 
1102     TRACE("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u, viewport %p.\n",
1103           iface, device, camera, x, y, width, height, viewport);
1104 
1105     if (!device || !camera)
1106         return D3DRMERR_BADOBJECT;
1107     if (!viewport)
1108         return D3DRMERR_BADVALUE;
1109 
1110     if (FAILED(hr = IDirect3DRMDevice_QueryInterface(device, &IID_IDirect3DRMDevice3, (void **)&device3)))
1111         return hr;
1112 
1113     if (FAILED(hr = IDirect3DRMFrame_QueryInterface(camera, &IID_IDirect3DRMFrame3, (void **)&camera3)))
1114     {
1115         IDirect3DRMDevice3_Release(device3);
1116         return hr;
1117     }
1118 
1119     hr = IDirect3DRM3_CreateViewport(&d3drm->IDirect3DRM3_iface, device3, camera3, x, y, width, height, &viewport2);
1120     IDirect3DRMDevice3_Release(device3);
1121     IDirect3DRMFrame3_Release(camera3);
1122     if (FAILED(hr))
1123         return hr;
1124 
1125     hr = IDirect3DRMViewport2_QueryInterface(viewport2, &IID_IDirect3DRMViewport, (void **)viewport);
1126     IDirect3DRMViewport2_Release(viewport2);
1127 
1128     return hr;
1129 }
1130 
1131 static HRESULT WINAPI d3drm2_CreateWrap(IDirect3DRM2 *iface, D3DRMWRAPTYPE type, IDirect3DRMFrame *frame,
1132         D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
1133         D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, D3DVALUE ou, D3DVALUE ov, D3DVALUE su, D3DVALUE sv,
1134         IDirect3DRMWrap **wrap)
1135 {
1136     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1137 
1138     TRACE("iface %p, type %#x, frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, "
1139             "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p.\n",
1140             iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz, ou, ov, su, sv, wrap);
1141 
1142     return IDirect3DRM_CreateWrap(&d3drm->IDirect3DRM_iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz,
1143             ou, ov, su, sv, wrap);
1144 }
1145 
1146 static HRESULT WINAPI d3drm2_CreateUserVisual(IDirect3DRM2 *iface,
1147         D3DRMUSERVISUALCALLBACK cb, void *ctx, IDirect3DRMUserVisual **visual)
1148 {
1149     FIXME("iface %p, cb %p, ctx %p, visual %p stub!\n", iface, cb, ctx, visual);
1150 
1151     return E_NOTIMPL;
1152 }
1153 
1154 static HRESULT WINAPI d3drm2_LoadTexture(IDirect3DRM2 *iface,
1155         const char *filename, IDirect3DRMTexture2 **texture)
1156 {
1157     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1158     IDirect3DRMTexture3 *texture3;
1159     HRESULT hr;
1160 
1161     TRACE("iface %p, filename %s, texture %p.\n", iface, debugstr_a(filename), texture);
1162 
1163     if (!texture)
1164         return D3DRMERR_BADVALUE;
1165 
1166     if (FAILED(hr = IDirect3DRM3_LoadTexture(&d3drm->IDirect3DRM3_iface, filename, &texture3)))
1167     {
1168         *texture = NULL;
1169         return hr;
1170     }
1171 
1172     hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture2, (void **)texture);
1173     IDirect3DRMTexture3_Release(texture3);
1174 
1175     return hr;
1176 }
1177 
1178 static HRESULT WINAPI d3drm2_LoadTextureFromResource(IDirect3DRM2 *iface, HMODULE module,
1179         const char *resource_name, const char *resource_type, IDirect3DRMTexture2 **texture)
1180 {
1181     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1182     struct d3drm_texture *object;
1183     HRESULT hr;
1184 
1185     FIXME("iface %p, resource_name %s, resource_type %s, texture %p stub!\n",
1186             iface, debugstr_a(resource_name), debugstr_a(resource_type), texture);
1187 
1188     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1189         return hr;
1190 
1191     *texture = &object->IDirect3DRMTexture2_iface;
1192 
1193     return D3DRM_OK;
1194 }
1195 
1196 static HRESULT WINAPI d3drm2_SetSearchPath(IDirect3DRM2 *iface, const char *path)
1197 {
1198     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
1199 
1200     return E_NOTIMPL;
1201 }
1202 
1203 static HRESULT WINAPI d3drm2_AddSearchPath(IDirect3DRM2 *iface, const char *path)
1204 {
1205     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
1206 
1207     return E_NOTIMPL;
1208 }
1209 
1210 static HRESULT WINAPI d3drm2_GetSearchPath(IDirect3DRM2 *iface, DWORD *size, char *path)
1211 {
1212     FIXME("iface %p, size %p, path %p stub!\n", iface, size, path);
1213 
1214     return E_NOTIMPL;
1215 }
1216 
1217 static HRESULT WINAPI d3drm2_SetDefaultTextureColors(IDirect3DRM2 *iface, DWORD color_count)
1218 {
1219     FIXME("iface %p, color_count %u stub!\n", iface, color_count);
1220 
1221     return E_NOTIMPL;
1222 }
1223 
1224 static HRESULT WINAPI d3drm2_SetDefaultTextureShades(IDirect3DRM2 *iface, DWORD shade_count)
1225 {
1226     FIXME("iface %p, shade_count %u stub!\n", iface, shade_count);
1227 
1228     return E_NOTIMPL;
1229 }
1230 
1231 static HRESULT WINAPI d3drm2_GetDevices(IDirect3DRM2 *iface, IDirect3DRMDeviceArray **array)
1232 {
1233     FIXME("iface %p, array %p stub!\n", iface, array);
1234 
1235     return E_NOTIMPL;
1236 }
1237 
1238 static HRESULT WINAPI d3drm2_GetNamedObject(IDirect3DRM2 *iface,
1239         const char *name, IDirect3DRMObject **object)
1240 {
1241     FIXME("iface %p, name %s, object %p stub!\n", iface, debugstr_a(name), object);
1242 
1243     return E_NOTIMPL;
1244 }
1245 
1246 static HRESULT WINAPI d3drm2_EnumerateObjects(IDirect3DRM2 *iface, D3DRMOBJECTCALLBACK cb, void *ctx)
1247 {
1248     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
1249 
1250     return E_NOTIMPL;
1251 }
1252 
1253 static HRESULT WINAPI d3drm2_Load(IDirect3DRM2 *iface, void *source, void *object_id, IID **iids,
1254         DWORD iid_count, D3DRMLOADOPTIONS flags, D3DRMLOADCALLBACK load_cb, void *load_ctx,
1255         D3DRMLOADTEXTURECALLBACK load_tex_cb, void *load_tex_ctx, IDirect3DRMFrame *parent_frame)
1256 {
1257     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1258     IDirect3DRMFrame3 *parent_frame3 = NULL;
1259     HRESULT hr = D3DRM_OK;
1260 
1261     TRACE("iface %p, source %p, object_id %p, iids %p, iid_count %u, flags %#x, "
1262             "load_cb %p, load_ctx %p, load_tex_cb %p, load_tex_ctx %p, parent_frame %p.\n",
1263             iface, source, object_id, iids, iid_count, flags,
1264             load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame);
1265 
1266     if (parent_frame)
1267         hr = IDirect3DRMFrame_QueryInterface(parent_frame, &IID_IDirect3DRMFrame3, (void **)&parent_frame3);
1268     if (SUCCEEDED(hr))
1269         hr = IDirect3DRM3_Load(&d3drm->IDirect3DRM3_iface, source, object_id, iids, iid_count,
1270                 flags, load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame3);
1271     if (parent_frame3)
1272         IDirect3DRMFrame3_Release(parent_frame3);
1273 
1274     return hr;
1275 }
1276 
1277 static HRESULT WINAPI d3drm2_Tick(IDirect3DRM2 *iface, D3DVALUE tick)
1278 {
1279     FIXME("iface %p, tick %.8e stub!\n", iface, tick);
1280 
1281     return E_NOTIMPL;
1282 }
1283 
1284 static HRESULT WINAPI d3drm2_CreateProgressiveMesh(IDirect3DRM2 *iface, IDirect3DRMProgressiveMesh **mesh)
1285 {
1286     FIXME("iface %p, mesh %p stub!\n", iface, mesh);
1287 
1288     return E_NOTIMPL;
1289 }
1290 
1291 static const struct IDirect3DRM2Vtbl d3drm2_vtbl =
1292 {
1293     d3drm2_QueryInterface,
1294     d3drm2_AddRef,
1295     d3drm2_Release,
1296     d3drm2_CreateObject,
1297     d3drm2_CreateFrame,
1298     d3drm2_CreateMesh,
1299     d3drm2_CreateMeshBuilder,
1300     d3drm2_CreateFace,
1301     d3drm2_CreateAnimation,
1302     d3drm2_CreateAnimationSet,
1303     d3drm2_CreateTexture,
1304     d3drm2_CreateLight,
1305     d3drm2_CreateLightRGB,
1306     d3drm2_CreateMaterial,
1307     d3drm2_CreateDevice,
1308     d3drm2_CreateDeviceFromSurface,
1309     d3drm2_CreateDeviceFromD3D,
1310     d3drm2_CreateDeviceFromClipper,
1311     d3drm2_CreateTextureFromSurface,
1312     d3drm2_CreateShadow,
1313     d3drm2_CreateViewport,
1314     d3drm2_CreateWrap,
1315     d3drm2_CreateUserVisual,
1316     d3drm2_LoadTexture,
1317     d3drm2_LoadTextureFromResource,
1318     d3drm2_SetSearchPath,
1319     d3drm2_AddSearchPath,
1320     d3drm2_GetSearchPath,
1321     d3drm2_SetDefaultTextureColors,
1322     d3drm2_SetDefaultTextureShades,
1323     d3drm2_GetDevices,
1324     d3drm2_GetNamedObject,
1325     d3drm2_EnumerateObjects,
1326     d3drm2_Load,
1327     d3drm2_Tick,
1328     d3drm2_CreateProgressiveMesh,
1329 };
1330 
1331 static HRESULT WINAPI d3drm3_QueryInterface(IDirect3DRM3 *iface, REFIID riid, void **out)
1332 {
1333     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1334 
1335     return d3drm1_QueryInterface(&d3drm->IDirect3DRM_iface, riid, out);
1336 }
1337 
1338 static ULONG WINAPI d3drm3_AddRef(IDirect3DRM3 *iface)
1339 {
1340     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1341     ULONG refcount = InterlockedIncrement(&d3drm->ref3);
1342 
1343     TRACE("%p increasing refcount to %u.\n", iface, refcount);
1344 
1345     if (refcount == 1)
1346         InterlockedIncrement(&d3drm->iface_count);
1347 
1348     return refcount;
1349 }
1350 
1351 static ULONG WINAPI d3drm3_Release(IDirect3DRM3 *iface)
1352 {
1353     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1354     ULONG refcount = InterlockedDecrement(&d3drm->ref3);
1355 
1356     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
1357 
1358     if (!refcount && !InterlockedDecrement(&d3drm->iface_count))
1359         d3drm_destroy(d3drm);
1360 
1361     return refcount;
1362 }
1363 
1364 static HRESULT WINAPI d3drm3_CreateObject(IDirect3DRM3 *iface,
1365         REFCLSID clsid, IUnknown *outer, REFIID iid, void **out)
1366 {
1367     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1368     IUnknown *object;
1369     unsigned int i;
1370     HRESULT hr;
1371 
1372     static const struct
1373     {
1374         const CLSID *clsid;
1375         HRESULT (*create_object)(void **object, IDirect3DRM *d3drm);
1376     }
1377     object_table[] =
1378     {
1379         {&CLSID_CDirect3DRMTexture, d3drm_create_texture_object},
1380         {&CLSID_CDirect3DRMDevice, d3drm_create_device_object},
1381         {&CLSID_CDirect3DRMViewport, d3drm_create_viewport_object},
1382         {&CLSID_CDirect3DRMFace, d3drm_create_face_object},
1383         {&CLSID_CDirect3DRMMeshBuilder, d3drm_create_mesh_builder_object},
1384         {&CLSID_CDirect3DRMFrame, d3drm_create_frame_object},
1385         {&CLSID_CDirect3DRMLight, d3drm_create_light_object},
1386         {&CLSID_CDirect3DRMMaterial, d3drm_create_material_object},
1387         {&CLSID_CDirect3DRMMesh, d3drm_create_mesh_object},
1388         {&CLSID_CDirect3DRMAnimation, d3drm_create_animation_object},
1389         {&CLSID_CDirect3DRMWrap, d3drm_create_wrap_object},
1390     };
1391 
1392     TRACE("iface %p, clsid %s, outer %p, iid %s, out %p.\n",
1393             iface, debugstr_guid(clsid), outer, debugstr_guid(iid), out);
1394 
1395     if (!out)
1396         return D3DRMERR_BADVALUE;
1397 
1398     if (!clsid || !iid)
1399     {
1400         *out = NULL;
1401         return D3DRMERR_BADVALUE;
1402     }
1403 
1404     if (outer)
1405     {
1406         FIXME("COM aggregation for outer IUnknown (%p) not implemented. Returning E_NOTIMPL.\n", outer);
1407         *out = NULL;
1408         return E_NOTIMPL;
1409     }
1410 
1411     for (i = 0; i < ARRAY_SIZE(object_table); ++i)
1412     {
1413         if (IsEqualGUID(clsid, object_table[i].clsid))
1414         {
1415             if (FAILED(hr = object_table[i].create_object((void **)&object, &d3drm->IDirect3DRM_iface)))
1416             {
1417                 *out = NULL;
1418                 return hr;
1419             }
1420             break;
1421         }
1422     }
1423     if (i == ARRAY_SIZE(object_table))
1424     {
1425         FIXME("%s not implemented. Returning CLASSFACTORY_E_FIRST.\n", debugstr_guid(clsid));
1426         *out = NULL;
1427         return CLASSFACTORY_E_FIRST;
1428     }
1429 
1430     if (FAILED(hr = IUnknown_QueryInterface(object, iid, out)))
1431         *out = NULL;
1432     IUnknown_Release(object);
1433 
1434     return hr;
1435 }
1436 
1437 static HRESULT WINAPI d3drm3_CreateFrame(IDirect3DRM3 *iface,
1438         IDirect3DRMFrame3 *parent, IDirect3DRMFrame3 **frame)
1439 {
1440     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1441     struct d3drm_frame *object;
1442     HRESULT hr;
1443 
1444     TRACE("iface %p, parent %p, frame %p.\n", iface, parent, frame);
1445 
1446     if (FAILED(hr = d3drm_frame_create(&object, (IUnknown *)parent, &d3drm->IDirect3DRM_iface)))
1447         return hr;
1448 
1449     *frame = &object->IDirect3DRMFrame3_iface;
1450 
1451     return D3DRM_OK;
1452 }
1453 
1454 static HRESULT WINAPI d3drm3_CreateMesh(IDirect3DRM3 *iface, IDirect3DRMMesh **mesh)
1455 {
1456     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1457     struct d3drm_mesh *object;
1458     HRESULT hr;
1459 
1460     TRACE("iface %p, mesh %p.\n", iface, mesh);
1461 
1462     if (FAILED(hr = d3drm_mesh_create(&object, &d3drm->IDirect3DRM_iface)))
1463         return hr;
1464 
1465     *mesh = &object->IDirect3DRMMesh_iface;
1466 
1467     return S_OK;
1468 }
1469 
1470 static HRESULT WINAPI d3drm3_CreateMeshBuilder(IDirect3DRM3 *iface, IDirect3DRMMeshBuilder3 **mesh_builder)
1471 {
1472     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1473     struct d3drm_mesh_builder *object;
1474     HRESULT hr;
1475 
1476     TRACE("iface %p, mesh_builder %p.\n", iface, mesh_builder);
1477 
1478     if (FAILED(hr = d3drm_mesh_builder_create(&object, &d3drm->IDirect3DRM_iface)))
1479         return hr;
1480 
1481     *mesh_builder = &object->IDirect3DRMMeshBuilder3_iface;
1482 
1483     return S_OK;
1484 }
1485 
1486 static HRESULT WINAPI d3drm3_CreateFace(IDirect3DRM3 *iface, IDirect3DRMFace2 **face)
1487 {
1488     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1489     IDirect3DRMFace *face1;
1490     HRESULT hr;
1491 
1492     TRACE("iface %p, face %p.\n", iface, face);
1493 
1494     if (FAILED(hr = IDirect3DRM_CreateFace(&d3drm->IDirect3DRM_iface, &face1)))
1495         return hr;
1496 
1497     hr = IDirect3DRMFace_QueryInterface(face1, &IID_IDirect3DRMFace2, (void **)face);
1498     IDirect3DRMFace_Release(face1);
1499 
1500     return hr;
1501 }
1502 
1503 static HRESULT WINAPI d3drm3_CreateAnimation(IDirect3DRM3 *iface, IDirect3DRMAnimation2 **animation)
1504 {
1505     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1506     struct d3drm_animation *object;
1507     HRESULT hr;
1508 
1509     TRACE("iface %p, animation %p.\n", iface, animation);
1510 
1511     if (FAILED(hr = d3drm_animation_create(&object, &d3drm->IDirect3DRM_iface)))
1512         return hr;
1513 
1514     *animation = &object->IDirect3DRMAnimation2_iface;
1515 
1516     return hr;
1517 }
1518 
1519 static HRESULT WINAPI d3drm3_CreateAnimationSet(IDirect3DRM3 *iface, IDirect3DRMAnimationSet2 **set)
1520 {
1521     FIXME("iface %p, set %p stub!\n", iface, set);
1522 
1523     return E_NOTIMPL;
1524 }
1525 
1526 static HRESULT WINAPI d3drm3_CreateTexture(IDirect3DRM3 *iface,
1527         D3DRMIMAGE *image, IDirect3DRMTexture3 **texture)
1528 {
1529     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1530     struct d3drm_texture *object;
1531     HRESULT hr;
1532 
1533     TRACE("iface %p, image %p, texture %p.\n", iface, image, texture);
1534 
1535     if (!texture)
1536         return D3DRMERR_BADVALUE;
1537 
1538     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1539         return hr;
1540 
1541     *texture = &object->IDirect3DRMTexture3_iface;
1542 
1543     if (FAILED(IDirect3DRMTexture3_InitFromImage(*texture, image)))
1544     {
1545         IDirect3DRMTexture3_Release(*texture);
1546         *texture = NULL;
1547         return D3DRMERR_BADVALUE;
1548     }
1549 
1550     return D3DRM_OK;
1551 }
1552 
1553 static HRESULT WINAPI d3drm3_CreateLight(IDirect3DRM3 *iface,
1554         D3DRMLIGHTTYPE type, D3DCOLOR color, IDirect3DRMLight **light)
1555 {
1556     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1557     struct d3drm_light *object;
1558     HRESULT hr;
1559 
1560     FIXME("iface %p, type %#x, color 0x%08x, light %p partial stub!\n", iface, type, color, light);
1561 
1562     if (SUCCEEDED(hr = d3drm_light_create(&object, &d3drm->IDirect3DRM_iface)))
1563     {
1564         IDirect3DRMLight_SetType(&object->IDirect3DRMLight_iface, type);
1565         IDirect3DRMLight_SetColor(&object->IDirect3DRMLight_iface, color);
1566     }
1567 
1568     *light = &object->IDirect3DRMLight_iface;
1569 
1570     return hr;
1571 }
1572 
1573 static HRESULT WINAPI d3drm3_CreateLightRGB(IDirect3DRM3 *iface, D3DRMLIGHTTYPE type,
1574         D3DVALUE red, D3DVALUE green, D3DVALUE blue, IDirect3DRMLight **light)
1575 {
1576     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1577     struct d3drm_light *object;
1578     HRESULT hr;
1579 
1580     FIXME("iface %p, type %#x, red %.8e, green %.8e, blue %.8e, light %p partial stub!\n",
1581             iface, type, red, green, blue, light);
1582 
1583     if (SUCCEEDED(hr = d3drm_light_create(&object, &d3drm->IDirect3DRM_iface)))
1584     {
1585         IDirect3DRMLight_SetType(&object->IDirect3DRMLight_iface, type);
1586         IDirect3DRMLight_SetColorRGB(&object->IDirect3DRMLight_iface, red, green, blue);
1587     }
1588 
1589     *light = &object->IDirect3DRMLight_iface;
1590 
1591     return hr;
1592 }
1593 
1594 static HRESULT WINAPI d3drm3_CreateMaterial(IDirect3DRM3 *iface,
1595         D3DVALUE power, IDirect3DRMMaterial2 **material)
1596 {
1597     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1598     struct d3drm_material *object;
1599     HRESULT hr;
1600 
1601     TRACE("iface %p, power %.8e, material %p.\n", iface, power, material);
1602 
1603     if (SUCCEEDED(hr = d3drm_material_create(&object, &d3drm->IDirect3DRM_iface)))
1604         IDirect3DRMMaterial2_SetPower(&object->IDirect3DRMMaterial2_iface, power);
1605 
1606     *material = &object->IDirect3DRMMaterial2_iface;
1607 
1608     return hr;
1609 }
1610 
1611 static HRESULT WINAPI d3drm3_CreateDevice(IDirect3DRM3 *iface,
1612         DWORD width, DWORD height, IDirect3DRMDevice3 **device)
1613 {
1614     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1615     struct d3drm_device *object;
1616     HRESULT hr;
1617 
1618     FIXME("iface %p, width %u, height %u, device %p partial stub!\n", iface, width, height, device);
1619 
1620     if (FAILED(hr = d3drm_device_create(&object, &d3drm->IDirect3DRM_iface)))
1621         return hr;
1622 
1623     *device = &object->IDirect3DRMDevice3_iface;
1624 
1625     return D3DRM_OK;
1626 }
1627 
1628 static HRESULT WINAPI d3drm3_CreateDeviceFromSurface(IDirect3DRM3 *iface, GUID *guid,
1629         IDirectDraw *ddraw, IDirectDrawSurface *backbuffer, DWORD flags, IDirect3DRMDevice3 **device)
1630 {
1631     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1632     struct d3drm_device *object;
1633     BOOL use_z_surface;
1634     HRESULT hr;
1635 
1636     TRACE("iface %p, guid %s, ddraw %p, backbuffer %p, flags %#x, device %p.\n",
1637             iface, debugstr_guid(guid), ddraw, backbuffer, flags, device);
1638 
1639     if (!device)
1640         return D3DRMERR_BADVALUE;
1641     *device = NULL;
1642 
1643     if (!backbuffer || !ddraw)
1644         return D3DRMERR_BADDEVICE;
1645 
1646     if (FAILED(hr = d3drm_device_create(&object, &d3drm->IDirect3DRM_iface)))
1647         return hr;
1648 
1649     use_z_surface = !(flags & D3DRMDEVICE_NOZBUFFER);
1650 
1651     if (SUCCEEDED(hr = d3drm_device_init(object, 3, ddraw, backbuffer, use_z_surface)))
1652         *device = &object->IDirect3DRMDevice3_iface;
1653     else
1654         d3drm_device_destroy(object);
1655 
1656     return hr;
1657 }
1658 
1659 static HRESULT WINAPI d3drm3_CreateDeviceFromD3D(IDirect3DRM3 *iface,
1660         IDirect3D2 *d3d, IDirect3DDevice2 *d3d_device, IDirect3DRMDevice3 **device)
1661 {
1662     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1663     struct d3drm_device *object;
1664     HRESULT hr;
1665 
1666     TRACE("iface %p, d3d %p, d3d_device %p, device %p.\n",
1667             iface, d3d, d3d_device, device);
1668 
1669     if (!device)
1670         return D3DRMERR_BADVALUE;
1671     *device = NULL;
1672 
1673     if (FAILED(hr = d3drm_device_create(&object, &d3drm->IDirect3DRM_iface)))
1674         return hr;
1675 
1676     if (FAILED(hr = IDirect3DRMDevice3_InitFromD3D2(&object->IDirect3DRMDevice3_iface, d3d, d3d_device)))
1677     {
1678         d3drm_device_destroy(object);
1679         return hr;
1680     }
1681     *device = &object->IDirect3DRMDevice3_iface;
1682 
1683     return D3DRM_OK;
1684 }
1685 
1686 static HRESULT WINAPI d3drm3_CreateDeviceFromClipper(IDirect3DRM3 *iface,
1687         IDirectDrawClipper *clipper, GUID *guid, int width, int height,
1688         IDirect3DRMDevice3 **device)
1689 {
1690     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1691     struct d3drm_device *object;
1692     IDirectDraw *ddraw;
1693     IDirectDrawSurface *render_target;
1694     HRESULT hr;
1695 
1696     TRACE("iface %p, clipper %p, guid %s, width %d, height %d, device %p.\n",
1697             iface, clipper, debugstr_guid(guid), width, height, device);
1698 
1699     if (!device)
1700         return D3DRMERR_BADVALUE;
1701     *device = NULL;
1702 
1703     if (!clipper || !width || !height)
1704         return D3DRMERR_BADVALUE;
1705 
1706     hr = DirectDrawCreate(NULL, &ddraw, NULL);
1707     if (FAILED(hr))
1708         return hr;
1709 
1710     if (FAILED(hr = d3drm_device_create(&object, &d3drm->IDirect3DRM_iface)))
1711     {
1712         IDirectDraw_Release(ddraw);
1713         return hr;
1714     }
1715 
1716     hr = d3drm_device_create_surfaces_from_clipper(object, ddraw, clipper, width, height, &render_target);
1717     if (FAILED(hr))
1718     {
1719         IDirectDraw_Release(ddraw);
1720         d3drm_device_destroy(object);
1721         return hr;
1722     }
1723 
1724     hr = d3drm_device_init(object, 3, ddraw, render_target, TRUE);
1725     IDirectDraw_Release(ddraw);
1726     IDirectDrawSurface_Release(render_target);
1727     if (FAILED(hr))
1728         d3drm_device_destroy(object);
1729     else
1730         *device = &object->IDirect3DRMDevice3_iface;
1731 
1732     return hr;
1733 }
1734 
1735 static HRESULT WINAPI d3drm3_CreateShadow(IDirect3DRM3 *iface, IUnknown *object, IDirect3DRMLight *light,
1736         D3DVALUE px, D3DVALUE py, D3DVALUE pz, D3DVALUE nx, D3DVALUE ny, D3DVALUE nz, IDirect3DRMShadow2 **shadow)
1737 {
1738     FIXME("iface %p, object %p, light %p, px %.8e, py %.8e, pz %.8e, nx %.8e, ny %.8e, nz %.8e, shadow %p stub!\n",
1739             iface, object, light, px, py, pz, nx, ny, nz, shadow);
1740 
1741     return E_NOTIMPL;
1742 }
1743 
1744 static HRESULT WINAPI d3drm3_CreateTextureFromSurface(IDirect3DRM3 *iface,
1745         IDirectDrawSurface *surface, IDirect3DRMTexture3 **texture)
1746 {
1747     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1748     struct d3drm_texture *object;
1749     HRESULT hr;
1750 
1751     TRACE("iface %p, surface %p, texture %p.\n", iface, surface, texture);
1752 
1753     if (!texture)
1754         return D3DRMERR_BADVALUE;
1755 
1756     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1757         return hr;
1758 
1759     *texture = &object->IDirect3DRMTexture3_iface;
1760 
1761     if (FAILED(IDirect3DRMTexture3_InitFromSurface(*texture, surface)))
1762     {
1763         IDirect3DRMTexture3_Release(*texture);
1764         *texture = NULL;
1765         return D3DRMERR_BADVALUE;
1766     }
1767 
1768     return D3DRM_OK;
1769 }
1770 
1771 static HRESULT WINAPI d3drm3_CreateViewport(IDirect3DRM3 *iface, IDirect3DRMDevice3 *device,
1772         IDirect3DRMFrame3 *camera, DWORD x, DWORD y, DWORD width, DWORD height, IDirect3DRMViewport2 **viewport)
1773 {
1774     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1775     struct d3drm_viewport *object;
1776     HRESULT hr;
1777 
1778     TRACE("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u, viewport %p.\n",
1779             iface, device, camera, x, y, width, height, viewport);
1780 
1781     if (!device || !camera)
1782         return D3DRMERR_BADOBJECT;
1783     if (!viewport)
1784         return D3DRMERR_BADVALUE;
1785 
1786     if (FAILED(hr = d3drm_viewport_create(&object, &d3drm->IDirect3DRM_iface)))
1787         return hr;
1788 
1789     *viewport = &object->IDirect3DRMViewport2_iface;
1790 
1791     if (FAILED(hr = IDirect3DRMViewport2_Init(*viewport, device, camera, x, y, width, height)))
1792     {
1793         IDirect3DRMViewport2_Release(*viewport);
1794         *viewport = NULL;
1795         return D3DRMERR_BADVALUE;
1796     }
1797 
1798     return D3DRM_OK;
1799 }
1800 
1801 static HRESULT WINAPI d3drm3_CreateWrap(IDirect3DRM3 *iface, D3DRMWRAPTYPE type, IDirect3DRMFrame3 *frame,
1802         D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
1803         D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, D3DVALUE ou, D3DVALUE ov, D3DVALUE su, D3DVALUE sv,
1804         IDirect3DRMWrap **wrap)
1805 {
1806     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1807     struct d3drm_wrap *object;
1808     HRESULT hr;
1809 
1810     FIXME("iface %p, type %#x, frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, "
1811             "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p, semi-stub.\n",
1812             iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz, ou, ov, su, sv, wrap);
1813 
1814     if (!wrap)
1815         return D3DRMERR_BADVALUE;
1816 
1817     if (FAILED(hr = d3drm_wrap_create(&object, &d3drm->IDirect3DRM_iface)))
1818         return hr;
1819 
1820     *wrap = &object->IDirect3DRMWrap_iface;
1821 
1822     return S_OK;
1823 }
1824 
1825 static HRESULT WINAPI d3drm3_CreateUserVisual(IDirect3DRM3 *iface,
1826         D3DRMUSERVISUALCALLBACK cb, void *ctx, IDirect3DRMUserVisual **visual)
1827 {
1828     FIXME("iface %p, cb %p, ctx %p, visual %p stub!\n", iface, cb, ctx, visual);
1829 
1830     return E_NOTIMPL;
1831 }
1832 
1833 static HRESULT WINAPI d3drm3_LoadTexture(IDirect3DRM3 *iface,
1834         const char *filename, IDirect3DRMTexture3 **texture)
1835 {
1836     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1837     struct d3drm_texture *object;
1838     HRESULT hr;
1839 
1840     TRACE("iface %p, filename %s, texture %p.\n", iface, debugstr_a(filename), texture);
1841 
1842     if (!texture)
1843         return D3DRMERR_BADVALUE;
1844 
1845     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1846         return hr;
1847 
1848     *texture = &object->IDirect3DRMTexture3_iface;
1849     if (FAILED(hr = IDirect3DRMTexture3_InitFromFile(*texture, filename)))
1850     {
1851         IDirect3DRMTexture3_Release(*texture);
1852         *texture = NULL;
1853         return hr == D3DRMERR_BADOBJECT ? D3DRMERR_FILENOTFOUND : hr;
1854     }
1855 
1856     return D3DRM_OK;
1857 }
1858 
1859 static HRESULT WINAPI d3drm3_LoadTextureFromResource(IDirect3DRM3 *iface, HMODULE module,
1860         const char *resource_name, const char *resource_type, IDirect3DRMTexture3 **texture)
1861 {
1862     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1863     struct d3drm_texture *object;
1864     HRESULT hr;
1865 
1866     FIXME("iface %p, module %p, resource_name %s, resource_type %s, texture %p stub!\n",
1867             iface, module, debugstr_a(resource_name), debugstr_a(resource_type), texture);
1868 
1869     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1870         return hr;
1871 
1872     *texture = &object->IDirect3DRMTexture3_iface;
1873 
1874     return D3DRM_OK;
1875 }
1876 
1877 static HRESULT WINAPI d3drm3_SetSearchPath(IDirect3DRM3 *iface, const char *path)
1878 {
1879     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
1880 
1881     return E_NOTIMPL;
1882 }
1883 
1884 static HRESULT WINAPI d3drm3_AddSearchPath(IDirect3DRM3 *iface, const char *path)
1885 {
1886     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
1887 
1888     return E_NOTIMPL;
1889 }
1890 
1891 static HRESULT WINAPI d3drm3_GetSearchPath(IDirect3DRM3 *iface, DWORD *size, char *path)
1892 {
1893     FIXME("iface %p, size %p, path %p stub!\n", iface, size, path);
1894 
1895     return E_NOTIMPL;
1896 }
1897 
1898 static HRESULT WINAPI d3drm3_SetDefaultTextureColors(IDirect3DRM3 *iface, DWORD color_count)
1899 {
1900     FIXME("iface %p, color_count %u stub!\n", iface, color_count);
1901 
1902     return E_NOTIMPL;
1903 }
1904 
1905 static HRESULT WINAPI d3drm3_SetDefaultTextureShades(IDirect3DRM3 *iface, DWORD shade_count)
1906 {
1907     FIXME("iface %p, shade_count %u stub!\n", iface, shade_count);
1908 
1909     return E_NOTIMPL;
1910 }
1911 
1912 static HRESULT WINAPI d3drm3_GetDevices(IDirect3DRM3 *iface, IDirect3DRMDeviceArray **array)
1913 {
1914     FIXME("iface %p, array %p stub!\n", iface, array);
1915 
1916     return E_NOTIMPL;
1917 }
1918 
1919 static HRESULT WINAPI d3drm3_GetNamedObject(IDirect3DRM3 *iface,
1920         const char *name, IDirect3DRMObject **object)
1921 {
1922     FIXME("iface %p, name %s, object %p stub!\n", iface, debugstr_a(name), object);
1923 
1924     return E_NOTIMPL;
1925 }
1926 
1927 static HRESULT WINAPI d3drm3_EnumerateObjects(IDirect3DRM3 *iface, D3DRMOBJECTCALLBACK cb, void *ctx)
1928 {
1929     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
1930 
1931     return E_NOTIMPL;
1932 }
1933 
1934 static HRESULT load_data(IDirect3DRM3 *iface, IDirectXFileData *data_object, IID **GUIDs, DWORD nb_GUIDs, D3DRMLOADCALLBACK LoadProc,
1935                          void *ArgLP, D3DRMLOADTEXTURECALLBACK LoadTextureProc, void *ArgLTP, IDirect3DRMFrame3 *parent_frame)
1936 {
1937     HRESULT ret = D3DRMERR_BADOBJECT;
1938     HRESULT hr;
1939     const GUID* guid;
1940     DWORD i;
1941     BOOL requested = FALSE;
1942 
1943     hr = IDirectXFileData_GetType(data_object, &guid);
1944     if (hr != DXFILE_OK)
1945         goto end;
1946 
1947     TRACE("Found object type whose GUID = %s\n", debugstr_guid(guid));
1948 
1949     /* Load object only if it is top level and requested or if it is part of another object */
1950 
1951     if (IsEqualGUID(guid, &TID_D3DRMMesh))
1952     {
1953         TRACE("Found TID_D3DRMMesh\n");
1954 
1955         for (i = 0; i < nb_GUIDs; i++)
1956             if (IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMeshBuilder) ||
1957                 IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMeshBuilder2) ||
1958                 IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMeshBuilder3))
1959             {
1960                 requested = TRUE;
1961                 break;
1962             }
1963 
1964         if (requested || parent_frame)
1965         {
1966             IDirect3DRMMeshBuilder3 *meshbuilder;
1967 
1968             TRACE("Load mesh data\n");
1969 
1970             hr = IDirect3DRM3_CreateMeshBuilder(iface, &meshbuilder);
1971             if (SUCCEEDED(hr))
1972             {
1973                 hr = load_mesh_data(meshbuilder, data_object, LoadTextureProc, ArgLTP);
1974                 if (SUCCEEDED(hr))
1975                 {
1976                     /* Only top level objects are notified */
1977                     if (!parent_frame)
1978                     {
1979                         IDirect3DRMObject *object;
1980 
1981                         hr = IDirect3DRMMeshBuilder3_QueryInterface(meshbuilder, GUIDs[i], (void**)&object);
1982                         if (SUCCEEDED(hr))
1983                         {
1984                             LoadProc(object, GUIDs[i], ArgLP);
1985                             IDirect3DRMObject_Release(object);
1986                         }
1987                     }
1988                     else
1989                     {
1990                         IDirect3DRMFrame3_AddVisual(parent_frame, (IUnknown*)meshbuilder);
1991                     }
1992                 }
1993                 IDirect3DRMMeshBuilder3_Release(meshbuilder);
1994             }
1995 
1996             if (FAILED(hr))
1997                 ERR("Cannot process mesh\n");
1998         }
1999     }
2000     else if (IsEqualGUID(guid, &TID_D3DRMFrame))
2001     {
2002         TRACE("Found TID_D3DRMFrame\n");
2003 
2004         for (i = 0; i < nb_GUIDs; i++)
2005             if (IsEqualGUID(GUIDs[i], &IID_IDirect3DRMFrame) ||
2006                 IsEqualGUID(GUIDs[i], &IID_IDirect3DRMFrame2) ||
2007                 IsEqualGUID(GUIDs[i], &IID_IDirect3DRMFrame3))
2008             {
2009                 requested = TRUE;
2010                 break;
2011             }
2012 
2013         if (requested || parent_frame)
2014         {
2015             IDirect3DRMFrame3 *frame;
2016 
2017             TRACE("Load frame data\n");
2018 
2019             hr = IDirect3DRM3_CreateFrame(iface, parent_frame, &frame);
2020             if (SUCCEEDED(hr))
2021             {
2022                 IDirectXFileObject *child;
2023 
2024                 while (SUCCEEDED(hr = IDirectXFileData_GetNextObject(data_object, &child)))
2025                 {
2026                     IDirectXFileData *data;
2027                     IDirectXFileDataReference *reference;
2028                     IDirectXFileBinary *binary;
2029 
2030                     if (SUCCEEDED(IDirectXFileObject_QueryInterface(child,
2031                             &IID_IDirectXFileBinary, (void **)&binary)))
2032                     {
2033                         FIXME("Binary Object not supported yet\n");
2034                         IDirectXFileBinary_Release(binary);
2035                     }
2036                     else if (SUCCEEDED(IDirectXFileObject_QueryInterface(child,
2037                             &IID_IDirectXFileData, (void **)&data)))
2038                     {
2039                         TRACE("Found Data Object\n");
2040                         hr = load_data(iface, data, GUIDs, nb_GUIDs, LoadProc, ArgLP, LoadTextureProc, ArgLTP, frame);
2041                         IDirectXFileData_Release(data);
2042                     }
2043                     else if (SUCCEEDED(IDirectXFileObject_QueryInterface(child,
2044                             &IID_IDirectXFileDataReference, (void **)&reference)))
2045                     {
2046                         TRACE("Found Data Object Reference\n");
2047                         IDirectXFileDataReference_Resolve(reference, &data);
2048                         hr = load_data(iface, data, GUIDs, nb_GUIDs, LoadProc, ArgLP, LoadTextureProc, ArgLTP, frame);
2049                         IDirectXFileData_Release(data);
2050                         IDirectXFileDataReference_Release(reference);
2051                     }
2052                     IDirectXFileObject_Release(child);
2053                 }
2054 
2055                 if (hr != DXFILEERR_NOMOREOBJECTS)
2056                 {
2057                     IDirect3DRMFrame3_Release(frame);
2058                     goto end;
2059                 }
2060                 hr = S_OK;
2061 
2062                 /* Only top level objects are notified */
2063                 if (!parent_frame)
2064                 {
2065                     IDirect3DRMObject *object;
2066 
2067                     hr = IDirect3DRMFrame3_QueryInterface(frame, GUIDs[i], (void**)&object);
2068                     if (SUCCEEDED(hr))
2069                     {
2070                         LoadProc(object, GUIDs[i], ArgLP);
2071                         IDirect3DRMObject_Release(object);
2072                     }
2073                 }
2074                 IDirect3DRMFrame3_Release(frame);
2075             }
2076 
2077             if (FAILED(hr))
2078                 ERR("Cannot process frame\n");
2079         }
2080     }
2081     else if (IsEqualGUID(guid, &TID_D3DRMMaterial))
2082     {
2083         TRACE("Found TID_D3DRMMaterial\n");
2084 
2085         /* Cannot be requested so nothing to do */
2086     }
2087     else if (IsEqualGUID(guid, &TID_D3DRMFrameTransformMatrix))
2088     {
2089         TRACE("Found TID_D3DRMFrameTransformMatrix\n");
2090 
2091         /* Cannot be requested */
2092         if (parent_frame)
2093         {
2094             D3DRMMATRIX4D *matrix;
2095             DWORD size;
2096 
2097             TRACE("Load Frame Transform Matrix data\n");
2098 
2099             hr = IDirectXFileData_GetData(data_object, NULL, &size, (void**)&matrix);
2100             if ((hr != DXFILE_OK) || (size != sizeof(matrix)))
2101                 goto end;
2102 
2103             hr = IDirect3DRMFrame3_AddTransform(parent_frame, D3DRMCOMBINE_REPLACE, *matrix);
2104             if (FAILED(hr))
2105                 goto end;
2106         }
2107     }
2108     else
2109     {
2110         FIXME("Found unknown TID %s\n", debugstr_guid(guid));
2111     }
2112 
2113     ret = D3DRM_OK;
2114 
2115 end:
2116 
2117     return ret;
2118 }
2119 
2120 static HRESULT WINAPI d3drm3_Load(IDirect3DRM3 *iface, void *source, void *object_id, IID **iids,
2121         DWORD iid_count, D3DRMLOADOPTIONS flags, D3DRMLOADCALLBACK load_cb, void *load_ctx,
2122         D3DRMLOADTEXTURECALLBACK load_tex_cb, void *load_tex_ctx, IDirect3DRMFrame3 *parent_frame)
2123 {
2124     DXFILELOADOPTIONS load_options;
2125     IDirectXFile *file = NULL;
2126     IDirectXFileEnumObject *enum_object = NULL;
2127     IDirectXFileData *data = NULL;
2128     HRESULT hr;
2129     const GUID* pGuid;
2130     DWORD size;
2131     struct d3drm_file_header *header;
2132     HRESULT ret = D3DRMERR_BADOBJECT;
2133     DWORD i;
2134 
2135     TRACE("iface %p, source %p, object_id %p, iids %p, iid_count %u, flags %#x, "
2136             "load_cb %p, load_ctx %p, load_tex_cb %p, load_tex_ctx %p, parent_frame %p.\n",
2137             iface, source, object_id, iids, iid_count, flags,
2138             load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame);
2139 
2140     TRACE("Looking for GUIDs:\n");
2141     for (i = 0; i < iid_count; ++i)
2142         TRACE("- %s (%s)\n", debugstr_guid(iids[i]), get_IID_string(iids[i]));
2143 
2144     if (flags == D3DRMLOAD_FROMMEMORY)
2145     {
2146         load_options = DXFILELOAD_FROMMEMORY;
2147     }
2148     else if (flags == D3DRMLOAD_FROMFILE)
2149     {
2150         load_options = DXFILELOAD_FROMFILE;
2151         TRACE("Loading from file %s\n", debugstr_a(source));
2152     }
2153     else
2154     {
2155         FIXME("Load options %#x not supported yet.\n", flags);
2156         return E_NOTIMPL;
2157     }
2158 
2159     hr = DirectXFileCreate(&file);
2160     if (hr != DXFILE_OK)
2161         goto end;
2162 
2163     hr = IDirectXFile_RegisterTemplates(file, templates, strlen(templates));
2164     if (hr != DXFILE_OK)
2165         goto end;
2166 
2167     hr = IDirectXFile_CreateEnumObject(file, source, load_options, &enum_object);
2168     if (hr != DXFILE_OK)
2169         goto end;
2170 
2171     hr = IDirectXFileEnumObject_GetNextDataObject(enum_object, &data);
2172     if (hr != DXFILE_OK)
2173         goto end;
2174 
2175     hr = IDirectXFileData_GetType(data, &pGuid);
2176     if (hr != DXFILE_OK)
2177         goto end;
2178 
2179     TRACE("Found object type whose GUID = %s\n", debugstr_guid(pGuid));
2180 
2181     if (!IsEqualGUID(pGuid, &TID_DXFILEHeader))
2182     {
2183         ret = D3DRMERR_BADFILE;
2184         goto end;
2185     }
2186 
2187     hr = IDirectXFileData_GetData(data, NULL, &size, (void **)&header);
2188     if ((hr != DXFILE_OK) || (size != sizeof(*header)))
2189         goto end;
2190 
2191     TRACE("Version is %u.%u, flags %#x.\n", header->major, header->minor, header->flags);
2192 
2193     /* Version must be 1.0.x */
2194     if ((header->major != 1) || (header->minor != 0))
2195     {
2196         ret = D3DRMERR_BADFILE;
2197         goto end;
2198     }
2199 
2200     IDirectXFileData_Release(data);
2201     data = NULL;
2202 
2203     while (1)
2204     {
2205         hr = IDirectXFileEnumObject_GetNextDataObject(enum_object, &data);
2206         if (hr == DXFILEERR_NOMOREOBJECTS)
2207         {
2208             TRACE("No more object\n");
2209             break;
2210         }
2211         else if (hr != DXFILE_OK)
2212         {
2213             ret = D3DRMERR_BADFILE;
2214             goto end;
2215         }
2216 
2217         ret = load_data(iface, data, iids, iid_count, load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame);
2218         if (ret != D3DRM_OK)
2219             goto end;
2220 
2221         IDirectXFileData_Release(data);
2222         data = NULL;
2223     }
2224 
2225     ret = D3DRM_OK;
2226 
2227 end:
2228     if (data)
2229         IDirectXFileData_Release(data);
2230     if (enum_object)
2231         IDirectXFileEnumObject_Release(enum_object);
2232     if (file)
2233         IDirectXFile_Release(file);
2234 
2235     return ret;
2236 }
2237 
2238 static HRESULT WINAPI d3drm3_Tick(IDirect3DRM3 *iface, D3DVALUE tick)
2239 {
2240     FIXME("iface %p, tick %.8e stub!\n", iface, tick);
2241 
2242     return E_NOTIMPL;
2243 }
2244 
2245 static HRESULT WINAPI d3drm3_CreateProgressiveMesh(IDirect3DRM3 *iface, IDirect3DRMProgressiveMesh **mesh)
2246 {
2247     FIXME("iface %p, mesh %p stub!\n", iface, mesh);
2248 
2249     return E_NOTIMPL;
2250 }
2251 
2252 static HRESULT WINAPI d3drm3_RegisterClient(IDirect3DRM3 *iface, REFGUID guid, DWORD *id)
2253 {
2254     FIXME("iface %p, guid %s, id %p stub!\n", iface, debugstr_guid(guid), id);
2255 
2256     return E_NOTIMPL;
2257 }
2258 
2259 static HRESULT WINAPI d3drm3_UnregisterClient(IDirect3DRM3 *iface, REFGUID guid)
2260 {
2261     FIXME("iface %p, guid %s stub!\n", iface, debugstr_guid(guid));
2262 
2263     return E_NOTIMPL;
2264 }
2265 
2266 static HRESULT WINAPI d3drm3_CreateClippedVisual(IDirect3DRM3 *iface,
2267         IDirect3DRMVisual *visual, IDirect3DRMClippedVisual **clipped_visual)
2268 {
2269     FIXME("iface %p, visual %p, clipped_visual %p stub!\n", iface, visual, clipped_visual);
2270 
2271     return E_NOTIMPL;
2272 }
2273 
2274 static HRESULT WINAPI d3drm3_SetOptions(IDirect3DRM3 *iface, DWORD flags)
2275 {
2276     FIXME("iface %p, flags %#x stub!\n", iface, flags);
2277 
2278     return E_NOTIMPL;
2279 }
2280 
2281 static HRESULT WINAPI d3drm3_GetOptions(IDirect3DRM3 *iface, DWORD *flags)
2282 {
2283     FIXME("iface %p, flags %p stub!\n", iface, flags);
2284 
2285     return E_NOTIMPL;
2286 }
2287 
2288 static const struct IDirect3DRM3Vtbl d3drm3_vtbl =
2289 {
2290     d3drm3_QueryInterface,
2291     d3drm3_AddRef,
2292     d3drm3_Release,
2293     d3drm3_CreateObject,
2294     d3drm3_CreateFrame,
2295     d3drm3_CreateMesh,
2296     d3drm3_CreateMeshBuilder,
2297     d3drm3_CreateFace,
2298     d3drm3_CreateAnimation,
2299     d3drm3_CreateAnimationSet,
2300     d3drm3_CreateTexture,
2301     d3drm3_CreateLight,
2302     d3drm3_CreateLightRGB,
2303     d3drm3_CreateMaterial,
2304     d3drm3_CreateDevice,
2305     d3drm3_CreateDeviceFromSurface,
2306     d3drm3_CreateDeviceFromD3D,
2307     d3drm3_CreateDeviceFromClipper,
2308     d3drm3_CreateTextureFromSurface,
2309     d3drm3_CreateShadow,
2310     d3drm3_CreateViewport,
2311     d3drm3_CreateWrap,
2312     d3drm3_CreateUserVisual,
2313     d3drm3_LoadTexture,
2314     d3drm3_LoadTextureFromResource,
2315     d3drm3_SetSearchPath,
2316     d3drm3_AddSearchPath,
2317     d3drm3_GetSearchPath,
2318     d3drm3_SetDefaultTextureColors,
2319     d3drm3_SetDefaultTextureShades,
2320     d3drm3_GetDevices,
2321     d3drm3_GetNamedObject,
2322     d3drm3_EnumerateObjects,
2323     d3drm3_Load,
2324     d3drm3_Tick,
2325     d3drm3_CreateProgressiveMesh,
2326     d3drm3_RegisterClient,
2327     d3drm3_UnregisterClient,
2328     d3drm3_CreateClippedVisual,
2329     d3drm3_SetOptions,
2330     d3drm3_GetOptions,
2331 };
2332 
2333 HRESULT WINAPI Direct3DRMCreate(IDirect3DRM **d3drm)
2334 {
2335     struct d3drm *object;
2336 
2337     TRACE("d3drm %p.\n", d3drm);
2338 
2339     if (!(object = heap_alloc_zero(sizeof(*object))))
2340         return E_OUTOFMEMORY;
2341 
2342     object->IDirect3DRM_iface.lpVtbl = &d3drm1_vtbl;
2343     object->IDirect3DRM2_iface.lpVtbl = &d3drm2_vtbl;
2344     object->IDirect3DRM3_iface.lpVtbl = &d3drm3_vtbl;
2345     object->ref1 = 1;
2346     object->iface_count = 1;
2347 
2348     *d3drm = &object->IDirect3DRM_iface;
2349 
2350     return S_OK;
2351 }
2352 
2353 HRESULT WINAPI DllCanUnloadNow(void)
2354 {
2355     return S_FALSE;
2356 }
2357 
2358 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
2359 {
2360     TRACE("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
2361 
2362     if(!ppv)
2363         return E_INVALIDARG;
2364 
2365     return CLASS_E_CLASSNOTAVAILABLE;
2366 }
2367