winhttp/tests: Fix a test failure on some W2K/XP systems.
[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 && !This->from_ref)
632     {
633       HeapFree(GetProcessHeap(), 0, This->pstrings);
634       HeapFree(GetProcessHeap(), 0, This->pobj->pdata);
635       HeapFree(GetProcessHeap(), 0, This->pobj);
636     }
637     HeapFree(GetProcessHeap(), 0, This);
638   }
639
640   return ref;
641 }
642
643 /*** IDirectXFileObject methods ***/
644 static HRESULT WINAPI IDirectXFileDataImpl_GetName(IDirectXFileData* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
645
646 {
647   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
648
649   TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
650
651   if (!pstrNameBuf)
652     return DXFILEERR_BADVALUE;
653
654   strcpy(pstrNameBuf, This->pobj->name);
655
656   return DXFILE_OK;
657 }
658
659 static HRESULT WINAPI IDirectXFileDataImpl_GetId(IDirectXFileData* iface, LPGUID pGuid)
660 {
661   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
662
663   TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
664
665   if (!pGuid)
666     return DXFILEERR_BADVALUE;
667
668   memcpy(pGuid, &This->pobj->class_id, 16);
669
670   return DXFILE_OK;
671 }
672
673 /*** IDirectXFileData methods ***/
674 static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCSTR szMember, DWORD* pcbSize, void** ppvData)
675 {
676   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
677
678   TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, szMember, pcbSize, ppvData);
679
680   if (!pcbSize || !ppvData)
681     return DXFILEERR_BADVALUE;
682
683   if (szMember)
684   {
685     FIXME("Specifying a member is not supported yet!\n");
686     return DXFILEERR_BADVALUE;
687   }
688
689   *pcbSize = This->pobj->size;
690   *ppvData = This->pobj->root->pdata + This->pobj->pos_data;
691
692   return DXFILE_OK;
693 }
694
695 static HRESULT WINAPI IDirectXFileDataImpl_GetType(IDirectXFileData* iface, const GUID** pguid)
696 {
697   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
698   static GUID guid;
699
700   TRACE("(%p/%p)->(%p)\n", This, iface, pguid);
701
702   if (!pguid)
703     return DXFILEERR_BADVALUE;
704
705   memcpy(&guid, &This->pobj->type, 16);
706   *pguid = &guid;
707
708   return DXFILE_OK;
709 }
710
711 static HRESULT WINAPI IDirectXFileDataImpl_GetNextObject(IDirectXFileData* iface, LPDIRECTXFILEOBJECT* ppChildObj)
712 {
713   HRESULT hr;
714   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
715
716   TRACE("(%p/%p)->(%p)\n", This, iface, ppChildObj);
717
718   if (This->cur_enum_object >= This->pobj->nb_childs)
719     return DXFILEERR_NOMOREOBJECTS;
720
721   if (This->from_ref && (This->level >= 1))
722   {
723     /* Only 2 levels can enumerated if the object is obtained from a reference */
724     return DXFILEERR_NOMOREOBJECTS;
725   }
726
727   if (This->pobj->childs[This->cur_enum_object]->binary)
728   {
729     IDirectXFileBinaryImpl *object;
730
731     hr = IDirectXFileBinaryImpl_Create(&object);
732     if (FAILED(hr))
733       return hr;
734
735     *ppChildObj = (LPDIRECTXFILEOBJECT)object;
736   }
737   else if (This->pobj->childs[This->cur_enum_object]->ptarget)
738   {
739     IDirectXFileDataReferenceImpl *object;
740
741     hr = IDirectXFileDataReferenceImpl_Create(&object);
742     if (FAILED(hr))
743       return hr;
744
745     object->ptarget = This->pobj->childs[This->cur_enum_object++]->ptarget;
746
747     *ppChildObj = (LPDIRECTXFILEOBJECT)object;
748   }
749   else
750   {
751     IDirectXFileDataImpl *object;
752
753     hr = IDirectXFileDataImpl_Create(&object);
754     if (FAILED(hr))
755       return hr;
756
757     object->pobj = This->pobj->childs[This->cur_enum_object++];
758     object->cur_enum_object = 0;
759     object->from_ref = This->from_ref;
760     object->level = This->level + 1;
761
762     *ppChildObj = (LPDIRECTXFILEOBJECT)object;
763   }
764
765   return DXFILE_OK;
766 }
767
768 static HRESULT WINAPI IDirectXFileDataImpl_AddDataObject(IDirectXFileData* iface, LPDIRECTXFILEDATA pDataObj)
769 {
770   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
771
772   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pDataObj); 
773
774   return DXFILEERR_BADVALUE;
775 }
776
777 static HRESULT WINAPI IDirectXFileDataImpl_AddDataReference(IDirectXFileData* iface, LPCSTR szRef, const GUID* pguidRef)
778 {
779   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
780
781   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szRef, pguidRef); 
782
783   return DXFILEERR_BADVALUE;
784 }
785
786 static HRESULT WINAPI IDirectXFileDataImpl_AddBinaryObject(IDirectXFileData* iface, LPCSTR szName, const GUID* pguid, LPCSTR szMimeType, LPVOID pvData, DWORD cbSize)
787 {
788   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
789
790   FIXME("(%p/%p)->(%s,%p,%s,%p,%d) stub!\n", This, iface, szName, pguid, szMimeType, pvData, cbSize);
791
792   return DXFILEERR_BADVALUE;
793 }
794
795 static const IDirectXFileDataVtbl IDirectXFileData_Vtbl =
796 {
797     IDirectXFileDataImpl_QueryInterface,
798     IDirectXFileDataImpl_AddRef,
799     IDirectXFileDataImpl_Release,
800     IDirectXFileDataImpl_GetName,
801     IDirectXFileDataImpl_GetId,
802     IDirectXFileDataImpl_GetData,
803     IDirectXFileDataImpl_GetType,
804     IDirectXFileDataImpl_GetNextObject,
805     IDirectXFileDataImpl_AddDataObject,
806     IDirectXFileDataImpl_AddDataReference,
807     IDirectXFileDataImpl_AddBinaryObject
808 };
809
810 static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj)
811 {
812     IDirectXFileDataReferenceImpl* object;
813
814     TRACE("(%p)\n", ppObj);
815       
816     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataReferenceImpl));
817     if (!object)
818     {
819         ERR("Out of memory\n");
820         return DXFILEERR_BADALLOC;
821     }
822     
823     object->lpVtbl.lpVtbl = &IDirectXFileDataReference_Vtbl;
824     object->ref = 1;
825
826     *ppObj = object;
827     
828     return S_OK;
829 }
830
831 /*** IUnknown methods ***/
832 static HRESULT WINAPI IDirectXFileDataReferenceImpl_QueryInterface(IDirectXFileDataReference* iface, REFIID riid, void** ppvObject)
833 {
834   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
835
836   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
837
838   if (IsEqualGUID(riid, &IID_IUnknown)
839       || IsEqualGUID(riid, &IID_IDirectXFileObject)
840       || IsEqualGUID(riid, &IID_IDirectXFileDataReference))
841   {
842     IClassFactory_AddRef(iface);
843     *ppvObject = This;
844     return S_OK;
845   }
846
847   /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
848   if (!IsEqualGUID(riid, &IID_IDirectXFileData)
849       && !IsEqualGUID(riid, &IID_IDirectXFileBinary))
850     ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
851
852   return E_NOINTERFACE;
853 }
854
855 static ULONG WINAPI IDirectXFileDataReferenceImpl_AddRef(IDirectXFileDataReference* iface)
856 {
857   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
858   ULONG ref = InterlockedIncrement(&This->ref);
859
860   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
861
862   return ref;
863 }
864
865 static ULONG WINAPI IDirectXFileDataReferenceImpl_Release(IDirectXFileDataReference* iface)
866 {
867   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
868   ULONG ref = InterlockedDecrement(&This->ref);
869
870   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
871
872   if (!ref)
873     HeapFree(GetProcessHeap(), 0, This);
874
875   return ref;
876 }
877
878 /*** IDirectXFileObject methods ***/
879 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetName(IDirectXFileDataReference* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
880 {
881   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
882
883   TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
884
885   if (!pstrNameBuf)
886     return DXFILEERR_BADVALUE;
887
888   strcpy(pstrNameBuf, This->ptarget->name);
889
890   return DXFILEERR_BADVALUE;
891 }
892
893 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetId(IDirectXFileDataReference* iface, LPGUID pGuid)
894 {
895   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
896
897   TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
898
899   if (!pGuid)
900     return DXFILEERR_BADVALUE;
901
902   memcpy(pGuid, &This->ptarget->class_id, 16);
903
904   return DXFILE_OK;
905 }
906
907 /*** IDirectXFileDataReference ***/
908 static HRESULT WINAPI IDirectXFileDataReferenceImpl_Resolve(IDirectXFileDataReference* iface, LPDIRECTXFILEDATA* ppDataObj)
909 {
910   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
911   IDirectXFileDataImpl *object;
912   HRESULT hr;
913
914   TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
915
916   if (!ppDataObj)
917     return DXFILEERR_BADVALUE;
918
919   hr = IDirectXFileDataImpl_Create(&object);
920   if (FAILED(hr))
921     return hr;
922
923   object->pobj = This->ptarget;
924   object->cur_enum_object = 0;
925   object->level = 0;
926   object->from_ref = TRUE;
927
928   *ppDataObj = (LPDIRECTXFILEDATA)object;
929
930   return DXFILE_OK;
931 }
932
933 static const IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl =
934 {
935     IDirectXFileDataReferenceImpl_QueryInterface,
936     IDirectXFileDataReferenceImpl_AddRef,
937     IDirectXFileDataReferenceImpl_Release,
938     IDirectXFileDataReferenceImpl_GetName,
939     IDirectXFileDataReferenceImpl_GetId,
940     IDirectXFileDataReferenceImpl_Resolve
941 };
942
943 static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj)
944 {
945     IDirectXFileEnumObjectImpl* object;
946
947     TRACE("(%p)\n", ppObj);
948       
949     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileEnumObjectImpl));
950     if (!object)
951     {
952         ERR("Out of memory\n");
953         return DXFILEERR_BADALLOC;
954     }
955     
956     object->lpVtbl.lpVtbl = &IDirectXFileEnumObject_Vtbl;
957     object->ref = 1;
958
959     *ppObj = object;
960     
961     return S_OK;
962 }
963
964 /*** IUnknown methods ***/
965 static HRESULT WINAPI IDirectXFileEnumObjectImpl_QueryInterface(IDirectXFileEnumObject* iface, REFIID riid, void** ppvObject)
966 {
967   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
968
969   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
970
971   if (IsEqualGUID(riid, &IID_IUnknown)
972       || IsEqualGUID(riid, &IID_IDirectXFileEnumObject))
973   {
974     IClassFactory_AddRef(iface);
975     *ppvObject = This;
976     return S_OK;
977   }
978
979   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
980   return E_NOINTERFACE;
981 }
982
983 static ULONG WINAPI IDirectXFileEnumObjectImpl_AddRef(IDirectXFileEnumObject* iface)
984 {
985   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
986   ULONG ref = InterlockedIncrement(&This->ref);
987
988   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
989
990   return ref;
991 }
992
993 static ULONG WINAPI IDirectXFileEnumObjectImpl_Release(IDirectXFileEnumObject* iface)
994 {
995   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
996   ULONG ref = InterlockedDecrement(&This->ref);
997
998   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
999
1000   if (!ref)
1001   {
1002     int i;
1003     for (i = 0; i < This->nb_xobjects; i++)
1004       IDirectXFileData_Release(This->pRefObjects[i]);
1005     if (This->source == DXFILELOAD_FROMFILE)
1006     {
1007       UnmapViewOfFile(This->buffer);
1008       CloseHandle(This->file_mapping);
1009       CloseHandle(This->hFile);
1010     }
1011     else if (This->source == DXFILELOAD_FROMRESOURCE)
1012       FreeResource(This->resource_data);
1013     HeapFree(GetProcessHeap(), 0, This);
1014   }
1015
1016   return ref;
1017 }
1018
1019 /*** IDirectXFileEnumObject methods ***/
1020 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetNextDataObject(IDirectXFileEnumObject* iface, LPDIRECTXFILEDATA* ppDataObj)
1021 {
1022   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1023   IDirectXFileDataImpl* object;
1024   HRESULT hr;
1025   LPBYTE pstrings = NULL;
1026
1027   TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
1028
1029   if (This->nb_xobjects >= MAX_OBJECTS)
1030   {
1031     ERR("Too many objects\n");
1032     return DXFILEERR_NOMOREOBJECTS;
1033   }
1034
1035   if (!This->buf.rem_bytes)
1036     return DXFILEERR_NOMOREOBJECTS;
1037
1038   hr = IDirectXFileDataImpl_Create(&object);
1039   if (FAILED(hr))
1040     return hr;
1041
1042   This->buf.pxo_globals = This->xobjects;
1043   This->buf.nb_pxo_globals = This->nb_xobjects;
1044   This->buf.cur_subobject = 1;
1045   This->buf.level = 0;
1046
1047   This->buf.pxo_tab = HeapAlloc(GetProcessHeap(), 0, sizeof(xobject)*MAX_SUBOBJECTS);
1048   if (!This->buf.pxo_tab)
1049   {
1050     ERR("Out of memory\n");
1051     hr = DXFILEERR_BADALLOC;
1052     goto error;
1053   }
1054   This->buf.pxo = This->xobjects[This->nb_xobjects] = This->buf.pxo_tab;
1055
1056   This->buf.pxo->pdata = This->buf.pdata = NULL;
1057   This->buf.capacity = 0;
1058   This->buf.cur_pos_data = 0;
1059
1060   pstrings = HeapAlloc(GetProcessHeap(), 0, MAX_STRINGS_BUFFER);
1061   if (!pstrings)
1062   {
1063     ERR("Out of memory\n");
1064     hr = DXFILEERR_BADALLOC;
1065     goto error;
1066   }
1067   This->buf.cur_pstrings = This->buf.pstrings = object->pstrings = pstrings;
1068
1069   if (!parse_object(&This->buf))
1070   {
1071     TRACE("Object is not correct\n");
1072     hr = DXFILEERR_PARSEERROR;
1073     goto error;
1074   }
1075
1076   This->buf.pxo->nb_subobjects = This->buf.cur_subobject;
1077   if (This->buf.cur_subobject > MAX_SUBOBJECTS)
1078   {
1079     FIXME("Too many suobjects %d\n", This->buf.cur_subobject);
1080     hr = DXFILEERR_BADALLOC;
1081     goto error;
1082   }
1083
1084   object->pstrings = pstrings;
1085   object->pobj = This->buf.pxo;
1086   object->cur_enum_object = 0;
1087   object->level = 0;
1088   object->from_ref = FALSE;
1089
1090   *ppDataObj = (LPDIRECTXFILEDATA)object;
1091
1092   /* Get a reference to created object */
1093   This->pRefObjects[This->nb_xobjects] = (LPDIRECTXFILEDATA)object;
1094   IDirectXFileData_AddRef(This->pRefObjects[This->nb_xobjects]);
1095
1096   This->nb_xobjects++;
1097
1098   return DXFILE_OK;
1099
1100 error:
1101
1102   HeapFree(GetProcessHeap(), 0, This->buf.pxo_tab);
1103   HeapFree(GetProcessHeap(), 0, This->buf.pxo->pdata);
1104   HeapFree(GetProcessHeap(), 0, pstrings);
1105
1106   return hr;
1107 }
1108
1109 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectById(IDirectXFileEnumObject* iface, REFGUID rguid, LPDIRECTXFILEDATA* ppDataObj)
1110 {
1111   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1112
1113   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, rguid, ppDataObj); 
1114
1115   return DXFILEERR_BADVALUE;
1116 }
1117
1118 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectByName(IDirectXFileEnumObject* iface, LPCSTR szName, LPDIRECTXFILEDATA* ppDataObj)
1119 {
1120   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1121
1122   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szName, ppDataObj); 
1123
1124   return DXFILEERR_BADVALUE;
1125 }
1126
1127 static const IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl =
1128 {
1129     IDirectXFileEnumObjectImpl_QueryInterface,
1130     IDirectXFileEnumObjectImpl_AddRef,
1131     IDirectXFileEnumObjectImpl_Release,
1132     IDirectXFileEnumObjectImpl_GetNextDataObject,
1133     IDirectXFileEnumObjectImpl_GetDataObjectById,
1134     IDirectXFileEnumObjectImpl_GetDataObjectByName
1135 };
1136
1137 static HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj)
1138 {
1139     IDirectXFileSaveObjectImpl* object;
1140
1141     TRACE("(%p)\n", ppObj);
1142
1143     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileSaveObjectImpl));
1144     if (!object)
1145     {
1146         ERR("Out of memory\n");
1147         return DXFILEERR_BADALLOC;
1148     }
1149
1150     object->lpVtbl.lpVtbl = &IDirectXFileSaveObject_Vtbl;
1151     object->ref = 1;
1152
1153     *ppObj = object;
1154
1155     return S_OK;
1156 }
1157
1158 /*** IUnknown methods ***/
1159 static HRESULT WINAPI IDirectXFileSaveObjectImpl_QueryInterface(IDirectXFileSaveObject* iface, REFIID riid, void** ppvObject)
1160 {
1161   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1162
1163   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1164
1165   if (IsEqualGUID(riid, &IID_IUnknown)
1166       || IsEqualGUID(riid, &IID_IDirectXFileSaveObject))
1167   {
1168     IClassFactory_AddRef(iface);
1169     *ppvObject = This;
1170     return S_OK;
1171   }
1172
1173   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1174   return E_NOINTERFACE;
1175 }
1176
1177 static ULONG WINAPI IDirectXFileSaveObjectImpl_AddRef(IDirectXFileSaveObject* iface)
1178 {
1179   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1180   ULONG ref = InterlockedIncrement(&This->ref);
1181
1182   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1183
1184   return ref;
1185 }
1186
1187 static ULONG WINAPI IDirectXFileSaveObjectImpl_Release(IDirectXFileSaveObject* iface)
1188 {
1189   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1190   ULONG ref = InterlockedDecrement(&This->ref);
1191
1192   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1193
1194   if (!ref)
1195     HeapFree(GetProcessHeap(), 0, This);
1196
1197   return ref;
1198 }
1199
1200 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveTemplates(IDirectXFileSaveObject* iface, DWORD cTemplates, const GUID** ppguidTemplates)
1201 {
1202   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1203
1204   FIXME("(%p/%p)->(%d,%p) stub!\n", This, iface, cTemplates, ppguidTemplates);
1205
1206   return DXFILEERR_BADVALUE;
1207 }
1208
1209 static HRESULT WINAPI IDirectXFileSaveObjectImpl_CreateDataObject(IDirectXFileSaveObject* iface, REFGUID rguidTemplate, LPCSTR szName, const GUID* pguid, DWORD cbSize, LPVOID pvData, LPDIRECTXFILEDATA* ppDataObj)
1210 {
1211   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1212
1213   FIXME("(%p/%p)->(%p,%s,%p,%d,%p,%p) stub!\n", This, iface, rguidTemplate, szName, pguid, cbSize, pvData, ppDataObj);
1214
1215   return DXFILEERR_BADVALUE;
1216 }
1217
1218 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveData(IDirectXFileSaveObject* iface, LPDIRECTXFILEDATA ppDataObj)
1219 {
1220   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1221
1222   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj); 
1223
1224   return DXFILEERR_BADVALUE;
1225 }
1226
1227 static const IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl =
1228 {
1229     IDirectXFileSaveObjectImpl_QueryInterface,
1230     IDirectXFileSaveObjectImpl_AddRef,
1231     IDirectXFileSaveObjectImpl_Release,
1232     IDirectXFileSaveObjectImpl_SaveTemplates,
1233     IDirectXFileSaveObjectImpl_CreateDataObject,
1234     IDirectXFileSaveObjectImpl_SaveData
1235 };