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