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