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 "wine/port.h"
23 #include "d3dx9_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3dx
);
30 static HRESULT
error_dxfile_to_d3dxfile(HRESULT error
)
34 case DXFILEERR_BADFILETYPE
:
35 return D3DXFERR_BADFILETYPE
;
36 case DXFILEERR_BADFILEVERSION
:
37 return D3DXFERR_BADFILEVERSION
;
38 case DXFILEERR_BADFILEFLOATSIZE
:
39 return D3DXFERR_BADFILEFLOATSIZE
;
40 case DXFILEERR_PARSEERROR
:
41 return D3DXFERR_PARSEERROR
;
42 case DXFILEERR_BADVALUE
:
43 return D3DXFERR_BADVALUE
;
45 FIXME("Cannot map error %#x\n", error
);
52 ID3DXFile ID3DXFile_iface
;
57 struct d3dx9_file_enum_object
59 ID3DXFileEnumObject ID3DXFileEnumObject_iface
;
62 ID3DXFileData
**children
;
65 struct d3dx9_file_data
67 ID3DXFileData ID3DXFileData_iface
;
70 IDirectXFileData
*dxfile_data
;
72 ID3DXFileData
**children
;
75 static inline struct d3dx9_file
*impl_from_ID3DXFile(ID3DXFile
*iface
)
77 return CONTAINING_RECORD(iface
, struct d3dx9_file
, ID3DXFile_iface
);
80 static inline struct d3dx9_file_enum_object
*impl_from_ID3DXFileEnumObject(ID3DXFileEnumObject
*iface
)
82 return CONTAINING_RECORD(iface
, struct d3dx9_file_enum_object
, ID3DXFileEnumObject_iface
);
85 static inline struct d3dx9_file_data
*impl_from_ID3DXFileData(ID3DXFileData
*iface
)
87 return CONTAINING_RECORD(iface
, struct d3dx9_file_data
, ID3DXFileData_iface
);
90 static HRESULT WINAPI
d3dx9_file_data_QueryInterface(ID3DXFileData
*iface
, REFIID riid
, void **out
)
92 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
94 if (IsEqualGUID(riid
, &IID_ID3DXFileData
)
95 || IsEqualGUID(riid
, &IID_IUnknown
))
97 iface
->lpVtbl
->AddRef(iface
);
102 WARN("Interface %s not found.\n", debugstr_guid(riid
));
105 return E_NOINTERFACE
;
108 static ULONG WINAPI
d3dx9_file_data_AddRef(ID3DXFileData
*iface
)
110 struct d3dx9_file_data
*file_data
= impl_from_ID3DXFileData(iface
);
111 ULONG refcount
= InterlockedIncrement(&file_data
->ref
);
113 TRACE("%p increasing refcount to %u.\n", file_data
, refcount
);
118 static ULONG WINAPI
d3dx9_file_data_Release(ID3DXFileData
*iface
)
120 struct d3dx9_file_data
*file_data
= impl_from_ID3DXFileData(iface
);
121 ULONG refcount
= InterlockedDecrement(&file_data
->ref
);
123 TRACE("%p decreasing refcount to %u.\n", file_data
, refcount
);
129 for (i
= 0; i
< file_data
->nb_children
; ++i
)
131 ID3DXFileData
*child
= file_data
->children
[i
];
132 child
->lpVtbl
->Release(child
);
134 HeapFree(GetProcessHeap(), 0, file_data
->children
);
135 IDirectXFileData_Release(file_data
->dxfile_data
);
136 HeapFree(GetProcessHeap(), 0, file_data
);
142 static HRESULT WINAPI
d3dx9_file_data_GetEnum(ID3DXFileData
*iface
, ID3DXFileEnumObject
**enum_object
)
144 FIXME("iface %p, enum_object %p stub!\n", iface
, enum_object
);
149 static HRESULT WINAPI
d3dx9_file_data_GetName(ID3DXFileData
*iface
, char *name
, SIZE_T
*size
)
151 struct d3dx9_file_data
*file_data
= impl_from_ID3DXFileData(iface
);
155 TRACE("iface %p, name %p, size %p.\n", iface
, name
, size
);
158 return D3DXFERR_BADVALUE
;
162 ret
= IDirectXFileData_GetName(file_data
->dxfile_data
, name
, &dxfile_size
);
163 if (ret
!= DXFILE_OK
)
164 return error_dxfile_to_d3dxfile(ret
);
168 /* Contrary to d3dxof, d3dx9_36 returns an empty string with a null byte when no name is available.
169 * If the input size is 0, it returns a length of 1 without touching the buffer */
180 static HRESULT WINAPI
d3dx9_file_data_GetId(ID3DXFileData
*iface
, GUID
*guid
)
182 struct d3dx9_file_data
*file_data
= impl_from_ID3DXFileData(iface
);
185 TRACE("iface %p, guid %p.\n", iface
, guid
);
190 ret
= IDirectXFileData_GetId(file_data
->dxfile_data
, guid
);
191 if (ret
!= DXFILE_OK
)
192 return error_dxfile_to_d3dxfile(ret
);
197 static HRESULT WINAPI
d3dx9_file_data_Lock(ID3DXFileData
*iface
, SIZE_T
*size
, const void **data
)
199 struct d3dx9_file_data
*file_data
= impl_from_ID3DXFileData(iface
);
203 TRACE("iface %p, size %p, data %p.\n", iface
, size
, data
);
208 ret
= IDirectXFileData_GetData(file_data
->dxfile_data
, NULL
, &dxfile_size
, (void **)data
);
209 if (ret
!= DXFILE_OK
)
210 return error_dxfile_to_d3dxfile(ret
);
217 static HRESULT WINAPI
d3dx9_file_data_Unlock(ID3DXFileData
*iface
)
219 TRACE("iface %p.\n", iface
);
226 static HRESULT WINAPI
d3dx9_file_data_GetType(ID3DXFileData
*iface
, GUID
*guid
)
228 struct d3dx9_file_data
*file_data
= impl_from_ID3DXFileData(iface
);
229 const GUID
*dxfile_guid
;
232 TRACE("iface %p, guid %p.\n", iface
, guid
);
234 ret
= IDirectXFileData_GetType(file_data
->dxfile_data
, &dxfile_guid
);
235 if (ret
!= DXFILE_OK
)
236 return error_dxfile_to_d3dxfile(ret
);
238 *guid
= *dxfile_guid
;
243 static BOOL WINAPI
d3dx9_file_data_IsReference(ID3DXFileData
*iface
)
245 struct d3dx9_file_data
*file_data
= impl_from_ID3DXFileData(iface
);
247 TRACE("iface %p.\n", iface
);
249 return file_data
->reference
;
252 static HRESULT WINAPI
d3dx9_file_data_GetChildren(ID3DXFileData
*iface
, SIZE_T
*children
)
254 struct d3dx9_file_data
*file_data
= impl_from_ID3DXFileData(iface
);
256 TRACE("iface %p, children %p.\n", iface
, children
);
261 *children
= file_data
->nb_children
;
266 static HRESULT WINAPI
d3dx9_file_data_GetChild(ID3DXFileData
*iface
, SIZE_T id
, ID3DXFileData
**object
)
268 struct d3dx9_file_data
*file_data
= impl_from_ID3DXFileData(iface
);
270 TRACE("iface %p, id %#lx, object %p.\n", iface
, id
, object
);
275 *object
= file_data
->children
[id
];
276 (*object
)->lpVtbl
->AddRef(*object
);
281 static const ID3DXFileDataVtbl d3dx9_file_data_vtbl
=
283 d3dx9_file_data_QueryInterface
,
284 d3dx9_file_data_AddRef
,
285 d3dx9_file_data_Release
,
286 d3dx9_file_data_GetEnum
,
287 d3dx9_file_data_GetName
,
288 d3dx9_file_data_GetId
,
289 d3dx9_file_data_Lock
,
290 d3dx9_file_data_Unlock
,
291 d3dx9_file_data_GetType
,
292 d3dx9_file_data_IsReference
,
293 d3dx9_file_data_GetChildren
,
294 d3dx9_file_data_GetChild
,
297 static HRESULT
d3dx9_file_data_create(IDirectXFileObject
*dxfile_object
, ID3DXFileData
**ret_iface
)
299 struct d3dx9_file_data
*object
;
300 IDirectXFileObject
*data_object
;
301 unsigned int children_array_size
= 0;
304 TRACE("dxfile_object %p, ret_iface %p.\n", dxfile_object
, ret_iface
);
308 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
310 return E_OUTOFMEMORY
;
312 object
->ID3DXFileData_iface
.lpVtbl
= &d3dx9_file_data_vtbl
;
315 ret
= IDirectXFileObject_QueryInterface(dxfile_object
, &IID_IDirectXFileData
, (void **)&object
->dxfile_data
);
318 IDirectXFileDataReference
*reference
;
320 ret
= IDirectXFileObject_QueryInterface(dxfile_object
, &IID_IDirectXFileDataReference
, (void **)&reference
);
323 ret
= IDirectXFileDataReference_Resolve(reference
, &object
->dxfile_data
);
324 IUnknown_Release(reference
);
327 HeapFree(GetProcessHeap(), 0, object
);
330 object
->reference
= TRUE
;
334 FIXME("Don't know what to do with binary object\n");
335 HeapFree(GetProcessHeap(), 0, object
);
340 while (SUCCEEDED(ret
= IDirectXFileData_GetNextObject(object
->dxfile_data
, &data_object
)))
342 if (object
->nb_children
>= children_array_size
)
344 ID3DXFileData
**new_children
;
346 if (object
->children
)
348 children_array_size
*= 2;
349 new_children
= HeapReAlloc(GetProcessHeap(), 0, object
->children
,
350 sizeof(*object
->children
) * children_array_size
);
354 children_array_size
= 4;
355 new_children
= HeapAlloc(GetProcessHeap(), 0, sizeof(*object
->children
) * children_array_size
);
362 object
->children
= new_children
;
364 ret
= d3dx9_file_data_create(data_object
, &object
->children
[object
->nb_children
]);
365 IUnknown_Release(data_object
);
368 object
->nb_children
++;
370 if (ret
!= DXFILEERR_NOMOREOBJECTS
)
372 (&object
->ID3DXFileData_iface
)->lpVtbl
->Release(&object
->ID3DXFileData_iface
);
375 if (object
->children
)
377 ID3DXFileData
**new_children
;
379 new_children
= HeapReAlloc(GetProcessHeap(), 0, object
->children
,
380 sizeof(*object
->children
) * object
->nb_children
);
382 object
->children
= new_children
;
385 TRACE("Found %u children\n", object
->nb_children
);
387 *ret_iface
= &object
->ID3DXFileData_iface
;
392 static HRESULT WINAPI
d3dx9_file_enum_object_QueryInterface(ID3DXFileEnumObject
*iface
, REFIID riid
, void **out
)
394 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
396 if (IsEqualGUID(riid
, &IID_ID3DXFileEnumObject
)
397 || IsEqualGUID(riid
, &IID_IUnknown
))
399 iface
->lpVtbl
->AddRef(iface
);
404 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
407 return E_NOINTERFACE
;
410 static ULONG WINAPI
d3dx9_file_enum_object_AddRef(ID3DXFileEnumObject
*iface
)
412 struct d3dx9_file_enum_object
*file_enum
= impl_from_ID3DXFileEnumObject(iface
);
413 ULONG refcount
= InterlockedIncrement(&file_enum
->ref
);
415 TRACE("%p increasing refcount to %u.\n", file_enum
, refcount
);
420 static ULONG WINAPI
d3dx9_file_enum_object_Release(ID3DXFileEnumObject
*iface
)
422 struct d3dx9_file_enum_object
*file_enum
= impl_from_ID3DXFileEnumObject(iface
);
423 ULONG refcount
= InterlockedDecrement(&file_enum
->ref
);
425 TRACE("%p decreasing refcount to %u.\n", file_enum
, refcount
);
431 for (i
= 0; i
< file_enum
->nb_children
; ++i
)
433 ID3DXFileData
*child
= file_enum
->children
[i
];
434 child
->lpVtbl
->Release(child
);
436 HeapFree(GetProcessHeap(), 0, file_enum
->children
);
437 HeapFree(GetProcessHeap(), 0, file_enum
);
443 static HRESULT WINAPI
d3dx9_file_enum_object_GetFile(ID3DXFileEnumObject
*iface
, ID3DXFile
**file
)
445 FIXME("iface %p, file %p stub!\n", iface
, file
);
450 static HRESULT WINAPI
d3dx9_file_enum_object_GetChildren(ID3DXFileEnumObject
*iface
, SIZE_T
*children
)
452 struct d3dx9_file_enum_object
*file_enum
= impl_from_ID3DXFileEnumObject(iface
);
454 TRACE("iface %p, children %p.\n", iface
, children
);
459 *children
= file_enum
->nb_children
;
464 static HRESULT WINAPI
d3dx9_file_enum_object_GetChild(ID3DXFileEnumObject
*iface
, SIZE_T id
, ID3DXFileData
**object
)
466 struct d3dx9_file_enum_object
*file_enum
= impl_from_ID3DXFileEnumObject(iface
);
468 TRACE("iface %p, id %#lx, object %p.\n", iface
, id
, object
);
473 *object
= file_enum
->children
[id
];
474 (*object
)->lpVtbl
->AddRef(*object
);
479 static HRESULT WINAPI
d3dx9_file_enum_object_GetDataObjectById(ID3DXFileEnumObject
*iface
,
480 REFGUID guid
, ID3DXFileData
**object
)
482 FIXME("iface %p, guid %s, object %p stub!\n", iface
, debugstr_guid(guid
), object
);
487 static HRESULT WINAPI
d3dx9_file_enum_object_GetDataObjectByName(ID3DXFileEnumObject
*iface
,
488 const char *name
, ID3DXFileData
**object
)
490 FIXME("iface %p, name %s, object %p stub!\n", iface
, debugstr_a(name
), object
);
495 static const ID3DXFileEnumObjectVtbl d3dx9_file_enum_object_vtbl
=
497 d3dx9_file_enum_object_QueryInterface
,
498 d3dx9_file_enum_object_AddRef
,
499 d3dx9_file_enum_object_Release
,
500 d3dx9_file_enum_object_GetFile
,
501 d3dx9_file_enum_object_GetChildren
,
502 d3dx9_file_enum_object_GetChild
,
503 d3dx9_file_enum_object_GetDataObjectById
,
504 d3dx9_file_enum_object_GetDataObjectByName
,
507 static HRESULT WINAPI
d3dx9_file_QueryInterface(ID3DXFile
*iface
, REFIID riid
, void **out
)
509 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
511 if (IsEqualGUID(riid
, &IID_ID3DXFile
)
512 || IsEqualGUID(riid
, &IID_IUnknown
))
514 iface
->lpVtbl
->AddRef(iface
);
519 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
522 return E_NOINTERFACE
;
525 static ULONG WINAPI
d3dx9_file_AddRef(ID3DXFile
*iface
)
527 struct d3dx9_file
*file
= impl_from_ID3DXFile(iface
);
528 ULONG refcount
= InterlockedIncrement(&file
->ref
);
530 TRACE("%p increasing refcount to %u.\n", file
, refcount
);
535 static ULONG WINAPI
d3dx9_file_Release(ID3DXFile
*iface
)
537 struct d3dx9_file
*file
= impl_from_ID3DXFile(iface
);
538 ULONG refcount
= InterlockedDecrement(&file
->ref
);
540 TRACE("%p decreasing refcount to %u.\n", file
, refcount
);
544 IDirectXFile_Release(file
->dxfile
);
545 HeapFree(GetProcessHeap(), 0, file
);
551 static HRESULT WINAPI
d3dx9_file_CreateEnumObject(ID3DXFile
*iface
, const void *source
,
552 D3DXF_FILELOADOPTIONS options
, ID3DXFileEnumObject
**enum_object
)
554 struct d3dx9_file
*file
= impl_from_ID3DXFile(iface
);
555 struct d3dx9_file_enum_object
*object
;
556 IDirectXFileEnumObject
*dxfile_enum_object
;
558 DXFILELOADOPTIONS dxfile_options
;
559 DXFILELOADRESOURCE dxfile_resource
;
560 DXFILELOADMEMORY dxfile_memory
;
561 IDirectXFileData
*data_object
;
562 unsigned children_array_size
= 0;
565 TRACE("iface %p, source %p, options %#x, enum_object %p.\n", iface
, source
, options
, enum_object
);
572 if (options
== D3DXF_FILELOAD_FROMFILE
)
574 dxfile_source
= (void*)source
;
575 dxfile_options
= DXFILELOAD_FROMFILE
;
577 else if (options
== D3DXF_FILELOAD_FROMRESOURCE
)
579 D3DXF_FILELOADRESOURCE
*resource
= (D3DXF_FILELOADRESOURCE
*)source
;
581 dxfile_resource
.hModule
= resource
->hModule
;
582 dxfile_resource
.lpName
= resource
->lpName
;
583 dxfile_resource
.lpType
= resource
->lpType
;
584 dxfile_source
= &dxfile_resource
;
585 dxfile_options
= DXFILELOAD_FROMRESOURCE
;
587 else if (options
== D3DXF_FILELOAD_FROMMEMORY
)
589 D3DXF_FILELOADMEMORY
*memory
= (D3DXF_FILELOADMEMORY
*)source
;
591 dxfile_memory
.lpMemory
= memory
->lpMemory
;
592 dxfile_memory
.dSize
= memory
->dSize
;
593 dxfile_source
= &dxfile_memory
;
594 dxfile_options
= DXFILELOAD_FROMMEMORY
;
598 FIXME("Source type %u is not handled yet\n", options
);
602 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
604 return E_OUTOFMEMORY
;
606 object
->ID3DXFileEnumObject_iface
.lpVtbl
= &d3dx9_file_enum_object_vtbl
;
609 ret
= IDirectXFile_CreateEnumObject(file
->dxfile
, dxfile_source
, dxfile_options
, &dxfile_enum_object
);
613 HeapFree(GetProcessHeap(), 0, object
);
617 /* Fill enum object with top level data objects */
618 while (SUCCEEDED(ret
= IDirectXFileEnumObject_GetNextDataObject(dxfile_enum_object
, &data_object
)))
620 if (object
->nb_children
>= children_array_size
)
622 ID3DXFileData
**new_children
;
624 if (object
->children
)
626 children_array_size
*= 2;
627 new_children
= HeapReAlloc(GetProcessHeap(), 0, object
->children
,
628 sizeof(*object
->children
) * children_array_size
);
632 children_array_size
= 4;
633 new_children
= HeapAlloc(GetProcessHeap(), 0, sizeof(*object
->children
) * children_array_size
);
640 object
->children
= new_children
;
642 ret
= d3dx9_file_data_create((IDirectXFileObject
*)data_object
,
643 &object
->children
[object
->nb_children
]);
644 IUnknown_Release(data_object
);
647 object
->nb_children
++;
649 if (object
->children
)
651 ID3DXFileData
**new_children
;
653 new_children
= HeapReAlloc(GetProcessHeap(), 0, object
->children
,
654 sizeof(*object
->children
) * object
->nb_children
);
656 object
->children
= new_children
;
659 IDirectXFileEnumObject_Release(dxfile_enum_object
);
661 if (ret
!= DXFILEERR_NOMOREOBJECTS
)
662 WARN("Cannot get all top level data objects\n");
664 TRACE("Found %u children\n", object
->nb_children
);
666 *enum_object
= &object
->ID3DXFileEnumObject_iface
;
671 static HRESULT WINAPI
d3dx9_file_CreateSaveObject(ID3DXFile
*iface
, const void *data
,
672 D3DXF_FILESAVEOPTIONS options
, D3DXF_FILEFORMAT format
, ID3DXFileSaveObject
**save_object
)
674 FIXME("iface %p, data %p, options %#x, format %#x, save_object %p stub!\n",
675 iface
, data
, options
, format
, save_object
);
680 static HRESULT WINAPI
d3dx9_file_RegisterTemplates(ID3DXFile
*iface
, const void *data
, SIZE_T size
)
682 struct d3dx9_file
*file
= impl_from_ID3DXFile(iface
);
685 TRACE("iface %p, data %p, size %lu.\n", iface
, data
, size
);
687 ret
= IDirectXFile_RegisterTemplates(file
->dxfile
, (void *)data
, size
);
688 if (ret
!= DXFILE_OK
)
690 WARN("Error %#x\n", ret
);
691 return error_dxfile_to_d3dxfile(ret
);
697 static HRESULT WINAPI
d3dx9_file_RegisterEnumTemplates(ID3DXFile
*iface
, ID3DXFileEnumObject
*enum_object
)
699 FIXME("iface %p, enum_object %p stub!\n", iface
, enum_object
);
704 static const ID3DXFileVtbl d3dx9_file_vtbl
=
706 d3dx9_file_QueryInterface
,
709 d3dx9_file_CreateEnumObject
,
710 d3dx9_file_CreateSaveObject
,
711 d3dx9_file_RegisterTemplates
,
712 d3dx9_file_RegisterEnumTemplates
,
715 HRESULT WINAPI
D3DXFileCreate(ID3DXFile
**d3dxfile
)
717 struct d3dx9_file
*object
;
720 TRACE("d3dxfile %p.\n", d3dxfile
);
727 object
= HeapAlloc(GetProcessHeap(), 0, sizeof(*object
));
729 return E_OUTOFMEMORY
;
731 ret
= DirectXFileCreate(&object
->dxfile
);
734 HeapFree(GetProcessHeap(), 0, object
);
735 if (ret
== E_OUTOFMEMORY
)
740 object
->ID3DXFile_iface
.lpVtbl
= &d3dx9_file_vtbl
;
743 *d3dxfile
= &object
->ID3DXFile_iface
;