gdiplus: Mark the Graphics object as busy before freeing it.
[wine.git] / dlls / d3dx9_36 / xfile.c
blob84e480c2dd9b41e2dd717c343c7404b215cd7cd2
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
20 #include "wine/debug.h"
22 #include "d3dx9.h"
23 #include "d3dx9xof.h"
24 #undef MAKE_DDHRESULT
25 #include "dxfile.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
29 static HRESULT error_dxfile_to_d3dxfile(HRESULT error)
31 switch (error)
33 case DXFILEERR_BADFILETYPE:
34 return D3DXFERR_BADFILETYPE;
35 case DXFILEERR_BADFILEVERSION:
36 return D3DXFERR_BADFILEVERSION;
37 case DXFILEERR_BADFILEFLOATSIZE:
38 return D3DXFERR_BADFILEFLOATSIZE;
39 case DXFILEERR_PARSEERROR:
40 return D3DXFERR_PARSEERROR;
41 case DXFILEERR_BADVALUE:
42 return D3DXFERR_BADVALUE;
43 default:
44 FIXME("Cannot map error %#x\n", error);
45 return E_FAIL;
49 struct d3dx9_file
51 ID3DXFile ID3DXFile_iface;
52 LONG ref;
53 IDirectXFile *dxfile;
56 struct d3dx9_file_enum_object
58 ID3DXFileEnumObject ID3DXFileEnumObject_iface;
59 LONG ref;
60 ULONG nb_children;
61 ID3DXFileData **children;
64 struct d3dx9_file_data
66 ID3DXFileData ID3DXFileData_iface;
67 LONG ref;
68 BOOL reference;
69 IDirectXFileData *dxfile_data;
70 ULONG nb_children;
71 ID3DXFileData **children;
74 static inline struct d3dx9_file *impl_from_ID3DXFile(ID3DXFile *iface)
76 return CONTAINING_RECORD(iface, struct d3dx9_file, ID3DXFile_iface);
79 static inline struct d3dx9_file_enum_object *impl_from_ID3DXFileEnumObject(ID3DXFileEnumObject *iface)
81 return CONTAINING_RECORD(iface, struct d3dx9_file_enum_object, ID3DXFileEnumObject_iface);
84 static inline struct d3dx9_file_data *impl_from_ID3DXFileData(ID3DXFileData *iface)
86 return CONTAINING_RECORD(iface, struct d3dx9_file_data, ID3DXFileData_iface);
89 static HRESULT WINAPI d3dx9_file_data_QueryInterface(ID3DXFileData *iface, REFIID riid, void **out)
91 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
93 if (IsEqualGUID(riid, &IID_ID3DXFileData)
94 || IsEqualGUID(riid, &IID_IUnknown))
96 iface->lpVtbl->AddRef(iface);
97 *out = iface;
98 return S_OK;
101 WARN("Interface %s not found.\n", debugstr_guid(riid));
103 *out = NULL;
104 return E_NOINTERFACE;
107 static ULONG WINAPI d3dx9_file_data_AddRef(ID3DXFileData *iface)
109 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
110 ULONG refcount = InterlockedIncrement(&file_data->ref);
112 TRACE("%p increasing refcount to %u.\n", file_data, refcount);
114 return refcount;
117 static ULONG WINAPI d3dx9_file_data_Release(ID3DXFileData *iface)
119 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
120 ULONG refcount = InterlockedDecrement(&file_data->ref);
122 TRACE("%p decreasing refcount to %u.\n", file_data, refcount);
124 if (!refcount)
126 ULONG i;
128 for (i = 0; i < file_data->nb_children; ++i)
130 ID3DXFileData *child = file_data->children[i];
131 child->lpVtbl->Release(child);
133 HeapFree(GetProcessHeap(), 0, file_data->children);
134 IDirectXFileData_Release(file_data->dxfile_data);
135 HeapFree(GetProcessHeap(), 0, file_data);
138 return refcount;
141 static HRESULT WINAPI d3dx9_file_data_GetEnum(ID3DXFileData *iface, ID3DXFileEnumObject **enum_object)
143 FIXME("iface %p, enum_object %p stub!\n", iface, enum_object);
145 return E_NOTIMPL;
148 static HRESULT WINAPI d3dx9_file_data_GetName(ID3DXFileData *iface, char *name, SIZE_T *size)
150 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
151 DWORD dxfile_size;
152 HRESULT ret;
154 TRACE("iface %p, name %p, size %p.\n", iface, name, size);
156 if (!size)
157 return D3DXFERR_BADVALUE;
159 dxfile_size = *size;
161 ret = IDirectXFileData_GetName(file_data->dxfile_data, name, &dxfile_size);
162 if (ret != DXFILE_OK)
163 return error_dxfile_to_d3dxfile(ret);
165 if (!dxfile_size)
167 /* Contrary to d3dxof, d3dx9_36 returns an empty string with a null byte when no name is available.
168 * If the input size is 0, it returns a length of 1 without touching the buffer */
169 dxfile_size = 1;
170 if (name && *size)
171 name[0] = 0;
174 *size = dxfile_size;
176 return S_OK;
179 static HRESULT WINAPI d3dx9_file_data_GetId(ID3DXFileData *iface, GUID *guid)
181 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
182 HRESULT ret;
184 TRACE("iface %p, guid %p.\n", iface, guid);
186 if (!guid)
187 return E_POINTER;
189 ret = IDirectXFileData_GetId(file_data->dxfile_data, guid);
190 if (ret != DXFILE_OK)
191 return error_dxfile_to_d3dxfile(ret);
193 return S_OK;
196 static HRESULT WINAPI d3dx9_file_data_Lock(ID3DXFileData *iface, SIZE_T *size, const void **data)
198 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
199 DWORD dxfile_size;
200 HRESULT ret;
202 TRACE("iface %p, size %p, data %p.\n", iface, size, data);
204 if (!size || !data)
205 return E_POINTER;
207 ret = IDirectXFileData_GetData(file_data->dxfile_data, NULL, &dxfile_size, (void **)data);
208 if (ret != DXFILE_OK)
209 return error_dxfile_to_d3dxfile(ret);
211 *size = dxfile_size;
213 return S_OK;
216 static HRESULT WINAPI d3dx9_file_data_Unlock(ID3DXFileData *iface)
218 TRACE("iface %p.\n", iface);
220 /* Nothing to do */
222 return S_OK;
225 static HRESULT WINAPI d3dx9_file_data_GetType(ID3DXFileData *iface, GUID *guid)
227 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
228 const GUID *dxfile_guid;
229 HRESULT ret;
231 TRACE("iface %p, guid %p.\n", iface, guid);
233 ret = IDirectXFileData_GetType(file_data->dxfile_data, &dxfile_guid);
234 if (ret != DXFILE_OK)
235 return error_dxfile_to_d3dxfile(ret);
237 *guid = *dxfile_guid;
239 return S_OK;
242 static BOOL WINAPI d3dx9_file_data_IsReference(ID3DXFileData *iface)
244 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
246 TRACE("iface %p.\n", iface);
248 return file_data->reference;
251 static HRESULT WINAPI d3dx9_file_data_GetChildren(ID3DXFileData *iface, SIZE_T *children)
253 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
255 TRACE("iface %p, children %p.\n", iface, children);
257 if (!children)
258 return E_POINTER;
260 *children = file_data->nb_children;
262 return S_OK;
265 static HRESULT WINAPI d3dx9_file_data_GetChild(ID3DXFileData *iface, SIZE_T id, ID3DXFileData **object)
267 struct d3dx9_file_data *file_data = impl_from_ID3DXFileData(iface);
269 TRACE("iface %p, id %#lx, object %p.\n", iface, id, object);
271 if (!object)
272 return E_POINTER;
274 *object = file_data->children[id];
275 (*object)->lpVtbl->AddRef(*object);
277 return S_OK;
280 static const ID3DXFileDataVtbl d3dx9_file_data_vtbl =
282 d3dx9_file_data_QueryInterface,
283 d3dx9_file_data_AddRef,
284 d3dx9_file_data_Release,
285 d3dx9_file_data_GetEnum,
286 d3dx9_file_data_GetName,
287 d3dx9_file_data_GetId,
288 d3dx9_file_data_Lock,
289 d3dx9_file_data_Unlock,
290 d3dx9_file_data_GetType,
291 d3dx9_file_data_IsReference,
292 d3dx9_file_data_GetChildren,
293 d3dx9_file_data_GetChild,
296 static HRESULT d3dx9_file_data_create(IDirectXFileObject *dxfile_object, ID3DXFileData **ret_iface)
298 struct d3dx9_file_data *object;
299 IDirectXFileObject *data_object;
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 if (FAILED(ret))
324 HeapFree(GetProcessHeap(), 0, object);
325 return E_FAIL;
327 object->reference = TRUE;
329 else
331 FIXME("Don't known what to do with binary object\n");
332 HeapFree(GetProcessHeap(), 0, object);
333 return E_FAIL;
337 while (SUCCEEDED(ret = IDirectXFileData_GetNextObject(object->dxfile_data, &data_object)))
339 if (object->children)
340 object->children = HeapReAlloc(GetProcessHeap(), 0, object->children, sizeof(ID3DXFileData*) * (object->nb_children + 1));
341 else
342 object->children = HeapAlloc(GetProcessHeap(), 0, sizeof(ID3DXFileData*));
343 if (!object->children)
345 ret = E_OUTOFMEMORY;
346 break;
348 if (FAILED(ret = d3dx9_file_data_create(data_object, &object->children[object->nb_children])))
349 break;
350 object->nb_children++;
353 if (ret != DXFILEERR_NOMOREOBJECTS)
355 (&object->ID3DXFileData_iface)->lpVtbl->Release(&object->ID3DXFileData_iface);
356 return ret;
359 TRACE("Found %u children\n", object->nb_children);
361 *ret_iface = &object->ID3DXFileData_iface;
363 return S_OK;
366 static HRESULT WINAPI d3dx9_file_enum_object_QueryInterface(ID3DXFileEnumObject *iface, REFIID riid, void **out)
368 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
370 if (IsEqualGUID(riid, &IID_ID3DXFileEnumObject)
371 || IsEqualGUID(riid, &IID_IUnknown))
373 iface->lpVtbl->AddRef(iface);
374 *out = iface;
375 return S_OK;
378 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
380 *out = NULL;
381 return E_NOINTERFACE;
384 static ULONG WINAPI d3dx9_file_enum_object_AddRef(ID3DXFileEnumObject *iface)
386 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
387 ULONG refcount = InterlockedIncrement(&file_enum->ref);
389 TRACE("%p increasing refcount to %u.\n", file_enum, refcount);
391 return refcount;
394 static ULONG WINAPI d3dx9_file_enum_object_Release(ID3DXFileEnumObject *iface)
396 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
397 ULONG refcount = InterlockedDecrement(&file_enum->ref);
399 TRACE("%p decreasing refcount to %u.\n", file_enum, refcount);
401 if (!refcount)
403 ULONG i;
405 for (i = 0; i < file_enum->nb_children; ++i)
407 ID3DXFileData *child = file_enum->children[i];
408 child->lpVtbl->Release(child);
410 HeapFree(GetProcessHeap(), 0, file_enum->children);
411 HeapFree(GetProcessHeap(), 0, file_enum);
414 return refcount;
417 static HRESULT WINAPI d3dx9_file_enum_object_GetFile(ID3DXFileEnumObject *iface, ID3DXFile **file)
419 FIXME("iface %p, file %p stub!\n", iface, file);
421 return E_NOTIMPL;
424 static HRESULT WINAPI d3dx9_file_enum_object_GetChildren(ID3DXFileEnumObject *iface, SIZE_T *children)
426 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
428 TRACE("iface %p, children %p.\n", iface, children);
430 if (!children)
431 return E_POINTER;
433 *children = file_enum->nb_children;
435 return S_OK;
438 static HRESULT WINAPI d3dx9_file_enum_object_GetChild(ID3DXFileEnumObject *iface, SIZE_T id, ID3DXFileData **object)
440 struct d3dx9_file_enum_object *file_enum = impl_from_ID3DXFileEnumObject(iface);
442 TRACE("iface %p, id %#lx, object %p.\n", iface, id, object);
444 if (!object)
445 return E_POINTER;
447 *object = file_enum->children[id];
448 (*object)->lpVtbl->AddRef(*object);
450 return S_OK;
453 static HRESULT WINAPI d3dx9_file_enum_object_GetDataObjectById(ID3DXFileEnumObject *iface,
454 REFGUID guid, ID3DXFileData **object)
456 FIXME("iface %p, guid %s, object %p stub!\n", iface, debugstr_guid(guid), object);
458 return E_NOTIMPL;
461 static HRESULT WINAPI d3dx9_file_enum_object_GetDataObjectByName(ID3DXFileEnumObject *iface,
462 const char *name, ID3DXFileData **object)
464 FIXME("iface %p, name %s, object %p stub!\n", iface, debugstr_a(name), object);
466 return E_NOTIMPL;
469 static const ID3DXFileEnumObjectVtbl d3dx9_file_enum_object_vtbl =
471 d3dx9_file_enum_object_QueryInterface,
472 d3dx9_file_enum_object_AddRef,
473 d3dx9_file_enum_object_Release,
474 d3dx9_file_enum_object_GetFile,
475 d3dx9_file_enum_object_GetChildren,
476 d3dx9_file_enum_object_GetChild,
477 d3dx9_file_enum_object_GetDataObjectById,
478 d3dx9_file_enum_object_GetDataObjectByName,
481 static HRESULT WINAPI d3dx9_file_QueryInterface(ID3DXFile *iface, REFIID riid, void **out)
483 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
485 if (IsEqualGUID(riid, &IID_ID3DXFile)
486 || IsEqualGUID(riid, &IID_IUnknown))
488 iface->lpVtbl->AddRef(iface);
489 *out = iface;
490 return S_OK;
493 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
495 *out = NULL;
496 return E_NOINTERFACE;
499 static ULONG WINAPI d3dx9_file_AddRef(ID3DXFile *iface)
501 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
502 ULONG refcount = InterlockedIncrement(&file->ref);
504 TRACE("%p increasing refcount to %u.\n", file, refcount);
506 return refcount;
509 static ULONG WINAPI d3dx9_file_Release(ID3DXFile *iface)
511 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
512 ULONG refcount = InterlockedDecrement(&file->ref);
514 TRACE("%p decreasing refcount to %u.\n", file, refcount);
516 if (!refcount)
518 IDirectXFile_Release(file->dxfile);
519 HeapFree(GetProcessHeap(), 0, file);
522 return refcount;
525 static HRESULT WINAPI d3dx9_file_CreateEnumObject(ID3DXFile *iface, const void *source,
526 D3DXF_FILELOADOPTIONS options, ID3DXFileEnumObject **enum_object)
528 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
529 struct d3dx9_file_enum_object *object;
530 IDirectXFileEnumObject *dxfile_enum_object;
531 void *dxfile_source;
532 DXFILELOADOPTIONS dxfile_options;
533 DXFILELOADRESOURCE dxfile_resource;
534 DXFILELOADMEMORY dxfile_memory;
535 IDirectXFileData *data_object;
536 HRESULT ret;
538 TRACE("iface %p, source %p, options %#x, enum_object %p.\n", iface, source, options, enum_object);
540 if (!enum_object)
541 return E_POINTER;
543 *enum_object = NULL;
545 if (options == D3DXF_FILELOAD_FROMFILE)
547 dxfile_source = (void*)source;
548 dxfile_options = DXFILELOAD_FROMFILE;
550 else if (options == D3DXF_FILELOAD_FROMRESOURCE)
552 D3DXF_FILELOADRESOURCE *resource = (D3DXF_FILELOADRESOURCE*)source;
554 dxfile_resource.hModule = resource->hModule;
555 dxfile_resource.lpName = resource->lpName;
556 dxfile_resource.lpType = resource->lpType;
557 dxfile_source = &dxfile_resource;
558 dxfile_options = DXFILELOAD_FROMRESOURCE;
560 else if (options == D3DXF_FILELOAD_FROMMEMORY)
562 D3DXF_FILELOADMEMORY *memory = (D3DXF_FILELOADMEMORY*)source;
564 dxfile_memory.lpMemory = memory->lpMemory;
565 dxfile_memory.dSize = memory->dSize;
566 dxfile_source = &dxfile_memory;
567 dxfile_options = DXFILELOAD_FROMMEMORY;
569 else
571 FIXME("Source type %u is not handled yet\n", options);
572 return E_NOTIMPL;
575 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
576 if (!object)
577 return E_OUTOFMEMORY;
579 object->ID3DXFileEnumObject_iface.lpVtbl = &d3dx9_file_enum_object_vtbl;
580 object->ref = 1;
582 ret = IDirectXFile_CreateEnumObject(file->dxfile, dxfile_source, dxfile_options, &dxfile_enum_object);
584 if (ret != S_OK)
586 HeapFree(GetProcessHeap(), 0, object);
587 return ret;
590 /* Fill enum object with top level data objects */
591 while (SUCCEEDED(ret = IDirectXFileEnumObject_GetNextDataObject(dxfile_enum_object, &data_object)))
593 if (object->children)
594 object->children = HeapReAlloc(GetProcessHeap(), 0, object->children, sizeof(*object->children) * (object->nb_children + 1));
595 else
596 object->children = HeapAlloc(GetProcessHeap(), 0, sizeof(*object->children));
597 if (!object->children)
599 ret = E_OUTOFMEMORY;
600 break;
602 if (FAILED(ret = d3dx9_file_data_create((IDirectXFileObject*)data_object,
603 &object->children[object->nb_children])))
604 break;
605 object->nb_children++;
608 IDirectXFileEnumObject_Release(dxfile_enum_object);
610 if (ret != DXFILEERR_NOMOREOBJECTS)
611 WARN("Cannot get all top level data objects\n");
613 TRACE("Found %u children\n", object->nb_children);
615 *enum_object = &object->ID3DXFileEnumObject_iface;
617 return S_OK;
620 static HRESULT WINAPI d3dx9_file_CreateSaveObject(ID3DXFile *iface, const void *data,
621 D3DXF_FILESAVEOPTIONS options, D3DXF_FILEFORMAT format, ID3DXFileSaveObject **save_object)
623 FIXME("iface %p, data %p, options %#x, format %#x, save_object %p stub!\n",
624 iface, data, options, format, save_object);
626 return E_NOTIMPL;
629 static HRESULT WINAPI d3dx9_file_RegisterTemplates(ID3DXFile *iface, const void *data, SIZE_T size)
631 struct d3dx9_file *file = impl_from_ID3DXFile(iface);
632 HRESULT ret;
634 TRACE("iface %p, data %p, size %lu.\n", iface, data, size);
636 ret = IDirectXFile_RegisterTemplates(file->dxfile, (void *)data, size);
637 if (ret != DXFILE_OK)
639 WARN("Error %#x\n", ret);
640 return error_dxfile_to_d3dxfile(ret);
643 return S_OK;
646 static HRESULT WINAPI d3dx9_file_RegisterEnumTemplates(ID3DXFile *iface, ID3DXFileEnumObject *enum_object)
648 FIXME("iface %p, enum_object %p stub!\n", iface, enum_object);
650 return E_NOTIMPL;
653 static const ID3DXFileVtbl d3dx9_file_vtbl =
655 d3dx9_file_QueryInterface,
656 d3dx9_file_AddRef,
657 d3dx9_file_Release,
658 d3dx9_file_CreateEnumObject,
659 d3dx9_file_CreateSaveObject,
660 d3dx9_file_RegisterTemplates,
661 d3dx9_file_RegisterEnumTemplates,
664 HRESULT WINAPI D3DXFileCreate(ID3DXFile **d3dxfile)
666 struct d3dx9_file *object;
667 HRESULT ret;
669 TRACE("d3dxfile %p.\n", d3dxfile);
671 if (!d3dxfile)
672 return E_POINTER;
674 *d3dxfile = NULL;
676 object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
677 if (!object)
678 return E_OUTOFMEMORY;
680 ret = DirectXFileCreate(&object->dxfile);
681 if (ret != S_OK)
683 HeapFree(GetProcessHeap(), 0, object);
684 if (ret == E_OUTOFMEMORY)
685 return ret;
686 return E_FAIL;
689 object->ID3DXFile_iface.lpVtbl = &d3dx9_file_vtbl;
690 object->ref = 1;
692 *d3dxfile = &object->ID3DXFile_iface;
694 return S_OK;