kernel32: Add a test for threads state when a process is being terminated.
[wine] / dlls / d3dxof / parsing.c
1 /*
2  * X Files parsing
3  *
4  * Copyright 2008 Christian Costa
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/debug.h"
23
24 #define COBJMACROS
25
26 #include "winbase.h"
27 #include "wingdi.h"
28
29 #include "d3dxof_private.h"
30 #include "dxfile.h"
31
32 #include <stdio.h>
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3dxof_parsing);
35
36 #define MAKEFOUR(a,b,c,d) ((DWORD)a + ((DWORD)b << 8) + ((DWORD)c << 16) + ((DWORD)d << 24))
37 #define XOFFILE_FORMAT_MAGIC         MAKEFOUR('x','o','f',' ')
38 #define XOFFILE_FORMAT_VERSION_302   MAKEFOUR('0','3','0','2')
39 #define XOFFILE_FORMAT_VERSION_303   MAKEFOUR('0','3','0','3')
40 #define XOFFILE_FORMAT_BINARY        MAKEFOUR('b','i','n',' ')
41 #define XOFFILE_FORMAT_TEXT          MAKEFOUR('t','x','t',' ')
42 #define XOFFILE_FORMAT_BINARY_MSZIP  MAKEFOUR('b','z','i','p')
43 #define XOFFILE_FORMAT_TEXT_MSZIP    MAKEFOUR('t','z','i','p')
44 #define XOFFILE_FORMAT_COMPRESSED    MAKEFOUR('c','m','p',' ')
45 #define XOFFILE_FORMAT_FLOAT_BITS_32 MAKEFOUR('0','0','3','2')
46 #define XOFFILE_FORMAT_FLOAT_BITS_64 MAKEFOUR('0','0','6','4')
47
48 #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 /* FOURCC to string conversion for debug messages */
83 static const char *debugstr_fourcc(DWORD fourcc)
84 {
85     if (!fourcc) return "'null'";
86     return wine_dbg_sprintf ("\'%c%c%c%c\'",
87         (char)(fourcc), (char)(fourcc >> 8),
88         (char)(fourcc >> 16), (char)(fourcc >> 24));
89 }
90
91 static const char* get_primitive_string(WORD token)
92 {
93   switch(token)
94   {
95     case TOKEN_WORD:
96       return "WORD";
97     case TOKEN_DWORD:
98       return "DWORD";
99     case TOKEN_FLOAT:
100       return "FLOAT";
101     case TOKEN_DOUBLE:
102       return "DOUBLE";
103     case TOKEN_CHAR:
104       return "CHAR";
105     case TOKEN_UCHAR:
106       return "UCHAR";
107     case TOKEN_SWORD:
108       return "SWORD";
109     case TOKEN_SDWORD:
110       return "SDWORD";
111     case TOKEN_VOID:
112       return "VOID";
113     case TOKEN_LPSTR:
114       return "STRING";
115     case TOKEN_UNICODE:
116       return "UNICODE";
117     case TOKEN_CSTRING:
118       return "CSTRING ";
119     default:
120       break;
121   }
122   return NULL;
123 }
124
125 static void dump_template(xtemplate* templates_array, xtemplate* ptemplate)
126 {
127   ULONG j, k;
128   GUID* clsid;
129
130   clsid = &ptemplate->class_id;
131
132   DPRINTF("template %s\n", ptemplate->name);
133   DPRINTF("{\n");
134   DPRINTF(CLSIDFMT "\n", clsid->Data1, clsid->Data2, clsid->Data3, clsid->Data4[0],
135   clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7]);
136   for (j = 0; j < ptemplate->nb_members; j++)
137   {
138     if (ptemplate->members[j].nb_dims)
139       DPRINTF("array ");
140     if (ptemplate->members[j].type == TOKEN_NAME)
141       DPRINTF("%s ", templates_array[ptemplate->members[j].idx_template].name);
142     else
143       DPRINTF("%s ", get_primitive_string(ptemplate->members[j].type));
144     DPRINTF("%s", ptemplate->members[j].name);
145     for (k = 0; k < ptemplate->members[j].nb_dims; k++)
146     {
147       if (ptemplate->members[j].dim_fixed[k])
148         DPRINTF("[%d]", ptemplate->members[j].dim_value[k]);
149       else
150         DPRINTF("[%s]", ptemplate->members[ptemplate->members[j].dim_value[k]].name);
151     }
152     DPRINTF(";\n");
153   }
154   if (ptemplate->open)
155     DPRINTF("[...]\n");
156   else if (ptemplate->nb_children)
157   {
158     DPRINTF("[%s", ptemplate->children[0]);
159     for (j = 1; j < ptemplate->nb_children; j++)
160       DPRINTF(",%s", ptemplate->children[j]);
161     DPRINTF("]\n");
162   }
163   DPRINTF("}\n");
164 }
165
166 static BOOL read_bytes(parse_buffer * buf, LPVOID data, DWORD size)
167 {
168   if (buf->rem_bytes < size)
169     return FALSE;
170   memcpy(data, buf->buffer, size);
171   buf->buffer += size;
172   buf->rem_bytes -= size;
173   return TRUE;
174 }
175
176 static void rewind_bytes(parse_buffer * buf, DWORD size)
177 {
178   buf->buffer -= size;
179   buf->rem_bytes += size;
180 }
181
182 HRESULT parse_header(parse_buffer * buf, BYTE ** decomp_buffer_ptr)
183 {
184   /* X File common header:
185    *  0-3  -> Magic Number (format identifier)
186    *  4-7  -> Format Version
187    *  8-11 -> Format Type (text or binary, decompressed or compressed)
188    * 12-15 -> Float Size (32 or 64 bits) */
189   DWORD header[4];
190
191   if (!read_bytes(buf, header, sizeof(header)))
192     return DXFILEERR_BADFILETYPE;
193
194   if (TRACE_ON(d3dxof_parsing))
195   {
196     char string[17];
197     memcpy(string, header, 16);
198     string[16] = 0;
199     TRACE("header = '%s'\n", string);
200   }
201
202   if (header[0] != XOFFILE_FORMAT_MAGIC)
203     return DXFILEERR_BADFILETYPE;
204
205   if (header[1] != XOFFILE_FORMAT_VERSION_302 && header[1] != XOFFILE_FORMAT_VERSION_303)
206     return DXFILEERR_BADFILEVERSION;
207
208   if (header[2] != XOFFILE_FORMAT_BINARY && header[2] != XOFFILE_FORMAT_TEXT &&
209       header[2] != XOFFILE_FORMAT_BINARY_MSZIP && header[2] != XOFFILE_FORMAT_TEXT_MSZIP)
210   {
211     WARN("File type %s unknown\n", debugstr_fourcc(header[2]));
212     return DXFILEERR_BADFILETYPE;
213   }
214
215   if (header[3] != XOFFILE_FORMAT_FLOAT_BITS_32 && header[3] != XOFFILE_FORMAT_FLOAT_BITS_64)
216     return DXFILEERR_BADFILEFLOATSIZE;
217
218   buf->txt = header[2] == XOFFILE_FORMAT_TEXT || header[2] == XOFFILE_FORMAT_TEXT_MSZIP;
219
220   if (header[2] == XOFFILE_FORMAT_BINARY_MSZIP || header[2] == XOFFILE_FORMAT_TEXT_MSZIP)
221   {
222     /* Extended header for compressed data:
223      * 16-19 -> size of decompressed file including xof header,
224      * 20-21 -> size of first decompressed MSZIP chunk, 22-23 -> size of first compressed MSZIP chunk
225      * 24-xx -> compressed MSZIP data chunk
226      * xx-xx -> size of next decompressed MSZIP chunk, xx-xx -> size of next compressed MSZIP chunk
227      * xx-xx -> compressed MSZIP data chunk
228      * .............................................................................................. */
229     int err;
230     DWORD decomp_file_size;
231     WORD decomp_chunk_size;
232     WORD comp_chunk_size;
233     LPBYTE decomp_buffer;
234
235     if (!read_bytes(buf, &decomp_file_size, sizeof(decomp_file_size)))
236       return DXFILEERR_BADFILETYPE;
237
238     TRACE("Compressed format %s detected: decompressed file size with xof header = %d\n",
239           debugstr_fourcc(header[2]), decomp_file_size);
240
241     /* Does not take xof header into account */
242     decomp_file_size -= 16;
243
244     decomp_buffer = HeapAlloc(GetProcessHeap(), 0, decomp_file_size);
245     if (!decomp_buffer)
246     {
247         ERR("Out of memory\n");
248         return DXFILEERR_BADALLOC;
249     }
250     *decomp_buffer_ptr = decomp_buffer;
251
252     while (buf->rem_bytes)
253     {
254       if (!read_bytes(buf, &decomp_chunk_size, sizeof(decomp_chunk_size)))
255         return DXFILEERR_BADFILETYPE;
256       if (!read_bytes(buf, &comp_chunk_size, sizeof(comp_chunk_size)))
257         return DXFILEERR_BADFILETYPE;
258
259       TRACE("Process chunk: compressed_size = %d, decompressed_size = %d\n",
260             comp_chunk_size, decomp_chunk_size);
261
262       err = mszip_decompress(comp_chunk_size, decomp_chunk_size, (char*)buf->buffer, (char*)decomp_buffer);
263       if (err)
264       {
265         WARN("Error while decompressing MSZIP chunk %d\n", err);
266         HeapFree(GetProcessHeap(), 0, decomp_buffer);
267         return DXFILEERR_BADALLOC;
268       }
269       buf->rem_bytes -= comp_chunk_size;
270       buf->buffer += comp_chunk_size;
271       decomp_buffer += decomp_chunk_size;
272     }
273
274     if ((decomp_buffer - *decomp_buffer_ptr) != decomp_file_size)
275       ERR("Size of all decompressed chunks (%u) does not match decompressed file size (%u)\n",
276           (DWORD)(decomp_buffer - *decomp_buffer_ptr), decomp_file_size);
277
278     /* Use decompressed data */
279     buf->buffer = *decomp_buffer_ptr;
280     buf->rem_bytes = decomp_file_size;
281   }
282
283   TRACE("Header is correct\n");
284
285   return S_OK;
286 }
287
288 static void dump_TOKEN(WORD token)
289 {
290 #define DUMP_TOKEN(t) case t: TRACE(#t "\n"); break
291   switch(token)
292   {
293     DUMP_TOKEN(TOKEN_NAME);
294     DUMP_TOKEN(TOKEN_STRING);
295     DUMP_TOKEN(TOKEN_INTEGER);
296     DUMP_TOKEN(TOKEN_GUID);
297     DUMP_TOKEN(TOKEN_INTEGER_LIST);
298     DUMP_TOKEN(TOKEN_FLOAT_LIST);
299     DUMP_TOKEN(TOKEN_OBRACE);
300     DUMP_TOKEN(TOKEN_CBRACE);
301     DUMP_TOKEN(TOKEN_OPAREN);
302     DUMP_TOKEN(TOKEN_CPAREN);
303     DUMP_TOKEN(TOKEN_OBRACKET);
304     DUMP_TOKEN(TOKEN_CBRACKET);
305     DUMP_TOKEN(TOKEN_OANGLE);
306     DUMP_TOKEN(TOKEN_CANGLE);
307     DUMP_TOKEN(TOKEN_DOT);
308     DUMP_TOKEN(TOKEN_COMMA);
309     DUMP_TOKEN(TOKEN_SEMICOLON);
310     DUMP_TOKEN(TOKEN_TEMPLATE);
311     DUMP_TOKEN(TOKEN_WORD);
312     DUMP_TOKEN(TOKEN_DWORD);
313     DUMP_TOKEN(TOKEN_FLOAT);
314     DUMP_TOKEN(TOKEN_DOUBLE);
315     DUMP_TOKEN(TOKEN_CHAR);
316     DUMP_TOKEN(TOKEN_UCHAR);
317     DUMP_TOKEN(TOKEN_SWORD);
318     DUMP_TOKEN(TOKEN_SDWORD);
319     DUMP_TOKEN(TOKEN_VOID);
320     DUMP_TOKEN(TOKEN_LPSTR);
321     DUMP_TOKEN(TOKEN_UNICODE);
322     DUMP_TOKEN(TOKEN_CSTRING);
323     DUMP_TOKEN(TOKEN_ARRAY);
324     default:
325       if (0)
326         TRACE("Unknown token %d\n", token);
327       break;
328   }
329 #undef DUMP_TOKEN
330 }
331
332 static BOOL is_space(char c)
333 {
334   switch (c)
335   {
336     case 0x00:
337     case 0x0D:
338     case 0x0A:
339     case ' ':
340     case '\t':
341       return TRUE;
342   }
343   return FALSE;
344 }
345
346 static BOOL is_operator(char c)
347 {
348   switch(c)
349   {
350     case '{':
351     case '}':
352     case '[':
353     case ']':
354     case '(':
355     case ')':
356     case '<':
357     case '>':
358     case ',':
359     case ';':
360       return TRUE;
361   }
362   return FALSE;
363 }
364
365 static inline BOOL is_separator(char c)
366 {
367   return is_space(c) || is_operator(c);
368 }
369
370 static WORD get_operator_token(char c)
371 {
372   switch(c)
373   {
374     case '{':
375       return TOKEN_OBRACE;
376     case '}':
377       return TOKEN_CBRACE;
378     case '[':
379       return TOKEN_OBRACKET;
380     case ']':
381       return TOKEN_CBRACKET;
382     case '(':
383       return TOKEN_OPAREN;
384     case ')':
385       return TOKEN_CPAREN;
386     case '<':
387       return TOKEN_OANGLE;
388     case '>':
389       return TOKEN_CANGLE;
390     case ',':
391       return TOKEN_COMMA;
392     case ';':
393       return TOKEN_SEMICOLON;
394   }
395   return 0;
396 }
397
398 static BOOL is_keyword(parse_buffer* buf, const char* keyword)
399 {
400   char tmp[8]; /* longest keyword size (template) */
401   DWORD len = strlen(keyword);
402
403   if (!read_bytes(buf, tmp, len))
404     return FALSE;
405   if (strncasecmp(tmp, keyword, len))
406   {
407     rewind_bytes(buf, len);
408     return FALSE;
409   }
410
411   if (!read_bytes(buf, tmp, 1))
412     return TRUE;
413   if (is_separator(tmp[0]))
414   {
415     rewind_bytes(buf, 1);
416     return TRUE;
417   }
418   rewind_bytes(buf, len+1);
419   return FALSE;
420 }
421
422 static WORD get_keyword_token(parse_buffer* buf)
423 {
424   if (is_keyword(buf, "template"))
425     return TOKEN_TEMPLATE;
426   if (is_keyword(buf, "WORD"))
427     return TOKEN_WORD;
428   if (is_keyword(buf, "DWORD"))
429     return TOKEN_DWORD;
430   if (is_keyword(buf, "FLOAT"))
431     return TOKEN_FLOAT;
432   if (is_keyword(buf, "DOUBLE"))
433     return TOKEN_DOUBLE;
434   if (is_keyword(buf, "CHAR"))
435     return TOKEN_CHAR;
436   if (is_keyword(buf, "UCHAR"))
437     return TOKEN_UCHAR;
438   if (is_keyword(buf, "SWORD"))
439     return TOKEN_SWORD;
440   if (is_keyword(buf, "SDWORD"))
441     return TOKEN_SDWORD;
442   if (is_keyword(buf, "VOID"))
443     return TOKEN_VOID;
444   if (is_keyword(buf, "STRING"))
445     return TOKEN_LPSTR;
446   if (is_keyword(buf, "UNICODE"))
447     return TOKEN_UNICODE;
448   if (is_keyword(buf, "CSTRING"))
449     return TOKEN_CSTRING;
450   if (is_keyword(buf, "array"))
451     return TOKEN_ARRAY;
452
453   return 0;
454 }
455
456 static BOOL is_guid(parse_buffer* buf)
457 {
458   char tmp[50];
459   DWORD pos = 1;
460   GUID class_id;
461   DWORD tab[10];
462   int ret;
463
464   if (buf->rem_bytes < 38 || *buf->buffer != '<')
465     return FALSE;
466   tmp[0] = '<';
467   while (pos < sizeof(tmp) - 2 && *(buf->buffer+pos) != '>')
468   {
469     tmp[pos] = *(buf->buffer+pos);
470     pos++;
471   }
472   tmp[pos++] = '>';
473   tmp[pos] = 0;
474   if (pos != 38 /* <+36+> */)
475   {
476     TRACE("Wrong guid %s (%d)\n", tmp, pos);
477     return FALSE;
478   }
479   buf->buffer += pos;
480   buf->rem_bytes -= pos;
481
482   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);
483   if (ret != 11)
484   {
485     TRACE("Wrong guid %s (%d)\n", tmp, pos);
486     return FALSE;
487   }
488   TRACE("Found guid %s (%d)\n", tmp, pos);
489
490   class_id.Data2 = tab[0];
491   class_id.Data3 = tab[1];
492   class_id.Data4[0] = tab[2];
493   class_id.Data4[1] = tab[3];
494   class_id.Data4[2] = tab[4];
495   class_id.Data4[3] = tab[5];
496   class_id.Data4[4] = tab[6];
497   class_id.Data4[5] = tab[7];
498   class_id.Data4[6] = tab[8];
499   class_id.Data4[7] = tab[9];
500
501   *(GUID*)buf->value = class_id;
502
503   return TRUE;
504 }
505
506 static BOOL is_name(parse_buffer* buf)
507 {
508   char tmp[512];
509   DWORD pos = 0;
510   char c;
511   BOOL error = 0;
512   while (pos < buf->rem_bytes && !is_separator(c = *(buf->buffer+pos)))
513   {
514     if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')) || (c == '_') || (c == '-')))
515       error = 1;
516     if (pos < sizeof(tmp))
517         tmp[pos] = c;
518     pos++;
519   }
520   tmp[min(pos, sizeof(tmp) - 1)] = 0;
521
522   if (error)
523   {
524     TRACE("Wrong name %s\n", tmp);
525     return FALSE;
526   }
527
528   buf->buffer += pos;
529   buf->rem_bytes -= pos;
530
531   TRACE("Found name %s\n", tmp);
532   strcpy((char*)buf->value, tmp);
533
534   return TRUE;
535 }
536
537 static BOOL is_float(parse_buffer* buf)
538 {
539   char tmp[512];
540   DWORD pos = 0;
541   char c;
542   float decimal;
543   BOOL dot = 0;
544
545   while (pos < buf->rem_bytes && !is_separator(c = *(buf->buffer+pos)))
546   {
547     if (!((!pos && (c == '-')) || ((c >= '0') && (c <= '9')) || (!dot && (c == '.'))))
548       return FALSE;
549     if (c == '.')
550       dot = TRUE;
551     if (pos < sizeof(tmp))
552         tmp[pos] = c;
553     pos++;
554   }
555   tmp[min(pos, sizeof(tmp) - 1)] = 0;
556
557   buf->buffer += pos;
558   buf->rem_bytes -= pos;
559
560   sscanf(tmp, "%f", &decimal);
561
562   TRACE("Found float %s - %f\n", tmp, decimal);
563
564   *(float*)buf->value = decimal;
565
566   return TRUE;
567 }
568
569 static BOOL is_integer(parse_buffer* buf)
570 {
571   char tmp[512];
572   DWORD pos = 0;
573   char c;
574   DWORD integer;
575
576   while (pos < buf->rem_bytes && !is_separator(c = *(buf->buffer+pos)))
577   {
578     if (!((c >= '0') && (c <= '9')))
579       return FALSE;
580     if (pos < sizeof(tmp))
581         tmp[pos] = c;
582     pos++;
583   }
584   tmp[min(pos, sizeof(tmp) - 1)] = 0;
585
586   buf->buffer += pos;
587   buf->rem_bytes -= pos;
588
589   sscanf(tmp, "%d", &integer);
590
591   TRACE("Found integer %s - %d\n", tmp, integer);
592
593   *(DWORD*)buf->value = integer;
594
595   return TRUE;
596 }
597
598 static BOOL is_string(parse_buffer* buf)
599 {
600   char tmp[512];
601   DWORD pos = 0;
602   char c;
603   BOOL ok = 0;
604
605   if (*buf->buffer != '"')
606     return FALSE;
607
608   while ((pos+1) < buf->rem_bytes)
609   {
610     c = *(buf->buffer+pos+1);
611     if (c == '"')
612     {
613       ok = 1;
614       break;
615     }
616     if (pos < sizeof(tmp))
617         tmp[pos] = c;
618     pos++;
619   }
620   tmp[min(pos, sizeof(tmp) - 1)] = 0;
621
622   if (!ok)
623   {
624     TRACE("Wrong string %s\n", tmp);
625     return FALSE;
626   }
627
628   buf->buffer += pos + 2;
629   buf->rem_bytes -= pos + 2;
630
631   TRACE("Found string %s\n", tmp);
632   strcpy((char*)buf->value, tmp);
633
634   return TRUE;
635 }
636
637 static WORD parse_TOKEN(parse_buffer * buf)
638 {
639   WORD token;
640
641   if (buf->txt)
642   {
643     while(1)
644     {
645       char c;
646       if (!read_bytes(buf, &c, 1))
647         return 0;
648       /*TRACE("char = '%c'\n", is_space(c) ? ' ' : c);*/
649       if ((c == '#') || (c == '/'))
650       {
651         /* Handle comment (# or //) */
652         if (c == '/')
653         {
654           if (!read_bytes(buf, &c, 1))
655             return 0;
656           if (c != '/')
657             return 0;
658         }
659         c = 0;
660         while (c != 0x0A)
661         {
662           if (!read_bytes(buf, &c, 1))
663             return 0;
664         }
665         continue;
666       }
667       if (is_space(c))
668         continue;
669       if (is_operator(c) && (c != '<'))
670       {
671         token = get_operator_token(c);
672         break;
673       }
674       else if (c == '.')
675       {
676         token = TOKEN_DOT;
677         break;
678       }
679       else
680       {
681         rewind_bytes(buf, 1);
682
683         if ((token = get_keyword_token(buf)))
684           break;
685
686         if (is_guid(buf))
687         {
688           token = TOKEN_GUID;
689           break;
690         }
691         if (is_integer(buf))
692         {
693           token = TOKEN_INTEGER;
694           break;
695         }
696         if (is_float(buf))
697         {
698           token = TOKEN_FLOAT;
699           break;
700         }
701         if (is_string(buf))
702         {
703           token = TOKEN_LPSTR;
704           break;
705         }
706         if (is_name(buf))
707         {
708           token = TOKEN_NAME;
709           break;
710         }
711
712         FIXME("Unrecognize element\n");
713         return 0;
714       }
715     }
716   }
717   else
718   {
719     static int nb_elem;
720     static int is_float;
721
722     if (!nb_elem)
723     {
724       if (!read_bytes(buf, &token, 2))
725         return 0;
726
727       /* Convert integer and float list into separate elements */
728       if (token == TOKEN_INTEGER_LIST)
729       {
730         if (!read_bytes(buf, &nb_elem, 4))
731           return 0;
732         token = TOKEN_INTEGER;
733         is_float = FALSE;
734         TRACE("Integer list (TOKEN_INTEGER_LIST) of size %d\n", nb_elem);
735       }
736       else if (token == TOKEN_FLOAT_LIST)
737       {
738         if (!read_bytes(buf, &nb_elem, 4))
739           return 0;
740         token = TOKEN_FLOAT;
741         is_float = TRUE;
742         TRACE("Float list (TOKEN_FLOAT_LIST) of size %d\n", nb_elem);
743       }
744     }
745
746     if (nb_elem)
747     {
748       token = is_float ? TOKEN_FLOAT : TOKEN_INTEGER;
749       nb_elem--;
750         {
751           DWORD integer;
752
753           if (!read_bytes(buf, &integer, 4))
754             return 0;
755
756           *(DWORD*)buf->value = integer;
757         }
758       dump_TOKEN(token);
759       return token;
760     }
761
762     switch (token)
763     {
764       case TOKEN_NAME:
765         {
766           DWORD count;
767           char strname[100];
768
769           if (!read_bytes(buf, &count, 4))
770             return 0;
771           if (!read_bytes(buf, strname, count))
772             return 0;
773           strname[count] = 0;
774           /*TRACE("name = %s\n", strname);*/
775
776           strcpy((char*)buf->value, strname);
777         }
778         break;
779       case TOKEN_INTEGER:
780         {
781           DWORD integer;
782
783           if (!read_bytes(buf, &integer, 4))
784             return 0;
785           /*TRACE("integer = %ld\n", integer);*/
786
787           *(DWORD*)buf->value = integer;
788         }
789         break;
790       case TOKEN_GUID:
791         {
792           char strguid[39];
793           GUID class_id;
794
795           if (!read_bytes(buf, &class_id, 16))
796             return 0;
797           sprintf(strguid, CLSIDFMT, class_id.Data1, class_id.Data2, class_id.Data3, class_id.Data4[0],
798             class_id.Data4[1], class_id.Data4[2], class_id.Data4[3], class_id.Data4[4], class_id.Data4[5],
799             class_id.Data4[6], class_id.Data4[7]);
800           /*TRACE("guid = {%s}\n", strguid);*/
801
802           *(GUID*)buf->value = class_id;
803         }
804         break;
805       case TOKEN_STRING:
806         {
807           DWORD count;
808           WORD tmp_token;
809           char strname[100];
810           if (!read_bytes(buf, &count, 4))
811             return 0;
812           if (!read_bytes(buf, strname, count))
813             return 0;
814           strname[count] = 0;
815           if (!read_bytes(buf, &tmp_token, 2))
816             return 0;
817           if ((tmp_token != TOKEN_COMMA) && (tmp_token != TOKEN_SEMICOLON))
818             ERR("No comma or semicolon (got %d)\n", tmp_token);
819           /*TRACE("name = %s\n", strname);*/
820
821           strcpy((char*)buf->value, strname);
822           token = TOKEN_LPSTR;
823         }
824         break;
825       case TOKEN_OBRACE:
826       case TOKEN_CBRACE:
827       case TOKEN_OPAREN:
828       case TOKEN_CPAREN:
829       case TOKEN_OBRACKET:
830       case TOKEN_CBRACKET:
831       case TOKEN_OANGLE:
832       case TOKEN_CANGLE:
833       case TOKEN_DOT:
834       case TOKEN_COMMA:
835       case TOKEN_SEMICOLON:
836       case TOKEN_TEMPLATE:
837       case TOKEN_WORD:
838       case TOKEN_DWORD:
839       case TOKEN_FLOAT:
840       case TOKEN_DOUBLE:
841       case TOKEN_CHAR:
842       case TOKEN_UCHAR:
843       case TOKEN_SWORD:
844       case TOKEN_SDWORD:
845       case TOKEN_VOID:
846       case TOKEN_LPSTR:
847       case TOKEN_UNICODE:
848       case TOKEN_CSTRING:
849       case TOKEN_ARRAY:
850         break;
851       default:
852         return 0;
853     }
854   }
855
856   dump_TOKEN(token);
857
858   return token;
859 }
860
861 static WORD get_TOKEN(parse_buffer * buf)
862 {
863   if (buf->token_present)
864   {
865     buf->token_present = FALSE;
866     return buf->current_token;
867   }
868
869   buf->current_token = parse_TOKEN(buf);
870
871   return buf->current_token;
872 }
873
874 static WORD check_TOKEN(parse_buffer * buf)
875 {
876   if (buf->token_present)
877     return buf->current_token;
878
879   buf->current_token = parse_TOKEN(buf);
880   buf->token_present = TRUE;
881
882   return buf->current_token;
883 }
884
885 static BOOL is_template_available(parse_buffer * buf)
886 {
887   return check_TOKEN(buf) == TOKEN_TEMPLATE;
888 }
889
890 static inline BOOL is_primitive_type(WORD token)
891 {
892   BOOL ret;
893   switch(token)
894   {
895     case TOKEN_WORD:
896     case TOKEN_DWORD:
897     case TOKEN_FLOAT:
898     case TOKEN_DOUBLE:
899     case TOKEN_CHAR:
900     case TOKEN_UCHAR:
901     case TOKEN_SWORD:
902     case TOKEN_SDWORD:
903     case TOKEN_LPSTR:
904     case TOKEN_UNICODE:
905     case TOKEN_CSTRING:
906       ret = 1;
907       break;
908     default:
909       ret = 0;
910       break;
911   }
912   return ret;
913 }
914
915 static BOOL parse_template_option_info(parse_buffer * buf)
916 {
917   xtemplate* cur_template = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates];
918
919   if (check_TOKEN(buf) == TOKEN_DOT)
920   {
921     get_TOKEN(buf);
922     if (get_TOKEN(buf) != TOKEN_DOT)
923       return FALSE;
924     if (get_TOKEN(buf) != TOKEN_DOT)
925       return FALSE;
926     cur_template->open = TRUE;
927   }
928   else
929   {
930     while (1)
931     {
932       if (get_TOKEN(buf) != TOKEN_NAME)
933         return FALSE;
934       strcpy(cur_template->children[cur_template->nb_children], (char*)buf->value);
935       if (check_TOKEN(buf) == TOKEN_GUID)
936         get_TOKEN(buf);
937       cur_template->nb_children++;
938       if (check_TOKEN(buf) != TOKEN_COMMA)
939         break;
940       get_TOKEN(buf);
941     }
942     cur_template->open = FALSE;
943   }
944
945   return TRUE;
946 }
947
948 static BOOL parse_template_members_list(parse_buffer * buf)
949 {
950   int idx_member = 0;
951   member* cur_member;
952
953   while (1)
954   {
955     BOOL array = 0;
956     int nb_dims = 0;
957     cur_member = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[idx_member];
958
959     if (check_TOKEN(buf) == TOKEN_ARRAY)
960     {
961       get_TOKEN(buf);
962       array = 1;
963     }
964
965     if (check_TOKEN(buf) == TOKEN_NAME)
966     {
967       cur_member->type = get_TOKEN(buf);
968       cur_member->idx_template = 0;
969       while (cur_member->idx_template < buf->pdxf->nb_xtemplates)
970       {
971         if (!strcasecmp((char*)buf->value, buf->pdxf->xtemplates[cur_member->idx_template].name))
972           break;
973         cur_member->idx_template++;
974       }
975       if (cur_member->idx_template == buf->pdxf->nb_xtemplates)
976       {
977         ERR("Reference to a nonexistent template '%s'\n", (char*)buf->value);
978         return FALSE;
979       }
980     }
981     else if (is_primitive_type(check_TOKEN(buf)))
982       cur_member->type = get_TOKEN(buf);
983     else
984       break;
985
986     if (get_TOKEN(buf) != TOKEN_NAME)
987       return FALSE;
988     strcpy(cur_member->name, (char*)buf->value);
989
990     if (array)
991     {
992       while (check_TOKEN(buf) == TOKEN_OBRACKET)
993       {
994         if (nb_dims >= MAX_ARRAY_DIM)
995         {
996           FIXME("Too many dimensions (%d) for multi-dimensional array\n", nb_dims + 1);
997           return FALSE;
998         }
999         get_TOKEN(buf);
1000         if (check_TOKEN(buf) == TOKEN_INTEGER)
1001         {
1002           get_TOKEN(buf);
1003           cur_member->dim_fixed[nb_dims] = TRUE;
1004           cur_member->dim_value[nb_dims] = *(DWORD*)buf->value;
1005         }
1006         else
1007         {
1008           int i;
1009           if (get_TOKEN(buf) != TOKEN_NAME)
1010             return FALSE;
1011           for (i = 0; i < idx_member; i++)
1012           {
1013             if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[i].name))
1014             {
1015               if (buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[i].nb_dims)
1016               {
1017                 ERR("Array cannot be used to specify variable array size\n");
1018                 return FALSE;
1019               }
1020               if (buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[i].type != TOKEN_DWORD)
1021               {
1022                 FIXME("Only DWORD supported to specify variable array size\n");
1023                 return FALSE;
1024               }
1025               break;
1026             }
1027           }
1028           if (i == idx_member)
1029           {
1030             ERR("Reference to unknown member %s\n", (char*)buf->value);
1031             return FALSE;
1032           }
1033           cur_member->dim_fixed[nb_dims] = FALSE;
1034           cur_member->dim_value[nb_dims] = i;
1035         }
1036         if (get_TOKEN(buf) != TOKEN_CBRACKET)
1037           return FALSE;
1038         nb_dims++;
1039       }
1040       if (!nb_dims)
1041         return FALSE;
1042       cur_member->nb_dims = nb_dims;
1043     }
1044     if (get_TOKEN(buf) != TOKEN_SEMICOLON)
1045       return FALSE;
1046
1047     idx_member++;
1048   }
1049
1050   buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].nb_members = idx_member;
1051
1052   return TRUE;
1053 }
1054
1055 static BOOL parse_template_parts(parse_buffer * buf)
1056 {
1057   if (!parse_template_members_list(buf))
1058     return FALSE;
1059   if (check_TOKEN(buf) == TOKEN_OBRACKET)
1060   {
1061     get_TOKEN(buf);
1062     if (!parse_template_option_info(buf))
1063       return FALSE;
1064     if (get_TOKEN(buf) != TOKEN_CBRACKET)
1065      return FALSE;
1066   }
1067
1068   return TRUE;
1069 }
1070
1071 static void go_to_next_definition(parse_buffer * buf)
1072 {
1073   char c;
1074   while (buf->rem_bytes)
1075   {
1076     if (!read_bytes(buf, &c, 1))
1077       return;
1078     if ((c == '#') || (c == '/'))
1079     {
1080       /* Handle comment (# or //) */
1081       if (c == '/')
1082       {
1083         if (!read_bytes(buf, &c, 1))
1084           return;
1085         if (c != '/')
1086           return;
1087       }
1088       c = 0;
1089       while (c != 0x0A)
1090       {
1091         if (!read_bytes(buf, &c, 1))
1092           return;
1093       }
1094       continue;
1095     }
1096     else if (!is_space(c))
1097     {
1098       rewind_bytes(buf, 1);
1099       break;
1100     }
1101   }
1102 }
1103
1104 static BOOL parse_template(parse_buffer * buf)
1105 {
1106   if (get_TOKEN(buf) != TOKEN_TEMPLATE)
1107     return FALSE;
1108   if (get_TOKEN(buf) != TOKEN_NAME)
1109     return FALSE;
1110   strcpy(buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].name, (char*)buf->value);
1111   if (get_TOKEN(buf) != TOKEN_OBRACE)
1112     return FALSE;
1113   if (get_TOKEN(buf) != TOKEN_GUID)
1114     return FALSE;
1115   buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].class_id = *(GUID*)buf->value;
1116   if (!parse_template_parts(buf))
1117     return FALSE;
1118   if (get_TOKEN(buf) != TOKEN_CBRACE)
1119     return FALSE;
1120   if (buf->txt)
1121   {
1122     /* Go to the next template */
1123     go_to_next_definition(buf);
1124   }
1125
1126   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));
1127   buf->pdxf->nb_xtemplates++;
1128
1129   return TRUE;
1130 }
1131
1132 BOOL parse_templates(parse_buffer * buf)
1133 {
1134   while (buf->rem_bytes && is_template_available(buf))
1135   {
1136     if (!parse_template(buf))
1137     {
1138       WARN("Template is not correct\n");
1139       return FALSE;
1140     }
1141     else
1142     {
1143       TRACE("Template successfully parsed:\n");
1144       if (TRACE_ON(d3dxof_parsing))
1145         dump_template(buf->pdxf->xtemplates, &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates - 1]);
1146     }
1147   }
1148   return TRUE;
1149 }
1150
1151 static BOOL check_buffer(parse_buffer * buf, ULONG size)
1152 {
1153   if ((buf->cur_pos_data + size) > buf->capacity)
1154   {
1155     LPBYTE pdata;
1156     ULONG new_capacity = buf->capacity ? 2 * buf->capacity : 100000;
1157
1158     pdata = HeapAlloc(GetProcessHeap(), 0, new_capacity);
1159     if (!pdata)
1160       return FALSE;
1161     memcpy(pdata, buf->pdata, buf->cur_pos_data);
1162     HeapFree(GetProcessHeap(), 0, buf->pdata);
1163     buf->capacity = new_capacity;
1164     buf->pdata = pdata;
1165     buf->pxo->root->pdata = pdata;
1166   }
1167   return TRUE;
1168 }
1169
1170 static BOOL parse_object_parts(parse_buffer * buf, BOOL allow_optional);
1171 static BOOL parse_object_members_list(parse_buffer * buf)
1172 {
1173   DWORD token;
1174   ULONG i;
1175   xtemplate* pt = buf->pxt[buf->level];
1176
1177   buf->pxo->nb_members = pt->nb_members;
1178
1179   for (i = 0; i < pt->nb_members; i++)
1180   {
1181     ULONG k;
1182     ULONG nb_elems = 1;
1183
1184     buf->pxo->members[i].name = pt->members[i].name;
1185     buf->pxo->members[i].start = buf->cur_pos_data;
1186
1187     for (k = 0; k < pt->members[i].nb_dims; k++)
1188     {
1189       if (pt->members[i].dim_fixed[k])
1190         nb_elems *= pt->members[i].dim_value[k];
1191       else
1192         nb_elems *= *(DWORD*)(buf->pxo->root->pdata + buf->pxo->members[pt->members[i].dim_value[k]].start);
1193     }
1194
1195     TRACE("Elements to consider: %u\n", nb_elems);
1196
1197     for (k = 0; k < nb_elems; k++)
1198     {
1199       if (buf->txt && k)
1200       {
1201         token = check_TOKEN(buf);
1202         if (token == TOKEN_COMMA)
1203         {
1204           get_TOKEN(buf);
1205         }
1206         else
1207         {
1208           /* Allow comma omission */
1209           if (!((token == TOKEN_FLOAT) || (token == TOKEN_INTEGER)))
1210             return FALSE;
1211         }
1212       }
1213
1214       if (pt->members[i].type == TOKEN_NAME)
1215       {
1216         ULONG j;
1217
1218         TRACE("Found sub-object %s\n", buf->pdxf->xtemplates[pt->members[i].idx_template].name);
1219         buf->level++;
1220         /* To do template lookup */
1221         for (j = 0; j < buf->pdxf->nb_xtemplates; j++)
1222         {
1223           if (!strcasecmp(buf->pdxf->xtemplates[pt->members[i].idx_template].name, buf->pdxf->xtemplates[j].name))
1224           {
1225             buf->pxt[buf->level] = &buf->pdxf->xtemplates[j];
1226             break;
1227           }
1228         }
1229         if (j == buf->pdxf->nb_xtemplates)
1230         {
1231           ERR("Unknown template %s\n", (char*)buf->value);
1232           buf->level--;
1233           return FALSE;
1234         }
1235         TRACE("Enter %s\n", buf->pdxf->xtemplates[pt->members[i].idx_template].name);
1236         if (!parse_object_parts(buf, FALSE))
1237         {
1238           buf->level--;
1239           return FALSE;
1240         }
1241         buf->level--;
1242       }
1243       else
1244       {
1245         token = check_TOKEN(buf);
1246         if (token == TOKEN_INTEGER)
1247         {
1248           get_TOKEN(buf);
1249           TRACE("%s = %d\n", pt->members[i].name, *(DWORD*)buf->value);
1250           /* Assume larger size */
1251           if (!check_buffer(buf, 4))
1252             return FALSE;
1253           if (pt->members[i].type == TOKEN_WORD)
1254           {
1255             *(((WORD*)(buf->pdata + buf->cur_pos_data))) = (WORD)(*(DWORD*)buf->value);
1256             buf->cur_pos_data += 2;
1257           }
1258           else if (pt->members[i].type == TOKEN_DWORD)
1259           {
1260             *(((DWORD*)(buf->pdata + buf->cur_pos_data))) = (DWORD)(*(DWORD*)buf->value);
1261             buf->cur_pos_data += 4;
1262           }
1263           else
1264           {
1265             FIXME("Token %d not supported\n", pt->members[i].type);
1266             return FALSE;
1267           }
1268         }
1269         else if (token == TOKEN_FLOAT)
1270         {
1271           get_TOKEN(buf);
1272           TRACE("%s = %f\n", pt->members[i].name, *(float*)buf->value);
1273           if (!check_buffer(buf, 4))
1274             return FALSE;
1275           if (pt->members[i].type == TOKEN_FLOAT)
1276           {
1277             *(((float*)(buf->pdata + buf->cur_pos_data))) = (float)(*(float*)buf->value);
1278             buf->cur_pos_data += 4;
1279           }
1280           else
1281           {
1282             FIXME("Token %d not supported\n", pt->members[i].type);
1283             return FALSE;
1284           }
1285         }
1286         else if (token == TOKEN_LPSTR)
1287         {
1288           get_TOKEN(buf);
1289           TRACE("%s = %s\n", pt->members[i].name, (char*)buf->value);
1290           if (!check_buffer(buf, sizeof(LPSTR)))
1291             return FALSE;
1292           if (pt->members[i].type == TOKEN_LPSTR)
1293           {
1294             int len = strlen((char*)buf->value) + 1;
1295             if ((buf->cur_pstrings - buf->pstrings + len) > MAX_STRINGS_BUFFER)
1296             {
1297               FIXME("Buffer too small %p %p %d\n", buf->cur_pstrings, buf->pstrings, len);
1298               return FALSE;
1299             }
1300             strcpy((char*)buf->cur_pstrings, (char*)buf->value);
1301             *(((LPCSTR*)(buf->pdata + buf->cur_pos_data))) = (char*)buf->cur_pstrings;
1302             buf->cur_pstrings += len;
1303             buf->cur_pos_data += sizeof(LPSTR);
1304           }
1305           else
1306           {
1307             FIXME("Token %d not supported\n", pt->members[i].type);
1308             return FALSE;
1309           }
1310         }
1311         else
1312         {
1313           FIXME("Unexpected token %d\n", token);
1314           return FALSE;
1315         }
1316       }
1317     }
1318
1319     /* Empty arrays can have the semicolon at the end or not so remove it if any and skip next check */
1320     if (!nb_elems && (check_TOKEN(buf) == TOKEN_SEMICOLON))
1321       get_TOKEN(buf);
1322
1323     if (nb_elems && buf->txt && (check_TOKEN(buf) != TOKEN_CBRACE) && (check_TOKEN(buf) != TOKEN_NAME))
1324     {
1325       token = get_TOKEN(buf);
1326       if ((token != TOKEN_SEMICOLON) && (token != TOKEN_COMMA))
1327         return FALSE;
1328     }
1329     buf->pxo->members[i].size = buf->cur_pos_data - buf->pxo->members[i].start;
1330   }
1331
1332   return TRUE;
1333 }
1334
1335 static BOOL parse_object_parts(parse_buffer * buf, BOOL allow_optional)
1336 {
1337   buf->pxo->nb_children = 0;
1338
1339   if (!parse_object_members_list(buf))
1340     return FALSE;
1341
1342   if (allow_optional)
1343   {
1344     buf->pxo->size = buf->cur_pos_data - buf->pxo->pos_data;
1345
1346     /* Skip trailing semicolon */
1347     while (check_TOKEN(buf) == TOKEN_SEMICOLON)
1348       get_TOKEN(buf);
1349
1350     while (1)
1351     {
1352       if (check_TOKEN(buf) == TOKEN_OBRACE)
1353       {
1354         ULONG i, j;
1355         get_TOKEN(buf);
1356         if (get_TOKEN(buf) != TOKEN_NAME)
1357           return FALSE;
1358         if (get_TOKEN(buf) != TOKEN_CBRACE)
1359           return FALSE;
1360         TRACE("Found optional reference %s\n", (char*)buf->value);
1361         for (i = 0; i < (buf->nb_pxo_globals+1); i++)
1362         {
1363           for (j = 0; j < (buf->pxo_globals[i])[0].nb_subobjects; j++)
1364           {
1365             if (!strcmp((buf->pxo_globals[i])[j].name, (char*)buf->value))
1366               goto _exit;
1367           }
1368         }
1369 _exit:
1370         if (i == (buf->nb_pxo_globals+1))
1371         {
1372           ERR("Reference to unknown object %s\n", (char*)buf->value);
1373           return FALSE;
1374         }
1375
1376         if (buf->pxo->root->nb_subobjects >= MAX_SUBOBJECTS)
1377         {
1378             FIXME("Too many sub-objects\n");
1379             return FALSE;
1380         }
1381
1382         buf->pxo->children[buf->pxo->nb_children] = &buf->pxo_tab[buf->pxo->root->nb_subobjects++];
1383         buf->pxo->children[buf->pxo->nb_children]->ptarget = &(buf->pxo_globals[i])[j];
1384         buf->pxo->children[buf->pxo->nb_children]->binary = FALSE;
1385         buf->pxo->nb_children++;
1386       }
1387       else if (check_TOKEN(buf) == TOKEN_NAME)
1388       {
1389         xobject* pxo = buf->pxo;
1390
1391         if (buf->pxo->root->nb_subobjects >= MAX_SUBOBJECTS)
1392         {
1393             FIXME("Too many sub-objects\n");
1394             return FALSE;
1395         }
1396
1397         buf->pxo = buf->pxo->children[buf->pxo->nb_children] = &buf->pxo_tab[buf->pxo->root->nb_subobjects++];
1398
1399         TRACE("Enter optional %s\n", (char*)buf->value);
1400         buf->level++;
1401         if (!parse_object(buf))
1402         {
1403           buf->level--;
1404           return FALSE;
1405         }
1406         buf->level--;
1407         buf->pxo = pxo;
1408         buf->pxo->nb_children++;
1409       }
1410       else
1411         break;
1412     }
1413   }
1414
1415   if (buf->pxo->nb_children > MAX_CHILDREN)
1416   {
1417     FIXME("Too many children %d\n", buf->pxo->nb_children);
1418     return FALSE;
1419   }
1420
1421   return TRUE;
1422 }
1423
1424 BOOL parse_object(parse_buffer * buf)
1425 {
1426   ULONG i;
1427
1428   buf->pxo->pos_data = buf->cur_pos_data;
1429   buf->pxo->ptarget = NULL;
1430   buf->pxo->binary = FALSE;
1431   buf->pxo->root = buf->pxo_tab;
1432
1433   if (get_TOKEN(buf) != TOKEN_NAME)
1434     return FALSE;
1435
1436   /* To do template lookup */
1437   for (i = 0; i < buf->pdxf->nb_xtemplates; i++)
1438   {
1439     if (!strcasecmp((char*)buf->value, buf->pdxf->xtemplates[i].name))
1440     {
1441       buf->pxt[buf->level] = &buf->pdxf->xtemplates[i];
1442       memcpy(&buf->pxo->type, &buf->pdxf->xtemplates[i].class_id, 16);
1443       break;
1444     }
1445   }
1446   if (i == buf->pdxf->nb_xtemplates)
1447   {
1448     ERR("Unknown template %s\n", (char*)buf->value);
1449     return FALSE;
1450   }
1451
1452   if (check_TOKEN(buf) == TOKEN_NAME)
1453   {
1454     get_TOKEN(buf);
1455     strcpy(buf->pxo->name, (char*)buf->value);
1456   }
1457   else
1458     buf->pxo->name[0] = 0;
1459
1460   if (get_TOKEN(buf) != TOKEN_OBRACE)
1461     return FALSE;
1462   if (check_TOKEN(buf) == TOKEN_GUID)
1463   {
1464     get_TOKEN(buf);
1465     memcpy(&buf->pxo->class_id, buf->value, 16);
1466   }
1467   else
1468     memset(&buf->pxo->class_id, 0, 16);
1469
1470   if (!parse_object_parts(buf, TRUE))
1471     return FALSE;
1472   if (get_TOKEN(buf) != TOKEN_CBRACE)
1473     return FALSE;
1474
1475   if (buf->txt)
1476   {
1477     /* Go to the next object */
1478     go_to_next_definition(buf);
1479   }
1480
1481   return TRUE;
1482 }