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