richedit: Enter at the end of a table row appends a new row.
[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 typedef struct {
83   /* Buffer to parse */
84   LPBYTE buffer;
85   DWORD rem_bytes;
86   /* Misc info */
87   BOOL txt;
88   BYTE value[100];
89   IDirectXFileImpl* pdxf;
90 } parse_buffer;
91
92 static const struct IDirectXFileVtbl IDirectXFile_Vtbl;
93 static const struct IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl;
94 static const struct IDirectXFileDataVtbl IDirectXFileData_Vtbl;
95 static const struct IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl;
96 static const struct IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl;
97 static const struct IDirectXFileObjectVtbl IDirectXFileObject_Vtbl;
98 static const struct IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl;
99
100 HRESULT IDirectXFileImpl_Create(IUnknown* pUnkOuter, LPVOID* ppObj)
101 {
102     IDirectXFileImpl* object;
103
104     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
105       
106     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileImpl));
107     
108     object->lpVtbl.lpVtbl = &IDirectXFile_Vtbl;
109     object->ref = 1;
110
111     *ppObj = object;
112     
113     return S_OK;
114 }
115
116 /*** IUnknown methods ***/
117 static HRESULT WINAPI IDirectXFileImpl_QueryInterface(IDirectXFile* iface, REFIID riid, void** ppvObject)
118 {
119   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
120
121   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
122
123   if (IsEqualGUID(riid, &IID_IUnknown)
124       || IsEqualGUID(riid, &IID_IDirectXFile))
125   {
126     IClassFactory_AddRef(iface);
127     *ppvObject = This;
128     return S_OK;
129   }
130
131   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
132   return E_NOINTERFACE;
133 }
134
135 static ULONG WINAPI IDirectXFileImpl_AddRef(IDirectXFile* iface)
136 {
137   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
138   ULONG ref = InterlockedIncrement(&This->ref);
139
140   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
141
142   return ref;
143 }
144
145 static ULONG WINAPI IDirectXFileImpl_Release(IDirectXFile* iface)
146 {
147   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
148   ULONG ref = InterlockedDecrement(&This->ref);
149
150   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
151
152   if (!ref)
153     HeapFree(GetProcessHeap(), 0, This);
154
155   return ref;
156 }
157
158 /*** IDirectXFile methods ***/
159 static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPVOID pvSource, DXFILELOADOPTIONS dwLoadOptions, LPDIRECTXFILEENUMOBJECT* ppEnumObj)
160 {
161   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
162   IDirectXFileEnumObjectImpl* object;
163   HRESULT hr;
164   DWORD header[4];
165   DWORD size;
166   HANDLE hFile = INVALID_HANDLE_VALUE;
167
168   FIXME("(%p/%p)->(%p,%x,%p) partial stub!\n", This, iface, pvSource, dwLoadOptions, ppEnumObj);
169
170   if (!ppEnumObj)
171     return DXFILEERR_BADVALUE;
172
173   if (dwLoadOptions == DXFILELOAD_FROMFILE)
174   {
175     TRACE("Open source file '%s'\n", (char*)pvSource);
176
177     hFile = CreateFileA((char*)pvSource, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
178     if (hFile == INVALID_HANDLE_VALUE)
179     {
180       TRACE("File '%s' not found\n", (char*)pvSource);
181       return DXFILEERR_FILENOTFOUND;
182     }
183
184     if (!ReadFile(hFile, header, 16, &size, NULL))
185     {
186       hr = DXFILEERR_BADVALUE;
187       goto error;
188     }
189
190     if (size < 16)
191     {
192       hr = DXFILEERR_BADFILETYPE;
193       goto error;
194     }
195
196     if (TRACE_ON(d3dxof))
197     {
198       char string[17];
199       memcpy(string, header, 16);
200       string[16] = 0;
201       TRACE("header = '%s'\n", string);
202     }
203   }
204   else
205   {
206     FIXME("Source type %d is not handled yet\n", dwLoadOptions);
207     hr = DXFILEERR_NOTDONEYET;
208     goto error;
209   }
210
211   if (header[0] != XOFFILE_FORMAT_MAGIC)
212   {
213     hr = DXFILEERR_BADFILETYPE;
214     goto error;
215   }
216
217   if (header[1] != XOFFILE_FORMAT_VERSION)
218   {
219     hr = DXFILEERR_BADFILEVERSION;
220     goto error;
221   }
222
223   if ((header[2] != XOFFILE_FORMAT_BINARY) && (header[2] != XOFFILE_FORMAT_TEXT) && (header[2] != XOFFILE_FORMAT_COMPRESSED))
224   {
225     hr = DXFILEERR_BADFILETYPE;
226     goto error;
227   }
228
229   if (header[2] == XOFFILE_FORMAT_BINARY)
230   {
231     FIXME("Binary format not supported yet\n");
232     hr = DXFILEERR_NOTDONEYET;
233     goto error;
234   }
235
236   if (header[2] == XOFFILE_FORMAT_COMPRESSED)
237   {
238     FIXME("Compressed formats not supported yet\n");
239     hr = DXFILEERR_BADVALUE;
240     goto error;
241   }
242
243   if ((header[3] != XOFFILE_FORMAT_FLOAT_BITS_32) && (header[3] != XOFFILE_FORMAT_FLOAT_BITS_64))
244   {
245     hr = DXFILEERR_BADFILEFLOATSIZE;
246     goto error;
247   }
248
249   TRACE("Header is correct\n");
250
251   hr = IDirectXFileEnumObjectImpl_Create(&object);
252   if (!SUCCEEDED(hr))
253     goto error;
254
255   object->source = dwLoadOptions;
256   object->hFile = hFile;
257
258   *ppEnumObj = (LPDIRECTXFILEENUMOBJECT)object;
259
260   return DXFILE_OK;
261
262 error:
263   if (hFile != INVALID_HANDLE_VALUE)
264     CloseHandle(hFile);
265   *ppEnumObj = NULL;
266
267   return hr;
268 }
269
270 static HRESULT WINAPI IDirectXFileImpl_CreateSaveObject(IDirectXFile* iface, LPCSTR szFileName, DXFILEFORMAT dwFileFormat, LPDIRECTXFILESAVEOBJECT* ppSaveObj)
271 {
272   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
273
274   FIXME("(%p/%p)->(%s,%x,%p) stub!\n", This, iface, szFileName, dwFileFormat, ppSaveObj);
275
276   return DXFILEERR_BADVALUE;
277 }
278
279 static BOOL read_bytes(parse_buffer * buf, LPVOID data, DWORD size)
280 {
281   if (buf->rem_bytes < size)
282     return FALSE;
283   memcpy(data, buf->buffer, size);
284   buf->buffer += size;
285   buf->rem_bytes -= size;
286   return TRUE;
287 }
288
289 static void dump_TOKEN(WORD token)
290 {
291 #define DUMP_TOKEN(t) case t: TRACE(#t "\n"); break
292   switch(token)
293   {
294     DUMP_TOKEN(TOKEN_NAME);
295     DUMP_TOKEN(TOKEN_STRING);
296     DUMP_TOKEN(TOKEN_INTEGER);
297     DUMP_TOKEN(TOKEN_GUID);
298     DUMP_TOKEN(TOKEN_INTEGER_LIST);
299     DUMP_TOKEN(TOKEN_FLOAT_LIST);
300     DUMP_TOKEN(TOKEN_OBRACE);
301     DUMP_TOKEN(TOKEN_CBRACE);
302     DUMP_TOKEN(TOKEN_OPAREN);
303     DUMP_TOKEN(TOKEN_CPAREN);
304     DUMP_TOKEN(TOKEN_OBRACKET);
305     DUMP_TOKEN(TOKEN_CBRACKET);
306     DUMP_TOKEN(TOKEN_OANGLE);
307     DUMP_TOKEN(TOKEN_CANGLE);
308     DUMP_TOKEN(TOKEN_DOT);
309     DUMP_TOKEN(TOKEN_COMMA);
310     DUMP_TOKEN(TOKEN_SEMICOLON);
311     DUMP_TOKEN(TOKEN_TEMPLATE);
312     DUMP_TOKEN(TOKEN_WORD);
313     DUMP_TOKEN(TOKEN_DWORD);
314     DUMP_TOKEN(TOKEN_FLOAT);
315     DUMP_TOKEN(TOKEN_DOUBLE);
316     DUMP_TOKEN(TOKEN_CHAR);
317     DUMP_TOKEN(TOKEN_UCHAR);
318     DUMP_TOKEN(TOKEN_SWORD);
319     DUMP_TOKEN(TOKEN_SDWORD);
320     DUMP_TOKEN(TOKEN_VOID);
321     DUMP_TOKEN(TOKEN_LPSTR);
322     DUMP_TOKEN(TOKEN_UNICODE);
323     DUMP_TOKEN(TOKEN_CSTRING);
324     DUMP_TOKEN(TOKEN_ARRAY);
325     default:
326       if (0)
327         TRACE("Unknown token %d\n", token);
328       break;
329   }
330 #undef DUMP_TOKEN
331 }
332
333 static BOOL is_space(char c)
334 {
335   switch (c)
336   {
337     case 0x00:
338     case 0x0D:
339     case 0x0A:
340     case ' ':
341     case '\t':
342       return TRUE;
343   }
344   return FALSE;
345 }
346
347 static BOOL is_operator(char c)
348 {
349   switch(c)
350   {
351     case '{':
352     case '}':
353     case '[':
354     case ']':
355     case '(':
356     case ')':
357     case '<':
358     case '>':
359     case ',':
360     case ';':
361       return TRUE;
362   }
363   return FALSE;
364 }
365
366 static inline BOOL is_separator(char c)
367 {
368   return is_space(c) || is_operator(c);
369 }
370
371 static WORD get_operator_token(char c)
372 {
373   switch(c)
374   {
375     case '{':
376       return TOKEN_OBRACE;
377     case '}':
378       return TOKEN_CBRACE;
379     case '[':
380       return TOKEN_OBRACKET;
381     case ']':
382       return TOKEN_CBRACKET;
383     case '(':
384       return TOKEN_OPAREN;
385     case ')':
386       return TOKEN_CPAREN;
387     case '<':
388       return TOKEN_OANGLE;
389     case '>':
390       return TOKEN_CANGLE;
391     case ',':
392       return TOKEN_COMMA;
393     case ';':
394       return TOKEN_SEMICOLON;
395   }
396   return 0;
397 }
398
399 static BOOL is_keyword(parse_buffer* buf, const char* keyword)
400 {
401   DWORD len = strlen(keyword);
402   if (!strncmp((char*)buf->buffer, keyword,len) && is_separator(*(buf->buffer+len)))
403   {
404     buf->buffer += len;
405     buf->rem_bytes -= len;
406     return TRUE;
407   }
408   return FALSE;
409 }
410
411 static WORD get_keyword_token(parse_buffer* buf)
412 {
413   if (is_keyword(buf, "template"))
414     return TOKEN_TEMPLATE;
415   if (is_keyword(buf, "WORD"))
416     return TOKEN_WORD;
417   if (is_keyword(buf, "DWORD"))
418     return TOKEN_DWORD;
419   if (is_keyword(buf, "FLOAT"))
420     return TOKEN_FLOAT;
421   if (is_keyword(buf, "DOUBLE"))
422     return TOKEN_DOUBLE;
423   if (is_keyword(buf, "CHAR"))
424     return TOKEN_CHAR;
425   if (is_keyword(buf, "UCHAR"))
426     return TOKEN_UCHAR;
427   if (is_keyword(buf, "SWORD"))
428     return TOKEN_SWORD;
429   if (is_keyword(buf, "SDWORD"))
430     return TOKEN_SDWORD;
431   if (is_keyword(buf, "VOID"))
432     return TOKEN_VOID;
433   if (is_keyword(buf, "STRING"))
434     return TOKEN_LPSTR;
435   if (is_keyword(buf, "UNICODE"))
436     return TOKEN_UNICODE;
437   if (is_keyword(buf, "CSTRING"))
438     return TOKEN_CSTRING;
439   if (is_keyword(buf, "array"))
440     return TOKEN_ARRAY;
441
442   return 0;
443 }
444
445 static BOOL is_guid(parse_buffer* buf)
446 {
447   char tmp[50];
448   DWORD pos = 1;
449   GUID class_id;
450   DWORD tab[10];
451   int ret;
452
453   if (*buf->buffer != '<')
454     return FALSE;
455   tmp[0] = '<';
456   while (*(buf->buffer+pos) != '>')
457   {
458     tmp[pos] = *(buf->buffer+pos);
459     pos++;
460   }
461   tmp[pos++] = '>';
462   tmp[pos] = 0;
463   if (pos != 38 /* <+36+> */)
464   {
465     TRACE("Wrong guid %s (%d)\n", tmp, pos);
466     return FALSE;
467   }
468   buf->buffer += pos;
469   buf->rem_bytes -= pos;
470
471   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);
472   if (ret != 11)
473   {
474     TRACE("Wrong guid %s (%d)\n", tmp, pos);
475     return FALSE;
476   }
477   TRACE("Found guid %s (%d)\n", tmp, pos);
478
479   class_id.Data2 = tab[0];
480   class_id.Data3 = tab[1];
481   class_id.Data4[0] = tab[2];
482   class_id.Data4[1] = tab[3];
483   class_id.Data4[2] = tab[4];
484   class_id.Data4[3] = tab[5];
485   class_id.Data4[4] = tab[6];
486   class_id.Data4[5] = tab[7];
487   class_id.Data4[6] = tab[8];
488   class_id.Data4[7] = tab[9];
489
490   *(GUID*)buf->value = class_id;
491
492   return TRUE;
493 }
494
495 static BOOL is_name(parse_buffer* buf)
496 {
497   char tmp[50];
498   DWORD pos = 0;
499   char c;
500   BOOL error = 0;
501   while (!is_separator(c = *(buf->buffer+pos)))
502   {
503     if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9'))))
504       error = 1;
505     tmp[pos++] = c;
506   }
507   tmp[pos] = 0;
508
509   if (error)
510   {
511     TRACE("Wrong name %s\n", tmp);
512     return FALSE;
513   }
514
515   buf->buffer += pos;
516   buf->rem_bytes -= pos;
517
518   TRACE("Found name %s\n", tmp);
519   strcpy((char*)buf->value, tmp);
520
521   return TRUE;
522 }
523
524 static BOOL is_integer(parse_buffer* buf)
525 {
526   char tmp[50];
527   DWORD pos = 0;
528   char c;
529   DWORD integer;
530
531   while (!is_separator(c = *(buf->buffer+pos)))
532   {
533     if (!((c >= '0') && (c <= '9')))
534       return FALSE;
535     tmp[pos++] = c;
536   }
537   tmp[pos] = 0;
538
539   buf->buffer += pos;
540   buf->rem_bytes -= pos;
541
542   sscanf(tmp, "%d", &integer);
543
544   TRACE("Found integer %s - %d\n", tmp, integer);
545
546   *(WORD*)buf->value = integer;
547
548   return TRUE;
549 }
550
551 static WORD parse_TOKEN_dbg_opt(parse_buffer * buf, BOOL show_token)
552 {
553   WORD token;
554
555   if (buf->txt)
556   {
557     while(1)
558     {
559       char c;
560       if (!read_bytes(buf, &c, 1))
561         return 0;
562       /*TRACE("char = '%c'\n", is_space(c) ? ' ' : c);*/
563       if ((c == '#') || (c == '/'))
564       {
565         /* Handle comment (# or //) */
566         if (c == '/')
567         {
568           if (!read_bytes(buf, &c, 1))
569             return 0;
570           if (c != '/')
571             return 0;
572         }
573         c = 0;
574         while (c != 0x0A)
575         {
576           if (!read_bytes(buf, &c, 1))
577             return 0;
578         }
579         continue;
580       }
581       if (is_space(c))
582         continue;
583       if (is_operator(c) && (c != '<'))
584       {
585         token = get_operator_token(c);
586         break;
587       }
588       else if (c == '.')
589       {
590         token = TOKEN_DOT;
591         break;
592       }
593       else
594       {
595         buf->buffer -= 1;
596         buf->rem_bytes += 1;
597
598         if ((token = get_keyword_token(buf)))
599           break;
600
601         if (is_guid(buf))
602         {
603           token = TOKEN_GUID;
604           break;
605         }
606         if (is_integer(buf))
607         {
608           token = TOKEN_INTEGER;
609           break;
610         }
611         if (is_name(buf))
612         {
613           token = TOKEN_NAME;
614           break;
615         }
616
617         FIXME("Unrecognize element\n");
618         return 0;
619       }
620     }
621   }
622   else
623   {
624     if (!read_bytes(buf, &token, 2))
625       return 0;
626   }
627
628   switch(token)
629   {
630     case TOKEN_NAME:
631     case TOKEN_STRING:
632     case TOKEN_INTEGER:
633     case TOKEN_GUID:
634     case TOKEN_INTEGER_LIST:
635     case TOKEN_FLOAT_LIST:
636     case TOKEN_OBRACE:
637     case TOKEN_CBRACE:
638     case TOKEN_OPAREN:
639     case TOKEN_CPAREN:
640     case TOKEN_OBRACKET:
641     case TOKEN_CBRACKET:
642     case TOKEN_OANGLE:
643     case TOKEN_CANGLE:
644     case TOKEN_DOT:
645     case TOKEN_COMMA:
646     case TOKEN_SEMICOLON:
647     case TOKEN_TEMPLATE:
648     case TOKEN_WORD:
649     case TOKEN_DWORD:
650     case TOKEN_FLOAT:
651     case TOKEN_DOUBLE:
652     case TOKEN_CHAR:
653     case TOKEN_UCHAR:
654     case TOKEN_SWORD:
655     case TOKEN_SDWORD:
656     case TOKEN_VOID:
657     case TOKEN_LPSTR:
658     case TOKEN_UNICODE:
659     case TOKEN_CSTRING:
660     case TOKEN_ARRAY:
661       break;
662     default:
663       return 0;
664   }
665
666   if (show_token)
667     dump_TOKEN(token);
668
669   return token;
670 }
671
672 static const char* get_primitive_string(WORD token)
673 {
674   switch(token)
675   {
676     case TOKEN_WORD:
677       return "WORD";
678     case TOKEN_DWORD:
679       return "DWORD";
680     case TOKEN_FLOAT:
681       return "FLOAT";
682     case TOKEN_DOUBLE:
683       return "DOUBLE";
684     case TOKEN_CHAR:
685       return "CHAR";
686     case TOKEN_UCHAR:
687       return "UCHAR";
688     case TOKEN_SWORD:
689       return "SWORD";
690     case TOKEN_SDWORD:
691       return "SDWORD";
692     case TOKEN_VOID:
693       return "VOID";
694     case TOKEN_LPSTR:
695       return "STRING";
696     case TOKEN_UNICODE:
697       return "UNICODE";
698     case TOKEN_CSTRING:
699       return "CSTRING ";
700     default:
701       break;
702   }
703   return NULL;
704 }
705
706 static inline WORD parse_TOKEN(parse_buffer * buf)
707 {
708   return parse_TOKEN_dbg_opt(buf, TRUE);
709 }
710
711 static WORD check_TOKEN(parse_buffer * buf)
712 {
713   WORD token;
714
715   if (buf->txt)
716   {
717     parse_buffer save = *buf;
718     /*TRACE("check: ");*/
719     token = parse_TOKEN_dbg_opt(buf, FALSE);
720     *buf = save;
721     return token;
722   }
723
724   if (!read_bytes(buf, &token, 2))
725     return 0;
726   buf->buffer -= 2;
727   buf->rem_bytes += 2;
728   if (0)
729   {
730     TRACE("check: ");
731     dump_TOKEN(token);
732   }
733   return token;
734 }
735
736 static inline BOOL is_primitive_type(WORD token)
737 {
738   BOOL ret;
739   switch(token)
740   {
741     case TOKEN_WORD:
742     case TOKEN_DWORD:
743     case TOKEN_FLOAT:
744     case TOKEN_DOUBLE:
745     case TOKEN_CHAR:
746     case TOKEN_UCHAR:
747     case TOKEN_SWORD:
748     case TOKEN_SDWORD:
749     case TOKEN_LPSTR:
750     case TOKEN_UNICODE:
751     case TOKEN_CSTRING:
752       ret = 1;
753       break;
754     default:
755       ret = 0;
756       break;
757   }
758   return ret;
759 }
760
761 static BOOL parse_name(parse_buffer * buf)
762 {
763   DWORD count;
764   char strname[100];
765
766   if (parse_TOKEN(buf) != TOKEN_NAME)
767     return FALSE;
768   if (buf->txt)
769     return TRUE;
770   if (!read_bytes(buf, &count, 4))
771     return FALSE;
772   if (!read_bytes(buf, strname, count))
773     return FALSE;
774   strname[count] = 0;
775   /*TRACE("name = %s\n", strname);*/
776
777   strcpy((char*)buf->value, strname);
778
779   return TRUE;
780 }
781
782 static BOOL parse_class_id(parse_buffer * buf)
783 {
784   char strguid[38];
785   GUID class_id;
786
787   if (parse_TOKEN(buf) != TOKEN_GUID)
788     return FALSE;
789   if (buf->txt)
790     return TRUE;
791   if (!read_bytes(buf, &class_id, 16))
792     return FALSE;
793   sprintf(strguid, CLSIDFMT, class_id.Data1, class_id.Data2, class_id.Data3, class_id.Data4[0],
794     class_id.Data4[1], class_id.Data4[2], class_id.Data4[3], class_id.Data4[4], class_id.Data4[5], class_id.Data4[6], class_id.Data4[7]);
795   /*TRACE("guid = {%s}\n", strguid);*/
796
797   *(GUID*)buf->value = class_id;
798
799   return TRUE;
800 }
801
802 static BOOL parse_integer(parse_buffer * buf)
803 {
804   DWORD integer;
805
806   if (parse_TOKEN(buf) != TOKEN_INTEGER)
807     return FALSE;
808   if (buf->txt)
809     return TRUE;
810   if (!read_bytes(buf, &integer, 4))
811     return FALSE;
812   /*TRACE("integer = %ld\n", integer);*/
813
814   *(DWORD*)buf->value = integer;
815
816   return TRUE;
817 }
818
819 static BOOL parse_template_option_info(parse_buffer * buf)
820 {
821   xtemplate* cur_template = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates];
822
823   if (check_TOKEN(buf) == TOKEN_DOT)
824   {
825     parse_TOKEN(buf);
826     if (parse_TOKEN(buf) != TOKEN_DOT)
827       return FALSE;
828     if (parse_TOKEN(buf) != TOKEN_DOT)
829       return FALSE;
830     cur_template->open = TRUE;
831   }
832   else
833   {
834     while (1)
835     {
836       if (!parse_name(buf))
837         return FALSE;
838       strcpy(cur_template->childs[cur_template->nb_childs], (char*)buf->value);
839       if (check_TOKEN(buf) == TOKEN_GUID)
840         if (!parse_class_id(buf))
841           return FALSE;
842       cur_template->nb_childs++;
843       if (check_TOKEN(buf) != TOKEN_COMMA)
844         break;
845       parse_TOKEN(buf);
846     }
847     cur_template->open = FALSE;
848   }
849
850   return TRUE;
851 }
852
853 static BOOL parse_template_members_list(parse_buffer * buf)
854 {
855   parse_buffer save1;
856   int idx_member = 0;
857   member* cur_member;
858
859   while (1)
860   {
861     cur_member = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[idx_member];
862     save1 = *buf;
863
864     if (check_TOKEN(buf) == TOKEN_NAME)
865     {
866       if (!parse_name(buf))
867         break;
868       while (cur_member->idx_template < buf->pdxf->nb_xtemplates)
869       {
870         if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[cur_member->idx_template].name))
871           break;
872         cur_member->idx_template++;
873       }
874       if (cur_member->idx_template == buf->pdxf->nb_xtemplates)
875       {
876         TRACE("Reference to a nonexistent template '%s'\n", (char*)buf->value);
877         return FALSE;
878       }
879       if (check_TOKEN(buf) == TOKEN_NAME)
880         if (!parse_name(buf))
881           break;
882       if (parse_TOKEN(buf) != TOKEN_SEMICOLON)
883         break;
884       cur_member->type = TOKEN_NAME;
885       strcpy(cur_member->name, (char*)buf->value);
886       idx_member++;
887     }
888     else if (check_TOKEN(buf) == TOKEN_ARRAY)
889     {
890       parse_buffer save2;
891       WORD token;
892       int nb_dims = 0;
893
894       parse_TOKEN(buf);
895       token = check_TOKEN(buf);
896       if (is_primitive_type(token))
897       {
898         parse_TOKEN(buf);
899         cur_member->type = token;
900       }
901       else
902       {
903         if (!parse_name(buf))
904           break;
905         cur_member->type = TOKEN_NAME;
906         cur_member->idx_template = 0;
907         while (cur_member->idx_template < buf->pdxf->nb_xtemplates)
908         {
909           if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[cur_member->idx_template].name))
910             break;
911           cur_member->idx_template++;
912         }
913         if (cur_member->idx_template == buf->pdxf->nb_xtemplates)
914         {
915           TRACE("Reference to nonexistent template '%s'\n", (char*)buf->value);
916           return FALSE;
917         }
918       }
919       if (!parse_name(buf))
920         break;
921       strcpy(cur_member->name, (char*)buf->value);
922       save2 = *buf;
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         parse_TOKEN(buf);
931         if (check_TOKEN(buf) == TOKEN_INTEGER)
932         {
933           if (!parse_integer(buf))
934             break;
935           cur_member->dim_fixed[nb_dims] = TRUE;
936           cur_member->dim_value[nb_dims] = *(DWORD*)buf->value;
937         }
938         else
939         {
940           if (!parse_name(buf))
941             break;
942           cur_member->dim_fixed[nb_dims] = FALSE;
943           /* Hack: Assume array size is specified in previous member */
944           cur_member->dim_value[nb_dims] = idx_member - 1;
945         }
946         if (parse_TOKEN(buf) != TOKEN_CBRACKET)
947           break;
948         save2 = *buf;
949         nb_dims++;
950       }
951       *buf = save2;
952       if (parse_TOKEN(buf) != TOKEN_SEMICOLON)
953         break;
954       cur_member->nb_dims = nb_dims;
955       idx_member++;
956     }
957     else if (is_primitive_type(check_TOKEN(buf)))
958     {
959       cur_member->type = check_TOKEN(buf);
960       parse_TOKEN(buf);
961       if (check_TOKEN(buf) == TOKEN_NAME)
962         if (!parse_name(buf))
963           break;
964       strcpy(cur_member->name, (char*)buf->value);
965       if (parse_TOKEN(buf) != TOKEN_SEMICOLON)
966         break;
967       idx_member++;
968     }
969     else
970       break;
971   }
972
973   *buf = save1;
974   buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].nb_members = idx_member;
975
976   return TRUE;
977 }
978
979 static BOOL parse_template_parts(parse_buffer * buf)
980 {
981   if (check_TOKEN(buf) == TOKEN_OBRACKET)
982   {
983     parse_TOKEN(buf);
984     if (!parse_template_option_info(buf))
985       return FALSE;
986     if (parse_TOKEN(buf) != TOKEN_CBRACKET)
987       return FALSE;
988   }
989   else
990   {
991     if (!parse_template_members_list(buf))
992       return FALSE;
993     if (check_TOKEN(buf) == TOKEN_OBRACKET)
994     {
995       parse_TOKEN(buf);
996       if (!parse_template_option_info(buf))
997         return FALSE;
998       if (parse_TOKEN(buf) != TOKEN_CBRACKET)
999        return FALSE;
1000     }
1001   }
1002
1003   return TRUE;
1004 }
1005
1006 static BOOL parse_template(parse_buffer * buf)
1007 {
1008   if (parse_TOKEN(buf) != TOKEN_TEMPLATE)
1009     return FALSE;
1010   if (!parse_name(buf))
1011     return FALSE;
1012   strcpy(buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].name, (char*)buf->value);
1013   if (parse_TOKEN(buf) != TOKEN_OBRACE)
1014     return FALSE;
1015   if (!parse_class_id(buf))
1016     return FALSE;
1017   buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].class_id = *(GUID*)buf->value;
1018   if (!parse_template_parts(buf))
1019     return FALSE;
1020   if (parse_TOKEN(buf) != TOKEN_CBRACE)
1021     return FALSE;
1022   if (buf->txt)
1023   {
1024     /* Go to the next template */
1025     while (buf->rem_bytes && is_space(*buf->buffer))
1026     {
1027       buf->buffer++;
1028       buf->rem_bytes--;
1029     }
1030   }
1031
1032   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));
1033   buf->pdxf->nb_xtemplates++;
1034
1035   return TRUE;
1036 }
1037
1038 static HRESULT WINAPI IDirectXFileImpl_RegisterTemplates(IDirectXFile* iface, LPVOID pvData, DWORD cbSize)
1039 {
1040   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
1041   DWORD token_header;
1042   parse_buffer buf;
1043
1044   buf.buffer = (LPBYTE)pvData;
1045   buf.rem_bytes = cbSize;
1046   buf.txt = FALSE;
1047   buf.pdxf = This;
1048
1049   FIXME("(%p/%p)->(%p,%d) partial stub!\n", This, iface, pvData, cbSize);
1050
1051   if (!pvData)
1052     return DXFILEERR_BADVALUE;
1053
1054   if (cbSize < 16)
1055     return DXFILEERR_BADFILETYPE;
1056
1057   if (TRACE_ON(d3dxof))
1058   {
1059     char string[17];
1060     memcpy(string, pvData, 16);
1061     string[16] = 0;
1062     TRACE("header = '%s'\n", string);
1063   }
1064
1065   read_bytes(&buf, &token_header, 4);
1066
1067   if (token_header != XOFFILE_FORMAT_MAGIC)
1068     return DXFILEERR_BADFILETYPE;
1069
1070   read_bytes(&buf, &token_header, 4);
1071
1072   if (token_header != XOFFILE_FORMAT_VERSION)
1073     return DXFILEERR_BADFILEVERSION;
1074
1075   read_bytes(&buf, &token_header, 4);
1076
1077   if ((token_header != XOFFILE_FORMAT_BINARY) && (token_header != XOFFILE_FORMAT_TEXT) && (token_header != XOFFILE_FORMAT_COMPRESSED))
1078     return DXFILEERR_BADFILETYPE;
1079
1080   if (token_header == XOFFILE_FORMAT_TEXT)
1081   {
1082     buf.txt = TRUE;
1083   }
1084
1085   if (token_header == XOFFILE_FORMAT_COMPRESSED)
1086   {
1087     FIXME("Compressed formats not supported yet\n");
1088     return DXFILEERR_BADVALUE;
1089   }
1090
1091   read_bytes(&buf, &token_header, 4);
1092
1093   if ((token_header != XOFFILE_FORMAT_FLOAT_BITS_32) && (token_header != XOFFILE_FORMAT_FLOAT_BITS_64))
1094     return DXFILEERR_BADFILEFLOATSIZE;
1095
1096   TRACE("Header is correct\n");
1097
1098   while (buf.rem_bytes)
1099   {
1100     if (!parse_template(&buf))
1101     {
1102       TRACE("Template is not correct\n");
1103       return DXFILEERR_BADVALUE;
1104     }
1105     else
1106     {
1107       TRACE("Template successfully parsed:\n");
1108       if (TRACE_ON(d3dxof))
1109       {
1110         int i,j,k;
1111         GUID* clsid;
1112
1113         i = This->nb_xtemplates - 1;
1114         clsid = &This->xtemplates[i].class_id;
1115
1116         DPRINTF("template %s\n", This->xtemplates[i].name);
1117         DPRINTF("{\n");
1118         DPRINTF(CLSIDFMT "\n", clsid->Data1, clsid->Data2, clsid->Data3, clsid->Data4[0],
1119           clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7]);
1120         for (j = 0; j < This->xtemplates[i].nb_members; j++)
1121         {
1122           if (This->xtemplates[i].members[j].nb_dims)
1123             DPRINTF("array ");
1124           if (This->xtemplates[i].members[j].type == TOKEN_NAME)
1125             DPRINTF("%s ", This->xtemplates[This->xtemplates[i].members[j].idx_template].name);
1126           else
1127             DPRINTF("%s ", get_primitive_string(This->xtemplates[i].members[j].type));
1128           DPRINTF("%s", This->xtemplates[i].members[j].name);
1129           for (k = 0; k < This->xtemplates[i].members[j].nb_dims; k++)
1130           {
1131             if (This->xtemplates[i].members[j].dim_fixed[k])
1132               DPRINTF("[%d]", This->xtemplates[i].members[j].dim_value[k]);
1133             else
1134               DPRINTF("[%s]", This->xtemplates[i].members[This->xtemplates[i].members[j].dim_value[k]].name);
1135           }
1136           DPRINTF(";\n");
1137         }
1138         if (This->xtemplates[i].open)
1139           DPRINTF("[...]\n");
1140         else if (This->xtemplates[i].nb_childs)
1141         {
1142           DPRINTF("[%s", This->xtemplates[i].childs[0]);
1143           for (j = 1; j < This->xtemplates[i].nb_childs; j++)
1144             DPRINTF(",%s", This->xtemplates[i].childs[j]);
1145           DPRINTF("]\n");
1146         }
1147         DPRINTF("}\n");
1148       }
1149     }
1150   }
1151
1152   if (TRACE_ON(d3dxof))
1153   {
1154     int i;
1155     TRACE("Registered templates (%d):\n", This->nb_xtemplates);
1156     for (i = 0; i < This->nb_xtemplates; i++)
1157       DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
1158   }
1159
1160   return DXFILE_OK;
1161 }
1162
1163 static const IDirectXFileVtbl IDirectXFile_Vtbl =
1164 {
1165   IDirectXFileImpl_QueryInterface,
1166   IDirectXFileImpl_AddRef,
1167   IDirectXFileImpl_Release,
1168   IDirectXFileImpl_CreateEnumObject,
1169   IDirectXFileImpl_CreateSaveObject,
1170   IDirectXFileImpl_RegisterTemplates
1171 };
1172
1173 HRESULT IDirectXFileBinaryImpl_Create(IDirectXFileBinaryImpl** ppObj)
1174 {
1175     IDirectXFileBinaryImpl* object;
1176
1177     TRACE("(%p)\n", ppObj);
1178       
1179     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileBinaryImpl));
1180     
1181     object->lpVtbl.lpVtbl = &IDirectXFileBinary_Vtbl;
1182     object->ref = 1;
1183
1184     *ppObj = object;
1185     
1186     return DXFILE_OK;
1187 }
1188
1189 /*** IUnknown methods ***/
1190 static HRESULT WINAPI IDirectXFileBinaryImpl_QueryInterface(IDirectXFileBinary* iface, REFIID riid, void** ppvObject)
1191 {
1192   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1193
1194   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1195
1196   if (IsEqualGUID(riid, &IID_IUnknown)
1197       || IsEqualGUID(riid, &IID_IDirectXFileObject)
1198       || IsEqualGUID(riid, &IID_IDirectXFileBinary))
1199   {
1200     IClassFactory_AddRef(iface);
1201     *ppvObject = This;
1202     return S_OK;
1203   }
1204
1205   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1206   return E_NOINTERFACE;
1207 }
1208
1209 static ULONG WINAPI IDirectXFileBinaryImpl_AddRef(IDirectXFileBinary* iface)
1210 {
1211   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1212   ULONG ref = InterlockedIncrement(&This->ref);
1213
1214   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1215
1216   return ref;
1217 }
1218
1219 static ULONG WINAPI IDirectXFileBinaryImpl_Release(IDirectXFileBinary* iface)
1220 {
1221   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1222   ULONG ref = InterlockedDecrement(&This->ref);
1223
1224   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1225
1226   if (!ref)
1227     HeapFree(GetProcessHeap(), 0, This);
1228
1229   return ref;
1230 }
1231
1232 /*** IDirectXFileObject methods ***/
1233 static HRESULT WINAPI IDirectXFileBinaryImpl_GetName(IDirectXFileBinary* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1234
1235 {
1236   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1237
1238   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
1239
1240   return DXFILEERR_BADVALUE;
1241 }
1242
1243 static HRESULT WINAPI IDirectXFileBinaryImpl_GetId(IDirectXFileBinary* iface, LPGUID pGuid)
1244 {
1245   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1246
1247   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
1248
1249   return DXFILEERR_BADVALUE;
1250 }
1251
1252 /*** IDirectXFileBinary methods ***/
1253 static HRESULT WINAPI IDirectXFileBinaryImpl_GetSize(IDirectXFileBinary* iface, DWORD* pcbSize)
1254 {
1255   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1256
1257   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pcbSize); 
1258
1259   return DXFILEERR_BADVALUE;
1260 }
1261
1262 static HRESULT WINAPI IDirectXFileBinaryImpl_GetMimeType(IDirectXFileBinary* iface, LPCSTR* pszMimeType)
1263 {
1264   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1265
1266   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pszMimeType);
1267
1268   return DXFILEERR_BADVALUE;
1269 }
1270
1271 static HRESULT WINAPI IDirectXFileBinaryImpl_Read(IDirectXFileBinary* iface, LPVOID pvData, DWORD cbSize, LPDWORD pcbRead)
1272 {
1273   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1274
1275   FIXME("(%p/%p)->(%p, %d, %p) stub!\n", This, iface, pvData, cbSize, pcbRead);
1276
1277   return DXFILEERR_BADVALUE;
1278 }
1279
1280 static const IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl =
1281 {
1282     IDirectXFileBinaryImpl_QueryInterface,
1283     IDirectXFileBinaryImpl_AddRef,
1284     IDirectXFileBinaryImpl_Release,
1285     IDirectXFileBinaryImpl_GetName,
1286     IDirectXFileBinaryImpl_GetId,
1287     IDirectXFileBinaryImpl_GetSize,
1288     IDirectXFileBinaryImpl_GetMimeType,
1289     IDirectXFileBinaryImpl_Read
1290 };
1291
1292 HRESULT IDirectXFileDataImpl_Create(IDirectXFileDataImpl** ppObj)
1293 {
1294     IDirectXFileDataImpl* object;
1295
1296     TRACE("(%p)\n", ppObj);
1297       
1298     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataImpl));
1299     
1300     object->lpVtbl.lpVtbl = &IDirectXFileData_Vtbl;
1301     object->ref = 1;
1302
1303     *ppObj = object;
1304     
1305     return S_OK;
1306 }
1307
1308 /*** IUnknown methods ***/
1309 static HRESULT WINAPI IDirectXFileDataImpl_QueryInterface(IDirectXFileData* iface, REFIID riid, void** ppvObject)
1310 {
1311   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1312
1313   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1314
1315   if (IsEqualGUID(riid, &IID_IUnknown)
1316       || IsEqualGUID(riid, &IID_IDirectXFileObject)
1317       || IsEqualGUID(riid, &IID_IDirectXFileData))
1318   {
1319     IClassFactory_AddRef(iface);
1320     *ppvObject = This;
1321     return S_OK;
1322   }
1323
1324   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1325   return E_NOINTERFACE;
1326 }
1327
1328 static ULONG WINAPI IDirectXFileDataImpl_AddRef(IDirectXFileData* iface)
1329 {
1330   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1331   ULONG ref = InterlockedIncrement(&This->ref);
1332
1333   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1334
1335   return ref;
1336 }
1337
1338 static ULONG WINAPI IDirectXFileDataImpl_Release(IDirectXFileData* iface)
1339 {
1340   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1341   ULONG ref = InterlockedDecrement(&This->ref);
1342
1343   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1344
1345   if (!ref)
1346     HeapFree(GetProcessHeap(), 0, This);
1347
1348   return ref;
1349 }
1350
1351 /*** IDirectXFileObject methods ***/
1352 static HRESULT WINAPI IDirectXFileDataImpl_GetName(IDirectXFileData* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1353
1354 {
1355   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1356
1357   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
1358
1359   return DXFILEERR_BADVALUE;
1360 }
1361
1362 static HRESULT WINAPI IDirectXFileDataImpl_GetId(IDirectXFileData* iface, LPGUID pGuid)
1363 {
1364   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1365
1366   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
1367
1368   return DXFILEERR_BADVALUE;
1369 }
1370
1371 /*** IDirectXFileData methods ***/
1372 static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCSTR szMember, DWORD* pcbSize, void** ppvData)
1373 {
1374   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1375
1376   FIXME("(%p/%p)->(%s,%p,%p) stub!\n", This, iface, szMember, pcbSize, ppvData); 
1377
1378   return DXFILEERR_BADVALUE;
1379 }
1380
1381 static HRESULT WINAPI IDirectXFileDataImpl_GetType(IDirectXFileData* iface, const GUID** pguid)
1382 {
1383   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1384
1385   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pguid); 
1386
1387   return DXFILEERR_BADVALUE;
1388 }
1389
1390 static HRESULT WINAPI IDirectXFileDataImpl_GetNextObject(IDirectXFileData* iface, LPDIRECTXFILEOBJECT* ppChildObj)
1391 {
1392   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1393
1394   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppChildObj); 
1395
1396   return DXFILEERR_BADVALUE;
1397 }
1398
1399 static HRESULT WINAPI IDirectXFileDataImpl_AddDataObject(IDirectXFileData* iface, LPDIRECTXFILEDATA pDataObj)
1400 {
1401   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1402
1403   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pDataObj); 
1404
1405   return DXFILEERR_BADVALUE;
1406 }
1407
1408 static HRESULT WINAPI IDirectXFileDataImpl_AddDataReference(IDirectXFileData* iface, LPCSTR szRef, const GUID* pguidRef)
1409 {
1410   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1411
1412   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szRef, pguidRef); 
1413
1414   return DXFILEERR_BADVALUE;
1415 }
1416
1417 static HRESULT WINAPI IDirectXFileDataImpl_AddBinaryObject(IDirectXFileData* iface, LPCSTR szName, const GUID* pguid, LPCSTR szMimeType, LPVOID pvData, DWORD cbSize)
1418 {
1419   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1420
1421   FIXME("(%p/%p)->(%s,%p,%s,%p,%d) stub!\n", This, iface, szName, pguid, szMimeType, pvData, cbSize);
1422
1423   return DXFILEERR_BADVALUE;
1424 }
1425
1426 static const IDirectXFileDataVtbl IDirectXFileData_Vtbl =
1427 {
1428     IDirectXFileDataImpl_QueryInterface,
1429     IDirectXFileDataImpl_AddRef,
1430     IDirectXFileDataImpl_Release,
1431     IDirectXFileDataImpl_GetName,
1432     IDirectXFileDataImpl_GetId,
1433     IDirectXFileDataImpl_GetData,
1434     IDirectXFileDataImpl_GetType,
1435     IDirectXFileDataImpl_GetNextObject,
1436     IDirectXFileDataImpl_AddDataObject,
1437     IDirectXFileDataImpl_AddDataReference,
1438     IDirectXFileDataImpl_AddBinaryObject
1439 };
1440
1441 HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj)
1442 {
1443     IDirectXFileDataReferenceImpl* object;
1444
1445     TRACE("(%p)\n", ppObj);
1446       
1447     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataReferenceImpl));
1448     
1449     object->lpVtbl.lpVtbl = &IDirectXFileDataReference_Vtbl;
1450     object->ref = 1;
1451
1452     *ppObj = object;
1453     
1454     return S_OK;
1455 }
1456
1457 /*** IUnknown methods ***/
1458 static HRESULT WINAPI IDirectXFileDataReferenceImpl_QueryInterface(IDirectXFileDataReference* iface, REFIID riid, void** ppvObject)
1459 {
1460   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1461
1462   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1463
1464   if (IsEqualGUID(riid, &IID_IUnknown)
1465       || IsEqualGUID(riid, &IID_IDirectXFileObject)
1466       || IsEqualGUID(riid, &IID_IDirectXFileDataReference))
1467   {
1468     IClassFactory_AddRef(iface);
1469     *ppvObject = This;
1470     return S_OK;
1471   }
1472
1473   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1474   return E_NOINTERFACE;
1475 }
1476
1477 static ULONG WINAPI IDirectXFileDataReferenceImpl_AddRef(IDirectXFileDataReference* iface)
1478 {
1479   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1480   ULONG ref = InterlockedIncrement(&This->ref);
1481
1482   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1483
1484   return ref;
1485 }
1486
1487 static ULONG WINAPI IDirectXFileDataReferenceImpl_Release(IDirectXFileDataReference* iface)
1488 {
1489   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1490   ULONG ref = InterlockedDecrement(&This->ref);
1491
1492   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1493
1494   if (!ref)
1495     HeapFree(GetProcessHeap(), 0, This);
1496
1497   return ref;
1498 }
1499
1500 /*** IDirectXFileObject methods ***/
1501 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetName(IDirectXFileDataReference* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1502 {
1503   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1504
1505   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
1506
1507   return DXFILEERR_BADVALUE;
1508 }
1509
1510 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetId(IDirectXFileDataReference* iface, LPGUID pGuid)
1511 {
1512   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1513
1514   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
1515
1516   return DXFILEERR_BADVALUE;
1517 }
1518
1519 /*** IDirectXFileDataReference ***/
1520 static HRESULT WINAPI IDirectXFileDataReferenceImpl_Resolve(IDirectXFileDataReference* iface, LPDIRECTXFILEDATA* ppDataObj)
1521 {
1522   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1523
1524   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj); 
1525
1526   return DXFILEERR_BADVALUE;
1527 }
1528
1529 static const IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl =
1530 {
1531     IDirectXFileDataReferenceImpl_QueryInterface,
1532     IDirectXFileDataReferenceImpl_AddRef,
1533     IDirectXFileDataReferenceImpl_Release,
1534     IDirectXFileDataReferenceImpl_GetName,
1535     IDirectXFileDataReferenceImpl_GetId,
1536     IDirectXFileDataReferenceImpl_Resolve
1537 };
1538
1539 HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj)
1540 {
1541     IDirectXFileEnumObjectImpl* object;
1542
1543     TRACE("(%p)\n", ppObj);
1544       
1545     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileEnumObjectImpl));
1546     
1547     object->lpVtbl.lpVtbl = &IDirectXFileEnumObject_Vtbl;
1548     object->ref = 1;
1549
1550     *ppObj = object;
1551     
1552     return S_OK;
1553 }
1554
1555 /*** IUnknown methods ***/
1556 static HRESULT WINAPI IDirectXFileEnumObjectImpl_QueryInterface(IDirectXFileEnumObject* iface, REFIID riid, void** ppvObject)
1557 {
1558   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1559
1560   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1561
1562   if (IsEqualGUID(riid, &IID_IUnknown)
1563       || IsEqualGUID(riid, &IID_IDirectXFileEnumObject))
1564   {
1565     IClassFactory_AddRef(iface);
1566     *ppvObject = This;
1567     return S_OK;
1568   }
1569
1570   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1571   return E_NOINTERFACE;
1572 }
1573
1574 static ULONG WINAPI IDirectXFileEnumObjectImpl_AddRef(IDirectXFileEnumObject* iface)
1575 {
1576   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1577   ULONG ref = InterlockedIncrement(&This->ref);
1578
1579   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1580
1581   return ref;
1582 }
1583
1584 static ULONG WINAPI IDirectXFileEnumObjectImpl_Release(IDirectXFileEnumObject* iface)
1585 {
1586   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1587   ULONG ref = InterlockedDecrement(&This->ref);
1588
1589   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1590
1591   if (!ref)
1592     HeapFree(GetProcessHeap(), 0, This);
1593
1594   return ref;
1595 }
1596
1597 /*** IDirectXFileEnumObject methods ***/
1598 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetNextDataObject(IDirectXFileEnumObject* iface, LPDIRECTXFILEDATA* ppDataObj)
1599 {
1600   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1601   IDirectXFileDataImpl* object;
1602   HRESULT hr;
1603   
1604   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj); 
1605
1606   hr = IDirectXFileDataImpl_Create(&object);
1607   if (!SUCCEEDED(hr))
1608     return hr;
1609
1610   *ppDataObj = (LPDIRECTXFILEDATA)object;
1611
1612   return DXFILE_OK;
1613 }
1614
1615 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectById(IDirectXFileEnumObject* iface, REFGUID rguid, LPDIRECTXFILEDATA* ppDataObj)
1616 {
1617   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1618
1619   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, rguid, ppDataObj); 
1620
1621   return DXFILEERR_BADVALUE;
1622 }
1623
1624 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectByName(IDirectXFileEnumObject* iface, LPCSTR szName, LPDIRECTXFILEDATA* ppDataObj)
1625 {
1626   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1627
1628   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szName, ppDataObj); 
1629
1630   return DXFILEERR_BADVALUE;
1631 }
1632
1633 static const IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl =
1634 {
1635     IDirectXFileEnumObjectImpl_QueryInterface,
1636     IDirectXFileEnumObjectImpl_AddRef,
1637     IDirectXFileEnumObjectImpl_Release,
1638     IDirectXFileEnumObjectImpl_GetNextDataObject,
1639     IDirectXFileEnumObjectImpl_GetDataObjectById,
1640     IDirectXFileEnumObjectImpl_GetDataObjectByName
1641 };
1642
1643 HRESULT IDirectXFileObjectImpl_Create(IDirectXFileObjectImpl** ppObj)
1644 {
1645     IDirectXFileObjectImpl* object;
1646
1647     TRACE("(%p)\n", ppObj);
1648       
1649     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileObjectImpl));
1650     
1651     object->lpVtbl.lpVtbl = &IDirectXFileObject_Vtbl;
1652     object->ref = 1;
1653
1654     *ppObj = object;
1655     
1656     return S_OK;
1657 }
1658
1659 /*** IUnknown methods ***/
1660 static HRESULT WINAPI IDirectXFileObjectImpl_QueryInterface(IDirectXFileObject* iface, REFIID riid, void** ppvObject)
1661 {
1662   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
1663
1664   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1665
1666   if (IsEqualGUID(riid, &IID_IUnknown)
1667       || IsEqualGUID(riid, &IID_IDirectXFileObject))
1668   {
1669     IClassFactory_AddRef(iface);
1670     *ppvObject = This;
1671     return S_OK;
1672   }
1673
1674   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1675   return E_NOINTERFACE;
1676 }
1677
1678 static ULONG WINAPI IDirectXFileObjectImpl_AddRef(IDirectXFileObject* iface)
1679 {
1680   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
1681   ULONG ref = InterlockedIncrement(&This->ref);
1682
1683   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1684
1685   return ref;
1686 }
1687
1688 static ULONG WINAPI IDirectXFileObjectImpl_Release(IDirectXFileObject* iface)
1689 {
1690   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
1691   ULONG ref = InterlockedDecrement(&This->ref);
1692
1693   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1694
1695   if (!ref)
1696     HeapFree(GetProcessHeap(), 0, This);
1697
1698   return ref;
1699 }
1700
1701 /*** IDirectXFileObject methods ***/
1702 static HRESULT WINAPI IDirectXFileObjectImpl_GetName(IDirectXFileObject* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1703 {
1704   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1705
1706   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
1707
1708   return DXFILEERR_BADVALUE;
1709 }
1710
1711 static HRESULT WINAPI IDirectXFileObjectImpl_GetId(IDirectXFileObject* iface, LPGUID pGuid)
1712 {
1713   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
1714
1715   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
1716
1717   return DXFILEERR_BADVALUE;
1718 }
1719
1720 static const IDirectXFileObjectVtbl IDirectXFileObject_Vtbl =
1721 {
1722     IDirectXFileObjectImpl_QueryInterface,
1723     IDirectXFileObjectImpl_AddRef,
1724     IDirectXFileObjectImpl_Release,
1725     IDirectXFileObjectImpl_GetName,
1726     IDirectXFileObjectImpl_GetId
1727 };
1728
1729 HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj)
1730 {
1731     IDirectXFileSaveObjectImpl* object;
1732
1733     TRACE("(%p)\n", ppObj);
1734
1735     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileSaveObjectImpl));
1736     
1737     object->lpVtbl.lpVtbl = &IDirectXFileSaveObject_Vtbl;
1738     object->ref = 1;
1739
1740     *ppObj = object;
1741     
1742     return S_OK;
1743 }
1744
1745 /*** IUnknown methods ***/
1746 static HRESULT WINAPI IDirectXFileSaveObjectImpl_QueryInterface(IDirectXFileSaveObject* iface, REFIID riid, void** ppvObject)
1747 {
1748   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1749
1750   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1751
1752   if (IsEqualGUID(riid, &IID_IUnknown)
1753       || IsEqualGUID(riid, &IID_IDirectXFileSaveObject))
1754   {
1755     IClassFactory_AddRef(iface);
1756     *ppvObject = This;
1757     return S_OK;
1758   }
1759
1760   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1761   return E_NOINTERFACE;
1762 }
1763
1764 static ULONG WINAPI IDirectXFileSaveObjectImpl_AddRef(IDirectXFileSaveObject* iface)
1765 {
1766   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1767   ULONG ref = InterlockedIncrement(&This->ref);
1768
1769   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1770
1771   return ref;
1772 }
1773
1774 static ULONG WINAPI IDirectXFileSaveObjectImpl_Release(IDirectXFileSaveObject* iface)
1775 {
1776   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1777   ULONG ref = InterlockedDecrement(&This->ref);
1778
1779   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1780
1781   if (!ref)
1782     HeapFree(GetProcessHeap(), 0, This);
1783
1784   return ref;
1785 }
1786
1787 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveTemplates(IDirectXFileSaveObject* iface, DWORD cTemplates, const GUID** ppguidTemplates)
1788 {
1789   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1790
1791   FIXME("(%p/%p)->(%d,%p) stub!\n", This, iface, cTemplates, ppguidTemplates);
1792
1793   return DXFILEERR_BADVALUE;
1794 }
1795
1796 static HRESULT WINAPI IDirectXFileSaveObjectImpl_CreateDataObject(IDirectXFileSaveObject* iface, REFGUID rguidTemplate, LPCSTR szName, const GUID* pguid, DWORD cbSize, LPVOID pvData, LPDIRECTXFILEDATA* ppDataObj)
1797 {
1798   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1799
1800   FIXME("(%p/%p)->(%p,%s,%p,%d,%p,%p) stub!\n", This, iface, rguidTemplate, szName, pguid, cbSize, pvData, ppDataObj);
1801
1802   return DXFILEERR_BADVALUE;
1803 }
1804
1805 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveData(IDirectXFileSaveObject* iface, LPDIRECTXFILEDATA ppDataObj)
1806 {
1807   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1808
1809   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj); 
1810
1811   return DXFILEERR_BADVALUE;
1812 }
1813
1814 static const IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl =
1815 {
1816     IDirectXFileSaveObjectImpl_QueryInterface,
1817     IDirectXFileSaveObjectImpl_AddRef,
1818     IDirectXFileSaveObjectImpl_Release,
1819     IDirectXFileSaveObjectImpl_SaveTemplates,
1820     IDirectXFileSaveObjectImpl_CreateDataObject,
1821     IDirectXFileSaveObjectImpl_SaveData
1822 };