[PATCH 1/2] winmm/tests: Demonstrate that WOM_DONE is not invoked reentrantly

Andrew Eikum aeikum at codeweavers.com
Thu Jan 27 10:22:59 CST 2022


From: Liam Murphy <liampm32 at gmail.com>

Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
---
 dlls/winmm/tests/wave.c | 103 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/dlls/winmm/tests/wave.c b/dlls/winmm/tests/wave.c
index 2f0c8443363..56501367190 100644
--- a/dlls/winmm/tests/wave.c
+++ b/dlls/winmm/tests/wave.c
@@ -1626,6 +1626,108 @@ static void test_fragmentsize(void)
     CloseHandle(hevent);
 }
 
+static void CALLBACK test_reentrant_callback_func(HWAVEOUT hwo, UINT uMsg,
+                                   DWORD_PTR dwInstance,
+                                   DWORD_PTR dwParam1, DWORD_PTR dwParam2)
+{
+    static int wom_done_count = 0;
+
+    switch(uMsg){
+        case WOM_OPEN:
+        case WOM_CLOSE:
+            ok(GetCurrentThreadId() == g_tid, "Got different thread ID\n");
+            break;
+
+        case WOM_DONE:
+            /* verify that WOM_DONE is not sent during the following waveOutWrite */
+            todo_wine_if(wom_done_count == 1)
+            ok(g_tid == 0, "callback called reentrantly\n");
+
+            g_tid = GetCurrentThreadId();
+
+            if(wom_done_count++ == 0){
+                Sleep(125); /* ensure 2nd header is done playing before waveOutWrite */
+                waveOutWrite(hwo, (WAVEHDR *)dwParam1, sizeof(WAVEHDR));
+            }
+
+            break;
+    }
+
+    g_tid = 0;
+    SetEvent((HANDLE)dwInstance);
+}
+
+static void test_reentrant_callback(void)
+{
+    MMRESULT rc;
+    WAVEHDR hdr[2];
+    HWAVEOUT wout;
+    WAVEFORMATEX fmt;
+    DWORD wait;
+    HANDLE hevent;
+
+    if(waveOutGetNumDevs() == 0)
+        return;
+
+    fmt.wFormatTag = WAVE_FORMAT_PCM;
+    fmt.nChannels = 2;
+    fmt.nSamplesPerSec = 44100;
+    fmt.wBitsPerSample = 16;
+    fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
+    fmt.nAvgBytesPerSec = fmt.nBlockAlign * fmt.nSamplesPerSec;
+    fmt.cbSize = sizeof(WAVEFORMATEX);
+
+    hevent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    g_tid = GetCurrentThreadId();
+
+    rc = waveOutOpen(&wout, WAVE_MAPPER, &fmt, (DWORD_PTR)test_reentrant_callback_func,
+            (DWORD_PTR)hevent, CALLBACK_FUNCTION);
+    ok(rc == MMSYSERR_NOERROR || rc == WAVERR_BADFORMAT ||
+           rc == MMSYSERR_INVALFLAG || rc == MMSYSERR_INVALPARAM,
+           "waveOutOpen(%s) failed: %s\n", dev_name(WAVE_MAPPER), wave_out_error(rc));
+    if(rc != MMSYSERR_NOERROR){
+        CloseHandle(hevent);
+        return;
+    }
+
+    wait = WaitForSingleObject(hevent, 1000);
+    ok(wait == WAIT_OBJECT_0, "wave open callback missed\n");
+
+    memset(hdr, 0, sizeof(hdr));
+    hdr[0].dwBufferLength = (fmt.nSamplesPerSec * fmt.nBlockAlign / 10);
+    hdr[1].dwBufferLength = hdr[0].dwBufferLength;
+    hdr[1].lpData = hdr[0].lpData =
+        HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, hdr[0].dwBufferLength);
+
+    rc = waveOutPrepareHeader(wout, &hdr[0], sizeof(hdr[0]));
+    ok(rc == MMSYSERR_NOERROR, "waveOutPrepareHeader failed: %s\n", wave_out_error(rc));
+
+    rc = waveOutPrepareHeader(wout, &hdr[1], sizeof(hdr[1]));
+    ok(rc == MMSYSERR_NOERROR, "waveOutPrepareHeader failed: %s\n", wave_out_error(rc));
+
+    rc = waveOutWrite(wout, &hdr[0], sizeof(hdr[0]));
+    ok(rc == MMSYSERR_NOERROR, "waveOutWrite failed: %s\n", wave_out_error(rc));
+
+    rc = waveOutWrite(wout, &hdr[1], sizeof(hdr[1]));
+    ok(rc == MMSYSERR_NOERROR, "waveOutWrite failed: %s\n", wave_out_error(rc));
+
+    wait = WaitForSingleObject(hevent, 1000);
+    ok(wait == WAIT_OBJECT_0, "header 1 callback missed\n");
+
+    wait = WaitForSingleObject(hevent, 1000);
+    ok(wait == WAIT_OBJECT_0, "header 2 callback missed\n");
+
+    wait = WaitForSingleObject(hevent, 1000);
+    ok(wait == WAIT_OBJECT_0, "header 3 callback missed\n");
+
+    g_tid = GetCurrentThreadId();
+    rc = waveOutClose(wout);
+    ok(rc == MMSYSERR_NOERROR, "waveOutClose failed: %s\n", wave_out_error(rc));
+
+    HeapFree(GetProcessHeap(), 0, hdr[0].lpData);
+    CloseHandle(hevent);
+}
+
 static void create_wav_file(char *temp_file)
 {
     WAVEFORMATEX format;
@@ -1727,5 +1829,6 @@ START_TEST(wave)
     wave_out_tests();
     test_sndPlaySound();
     test_fragmentsize();
+    test_reentrant_callback();
     test_PlaySound();
 }
-- 
2.35.0





More information about the wine-devel mailing list