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