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