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