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