xref: /reactos/dll/directx/wine/d3drm/d3drm.c (revision 5ddbd373)
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     FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
642 
643     if (FAILED(hr = d3drm_texture_create(&object, iface)))
644         return hr;
645 
646     *texture = &object->IDirect3DRMTexture_iface;
647 
648     return D3DRM_OK;
649 }
650 
651 static HRESULT WINAPI d3drm1_LoadTextureFromResource(IDirect3DRM *iface,
652         HRSRC resource, IDirect3DRMTexture **texture)
653 {
654     struct d3drm_texture *object;
655     HRESULT hr;
656 
657     FIXME("iface %p, resource %p, texture %p stub!\n", iface, resource, texture);
658 
659     if (FAILED(hr = d3drm_texture_create(&object, iface)))
660         return hr;
661 
662     *texture = &object->IDirect3DRMTexture_iface;
663 
664     return D3DRM_OK;
665 }
666 
667 static HRESULT WINAPI d3drm1_SetSearchPath(IDirect3DRM *iface, const char *path)
668 {
669     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
670 
671     return E_NOTIMPL;
672 }
673 
674 static HRESULT WINAPI d3drm1_AddSearchPath(IDirect3DRM *iface, const char *path)
675 {
676     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
677 
678     return E_NOTIMPL;
679 }
680 
681 static HRESULT WINAPI d3drm1_GetSearchPath(IDirect3DRM *iface, DWORD *size, char *path)
682 {
683     FIXME("iface %p, size %p, path %p stub!\n", iface, size, path);
684 
685     return E_NOTIMPL;
686 }
687 
688 static HRESULT WINAPI d3drm1_SetDefaultTextureColors(IDirect3DRM *iface, DWORD color_count)
689 {
690     FIXME("iface %p, color_count %u stub!\n", iface, color_count);
691 
692     return E_NOTIMPL;
693 }
694 
695 static HRESULT WINAPI d3drm1_SetDefaultTextureShades(IDirect3DRM *iface, DWORD shade_count)
696 {
697     FIXME("iface %p, shade_count %u stub!\n", iface, shade_count);
698 
699     return E_NOTIMPL;
700 }
701 
702 static HRESULT WINAPI d3drm1_GetDevices(IDirect3DRM *iface, IDirect3DRMDeviceArray **array)
703 {
704     FIXME("iface %p, array %p stub!\n", iface, array);
705 
706     return E_NOTIMPL;
707 }
708 
709 static HRESULT WINAPI d3drm1_GetNamedObject(IDirect3DRM *iface,
710         const char *name, IDirect3DRMObject **object)
711 {
712     FIXME("iface %p, name %s, object %p stub!\n", iface, debugstr_a(name), object);
713 
714     return E_NOTIMPL;
715 }
716 
717 static HRESULT WINAPI d3drm1_EnumerateObjects(IDirect3DRM *iface, D3DRMOBJECTCALLBACK cb, void *ctx)
718 {
719     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
720 
721     return E_NOTIMPL;
722 }
723 
724 static HRESULT WINAPI d3drm1_Load(IDirect3DRM *iface, void *source, void *object_id, IID **iids,
725         DWORD iid_count, D3DRMLOADOPTIONS flags, D3DRMLOADCALLBACK load_cb, void *load_ctx,
726         D3DRMLOADTEXTURECALLBACK load_tex_cb, void *load_tex_ctx, IDirect3DRMFrame *parent_frame)
727 {
728     struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
729     IDirect3DRMFrame3 *parent_frame3 = NULL;
730     HRESULT hr = D3DRM_OK;
731 
732     TRACE("iface %p, source %p, object_id %p, iids %p, iid_count %u, flags %#x, "
733             "load_cb %p, load_ctx %p, load_tex_cb %p, load_tex_ctx %p, parent_frame %p.\n",
734             iface, source, object_id, iids, iid_count, flags,
735             load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame);
736 
737     if (parent_frame)
738         hr = IDirect3DRMFrame_QueryInterface(parent_frame, &IID_IDirect3DRMFrame3, (void **)&parent_frame3);
739     if (SUCCEEDED(hr))
740         hr = IDirect3DRM3_Load(&d3drm->IDirect3DRM3_iface, source, object_id, iids, iid_count,
741                 flags, load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame3);
742     if (parent_frame3)
743         IDirect3DRMFrame3_Release(parent_frame3);
744 
745     return hr;
746 }
747 
748 static HRESULT WINAPI d3drm1_Tick(IDirect3DRM *iface, D3DVALUE tick)
749 {
750     FIXME("iface %p, tick %.8e stub!\n", iface, tick);
751 
752     return E_NOTIMPL;
753 }
754 
755 static const struct IDirect3DRMVtbl d3drm1_vtbl =
756 {
757     d3drm1_QueryInterface,
758     d3drm1_AddRef,
759     d3drm1_Release,
760     d3drm1_CreateObject,
761     d3drm1_CreateFrame,
762     d3drm1_CreateMesh,
763     d3drm1_CreateMeshBuilder,
764     d3drm1_CreateFace,
765     d3drm1_CreateAnimation,
766     d3drm1_CreateAnimationSet,
767     d3drm1_CreateTexture,
768     d3drm1_CreateLight,
769     d3drm1_CreateLightRGB,
770     d3drm1_CreateMaterial,
771     d3drm1_CreateDevice,
772     d3drm1_CreateDeviceFromSurface,
773     d3drm1_CreateDeviceFromD3D,
774     d3drm1_CreateDeviceFromClipper,
775     d3drm1_CreateTextureFromSurface,
776     d3drm1_CreateShadow,
777     d3drm1_CreateViewport,
778     d3drm1_CreateWrap,
779     d3drm1_CreateUserVisual,
780     d3drm1_LoadTexture,
781     d3drm1_LoadTextureFromResource,
782     d3drm1_SetSearchPath,
783     d3drm1_AddSearchPath,
784     d3drm1_GetSearchPath,
785     d3drm1_SetDefaultTextureColors,
786     d3drm1_SetDefaultTextureShades,
787     d3drm1_GetDevices,
788     d3drm1_GetNamedObject,
789     d3drm1_EnumerateObjects,
790     d3drm1_Load,
791     d3drm1_Tick,
792 };
793 
794 static HRESULT WINAPI d3drm2_QueryInterface(IDirect3DRM2 *iface, REFIID riid, void **out)
795 {
796     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
797 
798     return d3drm1_QueryInterface(&d3drm->IDirect3DRM_iface, riid, out);
799 }
800 
801 static ULONG WINAPI d3drm2_AddRef(IDirect3DRM2 *iface)
802 {
803     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
804     ULONG refcount = InterlockedIncrement(&d3drm->ref2);
805 
806     TRACE("%p increasing refcount to %u.\n", iface, refcount);
807 
808     if (refcount == 1)
809         InterlockedIncrement(&d3drm->iface_count);
810 
811     return refcount;
812 }
813 
814 static ULONG WINAPI d3drm2_Release(IDirect3DRM2 *iface)
815 {
816     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
817     ULONG refcount = InterlockedDecrement(&d3drm->ref2);
818 
819     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
820 
821     if (!refcount && !InterlockedDecrement(&d3drm->iface_count))
822         d3drm_destroy(d3drm);
823 
824     return refcount;
825 }
826 
827 static HRESULT WINAPI d3drm2_CreateObject(IDirect3DRM2 *iface,
828         REFCLSID clsid, IUnknown *outer, REFIID iid, void **out)
829 {
830     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
831 
832     TRACE("iface %p, clsid %s, outer %p, iid %s, out %p.\n",
833             iface, debugstr_guid(clsid), outer, debugstr_guid(iid), out);
834 
835     return IDirect3DRM3_CreateObject(&d3drm->IDirect3DRM3_iface, clsid, outer, iid, out);
836 }
837 
838 static HRESULT WINAPI d3drm2_CreateFrame(IDirect3DRM2 *iface,
839         IDirect3DRMFrame *parent_frame, IDirect3DRMFrame2 **frame)
840 {
841     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
842     struct d3drm_frame *object;
843     HRESULT hr;
844 
845     TRACE("iface %p, parent_frame %p, frame %p.\n", iface, parent_frame, frame);
846 
847     if (FAILED(hr = d3drm_frame_create(&object, (IUnknown *)parent_frame, &d3drm->IDirect3DRM_iface)))
848         return hr;
849 
850     *frame = &object->IDirect3DRMFrame2_iface;
851 
852     return D3DRM_OK;
853 }
854 
855 static HRESULT WINAPI d3drm2_CreateMesh(IDirect3DRM2 *iface, IDirect3DRMMesh **mesh)
856 {
857     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
858 
859     TRACE("iface %p, mesh %p.\n", iface, mesh);
860 
861     return IDirect3DRM3_CreateMesh(&d3drm->IDirect3DRM3_iface, mesh);
862 }
863 
864 static HRESULT WINAPI d3drm2_CreateMeshBuilder(IDirect3DRM2 *iface, IDirect3DRMMeshBuilder2 **mesh_builder)
865 {
866     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
867     struct d3drm_mesh_builder *object;
868     HRESULT hr;
869 
870     TRACE("iface %p, mesh_builder %p.\n", iface, mesh_builder);
871 
872     if (FAILED(hr = d3drm_mesh_builder_create(&object, &d3drm->IDirect3DRM_iface)))
873         return hr;
874 
875     *mesh_builder = &object->IDirect3DRMMeshBuilder2_iface;
876 
877     return S_OK;
878 }
879 
880 static HRESULT WINAPI d3drm2_CreateFace(IDirect3DRM2 *iface, IDirect3DRMFace **face)
881 {
882     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
883 
884     TRACE("iface %p, face %p.\n", iface, face);
885 
886     return IDirect3DRM_CreateFace(&d3drm->IDirect3DRM_iface, face);
887 }
888 
889 static HRESULT WINAPI d3drm2_CreateAnimation(IDirect3DRM2 *iface, IDirect3DRMAnimation **animation)
890 {
891     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
892 
893     TRACE("iface %p, animation %p.\n", iface, animation);
894 
895     return IDirect3DRM_CreateAnimation(&d3drm->IDirect3DRM_iface, animation);
896 }
897 
898 static HRESULT WINAPI d3drm2_CreateAnimationSet(IDirect3DRM2 *iface, IDirect3DRMAnimationSet **set)
899 {
900     FIXME("iface %p, set %p stub!\n", iface, set);
901 
902     return E_NOTIMPL;
903 }
904 
905 static HRESULT WINAPI d3drm2_CreateTexture(IDirect3DRM2 *iface,
906         D3DRMIMAGE *image, IDirect3DRMTexture2 **texture)
907 {
908     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
909     IDirect3DRMTexture3 *texture3;
910     HRESULT hr;
911 
912     TRACE("iface %p, image %p, texture %p.\n", iface, image, texture);
913 
914     if (!texture)
915         return D3DRMERR_BADVALUE;
916 
917     if (FAILED(hr = IDirect3DRM3_CreateTexture(&d3drm->IDirect3DRM3_iface, image, &texture3)))
918     {
919         *texture = NULL;
920         return hr;
921     }
922 
923     hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture2, (void **)texture);
924     IDirect3DRMTexture3_Release(texture3);
925 
926     return hr;
927 }
928 
929 static HRESULT WINAPI d3drm2_CreateLight(IDirect3DRM2 *iface,
930         D3DRMLIGHTTYPE type, D3DCOLOR color, IDirect3DRMLight **light)
931 {
932     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
933 
934     TRACE("iface %p, type %#x, color 0x%08x, light %p.\n", iface, type, color, light);
935 
936     return IDirect3DRM3_CreateLight(&d3drm->IDirect3DRM3_iface, type, color, light);
937 }
938 
939 static HRESULT WINAPI d3drm2_CreateLightRGB(IDirect3DRM2 *iface, D3DRMLIGHTTYPE type,
940         D3DVALUE red, D3DVALUE green, D3DVALUE blue, IDirect3DRMLight **light)
941 {
942     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
943 
944     TRACE("iface %p, type %#x, red %.8e, green %.8e, blue %.8e, light %p.\n",
945             iface, type, red, green, blue, light);
946 
947     return IDirect3DRM3_CreateLightRGB(&d3drm->IDirect3DRM3_iface, type, red, green, blue, light);
948 }
949 
950 static HRESULT WINAPI d3drm2_CreateMaterial(IDirect3DRM2 *iface,
951         D3DVALUE power, IDirect3DRMMaterial **material)
952 {
953     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
954 
955     TRACE("iface %p, power %.8e, material %p.\n", iface, power, material);
956 
957     return IDirect3DRM3_CreateMaterial(&d3drm->IDirect3DRM3_iface, power, (IDirect3DRMMaterial2 **)material);
958 }
959 
960 static HRESULT WINAPI d3drm2_CreateDevice(IDirect3DRM2 *iface,
961         DWORD width, DWORD height, IDirect3DRMDevice2 **device)
962 {
963     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
964     struct d3drm_device *object;
965     HRESULT hr;
966 
967     FIXME("iface %p, width %u, height %u, device %p partial stub!\n", iface, width, height, device);
968 
969     if (FAILED(hr = d3drm_device_create(&object, &d3drm->IDirect3DRM_iface)))
970         return hr;
971 
972     *device = &object->IDirect3DRMDevice2_iface;
973 
974     return D3DRM_OK;
975 }
976 
977 static HRESULT WINAPI d3drm2_CreateDeviceFromSurface(IDirect3DRM2 *iface, GUID *guid,
978         IDirectDraw *ddraw, IDirectDrawSurface *backbuffer, IDirect3DRMDevice2 **device)
979 {
980     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
981     IDirect3DRMDevice3 *device3;
982     HRESULT hr;
983     TRACE("iface %p, guid %s, ddraw %p, backbuffer %p, device %p.\n",
984             iface, debugstr_guid(guid), ddraw, backbuffer, device);
985 
986     if (!device)
987         return D3DRMERR_BADVALUE;
988     *device = NULL;
989     hr = IDirect3DRM3_CreateDeviceFromSurface(&d3drm->IDirect3DRM3_iface, guid, ddraw, backbuffer, 0, &device3);
990     if (FAILED(hr))
991         return hr;
992 
993     hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice2, (void**)device);
994     IDirect3DRMDevice3_Release(device3);
995 
996     return hr;
997 }
998 
999 static HRESULT WINAPI d3drm2_CreateDeviceFromD3D(IDirect3DRM2 *iface,
1000     IDirect3D2 *d3d, IDirect3DDevice2 *d3d_device, IDirect3DRMDevice2 **device)
1001 {
1002     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1003     IDirect3DRMDevice3 *device3;
1004     HRESULT hr;
1005 
1006     TRACE("iface %p, d3d %p, d3d_device %p, device %p.\n",
1007             iface, d3d, d3d_device, device);
1008 
1009     if (!device)
1010         return D3DRMERR_BADVALUE;
1011     *device = NULL;
1012 
1013     hr = IDirect3DRM3_CreateDeviceFromD3D(&d3drm->IDirect3DRM3_iface, d3d, d3d_device, &device3);
1014     if (FAILED(hr))
1015         return hr;
1016 
1017     hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice2, (void **)device);
1018     IDirect3DRMDevice3_Release(device3);
1019 
1020     return hr;
1021 }
1022 
1023 static HRESULT WINAPI d3drm2_CreateDeviceFromClipper(IDirect3DRM2 *iface,
1024         IDirectDrawClipper *clipper, GUID *guid, int width, int height,
1025         IDirect3DRMDevice2 **device)
1026 {
1027     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1028     IDirect3DRMDevice3 *device3;
1029     HRESULT hr;
1030 
1031     TRACE("iface %p, clipper %p, guid %s, width %d, height %d, device %p.\n",
1032             iface, clipper, debugstr_guid(guid), width, height, device);
1033 
1034     if (!device)
1035         return D3DRMERR_BADVALUE;
1036     *device = NULL;
1037     hr = IDirect3DRM3_CreateDeviceFromClipper(&d3drm->IDirect3DRM3_iface, clipper, guid, width, height, &device3);
1038     if (FAILED(hr))
1039         return hr;
1040 
1041     hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice2, (void**)device);
1042     IDirect3DRMDevice3_Release(device3);
1043 
1044     return hr;
1045 }
1046 
1047 static HRESULT WINAPI d3drm2_CreateTextureFromSurface(IDirect3DRM2 *iface,
1048         IDirectDrawSurface *surface, IDirect3DRMTexture2 **texture)
1049 {
1050     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1051     IDirect3DRMTexture3 *texture3;
1052     HRESULT hr;
1053 
1054     TRACE("iface %p, surface %p, texture %p.\n", iface, surface, texture);
1055 
1056     if (!texture)
1057         return D3DRMERR_BADVALUE;
1058 
1059     if (FAILED(hr = IDirect3DRM3_CreateTextureFromSurface(&d3drm->IDirect3DRM3_iface, surface, &texture3)))
1060     {
1061         *texture = NULL;
1062         return hr;
1063     }
1064 
1065     hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture, (void **)texture);
1066     IDirect3DRMTexture3_Release(texture3);
1067 
1068     return hr;
1069 }
1070 
1071 static HRESULT WINAPI d3drm2_CreateShadow(IDirect3DRM2 *iface, IDirect3DRMVisual *visual,
1072         IDirect3DRMLight *light, D3DVALUE px, D3DVALUE py, D3DVALUE pz, D3DVALUE nx, D3DVALUE ny, D3DVALUE nz,
1073         IDirect3DRMVisual **shadow)
1074 {
1075     FIXME("iface %p, visual %p, light %p, px %.8e, py %.8e, pz %.8e, nx %.8e, ny %.8e, nz %.8e, shadow %p stub!\n",
1076             iface, visual, light, px, py, pz, nx, ny, nz, shadow);
1077 
1078     return E_NOTIMPL;
1079 }
1080 
1081 static HRESULT WINAPI d3drm2_CreateViewport(IDirect3DRM2 *iface, IDirect3DRMDevice *device,
1082         IDirect3DRMFrame *camera, DWORD x, DWORD y, DWORD width, DWORD height, IDirect3DRMViewport **viewport)
1083 {
1084     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1085     IDirect3DRMDevice3 *device3;
1086     IDirect3DRMFrame3 *camera3;
1087     IDirect3DRMViewport2 *viewport2;
1088     HRESULT hr;
1089 
1090     TRACE("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u, viewport %p.\n",
1091           iface, device, camera, x, y, width, height, viewport);
1092 
1093     if (!device || !camera)
1094         return D3DRMERR_BADOBJECT;
1095     if (!viewport)
1096         return D3DRMERR_BADVALUE;
1097 
1098     if (FAILED(hr = IDirect3DRMDevice_QueryInterface(device, &IID_IDirect3DRMDevice3, (void **)&device3)))
1099         return hr;
1100 
1101     if (FAILED(hr = IDirect3DRMFrame_QueryInterface(camera, &IID_IDirect3DRMFrame3, (void **)&camera3)))
1102     {
1103         IDirect3DRMDevice3_Release(device3);
1104         return hr;
1105     }
1106 
1107     hr = IDirect3DRM3_CreateViewport(&d3drm->IDirect3DRM3_iface, device3, camera3, x, y, width, height, &viewport2);
1108     IDirect3DRMDevice3_Release(device3);
1109     IDirect3DRMFrame3_Release(camera3);
1110     if (FAILED(hr))
1111         return hr;
1112 
1113     hr = IDirect3DRMViewport2_QueryInterface(viewport2, &IID_IDirect3DRMViewport, (void **)viewport);
1114     IDirect3DRMViewport2_Release(viewport2);
1115 
1116     return hr;
1117 }
1118 
1119 static HRESULT WINAPI d3drm2_CreateWrap(IDirect3DRM2 *iface, D3DRMWRAPTYPE type, IDirect3DRMFrame *frame,
1120         D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
1121         D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, D3DVALUE ou, D3DVALUE ov, D3DVALUE su, D3DVALUE sv,
1122         IDirect3DRMWrap **wrap)
1123 {
1124     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1125 
1126     TRACE("iface %p, type %#x, frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, "
1127             "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p.\n",
1128             iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz, ou, ov, su, sv, wrap);
1129 
1130     return IDirect3DRM_CreateWrap(&d3drm->IDirect3DRM_iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz,
1131             ou, ov, su, sv, wrap);
1132 }
1133 
1134 static HRESULT WINAPI d3drm2_CreateUserVisual(IDirect3DRM2 *iface,
1135         D3DRMUSERVISUALCALLBACK cb, void *ctx, IDirect3DRMUserVisual **visual)
1136 {
1137     FIXME("iface %p, cb %p, ctx %p, visual %p stub!\n", iface, cb, ctx, visual);
1138 
1139     return E_NOTIMPL;
1140 }
1141 
1142 static HRESULT WINAPI d3drm2_LoadTexture(IDirect3DRM2 *iface,
1143         const char *filename, IDirect3DRMTexture2 **texture)
1144 {
1145     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1146     struct d3drm_texture *object;
1147     HRESULT hr;
1148 
1149     FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
1150 
1151     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1152         return hr;
1153 
1154     *texture = &object->IDirect3DRMTexture2_iface;
1155 
1156     return hr;
1157 }
1158 
1159 static HRESULT WINAPI d3drm2_LoadTextureFromResource(IDirect3DRM2 *iface, HMODULE module,
1160         const char *resource_name, const char *resource_type, IDirect3DRMTexture2 **texture)
1161 {
1162     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1163     struct d3drm_texture *object;
1164     HRESULT hr;
1165 
1166     FIXME("iface %p, resource_name %s, resource_type %s, texture %p stub!\n",
1167             iface, debugstr_a(resource_name), debugstr_a(resource_type), texture);
1168 
1169     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1170         return hr;
1171 
1172     *texture = &object->IDirect3DRMTexture2_iface;
1173 
1174     return D3DRM_OK;
1175 }
1176 
1177 static HRESULT WINAPI d3drm2_SetSearchPath(IDirect3DRM2 *iface, const char *path)
1178 {
1179     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
1180 
1181     return E_NOTIMPL;
1182 }
1183 
1184 static HRESULT WINAPI d3drm2_AddSearchPath(IDirect3DRM2 *iface, const char *path)
1185 {
1186     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
1187 
1188     return E_NOTIMPL;
1189 }
1190 
1191 static HRESULT WINAPI d3drm2_GetSearchPath(IDirect3DRM2 *iface, DWORD *size, char *path)
1192 {
1193     FIXME("iface %p, size %p, path %p stub!\n", iface, size, path);
1194 
1195     return E_NOTIMPL;
1196 }
1197 
1198 static HRESULT WINAPI d3drm2_SetDefaultTextureColors(IDirect3DRM2 *iface, DWORD color_count)
1199 {
1200     FIXME("iface %p, color_count %u stub!\n", iface, color_count);
1201 
1202     return E_NOTIMPL;
1203 }
1204 
1205 static HRESULT WINAPI d3drm2_SetDefaultTextureShades(IDirect3DRM2 *iface, DWORD shade_count)
1206 {
1207     FIXME("iface %p, shade_count %u stub!\n", iface, shade_count);
1208 
1209     return E_NOTIMPL;
1210 }
1211 
1212 static HRESULT WINAPI d3drm2_GetDevices(IDirect3DRM2 *iface, IDirect3DRMDeviceArray **array)
1213 {
1214     FIXME("iface %p, array %p stub!\n", iface, array);
1215 
1216     return E_NOTIMPL;
1217 }
1218 
1219 static HRESULT WINAPI d3drm2_GetNamedObject(IDirect3DRM2 *iface,
1220         const char *name, IDirect3DRMObject **object)
1221 {
1222     FIXME("iface %p, name %s, object %p stub!\n", iface, debugstr_a(name), object);
1223 
1224     return E_NOTIMPL;
1225 }
1226 
1227 static HRESULT WINAPI d3drm2_EnumerateObjects(IDirect3DRM2 *iface, D3DRMOBJECTCALLBACK cb, void *ctx)
1228 {
1229     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
1230 
1231     return E_NOTIMPL;
1232 }
1233 
1234 static HRESULT WINAPI d3drm2_Load(IDirect3DRM2 *iface, void *source, void *object_id, IID **iids,
1235         DWORD iid_count, D3DRMLOADOPTIONS flags, D3DRMLOADCALLBACK load_cb, void *load_ctx,
1236         D3DRMLOADTEXTURECALLBACK load_tex_cb, void *load_tex_ctx, IDirect3DRMFrame *parent_frame)
1237 {
1238     struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
1239     IDirect3DRMFrame3 *parent_frame3 = NULL;
1240     HRESULT hr = D3DRM_OK;
1241 
1242     TRACE("iface %p, source %p, object_id %p, iids %p, iid_count %u, flags %#x, "
1243             "load_cb %p, load_ctx %p, load_tex_cb %p, load_tex_ctx %p, parent_frame %p.\n",
1244             iface, source, object_id, iids, iid_count, flags,
1245             load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame);
1246 
1247     if (parent_frame)
1248         hr = IDirect3DRMFrame_QueryInterface(parent_frame, &IID_IDirect3DRMFrame3, (void **)&parent_frame3);
1249     if (SUCCEEDED(hr))
1250         hr = IDirect3DRM3_Load(&d3drm->IDirect3DRM3_iface, source, object_id, iids, iid_count,
1251                 flags, load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame3);
1252     if (parent_frame3)
1253         IDirect3DRMFrame3_Release(parent_frame3);
1254 
1255     return hr;
1256 }
1257 
1258 static HRESULT WINAPI d3drm2_Tick(IDirect3DRM2 *iface, D3DVALUE tick)
1259 {
1260     FIXME("iface %p, tick %.8e stub!\n", iface, tick);
1261 
1262     return E_NOTIMPL;
1263 }
1264 
1265 static HRESULT WINAPI d3drm2_CreateProgressiveMesh(IDirect3DRM2 *iface, IDirect3DRMProgressiveMesh **mesh)
1266 {
1267     FIXME("iface %p, mesh %p stub!\n", iface, mesh);
1268 
1269     return E_NOTIMPL;
1270 }
1271 
1272 static const struct IDirect3DRM2Vtbl d3drm2_vtbl =
1273 {
1274     d3drm2_QueryInterface,
1275     d3drm2_AddRef,
1276     d3drm2_Release,
1277     d3drm2_CreateObject,
1278     d3drm2_CreateFrame,
1279     d3drm2_CreateMesh,
1280     d3drm2_CreateMeshBuilder,
1281     d3drm2_CreateFace,
1282     d3drm2_CreateAnimation,
1283     d3drm2_CreateAnimationSet,
1284     d3drm2_CreateTexture,
1285     d3drm2_CreateLight,
1286     d3drm2_CreateLightRGB,
1287     d3drm2_CreateMaterial,
1288     d3drm2_CreateDevice,
1289     d3drm2_CreateDeviceFromSurface,
1290     d3drm2_CreateDeviceFromD3D,
1291     d3drm2_CreateDeviceFromClipper,
1292     d3drm2_CreateTextureFromSurface,
1293     d3drm2_CreateShadow,
1294     d3drm2_CreateViewport,
1295     d3drm2_CreateWrap,
1296     d3drm2_CreateUserVisual,
1297     d3drm2_LoadTexture,
1298     d3drm2_LoadTextureFromResource,
1299     d3drm2_SetSearchPath,
1300     d3drm2_AddSearchPath,
1301     d3drm2_GetSearchPath,
1302     d3drm2_SetDefaultTextureColors,
1303     d3drm2_SetDefaultTextureShades,
1304     d3drm2_GetDevices,
1305     d3drm2_GetNamedObject,
1306     d3drm2_EnumerateObjects,
1307     d3drm2_Load,
1308     d3drm2_Tick,
1309     d3drm2_CreateProgressiveMesh,
1310 };
1311 
1312 static HRESULT WINAPI d3drm3_QueryInterface(IDirect3DRM3 *iface, REFIID riid, void **out)
1313 {
1314     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1315 
1316     return d3drm1_QueryInterface(&d3drm->IDirect3DRM_iface, riid, out);
1317 }
1318 
1319 static ULONG WINAPI d3drm3_AddRef(IDirect3DRM3 *iface)
1320 {
1321     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1322     ULONG refcount = InterlockedIncrement(&d3drm->ref3);
1323 
1324     TRACE("%p increasing refcount to %u.\n", iface, refcount);
1325 
1326     if (refcount == 1)
1327         InterlockedIncrement(&d3drm->iface_count);
1328 
1329     return refcount;
1330 }
1331 
1332 static ULONG WINAPI d3drm3_Release(IDirect3DRM3 *iface)
1333 {
1334     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1335     ULONG refcount = InterlockedDecrement(&d3drm->ref3);
1336 
1337     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
1338 
1339     if (!refcount && !InterlockedDecrement(&d3drm->iface_count))
1340         d3drm_destroy(d3drm);
1341 
1342     return refcount;
1343 }
1344 
1345 static HRESULT WINAPI d3drm3_CreateObject(IDirect3DRM3 *iface,
1346         REFCLSID clsid, IUnknown *outer, REFIID iid, void **out)
1347 {
1348     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1349     IUnknown *object;
1350     unsigned int i;
1351     HRESULT hr;
1352 
1353     static const struct
1354     {
1355         const CLSID *clsid;
1356         HRESULT (*create_object)(void **object, IDirect3DRM *d3drm);
1357     }
1358     object_table[] =
1359     {
1360         {&CLSID_CDirect3DRMTexture, d3drm_create_texture_object},
1361         {&CLSID_CDirect3DRMDevice, d3drm_create_device_object},
1362         {&CLSID_CDirect3DRMViewport, d3drm_create_viewport_object},
1363         {&CLSID_CDirect3DRMFace, d3drm_create_face_object},
1364         {&CLSID_CDirect3DRMMeshBuilder, d3drm_create_mesh_builder_object},
1365         {&CLSID_CDirect3DRMFrame, d3drm_create_frame_object},
1366         {&CLSID_CDirect3DRMLight, d3drm_create_light_object},
1367         {&CLSID_CDirect3DRMMaterial, d3drm_create_material_object},
1368         {&CLSID_CDirect3DRMMesh, d3drm_create_mesh_object},
1369         {&CLSID_CDirect3DRMAnimation, d3drm_create_animation_object},
1370         {&CLSID_CDirect3DRMWrap, d3drm_create_wrap_object},
1371     };
1372 
1373     TRACE("iface %p, clsid %s, outer %p, iid %s, out %p.\n",
1374             iface, debugstr_guid(clsid), outer, debugstr_guid(iid), out);
1375 
1376     if (!out)
1377         return D3DRMERR_BADVALUE;
1378 
1379     if (!clsid || !iid)
1380     {
1381         *out = NULL;
1382         return D3DRMERR_BADVALUE;
1383     }
1384 
1385     if (outer)
1386     {
1387         FIXME("COM aggregation for outer IUnknown (%p) not implemented. Returning E_NOTIMPL.\n", outer);
1388         *out = NULL;
1389         return E_NOTIMPL;
1390     }
1391 
1392     for (i = 0; i < ARRAY_SIZE(object_table); ++i)
1393     {
1394         if (IsEqualGUID(clsid, object_table[i].clsid))
1395         {
1396             if (FAILED(hr = object_table[i].create_object((void **)&object, &d3drm->IDirect3DRM_iface)))
1397             {
1398                 *out = NULL;
1399                 return hr;
1400             }
1401             break;
1402         }
1403     }
1404     if (i == ARRAY_SIZE(object_table))
1405     {
1406         FIXME("%s not implemented. Returning CLASSFACTORY_E_FIRST.\n", debugstr_guid(clsid));
1407         *out = NULL;
1408         return CLASSFACTORY_E_FIRST;
1409     }
1410 
1411     if (FAILED(hr = IUnknown_QueryInterface(object, iid, out)))
1412         *out = NULL;
1413     IUnknown_Release(object);
1414 
1415     return hr;
1416 }
1417 
1418 static HRESULT WINAPI d3drm3_CreateFrame(IDirect3DRM3 *iface,
1419         IDirect3DRMFrame3 *parent, IDirect3DRMFrame3 **frame)
1420 {
1421     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1422     struct d3drm_frame *object;
1423     HRESULT hr;
1424 
1425     TRACE("iface %p, parent %p, frame %p.\n", iface, parent, frame);
1426 
1427     if (FAILED(hr = d3drm_frame_create(&object, (IUnknown *)parent, &d3drm->IDirect3DRM_iface)))
1428         return hr;
1429 
1430     *frame = &object->IDirect3DRMFrame3_iface;
1431 
1432     return D3DRM_OK;
1433 }
1434 
1435 static HRESULT WINAPI d3drm3_CreateMesh(IDirect3DRM3 *iface, IDirect3DRMMesh **mesh)
1436 {
1437     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1438     struct d3drm_mesh *object;
1439     HRESULT hr;
1440 
1441     TRACE("iface %p, mesh %p.\n", iface, mesh);
1442 
1443     if (FAILED(hr = d3drm_mesh_create(&object, &d3drm->IDirect3DRM_iface)))
1444         return hr;
1445 
1446     *mesh = &object->IDirect3DRMMesh_iface;
1447 
1448     return S_OK;
1449 }
1450 
1451 static HRESULT WINAPI d3drm3_CreateMeshBuilder(IDirect3DRM3 *iface, IDirect3DRMMeshBuilder3 **mesh_builder)
1452 {
1453     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1454     struct d3drm_mesh_builder *object;
1455     HRESULT hr;
1456 
1457     TRACE("iface %p, mesh_builder %p.\n", iface, mesh_builder);
1458 
1459     if (FAILED(hr = d3drm_mesh_builder_create(&object, &d3drm->IDirect3DRM_iface)))
1460         return hr;
1461 
1462     *mesh_builder = &object->IDirect3DRMMeshBuilder3_iface;
1463 
1464     return S_OK;
1465 }
1466 
1467 static HRESULT WINAPI d3drm3_CreateFace(IDirect3DRM3 *iface, IDirect3DRMFace2 **face)
1468 {
1469     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1470     IDirect3DRMFace *face1;
1471     HRESULT hr;
1472 
1473     TRACE("iface %p, face %p.\n", iface, face);
1474 
1475     if (FAILED(hr = IDirect3DRM_CreateFace(&d3drm->IDirect3DRM_iface, &face1)))
1476         return hr;
1477 
1478     hr = IDirect3DRMFace_QueryInterface(face1, &IID_IDirect3DRMFace2, (void **)face);
1479     IDirect3DRMFace_Release(face1);
1480 
1481     return hr;
1482 }
1483 
1484 static HRESULT WINAPI d3drm3_CreateAnimation(IDirect3DRM3 *iface, IDirect3DRMAnimation2 **animation)
1485 {
1486     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1487     struct d3drm_animation *object;
1488     HRESULT hr;
1489 
1490     TRACE("iface %p, animation %p.\n", iface, animation);
1491 
1492     if (FAILED(hr = d3drm_animation_create(&object, &d3drm->IDirect3DRM_iface)))
1493         return hr;
1494 
1495     *animation = &object->IDirect3DRMAnimation2_iface;
1496 
1497     return hr;
1498 }
1499 
1500 static HRESULT WINAPI d3drm3_CreateAnimationSet(IDirect3DRM3 *iface, IDirect3DRMAnimationSet2 **set)
1501 {
1502     FIXME("iface %p, set %p stub!\n", iface, set);
1503 
1504     return E_NOTIMPL;
1505 }
1506 
1507 static HRESULT WINAPI d3drm3_CreateTexture(IDirect3DRM3 *iface,
1508         D3DRMIMAGE *image, IDirect3DRMTexture3 **texture)
1509 {
1510     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1511     struct d3drm_texture *object;
1512     HRESULT hr;
1513 
1514     TRACE("iface %p, image %p, texture %p.\n", iface, image, texture);
1515 
1516     if (!texture)
1517         return D3DRMERR_BADVALUE;
1518 
1519     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1520         return hr;
1521 
1522     *texture = &object->IDirect3DRMTexture3_iface;
1523 
1524     if (FAILED(IDirect3DRMTexture3_InitFromImage(*texture, image)))
1525     {
1526         IDirect3DRMTexture3_Release(*texture);
1527         *texture = NULL;
1528         return D3DRMERR_BADVALUE;
1529     }
1530 
1531     return D3DRM_OK;
1532 }
1533 
1534 static HRESULT WINAPI d3drm3_CreateLight(IDirect3DRM3 *iface,
1535         D3DRMLIGHTTYPE type, D3DCOLOR color, IDirect3DRMLight **light)
1536 {
1537     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1538     struct d3drm_light *object;
1539     HRESULT hr;
1540 
1541     FIXME("iface %p, type %#x, color 0x%08x, light %p partial stub!\n", iface, type, color, light);
1542 
1543     if (SUCCEEDED(hr = d3drm_light_create(&object, &d3drm->IDirect3DRM_iface)))
1544     {
1545         IDirect3DRMLight_SetType(&object->IDirect3DRMLight_iface, type);
1546         IDirect3DRMLight_SetColor(&object->IDirect3DRMLight_iface, color);
1547     }
1548 
1549     *light = &object->IDirect3DRMLight_iface;
1550 
1551     return hr;
1552 }
1553 
1554 static HRESULT WINAPI d3drm3_CreateLightRGB(IDirect3DRM3 *iface, D3DRMLIGHTTYPE type,
1555         D3DVALUE red, D3DVALUE green, D3DVALUE blue, IDirect3DRMLight **light)
1556 {
1557     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1558     struct d3drm_light *object;
1559     HRESULT hr;
1560 
1561     FIXME("iface %p, type %#x, red %.8e, green %.8e, blue %.8e, light %p partial stub!\n",
1562             iface, type, red, green, blue, light);
1563 
1564     if (SUCCEEDED(hr = d3drm_light_create(&object, &d3drm->IDirect3DRM_iface)))
1565     {
1566         IDirect3DRMLight_SetType(&object->IDirect3DRMLight_iface, type);
1567         IDirect3DRMLight_SetColorRGB(&object->IDirect3DRMLight_iface, red, green, blue);
1568     }
1569 
1570     *light = &object->IDirect3DRMLight_iface;
1571 
1572     return hr;
1573 }
1574 
1575 static HRESULT WINAPI d3drm3_CreateMaterial(IDirect3DRM3 *iface,
1576         D3DVALUE power, IDirect3DRMMaterial2 **material)
1577 {
1578     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1579     struct d3drm_material *object;
1580     HRESULT hr;
1581 
1582     TRACE("iface %p, power %.8e, material %p.\n", iface, power, material);
1583 
1584     if (SUCCEEDED(hr = d3drm_material_create(&object, &d3drm->IDirect3DRM_iface)))
1585         IDirect3DRMMaterial2_SetPower(&object->IDirect3DRMMaterial2_iface, power);
1586 
1587     *material = &object->IDirect3DRMMaterial2_iface;
1588 
1589     return hr;
1590 }
1591 
1592 static HRESULT WINAPI d3drm3_CreateDevice(IDirect3DRM3 *iface,
1593         DWORD width, DWORD height, IDirect3DRMDevice3 **device)
1594 {
1595     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1596     struct d3drm_device *object;
1597     HRESULT hr;
1598 
1599     FIXME("iface %p, width %u, height %u, device %p partial stub!\n", iface, width, height, device);
1600 
1601     if (FAILED(hr = d3drm_device_create(&object, &d3drm->IDirect3DRM_iface)))
1602         return hr;
1603 
1604     *device = &object->IDirect3DRMDevice3_iface;
1605 
1606     return D3DRM_OK;
1607 }
1608 
1609 static HRESULT WINAPI d3drm3_CreateDeviceFromSurface(IDirect3DRM3 *iface, GUID *guid,
1610         IDirectDraw *ddraw, IDirectDrawSurface *backbuffer, DWORD flags, IDirect3DRMDevice3 **device)
1611 {
1612     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1613     struct d3drm_device *object;
1614     BOOL use_z_surface;
1615     HRESULT hr;
1616 
1617     TRACE("iface %p, guid %s, ddraw %p, backbuffer %p, flags %#x, device %p.\n",
1618             iface, debugstr_guid(guid), ddraw, backbuffer, flags, device);
1619 
1620     if (!device)
1621         return D3DRMERR_BADVALUE;
1622     *device = NULL;
1623 
1624     if (!backbuffer || !ddraw)
1625         return D3DRMERR_BADDEVICE;
1626 
1627     if (FAILED(hr = d3drm_device_create(&object, &d3drm->IDirect3DRM_iface)))
1628         return hr;
1629 
1630     use_z_surface = !(flags & D3DRMDEVICE_NOZBUFFER);
1631 
1632     if (SUCCEEDED(hr = d3drm_device_init(object, 3, ddraw, backbuffer, use_z_surface)))
1633         *device = &object->IDirect3DRMDevice3_iface;
1634     else
1635         d3drm_device_destroy(object);
1636 
1637     return hr;
1638 }
1639 
1640 static HRESULT WINAPI d3drm3_CreateDeviceFromD3D(IDirect3DRM3 *iface,
1641         IDirect3D2 *d3d, IDirect3DDevice2 *d3d_device, IDirect3DRMDevice3 **device)
1642 {
1643     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1644     struct d3drm_device *object;
1645     HRESULT hr;
1646 
1647     TRACE("iface %p, d3d %p, d3d_device %p, device %p.\n",
1648             iface, d3d, d3d_device, device);
1649 
1650     if (!device)
1651         return D3DRMERR_BADVALUE;
1652     *device = NULL;
1653 
1654     if (FAILED(hr = d3drm_device_create(&object, &d3drm->IDirect3DRM_iface)))
1655         return hr;
1656 
1657     if (FAILED(hr = IDirect3DRMDevice3_InitFromD3D2(&object->IDirect3DRMDevice3_iface, d3d, d3d_device)))
1658     {
1659         d3drm_device_destroy(object);
1660         return hr;
1661     }
1662     *device = &object->IDirect3DRMDevice3_iface;
1663 
1664     return D3DRM_OK;
1665 }
1666 
1667 static HRESULT WINAPI d3drm3_CreateDeviceFromClipper(IDirect3DRM3 *iface,
1668         IDirectDrawClipper *clipper, GUID *guid, int width, int height,
1669         IDirect3DRMDevice3 **device)
1670 {
1671     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1672     struct d3drm_device *object;
1673     IDirectDraw *ddraw;
1674     IDirectDrawSurface *render_target;
1675     HRESULT hr;
1676 
1677     TRACE("iface %p, clipper %p, guid %s, width %d, height %d, device %p.\n",
1678             iface, clipper, debugstr_guid(guid), width, height, device);
1679 
1680     if (!device)
1681         return D3DRMERR_BADVALUE;
1682     *device = NULL;
1683 
1684     if (!clipper || !width || !height)
1685         return D3DRMERR_BADVALUE;
1686 
1687     hr = DirectDrawCreate(NULL, &ddraw, NULL);
1688     if (FAILED(hr))
1689         return hr;
1690 
1691     if (FAILED(hr = d3drm_device_create(&object, &d3drm->IDirect3DRM_iface)))
1692     {
1693         IDirectDraw_Release(ddraw);
1694         return hr;
1695     }
1696 
1697     hr = d3drm_device_create_surfaces_from_clipper(object, ddraw, clipper, width, height, &render_target);
1698     if (FAILED(hr))
1699     {
1700         IDirectDraw_Release(ddraw);
1701         d3drm_device_destroy(object);
1702         return hr;
1703     }
1704 
1705     hr = d3drm_device_init(object, 3, ddraw, render_target, TRUE);
1706     IDirectDraw_Release(ddraw);
1707     IDirectDrawSurface_Release(render_target);
1708     if (FAILED(hr))
1709         d3drm_device_destroy(object);
1710     else
1711         *device = &object->IDirect3DRMDevice3_iface;
1712 
1713     return hr;
1714 }
1715 
1716 static HRESULT WINAPI d3drm3_CreateShadow(IDirect3DRM3 *iface, IUnknown *object, IDirect3DRMLight *light,
1717         D3DVALUE px, D3DVALUE py, D3DVALUE pz, D3DVALUE nx, D3DVALUE ny, D3DVALUE nz, IDirect3DRMShadow2 **shadow)
1718 {
1719     FIXME("iface %p, object %p, light %p, px %.8e, py %.8e, pz %.8e, nx %.8e, ny %.8e, nz %.8e, shadow %p stub!\n",
1720             iface, object, light, px, py, pz, nx, ny, nz, shadow);
1721 
1722     return E_NOTIMPL;
1723 }
1724 
1725 static HRESULT WINAPI d3drm3_CreateTextureFromSurface(IDirect3DRM3 *iface,
1726         IDirectDrawSurface *surface, IDirect3DRMTexture3 **texture)
1727 {
1728     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1729     struct d3drm_texture *object;
1730     HRESULT hr;
1731 
1732     TRACE("iface %p, surface %p, texture %p.\n", iface, surface, texture);
1733 
1734     if (!texture)
1735         return D3DRMERR_BADVALUE;
1736 
1737     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1738         return hr;
1739 
1740     *texture = &object->IDirect3DRMTexture3_iface;
1741 
1742     if (FAILED(IDirect3DRMTexture3_InitFromSurface(*texture, surface)))
1743     {
1744         IDirect3DRMTexture3_Release(*texture);
1745         *texture = NULL;
1746         return D3DRMERR_BADVALUE;
1747     }
1748 
1749     return D3DRM_OK;
1750 }
1751 
1752 static HRESULT WINAPI d3drm3_CreateViewport(IDirect3DRM3 *iface, IDirect3DRMDevice3 *device,
1753         IDirect3DRMFrame3 *camera, DWORD x, DWORD y, DWORD width, DWORD height, IDirect3DRMViewport2 **viewport)
1754 {
1755     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1756     struct d3drm_viewport *object;
1757     HRESULT hr;
1758 
1759     TRACE("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u, viewport %p.\n",
1760             iface, device, camera, x, y, width, height, viewport);
1761 
1762     if (!device || !camera)
1763         return D3DRMERR_BADOBJECT;
1764     if (!viewport)
1765         return D3DRMERR_BADVALUE;
1766 
1767     if (FAILED(hr = d3drm_viewport_create(&object, &d3drm->IDirect3DRM_iface)))
1768         return hr;
1769 
1770     *viewport = &object->IDirect3DRMViewport2_iface;
1771 
1772     if (FAILED(hr = IDirect3DRMViewport2_Init(*viewport, device, camera, x, y, width, height)))
1773     {
1774         IDirect3DRMViewport2_Release(*viewport);
1775         *viewport = NULL;
1776         return D3DRMERR_BADVALUE;
1777     }
1778 
1779     return D3DRM_OK;
1780 }
1781 
1782 static HRESULT WINAPI d3drm3_CreateWrap(IDirect3DRM3 *iface, D3DRMWRAPTYPE type, IDirect3DRMFrame3 *frame,
1783         D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, D3DVALUE dx, D3DVALUE dy, D3DVALUE dz,
1784         D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, D3DVALUE ou, D3DVALUE ov, D3DVALUE su, D3DVALUE sv,
1785         IDirect3DRMWrap **wrap)
1786 {
1787     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1788     struct d3drm_wrap *object;
1789     HRESULT hr;
1790 
1791     FIXME("iface %p, type %#x, frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, "
1792             "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p, semi-stub.\n",
1793             iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz, ou, ov, su, sv, wrap);
1794 
1795     if (!wrap)
1796         return D3DRMERR_BADVALUE;
1797 
1798     if (FAILED(hr = d3drm_wrap_create(&object, &d3drm->IDirect3DRM_iface)))
1799         return hr;
1800 
1801     *wrap = &object->IDirect3DRMWrap_iface;
1802 
1803     return S_OK;
1804 }
1805 
1806 static HRESULT WINAPI d3drm3_CreateUserVisual(IDirect3DRM3 *iface,
1807         D3DRMUSERVISUALCALLBACK cb, void *ctx, IDirect3DRMUserVisual **visual)
1808 {
1809     FIXME("iface %p, cb %p, ctx %p, visual %p stub!\n", iface, cb, ctx, visual);
1810 
1811     return E_NOTIMPL;
1812 }
1813 
1814 static HRESULT WINAPI d3drm3_LoadTexture(IDirect3DRM3 *iface,
1815         const char *filename, IDirect3DRMTexture3 **texture)
1816 {
1817     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1818     struct d3drm_texture *object;
1819     HRESULT hr;
1820 
1821     FIXME("iface %p, filename %s, texture %p stub!\n", iface, debugstr_a(filename), texture);
1822 
1823     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1824         return hr;
1825 
1826     *texture = &object->IDirect3DRMTexture3_iface;
1827 
1828     return D3DRM_OK;
1829 }
1830 
1831 static HRESULT WINAPI d3drm3_LoadTextureFromResource(IDirect3DRM3 *iface, HMODULE module,
1832         const char *resource_name, const char *resource_type, IDirect3DRMTexture3 **texture)
1833 {
1834     struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
1835     struct d3drm_texture *object;
1836     HRESULT hr;
1837 
1838     FIXME("iface %p, module %p, resource_name %s, resource_type %s, texture %p stub!\n",
1839             iface, module, debugstr_a(resource_name), debugstr_a(resource_type), texture);
1840 
1841     if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
1842         return hr;
1843 
1844     *texture = &object->IDirect3DRMTexture3_iface;
1845 
1846     return D3DRM_OK;
1847 }
1848 
1849 static HRESULT WINAPI d3drm3_SetSearchPath(IDirect3DRM3 *iface, const char *path)
1850 {
1851     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
1852 
1853     return E_NOTIMPL;
1854 }
1855 
1856 static HRESULT WINAPI d3drm3_AddSearchPath(IDirect3DRM3 *iface, const char *path)
1857 {
1858     FIXME("iface %p, path %s stub!\n", iface, debugstr_a(path));
1859 
1860     return E_NOTIMPL;
1861 }
1862 
1863 static HRESULT WINAPI d3drm3_GetSearchPath(IDirect3DRM3 *iface, DWORD *size, char *path)
1864 {
1865     FIXME("iface %p, size %p, path %p stub!\n", iface, size, path);
1866 
1867     return E_NOTIMPL;
1868 }
1869 
1870 static HRESULT WINAPI d3drm3_SetDefaultTextureColors(IDirect3DRM3 *iface, DWORD color_count)
1871 {
1872     FIXME("iface %p, color_count %u stub!\n", iface, color_count);
1873 
1874     return E_NOTIMPL;
1875 }
1876 
1877 static HRESULT WINAPI d3drm3_SetDefaultTextureShades(IDirect3DRM3 *iface, DWORD shade_count)
1878 {
1879     FIXME("iface %p, shade_count %u stub!\n", iface, shade_count);
1880 
1881     return E_NOTIMPL;
1882 }
1883 
1884 static HRESULT WINAPI d3drm3_GetDevices(IDirect3DRM3 *iface, IDirect3DRMDeviceArray **array)
1885 {
1886     FIXME("iface %p, array %p stub!\n", iface, array);
1887 
1888     return E_NOTIMPL;
1889 }
1890 
1891 static HRESULT WINAPI d3drm3_GetNamedObject(IDirect3DRM3 *iface,
1892         const char *name, IDirect3DRMObject **object)
1893 {
1894     FIXME("iface %p, name %s, object %p stub!\n", iface, debugstr_a(name), object);
1895 
1896     return E_NOTIMPL;
1897 }
1898 
1899 static HRESULT WINAPI d3drm3_EnumerateObjects(IDirect3DRM3 *iface, D3DRMOBJECTCALLBACK cb, void *ctx)
1900 {
1901     FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
1902 
1903     return E_NOTIMPL;
1904 }
1905 
1906 static HRESULT load_data(IDirect3DRM3 *iface, IDirectXFileData *data_object, IID **GUIDs, DWORD nb_GUIDs, D3DRMLOADCALLBACK LoadProc,
1907                          void *ArgLP, D3DRMLOADTEXTURECALLBACK LoadTextureProc, void *ArgLTP, IDirect3DRMFrame3 *parent_frame)
1908 {
1909     HRESULT ret = D3DRMERR_BADOBJECT;
1910     HRESULT hr;
1911     const GUID* guid;
1912     DWORD i;
1913     BOOL requested = FALSE;
1914 
1915     hr = IDirectXFileData_GetType(data_object, &guid);
1916     if (hr != DXFILE_OK)
1917         goto end;
1918 
1919     TRACE("Found object type whose GUID = %s\n", debugstr_guid(guid));
1920 
1921     /* Load object only if it is top level and requested or if it is part of another object */
1922 
1923     if (IsEqualGUID(guid, &TID_D3DRMMesh))
1924     {
1925         TRACE("Found TID_D3DRMMesh\n");
1926 
1927         for (i = 0; i < nb_GUIDs; i++)
1928             if (IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMeshBuilder) ||
1929                 IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMeshBuilder2) ||
1930                 IsEqualGUID(GUIDs[i], &IID_IDirect3DRMMeshBuilder3))
1931             {
1932                 requested = TRUE;
1933                 break;
1934             }
1935 
1936         if (requested || parent_frame)
1937         {
1938             IDirect3DRMMeshBuilder3 *meshbuilder;
1939 
1940             TRACE("Load mesh data\n");
1941 
1942             hr = IDirect3DRM3_CreateMeshBuilder(iface, &meshbuilder);
1943             if (SUCCEEDED(hr))
1944             {
1945                 hr = load_mesh_data(meshbuilder, data_object, LoadTextureProc, ArgLTP);
1946                 if (SUCCEEDED(hr))
1947                 {
1948                     /* Only top level objects are notified */
1949                     if (!parent_frame)
1950                     {
1951                         IDirect3DRMObject *object;
1952 
1953                         hr = IDirect3DRMMeshBuilder3_QueryInterface(meshbuilder, GUIDs[i], (void**)&object);
1954                         if (SUCCEEDED(hr))
1955                         {
1956                             LoadProc(object, GUIDs[i], ArgLP);
1957                             IDirect3DRMObject_Release(object);
1958                         }
1959                     }
1960                     else
1961                     {
1962                         IDirect3DRMFrame3_AddVisual(parent_frame, (IUnknown*)meshbuilder);
1963                     }
1964                 }
1965                 IDirect3DRMMeshBuilder3_Release(meshbuilder);
1966             }
1967 
1968             if (FAILED(hr))
1969                 ERR("Cannot process mesh\n");
1970         }
1971     }
1972     else if (IsEqualGUID(guid, &TID_D3DRMFrame))
1973     {
1974         TRACE("Found TID_D3DRMFrame\n");
1975 
1976         for (i = 0; i < nb_GUIDs; i++)
1977             if (IsEqualGUID(GUIDs[i], &IID_IDirect3DRMFrame) ||
1978                 IsEqualGUID(GUIDs[i], &IID_IDirect3DRMFrame2) ||
1979                 IsEqualGUID(GUIDs[i], &IID_IDirect3DRMFrame3))
1980             {
1981                 requested = TRUE;
1982                 break;
1983             }
1984 
1985         if (requested || parent_frame)
1986         {
1987             IDirect3DRMFrame3 *frame;
1988 
1989             TRACE("Load frame data\n");
1990 
1991             hr = IDirect3DRM3_CreateFrame(iface, parent_frame, &frame);
1992             if (SUCCEEDED(hr))
1993             {
1994                 IDirectXFileObject *child;
1995 
1996                 while (SUCCEEDED(hr = IDirectXFileData_GetNextObject(data_object, &child)))
1997                 {
1998                     IDirectXFileData *data;
1999                     IDirectXFileDataReference *reference;
2000                     IDirectXFileBinary *binary;
2001 
2002                     if (SUCCEEDED(IDirectXFileObject_QueryInterface(child,
2003                             &IID_IDirectXFileBinary, (void **)&binary)))
2004                     {
2005                         FIXME("Binary Object not supported yet\n");
2006                         IDirectXFileBinary_Release(binary);
2007                     }
2008                     else if (SUCCEEDED(IDirectXFileObject_QueryInterface(child,
2009                             &IID_IDirectXFileData, (void **)&data)))
2010                     {
2011                         TRACE("Found Data Object\n");
2012                         hr = load_data(iface, data, GUIDs, nb_GUIDs, LoadProc, ArgLP, LoadTextureProc, ArgLTP, frame);
2013                         IDirectXFileData_Release(data);
2014                     }
2015                     else if (SUCCEEDED(IDirectXFileObject_QueryInterface(child,
2016                             &IID_IDirectXFileDataReference, (void **)&reference)))
2017                     {
2018                         TRACE("Found Data Object Reference\n");
2019                         IDirectXFileDataReference_Resolve(reference, &data);
2020                         hr = load_data(iface, data, GUIDs, nb_GUIDs, LoadProc, ArgLP, LoadTextureProc, ArgLTP, frame);
2021                         IDirectXFileData_Release(data);
2022                         IDirectXFileDataReference_Release(reference);
2023                     }
2024                     IDirectXFileObject_Release(child);
2025                 }
2026 
2027                 if (hr != DXFILEERR_NOMOREOBJECTS)
2028                 {
2029                     IDirect3DRMFrame3_Release(frame);
2030                     goto end;
2031                 }
2032                 hr = S_OK;
2033 
2034                 /* Only top level objects are notified */
2035                 if (!parent_frame)
2036                 {
2037                     IDirect3DRMObject *object;
2038 
2039                     hr = IDirect3DRMFrame3_QueryInterface(frame, GUIDs[i], (void**)&object);
2040                     if (SUCCEEDED(hr))
2041                     {
2042                         LoadProc(object, GUIDs[i], ArgLP);
2043                         IDirect3DRMObject_Release(object);
2044                     }
2045                 }
2046                 IDirect3DRMFrame3_Release(frame);
2047             }
2048 
2049             if (FAILED(hr))
2050                 ERR("Cannot process frame\n");
2051         }
2052     }
2053     else if (IsEqualGUID(guid, &TID_D3DRMMaterial))
2054     {
2055         TRACE("Found TID_D3DRMMaterial\n");
2056 
2057         /* Cannot be requested so nothing to do */
2058     }
2059     else if (IsEqualGUID(guid, &TID_D3DRMFrameTransformMatrix))
2060     {
2061         TRACE("Found TID_D3DRMFrameTransformMatrix\n");
2062 
2063         /* Cannot be requested */
2064         if (parent_frame)
2065         {
2066             D3DRMMATRIX4D *matrix;
2067             DWORD size;
2068 
2069             TRACE("Load Frame Transform Matrix data\n");
2070 
2071             hr = IDirectXFileData_GetData(data_object, NULL, &size, (void**)&matrix);
2072             if ((hr != DXFILE_OK) || (size != sizeof(matrix)))
2073                 goto end;
2074 
2075             hr = IDirect3DRMFrame3_AddTransform(parent_frame, D3DRMCOMBINE_REPLACE, *matrix);
2076             if (FAILED(hr))
2077                 goto end;
2078         }
2079     }
2080     else
2081     {
2082         FIXME("Found unknown TID %s\n", debugstr_guid(guid));
2083     }
2084 
2085     ret = D3DRM_OK;
2086 
2087 end:
2088 
2089     return ret;
2090 }
2091 
2092 static HRESULT WINAPI d3drm3_Load(IDirect3DRM3 *iface, void *source, void *object_id, IID **iids,
2093         DWORD iid_count, D3DRMLOADOPTIONS flags, D3DRMLOADCALLBACK load_cb, void *load_ctx,
2094         D3DRMLOADTEXTURECALLBACK load_tex_cb, void *load_tex_ctx, IDirect3DRMFrame3 *parent_frame)
2095 {
2096     DXFILELOADOPTIONS load_options;
2097     IDirectXFile *file = NULL;
2098     IDirectXFileEnumObject *enum_object = NULL;
2099     IDirectXFileData *data = NULL;
2100     HRESULT hr;
2101     const GUID* pGuid;
2102     DWORD size;
2103     struct d3drm_file_header *header;
2104     HRESULT ret = D3DRMERR_BADOBJECT;
2105     DWORD i;
2106 
2107     TRACE("iface %p, source %p, object_id %p, iids %p, iid_count %u, flags %#x, "
2108             "load_cb %p, load_ctx %p, load_tex_cb %p, load_tex_ctx %p, parent_frame %p.\n",
2109             iface, source, object_id, iids, iid_count, flags,
2110             load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame);
2111 
2112     TRACE("Looking for GUIDs:\n");
2113     for (i = 0; i < iid_count; ++i)
2114         TRACE("- %s (%s)\n", debugstr_guid(iids[i]), get_IID_string(iids[i]));
2115 
2116     if (flags == D3DRMLOAD_FROMMEMORY)
2117     {
2118         load_options = DXFILELOAD_FROMMEMORY;
2119     }
2120     else if (flags == D3DRMLOAD_FROMFILE)
2121     {
2122         load_options = DXFILELOAD_FROMFILE;
2123         TRACE("Loading from file %s\n", debugstr_a(source));
2124     }
2125     else
2126     {
2127         FIXME("Load options %#x not supported yet.\n", flags);
2128         return E_NOTIMPL;
2129     }
2130 
2131     hr = DirectXFileCreate(&file);
2132     if (hr != DXFILE_OK)
2133         goto end;
2134 
2135     hr = IDirectXFile_RegisterTemplates(file, templates, strlen(templates));
2136     if (hr != DXFILE_OK)
2137         goto end;
2138 
2139     hr = IDirectXFile_CreateEnumObject(file, source, load_options, &enum_object);
2140     if (hr != DXFILE_OK)
2141         goto end;
2142 
2143     hr = IDirectXFileEnumObject_GetNextDataObject(enum_object, &data);
2144     if (hr != DXFILE_OK)
2145         goto end;
2146 
2147     hr = IDirectXFileData_GetType(data, &pGuid);
2148     if (hr != DXFILE_OK)
2149         goto end;
2150 
2151     TRACE("Found object type whose GUID = %s\n", debugstr_guid(pGuid));
2152 
2153     if (!IsEqualGUID(pGuid, &TID_DXFILEHeader))
2154     {
2155         ret = D3DRMERR_BADFILE;
2156         goto end;
2157     }
2158 
2159     hr = IDirectXFileData_GetData(data, NULL, &size, (void **)&header);
2160     if ((hr != DXFILE_OK) || (size != sizeof(*header)))
2161         goto end;
2162 
2163     TRACE("Version is %u.%u, flags %#x.\n", header->major, header->minor, header->flags);
2164 
2165     /* Version must be 1.0.x */
2166     if ((header->major != 1) || (header->minor != 0))
2167     {
2168         ret = D3DRMERR_BADFILE;
2169         goto end;
2170     }
2171 
2172     IDirectXFileData_Release(data);
2173     data = NULL;
2174 
2175     while (1)
2176     {
2177         hr = IDirectXFileEnumObject_GetNextDataObject(enum_object, &data);
2178         if (hr == DXFILEERR_NOMOREOBJECTS)
2179         {
2180             TRACE("No more object\n");
2181             break;
2182         }
2183         else if (hr != DXFILE_OK)
2184         {
2185             ret = D3DRMERR_BADFILE;
2186             goto end;
2187         }
2188 
2189         ret = load_data(iface, data, iids, iid_count, load_cb, load_ctx, load_tex_cb, load_tex_ctx, parent_frame);
2190         if (ret != D3DRM_OK)
2191             goto end;
2192 
2193         IDirectXFileData_Release(data);
2194         data = NULL;
2195     }
2196 
2197     ret = D3DRM_OK;
2198 
2199 end:
2200     if (data)
2201         IDirectXFileData_Release(data);
2202     if (enum_object)
2203         IDirectXFileEnumObject_Release(enum_object);
2204     if (file)
2205         IDirectXFile_Release(file);
2206 
2207     return ret;
2208 }
2209 
2210 static HRESULT WINAPI d3drm3_Tick(IDirect3DRM3 *iface, D3DVALUE tick)
2211 {
2212     FIXME("iface %p, tick %.8e stub!\n", iface, tick);
2213 
2214     return E_NOTIMPL;
2215 }
2216 
2217 static HRESULT WINAPI d3drm3_CreateProgressiveMesh(IDirect3DRM3 *iface, IDirect3DRMProgressiveMesh **mesh)
2218 {
2219     FIXME("iface %p, mesh %p stub!\n", iface, mesh);
2220 
2221     return E_NOTIMPL;
2222 }
2223 
2224 static HRESULT WINAPI d3drm3_RegisterClient(IDirect3DRM3 *iface, REFGUID guid, DWORD *id)
2225 {
2226     FIXME("iface %p, guid %s, id %p stub!\n", iface, debugstr_guid(guid), id);
2227 
2228     return E_NOTIMPL;
2229 }
2230 
2231 static HRESULT WINAPI d3drm3_UnregisterClient(IDirect3DRM3 *iface, REFGUID guid)
2232 {
2233     FIXME("iface %p, guid %s stub!\n", iface, debugstr_guid(guid));
2234 
2235     return E_NOTIMPL;
2236 }
2237 
2238 static HRESULT WINAPI d3drm3_CreateClippedVisual(IDirect3DRM3 *iface,
2239         IDirect3DRMVisual *visual, IDirect3DRMClippedVisual **clipped_visual)
2240 {
2241     FIXME("iface %p, visual %p, clipped_visual %p stub!\n", iface, visual, clipped_visual);
2242 
2243     return E_NOTIMPL;
2244 }
2245 
2246 static HRESULT WINAPI d3drm3_SetOptions(IDirect3DRM3 *iface, DWORD flags)
2247 {
2248     FIXME("iface %p, flags %#x stub!\n", iface, flags);
2249 
2250     return E_NOTIMPL;
2251 }
2252 
2253 static HRESULT WINAPI d3drm3_GetOptions(IDirect3DRM3 *iface, DWORD *flags)
2254 {
2255     FIXME("iface %p, flags %p stub!\n", iface, flags);
2256 
2257     return E_NOTIMPL;
2258 }
2259 
2260 static const struct IDirect3DRM3Vtbl d3drm3_vtbl =
2261 {
2262     d3drm3_QueryInterface,
2263     d3drm3_AddRef,
2264     d3drm3_Release,
2265     d3drm3_CreateObject,
2266     d3drm3_CreateFrame,
2267     d3drm3_CreateMesh,
2268     d3drm3_CreateMeshBuilder,
2269     d3drm3_CreateFace,
2270     d3drm3_CreateAnimation,
2271     d3drm3_CreateAnimationSet,
2272     d3drm3_CreateTexture,
2273     d3drm3_CreateLight,
2274     d3drm3_CreateLightRGB,
2275     d3drm3_CreateMaterial,
2276     d3drm3_CreateDevice,
2277     d3drm3_CreateDeviceFromSurface,
2278     d3drm3_CreateDeviceFromD3D,
2279     d3drm3_CreateDeviceFromClipper,
2280     d3drm3_CreateTextureFromSurface,
2281     d3drm3_CreateShadow,
2282     d3drm3_CreateViewport,
2283     d3drm3_CreateWrap,
2284     d3drm3_CreateUserVisual,
2285     d3drm3_LoadTexture,
2286     d3drm3_LoadTextureFromResource,
2287     d3drm3_SetSearchPath,
2288     d3drm3_AddSearchPath,
2289     d3drm3_GetSearchPath,
2290     d3drm3_SetDefaultTextureColors,
2291     d3drm3_SetDefaultTextureShades,
2292     d3drm3_GetDevices,
2293     d3drm3_GetNamedObject,
2294     d3drm3_EnumerateObjects,
2295     d3drm3_Load,
2296     d3drm3_Tick,
2297     d3drm3_CreateProgressiveMesh,
2298     d3drm3_RegisterClient,
2299     d3drm3_UnregisterClient,
2300     d3drm3_CreateClippedVisual,
2301     d3drm3_SetOptions,
2302     d3drm3_GetOptions,
2303 };
2304 
2305 HRESULT WINAPI Direct3DRMCreate(IDirect3DRM **d3drm)
2306 {
2307     struct d3drm *object;
2308 
2309     TRACE("d3drm %p.\n", d3drm);
2310 
2311     if (!(object = heap_alloc_zero(sizeof(*object))))
2312         return E_OUTOFMEMORY;
2313 
2314     object->IDirect3DRM_iface.lpVtbl = &d3drm1_vtbl;
2315     object->IDirect3DRM2_iface.lpVtbl = &d3drm2_vtbl;
2316     object->IDirect3DRM3_iface.lpVtbl = &d3drm3_vtbl;
2317     object->ref1 = 1;
2318     object->iface_count = 1;
2319 
2320     *d3drm = &object->IDirect3DRM_iface;
2321 
2322     return S_OK;
2323 }
2324 
2325 HRESULT WINAPI DllCanUnloadNow(void)
2326 {
2327     return S_FALSE;
2328 }
2329 
2330 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
2331 {
2332     TRACE("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
2333 
2334     if(!ppv)
2335         return E_INVALIDARG;
2336 
2337     return CLASS_E_CLASSNOTAVAILABLE;
2338 }
2339