push 337eb2e2d902d84a5d689451984c5832d7e04fc4
[wine/hacks.git] / dlls / d3dxof / d3dxof.c
blob4be62bdf94026e624d6e80bcd329dcdac871a086
1 /*
2 * Implementation of DirectX File Interfaces
4 * Copyright 2004, 2008 Christian Costa
6 * This file contains the (internal) driver registration functions,
7 * driver enumeration APIs and DirectDraw creation functions.
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.
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.
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
24 #include "config.h"
25 #include "wine/debug.h"
27 #define COBJMACROS
29 #include "winbase.h"
30 #include "wingdi.h"
32 #include "d3dxof_private.h"
33 #include "dxfile.h"
35 #include <stdio.h>
37 WINE_DEFAULT_DEBUG_CHANNEL(d3dxof);
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_302 MAKEFOUR('0','3','0','2')
42 #define XOFFILE_FORMAT_VERSION_303 MAKEFOUR('0','3','0','3')
43 #define XOFFILE_FORMAT_BINARY MAKEFOUR('b','i','n',' ')
44 #define XOFFILE_FORMAT_TEXT MAKEFOUR('t','x','t',' ')
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')
49 #define TOKEN_NAME 1
50 #define TOKEN_STRING 2
51 #define TOKEN_INTEGER 3
52 #define TOKEN_GUID 5
53 #define TOKEN_INTEGER_LIST 6
54 #define TOKEN_FLOAT_LIST 7
55 #define TOKEN_OBRACE 10
56 #define TOKEN_CBRACE 11
57 #define TOKEN_OPAREN 12
58 #define TOKEN_CPAREN 13
59 #define TOKEN_OBRACKET 14
60 #define TOKEN_CBRACKET 15
61 #define TOKEN_OANGLE 16
62 #define TOKEN_CANGLE 17
63 #define TOKEN_DOT 18
64 #define TOKEN_COMMA 19
65 #define TOKEN_SEMICOLON 20
66 #define TOKEN_TEMPLATE 31
67 #define TOKEN_WORD 40
68 #define TOKEN_DWORD 41
69 #define TOKEN_FLOAT 42
70 #define TOKEN_DOUBLE 43
71 #define TOKEN_CHAR 44
72 #define TOKEN_UCHAR 45
73 #define TOKEN_SWORD 46
74 #define TOKEN_SDWORD 47
75 #define TOKEN_VOID 48
76 #define TOKEN_LPSTR 49
77 #define TOKEN_UNICODE 50
78 #define TOKEN_CSTRING 51
79 #define TOKEN_ARRAY 52
81 #define CLSIDFMT "<%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X>"
83 #define MAX_INPUT_SIZE 2000000
84 #define MAX_DATA_SIZE 400000
86 static const struct IDirectXFileVtbl IDirectXFile_Vtbl;
87 static const struct IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl;
88 static const struct IDirectXFileDataVtbl IDirectXFileData_Vtbl;
89 static const struct IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl;
90 static const struct IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl;
91 static const struct IDirectXFileObjectVtbl IDirectXFileObject_Vtbl;
92 static const struct IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl;
94 static BOOL parse_object_parts(parse_buffer * buf, BOOL allow_optional);
95 static BOOL parse_object(parse_buffer * buf);
96 static const char* get_primitive_string(WORD token);
97 static WORD check_TOKEN(parse_buffer * buf);
98 static BOOL parse_template(parse_buffer * buf);
99 static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj);
100 static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj);
102 static void dump_template(xtemplate* templates_array, xtemplate* ptemplate)
104 int j, k;
105 GUID* clsid;
107 clsid = &ptemplate->class_id;
109 DPRINTF("template %s\n", ptemplate->name);
110 DPRINTF("{\n");
111 DPRINTF(CLSIDFMT "\n", clsid->Data1, clsid->Data2, clsid->Data3, clsid->Data4[0],
112 clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7]);
113 for (j = 0; j < ptemplate->nb_members; j++)
115 if (ptemplate->members[j].nb_dims)
116 DPRINTF("array ");
117 if (ptemplate->members[j].type == TOKEN_NAME)
118 DPRINTF("%s ", templates_array[ptemplate->members[j].idx_template].name);
119 else
120 DPRINTF("%s ", get_primitive_string(ptemplate->members[j].type));
121 DPRINTF("%s", ptemplate->members[j].name);
122 for (k = 0; k < ptemplate->members[j].nb_dims; k++)
124 if (ptemplate->members[j].dim_fixed[k])
125 DPRINTF("[%d]", ptemplate->members[j].dim_value[k]);
126 else
127 DPRINTF("[%s]", ptemplate->members[ptemplate->members[j].dim_value[k]].name);
129 DPRINTF(";\n");
131 if (ptemplate->open)
132 DPRINTF("[...]\n");
133 else if (ptemplate->nb_childs)
135 DPRINTF("[%s", ptemplate->childs[0]);
136 for (j = 1; j < ptemplate->nb_childs; j++)
137 DPRINTF(",%s", ptemplate->childs[j]);
138 DPRINTF("]\n");
140 DPRINTF("}\n");
143 HRESULT IDirectXFileImpl_Create(IUnknown* pUnkOuter, LPVOID* ppObj)
145 IDirectXFileImpl* object;
147 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
149 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileImpl));
151 object->lpVtbl.lpVtbl = &IDirectXFile_Vtbl;
152 object->ref = 1;
154 *ppObj = object;
156 return S_OK;
159 /*** IUnknown methods ***/
160 static HRESULT WINAPI IDirectXFileImpl_QueryInterface(IDirectXFile* iface, REFIID riid, void** ppvObject)
162 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
164 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
166 if (IsEqualGUID(riid, &IID_IUnknown)
167 || IsEqualGUID(riid, &IID_IDirectXFile))
169 IClassFactory_AddRef(iface);
170 *ppvObject = This;
171 return S_OK;
174 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
175 return E_NOINTERFACE;
178 static ULONG WINAPI IDirectXFileImpl_AddRef(IDirectXFile* iface)
180 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
181 ULONG ref = InterlockedIncrement(&This->ref);
183 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
185 return ref;
188 static ULONG WINAPI IDirectXFileImpl_Release(IDirectXFile* iface)
190 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
191 ULONG ref = InterlockedDecrement(&This->ref);
193 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
195 if (!ref)
196 HeapFree(GetProcessHeap(), 0, This);
198 return ref;
201 /*** IDirectXFile methods ***/
202 static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPVOID pvSource, DXFILELOADOPTIONS dwLoadOptions, LPDIRECTXFILEENUMOBJECT* ppEnumObj)
204 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
205 IDirectXFileEnumObjectImpl* object;
206 HRESULT hr;
207 DWORD header[4];
208 DWORD size;
209 HANDLE hFile = INVALID_HANDLE_VALUE;
210 LPDXFILELOADMEMORY lpdxflm = NULL;
212 TRACE("(%p/%p)->(%p,%x,%p)\n", This, iface, pvSource, dwLoadOptions, ppEnumObj);
214 if (!ppEnumObj)
215 return DXFILEERR_BADVALUE;
217 if (dwLoadOptions == DXFILELOAD_FROMFILE)
219 TRACE("Open source file '%s'\n", (char*)pvSource);
221 hFile = CreateFileA((char*)pvSource, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
222 if (hFile == INVALID_HANDLE_VALUE)
224 TRACE("File '%s' not found\n", (char*)pvSource);
225 return DXFILEERR_FILENOTFOUND;
228 if (!ReadFile(hFile, header, 16, &size, NULL))
230 hr = DXFILEERR_BADVALUE;
231 goto error;
234 if (size < 16)
236 hr = DXFILEERR_BADFILETYPE;
237 goto error;
240 else if (dwLoadOptions == DXFILELOAD_FROMMEMORY)
242 lpdxflm = (LPDXFILELOADMEMORY)pvSource;
244 TRACE("Source in memory at %p with size %d\n", lpdxflm->lpMemory, lpdxflm->dSize);
246 memcpy(header, (char*)lpdxflm->lpMemory, 16);
248 else
250 FIXME("Source type %d is not handled yet\n", dwLoadOptions);
251 hr = DXFILEERR_NOTDONEYET;
252 goto error;
255 if (TRACE_ON(d3dxof))
257 char string[17];
258 memcpy(string, header, 16);
259 string[16] = 0;
260 TRACE("header = '%s'\n", string);
263 if (header[0] != XOFFILE_FORMAT_MAGIC)
265 hr = DXFILEERR_BADFILETYPE;
266 goto error;
269 if ((header[1] != XOFFILE_FORMAT_VERSION_302) && (header[1] != XOFFILE_FORMAT_VERSION_303))
271 hr = DXFILEERR_BADFILEVERSION;
272 goto error;
275 if ((header[2] != XOFFILE_FORMAT_BINARY) && (header[2] != XOFFILE_FORMAT_TEXT) && (header[2] != XOFFILE_FORMAT_COMPRESSED))
277 hr = DXFILEERR_BADFILETYPE;
278 goto error;
281 if (header[2] == XOFFILE_FORMAT_COMPRESSED)
283 FIXME("Compressed formats not supported yet\n");
284 hr = DXFILEERR_BADVALUE;
285 goto error;
288 if ((header[3] != XOFFILE_FORMAT_FLOAT_BITS_32) && (header[3] != XOFFILE_FORMAT_FLOAT_BITS_64))
290 hr = DXFILEERR_BADFILEFLOATSIZE;
291 goto error;
294 TRACE("Header is correct\n");
296 hr = IDirectXFileEnumObjectImpl_Create(&object);
297 if (FAILED(hr))
298 goto error;
300 object->source = dwLoadOptions;
301 object->hFile = hFile;
302 object->pDirectXFile = This;
303 object->buf.pdxf = This;
304 object->buf.txt = (header[2] == XOFFILE_FORMAT_TEXT);
305 object->buf.token_present = FALSE;
306 object->buf.cur_subobject = 0;
308 if (dwLoadOptions == DXFILELOAD_FROMFILE)
310 object->buf.buffer = HeapAlloc(GetProcessHeap(), 0, MAX_INPUT_SIZE+1);
311 if (!object->buf.buffer)
313 WARN("Out of memory\n");
314 hr = DXFILEERR_BADALLOC;
315 goto error;
318 ReadFile(hFile, object->buf.buffer, MAX_INPUT_SIZE+1, &object->buf.rem_bytes, NULL);
319 if (object->buf.rem_bytes > MAX_INPUT_SIZE)
321 FIXME("File size > %d not supported yet\n", MAX_INPUT_SIZE);
322 HeapFree(GetProcessHeap(), 0, object->buf.buffer);
323 hr = DXFILEERR_PARSEERROR;
324 goto error;
327 else
329 object->buf.buffer = ((LPBYTE)lpdxflm->lpMemory) + 16;
330 object->buf.rem_bytes = lpdxflm->dSize;
333 TRACE("Read %d bytes\n", object->buf.rem_bytes);
335 *ppEnumObj = (LPDIRECTXFILEENUMOBJECT)object;
337 while (object->buf.rem_bytes && (check_TOKEN(&object->buf) == TOKEN_TEMPLATE))
339 if (!parse_template(&object->buf))
341 TRACE("Template is not correct\n");
342 hr = DXFILEERR_BADVALUE;
343 goto error;
345 else
347 TRACE("Template successfully parsed:\n");
348 if (TRACE_ON(d3dxof))
349 dump_template(This->xtemplates, &This->xtemplates[This->nb_xtemplates - 1]);
353 if (TRACE_ON(d3dxof))
355 int i;
356 TRACE("Registered templates (%d):\n", This->nb_xtemplates);
357 for (i = 0; i < This->nb_xtemplates; i++)
358 DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
361 return DXFILE_OK;
363 error:
364 if (hFile != INVALID_HANDLE_VALUE)
365 CloseHandle(hFile);
366 *ppEnumObj = NULL;
368 return hr;
371 static HRESULT WINAPI IDirectXFileImpl_CreateSaveObject(IDirectXFile* iface, LPCSTR szFileName, DXFILEFORMAT dwFileFormat, LPDIRECTXFILESAVEOBJECT* ppSaveObj)
373 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
375 FIXME("(%p/%p)->(%s,%x,%p) stub!\n", This, iface, szFileName, dwFileFormat, ppSaveObj);
377 return DXFILEERR_BADVALUE;
380 static BOOL read_bytes(parse_buffer * buf, LPVOID data, DWORD size)
382 if (buf->rem_bytes < size)
383 return FALSE;
384 memcpy(data, buf->buffer, size);
385 buf->buffer += size;
386 buf->rem_bytes -= size;
387 return TRUE;
390 static void dump_TOKEN(WORD token)
392 #define DUMP_TOKEN(t) case t: TRACE(#t "\n"); break
393 switch(token)
395 DUMP_TOKEN(TOKEN_NAME);
396 DUMP_TOKEN(TOKEN_STRING);
397 DUMP_TOKEN(TOKEN_INTEGER);
398 DUMP_TOKEN(TOKEN_GUID);
399 DUMP_TOKEN(TOKEN_INTEGER_LIST);
400 DUMP_TOKEN(TOKEN_FLOAT_LIST);
401 DUMP_TOKEN(TOKEN_OBRACE);
402 DUMP_TOKEN(TOKEN_CBRACE);
403 DUMP_TOKEN(TOKEN_OPAREN);
404 DUMP_TOKEN(TOKEN_CPAREN);
405 DUMP_TOKEN(TOKEN_OBRACKET);
406 DUMP_TOKEN(TOKEN_CBRACKET);
407 DUMP_TOKEN(TOKEN_OANGLE);
408 DUMP_TOKEN(TOKEN_CANGLE);
409 DUMP_TOKEN(TOKEN_DOT);
410 DUMP_TOKEN(TOKEN_COMMA);
411 DUMP_TOKEN(TOKEN_SEMICOLON);
412 DUMP_TOKEN(TOKEN_TEMPLATE);
413 DUMP_TOKEN(TOKEN_WORD);
414 DUMP_TOKEN(TOKEN_DWORD);
415 DUMP_TOKEN(TOKEN_FLOAT);
416 DUMP_TOKEN(TOKEN_DOUBLE);
417 DUMP_TOKEN(TOKEN_CHAR);
418 DUMP_TOKEN(TOKEN_UCHAR);
419 DUMP_TOKEN(TOKEN_SWORD);
420 DUMP_TOKEN(TOKEN_SDWORD);
421 DUMP_TOKEN(TOKEN_VOID);
422 DUMP_TOKEN(TOKEN_LPSTR);
423 DUMP_TOKEN(TOKEN_UNICODE);
424 DUMP_TOKEN(TOKEN_CSTRING);
425 DUMP_TOKEN(TOKEN_ARRAY);
426 default:
427 if (0)
428 TRACE("Unknown token %d\n", token);
429 break;
431 #undef DUMP_TOKEN
434 static BOOL is_space(char c)
436 switch (c)
438 case 0x00:
439 case 0x0D:
440 case 0x0A:
441 case ' ':
442 case '\t':
443 return TRUE;
445 return FALSE;
448 static BOOL is_operator(char c)
450 switch(c)
452 case '{':
453 case '}':
454 case '[':
455 case ']':
456 case '(':
457 case ')':
458 case '<':
459 case '>':
460 case ',':
461 case ';':
462 return TRUE;
464 return FALSE;
467 static inline BOOL is_separator(char c)
469 return is_space(c) || is_operator(c);
472 static WORD get_operator_token(char c)
474 switch(c)
476 case '{':
477 return TOKEN_OBRACE;
478 case '}':
479 return TOKEN_CBRACE;
480 case '[':
481 return TOKEN_OBRACKET;
482 case ']':
483 return TOKEN_CBRACKET;
484 case '(':
485 return TOKEN_OPAREN;
486 case ')':
487 return TOKEN_CPAREN;
488 case '<':
489 return TOKEN_OANGLE;
490 case '>':
491 return TOKEN_CANGLE;
492 case ',':
493 return TOKEN_COMMA;
494 case ';':
495 return TOKEN_SEMICOLON;
497 return 0;
500 static BOOL is_keyword(parse_buffer* buf, const char* keyword)
502 DWORD len = strlen(keyword);
503 if (!strncasecmp((char*)buf->buffer, keyword,len) && is_separator(*(buf->buffer+len)))
505 buf->buffer += len;
506 buf->rem_bytes -= len;
507 return TRUE;
509 return FALSE;
512 static WORD get_keyword_token(parse_buffer* buf)
514 if (is_keyword(buf, "template"))
515 return TOKEN_TEMPLATE;
516 if (is_keyword(buf, "WORD"))
517 return TOKEN_WORD;
518 if (is_keyword(buf, "DWORD"))
519 return TOKEN_DWORD;
520 if (is_keyword(buf, "FLOAT"))
521 return TOKEN_FLOAT;
522 if (is_keyword(buf, "DOUBLE"))
523 return TOKEN_DOUBLE;
524 if (is_keyword(buf, "CHAR"))
525 return TOKEN_CHAR;
526 if (is_keyword(buf, "UCHAR"))
527 return TOKEN_UCHAR;
528 if (is_keyword(buf, "SWORD"))
529 return TOKEN_SWORD;
530 if (is_keyword(buf, "SDWORD"))
531 return TOKEN_SDWORD;
532 if (is_keyword(buf, "VOID"))
533 return TOKEN_VOID;
534 if (is_keyword(buf, "STRING"))
535 return TOKEN_LPSTR;
536 if (is_keyword(buf, "UNICODE"))
537 return TOKEN_UNICODE;
538 if (is_keyword(buf, "CSTRING"))
539 return TOKEN_CSTRING;
540 if (is_keyword(buf, "array"))
541 return TOKEN_ARRAY;
543 return 0;
546 static BOOL is_guid(parse_buffer* buf)
548 char tmp[50];
549 DWORD pos = 1;
550 GUID class_id;
551 DWORD tab[10];
552 int ret;
554 if (*buf->buffer != '<')
555 return FALSE;
556 tmp[0] = '<';
557 while (*(buf->buffer+pos) != '>')
559 tmp[pos] = *(buf->buffer+pos);
560 pos++;
562 tmp[pos++] = '>';
563 tmp[pos] = 0;
564 if (pos != 38 /* <+36+> */)
566 TRACE("Wrong guid %s (%d)\n", tmp, pos);
567 return FALSE;
569 buf->buffer += pos;
570 buf->rem_bytes -= pos;
572 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);
573 if (ret != 11)
575 TRACE("Wrong guid %s (%d)\n", tmp, pos);
576 return FALSE;
578 TRACE("Found guid %s (%d)\n", tmp, pos);
580 class_id.Data2 = tab[0];
581 class_id.Data3 = tab[1];
582 class_id.Data4[0] = tab[2];
583 class_id.Data4[1] = tab[3];
584 class_id.Data4[2] = tab[4];
585 class_id.Data4[3] = tab[5];
586 class_id.Data4[4] = tab[6];
587 class_id.Data4[5] = tab[7];
588 class_id.Data4[6] = tab[8];
589 class_id.Data4[7] = tab[9];
591 *(GUID*)buf->value = class_id;
593 return TRUE;
596 static BOOL is_name(parse_buffer* buf)
598 char tmp[50];
599 DWORD pos = 0;
600 char c;
601 BOOL error = 0;
602 while (!is_separator(c = *(buf->buffer+pos)))
604 if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')) || (c == '_') || (c == '-')))
605 error = 1;
606 tmp[pos++] = c;
608 tmp[pos] = 0;
610 if (error)
612 TRACE("Wrong name %s\n", tmp);
613 return FALSE;
616 buf->buffer += pos;
617 buf->rem_bytes -= pos;
619 TRACE("Found name %s\n", tmp);
620 strcpy((char*)buf->value, tmp);
622 return TRUE;
625 static BOOL is_float(parse_buffer* buf)
627 char tmp[50];
628 DWORD pos = 0;
629 char c;
630 float decimal;
631 BOOL dot = 0;
633 while (!is_separator(c = *(buf->buffer+pos)))
635 if (!((!pos && (c == '-')) || ((c >= '0') && (c <= '9')) || (!dot && (c == '.'))))
636 return FALSE;
637 if (c == '.')
638 dot = TRUE;
639 tmp[pos++] = c;
641 tmp[pos] = 0;
643 buf->buffer += pos;
644 buf->rem_bytes -= pos;
646 sscanf(tmp, "%f", &decimal);
648 TRACE("Found float %s - %f\n", tmp, decimal);
650 *(float*)buf->value = decimal;
652 return TRUE;
655 static BOOL is_integer(parse_buffer* buf)
657 char tmp[50];
658 DWORD pos = 0;
659 char c;
660 DWORD integer;
662 while (!is_separator(c = *(buf->buffer+pos)))
664 if (!((c >= '0') && (c <= '9')))
665 return FALSE;
666 tmp[pos++] = c;
668 tmp[pos] = 0;
670 buf->buffer += pos;
671 buf->rem_bytes -= pos;
673 sscanf(tmp, "%d", &integer);
675 TRACE("Found integer %s - %d\n", tmp, integer);
677 *(DWORD*)buf->value = integer;
679 return TRUE;
682 static BOOL is_string(parse_buffer* buf)
684 char tmp[32];
685 DWORD pos = 0;
686 char c;
687 BOOL ok = 0;
689 if (*buf->buffer != '"')
690 return FALSE;
692 while (!is_separator(c = *(buf->buffer+pos+1)) && (pos < 31))
694 if (c == '"')
696 ok = 1;
697 break;
699 tmp[pos++] = c;
701 tmp[pos] = 0;
703 if (!ok)
705 TRACE("Wrong string %s\n", tmp);
706 return FALSE;
709 buf->buffer += pos + 2;
710 buf->rem_bytes -= pos + 2;
712 TRACE("Found string %s\n", tmp);
713 strcpy((char*)buf->value, tmp);
715 return TRUE;
718 static WORD parse_TOKEN(parse_buffer * buf)
720 WORD token;
722 if (buf->txt)
724 while(1)
726 char c;
727 if (!read_bytes(buf, &c, 1))
728 return 0;
729 /*TRACE("char = '%c'\n", is_space(c) ? ' ' : c);*/
730 if ((c == '#') || (c == '/'))
732 /* Handle comment (# or //) */
733 if (c == '/')
735 if (!read_bytes(buf, &c, 1))
736 return 0;
737 if (c != '/')
738 return 0;
740 c = 0;
741 while (c != 0x0A)
743 if (!read_bytes(buf, &c, 1))
744 return 0;
746 continue;
748 if (is_space(c))
749 continue;
750 if (is_operator(c) && (c != '<'))
752 token = get_operator_token(c);
753 break;
755 else if (c == '.')
757 token = TOKEN_DOT;
758 break;
760 else
762 buf->buffer -= 1;
763 buf->rem_bytes += 1;
765 if ((token = get_keyword_token(buf)))
766 break;
768 if (is_guid(buf))
770 token = TOKEN_GUID;
771 break;
773 if (is_integer(buf))
775 token = TOKEN_INTEGER;
776 break;
778 if (is_float(buf))
780 token = TOKEN_FLOAT;
781 break;
783 if (is_string(buf))
785 token = TOKEN_LPSTR;
786 break;
788 if (is_name(buf))
790 token = TOKEN_NAME;
791 break;
794 FIXME("Unrecognize element\n");
795 return 0;
799 else
801 static int nb_elem;
802 static int is_float;
804 if (!nb_elem)
806 if (!read_bytes(buf, &token, 2))
807 return 0;
809 /* Convert integer and float list into separate elements */
810 if (token == TOKEN_INTEGER_LIST)
812 if (!read_bytes(buf, &nb_elem, 4))
813 return 0;
814 token = TOKEN_INTEGER;
815 is_float = FALSE;
816 TRACE("Integer list (TOKEN_INTEGER_LIST) of size %d\n", nb_elem);
818 else if (token == TOKEN_FLOAT_LIST)
820 if (!read_bytes(buf, &nb_elem, 4))
821 return 0;
822 token = TOKEN_FLOAT;
823 is_float = TRUE;
824 TRACE("Float list (TOKEN_FLOAT_LIST) of size %d\n", nb_elem);
828 if (nb_elem)
830 token = is_float ? TOKEN_FLOAT : TOKEN_INTEGER;
831 nb_elem--;
833 DWORD integer;
835 if (!read_bytes(buf, &integer, 4))
836 return 0;
838 *(DWORD*)buf->value = integer;
840 dump_TOKEN(token);
841 return token;
844 switch (token)
846 case TOKEN_NAME:
848 DWORD count;
849 char strname[100];
851 if (!read_bytes(buf, &count, 4))
852 return 0;
853 if (!read_bytes(buf, strname, count))
854 return 0;
855 strname[count] = 0;
856 /*TRACE("name = %s\n", strname);*/
858 strcpy((char*)buf->value, strname);
860 break;
861 case TOKEN_INTEGER:
863 DWORD integer;
865 if (!read_bytes(buf, &integer, 4))
866 return 0;
867 /*TRACE("integer = %ld\n", integer);*/
869 *(DWORD*)buf->value = integer;
871 break;
872 case TOKEN_GUID:
874 char strguid[39];
875 GUID class_id;
877 if (!read_bytes(buf, &class_id, 16))
878 return 0;
879 sprintf(strguid, CLSIDFMT, class_id.Data1, class_id.Data2, class_id.Data3, class_id.Data4[0],
880 class_id.Data4[1], class_id.Data4[2], class_id.Data4[3], class_id.Data4[4], class_id.Data4[5],
881 class_id.Data4[6], class_id.Data4[7]);
882 /*TRACE("guid = {%s}\n", strguid);*/
884 *(GUID*)buf->value = class_id;
886 break;
887 case TOKEN_STRING:
889 DWORD count;
890 WORD tmp_token;
891 char strname[100];
892 if (!read_bytes(buf, &count, 4))
893 return 0;
894 if (!read_bytes(buf, strname, count))
895 return 0;
896 strname[count] = 0;
897 if (!read_bytes(buf, &tmp_token, 2))
898 return 0;
899 if ((tmp_token != TOKEN_COMMA) && (tmp_token != TOKEN_SEMICOLON))
900 ERR("No comma or semicolon (got %d)\n", tmp_token);
901 /*TRACE("name = %s\n", strname);*/
903 strcpy((char*)buf->value, strname);
904 token = TOKEN_LPSTR;
906 break;
907 case TOKEN_OBRACE:
908 case TOKEN_CBRACE:
909 case TOKEN_OPAREN:
910 case TOKEN_CPAREN:
911 case TOKEN_OBRACKET:
912 case TOKEN_CBRACKET:
913 case TOKEN_OANGLE:
914 case TOKEN_CANGLE:
915 case TOKEN_DOT:
916 case TOKEN_COMMA:
917 case TOKEN_SEMICOLON:
918 case TOKEN_TEMPLATE:
919 case TOKEN_WORD:
920 case TOKEN_DWORD:
921 case TOKEN_FLOAT:
922 case TOKEN_DOUBLE:
923 case TOKEN_CHAR:
924 case TOKEN_UCHAR:
925 case TOKEN_SWORD:
926 case TOKEN_SDWORD:
927 case TOKEN_VOID:
928 case TOKEN_LPSTR:
929 case TOKEN_UNICODE:
930 case TOKEN_CSTRING:
931 case TOKEN_ARRAY:
932 break;
933 default:
934 return 0;
938 dump_TOKEN(token);
940 return token;
943 static const char* get_primitive_string(WORD token)
945 switch(token)
947 case TOKEN_WORD:
948 return "WORD";
949 case TOKEN_DWORD:
950 return "DWORD";
951 case TOKEN_FLOAT:
952 return "FLOAT";
953 case TOKEN_DOUBLE:
954 return "DOUBLE";
955 case TOKEN_CHAR:
956 return "CHAR";
957 case TOKEN_UCHAR:
958 return "UCHAR";
959 case TOKEN_SWORD:
960 return "SWORD";
961 case TOKEN_SDWORD:
962 return "SDWORD";
963 case TOKEN_VOID:
964 return "VOID";
965 case TOKEN_LPSTR:
966 return "STRING";
967 case TOKEN_UNICODE:
968 return "UNICODE";
969 case TOKEN_CSTRING:
970 return "CSTRING ";
971 default:
972 break;
974 return NULL;
977 static WORD get_TOKEN(parse_buffer * buf)
979 if (buf->token_present)
981 buf->token_present = FALSE;
982 return buf->current_token;
985 buf->current_token = parse_TOKEN(buf);
987 return buf->current_token;
990 static WORD check_TOKEN(parse_buffer * buf)
992 if (buf->token_present)
993 return buf->current_token;
995 buf->current_token = parse_TOKEN(buf);
996 buf->token_present = TRUE;
998 return buf->current_token;
1001 static inline BOOL is_primitive_type(WORD token)
1003 BOOL ret;
1004 switch(token)
1006 case TOKEN_WORD:
1007 case TOKEN_DWORD:
1008 case TOKEN_FLOAT:
1009 case TOKEN_DOUBLE:
1010 case TOKEN_CHAR:
1011 case TOKEN_UCHAR:
1012 case TOKEN_SWORD:
1013 case TOKEN_SDWORD:
1014 case TOKEN_LPSTR:
1015 case TOKEN_UNICODE:
1016 case TOKEN_CSTRING:
1017 ret = 1;
1018 break;
1019 default:
1020 ret = 0;
1021 break;
1023 return ret;
1026 static BOOL parse_template_option_info(parse_buffer * buf)
1028 xtemplate* cur_template = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates];
1030 if (check_TOKEN(buf) == TOKEN_DOT)
1032 get_TOKEN(buf);
1033 if (get_TOKEN(buf) != TOKEN_DOT)
1034 return FALSE;
1035 if (get_TOKEN(buf) != TOKEN_DOT)
1036 return FALSE;
1037 cur_template->open = TRUE;
1039 else
1041 while (1)
1043 if (get_TOKEN(buf) != TOKEN_NAME)
1044 return FALSE;
1045 strcpy(cur_template->childs[cur_template->nb_childs], (char*)buf->value);
1046 if (check_TOKEN(buf) == TOKEN_GUID)
1047 get_TOKEN(buf);
1048 cur_template->nb_childs++;
1049 if (check_TOKEN(buf) != TOKEN_COMMA)
1050 break;
1051 get_TOKEN(buf);
1053 cur_template->open = FALSE;
1056 return TRUE;
1059 static BOOL parse_template_members_list(parse_buffer * buf)
1061 int idx_member = 0;
1062 member* cur_member;
1064 while (1)
1066 BOOL array = 0;
1067 int nb_dims = 0;
1068 cur_member = &buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[idx_member];
1070 if (check_TOKEN(buf) == TOKEN_ARRAY)
1072 get_TOKEN(buf);
1073 array = 1;
1076 if (check_TOKEN(buf) == TOKEN_NAME)
1078 cur_member->type = get_TOKEN(buf);
1079 cur_member->idx_template = 0;
1080 while (cur_member->idx_template < buf->pdxf->nb_xtemplates)
1082 if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[cur_member->idx_template].name))
1083 break;
1084 cur_member->idx_template++;
1086 if (cur_member->idx_template == buf->pdxf->nb_xtemplates)
1088 TRACE("Reference to a nonexistent template '%s'\n", (char*)buf->value);
1089 return FALSE;
1092 else if (is_primitive_type(check_TOKEN(buf)))
1093 cur_member->type = get_TOKEN(buf);
1094 else
1095 break;
1097 if (get_TOKEN(buf) != TOKEN_NAME)
1098 return FALSE;
1099 strcpy(cur_member->name, (char*)buf->value);
1101 if (array)
1103 while (check_TOKEN(buf) == TOKEN_OBRACKET)
1105 if (nb_dims >= MAX_ARRAY_DIM)
1107 FIXME("Too many dimensions (%d) for multi-dimensional array\n", nb_dims + 1);
1108 return FALSE;
1110 get_TOKEN(buf);
1111 if (check_TOKEN(buf) == TOKEN_INTEGER)
1113 get_TOKEN(buf);
1114 cur_member->dim_fixed[nb_dims] = TRUE;
1115 cur_member->dim_value[nb_dims] = *(DWORD*)buf->value;
1117 else
1119 int i;
1120 if (get_TOKEN(buf) != TOKEN_NAME)
1121 return FALSE;
1122 for (i = 0; i < idx_member; i++)
1124 if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[i].name))
1126 if (buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[i].nb_dims)
1128 ERR("Array cannot be used to specify variable array size\n");
1129 return FALSE;
1131 if (buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].members[i].type != TOKEN_DWORD)
1133 FIXME("Only DWORD supported to specify variable array size\n");
1134 return FALSE;
1136 break;
1139 if (i == idx_member)
1141 ERR("Reference to unknown member %s\n", (char*)buf->value);
1142 return FALSE;
1144 cur_member->dim_fixed[nb_dims] = FALSE;
1145 cur_member->dim_value[nb_dims] = i;
1147 if (get_TOKEN(buf) != TOKEN_CBRACKET)
1148 return FALSE;
1149 nb_dims++;
1151 if (!nb_dims)
1152 return FALSE;
1153 cur_member->nb_dims = nb_dims;
1155 if (get_TOKEN(buf) != TOKEN_SEMICOLON)
1156 return FALSE;
1158 idx_member++;
1161 buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].nb_members = idx_member;
1163 return TRUE;
1166 static BOOL parse_template_parts(parse_buffer * buf)
1168 if (!parse_template_members_list(buf))
1169 return FALSE;
1170 if (check_TOKEN(buf) == TOKEN_OBRACKET)
1172 get_TOKEN(buf);
1173 if (!parse_template_option_info(buf))
1174 return FALSE;
1175 if (get_TOKEN(buf) != TOKEN_CBRACKET)
1176 return FALSE;
1179 return TRUE;
1182 static void go_to_next_definition(parse_buffer * buf)
1184 while (buf->rem_bytes)
1186 char c = *buf->buffer;
1187 if ((c == '#') || (c == '/'))
1189 read_bytes(buf, &c, 1);
1190 /* Handle comment (# or //) */
1191 if (c == '/')
1193 if (!read_bytes(buf, &c, 1))
1194 return;
1195 if (c != '/')
1196 return;
1198 c = 0;
1199 while (c != 0x0A)
1201 if (!read_bytes(buf, &c, 1))
1202 return;
1204 continue;
1206 else if (is_space(*buf->buffer))
1208 buf->buffer++;
1209 buf->rem_bytes--;
1211 else
1212 break;
1216 static BOOL parse_template(parse_buffer * buf)
1218 if (get_TOKEN(buf) != TOKEN_TEMPLATE)
1219 return FALSE;
1220 if (get_TOKEN(buf) != TOKEN_NAME)
1221 return FALSE;
1222 strcpy(buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].name, (char*)buf->value);
1223 if (get_TOKEN(buf) != TOKEN_OBRACE)
1224 return FALSE;
1225 if (get_TOKEN(buf) != TOKEN_GUID)
1226 return FALSE;
1227 buf->pdxf->xtemplates[buf->pdxf->nb_xtemplates].class_id = *(GUID*)buf->value;
1228 if (!parse_template_parts(buf))
1229 return FALSE;
1230 if (get_TOKEN(buf) != TOKEN_CBRACE)
1231 return FALSE;
1232 if (buf->txt)
1234 /* Go to the next template */
1235 go_to_next_definition(buf);
1238 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));
1239 buf->pdxf->nb_xtemplates++;
1241 return TRUE;
1244 static HRESULT WINAPI IDirectXFileImpl_RegisterTemplates(IDirectXFile* iface, LPVOID pvData, DWORD cbSize)
1246 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
1247 DWORD token_header;
1248 parse_buffer buf;
1250 buf.buffer = (LPBYTE)pvData;
1251 buf.rem_bytes = cbSize;
1252 buf.txt = FALSE;
1253 buf.token_present = FALSE;
1254 buf.pdxf = This;
1256 TRACE("(%p/%p)->(%p,%d)\n", This, iface, pvData, cbSize);
1258 if (!pvData)
1259 return DXFILEERR_BADVALUE;
1261 if (cbSize < 16)
1262 return DXFILEERR_BADFILETYPE;
1264 if (TRACE_ON(d3dxof))
1266 char string[17];
1267 memcpy(string, pvData, 16);
1268 string[16] = 0;
1269 TRACE("header = '%s'\n", string);
1272 read_bytes(&buf, &token_header, 4);
1274 if (token_header != XOFFILE_FORMAT_MAGIC)
1275 return DXFILEERR_BADFILETYPE;
1277 read_bytes(&buf, &token_header, 4);
1279 if ((token_header != XOFFILE_FORMAT_VERSION_302) && (token_header != XOFFILE_FORMAT_VERSION_303))
1280 return DXFILEERR_BADFILEVERSION;
1282 read_bytes(&buf, &token_header, 4);
1284 if ((token_header != XOFFILE_FORMAT_BINARY) && (token_header != XOFFILE_FORMAT_TEXT) && (token_header != XOFFILE_FORMAT_COMPRESSED))
1285 return DXFILEERR_BADFILETYPE;
1287 if (token_header == XOFFILE_FORMAT_TEXT)
1289 buf.txt = TRUE;
1292 if (token_header == XOFFILE_FORMAT_COMPRESSED)
1294 FIXME("Compressed formats not supported yet\n");
1295 return DXFILEERR_BADVALUE;
1298 read_bytes(&buf, &token_header, 4);
1300 if ((token_header != XOFFILE_FORMAT_FLOAT_BITS_32) && (token_header != XOFFILE_FORMAT_FLOAT_BITS_64))
1301 return DXFILEERR_BADFILEFLOATSIZE;
1303 TRACE("Header is correct\n");
1305 while (buf.rem_bytes)
1307 if (!parse_template(&buf))
1309 TRACE("Template is not correct\n");
1310 return DXFILEERR_BADVALUE;
1312 else
1314 TRACE("Template successfully parsed:\n");
1315 if (TRACE_ON(d3dxof))
1316 dump_template(This->xtemplates, &This->xtemplates[This->nb_xtemplates - 1]);
1320 if (TRACE_ON(d3dxof))
1322 int i;
1323 TRACE("Registered templates (%d):\n", This->nb_xtemplates);
1324 for (i = 0; i < This->nb_xtemplates; i++)
1325 DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
1328 return DXFILE_OK;
1331 static const IDirectXFileVtbl IDirectXFile_Vtbl =
1333 IDirectXFileImpl_QueryInterface,
1334 IDirectXFileImpl_AddRef,
1335 IDirectXFileImpl_Release,
1336 IDirectXFileImpl_CreateEnumObject,
1337 IDirectXFileImpl_CreateSaveObject,
1338 IDirectXFileImpl_RegisterTemplates
1341 /*** IUnknown methods ***/
1342 static HRESULT WINAPI IDirectXFileBinaryImpl_QueryInterface(IDirectXFileBinary* iface, REFIID riid, void** ppvObject)
1344 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1346 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1348 if (IsEqualGUID(riid, &IID_IUnknown)
1349 || IsEqualGUID(riid, &IID_IDirectXFileObject)
1350 || IsEqualGUID(riid, &IID_IDirectXFileBinary))
1352 IClassFactory_AddRef(iface);
1353 *ppvObject = This;
1354 return S_OK;
1357 /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
1358 if (!IsEqualGUID(riid, &IID_IDirectXFileData)
1359 && !IsEqualGUID(riid, &IID_IDirectXFileDataReference))
1360 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1362 return E_NOINTERFACE;
1365 static ULONG WINAPI IDirectXFileBinaryImpl_AddRef(IDirectXFileBinary* iface)
1367 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1368 ULONG ref = InterlockedIncrement(&This->ref);
1370 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1372 return ref;
1375 static ULONG WINAPI IDirectXFileBinaryImpl_Release(IDirectXFileBinary* iface)
1377 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1378 ULONG ref = InterlockedDecrement(&This->ref);
1380 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1382 if (!ref)
1383 HeapFree(GetProcessHeap(), 0, This);
1385 return ref;
1388 /*** IDirectXFileObject methods ***/
1389 static HRESULT WINAPI IDirectXFileBinaryImpl_GetName(IDirectXFileBinary* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1392 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1394 FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen);
1396 return DXFILEERR_BADVALUE;
1399 static HRESULT WINAPI IDirectXFileBinaryImpl_GetId(IDirectXFileBinary* iface, LPGUID pGuid)
1401 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1403 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid);
1405 return DXFILEERR_BADVALUE;
1408 /*** IDirectXFileBinary methods ***/
1409 static HRESULT WINAPI IDirectXFileBinaryImpl_GetSize(IDirectXFileBinary* iface, DWORD* pcbSize)
1411 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1413 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pcbSize);
1415 return DXFILEERR_BADVALUE;
1418 static HRESULT WINAPI IDirectXFileBinaryImpl_GetMimeType(IDirectXFileBinary* iface, LPCSTR* pszMimeType)
1420 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1422 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pszMimeType);
1424 return DXFILEERR_BADVALUE;
1427 static HRESULT WINAPI IDirectXFileBinaryImpl_Read(IDirectXFileBinary* iface, LPVOID pvData, DWORD cbSize, LPDWORD pcbRead)
1429 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
1431 FIXME("(%p/%p)->(%p, %d, %p) stub!\n", This, iface, pvData, cbSize, pcbRead);
1433 return DXFILEERR_BADVALUE;
1436 static const IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl =
1438 IDirectXFileBinaryImpl_QueryInterface,
1439 IDirectXFileBinaryImpl_AddRef,
1440 IDirectXFileBinaryImpl_Release,
1441 IDirectXFileBinaryImpl_GetName,
1442 IDirectXFileBinaryImpl_GetId,
1443 IDirectXFileBinaryImpl_GetSize,
1444 IDirectXFileBinaryImpl_GetMimeType,
1445 IDirectXFileBinaryImpl_Read
1448 static HRESULT IDirectXFileDataImpl_Create(IDirectXFileDataImpl** ppObj)
1450 IDirectXFileDataImpl* object;
1452 TRACE("(%p)\n", ppObj);
1454 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataImpl));
1456 object->lpVtbl.lpVtbl = &IDirectXFileData_Vtbl;
1457 object->ref = 1;
1459 *ppObj = object;
1461 return S_OK;
1464 /*** IUnknown methods ***/
1465 static HRESULT WINAPI IDirectXFileDataImpl_QueryInterface(IDirectXFileData* iface, REFIID riid, void** ppvObject)
1467 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1469 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1471 if (IsEqualGUID(riid, &IID_IUnknown)
1472 || IsEqualGUID(riid, &IID_IDirectXFileObject)
1473 || IsEqualGUID(riid, &IID_IDirectXFileData))
1475 IClassFactory_AddRef(iface);
1476 *ppvObject = This;
1477 return S_OK;
1480 /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
1481 if (!IsEqualGUID(riid, &IID_IDirectXFileBinary)
1482 && !IsEqualGUID(riid, &IID_IDirectXFileDataReference))
1483 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1485 return E_NOINTERFACE;
1488 static ULONG WINAPI IDirectXFileDataImpl_AddRef(IDirectXFileData* iface)
1490 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1491 ULONG ref = InterlockedIncrement(&This->ref);
1493 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1495 return ref;
1498 static ULONG WINAPI IDirectXFileDataImpl_Release(IDirectXFileData* iface)
1500 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1501 ULONG ref = InterlockedDecrement(&This->ref);
1503 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1505 if (!ref)
1506 HeapFree(GetProcessHeap(), 0, This);
1508 return ref;
1511 /*** IDirectXFileObject methods ***/
1512 static HRESULT WINAPI IDirectXFileDataImpl_GetName(IDirectXFileData* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1515 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1517 TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
1519 if (!pstrNameBuf)
1520 return DXFILEERR_BADVALUE;
1522 strcpy(pstrNameBuf, This->pobj->name);
1524 return DXFILE_OK;
1527 static HRESULT WINAPI IDirectXFileDataImpl_GetId(IDirectXFileData* iface, LPGUID pGuid)
1529 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1531 TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
1533 if (!pGuid)
1534 return DXFILEERR_BADVALUE;
1536 memcpy(pGuid, &This->pobj->class_id, 16);
1538 return DXFILE_OK;
1541 /*** IDirectXFileData methods ***/
1542 static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCSTR szMember, DWORD* pcbSize, void** ppvData)
1544 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1546 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, szMember, pcbSize, ppvData);
1548 if (!pcbSize || !ppvData)
1549 return DXFILEERR_BADVALUE;
1551 if (szMember)
1553 FIXME("Specifying a member is not supported yet!\n");
1554 return DXFILEERR_BADVALUE;
1557 *pcbSize = This->pobj->size;
1558 *ppvData = This->pobj->pdata;
1560 return DXFILE_OK;
1563 static HRESULT WINAPI IDirectXFileDataImpl_GetType(IDirectXFileData* iface, const GUID** pguid)
1565 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1566 static GUID guid;
1568 TRACE("(%p/%p)->(%p)\n", This, iface, pguid);
1570 if (!pguid)
1571 return DXFILEERR_BADVALUE;
1573 memcpy(&guid, &This->pobj->type, 16);
1574 *pguid = &guid;
1576 return DXFILE_OK;
1579 static HRESULT WINAPI IDirectXFileDataImpl_GetNextObject(IDirectXFileData* iface, LPDIRECTXFILEOBJECT* ppChildObj)
1581 HRESULT hr;
1582 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1584 TRACE("(%p/%p)->(%p)\n", This, iface, ppChildObj);
1586 if (This->cur_enum_object >= This->pobj->nb_childs)
1587 return DXFILEERR_NOMOREOBJECTS;
1589 if (This->from_ref && (This->level >= 1))
1591 /* Only 2 levels can enumerated if the object is obtained from a reference */
1592 return DXFILEERR_NOMOREOBJECTS;
1595 if (This->pobj->childs[This->cur_enum_object]->ptarget)
1597 IDirectXFileDataReferenceImpl *object;
1599 hr = IDirectXFileDataReferenceImpl_Create(&object);
1600 if (hr != S_OK)
1601 return DXFILEERR_BADVALUE;
1603 object->ptarget = This->pobj->childs[This->cur_enum_object++]->ptarget;
1605 *ppChildObj = (LPDIRECTXFILEOBJECT)object;
1607 else
1609 IDirectXFileDataImpl *object;
1611 hr = IDirectXFileDataImpl_Create(&object);
1612 if (hr != S_OK)
1613 return DXFILEERR_BADVALUE;
1615 object->pobj = This->pobj->childs[This->cur_enum_object++];
1616 object->cur_enum_object = 0;
1617 object->from_ref = This->from_ref;
1618 object->level = This->level + 1;
1620 *ppChildObj = (LPDIRECTXFILEOBJECT)object;
1623 return DXFILE_OK;
1626 static HRESULT WINAPI IDirectXFileDataImpl_AddDataObject(IDirectXFileData* iface, LPDIRECTXFILEDATA pDataObj)
1628 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1630 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pDataObj);
1632 return DXFILEERR_BADVALUE;
1635 static HRESULT WINAPI IDirectXFileDataImpl_AddDataReference(IDirectXFileData* iface, LPCSTR szRef, const GUID* pguidRef)
1637 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1639 FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szRef, pguidRef);
1641 return DXFILEERR_BADVALUE;
1644 static HRESULT WINAPI IDirectXFileDataImpl_AddBinaryObject(IDirectXFileData* iface, LPCSTR szName, const GUID* pguid, LPCSTR szMimeType, LPVOID pvData, DWORD cbSize)
1646 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
1648 FIXME("(%p/%p)->(%s,%p,%s,%p,%d) stub!\n", This, iface, szName, pguid, szMimeType, pvData, cbSize);
1650 return DXFILEERR_BADVALUE;
1653 static const IDirectXFileDataVtbl IDirectXFileData_Vtbl =
1655 IDirectXFileDataImpl_QueryInterface,
1656 IDirectXFileDataImpl_AddRef,
1657 IDirectXFileDataImpl_Release,
1658 IDirectXFileDataImpl_GetName,
1659 IDirectXFileDataImpl_GetId,
1660 IDirectXFileDataImpl_GetData,
1661 IDirectXFileDataImpl_GetType,
1662 IDirectXFileDataImpl_GetNextObject,
1663 IDirectXFileDataImpl_AddDataObject,
1664 IDirectXFileDataImpl_AddDataReference,
1665 IDirectXFileDataImpl_AddBinaryObject
1668 static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj)
1670 IDirectXFileDataReferenceImpl* object;
1672 TRACE("(%p)\n", ppObj);
1674 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataReferenceImpl));
1676 object->lpVtbl.lpVtbl = &IDirectXFileDataReference_Vtbl;
1677 object->ref = 1;
1679 *ppObj = object;
1681 return S_OK;
1684 /*** IUnknown methods ***/
1685 static HRESULT WINAPI IDirectXFileDataReferenceImpl_QueryInterface(IDirectXFileDataReference* iface, REFIID riid, void** ppvObject)
1687 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1689 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1691 if (IsEqualGUID(riid, &IID_IUnknown)
1692 || IsEqualGUID(riid, &IID_IDirectXFileObject)
1693 || IsEqualGUID(riid, &IID_IDirectXFileDataReference))
1695 IClassFactory_AddRef(iface);
1696 *ppvObject = This;
1697 return S_OK;
1700 /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
1701 if (!IsEqualGUID(riid, &IID_IDirectXFileData)
1702 && !IsEqualGUID(riid, &IID_IDirectXFileBinary))
1703 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1705 return E_NOINTERFACE;
1708 static ULONG WINAPI IDirectXFileDataReferenceImpl_AddRef(IDirectXFileDataReference* iface)
1710 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1711 ULONG ref = InterlockedIncrement(&This->ref);
1713 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1715 return ref;
1718 static ULONG WINAPI IDirectXFileDataReferenceImpl_Release(IDirectXFileDataReference* iface)
1720 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1721 ULONG ref = InterlockedDecrement(&This->ref);
1723 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1725 if (!ref)
1726 HeapFree(GetProcessHeap(), 0, This);
1728 return ref;
1731 /*** IDirectXFileObject methods ***/
1732 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetName(IDirectXFileDataReference* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
1734 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1736 TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
1738 if (!pstrNameBuf)
1739 return DXFILEERR_BADVALUE;
1741 strcpy(pstrNameBuf, This->ptarget->name);
1743 return DXFILEERR_BADVALUE;
1746 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetId(IDirectXFileDataReference* iface, LPGUID pGuid)
1748 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1750 TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
1752 if (!pGuid)
1753 return DXFILEERR_BADVALUE;
1755 memcpy(pGuid, &This->ptarget->class_id, 16);
1757 return DXFILE_OK;
1760 /*** IDirectXFileDataReference ***/
1761 static HRESULT WINAPI IDirectXFileDataReferenceImpl_Resolve(IDirectXFileDataReference* iface, LPDIRECTXFILEDATA* ppDataObj)
1763 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
1764 IDirectXFileDataImpl *object;
1765 HRESULT hr;
1767 TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
1769 if (!ppDataObj)
1770 return DXFILEERR_BADVALUE;
1772 hr = IDirectXFileDataImpl_Create(&object);
1773 if (hr != S_OK)
1774 return DXFILEERR_BADVALUE;
1776 object->pobj = This->ptarget;
1777 object->cur_enum_object = 0;
1778 object->level = 0;
1779 object->from_ref = TRUE;
1781 *ppDataObj = (LPDIRECTXFILEDATA)object;
1783 return DXFILE_OK;
1786 static const IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl =
1788 IDirectXFileDataReferenceImpl_QueryInterface,
1789 IDirectXFileDataReferenceImpl_AddRef,
1790 IDirectXFileDataReferenceImpl_Release,
1791 IDirectXFileDataReferenceImpl_GetName,
1792 IDirectXFileDataReferenceImpl_GetId,
1793 IDirectXFileDataReferenceImpl_Resolve
1796 static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj)
1798 IDirectXFileEnumObjectImpl* object;
1800 TRACE("(%p)\n", ppObj);
1802 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileEnumObjectImpl));
1804 object->lpVtbl.lpVtbl = &IDirectXFileEnumObject_Vtbl;
1805 object->ref = 1;
1807 *ppObj = object;
1809 return S_OK;
1812 /*** IUnknown methods ***/
1813 static HRESULT WINAPI IDirectXFileEnumObjectImpl_QueryInterface(IDirectXFileEnumObject* iface, REFIID riid, void** ppvObject)
1815 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1817 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1819 if (IsEqualGUID(riid, &IID_IUnknown)
1820 || IsEqualGUID(riid, &IID_IDirectXFileEnumObject))
1822 IClassFactory_AddRef(iface);
1823 *ppvObject = This;
1824 return S_OK;
1827 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1828 return E_NOINTERFACE;
1831 static ULONG WINAPI IDirectXFileEnumObjectImpl_AddRef(IDirectXFileEnumObject* iface)
1833 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1834 ULONG ref = InterlockedIncrement(&This->ref);
1836 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1838 return ref;
1841 static ULONG WINAPI IDirectXFileEnumObjectImpl_Release(IDirectXFileEnumObject* iface)
1843 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1844 ULONG ref = InterlockedDecrement(&This->ref);
1846 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1848 if (!ref)
1850 CloseHandle(This->hFile);
1851 HeapFree(GetProcessHeap(), 0, This);
1854 return ref;
1857 static BOOL parse_object_members_list(parse_buffer * buf)
1859 DWORD token;
1860 int i;
1861 xtemplate* pt = buf->pxt[buf->level];
1862 DWORD last_dword = 0;
1864 for (i = 0; i < pt->nb_members; i++)
1866 int k;
1867 int nb_elems = 1;
1869 buf->pxo->members[i].start = buf->cur_pdata;
1871 for (k = 0; k < pt->members[i].nb_dims; k++)
1873 if (pt->members[i].dim_fixed[k])
1874 nb_elems *= pt->members[i].dim_value[k];
1875 else
1876 nb_elems *= *(DWORD*)buf->pxo->members[pt->members[i].dim_value[k]].start;
1879 TRACE("Elements to consider: %d\n", nb_elems);
1881 for (k = 0; k < nb_elems; k++)
1883 if (buf->txt && k)
1885 token = check_TOKEN(buf);
1886 if (token == TOKEN_COMMA)
1888 get_TOKEN(buf);
1890 else
1892 /* Allow comma omission */
1893 if (!((token == TOKEN_FLOAT) || (token == TOKEN_INTEGER)))
1894 return FALSE;
1898 if (pt->members[i].type == TOKEN_NAME)
1900 int j;
1902 TRACE("Found sub-object %s\n", buf->pdxf->xtemplates[pt->members[i].idx_template].name);
1903 buf->level++;
1904 /* To do template lookup */
1905 for (j = 0; j < buf->pdxf->nb_xtemplates; j++)
1907 if (!strcmp(buf->pdxf->xtemplates[pt->members[i].idx_template].name, buf->pdxf->xtemplates[j].name))
1909 buf->pxt[buf->level] = &buf->pdxf->xtemplates[j];
1910 break;
1913 if (j == buf->pdxf->nb_xtemplates)
1915 FIXME("Unknown template %s\n", (char*)buf->value);
1916 buf->level--;
1917 return FALSE;
1919 TRACE("Enter %s\n", buf->pdxf->xtemplates[pt->members[i].idx_template].name);
1920 if (!parse_object_parts(buf, FALSE))
1922 buf->level--;
1923 return FALSE;
1925 buf->level--;
1927 else
1929 token = check_TOKEN(buf);
1930 if (token == TOKEN_INTEGER)
1932 get_TOKEN(buf);
1933 last_dword = *(DWORD*)buf->value;
1934 TRACE("%s = %d\n", pt->members[i].name, *(DWORD*)buf->value);
1935 /* Assume larger size */
1936 if ((buf->cur_pdata - buf->pdata + 4) > MAX_DATA_SIZE)
1938 FIXME("Buffer too small\n");
1939 return FALSE;
1941 if (pt->members[i].type == TOKEN_WORD)
1943 *(((WORD*)(buf->cur_pdata))) = (WORD)(*(DWORD*)buf->value);
1944 buf->cur_pdata += 2;
1946 else if (pt->members[i].type == TOKEN_DWORD)
1948 *(((DWORD*)(buf->cur_pdata))) = (DWORD)(*(DWORD*)buf->value);
1949 buf->cur_pdata += 4;
1951 else
1953 FIXME("Token %d not supported\n", pt->members[i].type);
1954 return FALSE;
1957 else if (token == TOKEN_FLOAT)
1959 get_TOKEN(buf);
1960 TRACE("%s = %f\n", pt->members[i].name, *(float*)buf->value);
1961 /* Assume larger size */
1962 if ((buf->cur_pdata - buf->pdata + 4) > MAX_DATA_SIZE)
1964 FIXME("Buffer too small\n");
1965 return FALSE;
1967 if (pt->members[i].type == TOKEN_FLOAT)
1969 *(((float*)(buf->cur_pdata))) = (float)(*(float*)buf->value);
1970 buf->cur_pdata += 4;
1972 else
1974 FIXME("Token %d not supported\n", pt->members[i].type);
1975 return FALSE;
1978 else if (token == TOKEN_LPSTR)
1980 get_TOKEN(buf);
1981 TRACE("%s = %s\n", pt->members[i].name, (char*)buf->value);
1982 /* Assume larger size */
1983 if ((buf->cur_pdata - buf->pdata + 4) > MAX_DATA_SIZE)
1985 FIXME("Buffer too small\n");
1986 return FALSE;
1988 if (pt->members[i].type == TOKEN_LPSTR)
1990 int len = strlen((char*)buf->value) + 1;
1991 if ((buf->cur_pstrings - buf->pstrings + len) > MAX_STRINGS_BUFFER)
1993 FIXME("Buffer too small %p %p %d\n", buf->cur_pstrings, buf->pstrings, len);
1994 return FALSE;
1996 strcpy((char*)buf->cur_pstrings, (char*)buf->value);
1997 *(((LPCSTR*)(buf->cur_pdata))) = (char*)buf->cur_pstrings;
1998 buf->cur_pstrings += len;
1999 buf->cur_pdata += 4;
2001 else
2003 FIXME("Token %d not supported\n", pt->members[i].type);
2004 return FALSE;
2007 else
2009 FIXME("Unexpected token %d\n", token);
2010 return FALSE;
2015 if (buf->txt && (check_TOKEN(buf) != TOKEN_CBRACE))
2017 token = get_TOKEN(buf);
2018 if ((token != TOKEN_SEMICOLON) && (token != TOKEN_COMMA))
2020 /* Allow comma instead of semicolon in some specific cases */
2021 if (!((token == TOKEN_COMMA) && ((i+1) < pt->nb_members) && (pt->members[i].type == pt->members[i+1].type)
2022 && (!pt->members[i].nb_dims) && (!pt->members[i+1].nb_dims)))
2023 return FALSE;
2028 return TRUE;
2031 static BOOL parse_object_parts(parse_buffer * buf, BOOL allow_optional)
2033 if (!parse_object_members_list(buf))
2034 return FALSE;
2036 if (allow_optional)
2038 buf->pxo->size = buf->cur_pdata - buf->pxo->pdata;
2040 /* Skip trailing semicolon */
2041 while (check_TOKEN(buf) == TOKEN_SEMICOLON)
2042 get_TOKEN(buf);
2044 while (1)
2046 if (check_TOKEN(buf) == TOKEN_OBRACE)
2048 int i, j;
2049 get_TOKEN(buf);
2050 if (get_TOKEN(buf) != TOKEN_NAME)
2051 return FALSE;
2052 if (get_TOKEN(buf) != TOKEN_CBRACE)
2053 return FALSE;
2054 TRACE("Found optional reference %s\n", (char*)buf->value);
2055 for (i = 0; i < buf->nb_pxo_globals; i++)
2057 for (j = 0; j < buf->pxo_globals[i*MAX_SUBOBJECTS].nb_subobjects; j++)
2059 if (!strcmp(buf->pxo_globals[i*MAX_SUBOBJECTS+j].name, (char*)buf->value))
2060 goto _exit;
2063 _exit:
2064 if (i == buf->nb_pxo_globals)
2066 ERR("Reference to unknown object %s\n", (char*)buf->value);
2067 return FALSE;
2069 buf->pxo->childs[buf->pxo->nb_childs] = &buf->pxo_tab[buf->cur_subobject++];
2070 buf->pxo->childs[buf->pxo->nb_childs]->ptarget = &buf->pxo_globals[i*MAX_SUBOBJECTS+j];
2071 buf->pxo->nb_childs++;
2073 else if (check_TOKEN(buf) == TOKEN_NAME)
2075 xobject* pxo = buf->pxo;
2076 buf->pxo = buf->pxo->childs[buf->pxo->nb_childs] = &buf->pxo_tab[buf->cur_subobject++];
2078 TRACE("Enter optional %s\n", (char*)buf->value);
2079 buf->level++;
2080 if (!parse_object(buf))
2082 buf->level--;
2083 return FALSE;
2085 buf->level--;
2086 buf->pxo = pxo;
2087 buf->pxo->nb_childs++;
2089 else
2090 break;
2094 if (buf->pxo->nb_childs > MAX_CHILDS)
2096 FIXME("Too many childs %d\n", buf->pxo->nb_childs);
2097 return FALSE;
2100 return TRUE;
2103 static BOOL parse_object(parse_buffer * buf)
2105 int i;
2107 buf->pxo->pdata = buf->cur_pdata;
2108 buf->pxo->ptarget = NULL;
2110 if (get_TOKEN(buf) != TOKEN_NAME)
2111 return FALSE;
2113 /* To do template lookup */
2114 for (i = 0; i < buf->pdxf->nb_xtemplates; i++)
2116 if (!strcmp((char*)buf->value, buf->pdxf->xtemplates[i].name))
2118 buf->pxt[buf->level] = &buf->pdxf->xtemplates[i];
2119 memcpy(&buf->pxo->type, &buf->pdxf->xtemplates[i].class_id, 16);
2120 break;
2123 if (i == buf->pdxf->nb_xtemplates)
2125 FIXME("Unknown template %s\n", (char*)buf->value);
2126 return FALSE;
2129 if (check_TOKEN(buf) == TOKEN_NAME)
2131 get_TOKEN(buf);
2132 strcpy(buf->pxo->name, (char*)buf->value);
2134 else
2135 buf->pxo->name[0] = 0;
2137 if (get_TOKEN(buf) != TOKEN_OBRACE)
2138 return FALSE;
2139 if (check_TOKEN(buf) == TOKEN_GUID)
2141 get_TOKEN(buf);
2142 memcpy(&buf->pxo->class_id, buf->value, 16);
2144 else
2145 memset(&buf->pxo->class_id, 0, 16);
2147 if (!parse_object_parts(buf, TRUE))
2148 return FALSE;
2149 if (get_TOKEN(buf) != TOKEN_CBRACE)
2150 return FALSE;
2152 if (buf->txt)
2154 /* Go to the next object */
2155 go_to_next_definition(buf);
2158 return TRUE;
2161 /*** IDirectXFileEnumObject methods ***/
2162 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetNextDataObject(IDirectXFileEnumObject* iface, LPDIRECTXFILEDATA* ppDataObj)
2164 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
2165 IDirectXFileDataImpl* object;
2166 HRESULT hr;
2167 LPBYTE pdata;
2168 LPBYTE pstrings;
2170 TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
2172 if (This->nb_xobjects >= MAX_OBJECTS)
2174 ERR("Too many objects\n");
2175 return DXFILEERR_NOMOREOBJECTS;
2178 if (!This->buf.rem_bytes)
2179 return DXFILEERR_NOMOREOBJECTS;
2181 hr = IDirectXFileDataImpl_Create(&object);
2182 if (FAILED(hr))
2183 return hr;
2185 This->buf.pxo_globals = &This->xobjects[0][0];
2186 This->buf.nb_pxo_globals = This->nb_xobjects;
2187 This->buf.pxo_tab = &This->xobjects[This->nb_xobjects][0];
2188 This->buf.cur_subobject = 0;
2189 This->buf.pxo = &This->buf.pxo_tab[This->buf.cur_subobject++];
2190 This->buf.level = 0;
2192 pdata = HeapAlloc(GetProcessHeap(), 0, MAX_DATA_SIZE);
2193 if (!pdata)
2195 WARN("Out of memory\n");
2196 return DXFILEERR_BADALLOC;
2198 This->buf.cur_pdata = This->buf.pdata = pdata;
2200 pstrings = HeapAlloc(GetProcessHeap(), 0, MAX_STRINGS_BUFFER);
2201 if (!pstrings)
2203 WARN("Out of memory\n");
2204 HeapFree(GetProcessHeap(), 0, This->buf.pxo->pdata);
2205 return DXFILEERR_BADALLOC;
2207 This->buf.cur_pstrings = This->buf.pstrings = pstrings;
2209 if (!parse_object(&This->buf))
2211 TRACE("Object is not correct\n");
2212 HeapFree(GetProcessHeap(), 0, This->buf.pxo->pdata);
2213 HeapFree(GetProcessHeap(), 0, This->buf.pstrings);
2214 return DXFILEERR_PARSEERROR;
2217 This->buf.pxo->nb_subobjects = This->buf.cur_subobject;
2218 if (This->buf.cur_subobject > MAX_SUBOBJECTS)
2220 FIXME("Too many suobjects %d\n", This->buf.cur_subobject);
2221 return DXFILEERR_BADALLOC;
2224 object->pstrings = pstrings;
2225 object->pobj = This->buf.pxo;
2226 object->cur_enum_object = 0;
2227 object->level = 0;
2228 object->from_ref = FALSE;
2230 *ppDataObj = (LPDIRECTXFILEDATA)object;
2232 This->nb_xobjects++;
2234 return DXFILE_OK;
2237 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectById(IDirectXFileEnumObject* iface, REFGUID rguid, LPDIRECTXFILEDATA* ppDataObj)
2239 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
2241 FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, rguid, ppDataObj);
2243 return DXFILEERR_BADVALUE;
2246 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectByName(IDirectXFileEnumObject* iface, LPCSTR szName, LPDIRECTXFILEDATA* ppDataObj)
2248 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
2250 FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szName, ppDataObj);
2252 return DXFILEERR_BADVALUE;
2255 static const IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl =
2257 IDirectXFileEnumObjectImpl_QueryInterface,
2258 IDirectXFileEnumObjectImpl_AddRef,
2259 IDirectXFileEnumObjectImpl_Release,
2260 IDirectXFileEnumObjectImpl_GetNextDataObject,
2261 IDirectXFileEnumObjectImpl_GetDataObjectById,
2262 IDirectXFileEnumObjectImpl_GetDataObjectByName
2265 /*** IUnknown methods ***/
2266 static HRESULT WINAPI IDirectXFileObjectImpl_QueryInterface(IDirectXFileObject* iface, REFIID riid, void** ppvObject)
2268 IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
2270 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
2272 if (IsEqualGUID(riid, &IID_IUnknown)
2273 || IsEqualGUID(riid, &IID_IDirectXFileObject))
2275 IClassFactory_AddRef(iface);
2276 *ppvObject = This;
2277 return S_OK;
2280 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
2281 return E_NOINTERFACE;
2284 static ULONG WINAPI IDirectXFileObjectImpl_AddRef(IDirectXFileObject* iface)
2286 IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
2287 ULONG ref = InterlockedIncrement(&This->ref);
2289 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
2291 return ref;
2294 static ULONG WINAPI IDirectXFileObjectImpl_Release(IDirectXFileObject* iface)
2296 IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
2297 ULONG ref = InterlockedDecrement(&This->ref);
2299 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
2301 if (!ref)
2302 HeapFree(GetProcessHeap(), 0, This);
2304 return ref;
2307 /*** IDirectXFileObject methods ***/
2308 static HRESULT WINAPI IDirectXFileObjectImpl_GetName(IDirectXFileObject* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
2310 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
2312 FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen);
2314 return DXFILEERR_BADVALUE;
2317 static HRESULT WINAPI IDirectXFileObjectImpl_GetId(IDirectXFileObject* iface, LPGUID pGuid)
2319 IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface;
2321 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid);
2323 return DXFILEERR_BADVALUE;
2326 static const IDirectXFileObjectVtbl IDirectXFileObject_Vtbl =
2328 IDirectXFileObjectImpl_QueryInterface,
2329 IDirectXFileObjectImpl_AddRef,
2330 IDirectXFileObjectImpl_Release,
2331 IDirectXFileObjectImpl_GetName,
2332 IDirectXFileObjectImpl_GetId
2335 /*** IUnknown methods ***/
2336 static HRESULT WINAPI IDirectXFileSaveObjectImpl_QueryInterface(IDirectXFileSaveObject* iface, REFIID riid, void** ppvObject)
2338 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2340 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
2342 if (IsEqualGUID(riid, &IID_IUnknown)
2343 || IsEqualGUID(riid, &IID_IDirectXFileSaveObject))
2345 IClassFactory_AddRef(iface);
2346 *ppvObject = This;
2347 return S_OK;
2350 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
2351 return E_NOINTERFACE;
2354 static ULONG WINAPI IDirectXFileSaveObjectImpl_AddRef(IDirectXFileSaveObject* iface)
2356 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2357 ULONG ref = InterlockedIncrement(&This->ref);
2359 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
2361 return ref;
2364 static ULONG WINAPI IDirectXFileSaveObjectImpl_Release(IDirectXFileSaveObject* iface)
2366 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2367 ULONG ref = InterlockedDecrement(&This->ref);
2369 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
2371 if (!ref)
2372 HeapFree(GetProcessHeap(), 0, This);
2374 return ref;
2377 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveTemplates(IDirectXFileSaveObject* iface, DWORD cTemplates, const GUID** ppguidTemplates)
2379 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2381 FIXME("(%p/%p)->(%d,%p) stub!\n", This, iface, cTemplates, ppguidTemplates);
2383 return DXFILEERR_BADVALUE;
2386 static HRESULT WINAPI IDirectXFileSaveObjectImpl_CreateDataObject(IDirectXFileSaveObject* iface, REFGUID rguidTemplate, LPCSTR szName, const GUID* pguid, DWORD cbSize, LPVOID pvData, LPDIRECTXFILEDATA* ppDataObj)
2388 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2390 FIXME("(%p/%p)->(%p,%s,%p,%d,%p,%p) stub!\n", This, iface, rguidTemplate, szName, pguid, cbSize, pvData, ppDataObj);
2392 return DXFILEERR_BADVALUE;
2395 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveData(IDirectXFileSaveObject* iface, LPDIRECTXFILEDATA ppDataObj)
2397 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
2399 FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj);
2401 return DXFILEERR_BADVALUE;
2404 static const IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl =
2406 IDirectXFileSaveObjectImpl_QueryInterface,
2407 IDirectXFileSaveObjectImpl_AddRef,
2408 IDirectXFileSaveObjectImpl_Release,
2409 IDirectXFileSaveObjectImpl_SaveTemplates,
2410 IDirectXFileSaveObjectImpl_CreateDataObject,
2411 IDirectXFileSaveObjectImpl_SaveData