mmdevapi/tests: Add tests for IAudioClient::GetCurrentPadding.
[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 static 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   DWORD len;
732
733   TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
734
735   if (!pdwBufLen)
736     return DXFILEERR_BADVALUE;
737
738   len = strlen(This->pobj->name);
739   if (len)
740     len++;
741
742   if (pstrNameBuf) {
743     if (*pdwBufLen < len)
744       return DXFILEERR_BADVALUE;
745     CopyMemory(pstrNameBuf, This->pobj->name, len);
746   }
747   *pdwBufLen = len;
748
749   return DXFILE_OK;
750 }
751
752 static HRESULT WINAPI IDirectXFileDataImpl_GetId(IDirectXFileData* iface, LPGUID pGuid)
753 {
754   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
755
756   TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
757
758   if (!pGuid)
759     return DXFILEERR_BADVALUE;
760
761   memcpy(pGuid, &This->pobj->class_id, 16);
762
763   return DXFILE_OK;
764 }
765
766 /*** IDirectXFileData methods ***/
767 static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCSTR szMember, DWORD* pcbSize, void** ppvData)
768 {
769   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
770
771   TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, szMember, pcbSize, ppvData);
772
773   if (!pcbSize || !ppvData)
774     return DXFILEERR_BADVALUE;
775
776   if (szMember)
777   {
778     FIXME("Specifying a member is not supported yet!\n");
779     return DXFILEERR_BADVALUE;
780   }
781
782   *pcbSize = This->pobj->size;
783   *ppvData = This->pobj->root->pdata + This->pobj->pos_data;
784
785   return DXFILE_OK;
786 }
787
788 static HRESULT WINAPI IDirectXFileDataImpl_GetType(IDirectXFileData* iface, const GUID** pguid)
789 {
790   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
791   static GUID guid;
792
793   TRACE("(%p/%p)->(%p)\n", This, iface, pguid);
794
795   if (!pguid)
796     return DXFILEERR_BADVALUE;
797
798   memcpy(&guid, &This->pobj->type, 16);
799   *pguid = &guid;
800
801   return DXFILE_OK;
802 }
803
804 static HRESULT WINAPI IDirectXFileDataImpl_GetNextObject(IDirectXFileData* iface, LPDIRECTXFILEOBJECT* ppChildObj)
805 {
806   HRESULT hr;
807   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
808
809   TRACE("(%p/%p)->(%p)\n", This, iface, ppChildObj);
810
811   if (This->cur_enum_object >= This->pobj->nb_childs)
812     return DXFILEERR_NOMOREOBJECTS;
813
814   if (This->from_ref && (This->level >= 1))
815   {
816     /* Only 2 levels can be enumerated if the object is obtained from a reference */
817     return DXFILEERR_NOMOREOBJECTS;
818   }
819
820   if (This->pobj->childs[This->cur_enum_object]->binary)
821   {
822     IDirectXFileBinaryImpl *object;
823
824     hr = IDirectXFileBinaryImpl_Create(&object);
825     if (FAILED(hr))
826       return hr;
827
828     *ppChildObj = (LPDIRECTXFILEOBJECT)object;
829   }
830   else if (This->pobj->childs[This->cur_enum_object]->ptarget)
831   {
832     IDirectXFileDataReferenceImpl *object;
833
834     hr = IDirectXFileDataReferenceImpl_Create(&object);
835     if (FAILED(hr))
836       return hr;
837
838     object->ptarget = This->pobj->childs[This->cur_enum_object++]->ptarget;
839
840     *ppChildObj = (LPDIRECTXFILEOBJECT)object;
841   }
842   else
843   {
844     IDirectXFileDataImpl *object;
845
846     hr = IDirectXFileDataImpl_Create(&object);
847     if (FAILED(hr))
848       return hr;
849
850     object->pobj = This->pobj->childs[This->cur_enum_object++];
851     object->cur_enum_object = 0;
852     object->from_ref = This->from_ref;
853     object->level = This->level + 1;
854
855     *ppChildObj = (LPDIRECTXFILEOBJECT)object;
856   }
857
858   return DXFILE_OK;
859 }
860
861 static HRESULT WINAPI IDirectXFileDataImpl_AddDataObject(IDirectXFileData* iface, LPDIRECTXFILEDATA pDataObj)
862 {
863   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
864
865   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pDataObj); 
866
867   return DXFILEERR_BADVALUE;
868 }
869
870 static HRESULT WINAPI IDirectXFileDataImpl_AddDataReference(IDirectXFileData* iface, LPCSTR szRef, const GUID* pguidRef)
871 {
872   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
873
874   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szRef, pguidRef); 
875
876   return DXFILEERR_BADVALUE;
877 }
878
879 static HRESULT WINAPI IDirectXFileDataImpl_AddBinaryObject(IDirectXFileData* iface, LPCSTR szName, const GUID* pguid, LPCSTR szMimeType, LPVOID pvData, DWORD cbSize)
880 {
881   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
882
883   FIXME("(%p/%p)->(%s,%p,%s,%p,%d) stub!\n", This, iface, szName, pguid, szMimeType, pvData, cbSize);
884
885   return DXFILEERR_BADVALUE;
886 }
887
888 static const IDirectXFileDataVtbl IDirectXFileData_Vtbl =
889 {
890     IDirectXFileDataImpl_QueryInterface,
891     IDirectXFileDataImpl_AddRef,
892     IDirectXFileDataImpl_Release,
893     IDirectXFileDataImpl_GetName,
894     IDirectXFileDataImpl_GetId,
895     IDirectXFileDataImpl_GetData,
896     IDirectXFileDataImpl_GetType,
897     IDirectXFileDataImpl_GetNextObject,
898     IDirectXFileDataImpl_AddDataObject,
899     IDirectXFileDataImpl_AddDataReference,
900     IDirectXFileDataImpl_AddBinaryObject
901 };
902
903 static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj)
904 {
905     IDirectXFileDataReferenceImpl* object;
906
907     TRACE("(%p)\n", ppObj);
908       
909     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataReferenceImpl));
910     if (!object)
911     {
912         ERR("Out of memory\n");
913         return DXFILEERR_BADALLOC;
914     }
915     
916     object->lpVtbl = &IDirectXFileDataReference_Vtbl;
917     object->ref = 1;
918
919     *ppObj = object;
920     
921     return S_OK;
922 }
923
924 /*** IUnknown methods ***/
925 static HRESULT WINAPI IDirectXFileDataReferenceImpl_QueryInterface(IDirectXFileDataReference* iface, REFIID riid, void** ppvObject)
926 {
927   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
928
929   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
930
931   if (IsEqualGUID(riid, &IID_IUnknown)
932       || IsEqualGUID(riid, &IID_IDirectXFileObject)
933       || IsEqualGUID(riid, &IID_IDirectXFileDataReference))
934   {
935     IUnknown_AddRef(iface);
936     *ppvObject = This;
937     return S_OK;
938   }
939
940   /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
941   if (!IsEqualGUID(riid, &IID_IDirectXFileData)
942       && !IsEqualGUID(riid, &IID_IDirectXFileBinary))
943     ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
944
945   return E_NOINTERFACE;
946 }
947
948 static ULONG WINAPI IDirectXFileDataReferenceImpl_AddRef(IDirectXFileDataReference* iface)
949 {
950   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
951   ULONG ref = InterlockedIncrement(&This->ref);
952
953   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
954
955   return ref;
956 }
957
958 static ULONG WINAPI IDirectXFileDataReferenceImpl_Release(IDirectXFileDataReference* iface)
959 {
960   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
961   ULONG ref = InterlockedDecrement(&This->ref);
962
963   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
964
965   if (!ref)
966     HeapFree(GetProcessHeap(), 0, This);
967
968   return ref;
969 }
970
971 /*** IDirectXFileObject methods ***/
972 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetName(IDirectXFileDataReference* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
973 {
974   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
975   DWORD len;
976
977   TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
978
979   if (!pdwBufLen)
980     return DXFILEERR_BADVALUE;
981
982   len = strlen(This->ptarget->name);
983   if (len)
984     len++;
985
986   if (pstrNameBuf) {
987     if (*pdwBufLen < len)
988       return DXFILEERR_BADVALUE;
989     CopyMemory(pstrNameBuf, This->ptarget->name, len);
990   }
991   *pdwBufLen = len;
992
993   return DXFILE_OK;
994 }
995
996 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetId(IDirectXFileDataReference* iface, LPGUID pGuid)
997 {
998   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
999
1000   TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
1001
1002   if (!pGuid)
1003     return DXFILEERR_BADVALUE;
1004
1005   memcpy(pGuid, &This->ptarget->class_id, 16);
1006
1007   return DXFILE_OK;
1008 }
1009
1010 /*** IDirectXFileDataReference ***/
1011 static HRESULT WINAPI IDirectXFileDataReferenceImpl_Resolve(IDirectXFileDataReference* iface, LPDIRECTXFILEDATA* ppDataObj)
1012 {
1013   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1014   IDirectXFileDataImpl *object;
1015   HRESULT hr;
1016
1017   TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
1018
1019   if (!ppDataObj)
1020     return DXFILEERR_BADVALUE;
1021
1022   hr = IDirectXFileDataImpl_Create(&object);
1023   if (FAILED(hr))
1024     return hr;
1025
1026   object->pobj = This->ptarget;
1027   object->cur_enum_object = 0;
1028   object->level = 0;
1029   object->from_ref = TRUE;
1030
1031   *ppDataObj = (LPDIRECTXFILEDATA)object;
1032
1033   return DXFILE_OK;
1034 }
1035
1036 static const IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl =
1037 {
1038     IDirectXFileDataReferenceImpl_QueryInterface,
1039     IDirectXFileDataReferenceImpl_AddRef,
1040     IDirectXFileDataReferenceImpl_Release,
1041     IDirectXFileDataReferenceImpl_GetName,
1042     IDirectXFileDataReferenceImpl_GetId,
1043     IDirectXFileDataReferenceImpl_Resolve
1044 };
1045
1046 static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj)
1047 {
1048     IDirectXFileEnumObjectImpl* object;
1049
1050     TRACE("(%p)\n", ppObj);
1051       
1052     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileEnumObjectImpl));
1053     if (!object)
1054     {
1055         ERR("Out of memory\n");
1056         return DXFILEERR_BADALLOC;
1057     }
1058     
1059     object->lpVtbl = &IDirectXFileEnumObject_Vtbl;
1060     object->ref = 1;
1061
1062     *ppObj = object;
1063     
1064     return S_OK;
1065 }
1066
1067 /*** IUnknown methods ***/
1068 static HRESULT WINAPI IDirectXFileEnumObjectImpl_QueryInterface(IDirectXFileEnumObject* iface, REFIID riid, void** ppvObject)
1069 {
1070   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1071
1072   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1073
1074   if (IsEqualGUID(riid, &IID_IUnknown)
1075       || IsEqualGUID(riid, &IID_IDirectXFileEnumObject))
1076   {
1077     IUnknown_AddRef(iface);
1078     *ppvObject = This;
1079     return S_OK;
1080   }
1081
1082   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1083   return E_NOINTERFACE;
1084 }
1085
1086 static ULONG WINAPI IDirectXFileEnumObjectImpl_AddRef(IDirectXFileEnumObject* iface)
1087 {
1088   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1089   ULONG ref = InterlockedIncrement(&This->ref);
1090
1091   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1092
1093   return ref;
1094 }
1095
1096 static ULONG WINAPI IDirectXFileEnumObjectImpl_Release(IDirectXFileEnumObject* iface)
1097 {
1098   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1099   ULONG ref = InterlockedDecrement(&This->ref);
1100
1101   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1102
1103   if (!ref)
1104   {
1105     int i;
1106     for (i = 0; i < This->nb_xobjects; i++)
1107       IDirectXFileData_Release(This->pRefObjects[i]);
1108     if (This->source == DXFILELOAD_FROMFILE)
1109     {
1110       UnmapViewOfFile(This->buffer);
1111       CloseHandle(This->file_mapping);
1112       CloseHandle(This->hFile);
1113     }
1114     else if (This->source == DXFILELOAD_FROMRESOURCE)
1115       FreeResource(This->resource_data);
1116     HeapFree(GetProcessHeap(), 0, This->decomp_buffer);
1117     HeapFree(GetProcessHeap(), 0, This);
1118   }
1119
1120   return ref;
1121 }
1122
1123 /*** IDirectXFileEnumObject methods ***/
1124 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetNextDataObject(IDirectXFileEnumObject* iface, LPDIRECTXFILEDATA* ppDataObj)
1125 {
1126   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1127   IDirectXFileDataImpl* object;
1128   HRESULT hr;
1129   LPBYTE pstrings = NULL;
1130
1131   TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
1132
1133   if (This->nb_xobjects >= MAX_OBJECTS)
1134   {
1135     ERR("Too many objects\n");
1136     return DXFILEERR_NOMOREOBJECTS;
1137   }
1138
1139   /* Check if there are templates defined before the object */
1140   while (This->buf.rem_bytes && is_template_available(&This->buf))
1141   {
1142     if (!parse_template(&This->buf))
1143     {
1144       WARN("Template is not correct\n");
1145       hr = DXFILEERR_BADVALUE;
1146       goto error;
1147     }
1148     else
1149     {
1150       TRACE("Template successfully parsed:\n");
1151       if (TRACE_ON(d3dxof))
1152         dump_template(This->pDirectXFile->xtemplates, &This->pDirectXFile->xtemplates[This->pDirectXFile->nb_xtemplates - 1]);
1153     }
1154   }
1155
1156   if (!This->buf.rem_bytes)
1157     return DXFILEERR_NOMOREOBJECTS;
1158
1159   hr = IDirectXFileDataImpl_Create(&object);
1160   if (FAILED(hr))
1161     return hr;
1162
1163   This->buf.pxo_globals = This->xobjects;
1164   This->buf.nb_pxo_globals = This->nb_xobjects;
1165   This->buf.level = 0;
1166
1167   This->buf.pxo_tab = HeapAlloc(GetProcessHeap(), 0, sizeof(xobject)*MAX_SUBOBJECTS);
1168   if (!This->buf.pxo_tab)
1169   {
1170     ERR("Out of memory\n");
1171     hr = DXFILEERR_BADALLOC;
1172     goto error;
1173   }
1174   This->buf.pxo = This->xobjects[This->nb_xobjects] = This->buf.pxo_tab;
1175
1176   This->buf.pxo->pdata = This->buf.pdata = NULL;
1177   This->buf.capacity = 0;
1178   This->buf.cur_pos_data = 0;
1179   This->buf.pxo->nb_subobjects = 1;
1180
1181   pstrings = HeapAlloc(GetProcessHeap(), 0, MAX_STRINGS_BUFFER);
1182   if (!pstrings)
1183   {
1184     ERR("Out of memory\n");
1185     hr = DXFILEERR_BADALLOC;
1186     goto error;
1187   }
1188   This->buf.cur_pstrings = This->buf.pstrings = object->pstrings = pstrings;
1189
1190   if (!parse_object(&This->buf))
1191   {
1192     WARN("Object is not correct\n");
1193     hr = DXFILEERR_PARSEERROR;
1194     goto error;
1195   }
1196
1197   object->pstrings = pstrings;
1198   object->pobj = This->buf.pxo;
1199   object->cur_enum_object = 0;
1200   object->level = 0;
1201   object->from_ref = FALSE;
1202
1203   *ppDataObj = (LPDIRECTXFILEDATA)object;
1204
1205   /* Get a reference to created object */
1206   This->pRefObjects[This->nb_xobjects] = (LPDIRECTXFILEDATA)object;
1207   IDirectXFileData_AddRef(This->pRefObjects[This->nb_xobjects]);
1208
1209   This->nb_xobjects++;
1210
1211   return DXFILE_OK;
1212
1213 error:
1214
1215   HeapFree(GetProcessHeap(), 0, This->buf.pxo_tab);
1216   HeapFree(GetProcessHeap(), 0, This->buf.pdata);
1217   HeapFree(GetProcessHeap(), 0, pstrings);
1218
1219   return hr;
1220 }
1221
1222 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectById(IDirectXFileEnumObject* iface, REFGUID rguid, LPDIRECTXFILEDATA* ppDataObj)
1223 {
1224   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1225
1226   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, rguid, ppDataObj); 
1227
1228   return DXFILEERR_BADVALUE;
1229 }
1230
1231 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectByName(IDirectXFileEnumObject* iface, LPCSTR szName, LPDIRECTXFILEDATA* ppDataObj)
1232 {
1233   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1234
1235   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szName, ppDataObj); 
1236
1237   return DXFILEERR_BADVALUE;
1238 }
1239
1240 static const IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl =
1241 {
1242     IDirectXFileEnumObjectImpl_QueryInterface,
1243     IDirectXFileEnumObjectImpl_AddRef,
1244     IDirectXFileEnumObjectImpl_Release,
1245     IDirectXFileEnumObjectImpl_GetNextDataObject,
1246     IDirectXFileEnumObjectImpl_GetDataObjectById,
1247     IDirectXFileEnumObjectImpl_GetDataObjectByName
1248 };
1249
1250 static HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj)
1251 {
1252     IDirectXFileSaveObjectImpl* object;
1253
1254     TRACE("(%p)\n", ppObj);
1255
1256     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileSaveObjectImpl));
1257     if (!object)
1258     {
1259         ERR("Out of memory\n");
1260         return DXFILEERR_BADALLOC;
1261     }
1262
1263     object->lpVtbl = &IDirectXFileSaveObject_Vtbl;
1264     object->ref = 1;
1265
1266     *ppObj = object;
1267
1268     return S_OK;
1269 }
1270
1271 /*** IUnknown methods ***/
1272 static HRESULT WINAPI IDirectXFileSaveObjectImpl_QueryInterface(IDirectXFileSaveObject* iface, REFIID riid, void** ppvObject)
1273 {
1274   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1275
1276   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1277
1278   if (IsEqualGUID(riid, &IID_IUnknown)
1279       || IsEqualGUID(riid, &IID_IDirectXFileSaveObject))
1280   {
1281     IUnknown_AddRef(iface);
1282     *ppvObject = This;
1283     return S_OK;
1284   }
1285
1286   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1287   return E_NOINTERFACE;
1288 }
1289
1290 static ULONG WINAPI IDirectXFileSaveObjectImpl_AddRef(IDirectXFileSaveObject* iface)
1291 {
1292   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1293   ULONG ref = InterlockedIncrement(&This->ref);
1294
1295   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1296
1297   return ref;
1298 }
1299
1300 static ULONG WINAPI IDirectXFileSaveObjectImpl_Release(IDirectXFileSaveObject* iface)
1301 {
1302   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1303   ULONG ref = InterlockedDecrement(&This->ref);
1304
1305   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1306
1307   if (!ref)
1308     HeapFree(GetProcessHeap(), 0, This);
1309
1310   return ref;
1311 }
1312
1313 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveTemplates(IDirectXFileSaveObject* iface, DWORD cTemplates, const GUID** ppguidTemplates)
1314 {
1315   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1316
1317   FIXME("(%p/%p)->(%d,%p) stub!\n", This, iface, cTemplates, ppguidTemplates);
1318
1319   return DXFILEERR_BADVALUE;
1320 }
1321
1322 static HRESULT WINAPI IDirectXFileSaveObjectImpl_CreateDataObject(IDirectXFileSaveObject* iface, REFGUID rguidTemplate, LPCSTR szName, const GUID* pguid, DWORD cbSize, LPVOID pvData, LPDIRECTXFILEDATA* ppDataObj)
1323 {
1324   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1325
1326   FIXME("(%p/%p)->(%p,%s,%p,%d,%p,%p) stub!\n", This, iface, rguidTemplate, szName, pguid, cbSize, pvData, ppDataObj);
1327
1328   return DXFILEERR_BADVALUE;
1329 }
1330
1331 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveData(IDirectXFileSaveObject* iface, LPDIRECTXFILEDATA ppDataObj)
1332 {
1333   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1334
1335   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj); 
1336
1337   return DXFILEERR_BADVALUE;
1338 }
1339
1340 static const IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl =
1341 {
1342     IDirectXFileSaveObjectImpl_QueryInterface,
1343     IDirectXFileSaveObjectImpl_AddRef,
1344     IDirectXFileSaveObjectImpl_Release,
1345     IDirectXFileSaveObjectImpl_SaveTemplates,
1346     IDirectXFileSaveObjectImpl_CreateDataObject,
1347     IDirectXFileSaveObjectImpl_SaveData
1348 };