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