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 "d3dx9_36_private.h"
26 static HRESULT
error_dxfile_to_d3dxfile(HRESULT error
)
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
;
41 FIXME("Cannot map error %#x\n", error
);
47 ID3DXFile ID3DXFile_iface
;
53 ID3DXFileEnumObject ID3DXFileEnumObject_iface
;
56 ID3DXFileData
**children
;
57 } ID3DXFileEnumObjectImpl
;
60 ID3DXFileData ID3DXFileData_iface
;
63 IDirectXFileData
*dxfile_data
;
65 ID3DXFileData
**children
;
69 static inline ID3DXFileImpl
* impl_from_ID3DXFile(ID3DXFile
*iface
)
71 return CONTAINING_RECORD(iface
, ID3DXFileImpl
, ID3DXFile_iface
);
74 static inline ID3DXFileEnumObjectImpl
* impl_from_ID3DXFileEnumObject(ID3DXFileEnumObject
*iface
)
76 return CONTAINING_RECORD(iface
, ID3DXFileEnumObjectImpl
, ID3DXFileEnumObject_iface
);
79 static inline ID3DXFileDataImpl
* impl_from_ID3DXFileData(ID3DXFileData
*iface
)
81 return CONTAINING_RECORD(iface
, ID3DXFileDataImpl
, ID3DXFileData_iface
);
84 /*** IUnknown methods ***/
86 static HRESULT WINAPI
ID3DXFileDataImpl_QueryInterface(ID3DXFileData
*iface
, REFIID riid
, void **ret_iface
)
88 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ret_iface
);
90 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
91 IsEqualGUID(riid
, &IID_ID3DXFileData
))
93 iface
->lpVtbl
->AddRef(iface
);
98 WARN("(%p)->(%s, %p), not found\n", iface
, debugstr_guid(riid
), ret_iface
);
100 return E_NOINTERFACE
;
103 static ULONG WINAPI
ID3DXFileDataImpl_AddRef(ID3DXFileData
*iface
)
105 ID3DXFileDataImpl
*This
= impl_from_ID3DXFileData(iface
);
106 ULONG ref
= InterlockedIncrement(&This
->ref
);
108 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
113 static ULONG WINAPI
ID3DXFileDataImpl_Release(ID3DXFileData
*iface
)
115 ID3DXFileDataImpl
*This
= impl_from_ID3DXFileData(iface
);
116 ULONG ref
= InterlockedDecrement(&This
->ref
);
118 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
124 for (i
= 0; i
< This
->nb_children
; i
++)
125 (This
->children
[i
])->lpVtbl
->Release(This
->children
[i
]);
126 HeapFree(GetProcessHeap(), 0, This
->children
);
127 IDirectXFileData_Release(This
->dxfile_data
);
128 HeapFree(GetProcessHeap(), 0, This
);
135 /*** ID3DXFileData methods ***/
137 static HRESULT WINAPI
ID3DXFileDataImpl_GetEnum(ID3DXFileData
*iface
, ID3DXFileEnumObject
**enum_object
)
139 FIXME("(%p)->(%p): stub\n", iface
, enum_object
);
145 static HRESULT WINAPI
ID3DXFileDataImpl_GetName(ID3DXFileData
*iface
, char *name
, SIZE_T
*size
)
147 ID3DXFileDataImpl
*This
= impl_from_ID3DXFileData(iface
);
151 TRACE("(%p)->(%p, %p)\n", iface
, name
, size
);
154 return D3DXFERR_BADVALUE
;
158 ret
= IDirectXFileData_GetName(This
->dxfile_data
, name
, &dxfile_size
);
159 if (ret
!= DXFILE_OK
)
160 return error_dxfile_to_d3dxfile(ret
);
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 */
177 static HRESULT WINAPI
ID3DXFileDataImpl_GetId(ID3DXFileData
*iface
, GUID
*guid
)
179 ID3DXFileDataImpl
*This
= impl_from_ID3DXFileData(iface
);
182 TRACE("(%p)->(%p)\n", iface
, guid
);
187 ret
= IDirectXFileData_GetId(This
->dxfile_data
, guid
);
188 if (ret
!= DXFILE_OK
)
189 return error_dxfile_to_d3dxfile(ret
);
195 static HRESULT WINAPI
ID3DXFileDataImpl_Lock(ID3DXFileData
*iface
, SIZE_T
*size
, const void **data
)
197 ID3DXFileDataImpl
*This
= impl_from_ID3DXFileData(iface
);
201 TRACE("(%p)->(%p, %p)\n", iface
, size
, data
);
206 ret
= IDirectXFileData_GetData(This
->dxfile_data
, NULL
, &dxfile_size
, (void**)data
);
207 if (ret
!= DXFILE_OK
)
208 return error_dxfile_to_d3dxfile(ret
);
216 static HRESULT WINAPI
ID3DXFileDataImpl_Unlock(ID3DXFileData
*iface
)
218 TRACE("(%p)->()\n", iface
);
226 static HRESULT WINAPI
ID3DXFileDataImpl_GetType(ID3DXFileData
*iface
, GUID
*guid
)
228 ID3DXFileDataImpl
*This
= impl_from_ID3DXFileData(iface
);
229 const GUID
*dxfile_guid
;
232 TRACE("(%p)->(%p)\n", iface
, guid
);
234 ret
= IDirectXFileData_GetType(This
->dxfile_data
, &dxfile_guid
);
235 if (ret
!= DXFILE_OK
)
236 return error_dxfile_to_d3dxfile(ret
);
238 *guid
= *dxfile_guid
;
244 static BOOL WINAPI
ID3DXFileDataImpl_IsReference(ID3DXFileData
*iface
)
246 ID3DXFileDataImpl
*This
= impl_from_ID3DXFileData(iface
);
248 TRACE("(%p)->()\n", iface
);
250 return This
->reference
;
254 static HRESULT WINAPI
ID3DXFileDataImpl_GetChildren(ID3DXFileData
*iface
, SIZE_T
*children
)
256 ID3DXFileDataImpl
*This
= impl_from_ID3DXFileData(iface
);
258 TRACE("(%p)->(%p)\n", iface
, children
);
263 *children
= This
->nb_children
;
269 static HRESULT WINAPI
ID3DXFileDataImpl_GetChild(ID3DXFileData
*iface
, SIZE_T id
, ID3DXFileData
**object
)
271 ID3DXFileDataImpl
*This
= impl_from_ID3DXFileData(iface
);
273 TRACE("(%p)->(%lu, %p)\n", iface
, id
, object
);
278 *object
= This
->children
[id
];
279 (*object
)->lpVtbl
->AddRef(*object
);
285 static const ID3DXFileDataVtbl ID3DXFileData_Vtbl
=
287 ID3DXFileDataImpl_QueryInterface
,
288 ID3DXFileDataImpl_AddRef
,
289 ID3DXFileDataImpl_Release
,
290 ID3DXFileDataImpl_GetEnum
,
291 ID3DXFileDataImpl_GetName
,
292 ID3DXFileDataImpl_GetId
,
293 ID3DXFileDataImpl_Lock
,
294 ID3DXFileDataImpl_Unlock
,
295 ID3DXFileDataImpl_GetType
,
296 ID3DXFileDataImpl_IsReference
,
297 ID3DXFileDataImpl_GetChildren
,
298 ID3DXFileDataImpl_GetChild
302 static HRESULT
ID3DXFileDataImpl_Create(IDirectXFileObject
*dxfile_object
, ID3DXFileData
**ret_iface
)
304 ID3DXFileDataImpl
*object
;
305 IDirectXFileObject
*data_object
;
308 TRACE("(%p, %p)\n", dxfile_object
, ret_iface
);
312 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
314 return E_OUTOFMEMORY
;
316 object
->ID3DXFileData_iface
.lpVtbl
= &ID3DXFileData_Vtbl
;
319 ret
= IDirectXFileObject_QueryInterface(dxfile_object
, &IID_IDirectXFileData
, (void **)&object
->dxfile_data
);
322 IDirectXFileDataReference
*reference
;
324 ret
= IDirectXFileObject_QueryInterface(dxfile_object
, &IID_IDirectXFileDataReference
, (void **)&reference
);
327 ret
= IDirectXFileDataReference_Resolve(reference
, &object
->dxfile_data
);
330 HeapFree(GetProcessHeap(), 0, object
);
333 object
->reference
= TRUE
;
337 FIXME("Don't known what to do with binary object\n");
338 HeapFree(GetProcessHeap(), 0, object
);
343 while (SUCCEEDED(ret
= IDirectXFileData_GetNextObject(object
->dxfile_data
, &data_object
)))
345 if (object
->children
)
346 object
->children
= HeapReAlloc(GetProcessHeap(), 0, object
->children
, sizeof(ID3DXFileData
*) * (object
->nb_children
+ 1));
348 object
->children
= HeapAlloc(GetProcessHeap(), 0, sizeof(ID3DXFileData
*));
349 if (!object
->children
)
354 ret
= ID3DXFileDataImpl_Create(data_object
, &object
->children
[object
->nb_children
]);
357 object
->nb_children
++;
360 if (ret
!= DXFILEERR_NOMOREOBJECTS
)
362 (&object
->ID3DXFileData_iface
)->lpVtbl
->Release(&object
->ID3DXFileData_iface
);
366 TRACE("Found %u children\n", object
->nb_children
);
368 *ret_iface
= &object
->ID3DXFileData_iface
;
374 /*** IUnknown methods ***/
376 static HRESULT WINAPI
ID3DXFileEnumObjectImpl_QueryInterface(ID3DXFileEnumObject
*iface
, REFIID riid
, void **ret_iface
)
378 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ret_iface
);
380 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
381 IsEqualGUID(riid
, &IID_ID3DXFileEnumObject
))
383 iface
->lpVtbl
->AddRef(iface
);
388 WARN("(%p)->(%s, %p), not found\n", iface
, debugstr_guid(riid
), ret_iface
);
390 return E_NOINTERFACE
;
393 static ULONG WINAPI
ID3DXFileEnumObjectImpl_AddRef(ID3DXFileEnumObject
*iface
)
395 ID3DXFileEnumObjectImpl
*This
= impl_from_ID3DXFileEnumObject(iface
);
396 ULONG ref
= InterlockedIncrement(&This
->ref
);
398 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
403 static ULONG WINAPI
ID3DXFileEnumObjectImpl_Release(ID3DXFileEnumObject
*iface
)
405 ID3DXFileEnumObjectImpl
*This
= impl_from_ID3DXFileEnumObject(iface
);
406 ULONG ref
= InterlockedDecrement(&This
->ref
);
408 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
414 for (i
= 0; i
< This
->nb_children
; i
++)
415 (This
->children
[i
])->lpVtbl
->Release(This
->children
[i
]);
416 HeapFree(GetProcessHeap(), 0, This
->children
);
417 HeapFree(GetProcessHeap(), 0, This
);
424 /*** ID3DXFileEnumObject methods ***/
426 static HRESULT WINAPI
ID3DXFileEnumObjectImpl_GetFile(ID3DXFileEnumObject
*iface
, ID3DXFile
**file
)
428 FIXME("(%p)->(%p): stub\n", iface
, file
);
434 static HRESULT WINAPI
ID3DXFileEnumObjectImpl_GetChildren(ID3DXFileEnumObject
*iface
, SIZE_T
*children
)
436 ID3DXFileEnumObjectImpl
*This
= impl_from_ID3DXFileEnumObject(iface
);
438 TRACE("(%p)->(%p)\n", iface
, children
);
443 *children
= This
->nb_children
;
449 static HRESULT WINAPI
ID3DXFileEnumObjectImpl_GetChild(ID3DXFileEnumObject
*iface
, SIZE_T id
, ID3DXFileData
**object
)
451 ID3DXFileEnumObjectImpl
*This
= impl_from_ID3DXFileEnumObject(iface
);
453 TRACE("(%p)->(%lu, %p)\n", iface
, id
, object
);
458 *object
= This
->children
[id
];
459 (*object
)->lpVtbl
->AddRef(*object
);
465 static HRESULT WINAPI
ID3DXFileEnumObjectImpl_GetDataObjectById(ID3DXFileEnumObject
*iface
, REFGUID guid
, ID3DXFileData
**object
)
467 FIXME("(%p)->(%s, %p): stub\n", iface
, debugstr_guid(guid
), object
);
473 static HRESULT WINAPI
ID3DXFileEnumObjectImpl_GetDataObjectByName(ID3DXFileEnumObject
*iface
, const char *name
, ID3DXFileData
**object
)
475 FIXME("(%p)->(%s, %p): stub\n", iface
, debugstr_a(name
), object
);
481 static const ID3DXFileEnumObjectVtbl ID3DXFileEnumObject_Vtbl
=
483 ID3DXFileEnumObjectImpl_QueryInterface
,
484 ID3DXFileEnumObjectImpl_AddRef
,
485 ID3DXFileEnumObjectImpl_Release
,
486 ID3DXFileEnumObjectImpl_GetFile
,
487 ID3DXFileEnumObjectImpl_GetChildren
,
488 ID3DXFileEnumObjectImpl_GetChild
,
489 ID3DXFileEnumObjectImpl_GetDataObjectById
,
490 ID3DXFileEnumObjectImpl_GetDataObjectByName
494 /*** IUnknown methods ***/
496 static HRESULT WINAPI
ID3DXFileImpl_QueryInterface(ID3DXFile
*iface
, REFIID riid
, void **ret_iface
)
498 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ret_iface
);
500 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
501 IsEqualGUID(riid
, &IID_ID3DXFile
))
503 iface
->lpVtbl
->AddRef(iface
);
508 WARN("(%p)->(%s, %p), not found\n", iface
, debugstr_guid(riid
), ret_iface
);
510 return E_NOINTERFACE
;
514 static ULONG WINAPI
ID3DXFileImpl_AddRef(ID3DXFile
*iface
)
516 ID3DXFileImpl
*This
= impl_from_ID3DXFile(iface
);
517 ULONG ref
= InterlockedIncrement(&This
->ref
);
519 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
525 static ULONG WINAPI
ID3DXFileImpl_Release(ID3DXFile
*iface
)
527 ID3DXFileImpl
*This
= impl_from_ID3DXFile(iface
);
528 ULONG ref
= InterlockedDecrement(&This
->ref
);
530 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
534 IDirectXFile_Release(This
->dxfile
);
535 HeapFree(GetProcessHeap(), 0, This
);
542 /*** ID3DXFile methods ***/
544 static HRESULT WINAPI
ID3DXFileImpl_CreateEnumObject(ID3DXFile
*iface
, const void *source
, D3DXF_FILELOADOPTIONS options
, ID3DXFileEnumObject
**enum_object
)
546 ID3DXFileImpl
*This
= impl_from_ID3DXFile(iface
);
547 ID3DXFileEnumObjectImpl
*object
;
548 IDirectXFileEnumObject
*dxfile_enum_object
;
550 DXFILELOADOPTIONS dxfile_options
;
551 DXFILELOADRESOURCE dxfile_resource
;
552 DXFILELOADMEMORY dxfile_memory
;
553 IDirectXFileData
*data_object
;
556 TRACE("(%p)->(%p, %x, %p)\n", iface
, source
, options
, enum_object
);
563 if (options
== D3DXF_FILELOAD_FROMFILE
)
565 dxfile_source
= (void*)source
;
566 dxfile_options
= DXFILELOAD_FROMFILE
;
568 else if (options
== D3DXF_FILELOAD_FROMRESOURCE
)
570 D3DXF_FILELOADRESOURCE
*resource
= (D3DXF_FILELOADRESOURCE
*)source
;
572 dxfile_resource
.hModule
= resource
->hModule
;
573 dxfile_resource
.lpName
= resource
->lpName
;
574 dxfile_resource
.lpType
= resource
->lpType
;
575 dxfile_source
= &dxfile_resource
;
576 dxfile_options
= DXFILELOAD_FROMRESOURCE
;
578 else if (options
== D3DXF_FILELOAD_FROMMEMORY
)
580 D3DXF_FILELOADMEMORY
*memory
= (D3DXF_FILELOADMEMORY
*)source
;
582 dxfile_memory
.lpMemory
= memory
->lpMemory
;
583 dxfile_memory
.dSize
= memory
->dSize
;
584 dxfile_source
= &dxfile_memory
;
585 dxfile_options
= DXFILELOAD_FROMMEMORY
;
589 FIXME("Source type %u is not handled yet\n", options
);
593 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
595 return E_OUTOFMEMORY
;
597 object
->ID3DXFileEnumObject_iface
.lpVtbl
= &ID3DXFileEnumObject_Vtbl
;
600 ret
= IDirectXFile_CreateEnumObject(This
->dxfile
, dxfile_source
, dxfile_options
, &dxfile_enum_object
);
604 HeapFree(GetProcessHeap(), 0, object
);
608 /* Fill enum object with top level data objects */
609 while (SUCCEEDED(ret
= IDirectXFileEnumObject_GetNextDataObject(dxfile_enum_object
, &data_object
)))
611 if (object
->children
)
612 object
->children
= HeapReAlloc(GetProcessHeap(), 0, object
->children
, sizeof(*object
->children
) * (object
->nb_children
+ 1));
614 object
->children
= HeapAlloc(GetProcessHeap(), 0, sizeof(*object
->children
));
615 if (!object
->children
)
620 ret
= ID3DXFileDataImpl_Create((IDirectXFileObject
*)data_object
, &object
->children
[object
->nb_children
]);
623 object
->nb_children
++;
626 IDirectXFileEnumObject_Release(dxfile_enum_object
);
628 if (ret
!= DXFILEERR_NOMOREOBJECTS
)
629 WARN("Cannot get all top level data objects\n");
631 TRACE("Found %u children\n", object
->nb_children
);
633 *enum_object
= &object
->ID3DXFileEnumObject_iface
;
639 static HRESULT WINAPI
ID3DXFileImpl_CreateSaveObject(ID3DXFile
*iface
, const void *data
, D3DXF_FILESAVEOPTIONS options
, D3DXF_FILEFORMAT format
, ID3DXFileSaveObject
**save_object
)
641 FIXME("(%p)->(%p, %x, %u, %p): stub\n", iface
, data
, options
, format
, save_object
);
647 static HRESULT WINAPI
ID3DXFileImpl_RegisterTemplates(ID3DXFile
*iface
, const void *data
, SIZE_T size
)
649 ID3DXFileImpl
*This
= impl_from_ID3DXFile(iface
);
652 TRACE("(%p)->(%p, %lu)\n", iface
, data
, size
);
654 ret
= IDirectXFile_RegisterTemplates(This
->dxfile
, (void*)data
, size
);
655 if (ret
!= DXFILE_OK
)
657 WARN("Error %#x\n", ret
);
658 return error_dxfile_to_d3dxfile(ret
);
665 static HRESULT WINAPI
ID3DXFileImpl_RegisterEnumTemplates(ID3DXFile
*iface
, ID3DXFileEnumObject
*enum_object
)
667 FIXME("(%p)->(%p): stub\n", iface
, enum_object
);
673 static const ID3DXFileVtbl ID3DXFile_Vtbl
=
675 ID3DXFileImpl_QueryInterface
,
676 ID3DXFileImpl_AddRef
,
677 ID3DXFileImpl_Release
,
678 ID3DXFileImpl_CreateEnumObject
,
679 ID3DXFileImpl_CreateSaveObject
,
680 ID3DXFileImpl_RegisterTemplates
,
681 ID3DXFileImpl_RegisterEnumTemplates
684 HRESULT WINAPI
D3DXFileCreate(ID3DXFile
**d3dxfile
)
686 ID3DXFileImpl
*object
;
689 TRACE("(%p)\n", d3dxfile
);
696 object
= HeapAlloc(GetProcessHeap(), 0, sizeof(*object
));
698 return E_OUTOFMEMORY
;
700 ret
= DirectXFileCreate(&object
->dxfile
);
703 HeapFree(GetProcessHeap(), 0, object
);
704 if (ret
== E_OUTOFMEMORY
)
709 object
->ID3DXFile_iface
.lpVtbl
= &ID3DXFile_Vtbl
;
712 *d3dxfile
= &object
->ID3DXFile_iface
;