diff --git a/patches/dmime-PChannel-range/0001-dmime-Ensure-Channels-are-in-range-before-assignment.patch b/patches/dmime-PChannel-range/0001-dmime-Ensure-Channels-are-in-range-before-assignment.patch deleted file mode 100644 index 284ddb4d..00000000 --- a/patches/dmime-PChannel-range/0001-dmime-Ensure-Channels-are-in-range-before-assignment.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 6a4d40b86f94703f8c37264739fffc4885507ebf Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 17 Sep 2019 16:21:22 +1000 -Subject: [PATCH] dmime: Ensure Channels are in range before assignment. - -Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=17766 -Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=24740 ---- - dlls/dmime/performance.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c -index 6e4dae6be7..3bbbb3b853 100644 ---- a/dlls/dmime/performance.c -+++ b/dlls/dmime/performance.c -@@ -34,7 +34,7 @@ typedef struct IDirectMusicPerformance8Impl { - float fMasterTempo; - long lMasterVolume; - /* performance channels */ -- DMUSIC_PRIVATE_PCHANNEL PChannel[32]; -+ DMUSIC_PRIVATE_PCHANNEL PChannel[256]; - /* IDirectMusicPerformance8Impl fields */ - IDirectMusicAudioPath *pDefaultPath; - HANDLE hNotification; -@@ -624,6 +624,9 @@ static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannelBlock(IDirectMu - FIXME("(%p, %d, %p, %d): semi-stub\n", This, dwBlockNum, pPort, dwGroup-1); - if (NULL == pPort) return E_POINTER; - -+ if (dwBlockNum > ARRAY_SIZE(This->PChannel)) -+ return S_FALSE; -+ - range = 16 * dwBlockNum; - j = 0; - for (i = range; i < range+16; i++) { -@@ -633,7 +636,6 @@ static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannelBlock(IDirectMu - This->PChannel[i].channel = j; /* FIXME: should this be assigned? */ - j++; - } -- /*if (dwGroup > 2) return S_FALSE;*/ - - return S_OK; - } --- -2.17.1 - diff --git a/patches/dmime-PChannel-range/0001-dmime-Use-a-rbtree-to-store-the-PChannels-of-a-perfo.patch b/patches/dmime-PChannel-range/0001-dmime-Use-a-rbtree-to-store-the-PChannels-of-a-perfo.patch new file mode 100644 index 00000000..82c49c47 --- /dev/null +++ b/patches/dmime-PChannel-range/0001-dmime-Use-a-rbtree-to-store-the-PChannels-of-a-perfo.patch @@ -0,0 +1,208 @@ +From a6c2b72782900c1c66852a8f936886e8df194ab2 Mon Sep 17 00:00:00 2001 +From: Michael Stefaniuc +Date: Thu, 19 Dec 2019 23:20:18 +0100 +Subject: [PATCH 1/3] dmime: Use a rbtree to store the PChannels of a + performance + +The PChannel id is a 32bit, potentially random identifier and not an +array index. +Fixes also the handling of channel group "dwGroup" 0. As it is invalid +it is used to mark uninitialized PChannels. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=17766 +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=24740 +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=31562 + +Signed-off-by: Michael Stefaniuc +--- + dlls/dmime/performance.c | 109 +++++++++++++++++++++++++++------------ + 1 file changed, 75 insertions(+), 34 deletions(-) + +diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c +index 615a3f8b14..2124c1fe35 100644 +--- a/dlls/dmime/performance.c ++++ b/dlls/dmime/performance.c +@@ -19,10 +19,18 @@ + */ + + #include "dmime_private.h" ++#include "wine/heap.h" ++#include "wine/rbtree.h" + #include "dmobject.h" + + WINE_DEFAULT_DEBUG_CHANNEL(dmime); + ++struct pchannel_block { ++ DWORD block_num; /* Block 0 is PChannels 0-15, Block 1 is PChannels 16-31, etc */ ++ DMUSIC_PRIVATE_PCHANNEL pchannel[16]; ++ struct wine_rb_entry entry; ++}; ++ + typedef struct IDirectMusicPerformance8Impl { + IDirectMusicPerformance8 IDirectMusicPerformance8_iface; + LONG ref; +@@ -35,7 +43,7 @@ typedef struct IDirectMusicPerformance8Impl { + float fMasterTempo; + long lMasterVolume; + /* performance channels */ +- DMUSIC_PRIVATE_PCHANNEL PChannel[32]; ++ struct wine_rb_tree pchannels; + /* IDirectMusicPerformance8Impl fields */ + IDirectMusicAudioPath *pDefaultPath; + HANDLE hNotification; +@@ -192,6 +200,49 @@ static BOOL PostMessageToProcessMsgThread(IDirectMusicPerformance8Impl* This, UI + return PostThreadMessageA(This->procThreadId, iMsg, 0, 0); + } + ++static int pchannel_block_compare(const void *key, const struct wine_rb_entry *entry) ++{ ++ const struct pchannel_block *b = WINE_RB_ENTRY_VALUE(entry, const struct pchannel_block, entry); ++ ++ return *(DWORD *)key - b->block_num; ++} ++ ++static void pchannel_block_free(struct wine_rb_entry *entry, void *context) ++{ ++ struct pchannel_block *b = WINE_RB_ENTRY_VALUE(entry, struct pchannel_block, entry); ++ ++ heap_free(b); ++} ++ ++static struct pchannel_block *pchannel_block_set(struct wine_rb_tree *tree, DWORD block_num, ++ IDirectMusicPort *port, DWORD group, BOOL only_set_new) ++{ ++ struct pchannel_block *block; ++ struct wine_rb_entry *entry; ++ unsigned int i; ++ ++ entry = wine_rb_get(tree, &block_num); ++ if (entry) { ++ block = WINE_RB_ENTRY_VALUE(entry, struct pchannel_block, entry); ++ if (only_set_new) ++ return block; ++ } else { ++ if (!(block = heap_alloc(sizeof(*block)))) ++ return NULL; ++ block->block_num = block_num; ++ } ++ ++ for (i = 0; i < 16; ++i) { ++ block->pchannel[i].port = port; ++ block->pchannel[i].group = group; ++ block->pchannel[i].channel = i; ++ } ++ if (!entry) ++ wine_rb_put(tree, &block->block_num, &block->entry); ++ ++ return block; ++} ++ + static inline IDirectMusicPerformance8Impl *impl_from_IDirectMusicPerformance8(IDirectMusicPerformance8 *iface) + { + return CONTAINING_RECORD(iface, IDirectMusicPerformance8Impl, IDirectMusicPerformance8_iface); +@@ -236,6 +287,7 @@ static ULONG WINAPI IDirectMusicPerformance8Impl_Release(IDirectMusicPerformance + TRACE("(%p): ReleaseRef to %d\n", This, ref); + + if (ref == 0) { ++ wine_rb_destroy(&This->pchannels, pchannel_block_free, NULL); + This->safe.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->safe); + HeapFree(GetProcessHeap(), 0, This); +@@ -579,7 +631,6 @@ static HRESULT WINAPI IDirectMusicPerformance8Impl_AddPort(IDirectMusicPerforman + GUID port_guid; + IDirectMusicPort* pDefaultPort = NULL; + DMUS_PORTPARAMS params; +- int i, j; + hr = IDirectMusic8_GetDefaultPort(This->dmusic, &port_guid); + if (FAILED(hr)) return hr; + ZeroMemory(¶ms, sizeof(params)); +@@ -591,15 +642,7 @@ static HRESULT WINAPI IDirectMusicPerformance8Impl_AddPort(IDirectMusicPerforman + if (FAILED(hr)) return hr; + hr = IDirectMusicPort_Activate(pDefaultPort, TRUE); + if (FAILED(hr)) { IDirectMusicPort_Release(pDefaultPort); return hr; } +- j = 0; +- for (i = 0; i < 16; ++i) { +- if (NULL == This->PChannel[i].port) { +- This->PChannel[i].port = pPort; +- This->PChannel[i].group = 0; +- This->PChannel[i].channel = j; /* FIXME: should this be assigned? */ +- j++; +- } +- } ++ IDirectMusicPerformance8_AssignPChannelBlock(iface, 0, pDefaultPort, 1); + } else { + IDirectMusicPort_AddRef(pPort); + } +@@ -621,41 +664,38 @@ static HRESULT WINAPI IDirectMusicPerformance8Impl_RemovePort(IDirectMusicPerfor + } + + static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannelBlock(IDirectMusicPerformance8 *iface, +- DWORD dwBlockNum, IDirectMusicPort *pPort, DWORD dwGroup) ++ DWORD block_num, IDirectMusicPort *port, DWORD group) + { +- IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface); +- int i, j, range /* min value in range */; +- +- FIXME("(%p, %d, %p, %d): semi-stub\n", This, dwBlockNum, pPort, dwGroup-1); +- if (NULL == pPort) return E_POINTER; +- +- range = 16 * dwBlockNum; +- j = 0; +- for (i = range; i < range+16; i++) { +- /*TRACE("Setting PChannel[%i] to port %p, group %ld, MIDI port %i\n", i, pPort, dwGroup-1, j); */ +- This->PChannel[i].port = pPort; +- This->PChannel[i].group = dwGroup - 1; /* first index is always zero */ +- This->PChannel[i].channel = j; /* FIXME: should this be assigned? */ +- j++; +- } +- /*if (dwGroup > 2) return S_FALSE;*/ ++ IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface); + +- return S_OK; ++ FIXME("(%p, %d, %p, %d): semi-stub\n", This, block_num, port, group); ++ ++ if (!port) ++ return E_POINTER; ++ if (block_num > MAXDWORD / 16) ++ return E_INVALIDARG; ++ ++ pchannel_block_set(&This->pchannels, block_num, port, group, FALSE); ++ ++ return S_OK; + } + + static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannel(IDirectMusicPerformance8 *iface, +- DWORD PChannel, IDirectMusicPort *port, DWORD group, DWORD MChannel) ++ DWORD pchannel, IDirectMusicPort *port, DWORD group, DWORD channel) + { + IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface); ++ struct pchannel_block *block; + +- TRACE("(%p)->(%d, %p, %d, %d)\n", This, PChannel, port, group, MChannel); ++ FIXME("(%p)->(%d, %p, %d, %d) semi-stub\n", This, pchannel, port, group, channel); + + if (!port) + return E_POINTER; + +- This->PChannel[PChannel].port = port; +- This->PChannel[PChannel].group = group; +- This->PChannel[PChannel].channel = MChannel; ++ block = pchannel_block_set(&This->pchannels, pchannel / 16, port, 0, TRUE); ++ if (block) { ++ block->pchannel[pchannel % 16].group = group; ++ block->pchannel[pchannel % 16].channel = channel; ++ } + + return S_OK; + } +@@ -1211,6 +1251,7 @@ HRESULT WINAPI create_dmperformance(REFIID lpcGUID, void **ppobj) + obj->pDefaultPath = NULL; + InitializeCriticalSection(&obj->safe); + obj->safe.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectMusicPerformance8Impl*->safe"); ++ wine_rb_init(&obj->pchannels, pchannel_block_compare); + + obj->rtLatencyTime = 100; /* 100 ms TO FIX */ + obj->dwBumperLength = 50; /* 50 ms default */ +-- +2.17.1 + diff --git a/patches/dmime-PChannel-range/0002-dmime-tests-Add-PChannel-tests.patch b/patches/dmime-PChannel-range/0002-dmime-tests-Add-PChannel-tests.patch new file mode 100644 index 00000000..8df18e1f --- /dev/null +++ b/patches/dmime-PChannel-range/0002-dmime-tests-Add-PChannel-tests.patch @@ -0,0 +1,173 @@ +From bc158e53fb1df19ee8029c899bf2801f4a99ef33 Mon Sep 17 00:00:00 2001 +From: Michael Stefaniuc +Date: Thu, 19 Dec 2019 23:20:19 +0100 +Subject: [PATCH 2/3] dmime/tests: Add PChannel tests + +Signed-off-by: Michael Stefaniuc +--- + dlls/dmime/tests/performance.c | 126 ++++++++++++++++++++++++++++++++- + 1 file changed, 124 insertions(+), 2 deletions(-) + +diff --git a/dlls/dmime/tests/performance.c b/dlls/dmime/tests/performance.c +index 1d17e5200e..4c340252aa 100644 +--- a/dlls/dmime/tests/performance.c ++++ b/dlls/dmime/tests/performance.c +@@ -100,10 +100,18 @@ static HRESULT test_InitAudio(void) + return hr; + + port = NULL; ++ hr = IDirectMusicPerformance8_PChannelInfo(performance, 128, &port, NULL, NULL); ++ todo_wine ok(hr == E_INVALIDARG, "PChannelInfo failed, got %08x\n", hr); ++ hr = IDirectMusicPerformance8_PChannelInfo(performance, 127, &port, NULL, NULL); ++ ok(hr == S_OK, "PChannelInfo failed, got %08x\n", hr); + hr = IDirectMusicPerformance8_PChannelInfo(performance, 0, &port, NULL, NULL); +- ok(hr == S_OK, "Failed to call PChannelInfo (%x)\n", hr); ++ ok(hr == S_OK, "PChannelInfo failed, got %08x\n", hr); + ok(port != NULL, "IDirectMusicPort not set\n"); +- if (hr == S_OK && port != NULL) ++ hr = IDirectMusicPerformance8_AssignPChannel(performance, 0, port, 0, 0); ++ todo_wine ok(hr == DMUS_E_AUDIOPATHS_IN_USE, "AssignPChannel failed (%08x)\n", hr); ++ hr = IDirectMusicPerformance8_AssignPChannelBlock(performance, 0, port, 0); ++ todo_wine ok(hr == DMUS_E_AUDIOPATHS_IN_USE, "AssignPChannelBlock failed (%08x)\n", hr); ++ if (port) + IDirectMusicPort_Release(port); + + hr = IDirectMusicPerformance8_GetDefaultAudioPath(performance, &path); +@@ -120,6 +128,8 @@ static HRESULT test_InitAudio(void) + create_performance(&performance, NULL, NULL, FALSE); + hr = IDirectMusicPerformance8_InitAudio(performance, NULL, NULL, NULL, 0, 64, 0, NULL); + ok(hr == S_OK, "InitAudio failed: %08x\n", hr); ++ hr = IDirectMusicPerformance8_PChannelInfo(performance, 0, &port, NULL, NULL); ++ todo_wine ok(hr == E_INVALIDARG, "PChannelInfo failed, got %08x\n", hr); + destroy_performance(performance, NULL, NULL); + + /* Refcounts for auto generated dmusic and dsound */ +@@ -322,6 +332,117 @@ static void test_createport(void) + IDirectMusicPerformance_Release(perf); + } + ++static void test_pchannel(void) ++{ ++ IDirectMusicPerformance8 *perf; ++ IDirectMusicPort *port = NULL, *port2; ++ DWORD channel, group; ++ unsigned int i; ++ HRESULT hr; ++ ++ create_performance(&perf, NULL, NULL, FALSE); ++ hr = IDirectMusicPerformance8_Init(perf, NULL, NULL, NULL); ++ ok(hr == S_OK, "Init failed: %08x\n", hr); ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, 0, &port, NULL, NULL); ++ todo_wine ok(hr == E_INVALIDARG && !port, "PChannelInfo failed, got %08x, %p\n", hr, port); ++ ++ /* Add default port. Sets PChannels 0-15 to the corresponding channels in group 1 */ ++ hr = IDirectMusicPerformance8_AddPort(perf, NULL); ++ ok(hr == S_OK, "AddPort of default port failed: %08x\n", hr); ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, 0, NULL, NULL, NULL); ++ ok(hr == S_OK, "PChannelInfo failed, got %08x\n", hr); ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, 0, &port, NULL, NULL); ++ ok(hr == S_OK && port, "PChannelInfo failed, got %08x, %p\n", hr, port); ++ for (i = 1; i < 16; i++) { ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel); ++ todo_wine ok(hr == S_OK && port == port2 && group == 1 && channel == i, ++ "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); ++ IDirectMusicPort_Release(port2); ++ } ++ ++ /* Unset PChannels fail to retrieve */ ++ todo_wine { ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, 16, &port2, NULL, NULL); ++ ok(hr == E_INVALIDARG, "PChannelInfo failed, got %08x, %p\n", hr, port); ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, MAXDWORD - 16, &port2, NULL, NULL); ++ ok(hr == E_INVALIDARG, "PChannelInfo failed, got %08x, %p\n", hr, port); ++ } ++ ++ /* Channel group 0 can be set just fine */ ++ hr = IDirectMusicPerformance8_AssignPChannel(perf, 0, port, 0, 0); ++ ok(hr == S_OK, "AssignPChannel failed, got %08x\n", hr); ++ hr = IDirectMusicPerformance8_AssignPChannelBlock(perf, 0, port, 0); ++ ok(hr == S_OK, "AssignPChannelBlock failed, got %08x\n", hr); ++ for (i = 1; i < 16; i++) { ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel); ++ todo_wine ok(hr == S_OK && port == port2 && group == 0 && channel == i, ++ "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); ++ IDirectMusicPort_Release(port2); ++ } ++ ++ /* Last PChannel Block can be set only individually but not read */ ++ hr = IDirectMusicPerformance8_AssignPChannel(perf, MAXDWORD, port, 0, 3); ++ ok(hr == S_OK, "AssignPChannel failed, got %08x\n", hr); ++ port2 = (IDirectMusicPort *)0xdeadbeef; ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, MAXDWORD, &port2, NULL, NULL); ++ todo_wine ok(hr == E_INVALIDARG && port2 == (IDirectMusicPort *)0xdeadbeef, ++ "PChannelInfo failed, got %08x, %p\n", hr, port2); ++ hr = IDirectMusicPerformance8_AssignPChannelBlock(perf, MAXDWORD, port, 0); ++ ok(hr == E_INVALIDARG, "AssignPChannelBlock failed, got %08x\n", hr); ++ hr = IDirectMusicPerformance8_AssignPChannelBlock(perf, MAXDWORD / 16, port, 1); ++ todo_wine ok(hr == E_INVALIDARG, "AssignPChannelBlock failed, got %08x\n", hr); ++ for (i = MAXDWORD - 15; i < MAXDWORD; i++) { ++ hr = IDirectMusicPerformance8_AssignPChannel(perf, i, port, 0, 0); ++ ok(hr == S_OK, "AssignPChannel failed, got %08x\n", hr); ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, NULL, NULL); ++ todo_wine ok(hr == E_INVALIDARG && port2 == (IDirectMusicPort *)0xdeadbeef, ++ "PChannelInfo failed, got %08x, %p\n", hr, port2); ++ } ++ ++ /* Second to last PChannel Block can be set only individually and read */ ++ hr = IDirectMusicPerformance8_AssignPChannelBlock(perf, MAXDWORD / 16 - 1, port, 1); ++ todo_wine ok(hr == E_INVALIDARG, "AssignPChannelBlock failed, got %08x\n", hr); ++ for (i = MAXDWORD - 31; i < MAXDWORD - 15; i++) { ++ hr = IDirectMusicPerformance8_AssignPChannel(perf, i, port, 1, 7); ++ ok(hr == S_OK, "AssignPChannel failed, got %08x\n", hr); ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel); ++ todo_wine ok(hr == S_OK && port2 == port && group == 1 && channel == 7, ++ "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); ++ IDirectMusicPort_Release(port2); ++ } ++ ++ /* Third to last PChannel Block behaves normal */ ++ hr = IDirectMusicPerformance8_AssignPChannelBlock(perf, MAXDWORD / 16 - 2, port, 0); ++ ok(hr == S_OK, "AssignPChannelBlock failed, got %08x\n", hr); ++ for (i = MAXDWORD - 47; i < MAXDWORD - 31; i++) { ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel); ++ todo_wine ok(hr == S_OK && port2 == port && group == 0 && channel == i % 16, ++ "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); ++ IDirectMusicPort_Release(port2); ++ } ++ ++ /* One PChannel set in a Block, rest is initialized too */ ++ hr = IDirectMusicPerformance8_AssignPChannel(perf, 4711, port, 1, 13); ++ ok(hr == S_OK, "AssignPChannel failed, got %08x\n", hr); ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, 4711, &port2, &group, &channel); ++ todo_wine ok(hr == S_OK && port2 == port && group == 1 && channel == 13, ++ "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); ++ IDirectMusicPort_Release(port2); ++ group = channel = 0xdeadbeef; ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, 4712, &port2, &group, &channel); ++ todo_wine ok(hr == S_OK && port2 == port && group == 0 && channel == 8, ++ "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); ++ IDirectMusicPort_Release(port2); ++ group = channel = 0xdeadbeef; ++ hr = IDirectMusicPerformance8_PChannelInfo(perf, 4719, &port2, &group, &channel); ++ todo_wine ok(hr == S_OK && port2 == port && group == 0 && channel == 15, ++ "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); ++ IDirectMusicPort_Release(port2); ++ ++ IDirectMusicPort_Release(port); ++ destroy_performance(perf, NULL, NULL); ++} ++ + static void test_COM(void) + { + IDirectMusicPerformance *dmp = (IDirectMusicPerformance*)0xdeadbeef; +@@ -504,6 +625,7 @@ START_TEST( performance ) + + test_COM(); + test_createport(); ++ test_pchannel(); + test_notification_type(); + + CoUninitialize(); +-- +2.17.1 + diff --git a/patches/dmime-PChannel-range/0003-dmime-Implement-IDirectMusicPerformance8_PChannelInf.patch b/patches/dmime-PChannel-range/0003-dmime-Implement-IDirectMusicPerformance8_PChannelInf.patch new file mode 100644 index 00000000..a012532e --- /dev/null +++ b/patches/dmime-PChannel-range/0003-dmime-Implement-IDirectMusicPerformance8_PChannelInf.patch @@ -0,0 +1,174 @@ +From a649a14676b8b57019021021f9b1c3474c88f129 Mon Sep 17 00:00:00 2001 +From: Michael Stefaniuc +Date: Thu, 19 Dec 2019 23:20:20 +0100 +Subject: [PATCH 3/3] dmime: Implement IDirectMusicPerformance8_PChannelInfo() + +NOT FOR THE FREEZE ==> DEFER + +Not needed for the bugs referenced in patch 1 but to validate the tests +from patch 2. + +Signed-off-by: Michael Stefaniuc +--- + dlls/dmime/performance.c | 31 ++++++++++++++++++++++--------- + dlls/dmime/tests/performance.c | 24 +++++++++++------------- + 2 files changed, 33 insertions(+), 22 deletions(-) + +diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c +index 2124c1fe35..9f489f5e36 100644 +--- a/dlls/dmime/performance.c ++++ b/dlls/dmime/performance.c +@@ -701,18 +701,29 @@ static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannel(IDirectMusicPe + } + + static HRESULT WINAPI IDirectMusicPerformance8Impl_PChannelInfo(IDirectMusicPerformance8 *iface, +- DWORD PChannel, IDirectMusicPort **port, DWORD *group, DWORD *MChannel) ++ DWORD pchannel, IDirectMusicPort **port, DWORD *group, DWORD *channel) + { + IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface); +- DMUS_PORTPARAMS8 port_params; +- GUID default_port; ++ struct pchannel_block *block; ++ struct wine_rb_entry *entry; ++ DWORD block_num = pchannel / 16; ++ unsigned int index = pchannel % 16; + +- FIXME("(%p)->(%d, %p, %p, %p): stub\n", This, PChannel, port, group, MChannel); ++ TRACE("(%p)->(%d, %p, %p, %p)\n", This, pchannel, port, group, channel); + +- port_params.dwSize = sizeof(DMUS_PORTPARAMS8); +- port_params.dwValidParams = 0; +- IDirectMusic8_GetDefaultPort(This->dmusic, &default_port); +- IDirectMusic8_CreatePort(This->dmusic, &default_port, &port_params, port, NULL); ++ entry = wine_rb_get(&This->pchannels, &block_num); ++ if (!entry) ++ return E_INVALIDARG; ++ block = WINE_RB_ENTRY_VALUE(entry, struct pchannel_block, entry); ++ ++ if (port) { ++ *port = block->pchannel[index].port; ++ IDirectMusicPort_AddRef(*port); ++ } ++ if (group) ++ *group = block->pchannel[index].group; ++ if (channel) ++ *channel = block->pchannel[index].channel; + + return S_OK; + } +@@ -1102,7 +1113,9 @@ static HRESULT WINAPI IDirectMusicPerformance8Impl_CreateStandardAudioPath(IDire + return E_INVALIDARG; + } + +- /* FIXME: Should we create one secondary buffer for each PChannel? */ ++ /* FIXME: Create a proper port with enough dwGroups for the PChannels */ ++ IDirectMusicPerformance8_AddPort(iface, NULL); ++ + hr = IDirectSound_CreateSoundBuffer(This->dsound, &desc, &buffer, NULL); + if (FAILED(hr)) + return DSERR_BUFFERLOST; +diff --git a/dlls/dmime/tests/performance.c b/dlls/dmime/tests/performance.c +index 4c340252aa..adc20224c0 100644 +--- a/dlls/dmime/tests/performance.c ++++ b/dlls/dmime/tests/performance.c +@@ -101,9 +101,9 @@ static HRESULT test_InitAudio(void) + + port = NULL; + hr = IDirectMusicPerformance8_PChannelInfo(performance, 128, &port, NULL, NULL); +- todo_wine ok(hr == E_INVALIDARG, "PChannelInfo failed, got %08x\n", hr); ++ ok(hr == E_INVALIDARG, "PChannelInfo failed, got %08x\n", hr); + hr = IDirectMusicPerformance8_PChannelInfo(performance, 127, &port, NULL, NULL); +- ok(hr == S_OK, "PChannelInfo failed, got %08x\n", hr); ++ todo_wine ok(hr == S_OK, "PChannelInfo failed, got %08x\n", hr); + hr = IDirectMusicPerformance8_PChannelInfo(performance, 0, &port, NULL, NULL); + ok(hr == S_OK, "PChannelInfo failed, got %08x\n", hr); + ok(port != NULL, "IDirectMusicPort not set\n"); +@@ -129,7 +129,7 @@ static HRESULT test_InitAudio(void) + hr = IDirectMusicPerformance8_InitAudio(performance, NULL, NULL, NULL, 0, 64, 0, NULL); + ok(hr == S_OK, "InitAudio failed: %08x\n", hr); + hr = IDirectMusicPerformance8_PChannelInfo(performance, 0, &port, NULL, NULL); +- todo_wine ok(hr == E_INVALIDARG, "PChannelInfo failed, got %08x\n", hr); ++ ok(hr == E_INVALIDARG, "PChannelInfo failed, got %08x\n", hr); + destroy_performance(performance, NULL, NULL); + + /* Refcounts for auto generated dmusic and dsound */ +@@ -344,7 +344,7 @@ static void test_pchannel(void) + hr = IDirectMusicPerformance8_Init(perf, NULL, NULL, NULL); + ok(hr == S_OK, "Init failed: %08x\n", hr); + hr = IDirectMusicPerformance8_PChannelInfo(perf, 0, &port, NULL, NULL); +- todo_wine ok(hr == E_INVALIDARG && !port, "PChannelInfo failed, got %08x, %p\n", hr, port); ++ ok(hr == E_INVALIDARG && !port, "PChannelInfo failed, got %08x, %p\n", hr, port); + + /* Add default port. Sets PChannels 0-15 to the corresponding channels in group 1 */ + hr = IDirectMusicPerformance8_AddPort(perf, NULL); +@@ -355,18 +355,16 @@ static void test_pchannel(void) + ok(hr == S_OK && port, "PChannelInfo failed, got %08x, %p\n", hr, port); + for (i = 1; i < 16; i++) { + hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel); +- todo_wine ok(hr == S_OK && port == port2 && group == 1 && channel == i, ++ ok(hr == S_OK && port == port2 && group == 1 && channel == i, + "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); + IDirectMusicPort_Release(port2); + } + + /* Unset PChannels fail to retrieve */ +- todo_wine { + hr = IDirectMusicPerformance8_PChannelInfo(perf, 16, &port2, NULL, NULL); + ok(hr == E_INVALIDARG, "PChannelInfo failed, got %08x, %p\n", hr, port); + hr = IDirectMusicPerformance8_PChannelInfo(perf, MAXDWORD - 16, &port2, NULL, NULL); + ok(hr == E_INVALIDARG, "PChannelInfo failed, got %08x, %p\n", hr, port); +- } + + /* Channel group 0 can be set just fine */ + hr = IDirectMusicPerformance8_AssignPChannel(perf, 0, port, 0, 0); +@@ -375,7 +373,7 @@ static void test_pchannel(void) + ok(hr == S_OK, "AssignPChannelBlock failed, got %08x\n", hr); + for (i = 1; i < 16; i++) { + hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel); +- todo_wine ok(hr == S_OK && port == port2 && group == 0 && channel == i, ++ ok(hr == S_OK && port == port2 && group == 0 && channel == i, + "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); + IDirectMusicPort_Release(port2); + } +@@ -406,7 +404,7 @@ static void test_pchannel(void) + hr = IDirectMusicPerformance8_AssignPChannel(perf, i, port, 1, 7); + ok(hr == S_OK, "AssignPChannel failed, got %08x\n", hr); + hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel); +- todo_wine ok(hr == S_OK && port2 == port && group == 1 && channel == 7, ++ ok(hr == S_OK && port2 == port && group == 1 && channel == 7, + "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); + IDirectMusicPort_Release(port2); + } +@@ -416,7 +414,7 @@ static void test_pchannel(void) + ok(hr == S_OK, "AssignPChannelBlock failed, got %08x\n", hr); + for (i = MAXDWORD - 47; i < MAXDWORD - 31; i++) { + hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel); +- todo_wine ok(hr == S_OK && port2 == port && group == 0 && channel == i % 16, ++ ok(hr == S_OK && port2 == port && group == 0 && channel == i % 16, + "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); + IDirectMusicPort_Release(port2); + } +@@ -425,17 +423,17 @@ static void test_pchannel(void) + hr = IDirectMusicPerformance8_AssignPChannel(perf, 4711, port, 1, 13); + ok(hr == S_OK, "AssignPChannel failed, got %08x\n", hr); + hr = IDirectMusicPerformance8_PChannelInfo(perf, 4711, &port2, &group, &channel); +- todo_wine ok(hr == S_OK && port2 == port && group == 1 && channel == 13, ++ ok(hr == S_OK && port2 == port && group == 1 && channel == 13, + "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); + IDirectMusicPort_Release(port2); + group = channel = 0xdeadbeef; + hr = IDirectMusicPerformance8_PChannelInfo(perf, 4712, &port2, &group, &channel); +- todo_wine ok(hr == S_OK && port2 == port && group == 0 && channel == 8, ++ ok(hr == S_OK && port2 == port && group == 0 && channel == 8, + "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); + IDirectMusicPort_Release(port2); + group = channel = 0xdeadbeef; + hr = IDirectMusicPerformance8_PChannelInfo(perf, 4719, &port2, &group, &channel); +- todo_wine ok(hr == S_OK && port2 == port && group == 0 && channel == 15, ++ ok(hr == S_OK && port2 == port && group == 0 && channel == 15, + "PChannelInfo failed, got %08x, %p, %u, %u\n", hr, port2, group, channel); + IDirectMusicPort_Release(port2); + +-- +2.17.1 + diff --git a/patches/dmime-PChannel-range/definition b/patches/dmime-PChannel-range/definition index a9fcc6a3..b68b54e2 100644 --- a/patches/dmime-PChannel-range/definition +++ b/patches/dmime-PChannel-range/definition @@ -1,2 +1,3 @@ Fixes: [17766] Empire Earth crashes on start without native directmusic Fixes: [24740] Trinklet Supreme crashes on startup +Fixes: [31562] Stop crash when using lithtech game engine. diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 5866ffa4..3bcaa5fd 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -3166,14 +3166,19 @@ fi # | This patchset fixes the following Wine bugs: # | * [#17766] Empire Earth crashes on start without native directmusic # | * [#24740] Trinklet Supreme crashes on startup +# | * [#31562] Stop crash when using lithtech game engine. # | # | Modified files: -# | * dlls/dmime/performance.c +# | * dlls/dmime/performance.c, dlls/dmime/tests/performance.c # | if test "$enable_dmime_PChannel_range" -eq 1; then - patch_apply dmime-PChannel-range/0001-dmime-Ensure-Channels-are-in-range-before-assignment.patch + patch_apply dmime-PChannel-range/0001-dmime-Use-a-rbtree-to-store-the-PChannels-of-a-perfo.patch + patch_apply dmime-PChannel-range/0002-dmime-tests-Add-PChannel-tests.patch + patch_apply dmime-PChannel-range/0003-dmime-Implement-IDirectMusicPerformance8_PChannelInf.patch ( - printf '%s\n' '+ { "Alistair Leslie-Hughes", "dmime: Ensure Channels are in range before assignment.", 1 },'; + printf '%s\n' '+ { "Michael Stefaniuc", "dmime: Use a rbtree to store the PChannels of a performance.", 1 },'; + printf '%s\n' '+ { "Michael Stefaniuc", "dmime/tests: Add PChannel tests.", 1 },'; + printf '%s\n' '+ { "Michael Stefaniuc", "dmime: Implement IDirectMusicPerformance8_PChannelInfo().", 1 },'; ) >> "$patchlist" fi