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