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