Release 1.4.1.
[wine] / dlls / d3dxof / d3dxof.c
1 /*
2  * Implementation of DirectX File Interfaces
3  *
4  * Copyright 2004, 2008, 2010 Christian Costa
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/debug.h"
23
24 #define COBJMACROS
25
26 #include "winbase.h"
27 #include "wingdi.h"
28
29 #include "d3dxof_private.h"
30 #include "dxfile.h"
31
32 #include <stdio.h>
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3dxof);
35 WINE_DECLARE_DEBUG_CHANNEL(d3dxof_dump);
36
37 static const struct IDirectXFileVtbl IDirectXFile_Vtbl;
38 static const struct IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl;
39 static const struct IDirectXFileDataVtbl IDirectXFileData_Vtbl;
40 static const struct IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl;
41 static const struct IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl;
42 static const struct IDirectXFileObjectVtbl IDirectXFileObject_Vtbl;
43 static const struct IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl;
44
45 static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj);
46 static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj);
47 static HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj);
48
49 HRESULT IDirectXFileImpl_Create(IUnknown* pUnkOuter, LPVOID* ppObj)
50 {
51     IDirectXFileImpl* object;
52
53     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
54       
55     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileImpl));
56     if (!object)
57     {
58         ERR("Out of memory\n");
59         return DXFILEERR_BADALLOC;
60     }
61
62     object->IDirectXFile_iface.lpVtbl = &IDirectXFile_Vtbl;
63     object->ref = 1;
64
65     *ppObj = &object->IDirectXFile_iface;
66
67     return S_OK;
68 }
69
70 static inline IDirectXFileImpl *impl_from_IDirectXFile(IDirectXFile *iface)
71 {
72     return CONTAINING_RECORD(iface, IDirectXFileImpl, IDirectXFile_iface);
73 }
74
75 /*** IUnknown methods ***/
76 static HRESULT WINAPI IDirectXFileImpl_QueryInterface(IDirectXFile* iface, REFIID riid, void** ppvObject)
77 {
78   IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
79
80   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
81
82   if (IsEqualGUID(riid, &IID_IUnknown)
83       || IsEqualGUID(riid, &IID_IDirectXFile))
84   {
85     IUnknown_AddRef(iface);
86     *ppvObject = &This->IDirectXFile_iface;
87     return S_OK;
88   }
89
90   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
91   return E_NOINTERFACE;
92 }
93
94 static ULONG WINAPI IDirectXFileImpl_AddRef(IDirectXFile* iface)
95 {
96   IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
97   ULONG ref = InterlockedIncrement(&This->ref);
98
99   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
100
101   return ref;
102 }
103
104 static ULONG WINAPI IDirectXFileImpl_Release(IDirectXFile* iface)
105 {
106   IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
107   ULONG ref = InterlockedDecrement(&This->ref);
108
109   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
110
111   if (!ref)
112     HeapFree(GetProcessHeap(), 0, This);
113
114   return ref;
115 }
116
117 /*** IDirectXFile methods ***/
118 static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPVOID pvSource, DXFILELOADOPTIONS dwLoadOptions, LPDIRECTXFILEENUMOBJECT* ppEnumObj)
119 {
120   IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
121   IDirectXFileEnumObjectImpl* object;
122   HRESULT hr;
123   LPBYTE file_buffer;
124   DWORD file_size;
125
126   TRACE("(%p/%p)->(%p,%x,%p)\n", This, iface, pvSource, dwLoadOptions, ppEnumObj);
127
128   if (!ppEnumObj)
129     return DXFILEERR_BADVALUE;
130
131   /* Only lowest 4 bits are relevant in DXFILELOADOPTIONS */
132   dwLoadOptions &= 0xF;
133
134   hr = IDirectXFileEnumObjectImpl_Create(&object);
135   if (FAILED(hr))
136     return hr;
137
138   if (dwLoadOptions == DXFILELOAD_FROMFILE)
139   {
140     HANDLE hFile, file_mapping;
141
142     TRACE("Open source file '%s'\n", (char*)pvSource);
143
144     hFile = CreateFileA(pvSource, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
145     if (hFile == INVALID_HANDLE_VALUE)
146     {
147       TRACE("File '%s' not found\n", (char*)pvSource);
148       return DXFILEERR_FILENOTFOUND;
149     }
150
151     file_size = GetFileSize(hFile, NULL);
152
153     file_mapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
154     CloseHandle(hFile);
155     if (!file_mapping)
156     {
157       hr = DXFILEERR_BADFILETYPE;
158       goto error;
159     }
160
161     object->mapped_memory = MapViewOfFile(file_mapping, FILE_MAP_READ, 0, 0, 0);
162     CloseHandle(file_mapping);
163     if (!object->mapped_memory)
164     {
165       hr = DXFILEERR_BADFILETYPE;
166       goto error;
167     }
168     file_buffer = object->mapped_memory;
169   }
170   else if (dwLoadOptions == DXFILELOAD_FROMRESOURCE)
171   {
172     HRSRC resource_info;
173     HGLOBAL resource_data;
174     LPDXFILELOADRESOURCE lpdxflr = pvSource;
175
176     TRACE("Source in resource (module = %p, name = %s, type = %s\n", lpdxflr->hModule, debugstr_a(lpdxflr->lpName), debugstr_a(lpdxflr->lpType));
177
178     resource_info = FindResourceA(lpdxflr->hModule, lpdxflr->lpName, lpdxflr->lpType);
179     if (!resource_info)
180     {
181       hr = DXFILEERR_RESOURCENOTFOUND;
182       goto error;
183     }
184
185     file_size = SizeofResource(lpdxflr->hModule, resource_info);
186
187     resource_data = LoadResource(lpdxflr->hModule, resource_info);
188     if (!resource_data)
189     {
190       hr = DXFILEERR_BADRESOURCE;
191       goto error;
192     }
193
194     file_buffer = LockResource(resource_data);
195     if (!file_buffer)
196     {
197       hr = DXFILEERR_BADRESOURCE;
198       goto error;
199     }
200   }
201   else if (dwLoadOptions == DXFILELOAD_FROMMEMORY)
202   {
203     LPDXFILELOADMEMORY lpdxflm = pvSource;
204
205     TRACE("Source in memory at %p with size %d\n", lpdxflm->lpMemory, lpdxflm->dSize);
206
207     file_buffer = lpdxflm->lpMemory;
208     file_size = lpdxflm->dSize;
209   }
210   else
211   {
212     FIXME("Source type %d is not handled yet\n", dwLoadOptions);
213     hr = DXFILEERR_NOTDONEYET;
214     goto error;
215   }
216
217   TRACE("File size is %d bytes\n", file_size);
218
219   if (TRACE_ON(d3dxof_dump))
220   {
221     static USHORT num;
222     char tmp[12];
223     HANDLE file;
224     sprintf(tmp, "file%05u.x", num++);
225
226     file = CreateFileA(tmp, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
227     if (file != INVALID_HANDLE_VALUE)
228     {
229       WriteFile(file, file_buffer, file_size, NULL, NULL);
230       CloseHandle(file);
231     }
232   }
233
234   object->pDirectXFile = This;
235
236   object->buf.pdxf = This;
237   object->buf.token_present = FALSE;
238   object->buf.buffer = file_buffer;
239   object->buf.rem_bytes = file_size;
240   hr = parse_header(&object->buf, &object->decomp_buffer);
241   if (FAILED(hr))
242     goto error;
243
244   if (!parse_templates(&object->buf)) {
245     hr = DXFILEERR_BADVALUE;
246     goto error;
247   }
248
249   if (TRACE_ON(d3dxof))
250   {
251     int i;
252     TRACE("Registered templates (%d):\n", This->nb_xtemplates);
253     for (i = 0; i < This->nb_xtemplates; i++)
254       DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
255   }
256
257   *ppEnumObj = &object->IDirectXFileEnumObject_iface;
258
259   return DXFILE_OK;
260
261 error:
262   IDirectXFileEnumObject_Release(&object->IDirectXFileEnumObject_iface);
263   *ppEnumObj = NULL;
264
265   return hr;
266 }
267
268 static HRESULT WINAPI IDirectXFileImpl_CreateSaveObject(IDirectXFile* iface, LPCSTR szFileName, DXFILEFORMAT dwFileFormat, LPDIRECTXFILESAVEOBJECT* ppSaveObj)
269 {
270   IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
271   IDirectXFileSaveObjectImpl *object;
272   HRESULT hr;
273
274   FIXME("(%p/%p)->(%s,%x,%p) partial stub!\n", This, iface, szFileName, dwFileFormat, ppSaveObj);
275
276   if (!szFileName || !ppSaveObj)
277     return E_POINTER;
278
279   hr = IDirectXFileSaveObjectImpl_Create(&object);
280   if (SUCCEEDED(hr))
281     *ppSaveObj = &object->IDirectXFileSaveObject_iface;
282   return hr;
283 }
284
285 static HRESULT WINAPI IDirectXFileImpl_RegisterTemplates(IDirectXFile* iface, LPVOID pvData, DWORD cbSize)
286 {
287   IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
288   parse_buffer buf;
289   HRESULT hr;
290   LPBYTE decomp_buffer = NULL;
291
292   buf.buffer = pvData;
293   buf.rem_bytes = cbSize;
294   buf.txt = FALSE;
295   buf.token_present = FALSE;
296   buf.pdxf = This;
297
298   TRACE("(%p/%p)->(%p,%d)\n", This, iface, pvData, cbSize);
299
300   if (!pvData)
301     return DXFILEERR_BADVALUE;
302
303   if (TRACE_ON(d3dxof_dump))
304   {
305     static USHORT num;
306     char tmp[16];
307     HANDLE file;
308     sprintf(tmp, "template%05u.x", num++);
309
310     file = CreateFileA(tmp, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
311     if (file != INVALID_HANDLE_VALUE)
312     {
313       WriteFile(file, pvData, cbSize, NULL, NULL);
314       CloseHandle(file);
315     }
316   }
317
318   hr = parse_header(&buf, &decomp_buffer);
319   if (FAILED(hr))
320     goto cleanup;
321
322   if (!parse_templates(&buf)) {
323     hr = DXFILEERR_BADVALUE;
324     goto cleanup;
325   }
326
327   if (TRACE_ON(d3dxof))
328   {
329     int i;
330     TRACE("Registered templates (%d):\n", This->nb_xtemplates);
331     for (i = 0; i < This->nb_xtemplates; i++)
332       DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
333   }
334
335   hr = DXFILE_OK;
336 cleanup:
337   HeapFree(GetProcessHeap(), 0, decomp_buffer);
338   return hr;
339 }
340
341 static const IDirectXFileVtbl IDirectXFile_Vtbl =
342 {
343   IDirectXFileImpl_QueryInterface,
344   IDirectXFileImpl_AddRef,
345   IDirectXFileImpl_Release,
346   IDirectXFileImpl_CreateEnumObject,
347   IDirectXFileImpl_CreateSaveObject,
348   IDirectXFileImpl_RegisterTemplates
349 };
350
351 static HRESULT IDirectXFileBinaryImpl_Create(IDirectXFileBinaryImpl** ppObj)
352 {
353     IDirectXFileBinaryImpl* object;
354
355     TRACE("(%p)\n", ppObj);
356
357     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileBinaryImpl));
358     if (!object)
359     {
360         ERR("Out of memory\n");
361         return DXFILEERR_BADALLOC;
362     }
363
364     object->IDirectXFileBinary_iface.lpVtbl = &IDirectXFileBinary_Vtbl;
365     object->ref = 1;
366
367     *ppObj = object;
368
369     return DXFILE_OK;
370 }
371
372 static inline IDirectXFileBinaryImpl *impl_from_IDirectXFileBinary(IDirectXFileBinary *iface)
373 {
374     return CONTAINING_RECORD(iface, IDirectXFileBinaryImpl, IDirectXFileBinary_iface);
375 }
376
377 /*** IUnknown methods ***/
378 static HRESULT WINAPI IDirectXFileBinaryImpl_QueryInterface(IDirectXFileBinary* iface, REFIID riid, void** ppvObject)
379 {
380   IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
381
382   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
383
384   if (IsEqualGUID(riid, &IID_IUnknown)
385       || IsEqualGUID(riid, &IID_IDirectXFileObject)
386       || IsEqualGUID(riid, &IID_IDirectXFileBinary))
387   {
388     IUnknown_AddRef(iface);
389     *ppvObject = &This->IDirectXFileBinary_iface;
390     return S_OK;
391   }
392
393   /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
394   if (!IsEqualGUID(riid, &IID_IDirectXFileData)
395       && !IsEqualGUID(riid, &IID_IDirectXFileDataReference))
396     ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
397
398   return E_NOINTERFACE;
399 }
400
401 static ULONG WINAPI IDirectXFileBinaryImpl_AddRef(IDirectXFileBinary* iface)
402 {
403   IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
404   ULONG ref = InterlockedIncrement(&This->ref);
405
406   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
407
408   return ref;
409 }
410
411 static ULONG WINAPI IDirectXFileBinaryImpl_Release(IDirectXFileBinary* iface)
412 {
413   IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
414   ULONG ref = InterlockedDecrement(&This->ref);
415
416   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
417
418   if (!ref)
419     HeapFree(GetProcessHeap(), 0, This);
420
421   return ref;
422 }
423
424 /*** IDirectXFileObject methods ***/
425 static HRESULT WINAPI IDirectXFileBinaryImpl_GetName(IDirectXFileBinary* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
426
427 {
428   IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
429
430   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
431
432   return DXFILEERR_BADVALUE;
433 }
434
435 static HRESULT WINAPI IDirectXFileBinaryImpl_GetId(IDirectXFileBinary* iface, LPGUID pGuid)
436 {
437   IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
438
439   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
440
441   return DXFILEERR_BADVALUE;
442 }
443
444 /*** IDirectXFileBinary methods ***/
445 static HRESULT WINAPI IDirectXFileBinaryImpl_GetSize(IDirectXFileBinary* iface, DWORD* pcbSize)
446 {
447   IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
448
449   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pcbSize); 
450
451   return DXFILEERR_BADVALUE;
452 }
453
454 static HRESULT WINAPI IDirectXFileBinaryImpl_GetMimeType(IDirectXFileBinary* iface, LPCSTR* pszMimeType)
455 {
456   IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
457
458   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pszMimeType);
459
460   return DXFILEERR_BADVALUE;
461 }
462
463 static HRESULT WINAPI IDirectXFileBinaryImpl_Read(IDirectXFileBinary* iface, LPVOID pvData, DWORD cbSize, LPDWORD pcbRead)
464 {
465   IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
466
467   FIXME("(%p/%p)->(%p, %d, %p) stub!\n", This, iface, pvData, cbSize, pcbRead);
468
469   return DXFILEERR_BADVALUE;
470 }
471
472 static const IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl =
473 {
474     IDirectXFileBinaryImpl_QueryInterface,
475     IDirectXFileBinaryImpl_AddRef,
476     IDirectXFileBinaryImpl_Release,
477     IDirectXFileBinaryImpl_GetName,
478     IDirectXFileBinaryImpl_GetId,
479     IDirectXFileBinaryImpl_GetSize,
480     IDirectXFileBinaryImpl_GetMimeType,
481     IDirectXFileBinaryImpl_Read
482 };
483
484 static HRESULT IDirectXFileDataImpl_Create(IDirectXFileDataImpl** ppObj)
485 {
486     IDirectXFileDataImpl* object;
487
488     TRACE("(%p)\n", ppObj);
489       
490     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataImpl));
491     if (!object)
492     {
493         ERR("Out of memory\n");
494         return DXFILEERR_BADALLOC;
495     }
496
497     object->IDirectXFileData_iface.lpVtbl = &IDirectXFileData_Vtbl;
498     object->ref = 1;
499
500     *ppObj = object;
501     
502     return S_OK;
503 }
504
505 static inline IDirectXFileDataImpl *impl_from_IDirectXFileData(IDirectXFileData *iface)
506 {
507     return CONTAINING_RECORD(iface, IDirectXFileDataImpl, IDirectXFileData_iface);
508 }
509
510 /*** IUnknown methods ***/
511 static HRESULT WINAPI IDirectXFileDataImpl_QueryInterface(IDirectXFileData* iface, REFIID riid, void** ppvObject)
512 {
513   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
514
515   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
516
517   if (IsEqualGUID(riid, &IID_IUnknown)
518       || IsEqualGUID(riid, &IID_IDirectXFileObject)
519       || IsEqualGUID(riid, &IID_IDirectXFileData))
520   {
521     IUnknown_AddRef(iface);
522     *ppvObject = &This->IDirectXFileData_iface;
523     return S_OK;
524   }
525
526   /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
527   if (!IsEqualGUID(riid, &IID_IDirectXFileBinary)
528       && !IsEqualGUID(riid, &IID_IDirectXFileDataReference))
529     ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
530
531   return E_NOINTERFACE;
532 }
533
534 static ULONG WINAPI IDirectXFileDataImpl_AddRef(IDirectXFileData* iface)
535 {
536   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
537   ULONG ref = InterlockedIncrement(&This->ref);
538
539   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
540
541   return ref;
542 }
543
544 static ULONG WINAPI IDirectXFileDataImpl_Release(IDirectXFileData* iface)
545 {
546   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
547   ULONG ref = InterlockedDecrement(&This->ref);
548
549   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
550
551   if (!ref)
552   {
553     if (!This->level && !This->from_ref)
554     {
555       HeapFree(GetProcessHeap(), 0, This->pstrings);
556       if (This->pobj)
557       {
558         HeapFree(GetProcessHeap(), 0, This->pobj->pdata);
559         HeapFree(GetProcessHeap(), 0, This->pobj);
560       }
561     }
562     HeapFree(GetProcessHeap(), 0, This);
563   }
564
565   return ref;
566 }
567
568 /*** IDirectXFileObject methods ***/
569 static HRESULT WINAPI IDirectXFileDataImpl_GetName(IDirectXFileData* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
570 {
571   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
572   DWORD len;
573
574   TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
575
576   if (!pdwBufLen)
577     return DXFILEERR_BADVALUE;
578
579   len = strlen(This->pobj->name);
580   if (len)
581     len++;
582
583   if (pstrNameBuf) {
584     if (*pdwBufLen < len)
585       return DXFILEERR_BADVALUE;
586     CopyMemory(pstrNameBuf, This->pobj->name, len);
587   }
588   *pdwBufLen = len;
589
590   return DXFILE_OK;
591 }
592
593 static HRESULT WINAPI IDirectXFileDataImpl_GetId(IDirectXFileData* iface, LPGUID pGuid)
594 {
595   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
596
597   TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
598
599   if (!pGuid)
600     return DXFILEERR_BADVALUE;
601
602   memcpy(pGuid, &This->pobj->class_id, 16);
603
604   return DXFILE_OK;
605 }
606
607 /*** IDirectXFileData methods ***/
608 static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCSTR szMember, DWORD* pcbSize, void** ppvData)
609 {
610   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
611
612   TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_a(szMember), pcbSize, ppvData);
613
614   if (!pcbSize || !ppvData)
615     return DXFILEERR_BADVALUE;
616
617   if (szMember)
618   {
619     int i;
620     for (i = 0; i < This->pobj->nb_members; i++)
621       if (!strcmp(This->pobj->members[i].name, szMember))
622         break;
623     if (i == This->pobj->nb_members)
624     {
625       WARN("Unknown member '%s'\n", szMember);
626       return DXFILEERR_BADDATAREFERENCE;
627     }
628     *pcbSize = This->pobj->members[i].size;
629     *ppvData = This->pobj->root->pdata + This->pobj->members[i].start;
630   }
631   else
632   {
633     *pcbSize = This->pobj->size;
634     *ppvData = This->pobj->root->pdata + This->pobj->pos_data;
635   }
636
637   return DXFILE_OK;
638 }
639
640 static HRESULT WINAPI IDirectXFileDataImpl_GetType(IDirectXFileData* iface, const GUID** pguid)
641 {
642   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
643   static GUID guid;
644
645   TRACE("(%p/%p)->(%p)\n", This, iface, pguid);
646
647   if (!pguid)
648     return DXFILEERR_BADVALUE;
649
650   memcpy(&guid, &This->pobj->type, 16);
651   *pguid = &guid;
652
653   return DXFILE_OK;
654 }
655
656 static HRESULT WINAPI IDirectXFileDataImpl_GetNextObject(IDirectXFileData* iface, LPDIRECTXFILEOBJECT* ppChildObj)
657 {
658   HRESULT hr;
659   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
660
661   TRACE("(%p/%p)->(%p)\n", This, iface, ppChildObj);
662
663   if (This->cur_enum_object >= This->pobj->nb_children)
664     return DXFILEERR_NOMOREOBJECTS;
665
666   if (This->from_ref && (This->level >= 1))
667   {
668     /* Only 2 levels can be enumerated if the object is obtained from a reference */
669     return DXFILEERR_NOMOREOBJECTS;
670   }
671
672   if (This->pobj->children[This->cur_enum_object]->binary)
673   {
674     IDirectXFileBinaryImpl *object;
675
676     hr = IDirectXFileBinaryImpl_Create(&object);
677     if (FAILED(hr))
678       return hr;
679
680     *ppChildObj = (LPDIRECTXFILEOBJECT)&object->IDirectXFileBinary_iface;
681   }
682   else if (This->pobj->children[This->cur_enum_object]->ptarget)
683   {
684     IDirectXFileDataReferenceImpl *object;
685
686     hr = IDirectXFileDataReferenceImpl_Create(&object);
687     if (FAILED(hr))
688       return hr;
689
690     object->ptarget = This->pobj->children[This->cur_enum_object++]->ptarget;
691
692     *ppChildObj = (LPDIRECTXFILEOBJECT)&object->IDirectXFileDataReference_iface;
693   }
694   else
695   {
696     IDirectXFileDataImpl *object;
697
698     hr = IDirectXFileDataImpl_Create(&object);
699     if (FAILED(hr))
700       return hr;
701
702     object->pobj = This->pobj->children[This->cur_enum_object++];
703     object->cur_enum_object = 0;
704     object->from_ref = This->from_ref;
705     object->level = This->level + 1;
706
707     *ppChildObj = (LPDIRECTXFILEOBJECT)&object->IDirectXFileData_iface;
708   }
709
710   return DXFILE_OK;
711 }
712
713 static HRESULT WINAPI IDirectXFileDataImpl_AddDataObject(IDirectXFileData* iface, LPDIRECTXFILEDATA pDataObj)
714 {
715   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
716
717   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pDataObj); 
718
719   return DXFILEERR_BADVALUE;
720 }
721
722 static HRESULT WINAPI IDirectXFileDataImpl_AddDataReference(IDirectXFileData* iface, LPCSTR szRef, const GUID* pguidRef)
723 {
724   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
725
726   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szRef, pguidRef); 
727
728   return DXFILEERR_BADVALUE;
729 }
730
731 static HRESULT WINAPI IDirectXFileDataImpl_AddBinaryObject(IDirectXFileData* iface, LPCSTR szName, const GUID* pguid, LPCSTR szMimeType, LPVOID pvData, DWORD cbSize)
732 {
733   IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
734
735   FIXME("(%p/%p)->(%s,%p,%s,%p,%d) stub!\n", This, iface, szName, pguid, szMimeType, pvData, cbSize);
736
737   return DXFILEERR_BADVALUE;
738 }
739
740 static const IDirectXFileDataVtbl IDirectXFileData_Vtbl =
741 {
742     IDirectXFileDataImpl_QueryInterface,
743     IDirectXFileDataImpl_AddRef,
744     IDirectXFileDataImpl_Release,
745     IDirectXFileDataImpl_GetName,
746     IDirectXFileDataImpl_GetId,
747     IDirectXFileDataImpl_GetData,
748     IDirectXFileDataImpl_GetType,
749     IDirectXFileDataImpl_GetNextObject,
750     IDirectXFileDataImpl_AddDataObject,
751     IDirectXFileDataImpl_AddDataReference,
752     IDirectXFileDataImpl_AddBinaryObject
753 };
754
755 static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj)
756 {
757     IDirectXFileDataReferenceImpl* object;
758
759     TRACE("(%p)\n", ppObj);
760       
761     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataReferenceImpl));
762     if (!object)
763     {
764         ERR("Out of memory\n");
765         return DXFILEERR_BADALLOC;
766     }
767
768     object->IDirectXFileDataReference_iface.lpVtbl = &IDirectXFileDataReference_Vtbl;
769     object->ref = 1;
770
771     *ppObj = object;
772     
773     return S_OK;
774 }
775
776 static inline IDirectXFileDataReferenceImpl *impl_from_IDirectXFileDataReference(IDirectXFileDataReference *iface)
777 {
778     return CONTAINING_RECORD(iface, IDirectXFileDataReferenceImpl, IDirectXFileDataReference_iface);
779 }
780
781 /*** IUnknown methods ***/
782 static HRESULT WINAPI IDirectXFileDataReferenceImpl_QueryInterface(IDirectXFileDataReference* iface, REFIID riid, void** ppvObject)
783 {
784   IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
785
786   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
787
788   if (IsEqualGUID(riid, &IID_IUnknown)
789       || IsEqualGUID(riid, &IID_IDirectXFileObject)
790       || IsEqualGUID(riid, &IID_IDirectXFileDataReference))
791   {
792     IUnknown_AddRef(iface);
793     *ppvObject = &This->IDirectXFileDataReference_iface;
794     return S_OK;
795   }
796
797   /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
798   if (!IsEqualGUID(riid, &IID_IDirectXFileData)
799       && !IsEqualGUID(riid, &IID_IDirectXFileBinary))
800     ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
801
802   return E_NOINTERFACE;
803 }
804
805 static ULONG WINAPI IDirectXFileDataReferenceImpl_AddRef(IDirectXFileDataReference* iface)
806 {
807   IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
808   ULONG ref = InterlockedIncrement(&This->ref);
809
810   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
811
812   return ref;
813 }
814
815 static ULONG WINAPI IDirectXFileDataReferenceImpl_Release(IDirectXFileDataReference* iface)
816 {
817   IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
818   ULONG ref = InterlockedDecrement(&This->ref);
819
820   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
821
822   if (!ref)
823     HeapFree(GetProcessHeap(), 0, This);
824
825   return ref;
826 }
827
828 /*** IDirectXFileObject methods ***/
829 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetName(IDirectXFileDataReference* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
830 {
831   IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
832   DWORD len;
833
834   TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
835
836   if (!pdwBufLen)
837     return DXFILEERR_BADVALUE;
838
839   len = strlen(This->ptarget->name);
840   if (len)
841     len++;
842
843   if (pstrNameBuf) {
844     if (*pdwBufLen < len)
845       return DXFILEERR_BADVALUE;
846     CopyMemory(pstrNameBuf, This->ptarget->name, len);
847   }
848   *pdwBufLen = len;
849
850   return DXFILE_OK;
851 }
852
853 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetId(IDirectXFileDataReference* iface, LPGUID pGuid)
854 {
855   IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
856
857   TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
858
859   if (!pGuid)
860     return DXFILEERR_BADVALUE;
861
862   memcpy(pGuid, &This->ptarget->class_id, 16);
863
864   return DXFILE_OK;
865 }
866
867 /*** IDirectXFileDataReference ***/
868 static HRESULT WINAPI IDirectXFileDataReferenceImpl_Resolve(IDirectXFileDataReference* iface, LPDIRECTXFILEDATA* ppDataObj)
869 {
870   IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
871   IDirectXFileDataImpl *object;
872   HRESULT hr;
873
874   TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
875
876   if (!ppDataObj)
877     return DXFILEERR_BADVALUE;
878
879   hr = IDirectXFileDataImpl_Create(&object);
880   if (FAILED(hr))
881     return hr;
882
883   object->pobj = This->ptarget;
884   object->cur_enum_object = 0;
885   object->level = 0;
886   object->from_ref = TRUE;
887
888   *ppDataObj = (LPDIRECTXFILEDATA)object;
889
890   return DXFILE_OK;
891 }
892
893 static const IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl =
894 {
895     IDirectXFileDataReferenceImpl_QueryInterface,
896     IDirectXFileDataReferenceImpl_AddRef,
897     IDirectXFileDataReferenceImpl_Release,
898     IDirectXFileDataReferenceImpl_GetName,
899     IDirectXFileDataReferenceImpl_GetId,
900     IDirectXFileDataReferenceImpl_Resolve
901 };
902
903 static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj)
904 {
905     IDirectXFileEnumObjectImpl* object;
906
907     TRACE("(%p)\n", ppObj);
908       
909     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileEnumObjectImpl));
910     if (!object)
911     {
912         ERR("Out of memory\n");
913         return DXFILEERR_BADALLOC;
914     }
915
916     object->IDirectXFileEnumObject_iface.lpVtbl = &IDirectXFileEnumObject_Vtbl;
917     object->ref = 1;
918
919     *ppObj = object;
920     
921     return S_OK;
922 }
923
924 static inline IDirectXFileEnumObjectImpl *impl_from_IDirectXFileEnumObject(IDirectXFileEnumObject *iface)
925 {
926     return CONTAINING_RECORD(iface, IDirectXFileEnumObjectImpl, IDirectXFileEnumObject_iface);
927 }
928
929 /*** IUnknown methods ***/
930 static HRESULT WINAPI IDirectXFileEnumObjectImpl_QueryInterface(IDirectXFileEnumObject* iface, REFIID riid, void** ppvObject)
931 {
932   IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
933
934   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
935
936   if (IsEqualGUID(riid, &IID_IUnknown)
937       || IsEqualGUID(riid, &IID_IDirectXFileEnumObject))
938   {
939     IUnknown_AddRef(iface);
940     *ppvObject = &This->IDirectXFileEnumObject_iface;
941     return S_OK;
942   }
943
944   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
945   return E_NOINTERFACE;
946 }
947
948 static ULONG WINAPI IDirectXFileEnumObjectImpl_AddRef(IDirectXFileEnumObject* iface)
949 {
950   IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
951   ULONG ref = InterlockedIncrement(&This->ref);
952
953   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
954
955   return ref;
956 }
957
958 static ULONG WINAPI IDirectXFileEnumObjectImpl_Release(IDirectXFileEnumObject* iface)
959 {
960   IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
961   ULONG ref = InterlockedDecrement(&This->ref);
962
963   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
964
965   if (!ref)
966   {
967     int i;
968     for (i = 0; i < This->nb_xobjects; i++)
969       IDirectXFileData_Release(This->pRefObjects[i]);
970     if (This->mapped_memory)
971       UnmapViewOfFile(This->mapped_memory);
972     HeapFree(GetProcessHeap(), 0, This->decomp_buffer);
973     HeapFree(GetProcessHeap(), 0, This);
974   }
975
976   return ref;
977 }
978
979 /*** IDirectXFileEnumObject methods ***/
980 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetNextDataObject(IDirectXFileEnumObject* iface, LPDIRECTXFILEDATA* ppDataObj)
981 {
982   IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
983   IDirectXFileDataImpl* object;
984   HRESULT hr;
985
986   TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
987
988   if (This->nb_xobjects >= MAX_OBJECTS)
989   {
990     ERR("Too many objects\n");
991     *ppDataObj = NULL;
992     return DXFILEERR_NOMOREOBJECTS;
993   }
994
995   /* Check if there are templates defined before the object */
996   if (!parse_templates(&This->buf))
997   {
998     hr = DXFILEERR_BADVALUE;
999     goto error;
1000   }
1001
1002   if (!This->buf.rem_bytes)
1003   {
1004     *ppDataObj = NULL;
1005     return DXFILEERR_NOMOREOBJECTS;
1006   }
1007
1008   hr = IDirectXFileDataImpl_Create(&object);
1009   if (FAILED(hr))
1010     return hr;
1011
1012   object->pobj = HeapAlloc(GetProcessHeap(), 0, sizeof(xobject)*MAX_SUBOBJECTS);
1013   if (!object->pobj)
1014   {
1015     ERR("Out of memory\n");
1016     hr = DXFILEERR_BADALLOC;
1017     goto error;
1018   }
1019
1020   object->pstrings = HeapAlloc(GetProcessHeap(), 0, MAX_STRINGS_BUFFER);
1021   if (!object->pstrings)
1022   {
1023     ERR("Out of memory\n");
1024     hr = DXFILEERR_BADALLOC;
1025     goto error;
1026   }
1027
1028   object->cur_enum_object = 0;
1029   object->level = 0;
1030   object->from_ref = FALSE;
1031
1032   This->buf.pxo_globals = This->xobjects;
1033   This->buf.nb_pxo_globals = This->nb_xobjects;
1034   This->buf.level = 0;
1035   This->buf.pdata = NULL;
1036   This->buf.capacity = 0;
1037   This->buf.cur_pos_data = 0;
1038   This->buf.cur_pstrings = This->buf.pstrings = object->pstrings;
1039   This->buf.pxo = This->xobjects[This->nb_xobjects] = This->buf.pxo_tab = object->pobj;
1040   This->buf.pxo->pdata = NULL;
1041   This->buf.pxo->nb_subobjects = 1;
1042
1043   if (!parse_object(&This->buf))
1044   {
1045     WARN("Object is not correct\n");
1046     hr = DXFILEERR_PARSEERROR;
1047     goto error;
1048   }
1049
1050   *ppDataObj = (LPDIRECTXFILEDATA)object;
1051
1052   /* Get a reference to created object */
1053   This->pRefObjects[This->nb_xobjects] = (LPDIRECTXFILEDATA)object;
1054   IDirectXFileData_AddRef(This->pRefObjects[This->nb_xobjects]);
1055
1056   This->nb_xobjects++;
1057
1058   return DXFILE_OK;
1059
1060 error:
1061
1062   IDirectXFileData_Release(&object->IDirectXFileData_iface);
1063   *ppDataObj = NULL;
1064
1065   return hr;
1066 }
1067
1068 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectById(IDirectXFileEnumObject* iface, REFGUID rguid, LPDIRECTXFILEDATA* ppDataObj)
1069 {
1070   IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
1071
1072   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, rguid, ppDataObj); 
1073
1074   return DXFILEERR_BADVALUE;
1075 }
1076
1077 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectByName(IDirectXFileEnumObject* iface, LPCSTR szName, LPDIRECTXFILEDATA* ppDataObj)
1078 {
1079   IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
1080
1081   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szName, ppDataObj); 
1082
1083   return DXFILEERR_BADVALUE;
1084 }
1085
1086 static const IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl =
1087 {
1088     IDirectXFileEnumObjectImpl_QueryInterface,
1089     IDirectXFileEnumObjectImpl_AddRef,
1090     IDirectXFileEnumObjectImpl_Release,
1091     IDirectXFileEnumObjectImpl_GetNextDataObject,
1092     IDirectXFileEnumObjectImpl_GetDataObjectById,
1093     IDirectXFileEnumObjectImpl_GetDataObjectByName
1094 };
1095
1096 static HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj)
1097 {
1098     IDirectXFileSaveObjectImpl* object;
1099
1100     TRACE("(%p)\n", ppObj);
1101
1102     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileSaveObjectImpl));
1103     if (!object)
1104     {
1105         ERR("Out of memory\n");
1106         return DXFILEERR_BADALLOC;
1107     }
1108
1109     object->IDirectXFileSaveObject_iface.lpVtbl = &IDirectXFileSaveObject_Vtbl;
1110     object->ref = 1;
1111
1112     *ppObj = object;
1113
1114     return S_OK;
1115 }
1116
1117 static inline IDirectXFileSaveObjectImpl *impl_from_IDirectXFileSaveObject(IDirectXFileSaveObject *iface)
1118 {
1119     return CONTAINING_RECORD(iface, IDirectXFileSaveObjectImpl, IDirectXFileSaveObject_iface);
1120 }
1121
1122 /*** IUnknown methods ***/
1123 static HRESULT WINAPI IDirectXFileSaveObjectImpl_QueryInterface(IDirectXFileSaveObject* iface, REFIID riid, void** ppvObject)
1124 {
1125   IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1126
1127   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1128
1129   if (IsEqualGUID(riid, &IID_IUnknown)
1130       || IsEqualGUID(riid, &IID_IDirectXFileSaveObject))
1131   {
1132     IUnknown_AddRef(iface);
1133     *ppvObject = &This->IDirectXFileSaveObject_iface;
1134     return S_OK;
1135   }
1136
1137   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1138   return E_NOINTERFACE;
1139 }
1140
1141 static ULONG WINAPI IDirectXFileSaveObjectImpl_AddRef(IDirectXFileSaveObject* iface)
1142 {
1143   IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1144   ULONG ref = InterlockedIncrement(&This->ref);
1145
1146   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1147
1148   return ref;
1149 }
1150
1151 static ULONG WINAPI IDirectXFileSaveObjectImpl_Release(IDirectXFileSaveObject* iface)
1152 {
1153   IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1154   ULONG ref = InterlockedDecrement(&This->ref);
1155
1156   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1157
1158   if (!ref)
1159     HeapFree(GetProcessHeap(), 0, This);
1160
1161   return ref;
1162 }
1163
1164 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveTemplates(IDirectXFileSaveObject* iface, DWORD cTemplates, const GUID** ppguidTemplates)
1165 {
1166   IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1167
1168   FIXME("(%p/%p)->(%d,%p) stub!\n", This, iface, cTemplates, ppguidTemplates);
1169
1170   return DXFILEERR_BADVALUE;
1171 }
1172
1173 static HRESULT WINAPI IDirectXFileSaveObjectImpl_CreateDataObject(IDirectXFileSaveObject* iface, REFGUID rguidTemplate, LPCSTR szName, const GUID* pguid, DWORD cbSize, LPVOID pvData, LPDIRECTXFILEDATA* ppDataObj)
1174 {
1175   IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1176
1177   FIXME("(%p/%p)->(%p,%s,%p,%d,%p,%p) stub!\n", This, iface, rguidTemplate, szName, pguid, cbSize, pvData, ppDataObj);
1178
1179   return DXFILEERR_BADVALUE;
1180 }
1181
1182 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveData(IDirectXFileSaveObject* iface, LPDIRECTXFILEDATA ppDataObj)
1183 {
1184   IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1185
1186   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj); 
1187
1188   return DXFILEERR_BADVALUE;
1189 }
1190
1191 static const IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl =
1192 {
1193     IDirectXFileSaveObjectImpl_QueryInterface,
1194     IDirectXFileSaveObjectImpl_AddRef,
1195     IDirectXFileSaveObjectImpl_Release,
1196     IDirectXFileSaveObjectImpl_SaveTemplates,
1197     IDirectXFileSaveObjectImpl_CreateDataObject,
1198     IDirectXFileSaveObjectImpl_SaveData
1199 };