wintrust: Use helper function for setting confidence in SoftpubCheckCert.
[wine] / dlls / d3dxof / d3dxof.c
1 /*
2  * Implementation of DirectX File Interfaces
3  *
4  * Copyright 2004, 2008 Christian Costa
5  *
6  * This file contains the (internal) driver registration functions,
7  * driver enumeration APIs and DirectDraw creation functions.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25 #include "wine/debug.h"
26
27 #define COBJMACROS
28
29 #include "winbase.h"
30 #include "wingdi.h"
31
32 #include "d3dxof_private.h"
33 #include "dxfile.h"
34
35 #include <stdio.h>
36
37 WINE_DEFAULT_DEBUG_CHANNEL(d3dxof);
38
39 #define MAKEFOUR(a,b,c,d) ((DWORD)a + ((DWORD)b << 8) + ((DWORD)c << 16) + ((DWORD)d << 24))
40 #define XOFFILE_FORMAT_MAGIC         MAKEFOUR('x','o','f',' ')
41 #define XOFFILE_FORMAT_VERSION       MAKEFOUR('0','3','0','2')
42 #define XOFFILE_FORMAT_BINARY        MAKEFOUR('b','i','n',' ')
43 #define XOFFILE_FORMAT_TEXT          MAKEFOUR('t','x','t',' ')
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 #define TOKEN_NAME         1
49 #define TOKEN_STRING       2
50 #define TOKEN_INTEGER      3
51 #define TOKEN_GUID         5
52 #define TOKEN_INTEGER_LIST 6
53 #define TOKEN_FLOAT_LIST   7
54 #define TOKEN_OBRACE      10
55 #define TOKEN_CBRACE      11
56 #define TOKEN_OPAREN      12
57 #define TOKEN_CPAREN      13
58 #define TOKEN_OBRACKET    14
59 #define TOKEN_CBRACKET    15
60 #define TOKEN_OANGLE      16
61 #define TOKEN_CANGLE      17
62 #define TOKEN_DOT         18
63 #define TOKEN_COMMA       19
64 #define TOKEN_SEMICOLON   20
65 #define TOKEN_TEMPLATE    31
66 #define TOKEN_WORD        40
67 #define TOKEN_DWORD       41
68 #define TOKEN_FLOAT       42
69 #define TOKEN_DOUBLE      43
70 #define TOKEN_CHAR        44
71 #define TOKEN_UCHAR       45
72 #define TOKEN_SWORD       46
73 #define TOKEN_SDWORD      47
74 #define TOKEN_VOID        48
75 #define TOKEN_LPSTR       49
76 #define TOKEN_UNICODE     50
77 #define TOKEN_CSTRING     51
78 #define TOKEN_ARRAY       52
79
80 #define CLSIDFMT "<%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X>"
81
82 #define MAX_INPUT_SIZE 1000000
83 #define MAX_DATA_SIZE 100000
84
85 static const struct IDirectXFileVtbl IDirectXFile_Vtbl;
86 static const struct IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl;
87 static const struct IDirectXFileDataVtbl IDirectXFileData_Vtbl;
88 static const struct IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl;
89 static const struct IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl;
90 static const struct IDirectXFileObjectVtbl IDirectXFileObject_Vtbl;
91 static const struct IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl;
92
93 static BOOL parse_object_parts(parse_buffer * buf, BOOL allow_optional);
94 static BOOL parse_object(parse_buffer * buf);
95
96 HRESULT IDirectXFileImpl_Create(IUnknown* pUnkOuter, LPVOID* ppObj)
97 {
98     IDirectXFileImpl* object;
99
100     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
101       
102     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileImpl));
103     
104     object->lpVtbl.lpVtbl = &IDirectXFile_Vtbl;
105     object->ref = 1;
106
107     *ppObj = object;
108     
109     return S_OK;
110 }
111
112 /*** IUnknown methods ***/
113 static HRESULT WINAPI IDirectXFileImpl_QueryInterface(IDirectXFile* iface, REFIID riid, void** ppvObject)
114 {
115   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
116
117   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
118
119   if (IsEqualGUID(riid, &IID_IUnknown)
120       || IsEqualGUID(riid, &IID_IDirectXFile))
121   {
122     IClassFactory_AddRef(iface);
123     *ppvObject = This;
124     return S_OK;
125   }
126
127   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
128   return E_NOINTERFACE;
129 }
130
131 static ULONG WINAPI IDirectXFileImpl_AddRef(IDirectXFile* iface)
132 {
133   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
134   ULONG ref = InterlockedIncrement(&This->ref);
135
136   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
137
138   return ref;
139 }
140
141 static ULONG WINAPI IDirectXFileImpl_Release(IDirectXFile* iface)
142 {
143   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
144   ULONG ref = InterlockedDecrement(&This->ref);
145
146   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
147
148   if (!ref)
149     HeapFree(GetProcessHeap(), 0, This);
150
151   return ref;
152 }
153
154 /*** IDirectXFile methods ***/
155 static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPVOID pvSource, DXFILELOADOPTIONS dwLoadOptions, LPDIRECTXFILEENUMOBJECT* ppEnumObj)
156 {
157   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
158   IDirectXFileEnumObjectImpl* object;
159   HRESULT hr;
160   DWORD header[4];
161   DWORD size;
162   HANDLE hFile = INVALID_HANDLE_VALUE;
163
164   TRACE("(%p/%p)->(%p,%x,%p)\n", This, iface, pvSource, dwLoadOptions, ppEnumObj);
165
166   if (!ppEnumObj)
167     return DXFILEERR_BADVALUE;
168
169   if (dwLoadOptions == DXFILELOAD_FROMFILE)
170   {
171     TRACE("Open source file '%s'\n", (char*)pvSource);
172
173     hFile = CreateFileA((char*)pvSource, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
174     if (hFile == INVALID_HANDLE_VALUE)
175     {
176       TRACE("File '%s' not found\n", (char*)pvSource);
177       return DXFILEERR_FILENOTFOUND;
178     }
179
180     if (!ReadFile(hFile, header, 16, &size, NULL))
181     {
182       hr = DXFILEERR_BADVALUE;
183       goto error;
184     }
185
186     if (size < 16)
187     {
188       hr = DXFILEERR_BADFILETYPE;
189       goto error;
190     }
191
192     if (TRACE_ON(d3dxof))
193     {
194       char string[17];
195       memcpy(string, header, 16);
196       string[16] = 0;
197       TRACE("header = '%s'\n", string);
198     }
199   }
200   else
201   {
202     FIXME("Source type %d is not handled yet\n", dwLoadOptions);
203     hr = DXFILEERR_NOTDONEYET;
204     goto error;
205   }
206
207   if (header[0] != XOFFILE_FORMAT_MAGIC)
208   {
209     hr = DXFILEERR_BADFILETYPE;
210     goto error;
211   }
212
213   if (header[1] != XOFFILE_FORMAT_VERSION)
214   {
215     hr = DXFILEERR_BADFILEVERSION;
216     goto error;
217   }
218
219   if ((header[2] != XOFFILE_FORMAT_BINARY) && (header[2] != XOFFILE_FORMAT_TEXT) && (header[2] != XOFFILE_FORMAT_COMPRESSED))
220   {
221     hr = DXFILEERR_BADFILETYPE;
222     goto error;
223   }
224
225   if (header[2] == XOFFILE_FORMAT_BINARY)
226   {
227     FIXME("Binary format not supported yet\n");
228     hr = DXFILEERR_NOTDONEYET;
229     goto error;
230   }
231
232   if (header[2] == XOFFILE_FORMAT_COMPRESSED)
233   {
234     FIXME("Compressed formats not supported yet\n");
235     hr = DXFILEERR_BADVALUE;
236     goto error;
237   }
238
239   if ((header[3] != XOFFILE_FORMAT_FLOAT_BITS_32) && (header[3] != XOFFILE_FORMAT_FLOAT_BITS_64))
240   {
241     hr = DXFILEERR_BADFILEFLOATSIZE;
242     goto error;
243   }
244
245   TRACE("Header is correct\n");
246
247   hr = IDirectXFileEnumObjectImpl_Create(&object);
248   if (!SUCCEEDED(hr))
249     goto error;
250
251   object->source = dwLoadOptions;
252   object->hFile = hFile;
253   object->pDirectXFile = This;
254   object->buf.pdxf = This;
255   object->buf.txt = TRUE;
256   object->buf.token_present = FALSE;
257   object->buf.cur_subobject = 0;
258
259   object->buf.buffer = HeapAlloc(GetProcessHeap(), 0, MAX_INPUT_SIZE+1);
260   if (!object->buf.buffer)
261   {
262     WARN("Out of memory\n");
263     hr = DXFILEERR_BADALLOC;
264     goto error;
265   }
266
267   ReadFile(hFile, object->buf.buffer, MAX_INPUT_SIZE+1, &object->buf.rem_bytes, NULL);
268   if (object->buf.rem_bytes > MAX_INPUT_SIZE)
269   {
270     FIXME("File size > %d not supported yet\n", MAX_INPUT_SIZE);
271     HeapFree(GetProcessHeap(), 0, object->buf.buffer);
272     hr = DXFILEERR_PARSEERROR;
273     goto error;
274   }
275   TRACE("Read %d bytes\n", object->buf.rem_bytes);
276
277   *ppEnumObj = (LPDIRECTXFILEENUMOBJECT)object;
278
279   return DXFILE_OK;
280
281 error:
282   if (hFile != INVALID_HANDLE_VALUE)
283     CloseHandle(hFile);
284   *ppEnumObj = NULL;
285
286   return hr;
287 }
288
289 static HRESULT WINAPI IDirectXFileImpl_CreateSaveObject(IDirectXFile* iface, LPCSTR szFileName, DXFILEFORMAT dwFileFormat, LPDIRECTXFILESAVEOBJECT* ppSaveObj)
290 {
291   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
292
293   FIXME("(%p/%p)->(%s,%x,%p) stub!\n", This, iface, szFileName, dwFileFormat, ppSaveObj);
294
295   return DXFILEERR_BADVALUE;
296 }
297
298 static BOOL read_bytes(parse_buffer * buf, LPVOID data, DWORD size)
299 {
300   if (buf->rem_bytes < size)
301     return FALSE;
302   memcpy(data, buf->buffer, size);
303   buf->buffer += size;
304   buf->rem_bytes -= size;
305   return TRUE;
306 }
307
308 static void dump_TOKEN(WORD token)
309 {
310 #define DUMP_TOKEN(t) case t: TRACE(#t "\n"); break
311   switch(token)
312   {
313     DUMP_TOKEN(TOKEN_NAME);
314     DUMP_TOKEN(TOKEN_STRING);
315     DUMP_TOKEN(TOKEN_INTEGER);
316     DUMP_TOKEN(TOKEN_GUID);
317     DUMP_TOKEN(TOKEN_INTEGER_LIST);
318     DUMP_TOKEN(TOKEN_FLOAT_LIST);
319     DUMP_TOKEN(TOKEN_OBRACE);
320     DUMP_TOKEN(TOKEN_CBRACE);
321     DUMP_TOKEN(TOKEN_OPAREN);
322     DUMP_TOKEN(TOKEN_CPAREN);
323     DUMP_TOKEN(TOKEN_OBRACKET);
324     DUMP_TOKEN(TOKEN_CBRACKET);
325     DUMP_TOKEN(TOKEN_OANGLE);
326     DUMP_TOKEN(TOKEN_CANGLE);
327     DUMP_TOKEN(TOKEN_DOT);
328     DUMP_TOKEN(TOKEN_COMMA);
329     DUMP_TOKEN(TOKEN_SEMICOLON);
330     DUMP_TOKEN(TOKEN_TEMPLATE);
331     DUMP_TOKEN(TOKEN_WORD);
332     DUMP_TOKEN(TOKEN_DWORD);
333     DUMP_TOKEN(TOKEN_FLOAT);
334     DUMP_TOKEN(TOKEN_DOUBLE);
335     DUMP_TOKEN(TOKEN_CHAR);
336     DUMP_TOKEN(TOKEN_UCHAR);
337     DUMP_TOKEN(TOKEN_SWORD);
338     DUMP_TOKEN(TOKEN_SDWORD);
339     DUMP_TOKEN(TOKEN_VOID);
340     DUMP_TOKEN(TOKEN_LPSTR);
341     DUMP_TOKEN(TOKEN_UNICODE);
342     DUMP_TOKEN(TOKEN_CSTRING);
343     DUMP_TOKEN(TOKEN_ARRAY);
344     default:
345       if (0)
346         TRACE("Unknown token %d\n", token);
347       break;
348   }
349 #undef DUMP_TOKEN
350 }
351
352 static BOOL is_space(char c)
353 {
354   switch (c)
355   {
356     case 0x00:
357     case 0x0D:
358     case 0x0A:
359     case ' ':
360     case '\t':
361       return TRUE;
362   }
363   return FALSE;
364 }
365
366 static BOOL is_operator(char c)
367 {
368   switch(c)
369   {
370     case '{':
371     case '}':
372     case '[':
373     case ']':
374     case '(':
375     case ')':
376     case '<':
377     case '>':
378     case ',':
379     case ';':
380       return TRUE;
381   }
382   return FALSE;
383 }
384
385 static inline BOOL is_separator(char c)
386 {
387   return is_space(c) || is_operator(c);
388 }
389
390 static WORD get_operator_token(char c)
391 {
392   switch(c)
393   {
394     case '{':
395       return TOKEN_OBRACE;
396     case '}':
397       return TOKEN_CBRACE;
398     case '[':
399       return TOKEN_OBRACKET;
400     case ']':
401       return TOKEN_CBRACKET;
402     case '(':
403       return TOKEN_OPAREN;
404     case ')':
405       return TOKEN_CPAREN;
406     case '<':
407       return TOKEN_OANGLE;
408     case '>':
409       return TOKEN_CANGLE;
410     case ',':
411       return TOKEN_COMMA;
412     case ';':
413       return TOKEN_SEMICOLON;
414   }
415   return 0;
416 }
417
418 static BOOL is_keyword(parse_buffer* buf, const char* keyword)
419 {
420   DWORD len = strlen(keyword);
421   if (!strncmp((char*)buf->buffer, keyword,len) && is_separator(*(buf->buffer+len)))
422   {
423     buf->buffer += len;
424     buf->rem_bytes -= len;
425     return TRUE;
426   }
427   return FALSE;
428 }
429
430 static WORD get_keyword_token(parse_buffer* buf)
431 {
432   if (is_keyword(buf, "template"))
433     return TOKEN_TEMPLATE;
434   if (is_keyword(buf, "WORD"))
435     return TOKEN_WORD;
436   if (is_keyword(buf, "DWORD"))
437     return TOKEN_DWORD;
438   if (is_keyword(buf, "FLOAT"))
439     return TOKEN_FLOAT;
440   if (is_keyword(buf, "DOUBLE"))
441     return TOKEN_DOUBLE;
442   if (is_keyword(buf, "CHAR"))
443     return TOKEN_CHAR;
444   if (is_keyword(buf, "UCHAR"))
445     return TOKEN_UCHAR;
446   if (is_keyword(buf, "SWORD"))
447     return TOKEN_SWORD;
448   if (is_keyword(buf, "SDWORD"))
449     return TOKEN_SDWORD;
450   if (is_keyword(buf, "VOID"))
451     return TOKEN_VOID;
452   if (is_keyword(buf, "STRING"))
453     return TOKEN_LPSTR;
454   if (is_keyword(buf, "UNICODE"))
455     return TOKEN_UNICODE;
456   if (is_keyword(buf, "CSTRING"))
457     return TOKEN_CSTRING;
458   if (is_keyword(buf, "array"))
459     return TOKEN_ARRAY;
460
461   return 0;
462 }
463
464 static BOOL is_guid(parse_buffer* buf)
465 {
466   char tmp[50];
467   DWORD pos = 1;
468   GUID class_id;
469   DWORD tab[10];
470   int ret;
471
472   if (*buf->buffer != '<')
473     return FALSE;
474   tmp[0] = '<';
475   while (*(buf->buffer+pos) != '>')
476   {
477     tmp[pos] = *(buf->buffer+pos);
478     pos++;
479   }
480   tmp[pos++] = '>';
481   tmp[pos] = 0;
482   if (pos != 38 /* <+36+> */)
483   {
484     TRACE("Wrong guid %s (%d)\n", tmp, pos);
485     return FALSE;
486   }
487   buf->buffer += pos;
488   buf->rem_bytes -= pos;
489
490   ret = sscanf(tmp, CLSIDFMT, &class_id.Data1, tab, tab+1, tab+2, tab+3, tab+4, tab+5, tab+6, tab+7, tab+8, tab+9);
491   if (ret != 11)
492   {
493     TRACE("Wrong guid %s (%d)\n", tmp, pos);
494     return FALSE;
495   }
496   TRACE("Found guid %s (%d)\n", tmp, pos);
497
498   class_id.Data2 = tab[0];
499   class_id.Data3 = tab[1];
500   class_id.Data4[0] = tab[2];
501   class_id.Data4[1] = tab[3];
502   class_id.Data4[2] = tab[4];
503   class_id.Data4[3] = tab[5];
504   class_id.Data4[4] = tab[6];
505   class_id.Data4[5] = tab[7];
506   class_id.Data4[6] = tab[8];
507   class_id.Data4[7] = tab[9];
508
509   *(GUID*)buf->value = class_id;
510
511   return TRUE;
512 }
513
514 static BOOL is_name(parse_buffer* buf)
515 {
516   char tmp[50];
517   DWORD pos = 0;
518   char c;
519   BOOL error = 0;
520   while (!is_separator(c = *(buf->buffer+pos)))
521   {
522     if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')) || (c == '_')))
523       error = 1;
524     tmp[pos++] = c;
525   }
526   tmp[pos] = 0;
527
528   if (error)
529   {
530     TRACE("Wrong name %s\n", tmp);
531     return FALSE;
532   }
533
534   buf->buffer += pos;
535   buf->rem_bytes -= pos;
536
537   TRACE("Found name %s\n", tmp);
538   strcpy((char*)buf->value, tmp);
539
540   return TRUE;
541 }
542
543 static BOOL is_float(parse_buffer* buf)
544 {
545   char tmp[50];
546   DWORD pos = 0;
547   char c;
548   float decimal;
549   BOOL dot = 0;
550
551   while (!is_separator(c = *(buf->buffer+pos)))
552   {
553     if (!((!pos && (c == '-')) || ((c >= '0') && (c <= '9')) || (!dot && (c == '.'))))
554       return FALSE;
555     if (c == '.')
556       dot = TRUE;
557     tmp[pos++] = c;
558   }
559   tmp[pos] = 0;
560
561   buf->buffer += pos;
562   buf->rem_bytes -= pos;
563
564   sscanf(tmp, "%f", &decimal);
565
566   TRACE("Found float %s - %f\n", tmp, decimal);
567
568   *(float*)buf->value = decimal;
569
570   return TRUE;
571 }
572
573 static BOOL is_integer(parse_buffer* buf)
574 {
575   char tmp[50];
576   DWORD pos = 0;
577   char c;
578   DWORD integer;
579
580   while (!is_separator(c = *(buf->buffer+pos)))
581   {
582     if (!((c >= '0') && (c <= '9')))
583       return FALSE;
584     tmp[pos++] = c;
585   }
586   tmp[pos] = 0;
587
588   buf->buffer += pos;
589   buf->rem_bytes -= pos;
590
591   sscanf(tmp, "%d", &integer);
592
593   TRACE("Found integer %s - %d\n", tmp, integer);
594
595   *(DWORD*)buf->value = integer;
596
597   return TRUE;
598 }
599
600 static WORD parse_TOKEN(parse_buffer * buf)
601 {
602   WORD token;
603
604   if (buf->txt)
605   {
606     while(1)
607     {
608       char c;
609       if (!read_bytes(buf, &c, 1))
610         return 0;
611       /*TRACE("char = '%c'\n", is_space(c) ? ' ' : c);*/
612       if ((c == '#') || (c == '/'))
613       {
614         /* Handle comment (# or //) */
615         if (c == '/')
616         {
617           if (!read_bytes(buf, &c, 1))
618             return 0;
619           if (c != '/')
620             return 0;
621         }
622         c = 0;
623         while (c != 0x0A)
624         {
625           if (!read_bytes(buf, &c, 1))
626             return 0;
627         }
628         continue;
629       }
630       if (is_space(c))
631         continue;
632       if (is_operator(c) && (c != '<'))
633       {
634         token = get_operator_token(c);
635         break;
636       }
637       else if (c == '.')
638       {
639         token = TOKEN_DOT;
640         break;
641       }
642       else
643       {
644         buf->buffer -= 1;
645         buf->rem_bytes += 1;
646
647         if ((token = get_keyword_token(buf)))
648           break;
649
650         if (is_guid(buf))
651         {
652           token = TOKEN_GUID;
653           break;
654         }
655         if (is_integer(buf))
656         {
657           token = TOKEN_INTEGER;
658           break;
659         }
660         if (is_float(buf))
661         {
662           token = TOKEN_FLOAT;
663           break;
664         }
665         if (is_name(buf))
666         {
667           token = TOKEN_NAME;
668           break;
669         }
670
671         FIXME("Unrecognize element\n");
672         return 0;
673       }
674     }
675   }
676   else
677   {
678     if (!read_bytes(buf, &token, 2))
679       return 0;
680
681     switch(token)
682     {
683       case TOKEN_NAME:
684         {
685           DWORD count;
686           char strname[100];
687
688           if (!read_bytes(buf, &count, 4))
689             return 0;
690           if (!read_bytes(buf, strname, count))
691             return 0;
692           strname[count] = 0;
693           /*TRACE("name = %s\n", strname);*/
694
695           strcpy((char*)buf->value, strname);
696         }
697         break;
698       case TOKEN_INTEGER:
699         {
700           DWORD integer;
701
702           if (!read_bytes(buf, &integer, 4))
703             return 0;
704           /*TRACE("integer = %ld\n", integer);*/
705
706           *(DWORD*)buf->value = integer;
707         }
708         break;
709       case TOKEN_GUID:
710         {
711           char strguid[38];
712           GUID class_id;
713
714           if (!read_bytes(buf, &class_id, 16))
715             return 0;
716           sprintf(strguid, CLSIDFMT, class_id.Data1, class_id.Data2, class_id.Data3, class_id.Data4[0],
717             class_id.Data4[1], class_id.Data4[2], class_id.Data4[3], class_id.Data4[4], class_id.Data4[5],
718             class_id.Data4[6], class_id.Data4[7]);
719           /*TRACE("guid = {%s}\n", strguid);*/
720
721           *(GUID*)buf->value = class_id;
722         }
723         break;
724       case TOKEN_STRING:
725       case TOKEN_INTEGER_LIST:
726       case TOKEN_FLOAT_LIST:
727       case TOKEN_OBRACE:
728       case TOKEN_CBRACE:
729       case TOKEN_OPAREN:
730       case TOKEN_CPAREN:
731       case TOKEN_OBRACKET:
732       case TOKEN_CBRACKET:
733       case TOKEN_OANGLE:
734       case TOKEN_CANGLE:
735       case TOKEN_DOT:
736       case TOKEN_COMMA:
737       case TOKEN_SEMICOLON:
738       case TOKEN_TEMPLATE:
739       case TOKEN_WORD:
740       case TOKEN_DWORD:
741       case TOKEN_FLOAT:
742       case TOKEN_DOUBLE:
743       case TOKEN_CHAR:
744       case TOKEN_UCHAR:
745       case TOKEN_SWORD:
746       case TOKEN_SDWORD:
747       case TOKEN_VOID:
748       case TOKEN_LPSTR:
749       case TOKEN_UNICODE:
750       case TOKEN_CSTRING:
751       case TOKEN_ARRAY:
752         break;
753       default:
754         return 0;
755     }
756   }
757
758   dump_TOKEN(token);
759
760   return token;
761 }
762
763 static const char* get_primitive_string(WORD token)
764 {
765   switch(token)
766   {
767     case TOKEN_WORD:
768       return "WORD";
769     case TOKEN_DWORD:
770       return "DWORD";
771     case TOKEN_FLOAT:
772       return "FLOAT";
773     case TOKEN_DOUBLE:
774       return "DOUBLE";
775     case TOKEN_CHAR:
776       return "CHAR";
777     case TOKEN_UCHAR:
778       return "UCHAR";
779     case TOKEN_SWORD:
780       return "SWORD";
781     case TOKEN_SDWORD:
782       return "SDWORD";
783     case TOKEN_VOID:
784       return "VOID";
785     case TOKEN_LPSTR:
786       return "STRING";
787     case TOKEN_UNICODE:
788       return "UNICODE";
789     case TOKEN_CSTRING:
790       return "CSTRING ";
791     default:
792       break;
793   }
794   return NULL;
795 }
796
797 static WORD get_TOKEN(parse_buffer * buf)
798 {
799   if (buf->token_present)
800   {
801     buf->token_present = FALSE;
802     return buf->current_token;
803   }
804
805   buf->current_token = parse_TOKEN(buf);
806
807   return buf->current_token;
808 }
809
810 static WORD check_TOKEN(parse_buffer * buf)
811 {
812   if (buf->token_present)
813     return buf->current_token;
814
815   buf->current_token = parse_TOKEN(buf);
816   buf->token_present = TRUE;
817
818   return buf->current_token;
819 }
820
821 static inline BOOL is_primitive_type(WORD token)
822 {
823   BOOL ret;
824   switch(token)
825   {
826     case TOKEN_WORD:
827     case TOKEN_DWORD:
828     case TOKEN_FLOAT:
829     case TOKEN_DOUBLE:
830     case TOKEN_CHAR:
831     case TOKEN_UCHAR:
832     case TOKEN_SWORD:
833     case TOKEN_SDWORD:
834     case TOKEN_LPSTR:
835     case TOKEN_UNICODE:
836     case TOKEN_CSTRING:
837       ret = 1;
838       break;
839     default:
840       ret = 0;
841       break;
842   }
843   return ret;
844 }
845
846 static BOOL parse_template_option_info(parse_buffer * buf)
847 {
848   xtemplate* cur_template = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates];
849
850   if (check_TOKEN(buf) == TOKEN_DOT)
851   {
852     get_TOKEN(buf);
853     if (get_TOKEN(buf) != TOKEN_DOT)
854       return FALSE;
855     if (get_TOKEN(buf) != TOKEN_DOT)
856       return FALSE;
857     cur_template->open = TRUE;
858   }
859   else
860   {
861     while (1)
862     {
863       if (get_TOKEN(buf) != TOKEN_NAME)
864         return FALSE;
865       strcpy(cur_template->childs[cur_template->nb_childs], (char*)buf->value);
866       if (check_TOKEN(buf) == TOKEN_GUID)
867         get_TOKEN(buf);
868       cur_template->nb_childs++;
869       if (check_TOKEN(buf) != TOKEN_COMMA)
870         break;
871       get_TOKEN(buf);
872     }
873     cur_template->open = FALSE;
874   }
875
876   return TRUE;
877 }
878
879 static BOOL parse_template_members_list(parse_buffer * buf)
880 {
881   int idx_member = 0;
882   member* cur_member;
883
884   while (1)
885   {
886     BOOL array = 0;
887     int nb_dims = 0;
888     cur_member = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[idx_member];
889
890     if (check_TOKEN(buf) == TOKEN_ARRAY)
891     {
892       get_TOKEN(buf);
893       array = 1;
894     }
895
896     if (check_TOKEN(buf) == TOKEN_NAME)
897     {
898       cur_member->type = get_TOKEN(buf);
899       cur_member->idx_template = 0;
900       while (cur_member->idx_template < buf->pdxf->nb_xtemplates)
901       {
902         if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[cur_member->idx_template].name))
903           break;
904         cur_member->idx_template++;
905       }
906       if (cur_member->idx_template == buf->pdxf->nb_xtemplates)
907       {
908         TRACE("Reference to a nonexistent template '%s'\n", (char*)buf->value);
909         return FALSE;
910       }
911     }
912     else if (is_primitive_type(check_TOKEN(buf)))
913       cur_member->type = get_TOKEN(buf);
914     else
915       break;
916
917     if (get_TOKEN(buf) != TOKEN_NAME)
918       return FALSE;
919     strcpy(cur_member->name, (char*)buf->value);
920
921     if (array)
922     {
923       while (check_TOKEN(buf) == TOKEN_OBRACKET)
924       {
925         if (nb_dims)
926         {
927           FIXME("No support for multi-dimensional array yet\n");
928           return FALSE;
929         }
930         get_TOKEN(buf);
931         if (check_TOKEN(buf) == TOKEN_INTEGER)
932         {
933           get_TOKEN(buf);
934           cur_member->dim_fixed[nb_dims] = TRUE;
935           cur_member->dim_value[nb_dims] = *(DWORD*)buf->value;
936         }
937         else
938         {
939           if (get_TOKEN(buf) != TOKEN_NAME)
940             return FALSE;
941           cur_member->dim_fixed[nb_dims] = FALSE;
942           /* Hack: Assume array size is specified in previous member */
943           cur_member->dim_value[nb_dims] = idx_member - 1;
944         }
945         if (get_TOKEN(buf) != TOKEN_CBRACKET)
946           return FALSE;
947         nb_dims++;
948       }
949       if (!nb_dims)
950         return FALSE;
951       cur_member->nb_dims = nb_dims;
952     }
953     if (get_TOKEN(buf) != TOKEN_SEMICOLON)
954       return FALSE;
955
956     idx_member++;
957   }
958
959   buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].nb_members = idx_member;
960
961   return TRUE;
962 }
963
964 static BOOL parse_template_parts(parse_buffer * buf)
965 {
966   if (!parse_template_members_list(buf))
967     return FALSE;
968   if (check_TOKEN(buf) == TOKEN_OBRACKET)
969   {
970     get_TOKEN(buf);
971     if (!parse_template_option_info(buf))
972       return FALSE;
973     if (get_TOKEN(buf) != TOKEN_CBRACKET)
974      return FALSE;
975   }
976
977   return TRUE;
978 }
979
980 static BOOL parse_template(parse_buffer * buf)
981 {
982   if (get_TOKEN(buf) != TOKEN_TEMPLATE)
983     return FALSE;
984   if (get_TOKEN(buf) != TOKEN_NAME)
985     return FALSE;
986   strcpy(buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].name, (char*)buf->value);
987   if (get_TOKEN(buf) != TOKEN_OBRACE)
988     return FALSE;
989   if (get_TOKEN(buf) != TOKEN_GUID)
990     return FALSE;
991   buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].class_id = *(GUID*)buf->value;
992   if (!parse_template_parts(buf))
993     return FALSE;
994   if (get_TOKEN(buf) != TOKEN_CBRACE)
995     return FALSE;
996   if (buf->txt)
997   {
998     /* Go to the next template */
999     while (buf->rem_bytes && is_space(*buf->buffer))
1000     {
1001       buf->buffer++;
1002       buf->rem_bytes--;
1003     }
1004   }
1005
1006   TRACE("%d - %s - %s\n", buf->pdxf->nb_xtemplates, buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].name, debugstr_guid(&buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].class_id));
1007   buf->pdxf->nb_xtemplates++;
1008
1009   return TRUE;
1010 }
1011
1012 static HRESULT WINAPI IDirectXFileImpl_RegisterTemplates(IDirectXFile* iface, LPVOID pvData, DWORD cbSize)
1013 {
1014   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
1015   DWORD token_header;
1016   parse_buffer buf;
1017
1018   buf.buffer = (LPBYTE)pvData;
1019   buf.rem_bytes = cbSize;
1020   buf.txt = FALSE;
1021   buf.token_present = FALSE;
1022   buf.pdxf = This;
1023
1024   TRACE("(%p/%p)->(%p,%d)\n", This, iface, pvData, cbSize);
1025
1026   if (!pvData)
1027     return DXFILEERR_BADVALUE;
1028
1029   if (cbSize < 16)
1030     return DXFILEERR_BADFILETYPE;
1031
1032   if (TRACE_ON(d3dxof))
1033   {
1034     char string[17];
1035     memcpy(string, pvData, 16);
1036     string[16] = 0;
1037     TRACE("header = '%s'\n", string);
1038   }
1039
1040   read_bytes(&buf, &token_header, 4);
1041
1042   if (token_header != XOFFILE_FORMAT_MAGIC)
1043     return DXFILEERR_BADFILETYPE;
1044
1045   read_bytes(&buf, &token_header, 4);
1046
1047   if (token_header != XOFFILE_FORMAT_VERSION)
1048     return DXFILEERR_BADFILEVERSION;
1049
1050   read_bytes(&buf, &token_header, 4);
1051
1052   if ((token_header != XOFFILE_FORMAT_BINARY) && (token_header != XOFFILE_FORMAT_TEXT) && (token_header != XOFFILE_FORMAT_COMPRESSED))
1053     return DXFILEERR_BADFILETYPE;
1054
1055   if (token_header == XOFFILE_FORMAT_TEXT)
1056   {
1057     buf.txt = TRUE;
1058   }
1059
1060   if (token_header == XOFFILE_FORMAT_COMPRESSED)
1061   {
1062     FIXME("Compressed formats not supported yet\n");
1063     return DXFILEERR_BADVALUE;
1064   }
1065
1066   read_bytes(&buf, &token_header, 4);
1067
1068   if ((token_header != XOFFILE_FORMAT_FLOAT_BITS_32) && (token_header != XOFFILE_FORMAT_FLOAT_BITS_64))
1069     return DXFILEERR_BADFILEFLOATSIZE;
1070
1071   TRACE("Header is correct\n");
1072
1073   while (buf.rem_bytes)
1074   {
1075     if (!parse_template(&buf))
1076     {
1077       TRACE("Template is not correct\n");
1078       return DXFILEERR_BADVALUE;
1079     }
1080     else
1081     {
1082       TRACE("Template successfully parsed:\n");
1083       if (TRACE_ON(d3dxof))
1084       {
1085         int i,j,k;
1086         GUID* clsid;
1087
1088         i = This->nb_xtemplates - 1;
1089         clsid = &This->xtemplates[i].class_id;
1090
1091         DPRINTF("template %s\n", This->xtemplates[i].name);
1092         DPRINTF("{\n");
1093         DPRINTF(CLSIDFMT "\n", clsid->Data1, clsid->Data2, clsid->Data3, clsid->Data4[0],
1094           clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7]);
1095         for (j = 0; j < This->xtemplates[i].nb_members; j++)
1096         {
1097           if (This->xtemplates[i].members[j].nb_dims)
1098             DPRINTF("array ");
1099           if (This->xtemplates[i].members[j].type == TOKEN_NAME)
1100             DPRINTF("%s ", This->xtemplates[This->xtemplates[i].members[j].idx_template].name);
1101           else
1102             DPRINTF("%s ", get_primitive_string(This->xtemplates[i].members[j].type));
1103           DPRINTF("%s", This->xtemplates[i].members[j].name);
1104           for (k = 0; k < This->xtemplates[i].members[j].nb_dims; k++)
1105           {
1106             if (This->xtemplates[i].members[j].dim_fixed[k])
1107               DPRINTF("[%d]", This->xtemplates[i].members[j].dim_value[k]);
1108             else
1109               DPRINTF("[%s]", This->xtemplates[i].members[This->xtemplates[i].members[j].dim_value[k]].name);
1110           }
1111           DPRINTF(";\n");
1112         }
1113         if (This->xtemplates[i].open)
1114           DPRINTF("[...]\n");
1115         else if (This->xtemplates[i].nb_childs)
1116         {
1117           DPRINTF("[%s", This->xtemplates[i].childs[0]);
1118           for (j = 1; j < This->xtemplates[i].nb_childs; j++)
1119             DPRINTF(",%s", This->xtemplates[i].childs[j]);
1120           DPRINTF("]\n");
1121         }
1122         DPRINTF("}\n");
1123       }
1124     }
1125   }
1126
1127   if (TRACE_ON(d3dxof))
1128   {
1129     int i;
1130     TRACE("Registered templates (%d):\n", This->nb_xtemplates);
1131     for (i = 0; i < This->nb_xtemplates; i++)
1132       DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
1133   }
1134
1135   return DXFILE_OK;
1136 }
1137
1138 static const IDirectXFileVtbl IDirectXFile_Vtbl =
1139 {
1140   IDirectXFileImpl_QueryInterface,
1141   IDirectXFileImpl_AddRef,
1142   IDirectXFileImpl_Release,
1143   IDirectXFileImpl_CreateEnumObject,
1144   IDirectXFileImpl_CreateSaveObject,
1145   IDirectXFileImpl_RegisterTemplates
1146 };
1147
1148 HRESULT IDirectXFileBinaryImpl_Create(IDirectXFileBinaryImpl** ppObj)
1149 {
1150     IDirectXFileBinaryImpl* object;
1151
1152     TRACE("(%p)\n", ppObj);
1153       
1154     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileBinaryImpl));
1155     
1156     object->lpVtbl.lpVtbl = &IDirectXFileBinary_Vtbl;
1157     object->ref = 1;
1158
1159     *ppObj = object;
1160     
1161     return DXFILE_OK;
1162 }
1163
1164 /*** IUnknown methods ***/
1165 static HRESULT WINAPI IDirectXFileBinaryImpl_QueryInterface(IDirectXFileBinary* iface, REFIID riid, void** ppvObject)
1166 {
1167   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1168
1169   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1170
1171   if (IsEqualGUID(riid, &IID_IUnknown)
1172       || IsEqualGUID(riid, &IID_IDirectXFileObject)
1173       || IsEqualGUID(riid, &IID_IDirectXFileBinary))
1174   {
1175     IClassFactory_AddRef(iface);
1176     *ppvObject = This;
1177     return S_OK;
1178   }
1179
1180   /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
1181   if (!IsEqualGUID(riid, &IID_IDirectXFileData)
1182       && !IsEqualGUID(riid, &IID_IDirectXFileDataReference))
1183     ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1184
1185   return E_NOINTERFACE;
1186 }
1187
1188 static ULONG WINAPI IDirectXFileBinaryImpl_AddRef(IDirectXFileBinary* iface)
1189 {
1190   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1191   ULONG ref = InterlockedIncrement(&This->ref);
1192
1193   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1194
1195   return ref;
1196 }
1197
1198 static ULONG WINAPI IDirectXFileBinaryImpl_Release(IDirectXFileBinary* iface)
1199 {
1200   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1201   ULONG ref = InterlockedDecrement(&This->ref);
1202
1203   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1204
1205   if (!ref)
1206     HeapFree(GetProcessHeap(), 0, This);
1207
1208   return ref;
1209 }
1210
1211 /*** IDirectXFileObject methods ***/
1212 static HRESULT WINAPI IDirectXFileBinaryImpl_GetName(IDirectXFileBinary* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1213
1214 {
1215   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1216
1217   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
1218
1219   return DXFILEERR_BADVALUE;
1220 }
1221
1222 static HRESULT WINAPI IDirectXFileBinaryImpl_GetId(IDirectXFileBinary* iface, LPGUID pGuid)
1223 {
1224   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1225
1226   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
1227
1228   return DXFILEERR_BADVALUE;
1229 }
1230
1231 /*** IDirectXFileBinary methods ***/
1232 static HRESULT WINAPI IDirectXFileBinaryImpl_GetSize(IDirectXFileBinary* iface, DWORD* pcbSize)
1233 {
1234   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1235
1236   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pcbSize); 
1237
1238   return DXFILEERR_BADVALUE;
1239 }
1240
1241 static HRESULT WINAPI IDirectXFileBinaryImpl_GetMimeType(IDirectXFileBinary* iface, LPCSTR* pszMimeType)
1242 {
1243   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1244
1245   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pszMimeType);
1246
1247   return DXFILEERR_BADVALUE;
1248 }
1249
1250 static HRESULT WINAPI IDirectXFileBinaryImpl_Read(IDirectXFileBinary* iface, LPVOID pvData, DWORD cbSize, LPDWORD pcbRead)
1251 {
1252   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1253
1254   FIXME("(%p/%p)->(%p, %d, %p) stub!\n", This, iface, pvData, cbSize, pcbRead);
1255
1256   return DXFILEERR_BADVALUE;
1257 }
1258
1259 static const IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl =
1260 {
1261     IDirectXFileBinaryImpl_QueryInterface,
1262     IDirectXFileBinaryImpl_AddRef,
1263     IDirectXFileBinaryImpl_Release,
1264     IDirectXFileBinaryImpl_GetName,
1265     IDirectXFileBinaryImpl_GetId,
1266     IDirectXFileBinaryImpl_GetSize,
1267     IDirectXFileBinaryImpl_GetMimeType,
1268     IDirectXFileBinaryImpl_Read
1269 };
1270
1271 HRESULT IDirectXFileDataImpl_Create(IDirectXFileDataImpl** ppObj)
1272 {
1273     IDirectXFileDataImpl* object;
1274
1275     TRACE("(%p)\n", ppObj);
1276       
1277     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataImpl));
1278     
1279     object->lpVtbl.lpVtbl = &IDirectXFileData_Vtbl;
1280     object->ref = 1;
1281
1282     *ppObj = object;
1283     
1284     return S_OK;
1285 }
1286
1287 /*** IUnknown methods ***/
1288 static HRESULT WINAPI IDirectXFileDataImpl_QueryInterface(IDirectXFileData* iface, REFIID riid, void** ppvObject)
1289 {
1290   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1291
1292   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1293
1294   if (IsEqualGUID(riid, &IID_IUnknown)
1295       || IsEqualGUID(riid, &IID_IDirectXFileObject)
1296       || IsEqualGUID(riid, &IID_IDirectXFileData))
1297   {
1298     IClassFactory_AddRef(iface);
1299     *ppvObject = This;
1300     return S_OK;
1301   }
1302
1303   /* Do not print an error for interfaces that can be queried to retreive the type of the object */
1304   if (!IsEqualGUID(riid, &IID_IDirectXFileBinary)
1305       && !IsEqualGUID(riid, &IID_IDirectXFileDataReference))
1306     ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1307
1308   return E_NOINTERFACE;
1309 }
1310
1311 static ULONG WINAPI IDirectXFileDataImpl_AddRef(IDirectXFileData* iface)
1312 {
1313   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1314   ULONG ref = InterlockedIncrement(&This->ref);
1315
1316   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1317
1318   return ref;
1319 }
1320
1321 static ULONG WINAPI IDirectXFileDataImpl_Release(IDirectXFileData* iface)
1322 {
1323   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1324   ULONG ref = InterlockedDecrement(&This->ref);
1325
1326   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1327
1328   if (!ref)
1329     HeapFree(GetProcessHeap(), 0, This);
1330
1331   return ref;
1332 }
1333
1334 /*** IDirectXFileObject methods ***/
1335 static HRESULT WINAPI IDirectXFileDataImpl_GetName(IDirectXFileData* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1336
1337 {
1338   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1339
1340   TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
1341
1342   if (!pstrNameBuf)
1343     return DXFILEERR_BADVALUE;
1344
1345   strcpy(pstrNameBuf, This->pobj->name);
1346
1347   return DXFILE_OK;
1348 }
1349
1350 static HRESULT WINAPI IDirectXFileDataImpl_GetId(IDirectXFileData* iface, LPGUID pGuid)
1351 {
1352   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1353
1354   TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
1355
1356   if (!pGuid)
1357     return DXFILEERR_BADVALUE;
1358
1359   memcpy(pGuid, &This->pobj->class_id, 16);
1360
1361   return DXFILE_OK;
1362 }
1363
1364 /*** IDirectXFileData methods ***/
1365 static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCSTR szMember, DWORD* pcbSize, void** ppvData)
1366 {
1367   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1368
1369   TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, szMember, pcbSize, ppvData);
1370
1371   if (!pcbSize || !ppvData)
1372     return DXFILEERR_BADVALUE;
1373
1374   if (szMember)
1375   {
1376     FIXME("Specifying a member is not supported yet!\n");
1377     return DXFILEERR_BADVALUE;
1378   }
1379
1380   *pcbSize = This->pobj->size;
1381   *ppvData = This->pobj->pdata;
1382
1383   return DXFILE_OK;
1384 }
1385
1386 static HRESULT WINAPI IDirectXFileDataImpl_GetType(IDirectXFileData* iface, const GUID** pguid)
1387 {
1388   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1389   static GUID guid;
1390
1391   TRACE("(%p/%p)->(%p)\n", This, iface, pguid);
1392
1393   if (!pguid)
1394     return DXFILEERR_BADVALUE;
1395
1396   memcpy(&guid, &This->pobj->type, 16);
1397   *pguid = &guid;
1398
1399   return DXFILE_OK;
1400 }
1401
1402 static HRESULT WINAPI IDirectXFileDataImpl_GetNextObject(IDirectXFileData* iface, LPDIRECTXFILEOBJECT* ppChildObj)
1403 {
1404   HRESULT hr;
1405   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1406
1407   TRACE("(%p/%p)->(%p)\n", This, iface, ppChildObj);
1408
1409   if (This->cur_enum_object >= This->pobj->nb_childs)
1410     return DXFILEERR_NOMOREOBJECTS;
1411
1412   if (This->pobj->childs[This->cur_enum_object]->ptarget)
1413   {
1414     IDirectXFileDataReferenceImpl *object;
1415
1416     hr = IDirectXFileDataReferenceImpl_Create(&object);
1417     if (hr != S_OK)
1418       return DXFILEERR_BADVALUE;
1419
1420     object->ptarget = This->pobj->childs[This->cur_enum_object++]->ptarget;
1421
1422     *ppChildObj = (LPDIRECTXFILEOBJECT)object;
1423   }
1424   else
1425   {
1426     IDirectXFileDataImpl *object;
1427
1428     hr = IDirectXFileDataImpl_Create(&object);
1429     if (hr != S_OK)
1430       return DXFILEERR_BADVALUE;
1431
1432     object->pobj = This->pobj->childs[This->cur_enum_object++];
1433     object->cur_enum_object = 0;
1434
1435     *ppChildObj = (LPDIRECTXFILEOBJECT)object;
1436   }
1437
1438   return DXFILE_OK;
1439 }
1440
1441 static HRESULT WINAPI IDirectXFileDataImpl_AddDataObject(IDirectXFileData* iface, LPDIRECTXFILEDATA pDataObj)
1442 {
1443   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1444
1445   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pDataObj); 
1446
1447   return DXFILEERR_BADVALUE;
1448 }
1449
1450 static HRESULT WINAPI IDirectXFileDataImpl_AddDataReference(IDirectXFileData* iface, LPCSTR szRef, const GUID* pguidRef)
1451 {
1452   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1453
1454   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szRef, pguidRef); 
1455
1456   return DXFILEERR_BADVALUE;
1457 }
1458
1459 static HRESULT WINAPI IDirectXFileDataImpl_AddBinaryObject(IDirectXFileData* iface, LPCSTR szName, const GUID* pguid, LPCSTR szMimeType, LPVOID pvData, DWORD cbSize)
1460 {
1461   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1462
1463   FIXME("(%p/%p)->(%s,%p,%s,%p,%d) stub!\n", This, iface, szName, pguid, szMimeType, pvData, cbSize);
1464
1465   return DXFILEERR_BADVALUE;
1466 }
1467
1468 static const IDirectXFileDataVtbl IDirectXFileData_Vtbl =
1469 {
1470     IDirectXFileDataImpl_QueryInterface,
1471     IDirectXFileDataImpl_AddRef,
1472     IDirectXFileDataImpl_Release,
1473     IDirectXFileDataImpl_GetName,
1474     IDirectXFileDataImpl_GetId,
1475     IDirectXFileDataImpl_GetData,
1476     IDirectXFileDataImpl_GetType,
1477     IDirectXFileDataImpl_GetNextObject,
1478     IDirectXFileDataImpl_AddDataObject,
1479     IDirectXFileDataImpl_AddDataReference,
1480     IDirectXFileDataImpl_AddBinaryObject
1481 };
1482
1483 HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj)
1484 {
1485     IDirectXFileDataReferenceImpl* object;
1486
1487     TRACE("(%p)\n", ppObj);
1488       
1489     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataReferenceImpl));
1490     
1491     object->lpVtbl.lpVtbl = &IDirectXFileDataReference_Vtbl;
1492     object->ref = 1;
1493
1494     *ppObj = object;
1495     
1496     return S_OK;
1497 }
1498
1499 /*** IUnknown methods ***/
1500 static HRESULT WINAPI IDirectXFileDataReferenceImpl_QueryInterface(IDirectXFileDataReference* iface, REFIID riid, void** ppvObject)
1501 {
1502   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1503
1504   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1505
1506   if (IsEqualGUID(riid, &IID_IUnknown)
1507       || IsEqualGUID(riid, &IID_IDirectXFileObject)
1508       || IsEqualGUID(riid, &IID_IDirectXFileDataReference))
1509   {
1510     IClassFactory_AddRef(iface);
1511     *ppvObject = This;
1512     return S_OK;
1513   }
1514
1515   /* Do not print an error for interfaces that can be queried to retreive the type of the object */
1516   if (!IsEqualGUID(riid, &IID_IDirectXFileData)
1517       && !IsEqualGUID(riid, &IID_IDirectXFileBinary))
1518     ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1519
1520   return E_NOINTERFACE;
1521 }
1522
1523 static ULONG WINAPI IDirectXFileDataReferenceImpl_AddRef(IDirectXFileDataReference* iface)
1524 {
1525   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1526   ULONG ref = InterlockedIncrement(&This->ref);
1527
1528   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1529
1530   return ref;
1531 }
1532
1533 static ULONG WINAPI IDirectXFileDataReferenceImpl_Release(IDirectXFileDataReference* iface)
1534 {
1535   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1536   ULONG ref = InterlockedDecrement(&This->ref);
1537
1538   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1539
1540   if (!ref)
1541     HeapFree(GetProcessHeap(), 0, This);
1542
1543   return ref;
1544 }
1545
1546 /*** IDirectXFileObject methods ***/
1547 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetName(IDirectXFileDataReference* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1548 {
1549   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1550
1551   TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
1552
1553   if (!pstrNameBuf)
1554     return DXFILEERR_BADVALUE;
1555
1556   strcpy(pstrNameBuf, This->ptarget->name);
1557
1558   return DXFILEERR_BADVALUE;
1559 }
1560
1561 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetId(IDirectXFileDataReference* iface, LPGUID pGuid)
1562 {
1563   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1564
1565   TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
1566
1567   if (!pGuid)
1568     return DXFILEERR_BADVALUE;
1569
1570   memcpy(pGuid, &This->ptarget->class_id, 16);
1571
1572   return DXFILE_OK;
1573 }
1574
1575 /*** IDirectXFileDataReference ***/
1576 static HRESULT WINAPI IDirectXFileDataReferenceImpl_Resolve(IDirectXFileDataReference* iface, LPDIRECTXFILEDATA* ppDataObj)
1577 {
1578   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1579   IDirectXFileDataImpl *object;
1580   HRESULT hr;
1581
1582   TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
1583
1584   if (!ppDataObj)
1585     return DXFILEERR_BADVALUE;
1586
1587   hr = IDirectXFileDataImpl_Create(&object);
1588   if (hr != S_OK)
1589     return DXFILEERR_BADVALUE;
1590
1591   object->pobj = This->ptarget;
1592   object->cur_enum_object = 0;
1593
1594   *ppDataObj = (LPDIRECTXFILEDATA)object;
1595
1596   return DXFILE_OK;
1597 }
1598
1599 static const IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl =
1600 {
1601     IDirectXFileDataReferenceImpl_QueryInterface,
1602     IDirectXFileDataReferenceImpl_AddRef,
1603     IDirectXFileDataReferenceImpl_Release,
1604     IDirectXFileDataReferenceImpl_GetName,
1605     IDirectXFileDataReferenceImpl_GetId,
1606     IDirectXFileDataReferenceImpl_Resolve
1607 };
1608
1609 HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj)
1610 {
1611     IDirectXFileEnumObjectImpl* object;
1612
1613     TRACE("(%p)\n", ppObj);
1614       
1615     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileEnumObjectImpl));
1616     
1617     object->lpVtbl.lpVtbl = &IDirectXFileEnumObject_Vtbl;
1618     object->ref = 1;
1619
1620     *ppObj = object;
1621     
1622     return S_OK;
1623 }
1624
1625 /*** IUnknown methods ***/
1626 static HRESULT WINAPI IDirectXFileEnumObjectImpl_QueryInterface(IDirectXFileEnumObject* iface, REFIID riid, void** ppvObject)
1627 {
1628   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1629
1630   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1631
1632   if (IsEqualGUID(riid, &IID_IUnknown)
1633       || IsEqualGUID(riid, &IID_IDirectXFileEnumObject))
1634   {
1635     IClassFactory_AddRef(iface);
1636     *ppvObject = This;
1637     return S_OK;
1638   }
1639
1640   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1641   return E_NOINTERFACE;
1642 }
1643
1644 static ULONG WINAPI IDirectXFileEnumObjectImpl_AddRef(IDirectXFileEnumObject* iface)
1645 {
1646   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1647   ULONG ref = InterlockedIncrement(&This->ref);
1648
1649   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1650
1651   return ref;
1652 }
1653
1654 static ULONG WINAPI IDirectXFileEnumObjectImpl_Release(IDirectXFileEnumObject* iface)
1655 {
1656   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1657   ULONG ref = InterlockedDecrement(&This->ref);
1658
1659   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1660
1661   if (!ref)
1662     HeapFree(GetProcessHeap(), 0, This);
1663
1664   return ref;
1665 }
1666
1667 static BOOL parse_object_members_list(parse_buffer * buf)
1668 {
1669   DWORD token;
1670   int i;
1671   xtemplate* pt = buf->pxt[buf->level];
1672   DWORD last_dword = 0;
1673
1674   for (i = 0; i < pt->nb_members; i++)
1675   {
1676     int nb_elems, k;
1677
1678     if (pt->members[i].nb_dims > 1)
1679     {
1680       FIXME("Arrays with dimension > 1 not yet supported\n");
1681       return FALSE;
1682     }
1683     else if (pt->members[i].nb_dims)
1684     {
1685       if (!pt->members[i].dim_fixed[0])
1686       {
1687         if (!i)
1688         {
1689           FIXME("Array with variable must be preceded by the size\n");
1690           return FALSE;
1691         }
1692         nb_elems = last_dword;
1693         /*FIXME("Arrays with variable size not yet supported\n");
1694         return FALSE;*/
1695       }
1696       else
1697         nb_elems = pt->members[i].dim_value[0];
1698     }
1699     else
1700       nb_elems = 1;
1701
1702     for (k = 0; k < nb_elems; k++)
1703     {
1704       if (k)
1705       {
1706         if (get_TOKEN(buf) != TOKEN_COMMA)
1707           return FALSE;
1708       }
1709
1710       if (pt->members[i].type == TOKEN_NAME)
1711       {
1712         int j;
1713
1714         TRACE("Found suboject %s\n", buf->pdxf->xtemplates[pt->members[i].idx_template].name);
1715         buf->level++;
1716         /* To do template lookup */
1717         for (j = 0; j < buf->pdxf->nb_xtemplates; j++)
1718         {
1719           if (!strcmp(buf->pdxf->xtemplates[pt->members[i].idx_template].name, buf->pdxf->xtemplates[j].name))
1720           {
1721             buf->pxt[buf->level] = &buf->pdxf->xtemplates[j];
1722             break;
1723           }
1724         }
1725         if (j == buf->pdxf->nb_xtemplates)
1726         {
1727           FIXME("Unknown template %s\n", (char*)buf->value);
1728           buf->level--;
1729           return FALSE;
1730         }
1731         TRACE("Enter %s\n", buf->pdxf->xtemplates[pt->members[i].idx_template].name);
1732         if (!parse_object_parts(buf, FALSE))
1733         {
1734           buf->level--;
1735           return FALSE;
1736         }
1737         buf->level--;
1738         /*if (get_TOKEN(buf) != TOKEN_SEMICOLON)
1739           return FALSE;*/
1740       }
1741       else
1742       {
1743         token = check_TOKEN(buf);
1744         if (token == TOKEN_INTEGER)
1745         {
1746           get_TOKEN(buf);
1747           last_dword = *(DWORD*)buf->value;
1748           TRACE("%s = %d\n", pt->members[i].name, *(DWORD*)buf->value);
1749           /* Assume larger size */
1750           if ((buf->cur_pdata - buf->pxo->pdata + 4) > MAX_DATA_SIZE)
1751           {
1752             WARN("Buffer too small\n");
1753             return FALSE;
1754           }
1755           if (pt->members[i].type == TOKEN_WORD)
1756           {
1757             *(((WORD*)(buf->cur_pdata))) = (WORD)(*(DWORD*)buf->value);
1758             buf->cur_pdata += 2;
1759           }
1760           else if (pt->members[i].type == TOKEN_DWORD)
1761           {
1762             *(((DWORD*)(buf->cur_pdata))) = (DWORD)(*(DWORD*)buf->value);
1763             buf->cur_pdata += 4;
1764           }
1765           else
1766           {
1767             FIXME("Token %d not supported\n", pt->members[i].type);
1768             return FALSE;
1769           }
1770         }
1771         else if (token == TOKEN_FLOAT)
1772         {
1773           get_TOKEN(buf);
1774           TRACE("%s = %f\n", pt->members[i].name, *(float*)buf->value);
1775           /* Assume larger size */
1776           if ((buf->cur_pdata - buf->pxo->pdata + 4) > MAX_DATA_SIZE)
1777           {
1778             WARN("Buffer too small\n");
1779             return FALSE;
1780           }
1781           if (pt->members[i].type == TOKEN_FLOAT)
1782           {
1783             *(((float*)(buf->cur_pdata))) = (float)(*(float*)buf->value);
1784             buf->cur_pdata += 4;
1785           }
1786           else
1787           {
1788             FIXME("Token %d not supported\n", pt->members[i].type);
1789             return FALSE;
1790           }
1791         }
1792         else
1793           return FALSE;
1794       }
1795     }
1796
1797     token = get_TOKEN(buf);
1798     if (token != TOKEN_SEMICOLON)
1799     {
1800       /* Allow comma instead of semicolon in some specific cases */
1801       if (!((token == TOKEN_COMMA) && ((i+1) < pt->nb_members) && (pt->members[i].type == pt->members[i+1].type)
1802         && (!pt->members[i].nb_dims) && (!pt->members[i+1].nb_dims)))
1803         return FALSE;
1804     }
1805   }
1806
1807   return TRUE;
1808 }
1809
1810 static BOOL parse_object_parts(parse_buffer * buf, BOOL allow_optional)
1811 {
1812   if (!parse_object_members_list(buf))
1813     return FALSE;
1814
1815   if (allow_optional)
1816   {
1817     buf->pxo->size = buf->cur_pdata - buf->pxo->pdata;
1818
1819     /* Skip trailing semicolon */
1820     while (check_TOKEN(buf) == TOKEN_SEMICOLON)
1821       get_TOKEN(buf);
1822
1823     while (1)
1824     {
1825       if (check_TOKEN(buf) == TOKEN_OBRACE)
1826       {
1827         int i;
1828         get_TOKEN(buf);
1829         if (get_TOKEN(buf) != TOKEN_NAME)
1830           return FALSE;
1831         if (get_TOKEN(buf) != TOKEN_CBRACE)
1832           return FALSE;
1833         TRACE("Found optional reference %s\n", (char*)buf->value);
1834         for (i = 0; i < buf->nb_pxo_globals; i++)
1835         {
1836           if (!strcmp(buf->pxo_globals[i*MAX_SUBOBJECTS].name, (char*)buf->value))
1837             break;
1838         }
1839         if (i == buf->nb_pxo_globals)
1840         {
1841           ERR("Reference to unknown object %s\n", (char*)buf->value);
1842           return FALSE;
1843         }
1844         buf->pxo->childs[buf->pxo->nb_childs] = &buf->pxo_tab[buf->cur_subobject++];
1845         buf->pxo->childs[buf->pxo->nb_childs]->ptarget = &buf->pxo_globals[i*MAX_SUBOBJECTS];
1846         buf->pxo->nb_childs++;
1847       }
1848       else if (check_TOKEN(buf) == TOKEN_NAME)
1849       {
1850         xobject* pxo = buf->pxo;
1851         buf->pxo = buf->pxo->childs[buf->pxo->nb_childs] = &buf->pxo_tab[buf->cur_subobject++];
1852
1853         TRACE("Enter optional %s\n", (char*)buf->value);
1854         buf->level++;
1855         if (!parse_object(buf))
1856         {
1857           buf->level--;
1858           return FALSE;
1859         }
1860         buf->level--;
1861         buf->pxo = pxo;
1862         buf->pxo->nb_childs++;
1863       }
1864       else
1865         break;
1866     }
1867   }
1868
1869   return TRUE;
1870 }
1871
1872 static BOOL parse_object(parse_buffer * buf)
1873 {
1874   int i;
1875
1876   buf->pxo->pdata = buf->cur_pdata;
1877   buf->pxo->ptarget = NULL;
1878
1879   if (get_TOKEN(buf) != TOKEN_NAME)
1880     return FALSE;
1881
1882   /* To do template lookup */
1883   for (i = 0; i < buf->pdxf->nb_xtemplates; i++)
1884   {
1885     if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[i].name))
1886     {
1887       buf->pxt[buf->level] = &buf->pdxf->xtemplates[i];
1888       memcpy(&buf->pxo->type, &buf->pdxf->xtemplates[i].class_id, 16);
1889       break;
1890     }
1891   }
1892   if (i == buf->pdxf->nb_xtemplates)
1893   {
1894     FIXME("Unknown template %s\n", (char*)buf->value);
1895     return FALSE;
1896   }
1897
1898   if (check_TOKEN(buf) == TOKEN_NAME)
1899   {
1900     get_TOKEN(buf);
1901     strcpy(buf->pxo->name, (char*)buf->value);
1902   }
1903   else
1904     buf->pxo->name[0] = 0;
1905
1906   if (get_TOKEN(buf) != TOKEN_OBRACE)
1907     return FALSE;
1908   if (check_TOKEN(buf) == TOKEN_GUID)
1909   {
1910     get_TOKEN(buf);
1911     memcpy(&buf->pxo->class_id, buf->value, 16);
1912   }
1913   else
1914     memset(&buf->pxo->class_id, 0, 16);
1915
1916   if (!parse_object_parts(buf, TRUE))
1917     return FALSE;
1918   if (get_TOKEN(buf) != TOKEN_CBRACE)
1919     return FALSE;
1920
1921   if (buf->txt)
1922   {
1923     /* Go to the next object */
1924     while (buf->rem_bytes && is_space(*buf->buffer))
1925     {
1926       buf->buffer++;
1927       buf->rem_bytes--;
1928     }
1929   }
1930
1931   return TRUE;
1932 }
1933
1934 /*** IDirectXFileEnumObject methods ***/
1935 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetNextDataObject(IDirectXFileEnumObject* iface, LPDIRECTXFILEDATA* ppDataObj)
1936 {
1937   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1938   IDirectXFileDataImpl* object;
1939   HRESULT hr;
1940   LPBYTE pdata;
1941   
1942   TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
1943
1944   if (!This->buf.rem_bytes)
1945     return DXFILEERR_NOMOREOBJECTS;
1946
1947   hr = IDirectXFileDataImpl_Create(&object);
1948   if (!SUCCEEDED(hr))
1949     return hr;
1950
1951   This->buf.pxo_globals = &This->xobjects[0][0];
1952   This->buf.nb_pxo_globals = This->nb_xobjects;
1953   This->buf.pxo_tab = &This->xobjects[This->nb_xobjects][0];
1954   This->buf.cur_subobject = 0;
1955   This->buf.pxo = &This->buf.pxo_tab[This->buf.cur_subobject++];
1956
1957   pdata = HeapAlloc(GetProcessHeap(), 0, MAX_DATA_SIZE);
1958   if (!pdata)
1959   {
1960     WARN("Out of memory\n");
1961     return DXFILEERR_BADALLOC;
1962   }
1963   This->buf.cur_pdata = pdata;
1964   This->buf.level = 0;
1965
1966   if (!parse_object(&This->buf))
1967   {
1968     TRACE("Object is not correct\n");
1969     HeapFree(GetProcessHeap(), 0, This->buf.pxo->pdata);
1970     return DXFILEERR_PARSEERROR;
1971   }
1972
1973   object->pobj = This->buf.pxo;
1974   object->cur_enum_object = 0;
1975
1976   *ppDataObj = (LPDIRECTXFILEDATA)object;
1977
1978   This->nb_xobjects++;
1979
1980   return DXFILE_OK;
1981 }
1982
1983 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectById(IDirectXFileEnumObject* iface, REFGUID rguid, LPDIRECTXFILEDATA* ppDataObj)
1984 {
1985   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1986
1987   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, rguid, ppDataObj); 
1988
1989   return DXFILEERR_BADVALUE;
1990 }
1991
1992 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectByName(IDirectXFileEnumObject* iface, LPCSTR szName, LPDIRECTXFILEDATA* ppDataObj)
1993 {
1994   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1995
1996   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szName, ppDataObj); 
1997
1998   return DXFILEERR_BADVALUE;
1999 }
2000
2001 static const IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl =
2002 {
2003     IDirectXFileEnumObjectImpl_QueryInterface,
2004     IDirectXFileEnumObjectImpl_AddRef,
2005     IDirectXFileEnumObjectImpl_Release,
2006     IDirectXFileEnumObjectImpl_GetNextDataObject,
2007     IDirectXFileEnumObjectImpl_GetDataObjectById,
2008     IDirectXFileEnumObjectImpl_GetDataObjectByName
2009 };
2010
2011 HRESULT IDirectXFileObjectImpl_Create(IDirectXFileObjectImpl** ppObj)
2012 {
2013     IDirectXFileObjectImpl* object;
2014
2015     TRACE("(%p)\n", ppObj);
2016       
2017     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileObjectImpl));
2018     
2019     object->lpVtbl.lpVtbl = &IDirectXFileObject_Vtbl;
2020     object->ref = 1;
2021
2022     *ppObj = object;
2023     
2024     return S_OK;
2025 }
2026
2027 /*** IUnknown methods ***/
2028 static HRESULT WINAPI IDirectXFileObjectImpl_QueryInterface(IDirectXFileObject* iface, REFIID riid, void** ppvObject)
2029 {
2030   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
2031
2032   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
2033
2034   if (IsEqualGUID(riid, &IID_IUnknown)
2035       || IsEqualGUID(riid, &IID_IDirectXFileObject))
2036   {
2037     IClassFactory_AddRef(iface);
2038     *ppvObject = This;
2039     return S_OK;
2040   }
2041
2042   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
2043   return E_NOINTERFACE;
2044 }
2045
2046 static ULONG WINAPI IDirectXFileObjectImpl_AddRef(IDirectXFileObject* iface)
2047 {
2048   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
2049   ULONG ref = InterlockedIncrement(&This->ref);
2050
2051   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
2052
2053   return ref;
2054 }
2055
2056 static ULONG WINAPI IDirectXFileObjectImpl_Release(IDirectXFileObject* iface)
2057 {
2058   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
2059   ULONG ref = InterlockedDecrement(&This->ref);
2060
2061   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
2062
2063   if (!ref)
2064     HeapFree(GetProcessHeap(), 0, This);
2065
2066   return ref;
2067 }
2068
2069 /*** IDirectXFileObject methods ***/
2070 static HRESULT WINAPI IDirectXFileObjectImpl_GetName(IDirectXFileObject* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
2071 {
2072   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
2073
2074   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
2075
2076   return DXFILEERR_BADVALUE;
2077 }
2078
2079 static HRESULT WINAPI IDirectXFileObjectImpl_GetId(IDirectXFileObject* iface, LPGUID pGuid)
2080 {
2081   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
2082
2083   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
2084
2085   return DXFILEERR_BADVALUE;
2086 }
2087
2088 static const IDirectXFileObjectVtbl IDirectXFileObject_Vtbl =
2089 {
2090     IDirectXFileObjectImpl_QueryInterface,
2091     IDirectXFileObjectImpl_AddRef,
2092     IDirectXFileObjectImpl_Release,
2093     IDirectXFileObjectImpl_GetName,
2094     IDirectXFileObjectImpl_GetId
2095 };
2096
2097 HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj)
2098 {
2099     IDirectXFileSaveObjectImpl* object;
2100
2101     TRACE("(%p)\n", ppObj);
2102
2103     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileSaveObjectImpl));
2104     
2105     object->lpVtbl.lpVtbl = &IDirectXFileSaveObject_Vtbl;
2106     object->ref = 1;
2107
2108     *ppObj = object;
2109     
2110     return S_OK;
2111 }
2112
2113 /*** IUnknown methods ***/
2114 static HRESULT WINAPI IDirectXFileSaveObjectImpl_QueryInterface(IDirectXFileSaveObject* iface, REFIID riid, void** ppvObject)
2115 {
2116   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2117
2118   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
2119
2120   if (IsEqualGUID(riid, &IID_IUnknown)
2121       || IsEqualGUID(riid, &IID_IDirectXFileSaveObject))
2122   {
2123     IClassFactory_AddRef(iface);
2124     *ppvObject = This;
2125     return S_OK;
2126   }
2127
2128   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
2129   return E_NOINTERFACE;
2130 }
2131
2132 static ULONG WINAPI IDirectXFileSaveObjectImpl_AddRef(IDirectXFileSaveObject* iface)
2133 {
2134   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2135   ULONG ref = InterlockedIncrement(&This->ref);
2136
2137   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
2138
2139   return ref;
2140 }
2141
2142 static ULONG WINAPI IDirectXFileSaveObjectImpl_Release(IDirectXFileSaveObject* iface)
2143 {
2144   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2145   ULONG ref = InterlockedDecrement(&This->ref);
2146
2147   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
2148
2149   if (!ref)
2150     HeapFree(GetProcessHeap(), 0, This);
2151
2152   return ref;
2153 }
2154
2155 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveTemplates(IDirectXFileSaveObject* iface, DWORD cTemplates, const GUID** ppguidTemplates)
2156 {
2157   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2158
2159   FIXME("(%p/%p)->(%d,%p) stub!\n", This, iface, cTemplates, ppguidTemplates);
2160
2161   return DXFILEERR_BADVALUE;
2162 }
2163
2164 static HRESULT WINAPI IDirectXFileSaveObjectImpl_CreateDataObject(IDirectXFileSaveObject* iface, REFGUID rguidTemplate, LPCSTR szName, const GUID* pguid, DWORD cbSize, LPVOID pvData, LPDIRECTXFILEDATA* ppDataObj)
2165 {
2166   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2167
2168   FIXME("(%p/%p)->(%p,%s,%p,%d,%p,%p) stub!\n", This, iface, rguidTemplate, szName, pguid, cbSize, pvData, ppDataObj);
2169
2170   return DXFILEERR_BADVALUE;
2171 }
2172
2173 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveData(IDirectXFileSaveObject* iface, LPDIRECTXFILEDATA ppDataObj)
2174 {
2175   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2176
2177   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj); 
2178
2179   return DXFILEERR_BADVALUE;
2180 }
2181
2182 static const IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl =
2183 {
2184     IDirectXFileSaveObjectImpl_QueryInterface,
2185     IDirectXFileSaveObjectImpl_AddRef,
2186     IDirectXFileSaveObjectImpl_Release,
2187     IDirectXFileSaveObjectImpl_SaveTemplates,
2188     IDirectXFileSaveObjectImpl_CreateDataObject,
2189     IDirectXFileSaveObjectImpl_SaveData
2190 };