mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / d3dx9_36 / xfile.c
blob4f7d3eefd6099332fe1a13d619c95420cd0cefcd
1 /*
2 * Copyright (C) 2012 Christian Costa
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.
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.
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
21 #include "d3dx9_private.h"
22 #include "d3dx9xof.h"
23 #undef MAKE_DDHRESULT
24 #include "dxfile.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
28 static HRESULT error_dxfile_to_d3dxfile(HRESULT error)
30 switch (error)
32 case DXFILEERR_BADFILETYPE:
33 return D3DXFERR_BADFILETYPE;
34 case DXFILEERR_BADFILEVERSION:
35 return D3DXFERR_BADFILEVERSION;
36 case DXFILEERR_BADFILEFLOATSIZE:
37 return D3DXFERR_BADFILEFLOATSIZE;
38 case DXFILEERR_PARSEERROR:
39 return D3DXFERR_PARSEERROR;
40 case DXFILEERR_BADVALUE:
41 return D3DXFERR_BADVALUE;
42 default:
43 FIXME("Cannot map error %#x\n", error);
44 return E_FAIL;
48 struct d3dx9_file
50 ID3DXFile ID3DXFile_iface;
51 LONG ref;
52 IDirectXFile *dxfile;
55 struct d3dx9_file_enum_object
57 ID3DXFileEnumObject ID3DXFileEnumObject_iface;
58 LONG ref;
59 ULONG nb_children;
60 ID3DXFileData **children;
63 struct d3dx9_file_data
65 ID3DXFileData ID3DXFileData_iface;
66 LONG ref;
67 BOOL reference;
68 IDirectXFileData *dxfile_data;
69 ULONG nb_children;
70 ID3DXFileData **children;
73 static inline struct d3dx9_file *impl_from_ID3DXFile(ID3DXFile *iface)
75 return CONTAINING_RECORD(iface, struct d3dx9_file, ID3DXFile_iface);
78 static inline struct d3dx9_file_enum_object *impl_from_ID3DXFileEnumObject(ID3DXFileEnumObject *iface)
80 return CONTAINING_RECORD(iface, struct d3dx9_file_enum_object, ID3DXFileEnumObject_iface);
83 static inline struct d3dx9_file_data *impl_from_ID3DXFileData(ID3DXFileData *iface)
85 return CONTAINING_RECORD(iface, struct d3dx9_file_data, ID3DXFileData_iface);
88 static HRESULT WINAPI d3dx9_file_data_QueryInterface(ID3DXFileData *iface, REFIID riid, void **out)
90 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
92 if (IsEqualGUID(riid, &IID_ID3DXFileData)
93 || IsEqualGUID(riid, &IID_IUnknown))
95 iface->lpVtbl->AddRef(iface);
96 *out = iface;
97 return S_OK;
100 WARN("Interface %s not found.\n", debugstr_guid(riid));
102 *out = NULL;
103 return E_NOINTERFACE;
106 static ULONG WINAPI d3dx9_file_data_AddRef(ID3DXFileData *iface)
108 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
109 ULONG refcount = InterlockedIncrement(&file_data->ref);
111 TRACE("%p increasing refcount to %u.\n", file_data, refcount);
113 return refcount;
116 static ULONG WINAPI d3dx9_file_data_Release(ID3DXFileData *iface)
118 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
119 ULONG refcount = InterlockedDecrement(&file_data->ref);
121 TRACE("%p decreasing refcount to %u.\n", file_data, refcount);
123 if (!refcount)
125 ULONG i;
127 for (i = 0; i < file_data->nb_children; ++i)
129 ID3DXFileData *child = file_data->children[i];
130 child->lpVtbl->Release(child);
132 HeapFree(GetProcessHeap(), 0, file_data->children);
133 IDirectXFileData_Release(file_data->dxfile_data);
134 HeapFree(GetProcessHeap(), 0, file_data);
137 return refcount;
140 static HRESULT WINAPI d3dx9_file_data_GetEnum(ID3DXFileData *iface, ID3DXFileEnumObject **enum_object)
142 FIXME("iface %p, enum_object %p stub!\n", iface, enum_object);
144 return E_NOTIMPL;
147 static HRESULT WINAPI d3dx9_file_data_GetName(ID3DXFileData *iface, char *name, SIZE_T *size)
149 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
150 DWORD dxfile_size;
151 HRESULT ret;
153 TRACE("iface %p, name %p, size %p.\n", iface, name, size);
155 if (!size)
156 return D3DXFERR_BADVALUE;
158 dxfile_size = *size;
160 ret = IDirectXFileData_GetName(file_data->dxfile_data, name, &dxfile_size);
161 if (ret != DXFILE_OK)
162 return error_dxfile_to_d3dxfile(ret);
164 if (!dxfile_size)
166 /* Contrary to d3dxof, d3dx9_36 returns an empty string with a null byte when no name is available.
167 * If the input size is 0, it returns a length of 1 without touching the buffer */
168 dxfile_size = 1;
169 if (name && *size)
170 name[0] = 0;
173 *size = dxfile_size;
175 return S_OK;
178 static HRESULT WINAPI d3dx9_file_data_GetId(ID3DXFileData *iface, GUID *guid)
180 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
181 HRESULT ret;
183 TRACE("iface %p, guid %p.\n", iface, guid);
185 if (!guid)
186 return E_POINTER;
188 ret = IDirectXFileData_GetId(file_data->dxfile_data, guid);
189 if (ret != DXFILE_OK)
190 return error_dxfile_to_d3dxfile(ret);
192 return S_OK;
195 static HRESULT WINAPI d3dx9_file_data_Lock(ID3DXFileData *iface, SIZE_T *size, const void **data)
197 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
198 DWORD dxfile_size;
199 HRESULT ret;
201 TRACE("iface %p, size %p, data %p.\n", iface, size, data);
203 if (!size || !data)
204 return E_POINTER;
206 ret = IDirectXFileData_GetData(file_data->dxfile_data, NULL, &dxfile_size, (void **)data);
207 if (ret != DXFILE_OK)
208 return error_dxfile_to_d3dxfile(ret);
210 *size = dxfile_size;
212 return S_OK;
215 static HRESULT WINAPI d3dx9_file_data_Unlock(ID3DXFileData *iface)
217 TRACE("iface %p.\n", iface);
219 /* Nothing to do */
221 return S_OK;
224 static HRESULT WINAPI d3dx9_file_data_GetType(ID3DXFileData *iface, GUID *guid)
226 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
227 const GUID *dxfile_guid;
228 HRESULT ret;
230 TRACE("iface %p, guid %p.\n", iface, guid);
232 ret = IDirectXFileData_GetType(file_data->dxfile_data, &dxfile_guid);
233 if (ret != DXFILE_OK)
234 return error_dxfile_to_d3dxfile(ret);
236 *guid = *dxfile_guid;
238 return S_OK;
241 static BOOL WINAPI d3dx9_file_data_IsReference(ID3DXFileData *iface)
243 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
245 TRACE("iface %p.\n", iface);
247 return file_data->reference;
250 static HRESULT WINAPI d3dx9_file_data_GetChildren(ID3DXFileData *iface, SIZE_T *children)
252 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
254 TRACE("iface %p, children %p.\n", iface, children);
256 if (!children)
257 return E_POINTER;
259 *children = file_data->nb_children;
261 return S_OK;
264 static HRESULT WINAPI d3dx9_file_data_GetChild(ID3DXFileData *iface, SIZE_T id, ID3DXFileData **object)
266 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
268 TRACE("iface %p, id %#lx, object %p.\n", iface, id, object);
270 if (!object)
271 return E_POINTER;
273 *object = file_data->children[id];
274 (*object)->lpVtbl->AddRef(*object);
276 return S_OK;
279 static const ID3DXFileDataVtbl d3dx9_file_data_vtbl =
281 d3dx9_file_data_QueryInterface,
282 d3dx9_file_data_AddRef,
283 d3dx9_file_data_Release,
284 d3dx9_file_data_GetEnum,
285 d3dx9_file_data_GetName,
286 d3dx9_file_data_GetId,
287 d3dx9_file_data_Lock,
288 d3dx9_file_data_Unlock,
289 d3dx9_file_data_GetType,
290 d3dx9_file_data_IsReference,
291 d3dx9_file_data_GetChildren,
292 d3dx9_file_data_GetChild,
295 static HRESULT d3dx9_file_data_create(IDirectXFileObject *dxfile_object, ID3DXFileData **ret_iface)
297 struct d3dx9_file_data *object;
298 IDirectXFileObject *data_object;
299 unsigned int children_array_size = 0;
300 HRESULT ret;
302 TRACE("dxfile_object %p, ret_iface %p.\n", dxfile_object, ret_iface);
304 *ret_iface = NULL;
306 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
307 if (!object)
308 return E_OUTOFMEMORY;
310 object->ID3DXFileData_iface.lpVtbl = &d3dx9_file_data_vtbl;
311 object->ref = 1;
313 ret = IDirectXFileObject_QueryInterface(dxfile_object, &IID_IDirectXFileData, (void **)&object->dxfile_data);
314 if (FAILED(ret))
316 IDirectXFileDataReference *reference;
318 ret = IDirectXFileObject_QueryInterface(dxfile_object, &IID_IDirectXFileDataReference, (void **)&reference);
319 if (SUCCEEDED(ret))
321 ret = IDirectXFileDataReference_Resolve(reference, &object->dxfile_data);
322 IUnknown_Release(reference);
323 if (FAILED(ret))
325 HeapFree(GetProcessHeap(), 0, object);
326 return E_FAIL;
328 object->reference = TRUE;
330 else
332 FIXME("Don't know what to do with binary object\n");
333 HeapFree(GetProcessHeap(), 0, object);
334 return E_FAIL;
338 while (SUCCEEDED(ret = IDirectXFileData_GetNextObject(object->dxfile_data, &data_object)))
340 if (object->nb_children >= children_array_size)
342 ID3DXFileData **new_children;
344 if (object->children)
346 children_array_size *= 2;
347 new_children = HeapReAlloc(GetProcessHeap(), 0, object->children,
348 sizeof(*object->children) * children_array_size);
350 else
352 children_array_size = 4;
353 new_children = HeapAlloc(GetProcessHeap(), 0, sizeof(*object->children) * children_array_size);
355 if (!new_children)
357 ret = E_OUTOFMEMORY;
358 break;
360 object->children = new_children;
362 ret = d3dx9_file_data_create(data_object, &object->children[object->nb_children]);
363 IUnknown_Release(data_object);
364 if (FAILED(ret))
365 break;
366 object->nb_children++;
368 if (ret != DXFILEERR_NOMOREOBJECTS)
370 (&object->ID3DXFileData_iface)->lpVtbl->Release(&object->ID3DXFileData_iface);
371 return ret;
373 if (object->children)
375 ID3DXFileData **new_children;
377 new_children = HeapReAlloc(GetProcessHeap(), 0, object->children,
378 sizeof(*object->children) * object->nb_children);
379 if (new_children)
380 object->children = new_children;
383 TRACE("Found %u children\n", object->nb_children);
385 *ret_iface = &object->ID3DXFileData_iface;
387 return S_OK;
390 static HRESULT WINAPI d3dx9_file_enum_object_QueryInterface(ID3DXFileEnumObject *iface, REFIID riid, void **out)
392 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
394 if (IsEqualGUID(riid, &IID_ID3DXFileEnumObject)
395 || IsEqualGUID(riid, &IID_IUnknown))
397 iface->lpVtbl->AddRef(iface);
398 *out = iface;
399 return S_OK;
402 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
404 *out = NULL;
405 return E_NOINTERFACE;
408 static ULONG WINAPI d3dx9_file_enum_object_AddRef(ID3DXFileEnumObject *iface)
410 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
411 ULONG refcount = InterlockedIncrement(&file_enum->ref);
413 TRACE("%p increasing refcount to %u.\n", file_enum, refcount);
415 return refcount;
418 static ULONG WINAPI d3dx9_file_enum_object_Release(ID3DXFileEnumObject *iface)
420 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
421 ULONG refcount = InterlockedDecrement(&file_enum->ref);
423 TRACE("%p decreasing refcount to %u.\n", file_enum, refcount);
425 if (!refcount)
427 ULONG i;
429 for (i = 0; i < file_enum->nb_children; ++i)
431 ID3DXFileData *child = file_enum->children[i];
432 child->lpVtbl->Release(child);
434 HeapFree(GetProcessHeap(), 0, file_enum->children);
435 HeapFree(GetProcessHeap(), 0, file_enum);
438 return refcount;
441 static HRESULT WINAPI d3dx9_file_enum_object_GetFile(ID3DXFileEnumObject *iface, ID3DXFile **file)
443 FIXME("iface %p, file %p stub!\n", iface, file);
445 return E_NOTIMPL;
448 static HRESULT WINAPI d3dx9_file_enum_object_GetChildren(ID3DXFileEnumObject *iface, SIZE_T *children)
450 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
452 TRACE("iface %p, children %p.\n", iface, children);
454 if (!children)
455 return E_POINTER;
457 *children = file_enum->nb_children;
459 return S_OK;
462 static HRESULT WINAPI d3dx9_file_enum_object_GetChild(ID3DXFileEnumObject *iface, SIZE_T id, ID3DXFileData **object)
464 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
466 TRACE("iface %p, id %#lx, object %p.\n", iface, id, object);
468 if (!object)
469 return E_POINTER;
471 *object = file_enum->children[id];
472 (*object)->lpVtbl->AddRef(*object);
474 return S_OK;
477 static HRESULT WINAPI d3dx9_file_enum_object_GetDataObjectById(ID3DXFileEnumObject *iface,
478 REFGUID guid, ID3DXFileData **object)
480 FIXME("iface %p, guid %s, object %p stub!\n", iface, debugstr_guid(guid), object);
482 return E_NOTIMPL;
485 static HRESULT WINAPI d3dx9_file_enum_object_GetDataObjectByName(ID3DXFileEnumObject *iface,
486 const char *name, ID3DXFileData **object)
488 FIXME("iface %p, name %s, object %p stub!\n", iface, debugstr_a(name), object);
490 return E_NOTIMPL;
493 static const ID3DXFileEnumObjectVtbl d3dx9_file_enum_object_vtbl =
495 d3dx9_file_enum_object_QueryInterface,
496 d3dx9_file_enum_object_AddRef,
497 d3dx9_file_enum_object_Release,
498 d3dx9_file_enum_object_GetFile,
499 d3dx9_file_enum_object_GetChildren,
500 d3dx9_file_enum_object_GetChild,
501 d3dx9_file_enum_object_GetDataObjectById,
502 d3dx9_file_enum_object_GetDataObjectByName,
505 static HRESULT WINAPI d3dx9_file_QueryInterface(ID3DXFile *iface, REFIID riid, void **out)
507 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
509 if (IsEqualGUID(riid, &IID_ID3DXFile)
510 || IsEqualGUID(riid, &IID_IUnknown))
512 iface->lpVtbl->AddRef(iface);
513 *out = iface;
514 return S_OK;
517 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
519 *out = NULL;
520 return E_NOINTERFACE;
523 static ULONG WINAPI d3dx9_file_AddRef(ID3DXFile *iface)
525 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
526 ULONG refcount = InterlockedIncrement(&file->ref);
528 TRACE("%p increasing refcount to %u.\n", file, refcount);
530 return refcount;
533 static ULONG WINAPI d3dx9_file_Release(ID3DXFile *iface)
535 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
536 ULONG refcount = InterlockedDecrement(&file->ref);
538 TRACE("%p decreasing refcount to %u.\n", file, refcount);
540 if (!refcount)
542 IDirectXFile_Release(file->dxfile);
543 HeapFree(GetProcessHeap(), 0, file);
546 return refcount;
549 static HRESULT WINAPI d3dx9_file_CreateEnumObject(ID3DXFile *iface, const void *source,
550 D3DXF_FILELOADOPTIONS options, ID3DXFileEnumObject **enum_object)
552 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
553 struct d3dx9_file_enum_object *object;
554 IDirectXFileEnumObject *dxfile_enum_object;
555 void *dxfile_source;
556 DXFILELOADOPTIONS dxfile_options;
557 DXFILELOADRESOURCE dxfile_resource;
558 DXFILELOADMEMORY dxfile_memory;
559 IDirectXFileData *data_object;
560 unsigned children_array_size = 0;
561 HRESULT ret;
563 TRACE("iface %p, source %p, options %#x, enum_object %p.\n", iface, source, options, enum_object);
565 if (!enum_object)
566 return E_POINTER;
568 *enum_object = NULL;
570 if (options == D3DXF_FILELOAD_FROMFILE)
572 dxfile_source = (void*)source;
573 dxfile_options = DXFILELOAD_FROMFILE;
575 else if (options == D3DXF_FILELOAD_FROMRESOURCE)
577 D3DXF_FILELOADRESOURCE *resource = (D3DXF_FILELOADRESOURCE*)source;
579 dxfile_resource.hModule = resource->hModule;
580 dxfile_resource.lpName = resource->lpName;
581 dxfile_resource.lpType = resource->lpType;
582 dxfile_source = &dxfile_resource;
583 dxfile_options = DXFILELOAD_FROMRESOURCE;
585 else if (options == D3DXF_FILELOAD_FROMMEMORY)
587 D3DXF_FILELOADMEMORY *memory = (D3DXF_FILELOADMEMORY*)source;
589 dxfile_memory.lpMemory = (void *)memory->lpMemory;
590 dxfile_memory.dSize = memory->dSize;
591 dxfile_source = &dxfile_memory;
592 dxfile_options = DXFILELOAD_FROMMEMORY;
594 else
596 FIXME("Source type %u is not handled yet\n", options);
597 return E_NOTIMPL;
600 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
601 if (!object)
602 return E_OUTOFMEMORY;
604 object->ID3DXFileEnumObject_iface.lpVtbl = &d3dx9_file_enum_object_vtbl;
605 object->ref = 1;
607 ret = IDirectXFile_CreateEnumObject(file->dxfile, dxfile_source, dxfile_options, &dxfile_enum_object);
609 if (ret != S_OK)
611 HeapFree(GetProcessHeap(), 0, object);
612 return ret;
615 /* Fill enum object with top level data objects */
616 while (SUCCEEDED(ret = IDirectXFileEnumObject_GetNextDataObject(dxfile_enum_object, &data_object)))
618 if (object->nb_children >= children_array_size)
620 ID3DXFileData **new_children;
622 if (object->children)
624 children_array_size *= 2;
625 new_children = HeapReAlloc(GetProcessHeap(), 0, object->children,
626 sizeof(*object->children) * children_array_size);
628 else
630 children_array_size = 4;
631 new_children = HeapAlloc(GetProcessHeap(), 0, sizeof(*object->children) * children_array_size);
633 if (!new_children)
635 ret = E_OUTOFMEMORY;
636 break;
638 object->children = new_children;
640 ret = d3dx9_file_data_create((IDirectXFileObject*)data_object,
641 &object->children[object->nb_children]);
642 IUnknown_Release(data_object);
643 if (FAILED(ret))
644 break;
645 object->nb_children++;
647 if (object->children)
649 ID3DXFileData **new_children;
651 new_children = HeapReAlloc(GetProcessHeap(), 0, object->children,
652 sizeof(*object->children) * object->nb_children);
653 if (new_children)
654 object->children = new_children;
657 IDirectXFileEnumObject_Release(dxfile_enum_object);
659 if (ret != DXFILEERR_NOMOREOBJECTS)
660 WARN("Cannot get all top level data objects\n");
662 TRACE("Found %u children\n", object->nb_children);
664 *enum_object = &object->ID3DXFileEnumObject_iface;
666 return S_OK;
669 static HRESULT WINAPI d3dx9_file_CreateSaveObject(ID3DXFile *iface, const void *data,
670 D3DXF_FILESAVEOPTIONS options, D3DXF_FILEFORMAT format, ID3DXFileSaveObject **save_object)
672 FIXME("iface %p, data %p, options %#x, format %#x, save_object %p stub!\n",
673 iface, data, options, format, save_object);
675 return E_NOTIMPL;
678 static HRESULT WINAPI d3dx9_file_RegisterTemplates(ID3DXFile *iface, const void *data, SIZE_T size)
680 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
681 HRESULT ret;
683 TRACE("iface %p, data %p, size %lu.\n", iface, data, size);
685 ret = IDirectXFile_RegisterTemplates(file->dxfile, (void *)data, size);
686 if (ret != DXFILE_OK)
688 WARN("Error %#x\n", ret);
689 return error_dxfile_to_d3dxfile(ret);
692 return S_OK;
695 static HRESULT WINAPI d3dx9_file_RegisterEnumTemplates(ID3DXFile *iface, ID3DXFileEnumObject *enum_object)
697 FIXME("iface %p, enum_object %p stub!\n", iface, enum_object);
699 return E_NOTIMPL;
702 static const ID3DXFileVtbl d3dx9_file_vtbl =
704 d3dx9_file_QueryInterface,
705 d3dx9_file_AddRef,
706 d3dx9_file_Release,
707 d3dx9_file_CreateEnumObject,
708 d3dx9_file_CreateSaveObject,
709 d3dx9_file_RegisterTemplates,
710 d3dx9_file_RegisterEnumTemplates,
713 HRESULT WINAPI D3DXFileCreate(ID3DXFile **d3dxfile)
715 struct d3dx9_file *object;
716 HRESULT ret;
718 TRACE("d3dxfile %p.\n", d3dxfile);
720 if (!d3dxfile)
721 return E_POINTER;
723 *d3dxfile = NULL;
725 object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
726 if (!object)
727 return E_OUTOFMEMORY;
729 ret = DirectXFileCreate(&object->dxfile);
730 if (ret != S_OK)
732 HeapFree(GetProcessHeap(), 0, object);
733 if (ret == E_OUTOFMEMORY)
734 return ret;
735 return E_FAIL;
738 object->ID3DXFile_iface.lpVtbl = &d3dx9_file_vtbl;
739 object->ref = 1;
741 *d3dxfile = &object->ID3DXFile_iface;
743 return S_OK;