[D3DX9_*] Sync with Wine Staging 3.3. CORE-14434
[reactos.git] / dll / directx / wine / d3dx9_36 / xfile.c
1 /*
2 * Copyright (C) 2012 Christian Costa
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 *
18 */
19
20 #include "config.h"
21 #include "wine/port.h"
22
23 #include "d3dx9_private.h"
24 #include "d3dx9xof.h"
25 #undef MAKE_DDHRESULT
26 #include "dxfile.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
29
30 static HRESULT error_dxfile_to_d3dxfile(HRESULT error)
31 {
32 switch (error)
33 {
34 case DXFILEERR_BADFILETYPE:
35 return D3DXFERR_BADFILETYPE;
36 case DXFILEERR_BADFILEVERSION:
37 return D3DXFERR_BADFILEVERSION;
38 case DXFILEERR_BADFILEFLOATSIZE:
39 return D3DXFERR_BADFILEFLOATSIZE;
40 case DXFILEERR_PARSEERROR:
41 return D3DXFERR_PARSEERROR;
42 case DXFILEERR_BADVALUE:
43 return D3DXFERR_BADVALUE;
44 default:
45 FIXME("Cannot map error %#x\n", error);
46 return E_FAIL;
47 }
48 }
49
50 struct d3dx9_file
51 {
52 ID3DXFile ID3DXFile_iface;
53 LONG ref;
54 IDirectXFile *dxfile;
55 };
56
57 struct d3dx9_file_enum_object
58 {
59 ID3DXFileEnumObject ID3DXFileEnumObject_iface;
60 LONG ref;
61 ULONG nb_children;
62 ID3DXFileData **children;
63 };
64
65 struct d3dx9_file_data
66 {
67 ID3DXFileData ID3DXFileData_iface;
68 LONG ref;
69 BOOL reference;
70 IDirectXFileData *dxfile_data;
71 ULONG nb_children;
72 ID3DXFileData **children;
73 };
74
75 static inline struct d3dx9_file *impl_from_ID3DXFile(ID3DXFile *iface)
76 {
77 return CONTAINING_RECORD(iface, struct d3dx9_file, ID3DXFile_iface);
78 }
79
80 static inline struct d3dx9_file_enum_object *impl_from_ID3DXFileEnumObject(ID3DXFileEnumObject *iface)
81 {
82 return CONTAINING_RECORD(iface, struct d3dx9_file_enum_object, ID3DXFileEnumObject_iface);
83 }
84
85 static inline struct d3dx9_file_data *impl_from_ID3DXFileData(ID3DXFileData *iface)
86 {
87 return CONTAINING_RECORD(iface, struct d3dx9_file_data, ID3DXFileData_iface);
88 }
89
90 static HRESULT WINAPI d3dx9_file_data_QueryInterface(ID3DXFileData *iface, REFIID riid, void **out)
91 {
92 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
93
94 if (IsEqualGUID(riid, &IID_ID3DXFileData)
95 || IsEqualGUID(riid, &IID_IUnknown))
96 {
97 iface->lpVtbl->AddRef(iface);
98 *out = iface;
99 return S_OK;
100 }
101
102 WARN("Interface %s not found.\n", debugstr_guid(riid));
103
104 *out = NULL;
105 return E_NOINTERFACE;
106 }
107
108 static ULONG WINAPI d3dx9_file_data_AddRef(ID3DXFileData *iface)
109 {
110 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
111 ULONG refcount = InterlockedIncrement(&file_data->ref);
112
113 TRACE("%p increasing refcount to %u.\n", file_data, refcount);
114
115 return refcount;
116 }
117
118 static ULONG WINAPI d3dx9_file_data_Release(ID3DXFileData *iface)
119 {
120 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
121 ULONG refcount = InterlockedDecrement(&file_data->ref);
122
123 TRACE("%p decreasing refcount to %u.\n", file_data, refcount);
124
125 if (!refcount)
126 {
127 ULONG i;
128
129 for (i = 0; i < file_data->nb_children; ++i)
130 {
131 ID3DXFileData *child = file_data->children[i];
132 child->lpVtbl->Release(child);
133 }
134 HeapFree(GetProcessHeap(), 0, file_data->children);
135 IDirectXFileData_Release(file_data->dxfile_data);
136 HeapFree(GetProcessHeap(), 0, file_data);
137 }
138
139 return refcount;
140 }
141
142 static HRESULT WINAPI d3dx9_file_data_GetEnum(ID3DXFileData *iface, ID3DXFileEnumObject **enum_object)
143 {
144 FIXME("iface %p, enum_object %p stub!\n", iface, enum_object);
145
146 return E_NOTIMPL;
147 }
148
149 static HRESULT WINAPI d3dx9_file_data_GetName(ID3DXFileData *iface, char *name, SIZE_T *size)
150 {
151 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
152 DWORD dxfile_size;
153 HRESULT ret;
154
155 TRACE("iface %p, name %p, size %p.\n", iface, name, size);
156
157 if (!size)
158 return D3DXFERR_BADVALUE;
159
160 dxfile_size = *size;
161
162 ret = IDirectXFileData_GetName(file_data->dxfile_data, name, &dxfile_size);
163 if (ret != DXFILE_OK)
164 return error_dxfile_to_d3dxfile(ret);
165
166 if (!dxfile_size)
167 {
168 /* Contrary to d3dxof, d3dx9_36 returns an empty string with a null byte when no name is available.
169 * If the input size is 0, it returns a length of 1 without touching the buffer */
170 dxfile_size = 1;
171 if (name && *size)
172 name[0] = 0;
173 }
174
175 *size = dxfile_size;
176
177 return S_OK;
178 }
179
180 static HRESULT WINAPI d3dx9_file_data_GetId(ID3DXFileData *iface, GUID *guid)
181 {
182 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
183 HRESULT ret;
184
185 TRACE("iface %p, guid %p.\n", iface, guid);
186
187 if (!guid)
188 return E_POINTER;
189
190 ret = IDirectXFileData_GetId(file_data->dxfile_data, guid);
191 if (ret != DXFILE_OK)
192 return error_dxfile_to_d3dxfile(ret);
193
194 return S_OK;
195 }
196
197 static HRESULT WINAPI d3dx9_file_data_Lock(ID3DXFileData *iface, SIZE_T *size, const void **data)
198 {
199 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
200 DWORD dxfile_size;
201 HRESULT ret;
202
203 TRACE("iface %p, size %p, data %p.\n", iface, size, data);
204
205 if (!size || !data)
206 return E_POINTER;
207
208 ret = IDirectXFileData_GetData(file_data->dxfile_data, NULL, &dxfile_size, (void **)data);
209 if (ret != DXFILE_OK)
210 return error_dxfile_to_d3dxfile(ret);
211
212 *size = dxfile_size;
213
214 return S_OK;
215 }
216
217 static HRESULT WINAPI d3dx9_file_data_Unlock(ID3DXFileData *iface)
218 {
219 TRACE("iface %p.\n", iface);
220
221 /* Nothing to do */
222
223 return S_OK;
224 }
225
226 static HRESULT WINAPI d3dx9_file_data_GetType(ID3DXFileData *iface, GUID *guid)
227 {
228 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
229 const GUID *dxfile_guid;
230 HRESULT ret;
231
232 TRACE("iface %p, guid %p.\n", iface, guid);
233
234 ret = IDirectXFileData_GetType(file_data->dxfile_data, &dxfile_guid);
235 if (ret != DXFILE_OK)
236 return error_dxfile_to_d3dxfile(ret);
237
238 *guid = *dxfile_guid;
239
240 return S_OK;
241 }
242
243 static BOOL WINAPI d3dx9_file_data_IsReference(ID3DXFileData *iface)
244 {
245 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
246
247 TRACE("iface %p.\n", iface);
248
249 return file_data->reference;
250 }
251
252 static HRESULT WINAPI d3dx9_file_data_GetChildren(ID3DXFileData *iface, SIZE_T *children)
253 {
254 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
255
256 TRACE("iface %p, children %p.\n", iface, children);
257
258 if (!children)
259 return E_POINTER;
260
261 *children = file_data->nb_children;
262
263 return S_OK;
264 }
265
266 static HRESULT WINAPI d3dx9_file_data_GetChild(ID3DXFileData *iface, SIZE_T id, ID3DXFileData **object)
267 {
268 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
269
270 TRACE("iface %p, id %#lx, object %p.\n", iface, id, object);
271
272 if (!object)
273 return E_POINTER;
274
275 *object = file_data->children[id];
276 (*object)->lpVtbl->AddRef(*object);
277
278 return S_OK;
279 }
280
281 static const ID3DXFileDataVtbl d3dx9_file_data_vtbl =
282 {
283 d3dx9_file_data_QueryInterface,
284 d3dx9_file_data_AddRef,
285 d3dx9_file_data_Release,
286 d3dx9_file_data_GetEnum,
287 d3dx9_file_data_GetName,
288 d3dx9_file_data_GetId,
289 d3dx9_file_data_Lock,
290 d3dx9_file_data_Unlock,
291 d3dx9_file_data_GetType,
292 d3dx9_file_data_IsReference,
293 d3dx9_file_data_GetChildren,
294 d3dx9_file_data_GetChild,
295 };
296
297 static HRESULT d3dx9_file_data_create(IDirectXFileObject *dxfile_object, ID3DXFileData **ret_iface)
298 {
299 struct d3dx9_file_data *object;
300 IDirectXFileObject *data_object;
301 unsigned int children_array_size = 0;
302 HRESULT ret;
303
304 TRACE("dxfile_object %p, ret_iface %p.\n", dxfile_object, ret_iface);
305
306 *ret_iface = NULL;
307
308 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
309 if (!object)
310 return E_OUTOFMEMORY;
311
312 object->ID3DXFileData_iface.lpVtbl = &d3dx9_file_data_vtbl;
313 object->ref = 1;
314
315 ret = IDirectXFileObject_QueryInterface(dxfile_object, &IID_IDirectXFileData, (void **)&object->dxfile_data);
316 if (FAILED(ret))
317 {
318 IDirectXFileDataReference *reference;
319
320 ret = IDirectXFileObject_QueryInterface(dxfile_object, &IID_IDirectXFileDataReference, (void **)&reference);
321 if (SUCCEEDED(ret))
322 {
323 ret = IDirectXFileDataReference_Resolve(reference, &object->dxfile_data);
324 IUnknown_Release(reference);
325 if (FAILED(ret))
326 {
327 HeapFree(GetProcessHeap(), 0, object);
328 return E_FAIL;
329 }
330 object->reference = TRUE;
331 }
332 else
333 {
334 FIXME("Don't know what to do with binary object\n");
335 HeapFree(GetProcessHeap(), 0, object);
336 return E_FAIL;
337 }
338 }
339
340 while (SUCCEEDED(ret = IDirectXFileData_GetNextObject(object->dxfile_data, &data_object)))
341 {
342 if (object->nb_children >= children_array_size)
343 {
344 ID3DXFileData **new_children;
345
346 if (object->children)
347 {
348 children_array_size *= 2;
349 new_children = HeapReAlloc(GetProcessHeap(), 0, object->children,
350 sizeof(*object->children) * children_array_size);
351 }
352 else
353 {
354 children_array_size = 4;
355 new_children = HeapAlloc(GetProcessHeap(), 0, sizeof(*object->children) * children_array_size);
356 }
357 if (!new_children)
358 {
359 ret = E_OUTOFMEMORY;
360 break;
361 }
362 object->children = new_children;
363 }
364 ret = d3dx9_file_data_create(data_object, &object->children[object->nb_children]);
365 IUnknown_Release(data_object);
366 if (FAILED(ret))
367 break;
368 object->nb_children++;
369 }
370 if (ret != DXFILEERR_NOMOREOBJECTS)
371 {
372 (&object->ID3DXFileData_iface)->lpVtbl->Release(&object->ID3DXFileData_iface);
373 return ret;
374 }
375 if (object->children)
376 {
377 ID3DXFileData **new_children;
378
379 new_children = HeapReAlloc(GetProcessHeap(), 0, object->children,
380 sizeof(*object->children) * object->nb_children);
381 if (new_children)
382 object->children = new_children;
383 }
384
385 TRACE("Found %u children\n", object->nb_children);
386
387 *ret_iface = &object->ID3DXFileData_iface;
388
389 return S_OK;
390 }
391
392 static HRESULT WINAPI d3dx9_file_enum_object_QueryInterface(ID3DXFileEnumObject *iface, REFIID riid, void **out)
393 {
394 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
395
396 if (IsEqualGUID(riid, &IID_ID3DXFileEnumObject)
397 || IsEqualGUID(riid, &IID_IUnknown))
398 {
399 iface->lpVtbl->AddRef(iface);
400 *out = iface;
401 return S_OK;
402 }
403
404 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
405
406 *out = NULL;
407 return E_NOINTERFACE;
408 }
409
410 static ULONG WINAPI d3dx9_file_enum_object_AddRef(ID3DXFileEnumObject *iface)
411 {
412 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
413 ULONG refcount = InterlockedIncrement(&file_enum->ref);
414
415 TRACE("%p increasing refcount to %u.\n", file_enum, refcount);
416
417 return refcount;
418 }
419
420 static ULONG WINAPI d3dx9_file_enum_object_Release(ID3DXFileEnumObject *iface)
421 {
422 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
423 ULONG refcount = InterlockedDecrement(&file_enum->ref);
424
425 TRACE("%p decreasing refcount to %u.\n", file_enum, refcount);
426
427 if (!refcount)
428 {
429 ULONG i;
430
431 for (i = 0; i < file_enum->nb_children; ++i)
432 {
433 ID3DXFileData *child = file_enum->children[i];
434 child->lpVtbl->Release(child);
435 }
436 HeapFree(GetProcessHeap(), 0, file_enum->children);
437 HeapFree(GetProcessHeap(), 0, file_enum);
438 }
439
440 return refcount;
441 }
442
443 static HRESULT WINAPI d3dx9_file_enum_object_GetFile(ID3DXFileEnumObject *iface, ID3DXFile **file)
444 {
445 FIXME("iface %p, file %p stub!\n", iface, file);
446
447 return E_NOTIMPL;
448 }
449
450 static HRESULT WINAPI d3dx9_file_enum_object_GetChildren(ID3DXFileEnumObject *iface, SIZE_T *children)
451 {
452 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
453
454 TRACE("iface %p, children %p.\n", iface, children);
455
456 if (!children)
457 return E_POINTER;
458
459 *children = file_enum->nb_children;
460
461 return S_OK;
462 }
463
464 static HRESULT WINAPI d3dx9_file_enum_object_GetChild(ID3DXFileEnumObject *iface, SIZE_T id, ID3DXFileData **object)
465 {
466 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
467
468 TRACE("iface %p, id %#lx, object %p.\n", iface, id, object);
469
470 if (!object)
471 return E_POINTER;
472
473 *object = file_enum->children[id];
474 (*object)->lpVtbl->AddRef(*object);
475
476 return S_OK;
477 }
478
479 static HRESULT WINAPI d3dx9_file_enum_object_GetDataObjectById(ID3DXFileEnumObject *iface,
480 REFGUID guid, ID3DXFileData **object)
481 {
482 FIXME("iface %p, guid %s, object %p stub!\n", iface, debugstr_guid(guid), object);
483
484 return E_NOTIMPL;
485 }
486
487 static HRESULT WINAPI d3dx9_file_enum_object_GetDataObjectByName(ID3DXFileEnumObject *iface,
488 const char *name, ID3DXFileData **object)
489 {
490 FIXME("iface %p, name %s, object %p stub!\n", iface, debugstr_a(name), object);
491
492 return E_NOTIMPL;
493 }
494
495 static const ID3DXFileEnumObjectVtbl d3dx9_file_enum_object_vtbl =
496 {
497 d3dx9_file_enum_object_QueryInterface,
498 d3dx9_file_enum_object_AddRef,
499 d3dx9_file_enum_object_Release,
500 d3dx9_file_enum_object_GetFile,
501 d3dx9_file_enum_object_GetChildren,
502 d3dx9_file_enum_object_GetChild,
503 d3dx9_file_enum_object_GetDataObjectById,
504 d3dx9_file_enum_object_GetDataObjectByName,
505 };
506
507 static HRESULT WINAPI d3dx9_file_QueryInterface(ID3DXFile *iface, REFIID riid, void **out)
508 {
509 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
510
511 if (IsEqualGUID(riid, &IID_ID3DXFile)
512 || IsEqualGUID(riid, &IID_IUnknown))
513 {
514 iface->lpVtbl->AddRef(iface);
515 *out = iface;
516 return S_OK;
517 }
518
519 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
520
521 *out = NULL;
522 return E_NOINTERFACE;
523 }
524
525 static ULONG WINAPI d3dx9_file_AddRef(ID3DXFile *iface)
526 {
527 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
528 ULONG refcount = InterlockedIncrement(&file->ref);
529
530 TRACE("%p increasing refcount to %u.\n", file, refcount);
531
532 return refcount;
533 }
534
535 static ULONG WINAPI d3dx9_file_Release(ID3DXFile *iface)
536 {
537 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
538 ULONG refcount = InterlockedDecrement(&file->ref);
539
540 TRACE("%p decreasing refcount to %u.\n", file, refcount);
541
542 if (!refcount)
543 {
544 IDirectXFile_Release(file->dxfile);
545 HeapFree(GetProcessHeap(), 0, file);
546 }
547
548 return refcount;
549 }
550
551 static HRESULT WINAPI d3dx9_file_CreateEnumObject(ID3DXFile *iface, const void *source,
552 D3DXF_FILELOADOPTIONS options, ID3DXFileEnumObject **enum_object)
553 {
554 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
555 struct d3dx9_file_enum_object *object;
556 IDirectXFileEnumObject *dxfile_enum_object;
557 void *dxfile_source;
558 DXFILELOADOPTIONS dxfile_options;
559 DXFILELOADRESOURCE dxfile_resource;
560 DXFILELOADMEMORY dxfile_memory;
561 IDirectXFileData *data_object;
562 unsigned children_array_size = 0;
563 HRESULT ret;
564
565 TRACE("iface %p, source %p, options %#x, enum_object %p.\n", iface, source, options, enum_object);
566
567 if (!enum_object)
568 return E_POINTER;
569
570 *enum_object = NULL;
571
572 if (options == D3DXF_FILELOAD_FROMFILE)
573 {
574 dxfile_source = (void*)source;
575 dxfile_options = DXFILELOAD_FROMFILE;
576 }
577 else if (options == D3DXF_FILELOAD_FROMRESOURCE)
578 {
579 D3DXF_FILELOADRESOURCE *resource = (D3DXF_FILELOADRESOURCE*)source;
580
581 dxfile_resource.hModule = resource->hModule;
582 dxfile_resource.lpName = resource->lpName;
583 dxfile_resource.lpType = resource->lpType;
584 dxfile_source = &dxfile_resource;
585 dxfile_options = DXFILELOAD_FROMRESOURCE;
586 }
587 else if (options == D3DXF_FILELOAD_FROMMEMORY)
588 {
589 D3DXF_FILELOADMEMORY *memory = (D3DXF_FILELOADMEMORY*)source;
590
591 dxfile_memory.lpMemory = memory->lpMemory;
592 dxfile_memory.dSize = memory->dSize;
593 dxfile_source = &dxfile_memory;
594 dxfile_options = DXFILELOAD_FROMMEMORY;
595 }
596 else
597 {
598 FIXME("Source type %u is not handled yet\n", options);
599 return E_NOTIMPL;
600 }
601
602 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
603 if (!object)
604 return E_OUTOFMEMORY;
605
606 object->ID3DXFileEnumObject_iface.lpVtbl = &d3dx9_file_enum_object_vtbl;
607 object->ref = 1;
608
609 ret = IDirectXFile_CreateEnumObject(file->dxfile, dxfile_source, dxfile_options, &dxfile_enum_object);
610
611 if (ret != S_OK)
612 {
613 HeapFree(GetProcessHeap(), 0, object);
614 return ret;
615 }
616
617 /* Fill enum object with top level data objects */
618 while (SUCCEEDED(ret = IDirectXFileEnumObject_GetNextDataObject(dxfile_enum_object, &data_object)))
619 {
620 if (object->nb_children >= children_array_size)
621 {
622 ID3DXFileData **new_children;
623
624 if (object->children)
625 {
626 children_array_size *= 2;
627 new_children = HeapReAlloc(GetProcessHeap(), 0, object->children,
628 sizeof(*object->children) * children_array_size);
629 }
630 else
631 {
632 children_array_size = 4;
633 new_children = HeapAlloc(GetProcessHeap(), 0, sizeof(*object->children) * children_array_size);
634 }
635 if (!new_children)
636 {
637 ret = E_OUTOFMEMORY;
638 break;
639 }
640 object->children = new_children;
641 }
642 ret = d3dx9_file_data_create((IDirectXFileObject*)data_object,
643 &object->children[object->nb_children]);
644 IUnknown_Release(data_object);
645 if (FAILED(ret))
646 break;
647 object->nb_children++;
648 }
649 if (object->children)
650 {
651 ID3DXFileData **new_children;
652
653 new_children = HeapReAlloc(GetProcessHeap(), 0, object->children,
654 sizeof(*object->children) * object->nb_children);
655 if (new_children)
656 object->children = new_children;
657 }
658
659 IDirectXFileEnumObject_Release(dxfile_enum_object);
660
661 if (ret != DXFILEERR_NOMOREOBJECTS)
662 WARN("Cannot get all top level data objects\n");
663
664 TRACE("Found %u children\n", object->nb_children);
665
666 *enum_object = &object->ID3DXFileEnumObject_iface;
667
668 return S_OK;
669 }
670
671 static HRESULT WINAPI d3dx9_file_CreateSaveObject(ID3DXFile *iface, const void *data,
672 D3DXF_FILESAVEOPTIONS options, D3DXF_FILEFORMAT format, ID3DXFileSaveObject **save_object)
673 {
674 FIXME("iface %p, data %p, options %#x, format %#x, save_object %p stub!\n",
675 iface, data, options, format, save_object);
676
677 return E_NOTIMPL;
678 }
679
680 static HRESULT WINAPI d3dx9_file_RegisterTemplates(ID3DXFile *iface, const void *data, SIZE_T size)
681 {
682 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
683 HRESULT ret;
684
685 TRACE("iface %p, data %p, size %lu.\n", iface, data, size);
686
687 ret = IDirectXFile_RegisterTemplates(file->dxfile, (void *)data, size);
688 if (ret != DXFILE_OK)
689 {
690 WARN("Error %#x\n", ret);
691 return error_dxfile_to_d3dxfile(ret);
692 }
693
694 return S_OK;
695 }
696
697 static HRESULT WINAPI d3dx9_file_RegisterEnumTemplates(ID3DXFile *iface, ID3DXFileEnumObject *enum_object)
698 {
699 FIXME("iface %p, enum_object %p stub!\n", iface, enum_object);
700
701 return E_NOTIMPL;
702 }
703
704 static const ID3DXFileVtbl d3dx9_file_vtbl =
705 {
706 d3dx9_file_QueryInterface,
707 d3dx9_file_AddRef,
708 d3dx9_file_Release,
709 d3dx9_file_CreateEnumObject,
710 d3dx9_file_CreateSaveObject,
711 d3dx9_file_RegisterTemplates,
712 d3dx9_file_RegisterEnumTemplates,
713 };
714
715 HRESULT WINAPI D3DXFileCreate(ID3DXFile **d3dxfile)
716 {
717 struct d3dx9_file *object;
718 HRESULT ret;
719
720 TRACE("d3dxfile %p.\n", d3dxfile);
721
722 if (!d3dxfile)
723 return E_POINTER;
724
725 *d3dxfile = NULL;
726
727 object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
728 if (!object)
729 return E_OUTOFMEMORY;
730
731 ret = DirectXFileCreate(&object->dxfile);
732 if (ret != S_OK)
733 {
734 HeapFree(GetProcessHeap(), 0, object);
735 if (ret == E_OUTOFMEMORY)
736 return ret;
737 return E_FAIL;
738 }
739
740 object->ID3DXFile_iface.lpVtbl = &d3dx9_file_vtbl;
741 object->ref = 1;
742
743 *d3dxfile = &object->ID3DXFile_iface;
744
745 return S_OK;
746 }