d3dx9_36: Implement ID3DXFileDataImpl_GetName.
[wine] / dlls / 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 "wine/debug.h"
21
22 #include "d3dx9.h"
23 #include "d3dx9xof.h"
24 #undef MAKE_DDHRESULT
25 #include "dxfile.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
28
29 static HRESULT error_dxfile_to_d3dxfile(HRESULT error)
30 {
31     switch (error)
32     {
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         default:
42             FIXME("Cannot map error %#x\n", error);
43             return E_FAIL;
44     }
45 }
46
47 typedef struct {
48     ID3DXFile ID3DXFile_iface;
49     LONG ref;
50     IDirectXFile *dxfile;
51 } ID3DXFileImpl;
52
53 typedef struct {
54     ID3DXFileEnumObject ID3DXFileEnumObject_iface;
55     LONG ref;
56     ULONG nb_children;
57     ID3DXFileData **children;
58 } ID3DXFileEnumObjectImpl;
59
60 typedef struct {
61     ID3DXFileData ID3DXFileData_iface;
62     LONG ref;
63     IDirectXFileData *dxfile_data;
64 } ID3DXFileDataImpl;
65
66
67 static inline ID3DXFileImpl* impl_from_ID3DXFile(ID3DXFile *iface)
68 {
69     return CONTAINING_RECORD(iface, ID3DXFileImpl, ID3DXFile_iface);
70 }
71
72 static inline ID3DXFileEnumObjectImpl* impl_from_ID3DXFileEnumObject(ID3DXFileEnumObject *iface)
73 {
74     return CONTAINING_RECORD(iface, ID3DXFileEnumObjectImpl, ID3DXFileEnumObject_iface);
75 }
76
77 static inline ID3DXFileDataImpl* impl_from_ID3DXFileData(ID3DXFileData *iface)
78 {
79     return CONTAINING_RECORD(iface, ID3DXFileDataImpl, ID3DXFileData_iface);
80 }
81
82 /*** IUnknown methods ***/
83
84 static HRESULT WINAPI ID3DXFileDataImpl_QueryInterface(ID3DXFileData *iface, REFIID riid, void **ret_iface)
85 {
86     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface);
87
88     if (IsEqualGUID(riid, &IID_IUnknown) ||
89         IsEqualGUID(riid, &IID_ID3DXFileData))
90     {
91         iface->lpVtbl->AddRef(iface);
92         *ret_iface = iface;
93         return S_OK;
94     }
95
96     WARN("(%p)->(%s, %p), not found\n", iface, debugstr_guid(riid), ret_iface);
97     *ret_iface = NULL;
98     return E_NOINTERFACE;
99 }
100
101 static ULONG WINAPI ID3DXFileDataImpl_AddRef(ID3DXFileData *iface)
102 {
103     ID3DXFileDataImpl *This = impl_from_ID3DXFileData(iface);
104     ULONG ref = InterlockedIncrement(&This->ref);
105
106     TRACE("(%p)->(): new ref = %u\n", iface, ref);
107
108     return ref;
109 }
110
111 static ULONG WINAPI ID3DXFileDataImpl_Release(ID3DXFileData *iface)
112 {
113     ID3DXFileDataImpl *This = impl_from_ID3DXFileData(iface);
114     ULONG ref = InterlockedDecrement(&This->ref);
115
116     TRACE("(%p)->(): new ref = %u\n", iface, ref);
117
118     if (!ref)
119     {
120         IDirectXFileData_Release(This->dxfile_data);
121         HeapFree(GetProcessHeap(), 0, This);
122     }
123
124     return ref;
125 }
126
127
128 /*** ID3DXFileData methods ***/
129
130 static HRESULT WINAPI ID3DXFileDataImpl_GetEnum(ID3DXFileData *iface, ID3DXFileEnumObject **enum_object)
131 {
132     FIXME("(%p)->(%p): stub\n", iface, enum_object);
133
134     return E_NOTIMPL;
135 }
136
137
138 static HRESULT WINAPI ID3DXFileDataImpl_GetName(ID3DXFileData *iface, char *name, SIZE_T *size)
139 {
140     ID3DXFileDataImpl *This = impl_from_ID3DXFileData(iface);
141     DWORD dxfile_size;
142     HRESULT ret;
143
144     TRACE("(%p)->(%p, %p)\n", iface, name, size);
145
146     if (!name || !size)
147         return E_POINTER;
148
149     dxfile_size = *size;
150
151     ret = IDirectXFileData_GetName(This->dxfile_data, name, &dxfile_size);
152     if (ret != DXFILE_OK)
153         return error_dxfile_to_d3dxfile(ret);
154
155     *size = dxfile_size;
156
157     return S_OK;
158 }
159
160
161 static HRESULT WINAPI ID3DXFileDataImpl_GetId(ID3DXFileData *iface, GUID *guid)
162 {
163     FIXME("(%p)->(%p): stub\n", iface, guid);
164
165     return E_NOTIMPL;
166 }
167
168
169 static HRESULT WINAPI ID3DXFileDataImpl_Lock(ID3DXFileData *iface, SIZE_T *size, const void **data)
170 {
171     FIXME("(%p)->(%p, %p): stub\n", iface, size, data);
172
173     return E_NOTIMPL;
174 }
175
176
177 static HRESULT WINAPI ID3DXFileDataImpl_Unlock(ID3DXFileData *iface)
178 {
179     FIXME("(%p)->(): stub\n", iface);
180
181     return E_NOTIMPL;
182 }
183
184
185 static HRESULT WINAPI ID3DXFileDataImpl_GetType(ID3DXFileData *iface, GUID *guid)
186 {
187     ID3DXFileDataImpl *This = impl_from_ID3DXFileData(iface);
188     const GUID *dxfile_guid;
189     HRESULT ret;
190
191     TRACE("(%p)->(%p)\n", iface, guid);
192
193     ret = IDirectXFileData_GetType(This->dxfile_data, &dxfile_guid);
194     if (ret != DXFILE_OK)
195         return error_dxfile_to_d3dxfile(ret);
196
197     *guid = *dxfile_guid;
198
199     return S_OK;
200 }
201
202
203 static BOOL WINAPI ID3DXFileDataImpl_IsReference(ID3DXFileData *iface)
204 {
205     TRACE("(%p)->(): stub\n", iface);
206
207     return E_NOTIMPL;
208 }
209
210
211 static HRESULT WINAPI ID3DXFileDataImpl_GetChildren(ID3DXFileData *iface, SIZE_T *children)
212 {
213     TRACE("(%p)->(%p): stub\n", iface, children);
214
215     return E_NOTIMPL;
216 }
217
218
219 static HRESULT WINAPI ID3DXFileDataImpl_GetChild(ID3DXFileData *iface, SIZE_T id, ID3DXFileData **object)
220 {
221     TRACE("(%p)->(%lu, %p): stub\n", iface, id, object);
222
223     return E_NOTIMPL;
224 }
225
226
227 static const ID3DXFileDataVtbl ID3DXFileData_Vtbl =
228 {
229     ID3DXFileDataImpl_QueryInterface,
230     ID3DXFileDataImpl_AddRef,
231     ID3DXFileDataImpl_Release,
232     ID3DXFileDataImpl_GetEnum,
233     ID3DXFileDataImpl_GetName,
234     ID3DXFileDataImpl_GetId,
235     ID3DXFileDataImpl_Lock,
236     ID3DXFileDataImpl_Unlock,
237     ID3DXFileDataImpl_GetType,
238     ID3DXFileDataImpl_IsReference,
239     ID3DXFileDataImpl_GetChildren,
240     ID3DXFileDataImpl_GetChild
241 };
242
243
244 static HRESULT ID3DXFileDataImpl_Create(IDirectXFileData *dxfile_data, ID3DXFileData **ret_iface)
245 {
246     ID3DXFileDataImpl *object;
247
248     TRACE("(%p, %p)\n", dxfile_data, ret_iface);
249
250     *ret_iface = NULL;
251
252     object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
253     if (!object)
254         return E_OUTOFMEMORY;
255
256     object->ID3DXFileData_iface.lpVtbl = &ID3DXFileData_Vtbl;
257     object->ref = 1;
258     object->dxfile_data = dxfile_data;
259
260     *ret_iface = &object->ID3DXFileData_iface;
261
262     return S_OK;
263 }
264
265
266 /*** IUnknown methods ***/
267
268 static HRESULT WINAPI ID3DXFileEnumObjectImpl_QueryInterface(ID3DXFileEnumObject *iface, REFIID riid, void **ret_iface)
269 {
270     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface);
271
272     if (IsEqualGUID(riid, &IID_IUnknown) ||
273         IsEqualGUID(riid, &IID_ID3DXFileEnumObject))
274     {
275         iface->lpVtbl->AddRef(iface);
276         *ret_iface = iface;
277         return S_OK;
278     }
279
280     WARN("(%p)->(%s, %p), not found\n", iface, debugstr_guid(riid), ret_iface);
281     *ret_iface = NULL;
282     return E_NOINTERFACE;
283 }
284
285 static ULONG WINAPI ID3DXFileEnumObjectImpl_AddRef(ID3DXFileEnumObject *iface)
286 {
287     ID3DXFileEnumObjectImpl *This = impl_from_ID3DXFileEnumObject(iface);
288     ULONG ref = InterlockedIncrement(&This->ref);
289
290     TRACE("(%p)->(): new ref = %u\n", iface, ref);
291
292     return ref;
293 }
294
295 static ULONG WINAPI ID3DXFileEnumObjectImpl_Release(ID3DXFileEnumObject *iface)
296 {
297     ID3DXFileEnumObjectImpl *This = impl_from_ID3DXFileEnumObject(iface);
298     ULONG ref = InterlockedDecrement(&This->ref);
299
300     TRACE("(%p)->(): new ref = %u\n", iface, ref);
301
302     if (!ref)
303     {
304         ULONG i;
305
306         for (i = 0; i < This->nb_children; i++)
307             (This->children[i])->lpVtbl->Release(This->children[i]);
308         HeapFree(GetProcessHeap(), 0, This->children);
309         HeapFree(GetProcessHeap(), 0, This);
310     }
311
312     return ref;
313 }
314
315
316 /*** ID3DXFileEnumObject methods ***/
317
318 static HRESULT WINAPI ID3DXFileEnumObjectImpl_GetFile(ID3DXFileEnumObject *iface, ID3DXFile **file)
319 {
320     FIXME("(%p)->(%p): stub\n", iface, file);
321
322     return E_NOTIMPL;
323 }
324
325
326 static HRESULT WINAPI ID3DXFileEnumObjectImpl_GetChildren(ID3DXFileEnumObject *iface, SIZE_T *children)
327 {
328     ID3DXFileEnumObjectImpl *This = impl_from_ID3DXFileEnumObject(iface);
329
330     TRACE("(%p)->(%p)\n", iface, children);
331
332     if (!children)
333         return E_POINTER;
334
335     *children = This->nb_children;
336
337     return S_OK;
338 }
339
340
341 static HRESULT WINAPI ID3DXFileEnumObjectImpl_GetChild(ID3DXFileEnumObject *iface, SIZE_T id, ID3DXFileData **object)
342 {
343     ID3DXFileEnumObjectImpl *This = impl_from_ID3DXFileEnumObject(iface);
344
345     TRACE("(%p)->(%lu, %p)\n", iface, id, object);
346
347     if (!object)
348         return E_POINTER;
349
350     *object = This->children[id];
351     (*object)->lpVtbl->AddRef(*object);
352
353     return S_OK;
354 }
355
356
357 static HRESULT WINAPI ID3DXFileEnumObjectImpl_GetDataObjectById(ID3DXFileEnumObject *iface, REFGUID guid, ID3DXFileData **object)
358 {
359     FIXME("(%p)->(%s, %p): stub\n", iface, debugstr_guid(guid), object);
360
361     return E_NOTIMPL;
362 }
363
364
365 static HRESULT WINAPI ID3DXFileEnumObjectImpl_GetDataObjectByName(ID3DXFileEnumObject *iface, const char *name, ID3DXFileData **object)
366 {
367     FIXME("(%p)->(%s, %p): stub\n", iface, debugstr_a(name), object);
368
369     return E_NOTIMPL;
370 }
371
372
373 static const ID3DXFileEnumObjectVtbl ID3DXFileEnumObject_Vtbl =
374 {
375     ID3DXFileEnumObjectImpl_QueryInterface,
376     ID3DXFileEnumObjectImpl_AddRef,
377     ID3DXFileEnumObjectImpl_Release,
378     ID3DXFileEnumObjectImpl_GetFile,
379     ID3DXFileEnumObjectImpl_GetChildren,
380     ID3DXFileEnumObjectImpl_GetChild,
381     ID3DXFileEnumObjectImpl_GetDataObjectById,
382     ID3DXFileEnumObjectImpl_GetDataObjectByName
383 };
384
385
386 /*** IUnknown methods ***/
387
388 static HRESULT WINAPI ID3DXFileImpl_QueryInterface(ID3DXFile *iface, REFIID riid, void **ret_iface)
389 {
390     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface);
391
392     if (IsEqualGUID(riid, &IID_IUnknown) ||
393         IsEqualGUID(riid, &IID_ID3DXFile))
394     {
395         iface->lpVtbl->AddRef(iface);
396         *ret_iface = iface;
397         return S_OK;
398     }
399
400     WARN("(%p)->(%s, %p), not found\n", iface, debugstr_guid(riid), ret_iface);
401     *ret_iface = NULL;
402     return E_NOINTERFACE;
403 }
404
405
406 static ULONG WINAPI ID3DXFileImpl_AddRef(ID3DXFile *iface)
407 {
408     ID3DXFileImpl *This = impl_from_ID3DXFile(iface);
409     ULONG ref = InterlockedIncrement(&This->ref);
410
411     TRACE("(%p)->(): new ref = %u\n", iface, ref);
412
413     return ref;
414 }
415
416
417 static ULONG WINAPI ID3DXFileImpl_Release(ID3DXFile *iface)
418 {
419     ID3DXFileImpl *This = impl_from_ID3DXFile(iface);
420     ULONG ref = InterlockedDecrement(&This->ref);
421
422     TRACE("(%p)->(): new ref = %u\n", iface, ref);
423
424     if (!ref)
425     {
426         IDirectXFile_Release(This->dxfile);
427         HeapFree(GetProcessHeap(), 0, This);
428     }
429
430     return ref;
431 }
432
433
434 /*** ID3DXFile methods ***/
435
436 static HRESULT WINAPI ID3DXFileImpl_CreateEnumObject(ID3DXFile *iface, const void *source, D3DXF_FILELOADOPTIONS options, ID3DXFileEnumObject **enum_object)
437 {
438     ID3DXFileImpl *This = impl_from_ID3DXFile(iface);
439     ID3DXFileEnumObjectImpl *object;
440     IDirectXFileEnumObject *dxfile_enum_object;
441     void *dxfile_source;
442     DXFILELOADOPTIONS dxfile_options;
443     DXFILELOADRESOURCE dxfile_resource;
444     DXFILELOADMEMORY dxfile_memory;
445     IDirectXFileData *data_object;
446     HRESULT ret;
447
448     TRACE("(%p)->(%p, %x, %p)\n", iface, source, options, enum_object);
449
450     if (!enum_object)
451         return E_POINTER;
452
453     *enum_object = NULL;
454
455     if (options == D3DXF_FILELOAD_FROMFILE)
456     {
457         dxfile_source = (void*)source;
458         dxfile_options = DXFILELOAD_FROMFILE;
459     }
460     else if (options == D3DXF_FILELOAD_FROMRESOURCE)
461     {
462         D3DXF_FILELOADRESOURCE *resource = (D3DXF_FILELOADRESOURCE*)source;
463
464         dxfile_resource.hModule = resource->hModule;
465         dxfile_resource.lpName = resource->lpName;
466         dxfile_resource.lpType = resource->lpType;
467         dxfile_source = &dxfile_resource;
468         dxfile_options = DXFILELOAD_FROMRESOURCE;
469     }
470     else if (options == D3DXF_FILELOAD_FROMMEMORY)
471     {
472         D3DXF_FILELOADMEMORY *memory = (D3DXF_FILELOADMEMORY*)source;
473
474         dxfile_memory.lpMemory = memory->lpMemory;
475         dxfile_memory.dSize = memory->dSize;
476         dxfile_source = &dxfile_memory;
477         dxfile_options = DXFILELOAD_FROMMEMORY;
478     }
479     else
480     {
481         FIXME("Source type %u is not handled yet\n", options);
482         return E_NOTIMPL;
483     }
484
485     object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
486     if (!object)
487         return E_OUTOFMEMORY;
488
489     object->ID3DXFileEnumObject_iface.lpVtbl = &ID3DXFileEnumObject_Vtbl;
490     object->ref = 1;
491
492     ret = IDirectXFile_CreateEnumObject(This->dxfile, dxfile_source, dxfile_options, &dxfile_enum_object);
493
494     if (ret != S_OK)
495     {
496         HeapFree(GetProcessHeap(), 0, object);
497         return ret;
498     }
499
500     /* Fill enum object with top level data objects */
501     while (SUCCEEDED(ret = IDirectXFileEnumObject_GetNextDataObject(dxfile_enum_object, &data_object)))
502     {
503         if (object->children)
504             object->children = HeapReAlloc(GetProcessHeap(), 0, object->children, sizeof(*object->children) * (object->nb_children + 1));
505         else
506             object->children = HeapAlloc(GetProcessHeap(), 0, sizeof(*object->children));
507         if (!object->children)
508         {
509             ret = E_OUTOFMEMORY;
510             break;
511         }
512         ret = ID3DXFileDataImpl_Create(data_object, &object->children[object->nb_children]);
513         if (ret != S_OK)
514             break;
515         object->nb_children++;
516     }
517
518     IDirectXFileEnumObject_Release(dxfile_enum_object);
519
520     if (ret != DXFILEERR_NOMOREOBJECTS)
521         WARN("Cannot get all top level data objects\n");
522
523     TRACE("Found %u children\n", object->nb_children);
524
525     *enum_object = &object->ID3DXFileEnumObject_iface;
526
527     return S_OK;
528 }
529
530
531 static HRESULT WINAPI ID3DXFileImpl_CreateSaveObject(ID3DXFile *iface, const void *data, D3DXF_FILESAVEOPTIONS options, D3DXF_FILEFORMAT format, ID3DXFileSaveObject **save_object)
532 {
533     FIXME("(%p)->(%p, %x, %u, %p): stub\n", iface, data, options, format, save_object);
534
535     return E_NOTIMPL;
536 }
537
538
539 static HRESULT WINAPI ID3DXFileImpl_RegisterTemplates(ID3DXFile *iface, const void *data, SIZE_T size)
540 {
541     ID3DXFileImpl *This = impl_from_ID3DXFile(iface);
542     HRESULT ret;
543
544     TRACE("(%p)->(%p, %lu)\n", iface, data, size);
545
546     ret = IDirectXFile_RegisterTemplates(This->dxfile, (void*)data, size);
547     if (ret != DXFILE_OK)
548     {
549         WARN("Error %#x\n", ret);
550         return error_dxfile_to_d3dxfile(ret);
551     }
552
553     return S_OK;
554 }
555
556
557 static HRESULT WINAPI ID3DXFileImpl_RegisterEnumTemplates(ID3DXFile *iface, ID3DXFileEnumObject *enum_object)
558 {
559     FIXME("(%p)->(%p): stub\n", iface, enum_object);
560
561     return E_NOTIMPL;
562 }
563
564
565 static const ID3DXFileVtbl ID3DXFile_Vtbl =
566 {
567     ID3DXFileImpl_QueryInterface,
568     ID3DXFileImpl_AddRef,
569     ID3DXFileImpl_Release,
570     ID3DXFileImpl_CreateEnumObject,
571     ID3DXFileImpl_CreateSaveObject,
572     ID3DXFileImpl_RegisterTemplates,
573     ID3DXFileImpl_RegisterEnumTemplates
574 };
575
576 HRESULT WINAPI D3DXFileCreate(ID3DXFile **d3dxfile)
577 {
578     ID3DXFileImpl *object;
579     HRESULT ret;
580
581     TRACE("(%p)\n", d3dxfile);
582
583     if (!d3dxfile)
584         return E_POINTER;
585
586     *d3dxfile = NULL;
587
588     object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
589     if (!object)
590         return E_OUTOFMEMORY;
591
592     ret = DirectXFileCreate(&object->dxfile);
593     if (ret != S_OK)
594     {
595         HeapFree(GetProcessHeap(), 0, object);
596         if (ret == E_OUTOFMEMORY)
597             return ret;
598         return E_FAIL;
599     }
600
601     object->ID3DXFile_iface.lpVtbl = &ID3DXFile_Vtbl;
602     object->ref = 1;
603
604     *d3dxfile = &object->ID3DXFile_iface;
605
606     return S_OK;
607 }