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