From: Joerg Rueppel <joru.ossdev@gmail.com> The original d3dxof.dll does it. Space Empires V writes into the returned buffers for some reason and overwrites adjacent data. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49722 --- dlls/d3dxof/d3dxof.c | 13 ++++++-- dlls/d3dxof/d3dxof_private.h | 1 + dlls/d3dxof/tests/d3dxof.c | 60 ++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/dlls/d3dxof/d3dxof.c b/dlls/d3dxof/d3dxof.c index 250af38c895..c30e92ae699 100644 --- a/dlls/d3dxof/d3dxof.c +++ b/dlls/d3dxof/d3dxof.c @@ -551,6 +551,7 @@ static ULONG WINAPI IDirectXFileDataImpl_Release(IDirectXFileData *iface) if (!data->level && !data->from_ref) { HeapFree(GetProcessHeap(), 0, data->pstrings); + HeapFree(GetProcessHeap(), 0, data->pdata_user_copy); if (data->pobj) { HeapFree(GetProcessHeap(), 0, data->pobj->pdata); @@ -615,6 +616,14 @@ static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCS if (!pcbSize || !ppvData) return DXFILEERR_BADVALUE; + if (!This->pdata_user_copy && This->pobj->root->pdata && This->pobj->size > 0) + { + This->pdata_user_copy = HeapAlloc(GetProcessHeap(), 0, This->pobj->size); + if (!This->pdata_user_copy) + return DXFILEERR_BADALLOC; + memcpy(This->pdata_user_copy, This->pobj->root->pdata + This->pobj->pos_data, This->pobj->size); + } + if (szMember) { ULONG i; @@ -627,12 +636,12 @@ static HRESULT WINAPI IDirectXFileDataImpl_GetData(IDirectXFileData* iface, LPCS return DXFILEERR_BADDATAREFERENCE; } *pcbSize = This->pobj->members[i].size; - *ppvData = This->pobj->root->pdata + This->pobj->members[i].start; + *ppvData = This->pdata_user_copy + (This->pobj->members[i].start - This->pobj->pos_data); } else { *pcbSize = This->pobj->size; - *ppvData = This->pobj->root->pdata + This->pobj->pos_data; + *ppvData = This->pdata_user_copy; } return DXFILE_OK; diff --git a/dlls/d3dxof/d3dxof_private.h b/dlls/d3dxof/d3dxof_private.h index 9f208dfc9cb..d48a4a5d665 100644 --- a/dlls/d3dxof/d3dxof_private.h +++ b/dlls/d3dxof/d3dxof_private.h @@ -104,6 +104,7 @@ typedef struct { BOOL from_ref; ULONG level; LPBYTE pstrings; + LPBYTE pdata_user_copy; } IDirectXFileDataImpl; typedef struct { diff --git a/dlls/d3dxof/tests/d3dxof.c b/dlls/d3dxof/tests/d3dxof.c index b7b1b1cc502..68fb5cea915 100644 --- a/dlls/d3dxof/tests/d3dxof.c +++ b/dlls/d3dxof/tests/d3dxof.c @@ -366,6 +366,8 @@ static char object_complex[] = "3;;;, 0;;;, 1;;;, 2;;;,\n" "3;;;, 1;;;, 2;;;, 3;;;,\n" "3;;;, 3;;;, 1;;;, 2;;;,\n" +/* for heap alloc test */ +"Vector{0.0;;;, 0.0;;;, 0.0;;;}\n" "}\n"; static char template_using_index_color_lower[] = @@ -1005,6 +1007,63 @@ static void test_complex_object(void) IDirectXFile_Release(dxfile); } +static void test_getdata_separate_heap_alloc(void) +{ + IDirectXFile *dxfile = NULL; + IDirectXFileEnumObject *enum_object; + IDirectXFileData *root_data, *child_data; + IDirectXFileObject *child_obj; + DXFILELOADMEMORY load_info; + HRESULT hr; + size_t distance; + + DWORD root_size, child_size; + void *root_ptr, *child_ptr; + + if (!pDirectXFileCreate) + { + win_skip("DirectXFileCreate is not available\n"); + return; + } + + hr = pDirectXFileCreate(&dxfile); + ok(hr == DXFILE_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirectXFile_RegisterTemplates(dxfile, templates_complex_object, sizeof(templates_complex_object) - 1); + ok(hr == DXFILE_OK, "Unexpected hr %#lx.\n", hr); + + load_info.lpMemory = object_complex; + load_info.dSize = sizeof(object_complex) - 1; + hr = IDirectXFile_CreateEnumObject(dxfile, &load_info, DXFILELOAD_FROMMEMORY, &enum_object); + ok(hr == DXFILE_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirectXFileEnumObject_GetNextDataObject(enum_object, &root_data); + ok(hr == DXFILE_OK, "Unexpected hr %#lx.\n", hr); + hr = IDirectXFileData_GetData(root_data, NULL, &root_size, &root_ptr); + ok(hr == DXFILE_OK, "Unexpected hr %#lx.\n", hr); + ok(root_size == 104, "Unexpected root size %lu.\n", root_size); + + hr = IDirectXFileData_GetNextObject(root_data, &child_obj); + ok(hr == DXFILE_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirectXFileObject_QueryInterface(child_obj, &IID_IDirectXFileData, (void** )&child_data); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDirectXFileData_GetData(child_data, NULL, &child_size, &child_ptr); + ok(hr == DXFILE_OK, "Unexpected hr %#lx.\n", hr); + ok(child_size == 12, "Unexpected child size %lu.\n", child_size); + + distance = (root_ptr > child_ptr) ? (BYTE*) root_ptr - (BYTE*) child_ptr : (BYTE*) child_ptr - (BYTE*) root_ptr; + ok(distance > root_size + child_size, "Unexpected distance %Iu.\n", distance); + + IDirectXFileData_Release(child_data); + IDirectXFileObject_Release(child_obj); + + IDirectXFileData_Release(root_data); + IDirectXFileEnumObject_Release(enum_object); + IDirectXFile_Release(dxfile); +} + static void test_standard_templates(void) { IDirectXFile *dxfile = NULL; @@ -1061,6 +1120,7 @@ START_TEST(d3dxof) test_syntax(); test_syntax_semicolon_comma(); test_complex_object(); + test_getdata_separate_heap_alloc(); test_standard_templates(); test_type_index_color(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10278