0cab827787455f052e93b82e3477d1c8aa88355a
[reactos.git] / reactos / dll / directx / wine / d3dxof / d3dxof.c
1 /*
2 * Implementation of DirectX File Interfaces
3 *
4 * Copyright 2004, 2008, 2010 Christian Costa
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "d3dxof_private.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(d3dxof);
24 WINE_DECLARE_DEBUG_CHANNEL(d3dxof_dump);
25
26 static const struct IDirectXFileVtbl IDirectXFile_Vtbl;
27 static const struct IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl;
28 static const struct IDirectXFileDataVtbl IDirectXFileData_Vtbl;
29 static const struct IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl;
30 static const struct IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl;
31 static const struct IDirectXFileObjectVtbl IDirectXFileObject_Vtbl;
32 static const struct IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl;
33
34 static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj);
35 static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj);
36 static HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj);
37
38 #define TOKEN_DWORD 41
39 #define TOKEN_FLOAT 42
40
41 HRESULT IDirectXFileImpl_Create(IUnknown* pUnkOuter, LPVOID* ppObj)
42 {
43 IDirectXFileImpl* object;
44
45 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
46
47 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileImpl));
48 if (!object)
49 {
50 ERR("Out of memory\n");
51 return DXFILEERR_BADALLOC;
52 }
53
54 object->IDirectXFile_iface.lpVtbl = &IDirectXFile_Vtbl;
55 object->ref = 1;
56
57 /* Reserve first template to handle the case sensitive legacy type indexColor */
58 object->nb_xtemplates = 1;
59 strcpy(object->xtemplates[0].name, "indexColor");
60 object->xtemplates[0].nb_members = 2;
61 object->xtemplates[0].members[0].type = TOKEN_DWORD;
62 object->xtemplates[0].members[0].nb_dims = 0;
63 object->xtemplates[0].members[1].type = TOKEN_FLOAT;
64 object->xtemplates[0].members[1].nb_dims = 1;
65 object->xtemplates[0].members[1].dim_fixed[0] = TRUE;
66 object->xtemplates[0].members[1].dim_value[0] = 4;
67
68 *ppObj = &object->IDirectXFile_iface;
69
70 return S_OK;
71 }
72
73 static inline IDirectXFileImpl *impl_from_IDirectXFile(IDirectXFile *iface)
74 {
75 return CONTAINING_RECORD(iface, IDirectXFileImpl, IDirectXFile_iface);
76 }
77
78 /*** IUnknown methods ***/
79 static HRESULT WINAPI IDirectXFileImpl_QueryInterface(IDirectXFile* iface, REFIID riid, void** ppvObject)
80 {
81 IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
82
83 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
84
85 if (IsEqualGUID(riid, &IID_IUnknown)
86 || IsEqualGUID(riid, &IID_IDirectXFile))
87 {
88 IUnknown_AddRef(iface);
89 *ppvObject = &This->IDirectXFile_iface;
90 return S_OK;
91 }
92
93 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
94 return E_NOINTERFACE;
95 }
96
97 static ULONG WINAPI IDirectXFileImpl_AddRef(IDirectXFile* iface)
98 {
99 IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
100 ULONG ref = InterlockedIncrement(&This->ref);
101
102 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
103
104 return ref;
105 }
106
107 static ULONG WINAPI IDirectXFileImpl_Release(IDirectXFile* iface)
108 {
109 IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
110 ULONG ref = InterlockedDecrement(&This->ref);
111
112 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
113
114 if (!ref)
115 HeapFree(GetProcessHeap(), 0, This);
116
117 return ref;
118 }
119
120 /*** IDirectXFile methods ***/
121 static HRESULT WINAPI IDirectXFileImpl_CreateEnumObject(IDirectXFile* iface, LPVOID pvSource, DXFILELOADOPTIONS dwLoadOptions, LPDIRECTXFILEENUMOBJECT* ppEnumObj)
122 {
123 IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
124 IDirectXFileEnumObjectImpl* object;
125 HRESULT hr;
126 LPBYTE file_buffer;
127 DWORD file_size;
128
129 TRACE("(%p/%p)->(%p,%x,%p)\n", This, iface, pvSource, dwLoadOptions, ppEnumObj);
130
131 if (!ppEnumObj)
132 return DXFILEERR_BADVALUE;
133
134 /* Only lowest 4 bits are relevant in DXFILELOADOPTIONS */
135 dwLoadOptions &= 0xF;
136
137 hr = IDirectXFileEnumObjectImpl_Create(&object);
138 if (FAILED(hr))
139 return hr;
140
141 if (dwLoadOptions == DXFILELOAD_FROMFILE)
142 {
143 HANDLE hFile, file_mapping;
144
145 TRACE("Open source file '%s'\n", (char*)pvSource);
146
147 hFile = CreateFileA(pvSource, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
148 if (hFile == INVALID_HANDLE_VALUE)
149 {
150 TRACE("File '%s' not found\n", (char*)pvSource);
151 return DXFILEERR_FILENOTFOUND;
152 }
153
154 file_size = GetFileSize(hFile, NULL);
155
156 file_mapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
157 CloseHandle(hFile);
158 if (!file_mapping)
159 {
160 hr = DXFILEERR_BADFILETYPE;
161 goto error;
162 }
163
164 object->mapped_memory = MapViewOfFile(file_mapping, FILE_MAP_READ, 0, 0, 0);
165 CloseHandle(file_mapping);
166 if (!object->mapped_memory)
167 {
168 hr = DXFILEERR_BADFILETYPE;
169 goto error;
170 }
171 file_buffer = object->mapped_memory;
172 }
173 else if (dwLoadOptions == DXFILELOAD_FROMRESOURCE)
174 {
175 HRSRC resource_info;
176 HGLOBAL resource_data;
177 LPDXFILELOADRESOURCE lpdxflr = pvSource;
178
179 TRACE("Source in resource (module = %p, name = %s, type = %s\n", lpdxflr->hModule, debugstr_a(lpdxflr->lpName), debugstr_a(lpdxflr->lpType));
180
181 resource_info = FindResourceA(lpdxflr->hModule, lpdxflr->lpName, lpdxflr->lpType);
182 if (!resource_info)
183 {
184 hr = DXFILEERR_RESOURCENOTFOUND;
185 goto error;
186 }
187
188 file_size = SizeofResource(lpdxflr->hModule, resource_info);
189
190 resource_data = LoadResource(lpdxflr->hModule, resource_info);
191 if (!resource_data)
192 {
193 hr = DXFILEERR_BADRESOURCE;
194 goto error;
195 }
196
197 file_buffer = LockResource(resource_data);
198 if (!file_buffer)
199 {
200 hr = DXFILEERR_BADRESOURCE;
201 goto error;
202 }
203 }
204 else if (dwLoadOptions == DXFILELOAD_FROMMEMORY)
205 {
206 LPDXFILELOADMEMORY lpdxflm = pvSource;
207
208 TRACE("Source in memory at %p with size %d\n", lpdxflm->lpMemory, lpdxflm->dSize);
209
210 file_buffer = lpdxflm->lpMemory;
211 file_size = lpdxflm->dSize;
212 }
213 else
214 {
215 FIXME("Source type %d is not handled yet\n", dwLoadOptions);
216 hr = DXFILEERR_NOTDONEYET;
217 goto error;
218 }
219
220 TRACE("File size is %d bytes\n", file_size);
221
222 if (TRACE_ON(d3dxof_dump))
223 {
224 static USHORT num;
225 char tmp[12];
226 HANDLE file;
227 sprintf(tmp, "file%05u.x", num++);
228
229 file = CreateFileA(tmp, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
230 if (file != INVALID_HANDLE_VALUE)
231 {
232 WriteFile(file, file_buffer, file_size, NULL, NULL);
233 CloseHandle(file);
234 }
235 }
236
237 object->pDirectXFile = This;
238
239 object->buf.pdxf = This;
240 object->buf.token_present = FALSE;
241 object->buf.buffer = file_buffer;
242 object->buf.rem_bytes = file_size;
243 hr = parse_header(&object->buf, &object->decomp_buffer);
244 if (FAILED(hr))
245 goto error;
246
247 /* Check if there are templates defined before the object */
248 if (!parse_templates(&object->buf, TRUE))
249 {
250 hr = DXFILEERR_PARSEERROR;
251 goto error;
252 }
253
254 if (TRACE_ON(d3dxof))
255 {
256 ULONG i;
257 TRACE("Registered templates (%d):\n", This->nb_xtemplates);
258 for (i = 1; i < This->nb_xtemplates; i++)
259 DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
260 }
261
262 *ppEnumObj = &object->IDirectXFileEnumObject_iface;
263
264 return DXFILE_OK;
265
266 error:
267 IDirectXFileEnumObject_Release(&object->IDirectXFileEnumObject_iface);
268 *ppEnumObj = NULL;
269
270 return hr;
271 }
272
273 static HRESULT WINAPI IDirectXFileImpl_CreateSaveObject(IDirectXFile* iface, LPCSTR szFileName, DXFILEFORMAT dwFileFormat, LPDIRECTXFILESAVEOBJECT* ppSaveObj)
274 {
275 IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
276 IDirectXFileSaveObjectImpl *object;
277 HRESULT hr;
278
279 FIXME("(%p/%p)->(%s,%x,%p) partial stub!\n", This, iface, szFileName, dwFileFormat, ppSaveObj);
280
281 if (!szFileName || !ppSaveObj)
282 return E_POINTER;
283
284 hr = IDirectXFileSaveObjectImpl_Create(&object);
285 if (SUCCEEDED(hr))
286 *ppSaveObj = &object->IDirectXFileSaveObject_iface;
287 return hr;
288 }
289
290 static HRESULT WINAPI IDirectXFileImpl_RegisterTemplates(IDirectXFile* iface, LPVOID pvData, DWORD cbSize)
291 {
292 IDirectXFileImpl *This = impl_from_IDirectXFile(iface);
293 parse_buffer buf;
294 HRESULT hr;
295 LPBYTE decomp_buffer = NULL;
296
297 ZeroMemory(&buf, sizeof(buf));
298 buf.buffer = pvData;
299 buf.rem_bytes = cbSize;
300 buf.pdxf = This;
301
302 TRACE("(%p/%p)->(%p,%d)\n", This, iface, pvData, cbSize);
303
304 if (!pvData)
305 return DXFILEERR_BADVALUE;
306
307 if (TRACE_ON(d3dxof_dump))
308 {
309 static USHORT num;
310 char tmp[16];
311 HANDLE file;
312 sprintf(tmp, "template%05u.x", num++);
313
314 file = CreateFileA(tmp, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
315 if (file != INVALID_HANDLE_VALUE)
316 {
317 WriteFile(file, pvData, cbSize, NULL, NULL);
318 CloseHandle(file);
319 }
320 }
321
322 hr = parse_header(&buf, &decomp_buffer);
323 if (FAILED(hr))
324 goto cleanup;
325
326 if (!parse_templates(&buf, FALSE))
327 {
328 hr = DXFILEERR_PARSEERROR;
329 goto cleanup;
330 }
331
332 if (TRACE_ON(d3dxof))
333 {
334 ULONG i;
335 TRACE("Registered templates (%d):\n", This->nb_xtemplates);
336 for (i = 1; i < This->nb_xtemplates; i++)
337 DPRINTF("%s - %s\n", This->xtemplates[i].name, debugstr_guid(&This->xtemplates[i].class_id));
338 }
339
340 hr = DXFILE_OK;
341 cleanup:
342 HeapFree(GetProcessHeap(), 0, decomp_buffer);
343 return hr;
344 }
345
346 static const IDirectXFileVtbl IDirectXFile_Vtbl =
347 {
348 IDirectXFileImpl_QueryInterface,
349 IDirectXFileImpl_AddRef,
350 IDirectXFileImpl_Release,
351 IDirectXFileImpl_CreateEnumObject,
352 IDirectXFileImpl_CreateSaveObject,
353 IDirectXFileImpl_RegisterTemplates
354 };
355
356 static HRESULT IDirectXFileBinaryImpl_Create(IDirectXFileBinaryImpl** ppObj)
357 {
358 IDirectXFileBinaryImpl* object;
359
360 TRACE("(%p)\n", ppObj);
361
362 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileBinaryImpl));
363 if (!object)
364 {
365 ERR("Out of memory\n");
366 return DXFILEERR_BADALLOC;
367 }
368
369 object->IDirectXFileBinary_iface.lpVtbl = &IDirectXFileBinary_Vtbl;
370 object->ref = 1;
371
372 *ppObj = object;
373
374 return DXFILE_OK;
375 }
376
377 static inline IDirectXFileBinaryImpl *impl_from_IDirectXFileBinary(IDirectXFileBinary *iface)
378 {
379 return CONTAINING_RECORD(iface, IDirectXFileBinaryImpl, IDirectXFileBinary_iface);
380 }
381
382 /*** IUnknown methods ***/
383 static HRESULT WINAPI IDirectXFileBinaryImpl_QueryInterface(IDirectXFileBinary* iface, REFIID riid, void** ppvObject)
384 {
385 IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
386
387 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
388
389 if (IsEqualGUID(riid, &IID_IUnknown)
390 || IsEqualGUID(riid, &IID_IDirectXFileObject)
391 || IsEqualGUID(riid, &IID_IDirectXFileBinary))
392 {
393 IUnknown_AddRef(iface);
394 *ppvObject = &This->IDirectXFileBinary_iface;
395 return S_OK;
396 }
397
398 /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
399 if (!IsEqualGUID(riid, &IID_IDirectXFileData)
400 && !IsEqualGUID(riid, &IID_IDirectXFileDataReference))
401 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
402
403 return E_NOINTERFACE;
404 }
405
406 static ULONG WINAPI IDirectXFileBinaryImpl_AddRef(IDirectXFileBinary* iface)
407 {
408 IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
409 ULONG ref = InterlockedIncrement(&This->ref);
410
411 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
412
413 return ref;
414 }
415
416 static ULONG WINAPI IDirectXFileBinaryImpl_Release(IDirectXFileBinary* iface)
417 {
418 IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
419 ULONG ref = InterlockedDecrement(&This->ref);
420
421 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
422
423 if (!ref)
424 HeapFree(GetProcessHeap(), 0, This);
425
426 return ref;
427 }
428
429 /*** IDirectXFileObject methods ***/
430 static HRESULT WINAPI IDirectXFileBinaryImpl_GetName(IDirectXFileBinary* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
431
432 {
433 IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
434
435 FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, pstrNameBuf, pdwBufLen);
436
437 return DXFILEERR_BADVALUE;
438 }
439
440 static HRESULT WINAPI IDirectXFileBinaryImpl_GetId(IDirectXFileBinary* iface, LPGUID pGuid)
441 {
442 IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
443
444 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pGuid);
445
446 return DXFILEERR_BADVALUE;
447 }
448
449 /*** IDirectXFileBinary methods ***/
450 static HRESULT WINAPI IDirectXFileBinaryImpl_GetSize(IDirectXFileBinary* iface, DWORD* pcbSize)
451 {
452 IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
453
454 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pcbSize);
455
456 return DXFILEERR_BADVALUE;
457 }
458
459 static HRESULT WINAPI IDirectXFileBinaryImpl_GetMimeType(IDirectXFileBinary* iface, LPCSTR* pszMimeType)
460 {
461 IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
462
463 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pszMimeType);
464
465 return DXFILEERR_BADVALUE;
466 }
467
468 static HRESULT WINAPI IDirectXFileBinaryImpl_Read(IDirectXFileBinary* iface, LPVOID pvData, DWORD cbSize, LPDWORD pcbRead)
469 {
470 IDirectXFileBinaryImpl *This = impl_from_IDirectXFileBinary(iface);
471
472 FIXME("(%p/%p)->(%p, %d, %p) stub!\n", This, iface, pvData, cbSize, pcbRead);
473
474 return DXFILEERR_BADVALUE;
475 }
476
477 static const IDirectXFileBinaryVtbl IDirectXFileBinary_Vtbl =
478 {
479 IDirectXFileBinaryImpl_QueryInterface,
480 IDirectXFileBinaryImpl_AddRef,
481 IDirectXFileBinaryImpl_Release,
482 IDirectXFileBinaryImpl_GetName,
483 IDirectXFileBinaryImpl_GetId,
484 IDirectXFileBinaryImpl_GetSize,
485 IDirectXFileBinaryImpl_GetMimeType,
486 IDirectXFileBinaryImpl_Read
487 };
488
489 static HRESULT IDirectXFileDataImpl_Create(IDirectXFileDataImpl** ppObj)
490 {
491 IDirectXFileDataImpl* object;
492
493 TRACE("(%p)\n", ppObj);
494
495 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataImpl));
496 if (!object)
497 {
498 ERR("Out of memory\n");
499 return DXFILEERR_BADALLOC;
500 }
501
502 object->IDirectXFileData_iface.lpVtbl = &IDirectXFileData_Vtbl;
503 object->ref = 1;
504
505 *ppObj = object;
506
507 return S_OK;
508 }
509
510 static inline IDirectXFileDataImpl *impl_from_IDirectXFileData(IDirectXFileData *iface)
511 {
512 return CONTAINING_RECORD(iface, IDirectXFileDataImpl, IDirectXFileData_iface);
513 }
514
515 /*** IUnknown methods ***/
516 static HRESULT WINAPI IDirectXFileDataImpl_QueryInterface(IDirectXFileData* iface, REFIID riid, void** ppvObject)
517 {
518 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
519
520 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
521
522 if (IsEqualGUID(riid, &IID_IUnknown)
523 || IsEqualGUID(riid, &IID_IDirectXFileObject)
524 || IsEqualGUID(riid, &IID_IDirectXFileData))
525 {
526 IUnknown_AddRef(iface);
527 *ppvObject = &This->IDirectXFileData_iface;
528 return S_OK;
529 }
530
531 /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
532 if (!IsEqualGUID(riid, &IID_IDirectXFileBinary)
533 && !IsEqualGUID(riid, &IID_IDirectXFileDataReference))
534 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
535
536 return E_NOINTERFACE;
537 }
538
539 static ULONG WINAPI IDirectXFileDataImpl_AddRef(IDirectXFileData* iface)
540 {
541 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
542 ULONG ref = InterlockedIncrement(&This->ref);
543
544 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
545
546 return ref;
547 }
548
549 static ULONG WINAPI IDirectXFileDataImpl_Release(IDirectXFileData* iface)
550 {
551 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
552 ULONG ref = InterlockedDecrement(&This->ref);
553
554 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
555
556 if (!ref)
557 {
558 if (!This->level && !This->from_ref)
559 {
560 HeapFree(GetProcessHeap(), 0, This->pstrings);
561 if (This->pobj)
562 {
563 HeapFree(GetProcessHeap(), 0, This->pobj->pdata);
564 HeapFree(GetProcessHeap(), 0, This->pobj);
565 }
566 }
567 HeapFree(GetProcessHeap(), 0, This);
568 }
569
570 return ref;
571 }
572
573 /*** IDirectXFileObject methods ***/
574 static HRESULT WINAPI IDirectXFileDataImpl_GetName(IDirectXFileData* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
575 {
576 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
577 DWORD len;
578
579 TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
580
581 if (!pdwBufLen)
582 return DXFILEERR_BADVALUE;
583
584 len = strlen(This->pobj->name);
585 if (len)
586 len++;
587
588 if (pstrNameBuf) {
589 if (*pdwBufLen < len)
590 return DXFILEERR_BADVALUE;
591 CopyMemory(pstrNameBuf, This->pobj->name, len);
592 /* Even if we return a size of 0, an empty string with a null byte must be returned */
593 if (*pdwBufLen && !len)
594 pstrNameBuf[0] = 0;
595 }
596 *pdwBufLen = len;
597
598 return DXFILE_OK;
599 }
600
601 static HRESULT WINAPI IDirectXFileDataImpl_GetId(IDirectXFileData* iface, LPGUID pGuid)
602 {
603 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
604
605 TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
606
607 if (!pGuid)
608 return DXFILEERR_BADVALUE;
609
610 memcpy(pGuid, &This->pobj->class_id, 16);
611
612 return DXFILE_OK;
613 }
614
615 /*** IDirectXFileData methods ***/
616 static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCSTR szMember, DWORD* pcbSize, void** ppvData)
617 {
618 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
619
620 TRACE("(%p/%p)->(%s,%p,%p)\n", This, iface, debugstr_a(szMember), pcbSize, ppvData);
621
622 if (!pcbSize || !ppvData)
623 return DXFILEERR_BADVALUE;
624
625 if (szMember)
626 {
627 ULONG i;
628 for (i = 0; i < This->pobj->nb_members; i++)
629 if (!strcmp(This->pobj->members[i].name, szMember))
630 break;
631 if (i == This->pobj->nb_members)
632 {
633 WARN("Unknown member '%s'\n", szMember);
634 return DXFILEERR_BADDATAREFERENCE;
635 }
636 *pcbSize = This->pobj->members[i].size;
637 *ppvData = This->pobj->root->pdata + This->pobj->members[i].start;
638 }
639 else
640 {
641 *pcbSize = This->pobj->size;
642 *ppvData = This->pobj->root->pdata + This->pobj->pos_data;
643 }
644
645 return DXFILE_OK;
646 }
647
648 static HRESULT WINAPI IDirectXFileDataImpl_GetType(IDirectXFileData* iface, const GUID** pguid)
649 {
650 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
651 static GUID guid;
652
653 TRACE("(%p/%p)->(%p)\n", This, iface, pguid);
654
655 if (!pguid)
656 return DXFILEERR_BADVALUE;
657
658 memcpy(&guid, &This->pobj->type, 16);
659 *pguid = &guid;
660
661 return DXFILE_OK;
662 }
663
664 static HRESULT WINAPI IDirectXFileDataImpl_GetNextObject(IDirectXFileData* iface, LPDIRECTXFILEOBJECT* ppChildObj)
665 {
666 HRESULT hr;
667 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
668
669 TRACE("(%p/%p)->(%p)\n", This, iface, ppChildObj);
670
671 if (This->cur_enum_object >= This->pobj->nb_children)
672 {
673 *ppChildObj = NULL;
674 return DXFILEERR_NOMOREOBJECTS;
675 }
676
677 if (This->from_ref && (This->level >= 1))
678 {
679 /* Only 2 levels can be enumerated if the object is obtained from a reference */
680 *ppChildObj = NULL;
681 return DXFILEERR_NOMOREOBJECTS;
682 }
683
684 if (This->pobj->children[This->cur_enum_object]->binary)
685 {
686 IDirectXFileBinaryImpl *object;
687
688 hr = IDirectXFileBinaryImpl_Create(&object);
689 if (FAILED(hr))
690 return hr;
691
692 *ppChildObj = (LPDIRECTXFILEOBJECT)&object->IDirectXFileBinary_iface;
693 }
694 else if (This->pobj->children[This->cur_enum_object]->ptarget)
695 {
696 IDirectXFileDataReferenceImpl *object;
697
698 hr = IDirectXFileDataReferenceImpl_Create(&object);
699 if (FAILED(hr))
700 return hr;
701
702 object->ptarget = This->pobj->children[This->cur_enum_object++]->ptarget;
703
704 *ppChildObj = (LPDIRECTXFILEOBJECT)&object->IDirectXFileDataReference_iface;
705 }
706 else
707 {
708 IDirectXFileDataImpl *object;
709
710 hr = IDirectXFileDataImpl_Create(&object);
711 if (FAILED(hr))
712 return hr;
713
714 object->pobj = This->pobj->children[This->cur_enum_object++];
715 object->cur_enum_object = 0;
716 object->from_ref = This->from_ref;
717 object->level = This->level + 1;
718
719 *ppChildObj = (LPDIRECTXFILEOBJECT)&object->IDirectXFileData_iface;
720 }
721
722 return DXFILE_OK;
723 }
724
725 static HRESULT WINAPI IDirectXFileDataImpl_AddDataObject(IDirectXFileData* iface, LPDIRECTXFILEDATA pDataObj)
726 {
727 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
728
729 FIXME("(%p/%p)->(%p) stub!\n", This, iface, pDataObj);
730
731 return DXFILEERR_BADVALUE;
732 }
733
734 static HRESULT WINAPI IDirectXFileDataImpl_AddDataReference(IDirectXFileData* iface, LPCSTR szRef, const GUID* pguidRef)
735 {
736 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
737
738 FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szRef, pguidRef);
739
740 return DXFILEERR_BADVALUE;
741 }
742
743 static HRESULT WINAPI IDirectXFileDataImpl_AddBinaryObject(IDirectXFileData* iface, LPCSTR szName, const GUID* pguid, LPCSTR szMimeType, LPVOID pvData, DWORD cbSize)
744 {
745 IDirectXFileDataImpl *This = impl_from_IDirectXFileData(iface);
746
747 FIXME("(%p/%p)->(%s,%p,%s,%p,%d) stub!\n", This, iface, szName, pguid, szMimeType, pvData, cbSize);
748
749 return DXFILEERR_BADVALUE;
750 }
751
752 static const IDirectXFileDataVtbl IDirectXFileData_Vtbl =
753 {
754 IDirectXFileDataImpl_QueryInterface,
755 IDirectXFileDataImpl_AddRef,
756 IDirectXFileDataImpl_Release,
757 IDirectXFileDataImpl_GetName,
758 IDirectXFileDataImpl_GetId,
759 IDirectXFileDataImpl_GetData,
760 IDirectXFileDataImpl_GetType,
761 IDirectXFileDataImpl_GetNextObject,
762 IDirectXFileDataImpl_AddDataObject,
763 IDirectXFileDataImpl_AddDataReference,
764 IDirectXFileDataImpl_AddBinaryObject
765 };
766
767 static HRESULT IDirectXFileDataReferenceImpl_Create(IDirectXFileDataReferenceImpl** ppObj)
768 {
769 IDirectXFileDataReferenceImpl* object;
770
771 TRACE("(%p)\n", ppObj);
772
773 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileDataReferenceImpl));
774 if (!object)
775 {
776 ERR("Out of memory\n");
777 return DXFILEERR_BADALLOC;
778 }
779
780 object->IDirectXFileDataReference_iface.lpVtbl = &IDirectXFileDataReference_Vtbl;
781 object->ref = 1;
782
783 *ppObj = object;
784
785 return S_OK;
786 }
787
788 static inline IDirectXFileDataReferenceImpl *impl_from_IDirectXFileDataReference(IDirectXFileDataReference *iface)
789 {
790 return CONTAINING_RECORD(iface, IDirectXFileDataReferenceImpl, IDirectXFileDataReference_iface);
791 }
792
793 /*** IUnknown methods ***/
794 static HRESULT WINAPI IDirectXFileDataReferenceImpl_QueryInterface(IDirectXFileDataReference* iface, REFIID riid, void** ppvObject)
795 {
796 IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
797
798 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
799
800 if (IsEqualGUID(riid, &IID_IUnknown)
801 || IsEqualGUID(riid, &IID_IDirectXFileObject)
802 || IsEqualGUID(riid, &IID_IDirectXFileDataReference))
803 {
804 IUnknown_AddRef(iface);
805 *ppvObject = &This->IDirectXFileDataReference_iface;
806 return S_OK;
807 }
808
809 /* Do not print an error for interfaces that can be queried to retrieve the type of the object */
810 if (!IsEqualGUID(riid, &IID_IDirectXFileData)
811 && !IsEqualGUID(riid, &IID_IDirectXFileBinary))
812 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
813
814 return E_NOINTERFACE;
815 }
816
817 static ULONG WINAPI IDirectXFileDataReferenceImpl_AddRef(IDirectXFileDataReference* iface)
818 {
819 IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
820 ULONG ref = InterlockedIncrement(&This->ref);
821
822 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
823
824 return ref;
825 }
826
827 static ULONG WINAPI IDirectXFileDataReferenceImpl_Release(IDirectXFileDataReference* iface)
828 {
829 IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
830 ULONG ref = InterlockedDecrement(&This->ref);
831
832 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
833
834 if (!ref)
835 HeapFree(GetProcessHeap(), 0, This);
836
837 return ref;
838 }
839
840 /*** IDirectXFileObject methods ***/
841 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetName(IDirectXFileDataReference* iface, LPSTR pstrNameBuf, LPDWORD pdwBufLen)
842 {
843 IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
844 DWORD len;
845
846 TRACE("(%p/%p)->(%p,%p)\n", This, iface, pstrNameBuf, pdwBufLen);
847
848 if (!pdwBufLen)
849 return DXFILEERR_BADVALUE;
850
851 len = strlen(This->ptarget->name);
852 if (len)
853 len++;
854
855 if (pstrNameBuf) {
856 if (*pdwBufLen < len)
857 return DXFILEERR_BADVALUE;
858 CopyMemory(pstrNameBuf, This->ptarget->name, len);
859 /* Even if we return a size of 0, an empty string with a null byte must be returned */
860 if (*pdwBufLen && !len)
861 pstrNameBuf[0] = 0;
862 }
863 *pdwBufLen = len;
864
865 return DXFILE_OK;
866 }
867
868 static HRESULT WINAPI IDirectXFileDataReferenceImpl_GetId(IDirectXFileDataReference* iface, LPGUID pGuid)
869 {
870 IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
871
872 TRACE("(%p/%p)->(%p)\n", This, iface, pGuid);
873
874 if (!pGuid)
875 return DXFILEERR_BADVALUE;
876
877 memcpy(pGuid, &This->ptarget->class_id, 16);
878
879 return DXFILE_OK;
880 }
881
882 /*** IDirectXFileDataReference ***/
883 static HRESULT WINAPI IDirectXFileDataReferenceImpl_Resolve(IDirectXFileDataReference* iface, LPDIRECTXFILEDATA* ppDataObj)
884 {
885 IDirectXFileDataReferenceImpl *This = impl_from_IDirectXFileDataReference(iface);
886 IDirectXFileDataImpl *object;
887 HRESULT hr;
888
889 TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
890
891 if (!ppDataObj)
892 return DXFILEERR_BADVALUE;
893
894 hr = IDirectXFileDataImpl_Create(&object);
895 if (FAILED(hr))
896 return hr;
897
898 object->pobj = This->ptarget;
899 object->cur_enum_object = 0;
900 object->level = 0;
901 object->from_ref = TRUE;
902
903 *ppDataObj = (LPDIRECTXFILEDATA)object;
904
905 return DXFILE_OK;
906 }
907
908 static const IDirectXFileDataReferenceVtbl IDirectXFileDataReference_Vtbl =
909 {
910 IDirectXFileDataReferenceImpl_QueryInterface,
911 IDirectXFileDataReferenceImpl_AddRef,
912 IDirectXFileDataReferenceImpl_Release,
913 IDirectXFileDataReferenceImpl_GetName,
914 IDirectXFileDataReferenceImpl_GetId,
915 IDirectXFileDataReferenceImpl_Resolve
916 };
917
918 static HRESULT IDirectXFileEnumObjectImpl_Create(IDirectXFileEnumObjectImpl** ppObj)
919 {
920 IDirectXFileEnumObjectImpl* object;
921
922 TRACE("(%p)\n", ppObj);
923
924 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileEnumObjectImpl));
925 if (!object)
926 {
927 ERR("Out of memory\n");
928 return DXFILEERR_BADALLOC;
929 }
930
931 object->IDirectXFileEnumObject_iface.lpVtbl = &IDirectXFileEnumObject_Vtbl;
932 object->ref = 1;
933
934 *ppObj = object;
935
936 return S_OK;
937 }
938
939 static inline IDirectXFileEnumObjectImpl *impl_from_IDirectXFileEnumObject(IDirectXFileEnumObject *iface)
940 {
941 return CONTAINING_RECORD(iface, IDirectXFileEnumObjectImpl, IDirectXFileEnumObject_iface);
942 }
943
944 /*** IUnknown methods ***/
945 static HRESULT WINAPI IDirectXFileEnumObjectImpl_QueryInterface(IDirectXFileEnumObject* iface, REFIID riid, void** ppvObject)
946 {
947 IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
948
949 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
950
951 if (IsEqualGUID(riid, &IID_IUnknown)
952 || IsEqualGUID(riid, &IID_IDirectXFileEnumObject))
953 {
954 IUnknown_AddRef(iface);
955 *ppvObject = &This->IDirectXFileEnumObject_iface;
956 return S_OK;
957 }
958
959 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
960 return E_NOINTERFACE;
961 }
962
963 static ULONG WINAPI IDirectXFileEnumObjectImpl_AddRef(IDirectXFileEnumObject* iface)
964 {
965 IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
966 ULONG ref = InterlockedIncrement(&This->ref);
967
968 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
969
970 return ref;
971 }
972
973 static ULONG WINAPI IDirectXFileEnumObjectImpl_Release(IDirectXFileEnumObject* iface)
974 {
975 IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
976 ULONG ref = InterlockedDecrement(&This->ref);
977
978 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
979
980 if (!ref)
981 {
982 ULONG i;
983 for (i = 0; i < This->nb_xobjects; i++)
984 IDirectXFileData_Release(This->pRefObjects[i]);
985 if (This->mapped_memory)
986 UnmapViewOfFile(This->mapped_memory);
987 HeapFree(GetProcessHeap(), 0, This->decomp_buffer);
988 HeapFree(GetProcessHeap(), 0, This);
989 }
990
991 return ref;
992 }
993
994 /*** IDirectXFileEnumObject methods ***/
995 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetNextDataObject(IDirectXFileEnumObject* iface, LPDIRECTXFILEDATA* ppDataObj)
996 {
997 IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
998 IDirectXFileDataImpl* object;
999 HRESULT hr;
1000
1001 if (!ppDataObj)
1002 return E_POINTER;
1003
1004 *ppDataObj = NULL;
1005
1006 TRACE("(%p/%p)->(%p)\n", This, iface, ppDataObj);
1007
1008 if (This->nb_xobjects >= MAX_OBJECTS)
1009 {
1010 ERR("Too many objects\n");
1011 return DXFILEERR_NOMOREOBJECTS;
1012 }
1013
1014 /* Check if there are templates defined before the object */
1015 if (!parse_templates(&This->buf, TRUE))
1016 return DXFILEERR_PARSEERROR;
1017
1018 if (!This->buf.rem_bytes)
1019 return DXFILEERR_NOMOREOBJECTS;
1020
1021 hr = IDirectXFileDataImpl_Create(&object);
1022 if (FAILED(hr))
1023 return hr;
1024
1025 object->pobj = HeapAlloc(GetProcessHeap(), 0, sizeof(xobject)*MAX_SUBOBJECTS);
1026 if (!object->pobj)
1027 {
1028 ERR("Out of memory\n");
1029 hr = DXFILEERR_BADALLOC;
1030 goto error;
1031 }
1032
1033 object->pstrings = HeapAlloc(GetProcessHeap(), 0, MAX_STRINGS_BUFFER);
1034 if (!object->pstrings)
1035 {
1036 ERR("Out of memory\n");
1037 hr = DXFILEERR_BADALLOC;
1038 goto error;
1039 }
1040
1041 object->cur_enum_object = 0;
1042 object->level = 0;
1043 object->from_ref = FALSE;
1044
1045 This->buf.pxo_globals = This->xobjects;
1046 This->buf.nb_pxo_globals = This->nb_xobjects;
1047 This->buf.level = 0;
1048 This->buf.pdata = NULL;
1049 This->buf.capacity = 0;
1050 This->buf.cur_pos_data = 0;
1051 This->buf.cur_pstrings = This->buf.pstrings = object->pstrings;
1052 This->buf.pxo = This->xobjects[This->nb_xobjects] = This->buf.pxo_tab = object->pobj;
1053 This->buf.pxo->pdata = NULL;
1054 This->buf.pxo->nb_subobjects = 1;
1055
1056 if (!parse_object(&This->buf))
1057 {
1058 WARN("Object is not correct\n");
1059 hr = DXFILEERR_PARSEERROR;
1060 goto error;
1061 }
1062
1063 *ppDataObj = (LPDIRECTXFILEDATA)object;
1064
1065 /* Get a reference to created object */
1066 This->pRefObjects[This->nb_xobjects] = (LPDIRECTXFILEDATA)object;
1067 IDirectXFileData_AddRef(This->pRefObjects[This->nb_xobjects]);
1068
1069 This->nb_xobjects++;
1070
1071 return DXFILE_OK;
1072
1073 error:
1074
1075 IDirectXFileData_Release(&object->IDirectXFileData_iface);
1076
1077 return hr;
1078 }
1079
1080 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectById(IDirectXFileEnumObject* iface, REFGUID rguid, LPDIRECTXFILEDATA* ppDataObj)
1081 {
1082 IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
1083
1084 FIXME("(%p/%p)->(%p,%p) stub!\n", This, iface, rguid, ppDataObj);
1085
1086 return DXFILEERR_BADVALUE;
1087 }
1088
1089 static HRESULT WINAPI IDirectXFileEnumObjectImpl_GetDataObjectByName(IDirectXFileEnumObject* iface, LPCSTR szName, LPDIRECTXFILEDATA* ppDataObj)
1090 {
1091 IDirectXFileEnumObjectImpl *This = impl_from_IDirectXFileEnumObject(iface);
1092
1093 FIXME("(%p/%p)->(%s,%p) stub!\n", This, iface, szName, ppDataObj);
1094
1095 return DXFILEERR_BADVALUE;
1096 }
1097
1098 static const IDirectXFileEnumObjectVtbl IDirectXFileEnumObject_Vtbl =
1099 {
1100 IDirectXFileEnumObjectImpl_QueryInterface,
1101 IDirectXFileEnumObjectImpl_AddRef,
1102 IDirectXFileEnumObjectImpl_Release,
1103 IDirectXFileEnumObjectImpl_GetNextDataObject,
1104 IDirectXFileEnumObjectImpl_GetDataObjectById,
1105 IDirectXFileEnumObjectImpl_GetDataObjectByName
1106 };
1107
1108 static HRESULT IDirectXFileSaveObjectImpl_Create(IDirectXFileSaveObjectImpl** ppObj)
1109 {
1110 IDirectXFileSaveObjectImpl* object;
1111
1112 TRACE("(%p)\n", ppObj);
1113
1114 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectXFileSaveObjectImpl));
1115 if (!object)
1116 {
1117 ERR("Out of memory\n");
1118 return DXFILEERR_BADALLOC;
1119 }
1120
1121 object->IDirectXFileSaveObject_iface.lpVtbl = &IDirectXFileSaveObject_Vtbl;
1122 object->ref = 1;
1123
1124 *ppObj = object;
1125
1126 return S_OK;
1127 }
1128
1129 static inline IDirectXFileSaveObjectImpl *impl_from_IDirectXFileSaveObject(IDirectXFileSaveObject *iface)
1130 {
1131 return CONTAINING_RECORD(iface, IDirectXFileSaveObjectImpl, IDirectXFileSaveObject_iface);
1132 }
1133
1134 /*** IUnknown methods ***/
1135 static HRESULT WINAPI IDirectXFileSaveObjectImpl_QueryInterface(IDirectXFileSaveObject* iface, REFIID riid, void** ppvObject)
1136 {
1137 IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1138
1139 TRACE("(%p/%p)->(%s,%p)\n", iface, This, debugstr_guid(riid), ppvObject);
1140
1141 if (IsEqualGUID(riid, &IID_IUnknown)
1142 || IsEqualGUID(riid, &IID_IDirectXFileSaveObject))
1143 {
1144 IUnknown_AddRef(iface);
1145 *ppvObject = &This->IDirectXFileSaveObject_iface;
1146 return S_OK;
1147 }
1148
1149 ERR("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
1150 return E_NOINTERFACE;
1151 }
1152
1153 static ULONG WINAPI IDirectXFileSaveObjectImpl_AddRef(IDirectXFileSaveObject* iface)
1154 {
1155 IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1156 ULONG ref = InterlockedIncrement(&This->ref);
1157
1158 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
1159
1160 return ref;
1161 }
1162
1163 static ULONG WINAPI IDirectXFileSaveObjectImpl_Release(IDirectXFileSaveObject* iface)
1164 {
1165 IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1166 ULONG ref = InterlockedDecrement(&This->ref);
1167
1168 TRACE("(%p/%p)->(): new ref %d\n", iface, This, ref);
1169
1170 if (!ref)
1171 HeapFree(GetProcessHeap(), 0, This);
1172
1173 return ref;
1174 }
1175
1176 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveTemplates(IDirectXFileSaveObject* iface, DWORD cTemplates, const GUID** ppguidTemplates)
1177 {
1178 IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1179
1180 FIXME("(%p/%p)->(%d,%p) stub!\n", This, iface, cTemplates, ppguidTemplates);
1181
1182 return DXFILE_OK;
1183 }
1184
1185 static HRESULT WINAPI IDirectXFileSaveObjectImpl_CreateDataObject(IDirectXFileSaveObject* iface, REFGUID rguidTemplate, LPCSTR szName, const GUID* pguid, DWORD cbSize, LPVOID pvData, LPDIRECTXFILEDATA* ppDataObj)
1186 {
1187 IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1188
1189 FIXME("(%p/%p)->(%p,%s,%p,%d,%p,%p) stub!\n", This, iface, rguidTemplate, szName, pguid, cbSize, pvData, ppDataObj);
1190
1191 return DXFILEERR_BADVALUE;
1192 }
1193
1194 static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveData(IDirectXFileSaveObject* iface, LPDIRECTXFILEDATA ppDataObj)
1195 {
1196 IDirectXFileSaveObjectImpl *This = impl_from_IDirectXFileSaveObject(iface);
1197
1198 FIXME("(%p/%p)->(%p) stub!\n", This, iface, ppDataObj);
1199
1200 return DXFILEERR_BADVALUE;
1201 }
1202
1203 static const IDirectXFileSaveObjectVtbl IDirectXFileSaveObject_Vtbl =
1204 {
1205 IDirectXFileSaveObjectImpl_QueryInterface,
1206 IDirectXFileSaveObjectImpl_AddRef,
1207 IDirectXFileSaveObjectImpl_Release,
1208 IDirectXFileSaveObjectImpl_SaveTemplates,
1209 IDirectXFileSaveObjectImpl_CreateDataObject,
1210 IDirectXFileSaveObjectImpl_SaveData
1211 };