d3dxof: Start implementing IDirectXFile_CreateEnumObject.
[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_TEXT)
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");
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 (is_space(c))
564         continue;
565       if (is_operator(c) && (c != '<'))
566       {
567         token = get_operator_token(c);
568         break;
569       }
570       else if (c == '.')
571       {
572         token = TOKEN_DOT;
573         break;
574       }
575       else
576       {
577         buf->buffer -= 1;
578         buf->rem_bytes += 1;
579
580         if ((token = get_keyword_token(buf)))
581           break;
582
583         if (is_guid(buf))
584         {
585           token = TOKEN_GUID;
586           break;
587         }
588         if (is_integer(buf))
589         {
590           token = TOKEN_INTEGER;
591           break;
592         }
593         if (is_name(buf))
594         {
595           token = TOKEN_NAME;
596           break;
597         }
598
599         FIXME("Unrecognize element\n");
600         return 0;
601       }
602     }
603   }
604   else
605   {
606     if (!read_bytes(buf, &token, 2))
607       return 0;
608   }
609
610   switch(token)
611   {
612     case TOKEN_NAME:
613     case TOKEN_STRING:
614     case TOKEN_INTEGER:
615     case TOKEN_GUID:
616     case TOKEN_INTEGER_LIST:
617     case TOKEN_FLOAT_LIST:
618     case TOKEN_OBRACE:
619     case TOKEN_CBRACE:
620     case TOKEN_OPAREN:
621     case TOKEN_CPAREN:
622     case TOKEN_OBRACKET:
623     case TOKEN_CBRACKET:
624     case TOKEN_OANGLE:
625     case TOKEN_CANGLE:
626     case TOKEN_DOT:
627     case TOKEN_COMMA:
628     case TOKEN_SEMICOLON:
629     case TOKEN_TEMPLATE:
630     case TOKEN_WORD:
631     case TOKEN_DWORD:
632     case TOKEN_FLOAT:
633     case TOKEN_DOUBLE:
634     case TOKEN_CHAR:
635     case TOKEN_UCHAR:
636     case TOKEN_SWORD:
637     case TOKEN_SDWORD:
638     case TOKEN_VOID:
639     case TOKEN_LPSTR:
640     case TOKEN_UNICODE:
641     case TOKEN_CSTRING:
642     case TOKEN_ARRAY:
643       break;
644     default:
645       return 0;
646   }
647
648   if (show_token)
649     dump_TOKEN(token);
650
651   return token;
652 }
653
654 static const char* get_primitive_string(WORD token)
655 {
656   switch(token)
657   {
658     case TOKEN_WORD:
659       return "WORD";
660     case TOKEN_DWORD:
661       return "DWORD";
662     case TOKEN_FLOAT:
663       return "FLOAT";
664     case TOKEN_DOUBLE:
665       return "DOUBLE";
666     case TOKEN_CHAR:
667       return "CHAR";
668     case TOKEN_UCHAR:
669       return "UCHAR";
670     case TOKEN_SWORD:
671       return "SWORD";
672     case TOKEN_SDWORD:
673       return "SDWORD";
674     case TOKEN_VOID:
675       return "VOID";
676     case TOKEN_LPSTR:
677       return "STRING";
678     case TOKEN_UNICODE:
679       return "UNICODE";
680     case TOKEN_CSTRING:
681       return "CSTRING ";
682     default:
683       break;
684   }
685   return NULL;
686 }
687
688 static inline WORD parse_TOKEN(parse_buffer * buf)
689 {
690   return parse_TOKEN_dbg_opt(buf, TRUE);
691 }
692
693 static WORD check_TOKEN(parse_buffer * buf)
694 {
695   WORD token;
696
697   if (buf->txt)
698   {
699     parse_buffer save = *buf;
700     /*TRACE("check: ");*/
701     token = parse_TOKEN_dbg_opt(buf, FALSE);
702     *buf = save;
703     return token;
704   }
705
706   if (!read_bytes(buf, &token, 2))
707     return 0;
708   buf->buffer -= 2;
709   buf->rem_bytes += 2;
710   if (0)
711   {
712     TRACE("check: ");
713     dump_TOKEN(token);
714   }
715   return token;
716 }
717
718 static inline BOOL is_primitive_type(WORD token)
719 {
720   BOOL ret;
721   switch(token)
722   {
723     case TOKEN_WORD:
724     case TOKEN_DWORD:
725     case TOKEN_FLOAT:
726     case TOKEN_DOUBLE:
727     case TOKEN_CHAR:
728     case TOKEN_UCHAR:
729     case TOKEN_SWORD:
730     case TOKEN_SDWORD:
731     case TOKEN_LPSTR:
732     case TOKEN_UNICODE:
733     case TOKEN_CSTRING:
734       ret = 1;
735       break;
736     default:
737       ret = 0;
738       break;
739   }
740   return ret;
741 }
742
743 static BOOL parse_name(parse_buffer * buf)
744 {
745   DWORD count;
746   char strname[100];
747
748   if (parse_TOKEN(buf) != TOKEN_NAME)
749     return FALSE;
750   if (buf->txt)
751     return TRUE;
752   if (!read_bytes(buf, &count, 4))
753     return FALSE;
754   if (!read_bytes(buf, strname, count))
755     return FALSE;
756   strname[count] = 0;
757   /*TRACE("name = %s\n", strname);*/
758
759   strcpy((char*)buf->value, strname);
760
761   return TRUE;
762 }
763
764 static BOOL parse_class_id(parse_buffer * buf)
765 {
766   char strguid[38];
767   GUID class_id;
768
769   if (parse_TOKEN(buf) != TOKEN_GUID)
770     return FALSE;
771   if (buf->txt)
772     return TRUE;
773   if (!read_bytes(buf, &class_id, 16))
774     return FALSE;
775   sprintf(strguid, CLSIDFMT, class_id.Data1, class_id.Data2, class_id.Data3, class_id.Data4[0],
776     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]);
777   /*TRACE("guid = {%s}\n", strguid);*/
778
779   *(GUID*)buf->value = class_id;
780
781   return TRUE;
782 }
783
784 static BOOL parse_integer(parse_buffer * buf)
785 {
786   DWORD integer;
787
788   if (parse_TOKEN(buf) != TOKEN_INTEGER)
789     return FALSE;
790   if (buf->txt)
791     return TRUE;
792   if (!read_bytes(buf, &integer, 4))
793     return FALSE;
794   /*TRACE("integer = %ld\n", integer);*/
795
796   *(DWORD*)buf->value = integer;
797
798   return TRUE;
799 }
800
801 static BOOL parse_template_option_info(parse_buffer * buf)
802 {
803   xtemplate* cur_template = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates];
804
805   if (check_TOKEN(buf) == TOKEN_DOT)
806   {
807     parse_TOKEN(buf);
808     if (parse_TOKEN(buf) != TOKEN_DOT)
809       return FALSE;
810     if (parse_TOKEN(buf) != TOKEN_DOT)
811       return FALSE;
812     cur_template->open = TRUE;
813   }
814   else
815   {
816     while (1)
817     {
818       if (!parse_name(buf))
819         return FALSE;
820       strcpy(cur_template->childs[cur_template->nb_childs], (char*)buf->value);
821       if (check_TOKEN(buf) == TOKEN_GUID)
822         if (!parse_class_id(buf))
823           return FALSE;
824       cur_template->nb_childs++;
825       if (check_TOKEN(buf) != TOKEN_COMMA)
826         break;
827       parse_TOKEN(buf);
828     }
829     cur_template->open = FALSE;
830   }
831
832   return TRUE;
833 }
834
835 static BOOL parse_template_members_list(parse_buffer * buf)
836 {
837   parse_buffer save1;
838   int idx_member = 0;
839   member* cur_member;
840
841   while (1)
842   {
843     cur_member = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[idx_member];
844     save1 = *buf;
845
846     if (check_TOKEN(buf) == TOKEN_NAME)
847     {
848       if (!parse_name(buf))
849         break;
850       while (cur_member->idx_template < buf->pdxf->nb_xtemplates)
851       {
852         if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[cur_member->idx_template].name))
853           break;
854         cur_member->idx_template++;
855       }
856       if (cur_member->idx_template == buf->pdxf->nb_xtemplates)
857       {
858         TRACE("Reference to a nonexistent template '%s'\n", (char*)buf->value);
859         return FALSE;
860       }
861       if (check_TOKEN(buf) == TOKEN_NAME)
862         if (!parse_name(buf))
863           break;
864       if (parse_TOKEN(buf) != TOKEN_SEMICOLON)
865         break;
866       cur_member->type = TOKEN_NAME;
867       strcpy(cur_member->name, (char*)buf->value);
868       idx_member++;
869     }
870     else if (check_TOKEN(buf) == TOKEN_ARRAY)
871     {
872       parse_buffer save2;
873       WORD token;
874       int nb_dims = 0;
875
876       parse_TOKEN(buf);
877       token = check_TOKEN(buf);
878       if (is_primitive_type(token))
879       {
880         parse_TOKEN(buf);
881         cur_member->type = token;
882       }
883       else
884       {
885         if (!parse_name(buf))
886           break;
887         cur_member->type = TOKEN_NAME;
888         cur_member->idx_template = 0;
889         while (cur_member->idx_template < buf->pdxf->nb_xtemplates)
890         {
891           if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[cur_member->idx_template].name))
892             break;
893           cur_member->idx_template++;
894         }
895         if (cur_member->idx_template == buf->pdxf->nb_xtemplates)
896         {
897           TRACE("Reference to nonexistent template '%s'\n", (char*)buf->value);
898           return FALSE;
899         }
900       }
901       if (!parse_name(buf))
902         break;
903       strcpy(cur_member->name, (char*)buf->value);
904       save2 = *buf;
905       while (check_TOKEN(buf) == TOKEN_OBRACKET)
906       {
907         if (nb_dims)
908         {
909           FIXME("No support for multi-dimensional array yet\n");
910           return FALSE;
911         }
912         parse_TOKEN(buf);
913         if (check_TOKEN(buf) == TOKEN_INTEGER)
914         {
915           if (!parse_integer(buf))
916             break;
917           cur_member->dim_fixed[nb_dims] = TRUE;
918           cur_member->dim_value[nb_dims] = *(DWORD*)buf->value;
919         }
920         else
921         {
922           if (!parse_name(buf))
923             break;
924           cur_member->dim_fixed[nb_dims] = FALSE;
925           /* Hack: Assume array size is specified in previous member */
926           cur_member->dim_value[nb_dims] = idx_member - 1;
927         }
928         if (parse_TOKEN(buf) != TOKEN_CBRACKET)
929           break;
930         save2 = *buf;
931         nb_dims++;
932       }
933       *buf = save2;
934       if (parse_TOKEN(buf) != TOKEN_SEMICOLON)
935         break;
936       cur_member->nb_dims = nb_dims;
937       idx_member++;
938     }
939     else if (is_primitive_type(check_TOKEN(buf)))
940     {
941       cur_member->type = check_TOKEN(buf);
942       parse_TOKEN(buf);
943       if (check_TOKEN(buf) == TOKEN_NAME)
944         if (!parse_name(buf))
945           break;
946       strcpy(cur_member->name, (char*)buf->value);
947       if (parse_TOKEN(buf) != TOKEN_SEMICOLON)
948         break;
949       idx_member++;
950     }
951     else
952       break;
953   }
954
955   *buf = save1;
956   buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].nb_members = idx_member;
957
958   return TRUE;
959 }
960
961 static BOOL parse_template_parts(parse_buffer * buf)
962 {
963   if (check_TOKEN(buf) == TOKEN_OBRACKET)
964   {
965     parse_TOKEN(buf);
966     if (!parse_template_option_info(buf))
967       return FALSE;
968     if (parse_TOKEN(buf) != TOKEN_CBRACKET)
969       return FALSE;
970   }
971   else
972   {
973     if (!parse_template_members_list(buf))
974       return FALSE;
975     if (check_TOKEN(buf) == TOKEN_OBRACKET)
976     {
977       parse_TOKEN(buf);
978       if (!parse_template_option_info(buf))
979         return FALSE;
980       if (parse_TOKEN(buf) != TOKEN_CBRACKET)
981        return FALSE;
982     }
983   }
984
985   return TRUE;
986 }
987
988 static BOOL parse_template(parse_buffer * buf)
989 {
990   if (parse_TOKEN(buf) != TOKEN_TEMPLATE)
991     return FALSE;
992   if (!parse_name(buf))
993     return FALSE;
994   strcpy(buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].name, (char*)buf->value);
995   if (parse_TOKEN(buf) != TOKEN_OBRACE)
996     return FALSE;
997   if (!parse_class_id(buf))
998     return FALSE;
999   buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].class_id = *(GUID*)buf->value;
1000   if (!parse_template_parts(buf))
1001     return FALSE;
1002   if (parse_TOKEN(buf) != TOKEN_CBRACE)
1003     return FALSE;
1004   if (buf->txt)
1005   {
1006     /* Go to the next template */
1007     while (buf->rem_bytes && is_space(*buf->buffer))
1008     {
1009       buf->buffer++;
1010       buf->rem_bytes--;
1011     }
1012   }
1013
1014   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));
1015   buf->pdxf->nb_xtemplates++;
1016
1017   return TRUE;
1018 }
1019
1020 static HRESULT WINAPI IDirectXFileImpl_RegisterTemplates(IDirectXFile* iface, LPVOID pvData, DWORD cbSize)
1021 {
1022   IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
1023   DWORD token_header;
1024   parse_buffer buf;
1025
1026   buf.buffer = (LPBYTE)pvData;
1027   buf.rem_bytes = cbSize;
1028   buf.txt = FALSE;
1029   buf.pdxf = This;
1030
1031   FIXME("(%p/%p)->(%p,%d) partial stub!\n", This, iface, pvData, cbSize);
1032
1033   if (!pvData)
1034     return DXFILEERR_BADVALUE;
1035
1036   if (cbSize < 16)
1037     return DXFILEERR_BADFILETYPE;
1038
1039   if (TRACE_ON(d3dxof))
1040   {
1041     char string[17];
1042     memcpy(string, pvData, 16);
1043     string[16] = 0;
1044     TRACE("header = '%s'\n", string);
1045   }
1046
1047   read_bytes(&buf, &token_header, 4);
1048
1049   if (token_header != XOFFILE_FORMAT_MAGIC)
1050     return DXFILEERR_BADFILETYPE;
1051
1052   read_bytes(&buf, &token_header, 4);
1053
1054   if (token_header != XOFFILE_FORMAT_VERSION)
1055     return DXFILEERR_BADFILEVERSION;
1056
1057   read_bytes(&buf, &token_header, 4);
1058
1059   if ((token_header != XOFFILE_FORMAT_BINARY) && (token_header != XOFFILE_FORMAT_TEXT) && (token_header != XOFFILE_FORMAT_COMPRESSED))
1060     return DXFILEERR_BADFILETYPE;
1061
1062   if (token_header == XOFFILE_FORMAT_TEXT)
1063   {
1064     buf.txt = TRUE;
1065   }
1066
1067   if (token_header == XOFFILE_FORMAT_COMPRESSED)
1068   {
1069     FIXME("Compressed formats not supported yet\n");
1070     return DXFILEERR_BADVALUE;
1071   }
1072
1073   read_bytes(&buf, &token_header, 4);
1074
1075   if ((token_header != XOFFILE_FORMAT_FLOAT_BITS_32) && (token_header != XOFFILE_FORMAT_FLOAT_BITS_64))
1076     return DXFILEERR_BADFILEFLOATSIZE;
1077
1078   TRACE("Header is correct\n");
1079
1080   while (buf.rem_bytes)
1081   {
1082     if (!parse_template(&buf))
1083     {
1084       TRACE("Template is not correct\n");
1085       return DXFILEERR_BADVALUE;
1086     }
1087     else
1088     {
1089       TRACE("Template successfully parsed:\n");
1090       if (TRACE_ON(d3dxof))
1091       {
1092         int i,j,k;
1093         GUID* clsid;
1094
1095         i = This->nb_xtemplates - 1;
1096         clsid = &This->xtemplates[i].class_id;
1097
1098         DPRINTF("template %s\n", This->xtemplates[i].name);
1099         DPRINTF("{\n");
1100         DPRINTF(CLSIDFMT "\n", clsid->Data1, clsid->Data2, clsid->Data3, clsid->Data4[0],
1101           clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7]);
1102         for (j = 0; j < This->xtemplates[i].nb_members; j++)
1103         {
1104           if (This->xtemplates[i].members[j].nb_dims)
1105             DPRINTF("array ");
1106           if (This->xtemplates[i].members[j].type == TOKEN_NAME)
1107             DPRINTF("%s ", This->xtemplates[This->xtemplates[i].members[j].idx_template].name);
1108           else
1109             DPRINTF("%s ", get_primitive_string(This->xtemplates[i].members[j].type));
1110           DPRINTF("%s", This->xtemplates[i].members[j].name);
1111           for (k = 0; k < This->xtemplates[i].members[j].nb_dims; k++)
1112           {
1113             if (This->xtemplates[i].members[j].dim_fixed[k])
1114               DPRINTF("[%d]", This->xtemplates[i].members[j].dim_value[k]);
1115             else
1116               DPRINTF("[%s]", This->xtemplates[i].members[This->xtemplates[i].members[j].dim_value[k]].name);
1117           }
1118           DPRINTF(";\n");
1119         }
1120         if (This->xtemplates[i].open)
1121           DPRINTF("[...]\n");
1122         else if (This->xtemplates[i].nb_childs)
1123         {
1124           DPRINTF("[%s", This->xtemplates[i].childs[0]);
1125           for (j = 1; j < This->xtemplates[i].nb_childs; j++)
1126             DPRINTF(",%s", This->xtemplates[i].childs[j]);
1127           DPRINTF("]\n");
1128         }
1129         DPRINTF("}\n");
1130       }
1131     }
1132   }
1133
1134   if (TRACE_ON(d3dxof))
1135   {
1136     int i;
1137     TRACE("Registered templates (%d):\n", This->nb_xtemplates);
1138     for (i = 0; i < This->nb_xtemplates; i++)
1139       DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
1140   }
1141
1142   return DXFILE_OK;
1143 }
1144
1145 static const IDirectXFileVtbl IDirectXFile_Vtbl =
1146 {
1147   IDirectXFileImpl_QueryInterface,
1148   IDirectXFileImpl_AddRef,
1149   IDirectXFileImpl_Release,
1150   IDirectXFileImpl_CreateEnumObject,
1151   IDirectXFileImpl_CreateSaveObject,
1152   IDirectXFileImpl_RegisterTemplates
1153 };
1154
1155 HRESULT IDirectXFileBinaryImpl_Create(IDirectXFileBinaryImpl** ppObj)
1156 {
1157     IDirectXFileBinaryImpl* object;
1158
1159     TRACE("(%p)\n", ppObj);
1160       
1161     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileBinaryImpl));
1162     
1163     object->lpVtbl.lpVtbl = &IDirectXFileBinary_Vtbl;
1164     object->ref = 1;
1165
1166     *ppObj = object;
1167     
1168     return DXFILE_OK;
1169 }
1170
1171 /*** IUnknown methods ***/
1172 static HRESULT WINAPI IDirectXFileBinaryImpl_QueryInterface(IDirectXFileBinary* iface, REFIID riid, void** ppvObject)
1173 {
1174   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1175
1176   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1177
1178   if (IsEqualGUID(riid, &IID_IUnknown)
1179       || IsEqualGUID(riid, &IID_IDirectXFileObject)
1180       || IsEqualGUID(riid, &IID_IDirectXFileBinary))
1181   {
1182     IClassFactory_AddRef(iface);
1183     *ppvObject = This;
1184     return S_OK;
1185   }
1186
1187   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1188   return E_NOINTERFACE;
1189 }
1190
1191 static ULONG WINAPI IDirectXFileBinaryImpl_AddRef(IDirectXFileBinary* iface)
1192 {
1193   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1194   ULONG ref = InterlockedIncrement(&This->ref);
1195
1196   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1197
1198   return ref;
1199 }
1200
1201 static ULONG WINAPI IDirectXFileBinaryImpl_Release(IDirectXFileBinary* iface)
1202 {
1203   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1204   ULONG ref = InterlockedDecrement(&This->ref);
1205
1206   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1207
1208   if (!ref)
1209     HeapFree(GetProcessHeap(), 0, This);
1210
1211   return ref;
1212 }
1213
1214 /*** IDirectXFileObject methods ***/
1215 static HRESULT WINAPI IDirectXFileBinaryImpl_GetName(IDirectXFileBinary* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1216
1217 {
1218   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1219
1220   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
1221
1222   return DXFILEERR_BADVALUE;
1223 }
1224
1225 static HRESULT WINAPI IDirectXFileBinaryImpl_GetId(IDirectXFileBinary* iface, LPGUID pGuid)
1226 {
1227   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1228
1229   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
1230
1231   return DXFILEERR_BADVALUE;
1232 }
1233
1234 /*** IDirectXFileBinary methods ***/
1235 static HRESULT WINAPI IDirectXFileBinaryImpl_GetSize(IDirectXFileBinary* iface, DWORD* pcbSize)
1236 {
1237   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1238
1239   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pcbSize); 
1240
1241   return DXFILEERR_BADVALUE;
1242 }
1243
1244 static HRESULT WINAPI IDirectXFileBinaryImpl_GetMimeType(IDirectXFileBinary* iface, LPCSTR* pszMimeType)
1245 {
1246   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1247
1248   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pszMimeType);
1249
1250   return DXFILEERR_BADVALUE;
1251 }
1252
1253 static HRESULT WINAPI IDirectXFileBinaryImpl_Read(IDirectXFileBinary* iface, LPVOID pvData, DWORD cbSize, LPDWORD pcbRead)
1254 {
1255   IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1256
1257   FIXME("(%p/%p)->(%p, %d, %p) stub!\n", This, iface, pvData, cbSize, pcbRead);
1258
1259   return DXFILEERR_BADVALUE;
1260 }
1261
1262 static const IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl =
1263 {
1264     IDirectXFileBinaryImpl_QueryInterface,
1265     IDirectXFileBinaryImpl_AddRef,
1266     IDirectXFileBinaryImpl_Release,
1267     IDirectXFileBinaryImpl_GetName,
1268     IDirectXFileBinaryImpl_GetId,
1269     IDirectXFileBinaryImpl_GetSize,
1270     IDirectXFileBinaryImpl_GetMimeType,
1271     IDirectXFileBinaryImpl_Read
1272 };
1273
1274 HRESULT IDirectXFileDataImpl_Create(IDirectXFileDataImpl** ppObj)
1275 {
1276     IDirectXFileDataImpl* object;
1277
1278     TRACE("(%p)\n", ppObj);
1279       
1280     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataImpl));
1281     
1282     object->lpVtbl.lpVtbl = &IDirectXFileData_Vtbl;
1283     object->ref = 1;
1284
1285     *ppObj = object;
1286     
1287     return S_OK;
1288 }
1289
1290 /*** IUnknown methods ***/
1291 static HRESULT WINAPI IDirectXFileDataImpl_QueryInterface(IDirectXFileData* iface, REFIID riid, void** ppvObject)
1292 {
1293   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1294
1295   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1296
1297   if (IsEqualGUID(riid, &IID_IUnknown)
1298       || IsEqualGUID(riid, &IID_IDirectXFileObject)
1299       || IsEqualGUID(riid, &IID_IDirectXFileData))
1300   {
1301     IClassFactory_AddRef(iface);
1302     *ppvObject = This;
1303     return S_OK;
1304   }
1305
1306   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1307   return E_NOINTERFACE;
1308 }
1309
1310 static ULONG WINAPI IDirectXFileDataImpl_AddRef(IDirectXFileData* iface)
1311 {
1312   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1313   ULONG ref = InterlockedIncrement(&This->ref);
1314
1315   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1316
1317   return ref;
1318 }
1319
1320 static ULONG WINAPI IDirectXFileDataImpl_Release(IDirectXFileData* iface)
1321 {
1322   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1323   ULONG ref = InterlockedDecrement(&This->ref);
1324
1325   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1326
1327   if (!ref)
1328     HeapFree(GetProcessHeap(), 0, This);
1329
1330   return ref;
1331 }
1332
1333 /*** IDirectXFileObject methods ***/
1334 static HRESULT WINAPI IDirectXFileDataImpl_GetName(IDirectXFileData* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1335
1336 {
1337   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1338
1339   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
1340
1341   return DXFILEERR_BADVALUE;
1342 }
1343
1344 static HRESULT WINAPI IDirectXFileDataImpl_GetId(IDirectXFileData* iface, LPGUID pGuid)
1345 {
1346   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1347
1348   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
1349
1350   return DXFILEERR_BADVALUE;
1351 }
1352
1353 /*** IDirectXFileData methods ***/
1354 static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCSTR szMember, DWORD* pcbSize, void** ppvData)
1355 {
1356   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1357
1358   FIXME("(%p/%p)->(%s,%p,%p) stub!\n", This, iface, szMember, pcbSize, ppvData); 
1359
1360   return DXFILEERR_BADVALUE;
1361 }
1362
1363 static HRESULT WINAPI IDirectXFileDataImpl_GetType(IDirectXFileData* iface, const GUID** pguid)
1364 {
1365   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1366
1367   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pguid); 
1368
1369   return DXFILEERR_BADVALUE;
1370 }
1371
1372 static HRESULT WINAPI IDirectXFileDataImpl_GetNextObject(IDirectXFileData* iface, LPDIRECTXFILEOBJECT* ppChildObj)
1373 {
1374   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1375
1376   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppChildObj); 
1377
1378   return DXFILEERR_BADVALUE;
1379 }
1380
1381 static HRESULT WINAPI IDirectXFileDataImpl_AddDataObject(IDirectXFileData* iface, LPDIRECTXFILEDATA pDataObj)
1382 {
1383   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1384
1385   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pDataObj); 
1386
1387   return DXFILEERR_BADVALUE;
1388 }
1389
1390 static HRESULT WINAPI IDirectXFileDataImpl_AddDataReference(IDirectXFileData* iface, LPCSTR szRef, const GUID* pguidRef)
1391 {
1392   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1393
1394   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szRef, pguidRef); 
1395
1396   return DXFILEERR_BADVALUE;
1397 }
1398
1399 static HRESULT WINAPI IDirectXFileDataImpl_AddBinaryObject(IDirectXFileData* iface, LPCSTR szName, const GUID* pguid, LPCSTR szMimeType, LPVOID pvData, DWORD cbSize)
1400 {
1401   IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1402
1403   FIXME("(%p/%p)->(%s,%p,%s,%p,%d) stub!\n", This, iface, szName, pguid, szMimeType, pvData, cbSize);
1404
1405   return DXFILEERR_BADVALUE;
1406 }
1407
1408 static const IDirectXFileDataVtbl IDirectXFileData_Vtbl =
1409 {
1410     IDirectXFileDataImpl_QueryInterface,
1411     IDirectXFileDataImpl_AddRef,
1412     IDirectXFileDataImpl_Release,
1413     IDirectXFileDataImpl_GetName,
1414     IDirectXFileDataImpl_GetId,
1415     IDirectXFileDataImpl_GetData,
1416     IDirectXFileDataImpl_GetType,
1417     IDirectXFileDataImpl_GetNextObject,
1418     IDirectXFileDataImpl_AddDataObject,
1419     IDirectXFileDataImpl_AddDataReference,
1420     IDirectXFileDataImpl_AddBinaryObject
1421 };
1422
1423 HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj)
1424 {
1425     IDirectXFileDataReferenceImpl* object;
1426
1427     TRACE("(%p)\n", ppObj);
1428       
1429     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataReferenceImpl));
1430     
1431     object->lpVtbl.lpVtbl = &IDirectXFileDataReference_Vtbl;
1432     object->ref = 1;
1433
1434     *ppObj = object;
1435     
1436     return S_OK;
1437 }
1438
1439 /*** IUnknown methods ***/
1440 static HRESULT WINAPI IDirectXFileDataReferenceImpl_QueryInterface(IDirectXFileDataReference* iface, REFIID riid, void** ppvObject)
1441 {
1442   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1443
1444   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1445
1446   if (IsEqualGUID(riid, &IID_IUnknown)
1447       || IsEqualGUID(riid, &IID_IDirectXFileObject)
1448       || IsEqualGUID(riid, &IID_IDirectXFileDataReference))
1449   {
1450     IClassFactory_AddRef(iface);
1451     *ppvObject = This;
1452     return S_OK;
1453   }
1454
1455   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1456   return E_NOINTERFACE;
1457 }
1458
1459 static ULONG WINAPI IDirectXFileDataReferenceImpl_AddRef(IDirectXFileDataReference* iface)
1460 {
1461   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1462   ULONG ref = InterlockedIncrement(&This->ref);
1463
1464   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1465
1466   return ref;
1467 }
1468
1469 static ULONG WINAPI IDirectXFileDataReferenceImpl_Release(IDirectXFileDataReference* iface)
1470 {
1471   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1472   ULONG ref = InterlockedDecrement(&This->ref);
1473
1474   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1475
1476   if (!ref)
1477     HeapFree(GetProcessHeap(), 0, This);
1478
1479   return ref;
1480 }
1481
1482 /*** IDirectXFileObject methods ***/
1483 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetName(IDirectXFileDataReference* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1484 {
1485   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1486
1487   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
1488
1489   return DXFILEERR_BADVALUE;
1490 }
1491
1492 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetId(IDirectXFileDataReference* iface, LPGUID pGuid)
1493 {
1494   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1495
1496   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
1497
1498   return DXFILEERR_BADVALUE;
1499 }
1500
1501 /*** IDirectXFileDataReference ***/
1502 static HRESULT WINAPI IDirectXFileDataReferenceImpl_Resolve(IDirectXFileDataReference* iface, LPDIRECTXFILEDATA* ppDataObj)
1503 {
1504   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1505
1506   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj); 
1507
1508   return DXFILEERR_BADVALUE;
1509 }
1510
1511 static const IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl =
1512 {
1513     IDirectXFileDataReferenceImpl_QueryInterface,
1514     IDirectXFileDataReferenceImpl_AddRef,
1515     IDirectXFileDataReferenceImpl_Release,
1516     IDirectXFileDataReferenceImpl_GetName,
1517     IDirectXFileDataReferenceImpl_GetId,
1518     IDirectXFileDataReferenceImpl_Resolve
1519 };
1520
1521 HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj)
1522 {
1523     IDirectXFileEnumObjectImpl* object;
1524
1525     TRACE("(%p)\n", ppObj);
1526       
1527     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileEnumObjectImpl));
1528     
1529     object->lpVtbl.lpVtbl = &IDirectXFileEnumObject_Vtbl;
1530     object->ref = 1;
1531
1532     *ppObj = object;
1533     
1534     return S_OK;
1535 }
1536
1537 /*** IUnknown methods ***/
1538 static HRESULT WINAPI IDirectXFileEnumObjectImpl_QueryInterface(IDirectXFileEnumObject* iface, REFIID riid, void** ppvObject)
1539 {
1540   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1541
1542   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1543
1544   if (IsEqualGUID(riid, &IID_IUnknown)
1545       || IsEqualGUID(riid, &IID_IDirectXFileEnumObject))
1546   {
1547     IClassFactory_AddRef(iface);
1548     *ppvObject = This;
1549     return S_OK;
1550   }
1551
1552   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1553   return E_NOINTERFACE;
1554 }
1555
1556 static ULONG WINAPI IDirectXFileEnumObjectImpl_AddRef(IDirectXFileEnumObject* iface)
1557 {
1558   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1559   ULONG ref = InterlockedIncrement(&This->ref);
1560
1561   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1562
1563   return ref;
1564 }
1565
1566 static ULONG WINAPI IDirectXFileEnumObjectImpl_Release(IDirectXFileEnumObject* iface)
1567 {
1568   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1569   ULONG ref = InterlockedDecrement(&This->ref);
1570
1571   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1572
1573   if (!ref)
1574     HeapFree(GetProcessHeap(), 0, This);
1575
1576   return ref;
1577 }
1578
1579 /*** IDirectXFileEnumObject methods ***/
1580 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetNextDataObject(IDirectXFileEnumObject* iface, LPDIRECTXFILEDATA* ppDataObj)
1581 {
1582   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1583   IDirectXFileDataImpl* object;
1584   HRESULT hr;
1585   
1586   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj); 
1587
1588   hr = IDirectXFileDataImpl_Create(&object);
1589   if (!SUCCEEDED(hr))
1590     return hr;
1591
1592   *ppDataObj = (LPDIRECTXFILEDATA)object;
1593
1594   return DXFILE_OK;
1595 }
1596
1597 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectById(IDirectXFileEnumObject* iface, REFGUID rguid, LPDIRECTXFILEDATA* ppDataObj)
1598 {
1599   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1600
1601   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, rguid, ppDataObj); 
1602
1603   return DXFILEERR_BADVALUE;
1604 }
1605
1606 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectByName(IDirectXFileEnumObject* iface, LPCSTR szName, LPDIRECTXFILEDATA* ppDataObj)
1607 {
1608   IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1609
1610   FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szName, ppDataObj); 
1611
1612   return DXFILEERR_BADVALUE;
1613 }
1614
1615 static const IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl =
1616 {
1617     IDirectXFileEnumObjectImpl_QueryInterface,
1618     IDirectXFileEnumObjectImpl_AddRef,
1619     IDirectXFileEnumObjectImpl_Release,
1620     IDirectXFileEnumObjectImpl_GetNextDataObject,
1621     IDirectXFileEnumObjectImpl_GetDataObjectById,
1622     IDirectXFileEnumObjectImpl_GetDataObjectByName
1623 };
1624
1625 HRESULT IDirectXFileObjectImpl_Create(IDirectXFileObjectImpl** ppObj)
1626 {
1627     IDirectXFileObjectImpl* object;
1628
1629     TRACE("(%p)\n", ppObj);
1630       
1631     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileObjectImpl));
1632     
1633     object->lpVtbl.lpVtbl = &IDirectXFileObject_Vtbl;
1634     object->ref = 1;
1635
1636     *ppObj = object;
1637     
1638     return S_OK;
1639 }
1640
1641 /*** IUnknown methods ***/
1642 static HRESULT WINAPI IDirectXFileObjectImpl_QueryInterface(IDirectXFileObject* iface, REFIID riid, void** ppvObject)
1643 {
1644   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
1645
1646   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1647
1648   if (IsEqualGUID(riid, &IID_IUnknown)
1649       || IsEqualGUID(riid, &IID_IDirectXFileObject))
1650   {
1651     IClassFactory_AddRef(iface);
1652     *ppvObject = This;
1653     return S_OK;
1654   }
1655
1656   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1657   return E_NOINTERFACE;
1658 }
1659
1660 static ULONG WINAPI IDirectXFileObjectImpl_AddRef(IDirectXFileObject* iface)
1661 {
1662   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
1663   ULONG ref = InterlockedIncrement(&This->ref);
1664
1665   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1666
1667   return ref;
1668 }
1669
1670 static ULONG WINAPI IDirectXFileObjectImpl_Release(IDirectXFileObject* iface)
1671 {
1672   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
1673   ULONG ref = InterlockedDecrement(&This->ref);
1674
1675   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1676
1677   if (!ref)
1678     HeapFree(GetProcessHeap(), 0, This);
1679
1680   return ref;
1681 }
1682
1683 /*** IDirectXFileObject methods ***/
1684 static HRESULT WINAPI IDirectXFileObjectImpl_GetName(IDirectXFileObject* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1685 {
1686   IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1687
1688   FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen); 
1689
1690   return DXFILEERR_BADVALUE;
1691 }
1692
1693 static HRESULT WINAPI IDirectXFileObjectImpl_GetId(IDirectXFileObject* iface, LPGUID pGuid)
1694 {
1695   IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
1696
1697   FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid); 
1698
1699   return DXFILEERR_BADVALUE;
1700 }
1701
1702 static const IDirectXFileObjectVtbl IDirectXFileObject_Vtbl =
1703 {
1704     IDirectXFileObjectImpl_QueryInterface,
1705     IDirectXFileObjectImpl_AddRef,
1706     IDirectXFileObjectImpl_Release,
1707     IDirectXFileObjectImpl_GetName,
1708     IDirectXFileObjectImpl_GetId
1709 };
1710
1711 HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj)
1712 {
1713     IDirectXFileSaveObjectImpl* object;
1714
1715     TRACE("(%p)\n", ppObj);
1716
1717     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileSaveObjectImpl));
1718     
1719     object->lpVtbl.lpVtbl = &IDirectXFileSaveObject_Vtbl;
1720     object->ref = 1;
1721
1722     *ppObj = object;
1723     
1724     return S_OK;
1725 }
1726
1727 /*** IUnknown methods ***/
1728 static HRESULT WINAPI IDirectXFileSaveObjectImpl_QueryInterface(IDirectXFileSaveObject* iface, REFIID riid, void** ppvObject)
1729 {
1730   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1731
1732   TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1733
1734   if (IsEqualGUID(riid, &IID_IUnknown)
1735       || IsEqualGUID(riid, &IID_IDirectXFileSaveObject))
1736   {
1737     IClassFactory_AddRef(iface);
1738     *ppvObject = This;
1739     return S_OK;
1740   }
1741
1742   ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1743   return E_NOINTERFACE;
1744 }
1745
1746 static ULONG WINAPI IDirectXFileSaveObjectImpl_AddRef(IDirectXFileSaveObject* iface)
1747 {
1748   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1749   ULONG ref = InterlockedIncrement(&This->ref);
1750
1751   TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1752
1753   return ref;
1754 }
1755
1756 static ULONG WINAPI IDirectXFileSaveObjectImpl_Release(IDirectXFileSaveObject* iface)
1757 {
1758   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1759   ULONG ref = InterlockedDecrement(&This->ref);
1760
1761   TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1762
1763   if (!ref)
1764     HeapFree(GetProcessHeap(), 0, This);
1765
1766   return ref;
1767 }
1768
1769 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveTemplates(IDirectXFileSaveObject* iface, DWORD cTemplates, const GUID** ppguidTemplates)
1770 {
1771   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1772
1773   FIXME("(%p/%p)->(%d,%p) stub!\n", This, iface, cTemplates, ppguidTemplates);
1774
1775   return DXFILEERR_BADVALUE;
1776 }
1777
1778 static HRESULT WINAPI IDirectXFileSaveObjectImpl_CreateDataObject(IDirectXFileSaveObject* iface, REFGUID rguidTemplate, LPCSTR szName, const GUID* pguid, DWORD cbSize, LPVOID pvData, LPDIRECTXFILEDATA* ppDataObj)
1779 {
1780   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1781
1782   FIXME("(%p/%p)->(%p,%s,%p,%d,%p,%p) stub!\n", This, iface, rguidTemplate, szName, pguid, cbSize, pvData, ppDataObj);
1783
1784   return DXFILEERR_BADVALUE;
1785 }
1786
1787 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveData(IDirectXFileSaveObject* iface, LPDIRECTXFILEDATA ppDataObj)
1788 {
1789   IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1790
1791   FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj); 
1792
1793   return DXFILEERR_BADVALUE;
1794 }
1795
1796 static const IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl =
1797 {
1798     IDirectXFileSaveObjectImpl_QueryInterface,
1799     IDirectXFileSaveObjectImpl_AddRef,
1800     IDirectXFileSaveObjectImpl_Release,
1801     IDirectXFileSaveObjectImpl_SaveTemplates,
1802     IDirectXFileSaveObjectImpl_CreateDataObject,
1803     IDirectXFileSaveObjectImpl_SaveData
1804 };