d3dxof: Use proper macro for AddRef.
[wine/multimedia.git] / dlls / d3dxof / d3dxof.c
blob88a9e522770e52f02e2c458c88fbc2bd55828396
1 /*
2 * Implementation of DirectX File Interfaces
4 * Copyright 2004, 2008 Christian Costa
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.
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.
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
21 #include "config.h"
22 #include "wine/debug.h"
24 #define COBJMACROS
26 #include "winbase.h"
27 #include "wingdi.h"
29 #include "d3dxof_private.h"
30 #include "dxfile.h"
32 #include <stdio.h>
34 WINE_DEFAULT_DEBUG_CHANNEL(d3dxof);
36 #define MAKEFOUR(a,b,c,d) ((DWORD)a + ((DWORD)b << 8) + ((DWORD)c << 16) + ((DWORD)d << 24))
37 #define XOFFILE_FORMAT_MAGIC MAKEFOUR('x','o','f',' ')
38 #define XOFFILE_FORMAT_VERSION_302 MAKEFOUR('0','3','0','2')
39 #define XOFFILE_FORMAT_VERSION_303 MAKEFOUR('0','3','0','3')
40 #define XOFFILE_FORMAT_BINARY MAKEFOUR('b','i','n',' ')
41 #define XOFFILE_FORMAT_TEXT MAKEFOUR('t','x','t',' ')
42 #define XOFFILE_FORMAT_BINARY_MSZIP MAKEFOUR('b','z','i','p')
43 #define XOFFILE_FORMAT_TEXT_MSZIP MAKEFOUR('t','z','i','p')
44 #define XOFFILE_FORMAT_COMPRESSED MAKEFOUR('c','m','p',' ')
45 #define XOFFILE_FORMAT_FLOAT_BITS_32 MAKEFOUR('0','0','3','2')
46 #define XOFFILE_FORMAT_FLOAT_BITS_64 MAKEFOUR('0','0','6','4')
48 static const struct IDirectXFileVtbl IDirectXFile_Vtbl;
49 static const struct IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl;
50 static const struct IDirectXFileDataVtbl IDirectXFileData_Vtbl;
51 static const struct IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl;
52 static const struct IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl;
53 static const struct IDirectXFileObjectVtbl IDirectXFileObject_Vtbl;
54 static const struct IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl;
56 static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj);
57 static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj);
58 static HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj);
60 /* FOURCC to string conversion for debug messages */
61 const char *debugstr_fourcc(DWORD fourcc)
63 if (!fourcc) return "'null'";
64 return wine_dbg_sprintf ("\'%c%c%c%c\'",
65 (char)(fourcc), (char)(fourcc >> 8),
66 (char)(fourcc >> 16), (char)(fourcc >> 24));
69 HRESULT IDirectXFileImpl_Create(IUnknown* pUnkOuter, LPVOID* ppObj)
71 IDirectXFileImpl* object;
73 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
75 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileImpl));
76 if (!object)
78 ERR("Out of memory\n");
79 return DXFILEERR_BADALLOC;
82 object->lpVtbl = &IDirectXFile_Vtbl;
83 object->ref = 1;
85 *ppObj = object;
87 return S_OK;
90 /*** IUnknown methods ***/
91 static HRESULT WINAPI IDirectXFileImpl_QueryInterface(IDirectXFile* iface, REFIID riid, void** ppvObject)
93 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
95 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
97 if (IsEqualGUID(riid, &IID_IUnknown)
98 || IsEqualGUID(riid, &IID_IDirectXFile))
100 IUnknown_AddRef(iface);
101 *ppvObject = This;
102 return S_OK;
105 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
106 return E_NOINTERFACE;
109 static ULONG WINAPI IDirectXFileImpl_AddRef(IDirectXFile* iface)
111 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
112 ULONG ref = InterlockedIncrement(&This->ref);
114 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
116 return ref;
119 static ULONG WINAPI IDirectXFileImpl_Release(IDirectXFile* iface)
121 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
122 ULONG ref = InterlockedDecrement(&This->ref);
124 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
126 if (!ref)
127 HeapFree(GetProcessHeap(), 0, This);
129 return ref;
132 /*** IDirectXFile methods ***/
133 static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPVOID pvSource, DXFILELOADOPTIONS dwLoadOptions, LPDIRECTXFILEENUMOBJECT* ppEnumObj)
135 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
136 IDirectXFileEnumObjectImpl* object;
137 HRESULT hr;
138 DWORD* header;
139 HANDLE hFile = INVALID_HANDLE_VALUE;
140 HANDLE file_mapping = 0;
141 LPBYTE buffer = NULL;
142 HGLOBAL resource_data = 0;
143 LPBYTE file_buffer;
144 DWORD file_size;
146 LPDXFILELOADMEMORY lpdxflm = NULL;
148 TRACE("(%p/%p)->(%p,%x,%p)\n", This, iface, pvSource, dwLoadOptions, ppEnumObj);
150 if (!ppEnumObj)
151 return DXFILEERR_BADVALUE;
153 /* Only lowest 4 bits are relevant in DXFILELOADOPTIONS */
154 dwLoadOptions &= 0xF;
156 if (dwLoadOptions == DXFILELOAD_FROMFILE)
158 TRACE("Open source file '%s'\n", (char*)pvSource);
160 hFile = CreateFileA(pvSource, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
161 if (hFile == INVALID_HANDLE_VALUE)
163 TRACE("File '%s' not found\n", (char*)pvSource);
164 return DXFILEERR_FILENOTFOUND;
167 file_size = GetFileSize(hFile, NULL);
169 file_mapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
170 if (!file_mapping)
172 hr = DXFILEERR_BADFILETYPE;
173 goto error;
176 buffer = MapViewOfFile(file_mapping, FILE_MAP_READ, 0, 0, 0);
177 if (!buffer)
179 hr = DXFILEERR_BADFILETYPE;
180 goto error;
182 file_buffer = buffer;
184 else if (dwLoadOptions == DXFILELOAD_FROMRESOURCE)
186 HRSRC resource_info;
187 LPDXFILELOADRESOURCE lpdxflr = pvSource;
189 TRACE("Source in resource (module = %p, name = %s, type = %s\n", lpdxflr->hModule, debugstr_a(lpdxflr->lpName), debugstr_a(lpdxflr->lpType));
191 resource_info = FindResourceA(lpdxflr->hModule, lpdxflr->lpName, lpdxflr->lpType);
192 if (!resource_info)
194 hr = DXFILEERR_RESOURCENOTFOUND;
195 goto error;
198 file_size = SizeofResource(lpdxflr->hModule, resource_info);
200 resource_data = LoadResource(lpdxflr->hModule, resource_info);
201 if (!resource_data)
203 hr = DXFILEERR_BADRESOURCE;
204 goto error;
207 file_buffer = LockResource(resource_data);
208 if (!file_buffer)
210 hr = DXFILEERR_BADRESOURCE;
211 goto error;
214 else if (dwLoadOptions == DXFILELOAD_FROMMEMORY)
216 lpdxflm = pvSource;
218 TRACE("Source in memory at %p with size %d\n", lpdxflm->lpMemory, lpdxflm->dSize);
220 file_buffer = lpdxflm->lpMemory;
221 file_size = lpdxflm->dSize;
223 else
225 FIXME("Source type %d is not handled yet\n", dwLoadOptions);
226 hr = DXFILEERR_NOTDONEYET;
227 goto error;
230 header = (DWORD*)file_buffer;
232 if (TRACE_ON(d3dxof))
234 char string[17];
235 memcpy(string, header, 16);
236 string[16] = 0;
237 TRACE("header = '%s'\n", string);
240 if (file_size < 16)
242 hr = DXFILEERR_BADFILETYPE;
243 goto error;
246 if (header[0] != XOFFILE_FORMAT_MAGIC)
248 hr = DXFILEERR_BADFILETYPE;
249 goto error;
252 if ((header[1] != XOFFILE_FORMAT_VERSION_302) && (header[1] != XOFFILE_FORMAT_VERSION_303))
254 hr = DXFILEERR_BADFILEVERSION;
255 goto error;
258 if ((header[2] != XOFFILE_FORMAT_BINARY) && (header[2] != XOFFILE_FORMAT_TEXT) &&
259 (header[2] != XOFFILE_FORMAT_BINARY_MSZIP) && (header[2] != XOFFILE_FORMAT_TEXT_MSZIP))
261 WARN("File type %s unknown\n", debugstr_fourcc(header[2]));
262 hr = DXFILEERR_BADFILETYPE;
263 goto error;
266 if ((header[2] == XOFFILE_FORMAT_BINARY_MSZIP) || (header[2] == XOFFILE_FORMAT_TEXT_MSZIP))
268 FIXME("Compressed format %s not supported yet\n", debugstr_fourcc(header[2]));
269 hr = DXFILEERR_BADALLOC;
270 goto error;
273 if ((header[3] != XOFFILE_FORMAT_FLOAT_BITS_32) && (header[3] != XOFFILE_FORMAT_FLOAT_BITS_64))
275 hr = DXFILEERR_BADFILEFLOATSIZE;
276 goto error;
279 TRACE("Header is correct\n");
281 hr = IDirectXFileEnumObjectImpl_Create(&object);
282 if (FAILED(hr))
283 goto error;
285 object->source = dwLoadOptions;
286 object->hFile = hFile;
287 object->file_mapping = file_mapping;
288 object->buffer = buffer;
289 object->pDirectXFile = This;
290 object->buf.pdxf = This;
291 object->buf.txt = (header[2] == XOFFILE_FORMAT_TEXT);
292 object->buf.token_present = FALSE;
294 TRACE("File size is %d bytes\n", file_size);
296 /* Go to data after header */
297 object->buf.buffer = file_buffer + 16;
298 object->buf.rem_bytes = file_size - 16;
300 *ppEnumObj = (LPDIRECTXFILEENUMOBJECT)object;
302 while (object->buf.rem_bytes && is_template_available(&object->buf))
304 if (!parse_template(&object->buf))
306 TRACE("Template is not correct\n");
307 hr = DXFILEERR_BADVALUE;
308 goto error;
310 else
312 TRACE("Template successfully parsed:\n");
313 if (TRACE_ON(d3dxof))
314 dump_template(This->xtemplates, &This->xtemplates[This->nb_xtemplates - 1]);
318 if (TRACE_ON(d3dxof))
320 int i;
321 TRACE("Registered templates (%d):\n", This->nb_xtemplates);
322 for (i = 0; i < This->nb_xtemplates; i++)
323 DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
326 return DXFILE_OK;
328 error:
329 if (buffer)
330 UnmapViewOfFile(buffer);
331 if (file_mapping)
332 CloseHandle(file_mapping);
333 if (hFile != INVALID_HANDLE_VALUE)
334 CloseHandle(hFile);
335 if (resource_data)
336 FreeResource(resource_data);
337 *ppEnumObj = NULL;
339 return hr;
342 static HRESULT WINAPI IDirectXFileImpl_CreateSaveObject(IDirectXFile* iface, LPCSTR szFileName, DXFILEFORMAT dwFileFormat, LPDIRECTXFILESAVEOBJECT* ppSaveObj)
344 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
346 FIXME("(%p/%p)->(%s,%x,%p) partial stub!\n", This, iface, szFileName, dwFileFormat, ppSaveObj);
348 if (!szFileName || !ppSaveObj)
349 return E_POINTER;
351 return IDirectXFileSaveObjectImpl_Create((IDirectXFileSaveObjectImpl**)ppSaveObj);
354 static HRESULT WINAPI IDirectXFileImpl_RegisterTemplates(IDirectXFile* iface, LPVOID pvData, DWORD cbSize)
356 IDirectXFileImpl *This = (IDirectXFileImpl *)iface;
357 DWORD token_header;
358 parse_buffer buf;
360 buf.buffer = pvData;
361 buf.rem_bytes = cbSize;
362 buf.txt = FALSE;
363 buf.token_present = FALSE;
364 buf.pdxf = This;
366 TRACE("(%p/%p)->(%p,%d)\n", This, iface, pvData, cbSize);
368 if (!pvData)
369 return DXFILEERR_BADVALUE;
371 if (cbSize < 16)
372 return DXFILEERR_BADFILETYPE;
374 if (TRACE_ON(d3dxof))
376 char string[17];
377 memcpy(string, pvData, 16);
378 string[16] = 0;
379 TRACE("header = '%s'\n", string);
382 read_bytes(&buf, &token_header, 4);
384 if (token_header != XOFFILE_FORMAT_MAGIC)
385 return DXFILEERR_BADFILETYPE;
387 read_bytes(&buf, &token_header, 4);
389 if ((token_header != XOFFILE_FORMAT_VERSION_302) && (token_header != XOFFILE_FORMAT_VERSION_303))
390 return DXFILEERR_BADFILEVERSION;
392 read_bytes(&buf, &token_header, 4);
394 if ((token_header != XOFFILE_FORMAT_BINARY) && (token_header != XOFFILE_FORMAT_TEXT) &&
395 (token_header != XOFFILE_FORMAT_BINARY_MSZIP) && (token_header != XOFFILE_FORMAT_TEXT_MSZIP))
397 WARN("File type %s unknown\n", debugstr_fourcc(token_header));
398 return DXFILEERR_BADFILETYPE;
401 if ((token_header == XOFFILE_FORMAT_BINARY_MSZIP) || (token_header == XOFFILE_FORMAT_TEXT_MSZIP))
403 FIXME("Compressed format %s not supported yet\n", debugstr_fourcc(token_header));
404 return DXFILEERR_BADALLOC;
407 if (token_header == XOFFILE_FORMAT_TEXT)
408 buf.txt = TRUE;
410 read_bytes(&buf, &token_header, 4);
412 if ((token_header != XOFFILE_FORMAT_FLOAT_BITS_32) && (token_header != XOFFILE_FORMAT_FLOAT_BITS_64))
413 return DXFILEERR_BADFILEFLOATSIZE;
415 TRACE("Header is correct\n");
417 while (buf.rem_bytes)
419 if (!parse_template(&buf))
421 TRACE("Template is not correct\n");
422 return DXFILEERR_BADVALUE;
424 else
426 TRACE("Template successfully parsed:\n");
427 if (TRACE_ON(d3dxof))
428 dump_template(This->xtemplates, &This->xtemplates[This->nb_xtemplates - 1]);
432 if (TRACE_ON(d3dxof))
434 int i;
435 TRACE("Registered templates (%d):\n", This->nb_xtemplates);
436 for (i = 0; i < This->nb_xtemplates; i++)
437 DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
440 return DXFILE_OK;
443 static const IDirectXFileVtbl IDirectXFile_Vtbl =
445 IDirectXFileImpl_QueryInterface,
446 IDirectXFileImpl_AddRef,
447 IDirectXFileImpl_Release,
448 IDirectXFileImpl_CreateEnumObject,
449 IDirectXFileImpl_CreateSaveObject,
450 IDirectXFileImpl_RegisterTemplates
453 static HRESULT IDirectXFileBinaryImpl_Create(IDirectXFileBinaryImpl** ppObj)
455 IDirectXFileBinaryImpl* object;
457 TRACE("(%p)\n", ppObj);
459 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileBinaryImpl));
460 if (!object)
462 ERR("Out of memory\n");
463 return DXFILEERR_BADALLOC;
466 object->lpVtbl = &IDirectXFileBinary_Vtbl;
467 object->ref = 1;
469 *ppObj = object;
471 return DXFILE_OK;
474 /*** IUnknown methods ***/
475 static HRESULT WINAPI IDirectXFileBinaryImpl_QueryInterface(IDirectXFileBinary* iface, REFIID riid, void** ppvObject)
477 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
479 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
481 if (IsEqualGUID(riid, &IID_IUnknown)
482 || IsEqualGUID(riid, &IID_IDirectXFileObject)
483 || IsEqualGUID(riid, &IID_IDirectXFileBinary))
485 IUnknown_AddRef(iface);
486 *ppvObject = This;
487 return S_OK;
490 /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
491 if (!IsEqualGUID(riid, &IID_IDirectXFileData)
492 && !IsEqualGUID(riid, &IID_IDirectXFileDataReference))
493 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
495 return E_NOINTERFACE;
498 static ULONG WINAPI IDirectXFileBinaryImpl_AddRef(IDirectXFileBinary* iface)
500 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
501 ULONG ref = InterlockedIncrement(&This->ref);
503 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
505 return ref;
508 static ULONG WINAPI IDirectXFileBinaryImpl_Release(IDirectXFileBinary* iface)
510 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
511 ULONG ref = InterlockedDecrement(&This->ref);
513 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
515 if (!ref)
516 HeapFree(GetProcessHeap(), 0, This);
518 return ref;
521 /*** IDirectXFileObject methods ***/
522 static HRESULT WINAPI IDirectXFileBinaryImpl_GetName(IDirectXFileBinary* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
525 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
527 FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen);
529 return DXFILEERR_BADVALUE;
532 static HRESULT WINAPI IDirectXFileBinaryImpl_GetId(IDirectXFileBinary* iface, LPGUID pGuid)
534 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
536 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid);
538 return DXFILEERR_BADVALUE;
541 /*** IDirectXFileBinary methods ***/
542 static HRESULT WINAPI IDirectXFileBinaryImpl_GetSize(IDirectXFileBinary* iface, DWORD* pcbSize)
544 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
546 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pcbSize);
548 return DXFILEERR_BADVALUE;
551 static HRESULT WINAPI IDirectXFileBinaryImpl_GetMimeType(IDirectXFileBinary* iface, LPCSTR* pszMimeType)
553 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
555 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pszMimeType);
557 return DXFILEERR_BADVALUE;
560 static HRESULT WINAPI IDirectXFileBinaryImpl_Read(IDirectXFileBinary* iface, LPVOID pvData, DWORD cbSize, LPDWORD pcbRead)
562 IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface;
564 FIXME("(%p/%p)->(%p, %d, %p) stub!\n", This, iface, pvData, cbSize, pcbRead);
566 return DXFILEERR_BADVALUE;
569 static const IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl =
571 IDirectXFileBinaryImpl_QueryInterface,
572 IDirectXFileBinaryImpl_AddRef,
573 IDirectXFileBinaryImpl_Release,
574 IDirectXFileBinaryImpl_GetName,
575 IDirectXFileBinaryImpl_GetId,
576 IDirectXFileBinaryImpl_GetSize,
577 IDirectXFileBinaryImpl_GetMimeType,
578 IDirectXFileBinaryImpl_Read
581 static HRESULT IDirectXFileDataImpl_Create(IDirectXFileDataImpl** ppObj)
583 IDirectXFileDataImpl* object;
585 TRACE("(%p)\n", ppObj);
587 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataImpl));
588 if (!object)
590 ERR("Out of memory\n");
591 return DXFILEERR_BADALLOC;
594 object->lpVtbl = &IDirectXFileData_Vtbl;
595 object->ref = 1;
597 *ppObj = object;
599 return S_OK;
602 /*** IUnknown methods ***/
603 static HRESULT WINAPI IDirectXFileDataImpl_QueryInterface(IDirectXFileData* iface, REFIID riid, void** ppvObject)
605 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
607 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
609 if (IsEqualGUID(riid, &IID_IUnknown)
610 || IsEqualGUID(riid, &IID_IDirectXFileObject)
611 || IsEqualGUID(riid, &IID_IDirectXFileData))
613 IUnknown_AddRef(iface);
614 *ppvObject = This;
615 return S_OK;
618 /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
619 if (!IsEqualGUID(riid, &IID_IDirectXFileBinary)
620 && !IsEqualGUID(riid, &IID_IDirectXFileDataReference))
621 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
623 return E_NOINTERFACE;
626 static ULONG WINAPI IDirectXFileDataImpl_AddRef(IDirectXFileData* iface)
628 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
629 ULONG ref = InterlockedIncrement(&This->ref);
631 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
633 return ref;
636 static ULONG WINAPI IDirectXFileDataImpl_Release(IDirectXFileData* iface)
638 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
639 ULONG ref = InterlockedDecrement(&This->ref);
641 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
643 if (!ref)
645 if (!This->level && !This->from_ref)
647 HeapFree(GetProcessHeap(), 0, This->pstrings);
648 HeapFree(GetProcessHeap(), 0, This->pobj->pdata);
649 HeapFree(GetProcessHeap(), 0, This->pobj);
651 HeapFree(GetProcessHeap(), 0, This);
654 return ref;
657 /*** IDirectXFileObject methods ***/
658 static HRESULT WINAPI IDirectXFileDataImpl_GetName(IDirectXFileData* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
661 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
663 TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
665 if (!pstrNameBuf)
666 return DXFILEERR_BADVALUE;
668 strcpy(pstrNameBuf, This->pobj->name);
670 return DXFILE_OK;
673 static HRESULT WINAPI IDirectXFileDataImpl_GetId(IDirectXFileData* iface, LPGUID pGuid)
675 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
677 TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
679 if (!pGuid)
680 return DXFILEERR_BADVALUE;
682 memcpy(pGuid, &This->pobj->class_id, 16);
684 return DXFILE_OK;
687 /*** IDirectXFileData methods ***/
688 static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCSTR szMember, DWORD* pcbSize, void** ppvData)
690 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
692 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, szMember, pcbSize, ppvData);
694 if (!pcbSize || !ppvData)
695 return DXFILEERR_BADVALUE;
697 if (szMember)
699 FIXME("Specifying a member is not supported yet!\n");
700 return DXFILEERR_BADVALUE;
703 *pcbSize = This->pobj->size;
704 *ppvData = This->pobj->root->pdata + This->pobj->pos_data;
706 return DXFILE_OK;
709 static HRESULT WINAPI IDirectXFileDataImpl_GetType(IDirectXFileData* iface, const GUID** pguid)
711 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
712 static GUID guid;
714 TRACE("(%p/%p)->(%p)\n", This, iface, pguid);
716 if (!pguid)
717 return DXFILEERR_BADVALUE;
719 memcpy(&guid, &This->pobj->type, 16);
720 *pguid = &guid;
722 return DXFILE_OK;
725 static HRESULT WINAPI IDirectXFileDataImpl_GetNextObject(IDirectXFileData* iface, LPDIRECTXFILEOBJECT* ppChildObj)
727 HRESULT hr;
728 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
730 TRACE("(%p/%p)->(%p)\n", This, iface, ppChildObj);
732 if (This->cur_enum_object >= This->pobj->nb_childs)
733 return DXFILEERR_NOMOREOBJECTS;
735 if (This->from_ref && (This->level >= 1))
737 /* Only 2 levels can be enumerated if the object is obtained from a reference */
738 return DXFILEERR_NOMOREOBJECTS;
741 if (This->pobj->childs[This->cur_enum_object]->binary)
743 IDirectXFileBinaryImpl *object;
745 hr = IDirectXFileBinaryImpl_Create(&object);
746 if (FAILED(hr))
747 return hr;
749 *ppChildObj = (LPDIRECTXFILEOBJECT)object;
751 else if (This->pobj->childs[This->cur_enum_object]->ptarget)
753 IDirectXFileDataReferenceImpl *object;
755 hr = IDirectXFileDataReferenceImpl_Create(&object);
756 if (FAILED(hr))
757 return hr;
759 object->ptarget = This->pobj->childs[This->cur_enum_object++]->ptarget;
761 *ppChildObj = (LPDIRECTXFILEOBJECT)object;
763 else
765 IDirectXFileDataImpl *object;
767 hr = IDirectXFileDataImpl_Create(&object);
768 if (FAILED(hr))
769 return hr;
771 object->pobj = This->pobj->childs[This->cur_enum_object++];
772 object->cur_enum_object = 0;
773 object->from_ref = This->from_ref;
774 object->level = This->level + 1;
776 *ppChildObj = (LPDIRECTXFILEOBJECT)object;
779 return DXFILE_OK;
782 static HRESULT WINAPI IDirectXFileDataImpl_AddDataObject(IDirectXFileData* iface, LPDIRECTXFILEDATA pDataObj)
784 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
786 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pDataObj);
788 return DXFILEERR_BADVALUE;
791 static HRESULT WINAPI IDirectXFileDataImpl_AddDataReference(IDirectXFileData* iface, LPCSTR szRef, const GUID* pguidRef)
793 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
795 FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szRef, pguidRef);
797 return DXFILEERR_BADVALUE;
800 static HRESULT WINAPI IDirectXFileDataImpl_AddBinaryObject(IDirectXFileData* iface, LPCSTR szName, const GUID* pguid, LPCSTR szMimeType, LPVOID pvData, DWORD cbSize)
802 IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface;
804 FIXME("(%p/%p)->(%s,%p,%s,%p,%d) stub!\n", This, iface, szName, pguid, szMimeType, pvData, cbSize);
806 return DXFILEERR_BADVALUE;
809 static const IDirectXFileDataVtbl IDirectXFileData_Vtbl =
811 IDirectXFileDataImpl_QueryInterface,
812 IDirectXFileDataImpl_AddRef,
813 IDirectXFileDataImpl_Release,
814 IDirectXFileDataImpl_GetName,
815 IDirectXFileDataImpl_GetId,
816 IDirectXFileDataImpl_GetData,
817 IDirectXFileDataImpl_GetType,
818 IDirectXFileDataImpl_GetNextObject,
819 IDirectXFileDataImpl_AddDataObject,
820 IDirectXFileDataImpl_AddDataReference,
821 IDirectXFileDataImpl_AddBinaryObject
824 static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj)
826 IDirectXFileDataReferenceImpl* object;
828 TRACE("(%p)\n", ppObj);
830 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataReferenceImpl));
831 if (!object)
833 ERR("Out of memory\n");
834 return DXFILEERR_BADALLOC;
837 object->lpVtbl = &IDirectXFileDataReference_Vtbl;
838 object->ref = 1;
840 *ppObj = object;
842 return S_OK;
845 /*** IUnknown methods ***/
846 static HRESULT WINAPI IDirectXFileDataReferenceImpl_QueryInterface(IDirectXFileDataReference* iface, REFIID riid, void** ppvObject)
848 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
850 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
852 if (IsEqualGUID(riid, &IID_IUnknown)
853 || IsEqualGUID(riid, &IID_IDirectXFileObject)
854 || IsEqualGUID(riid, &IID_IDirectXFileDataReference))
856 IUnknown_AddRef(iface);
857 *ppvObject = This;
858 return S_OK;
861 /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
862 if (!IsEqualGUID(riid, &IID_IDirectXFileData)
863 && !IsEqualGUID(riid, &IID_IDirectXFileBinary))
864 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
866 return E_NOINTERFACE;
869 static ULONG WINAPI IDirectXFileDataReferenceImpl_AddRef(IDirectXFileDataReference* iface)
871 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
872 ULONG ref = InterlockedIncrement(&This->ref);
874 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
876 return ref;
879 static ULONG WINAPI IDirectXFileDataReferenceImpl_Release(IDirectXFileDataReference* iface)
881 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
882 ULONG ref = InterlockedDecrement(&This->ref);
884 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
886 if (!ref)
887 HeapFree(GetProcessHeap(), 0, This);
889 return ref;
892 /*** IDirectXFileObject methods ***/
893 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetName(IDirectXFileDataReference* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
895 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
897 TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
899 if (!pstrNameBuf)
900 return DXFILEERR_BADVALUE;
902 strcpy(pstrNameBuf, This->ptarget->name);
904 return DXFILEERR_BADVALUE;
907 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetId(IDirectXFileDataReference* iface, LPGUID pGuid)
909 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
911 TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
913 if (!pGuid)
914 return DXFILEERR_BADVALUE;
916 memcpy(pGuid, &This->ptarget->class_id, 16);
918 return DXFILE_OK;
921 /*** IDirectXFileDataReference ***/
922 static HRESULT WINAPI IDirectXFileDataReferenceImpl_Resolve(IDirectXFileDataReference* iface, LPDIRECTXFILEDATA* ppDataObj)
924 IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface;
925 IDirectXFileDataImpl *object;
926 HRESULT hr;
928 TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
930 if (!ppDataObj)
931 return DXFILEERR_BADVALUE;
933 hr = IDirectXFileDataImpl_Create(&object);
934 if (FAILED(hr))
935 return hr;
937 object->pobj = This->ptarget;
938 object->cur_enum_object = 0;
939 object->level = 0;
940 object->from_ref = TRUE;
942 *ppDataObj = (LPDIRECTXFILEDATA)object;
944 return DXFILE_OK;
947 static const IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl =
949 IDirectXFileDataReferenceImpl_QueryInterface,
950 IDirectXFileDataReferenceImpl_AddRef,
951 IDirectXFileDataReferenceImpl_Release,
952 IDirectXFileDataReferenceImpl_GetName,
953 IDirectXFileDataReferenceImpl_GetId,
954 IDirectXFileDataReferenceImpl_Resolve
957 static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj)
959 IDirectXFileEnumObjectImpl* object;
961 TRACE("(%p)\n", ppObj);
963 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileEnumObjectImpl));
964 if (!object)
966 ERR("Out of memory\n");
967 return DXFILEERR_BADALLOC;
970 object->lpVtbl = &IDirectXFileEnumObject_Vtbl;
971 object->ref = 1;
973 *ppObj = object;
975 return S_OK;
978 /*** IUnknown methods ***/
979 static HRESULT WINAPI IDirectXFileEnumObjectImpl_QueryInterface(IDirectXFileEnumObject* iface, REFIID riid, void** ppvObject)
981 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
983 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
985 if (IsEqualGUID(riid, &IID_IUnknown)
986 || IsEqualGUID(riid, &IID_IDirectXFileEnumObject))
988 IUnknown_AddRef(iface);
989 *ppvObject = This;
990 return S_OK;
993 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
994 return E_NOINTERFACE;
997 static ULONG WINAPI IDirectXFileEnumObjectImpl_AddRef(IDirectXFileEnumObject* iface)
999 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1000 ULONG ref = InterlockedIncrement(&This->ref);
1002 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1004 return ref;
1007 static ULONG WINAPI IDirectXFileEnumObjectImpl_Release(IDirectXFileEnumObject* iface)
1009 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1010 ULONG ref = InterlockedDecrement(&This->ref);
1012 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1014 if (!ref)
1016 int i;
1017 for (i = 0; i < This->nb_xobjects; i++)
1018 IDirectXFileData_Release(This->pRefObjects[i]);
1019 if (This->source == DXFILELOAD_FROMFILE)
1021 UnmapViewOfFile(This->buffer);
1022 CloseHandle(This->file_mapping);
1023 CloseHandle(This->hFile);
1025 else if (This->source == DXFILELOAD_FROMRESOURCE)
1026 FreeResource(This->resource_data);
1027 HeapFree(GetProcessHeap(), 0, This);
1030 return ref;
1033 /*** IDirectXFileEnumObject methods ***/
1034 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetNextDataObject(IDirectXFileEnumObject* iface, LPDIRECTXFILEDATA* ppDataObj)
1036 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1037 IDirectXFileDataImpl* object;
1038 HRESULT hr;
1039 LPBYTE pstrings = NULL;
1041 TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
1043 if (This->nb_xobjects >= MAX_OBJECTS)
1045 ERR("Too many objects\n");
1046 return DXFILEERR_NOMOREOBJECTS;
1049 /* Check if there are templates defined before the object */
1050 while (This->buf.rem_bytes && is_template_available(&This->buf))
1052 if (!parse_template(&This->buf))
1054 TRACE("Template is not correct\n");
1055 hr = DXFILEERR_BADVALUE;
1056 goto error;
1058 else
1060 TRACE("Template successfully parsed:\n");
1061 if (TRACE_ON(d3dxof))
1062 dump_template(This->pDirectXFile->xtemplates, &This->pDirectXFile->xtemplates[This->pDirectXFile->nb_xtemplates - 1]);
1066 if (!This->buf.rem_bytes)
1067 return DXFILEERR_NOMOREOBJECTS;
1069 hr = IDirectXFileDataImpl_Create(&object);
1070 if (FAILED(hr))
1071 return hr;
1073 This->buf.pxo_globals = This->xobjects;
1074 This->buf.nb_pxo_globals = This->nb_xobjects;
1075 This->buf.level = 0;
1077 This->buf.pxo_tab = HeapAlloc(GetProcessHeap(), 0, sizeof(xobject)*MAX_SUBOBJECTS);
1078 if (!This->buf.pxo_tab)
1080 ERR("Out of memory\n");
1081 hr = DXFILEERR_BADALLOC;
1082 goto error;
1084 This->buf.pxo = This->xobjects[This->nb_xobjects] = This->buf.pxo_tab;
1086 This->buf.pxo->pdata = This->buf.pdata = NULL;
1087 This->buf.capacity = 0;
1088 This->buf.cur_pos_data = 0;
1089 This->buf.pxo->nb_subobjects = 1;
1091 pstrings = HeapAlloc(GetProcessHeap(), 0, MAX_STRINGS_BUFFER);
1092 if (!pstrings)
1094 ERR("Out of memory\n");
1095 hr = DXFILEERR_BADALLOC;
1096 goto error;
1098 This->buf.cur_pstrings = This->buf.pstrings = object->pstrings = pstrings;
1100 if (!parse_object(&This->buf))
1102 TRACE("Object is not correct\n");
1103 hr = DXFILEERR_PARSEERROR;
1104 goto error;
1107 if (This->buf.pxo->nb_subobjects > MAX_SUBOBJECTS)
1109 FIXME("Too many subobjects %d\n", This->buf.pxo->nb_subobjects);
1110 hr = DXFILEERR_BADALLOC;
1111 goto error;
1114 object->pstrings = pstrings;
1115 object->pobj = This->buf.pxo;
1116 object->cur_enum_object = 0;
1117 object->level = 0;
1118 object->from_ref = FALSE;
1120 *ppDataObj = (LPDIRECTXFILEDATA)object;
1122 /* Get a reference to created object */
1123 This->pRefObjects[This->nb_xobjects] = (LPDIRECTXFILEDATA)object;
1124 IDirectXFileData_AddRef(This->pRefObjects[This->nb_xobjects]);
1126 This->nb_xobjects++;
1128 return DXFILE_OK;
1130 error:
1132 HeapFree(GetProcessHeap(), 0, This->buf.pxo_tab);
1133 HeapFree(GetProcessHeap(), 0, This->buf.pdata);
1134 HeapFree(GetProcessHeap(), 0, pstrings);
1136 return hr;
1139 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectById(IDirectXFileEnumObject* iface, REFGUID rguid, LPDIRECTXFILEDATA* ppDataObj)
1141 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1143 FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, rguid, ppDataObj);
1145 return DXFILEERR_BADVALUE;
1148 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectByName(IDirectXFileEnumObject* iface, LPCSTR szName, LPDIRECTXFILEDATA* ppDataObj)
1150 IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface;
1152 FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szName, ppDataObj);
1154 return DXFILEERR_BADVALUE;
1157 static const IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl =
1159 IDirectXFileEnumObjectImpl_QueryInterface,
1160 IDirectXFileEnumObjectImpl_AddRef,
1161 IDirectXFileEnumObjectImpl_Release,
1162 IDirectXFileEnumObjectImpl_GetNextDataObject,
1163 IDirectXFileEnumObjectImpl_GetDataObjectById,
1164 IDirectXFileEnumObjectImpl_GetDataObjectByName
1167 static HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj)
1169 IDirectXFileSaveObjectImpl* object;
1171 TRACE("(%p)\n", ppObj);
1173 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileSaveObjectImpl));
1174 if (!object)
1176 ERR("Out of memory\n");
1177 return DXFILEERR_BADALLOC;
1180 object->lpVtbl = &IDirectXFileSaveObject_Vtbl;
1181 object->ref = 1;
1183 *ppObj = object;
1185 return S_OK;
1188 /*** IUnknown methods ***/
1189 static HRESULT WINAPI IDirectXFileSaveObjectImpl_QueryInterface(IDirectXFileSaveObject* iface, REFIID riid, void** ppvObject)
1191 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1193 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1195 if (IsEqualGUID(riid, &IID_IUnknown)
1196 || IsEqualGUID(riid, &IID_IDirectXFileSaveObject))
1198 IUnknown_AddRef(iface);
1199 *ppvObject = This;
1200 return S_OK;
1203 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1204 return E_NOINTERFACE;
1207 static ULONG WINAPI IDirectXFileSaveObjectImpl_AddRef(IDirectXFileSaveObject* iface)
1209 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1210 ULONG ref = InterlockedIncrement(&This->ref);
1212 TRACE("(%p/%p): AddRef from %d\n", iface, This, ref - 1);
1214 return ref;
1217 static ULONG WINAPI IDirectXFileSaveObjectImpl_Release(IDirectXFileSaveObject* iface)
1219 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1220 ULONG ref = InterlockedDecrement(&This->ref);
1222 TRACE("(%p/%p): ReleaseRef to %d\n", iface, This, ref);
1224 if (!ref)
1225 HeapFree(GetProcessHeap(), 0, This);
1227 return ref;
1230 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveTemplates(IDirectXFileSaveObject* iface, DWORD cTemplates, const GUID** ppguidTemplates)
1232 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1234 FIXME("(%p/%p)->(%d,%p) stub!\n", This, iface, cTemplates, ppguidTemplates);
1236 return DXFILEERR_BADVALUE;
1239 static HRESULT WINAPI IDirectXFileSaveObjectImpl_CreateDataObject(IDirectXFileSaveObject* iface, REFGUID rguidTemplate, LPCSTR szName, const GUID* pguid, DWORD cbSize, LPVOID pvData, LPDIRECTXFILEDATA* ppDataObj)
1241 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1243 FIXME("(%p/%p)->(%p,%s,%p,%d,%p,%p) stub!\n", This, iface, rguidTemplate, szName, pguid, cbSize, pvData, ppDataObj);
1245 return DXFILEERR_BADVALUE;
1248 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveData(IDirectXFileSaveObject* iface, LPDIRECTXFILEDATA ppDataObj)
1250 IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface;
1252 FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj);
1254 return DXFILEERR_BADVALUE;
1257 static const IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl =
1259 IDirectXFileSaveObjectImpl_QueryInterface,
1260 IDirectXFileSaveObjectImpl_AddRef,
1261 IDirectXFileSaveObjectImpl_Release,
1262 IDirectXFileSaveObjectImpl_SaveTemplates,
1263 IDirectXFileSaveObjectImpl_CreateDataObject,
1264 IDirectXFileSaveObjectImpl_SaveData