[D3DX9_36]
[reactos.git] / reactos / 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 HRESULT ret;
298
299 TRACE("dxfile_object %p, ret_iface %p.\n", dxfile_object, ret_iface);
300
301 *ret_iface = NULL;
302
303 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
304 if (!object)
305 return E_OUTOFMEMORY;
306
307 object->ID3DXFileData_iface.lpVtbl = &d3dx9_file_data_vtbl;
308 object->ref = 1;
309
310 ret = IDirectXFileObject_QueryInterface(dxfile_object, &IID_IDirectXFileData, (void **)&object->dxfile_data);
311 if (FAILED(ret))
312 {
313 IDirectXFileDataReference *reference;
314
315 ret = IDirectXFileObject_QueryInterface(dxfile_object, &IID_IDirectXFileDataReference, (void **)&reference);
316 if (SUCCEEDED(ret))
317 {
318 ret = IDirectXFileDataReference_Resolve(reference, &object->dxfile_data);
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 known 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->children)
337 object->children = HeapReAlloc(GetProcessHeap(), 0, object->children, sizeof(ID3DXFileData*) * (object->nb_children + 1));
338 else
339 object->children = HeapAlloc(GetProcessHeap(), 0, sizeof(ID3DXFileData*));
340 if (!object->children)
341 {
342 ret = E_OUTOFMEMORY;
343 break;
344 }
345 if (FAILED(ret = d3dx9_file_data_create(data_object, &object->children[object->nb_children])))
346 break;
347 object->nb_children++;
348 }
349
350 if (ret != DXFILEERR_NOMOREOBJECTS)
351 {
352 (&object->ID3DXFileData_iface)->lpVtbl->Release(&object->ID3DXFileData_iface);
353 return ret;
354 }
355
356 TRACE("Found %u children\n", object->nb_children);
357
358 *ret_iface = &object->ID3DXFileData_iface;
359
360 return S_OK;
361 }
362
363 static HRESULT WINAPI d3dx9_file_enum_object_QueryInterface(ID3DXFileEnumObject *iface, REFIID riid, void **out)
364 {
365 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
366
367 if (IsEqualGUID(riid, &IID_ID3DXFileEnumObject)
368 || IsEqualGUID(riid, &IID_IUnknown))
369 {
370 iface->lpVtbl->AddRef(iface);
371 *out = iface;
372 return S_OK;
373 }
374
375 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
376
377 *out = NULL;
378 return E_NOINTERFACE;
379 }
380
381 static ULONG WINAPI d3dx9_file_enum_object_AddRef(ID3DXFileEnumObject *iface)
382 {
383 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
384 ULONG refcount = InterlockedIncrement(&file_enum->ref);
385
386 TRACE("%p increasing refcount to %u.\n", file_enum, refcount);
387
388 return refcount;
389 }
390
391 static ULONG WINAPI d3dx9_file_enum_object_Release(ID3DXFileEnumObject *iface)
392 {
393 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
394 ULONG refcount = InterlockedDecrement(&file_enum->ref);
395
396 TRACE("%p decreasing refcount to %u.\n", file_enum, refcount);
397
398 if (!refcount)
399 {
400 ULONG i;
401
402 for (i = 0; i < file_enum->nb_children; ++i)
403 {
404 ID3DXFileData *child = file_enum->children[i];
405 child->lpVtbl->Release(child);
406 }
407 HeapFree(GetProcessHeap(), 0, file_enum->children);
408 HeapFree(GetProcessHeap(), 0, file_enum);
409 }
410
411 return refcount;
412 }
413
414 static HRESULT WINAPI d3dx9_file_enum_object_GetFile(ID3DXFileEnumObject *iface, ID3DXFile **file)
415 {
416 FIXME("iface %p, file %p stub!\n", iface, file);
417
418 return E_NOTIMPL;
419 }
420
421 static HRESULT WINAPI d3dx9_file_enum_object_GetChildren(ID3DXFileEnumObject *iface, SIZE_T *children)
422 {
423 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
424
425 TRACE("iface %p, children %p.\n", iface, children);
426
427 if (!children)
428 return E_POINTER;
429
430 *children = file_enum->nb_children;
431
432 return S_OK;
433 }
434
435 static HRESULT WINAPI d3dx9_file_enum_object_GetChild(ID3DXFileEnumObject *iface, SIZE_T id, ID3DXFileData **object)
436 {
437 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
438
439 TRACE("iface %p, id %#lx, object %p.\n", iface, id, object);
440
441 if (!object)
442 return E_POINTER;
443
444 *object = file_enum->children[id];
445 (*object)->lpVtbl->AddRef(*object);
446
447 return S_OK;
448 }
449
450 static HRESULT WINAPI d3dx9_file_enum_object_GetDataObjectById(ID3DXFileEnumObject *iface,
451 REFGUID guid, ID3DXFileData **object)
452 {
453 FIXME("iface %p, guid %s, object %p stub!\n", iface, debugstr_guid(guid), object);
454
455 return E_NOTIMPL;
456 }
457
458 static HRESULT WINAPI d3dx9_file_enum_object_GetDataObjectByName(ID3DXFileEnumObject *iface,
459 const char *name, ID3DXFileData **object)
460 {
461 FIXME("iface %p, name %s, object %p stub!\n", iface, debugstr_a(name), object);
462
463 return E_NOTIMPL;
464 }
465
466 static const ID3DXFileEnumObjectVtbl d3dx9_file_enum_object_vtbl =
467 {
468 d3dx9_file_enum_object_QueryInterface,
469 d3dx9_file_enum_object_AddRef,
470 d3dx9_file_enum_object_Release,
471 d3dx9_file_enum_object_GetFile,
472 d3dx9_file_enum_object_GetChildren,
473 d3dx9_file_enum_object_GetChild,
474 d3dx9_file_enum_object_GetDataObjectById,
475 d3dx9_file_enum_object_GetDataObjectByName,
476 };
477
478 static HRESULT WINAPI d3dx9_file_QueryInterface(ID3DXFile *iface, REFIID riid, void **out)
479 {
480 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
481
482 if (IsEqualGUID(riid, &IID_ID3DXFile)
483 || IsEqualGUID(riid, &IID_IUnknown))
484 {
485 iface->lpVtbl->AddRef(iface);
486 *out = iface;
487 return S_OK;
488 }
489
490 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
491
492 *out = NULL;
493 return E_NOINTERFACE;
494 }
495
496 static ULONG WINAPI d3dx9_file_AddRef(ID3DXFile *iface)
497 {
498 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
499 ULONG refcount = InterlockedIncrement(&file->ref);
500
501 TRACE("%p increasing refcount to %u.\n", file, refcount);
502
503 return refcount;
504 }
505
506 static ULONG WINAPI d3dx9_file_Release(ID3DXFile *iface)
507 {
508 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
509 ULONG refcount = InterlockedDecrement(&file->ref);
510
511 TRACE("%p decreasing refcount to %u.\n", file, refcount);
512
513 if (!refcount)
514 {
515 IDirectXFile_Release(file->dxfile);
516 HeapFree(GetProcessHeap(), 0, file);
517 }
518
519 return refcount;
520 }
521
522 static HRESULT WINAPI d3dx9_file_CreateEnumObject(ID3DXFile *iface, const void *source,
523 D3DXF_FILELOADOPTIONS options, ID3DXFileEnumObject **enum_object)
524 {
525 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
526 struct d3dx9_file_enum_object *object;
527 IDirectXFileEnumObject *dxfile_enum_object;
528 void *dxfile_source;
529 DXFILELOADOPTIONS dxfile_options;
530 DXFILELOADRESOURCE dxfile_resource;
531 DXFILELOADMEMORY dxfile_memory;
532 IDirectXFileData *data_object;
533 HRESULT ret;
534
535 TRACE("iface %p, source %p, options %#x, enum_object %p.\n", iface, source, options, enum_object);
536
537 if (!enum_object)
538 return E_POINTER;
539
540 *enum_object = NULL;
541
542 if (options == D3DXF_FILELOAD_FROMFILE)
543 {
544 dxfile_source = (void*)source;
545 dxfile_options = DXFILELOAD_FROMFILE;
546 }
547 else if (options == D3DXF_FILELOAD_FROMRESOURCE)
548 {
549 D3DXF_FILELOADRESOURCE *resource = (D3DXF_FILELOADRESOURCE*)source;
550
551 dxfile_resource.hModule = resource->hModule;
552 dxfile_resource.lpName = resource->lpName;
553 dxfile_resource.lpType = resource->lpType;
554 dxfile_source = &dxfile_resource;
555 dxfile_options = DXFILELOAD_FROMRESOURCE;
556 }
557 else if (options == D3DXF_FILELOAD_FROMMEMORY)
558 {
559 D3DXF_FILELOADMEMORY *memory = (D3DXF_FILELOADMEMORY*)source;
560
561 dxfile_memory.lpMemory = memory->lpMemory;
562 dxfile_memory.dSize = memory->dSize;
563 dxfile_source = &dxfile_memory;
564 dxfile_options = DXFILELOAD_FROMMEMORY;
565 }
566 else
567 {
568 FIXME("Source type %u is not handled yet\n", options);
569 return E_NOTIMPL;
570 }
571
572 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
573 if (!object)
574 return E_OUTOFMEMORY;
575
576 object->ID3DXFileEnumObject_iface.lpVtbl = &d3dx9_file_enum_object_vtbl;
577 object->ref = 1;
578
579 ret = IDirectXFile_CreateEnumObject(file->dxfile, dxfile_source, dxfile_options, &dxfile_enum_object);
580
581 if (ret != S_OK)
582 {
583 HeapFree(GetProcessHeap(), 0, object);
584 return ret;
585 }
586
587 /* Fill enum object with top level data objects */
588 while (SUCCEEDED(ret = IDirectXFileEnumObject_GetNextDataObject(dxfile_enum_object, &data_object)))
589 {
590 if (object->children)
591 object->children = HeapReAlloc(GetProcessHeap(), 0, object->children, sizeof(*object->children) * (object->nb_children + 1));
592 else
593 object->children = HeapAlloc(GetProcessHeap(), 0, sizeof(*object->children));
594 if (!object->children)
595 {
596 ret = E_OUTOFMEMORY;
597 break;
598 }
599 if (FAILED(ret = d3dx9_file_data_create((IDirectXFileObject*)data_object,
600 &object->children[object->nb_children])))
601 break;
602 object->nb_children++;
603 }
604
605 IDirectXFileEnumObject_Release(dxfile_enum_object);
606
607 if (ret != DXFILEERR_NOMOREOBJECTS)
608 WARN("Cannot get all top level data objects\n");
609
610 TRACE("Found %u children\n", object->nb_children);
611
612 *enum_object = &object->ID3DXFileEnumObject_iface;
613
614 return S_OK;
615 }
616
617 static HRESULT WINAPI d3dx9_file_CreateSaveObject(ID3DXFile *iface, const void *data,
618 D3DXF_FILESAVEOPTIONS options, D3DXF_FILEFORMAT format, ID3DXFileSaveObject **save_object)
619 {
620 FIXME("iface %p, data %p, options %#x, format %#x, save_object %p stub!\n",
621 iface, data, options, format, save_object);
622
623 return E_NOTIMPL;
624 }
625
626 static HRESULT WINAPI d3dx9_file_RegisterTemplates(ID3DXFile *iface, const void *data, SIZE_T size)
627 {
628 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
629 HRESULT ret;
630
631 TRACE("iface %p, data %p, size %lu.\n", iface, data, size);
632
633 ret = IDirectXFile_RegisterTemplates(file->dxfile, (void *)data, size);
634 if (ret != DXFILE_OK)
635 {
636 WARN("Error %#x\n", ret);
637 return error_dxfile_to_d3dxfile(ret);
638 }
639
640 return S_OK;
641 }
642
643 static HRESULT WINAPI d3dx9_file_RegisterEnumTemplates(ID3DXFile *iface, ID3DXFileEnumObject *enum_object)
644 {
645 FIXME("iface %p, enum_object %p stub!\n", iface, enum_object);
646
647 return E_NOTIMPL;
648 }
649
650 static const ID3DXFileVtbl d3dx9_file_vtbl =
651 {
652 d3dx9_file_QueryInterface,
653 d3dx9_file_AddRef,
654 d3dx9_file_Release,
655 d3dx9_file_CreateEnumObject,
656 d3dx9_file_CreateSaveObject,
657 d3dx9_file_RegisterTemplates,
658 d3dx9_file_RegisterEnumTemplates,
659 };
660
661 HRESULT WINAPI D3DXFileCreate(ID3DXFile **d3dxfile)
662 {
663 struct d3dx9_file *object;
664 HRESULT ret;
665
666 TRACE("d3dxfile %p.\n", d3dxfile);
667
668 if (!d3dxfile)
669 return E_POINTER;
670
671 *d3dxfile = NULL;
672
673 object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
674 if (!object)
675 return E_OUTOFMEMORY;
676
677 ret = DirectXFileCreate(&object->dxfile);
678 if (ret != S_OK)
679 {
680 HeapFree(GetProcessHeap(), 0, object);
681 if (ret == E_OUTOFMEMORY)
682 return ret;
683 return E_FAIL;
684 }
685
686 object->ID3DXFile_iface.lpVtbl = &d3dx9_file_vtbl;
687 object->ref = 1;
688
689 *d3dxfile = &object->ID3DXFile_iface;
690
691 return S_OK;
692 }