[PATCH] winmm: Restrict some MCI actions to the creating thread

Andrew Eikum aeikum at codeweavers.com
Wed May 4 12:42:53 CDT 2016


This reverts commit 46d5973961fe2266074ac2855368c3fcf987c1b5 and fixes
Bug 38241 another way.

Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
---
 dlls/mciqtz32/mciqtz.c         | 199 +++++++++++------------------------------
 dlls/mciqtz32/mciqtz_private.h |  13 ---
 dlls/winmm/mci.c               |   6 ++
 dlls/winmm/tests/mci.c         |  41 +++++++++
 4 files changed, 97 insertions(+), 162 deletions(-)

diff --git a/dlls/mciqtz32/mciqtz.c b/dlls/mciqtz32/mciqtz.c
index 4e559b6..4c9074b 100644
--- a/dlls/mciqtz32/mciqtz.c
+++ b/dlls/mciqtz32/mciqtz.c
@@ -30,7 +30,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(mciqtz);
 
-static DWORD CALLBACK MCIQTZ_taskThread(LPVOID arg);
+static DWORD MCIQTZ_mciClose(UINT, DWORD, LPMCI_GENERIC_PARMS);
 static DWORD MCIQTZ_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS);
 
 /*======================================================================*
@@ -67,40 +67,6 @@ static WINE_MCIQTZ* MCIQTZ_mciGetOpenDev(UINT wDevID)
     return wma;
 }
 
-/***************************************************************************
- *                              MCIQTZ_relayTaskMessage         [internal]
- */
-static LRESULT MCIQTZ_relayTaskMessage(DWORD_PTR dwDevID, UINT wMsg,
-                                      DWORD dwFlags, LPARAM lpParms)
-{
-    WINE_MCIQTZ *wma;
-    LRESULT res;
-    HANDLE handles[2];
-    DWORD ret;
-    TRACE("(%08lX, %08x, %08x, %08lx)\n", dwDevID, wMsg, dwFlags, lpParms);
-
-    wma = MCIQTZ_mciGetOpenDev(dwDevID);
-    if (!wma)
-        return MCIERR_INVALID_DEVICE_ID;
-    EnterCriticalSection(&wma->cs);
-    wma->task.devid = dwDevID;
-    wma->task.msg   = wMsg;
-    wma->task.flags = dwFlags;
-    wma->task.parms = lpParms;
-    SetEvent(wma->task.notify);
-    handles[0] = wma->task.done;
-    handles[1] = wma->task.thread;
-    ret = WaitForMultipleObjects(sizeof(handles)/sizeof(handles[0]), handles,
-                                 FALSE, INFINITE);
-    if (ret == WAIT_OBJECT_0)
-        res = wma->task.res;
-    else
-        res = MCIERR_INTERNAL;
-    LeaveCriticalSection(&wma->cs);
-
-    return res;
-}
-
 /**************************************************************************
  *                              MCIQTZ_drvOpen                  [internal]
  */
@@ -120,25 +86,12 @@ static DWORD MCIQTZ_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp)
         return 0;
 
     wma->stop_event = CreateEventW(NULL, FALSE, FALSE, NULL);
-    wma->task.notify = CreateEventW(NULL, FALSE, FALSE, NULL);
-    if (!wma->task.notify) goto err;
-    wma->task.done = CreateEventW(NULL, FALSE, FALSE, NULL);
-    if (!wma->task.done)   goto err;
-    wma->task.thread = CreateThread(NULL, 0, MCIQTZ_taskThread, &wma->task, 0, NULL);
-    if (!wma->task.thread) goto err;
-    InitializeCriticalSection(&wma->cs);
-    wma->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINE_MCIQTZ");
     modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
     wma->wDevID = modp->wDeviceID;
     modp->wCustomCommandTable = wma->command_table = mciLoadCommandResource(MCIQTZ_hInstance, mciAviWStr, 0);
     mciSetDriverData(wma->wDevID, (DWORD_PTR)wma);
 
     return modp->wDeviceID;
-err:
-    if (wma->task.notify) CloseHandle(wma->task.notify);
-    if (wma->task.done)   CloseHandle(wma->task.done);
-    HeapFree(GetProcessHeap(), 0, wma);
-    return 0;
 }
 
 /**************************************************************************
@@ -154,16 +107,9 @@ static DWORD MCIQTZ_drvClose(DWORD dwDevID)
 
     if (wma) {
         /* finish all outstanding things */
-        MCIQTZ_relayTaskMessage(dwDevID, MCI_CLOSE_DRIVER, MCI_WAIT, 0);
+        MCIQTZ_mciClose(dwDevID, MCI_WAIT, NULL);
 
         mciFreeCommandResource(wma->command_table);
-        MCIQTZ_relayTaskMessage(dwDevID, MCI_CLOSE, MCI_WAIT, 0);
-        WaitForSingleObject(wma->task.thread, INFINITE);
-        CloseHandle(wma->task.notify);
-        CloseHandle(wma->task.done);
-        CloseHandle(wma->task.thread);
-        wma->cs.DebugInfo->Spare[0] = 0;
-        DeleteCriticalSection(&wma->cs);
         mciSetDriverData(dwDevID, 0);
         CloseHandle(wma->stop_event);
         HeapFree(GetProcessHeap(), 0, wma);
@@ -220,6 +166,9 @@ static DWORD MCIQTZ_mciOpen(UINT wDevID, DWORD dwFlags,
 
     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpOpenParms);
 
+    if(!lpOpenParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     wma = MCIQTZ_mciGetOpenDev(wDevID);
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
@@ -443,6 +392,9 @@ static DWORD MCIQTZ_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
 
     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
 
+    if(!lpParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     wma = MCIQTZ_mciGetOpenDev(wDevID);
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
@@ -500,6 +452,9 @@ static DWORD MCIQTZ_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms
 
     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
 
+    if(!lpParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     wma = MCIQTZ_mciGetOpenDev(wDevID);
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
@@ -615,6 +570,9 @@ static DWORD MCIQTZ_mciGetDevCaps(UINT wDevID, DWORD dwFlags, LPMCI_GETDEVCAPS_P
 
     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
 
+    if(!lpParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     wma = MCIQTZ_mciGetOpenDev(wDevID);
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
@@ -711,6 +669,9 @@ static DWORD MCIQTZ_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SET_PARMS lpPar
 
     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
 
+    if(!lpParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     wma = MCIQTZ_mciGetOpenDev(wDevID);
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
@@ -765,6 +726,9 @@ static DWORD MCIQTZ_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STATUS_PARMS
 
     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
 
+    if(!lpParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     wma = MCIQTZ_mciGetOpenDev(wDevID);
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
@@ -865,6 +829,9 @@ static DWORD MCIQTZ_mciWhere(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lp
 
     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
 
+    if(!lpParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     wma = MCIQTZ_mciGetOpenDev(wDevID);
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
@@ -927,6 +894,9 @@ static DWORD MCIQTZ_mciWindow(UINT wDevID, DWORD dwFlags, LPMCI_DGV_WINDOW_PARMS
 
     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
 
+    if(!lpParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
     if (dwFlags & MCI_TEST)
@@ -971,6 +941,9 @@ static DWORD MCIQTZ_mciPut(UINT wDevID, DWORD dwFlags, MCI_GENERIC_PARMS *lpParm
 
     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
 
+    if(!lpParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
 
@@ -1017,6 +990,9 @@ static DWORD MCIQTZ_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS
 
     TRACE("%04x, %08x, %p\n", wDevID, dwFlags, lpParms);
 
+    if(!lpParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     wma = MCIQTZ_mciGetOpenDev(wDevID);
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
@@ -1078,6 +1054,9 @@ static DWORD MCIQTZ_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_P
 
     TRACE("(%04x, %08x, %p)\n", wDevID, dwFlags, lpParms);
 
+    if(!lpParms)
+        return MCIERR_NULL_PARAMETER_BLOCK;
+
     wma = MCIQTZ_mciGetOpenDev(wDevID);
     if (!wma)
         return MCIERR_INVALID_DEVICE_ID;
@@ -1116,82 +1095,6 @@ static DWORD MCIQTZ_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_P
     return ret;
 }
 
-/***************************************************************************
- *                              MCIQTZ_taskThread               [internal]
- */
-static DWORD CALLBACK MCIQTZ_taskThread(LPVOID arg)
-{
-    WINE_MCIQTZ_TASK *task = (WINE_MCIQTZ_TASK *)arg;
-
-    for (;;) {
-        DWORD ret = WaitForSingleObject(task->notify, INFINITE);
-        if (ret != WAIT_OBJECT_0) {
-            TRACE("Got error (%u)\n", ret);
-            continue;
-        }
-
-        switch (task->msg) {
-        case MCI_OPEN_DRIVER:
-            task->res = MCIQTZ_mciOpen(task->devid, task->flags, (LPMCI_DGV_OPEN_PARMSW)task->parms);
-            break;
-        case MCI_CLOSE_DRIVER:
-            task->res = MCIQTZ_mciClose(task->devid, task->flags, (LPMCI_GENERIC_PARMS)task->parms);
-            break;
-        case MCI_PLAY:
-            task->res = MCIQTZ_mciPlay(task->devid, task->flags, (LPMCI_PLAY_PARMS)task->parms);
-            break;
-        case MCI_SEEK:
-            task->res = MCIQTZ_mciSeek(task->devid, task->flags, (LPMCI_SEEK_PARMS)task->parms);
-            break;
-        case MCI_STOP:
-            task->res = MCIQTZ_mciStop(task->devid, task->flags, (LPMCI_GENERIC_PARMS)task->parms);
-            break;
-        case MCI_PAUSE:
-            task->res = MCIQTZ_mciPause(task->devid, task->flags, (LPMCI_GENERIC_PARMS)task->parms);
-            break;
-        case MCI_RESUME:
-            task->res = MCIQTZ_mciResume(task->devid, task->flags, (LPMCI_GENERIC_PARMS)task->parms);
-            break;
-        case MCI_GETDEVCAPS:
-            task->res = MCIQTZ_mciGetDevCaps(task->devid, task->flags, (LPMCI_GETDEVCAPS_PARMS)task->parms);
-            break;
-        case MCI_SET:
-            task->res = MCIQTZ_mciSet(task->devid, task->flags, (LPMCI_DGV_SET_PARMS)task->parms);
-            break;
-        case MCI_STATUS:
-            task->res = MCIQTZ_mciStatus(task->devid, task->flags, (LPMCI_DGV_STATUS_PARMSW)task->parms);
-            break;
-        case MCI_WHERE:
-            task->res = MCIQTZ_mciWhere(task->devid, task->flags, (LPMCI_DGV_RECT_PARMS)task->parms);
-            break;
-        case MCI_SETAUDIO:
-            task->res = MCIQTZ_mciSetAudio(task->devid, task->flags, (LPMCI_DGV_SETAUDIO_PARMSW)task->parms);
-            break;
-        case MCI_UPDATE:
-            task->res = MCIQTZ_mciUpdate(task->devid, task->flags, (LPMCI_DGV_UPDATE_PARMS)task->parms);
-            break;
-        case MCI_WINDOW:
-            task->res = MCIQTZ_mciWindow(task->devid, task->flags, (LPMCI_DGV_WINDOW_PARMSW)task->parms);
-            break;
-        case MCI_PUT:
-            task->res = MCIQTZ_mciPut(task->devid, task->flags, (MCI_GENERIC_PARMS*)task->parms);
-            break;
-        case MCI_CLOSE:
-            /* Special internal message */
-            SetEvent(task->done);
-            goto end;
-        default:
-            FIXME("Shouldn't receive another message (%04x)\n", task->msg);
-            task->res = MCIERR_UNRECOGNIZED_COMMAND;
-            break;
-        }
-        SetEvent(task->done);
-    }
-
-end:
-    return 0;
-}
-
 /*======================================================================*
  *                          MCI QTZ entry points                        *
  *======================================================================*/
@@ -1223,27 +1126,25 @@ LRESULT CALLBACK MCIQTZ_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
         return 1;
 
     switch (wMsg) {
-        case MCI_OPEN_DRIVER:
-        case MCI_PLAY:
-        case MCI_SEEK:
-        case MCI_GETDEVCAPS:
-        case MCI_SET:
-        case MCI_STATUS:
-        case MCI_WHERE:
-            if (!dwParam2) return MCIERR_NULL_PARAMETER_BLOCK;
-            return MCIQTZ_relayTaskMessage(dwDevID, wMsg, dwParam1, dwParam2);
-        case MCI_CLOSE_DRIVER:
-        case MCI_STOP:
-        case MCI_PAUSE:
-        case MCI_RESUME:
-            return MCIQTZ_relayTaskMessage(dwDevID, wMsg, dwParam1, dwParam2);
+        case MCI_OPEN_DRIVER:   return MCIQTZ_mciOpen      (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSW)     dwParam2);
+        case MCI_CLOSE_DRIVER:  return MCIQTZ_mciClose     (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
+        case MCI_PLAY:          return MCIQTZ_mciPlay      (dwDevID, dwParam1, (LPMCI_PLAY_PARMS)          dwParam2);
+        case MCI_SEEK:          return MCIQTZ_mciSeek      (dwDevID, dwParam1, (LPMCI_SEEK_PARMS)          dwParam2);
+        case MCI_STOP:          return MCIQTZ_mciStop      (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
+        case MCI_PAUSE:         return MCIQTZ_mciPause     (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
+        case MCI_RESUME:        return MCIQTZ_mciResume    (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
+        case MCI_GETDEVCAPS:    return MCIQTZ_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)    dwParam2);
+        case MCI_SET:           return MCIQTZ_mciSet       (dwDevID, dwParam1, (LPMCI_DGV_SET_PARMS)       dwParam2);
+        case MCI_STATUS:        return MCIQTZ_mciStatus    (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSW)   dwParam2);
+        case MCI_WHERE:         return MCIQTZ_mciWhere     (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
         /* Digital Video specific */
-        case MCI_SETAUDIO:
+        case MCI_SETAUDIO:      return MCIQTZ_mciSetAudio  (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSW) dwParam2);
         case MCI_UPDATE:
+            return MCIQTZ_mciUpdate(dwDevID, dwParam1, (LPMCI_DGV_UPDATE_PARMS)dwParam2);
         case MCI_WINDOW:
+            return MCIQTZ_mciWindow(dwDevID, dwParam1, (LPMCI_DGV_WINDOW_PARMSW)dwParam2);
         case MCI_PUT:
-            if (!dwParam2) return MCIERR_NULL_PARAMETER_BLOCK;
-            return MCIQTZ_relayTaskMessage(dwDevID, wMsg, dwParam1, dwParam2);
+            return MCIQTZ_mciPut(dwDevID, dwParam1, (MCI_GENERIC_PARMS*)dwParam2);
         case MCI_RECORD:
         case MCI_INFO:
         case MCI_LOAD:
diff --git a/dlls/mciqtz32/mciqtz_private.h b/dlls/mciqtz32/mciqtz_private.h
index 6a3ca45..27939aa 100644
--- a/dlls/mciqtz32/mciqtz_private.h
+++ b/dlls/mciqtz32/mciqtz_private.h
@@ -26,17 +26,6 @@
 #include "dshow.h"
 
 typedef struct {
-    HANDLE         thread;
-    HANDLE         notify;
-    HANDLE         done;
-    DWORD          msg;
-    DWORD_PTR      devid;
-    DWORD          flags;
-    DWORD_PTR      parms;
-    LRESULT        res;
-} WINE_MCIQTZ_TASK;
-
-typedef struct {
     MCIDEVICEID    wDevID;
     BOOL           opened;
     BOOL           uninit;
@@ -54,8 +43,6 @@ typedef struct {
     HANDLE         callback;
     HANDLE         thread;
     HANDLE         stop_event;
-    CRITICAL_SECTION cs;
-    WINE_MCIQTZ_TASK task;
 } WINE_MCIQTZ;
 
 #endif  /* __WINE_PRIVATE_MCIQTZ_H */
diff --git a/dlls/winmm/mci.c b/dlls/winmm/mci.c
index b3c18820..b8adea6 100644
--- a/dlls/winmm/mci.c
+++ b/dlls/winmm/mci.c
@@ -891,6 +891,9 @@ static DWORD MCI_SendCommandFrom32(MCIDEVICEID wDevID, UINT16 wMsg, DWORD_PTR dw
     LPWINE_MCIDRIVER	wmd = MCI_GetDriver(wDevID);
 
     if (wmd) {
+        if(wmd->CreatorThread != GetCurrentThreadId())
+            return MCIERR_INVALID_DEVICE_NAME;
+
         dwRet = SendDriverMessage(wmd->hDriver, wMsg, dwParam1, dwParam2);
     }
     return dwRet;
@@ -1872,6 +1875,9 @@ static	DWORD MCI_Close(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
 	return MCIERR_INVALID_DEVICE_ID;
     }
 
+    if(wmd->CreatorThread != GetCurrentThreadId())
+        return MCIERR_INVALID_DEVICE_NAME;
+
     dwRet = MCI_SendCommandFrom32(wDevID, MCI_CLOSE_DRIVER, dwParam, (DWORD_PTR)lpParms);
 
     MCI_UnLoadMciDriver(wmd);
diff --git a/dlls/winmm/tests/mci.c b/dlls/winmm/tests/mci.c
index 14500a5..c0862c2 100644
--- a/dlls/winmm/tests/mci.c
+++ b/dlls/winmm/tests/mci.c
@@ -1391,6 +1391,46 @@ static void test_asyncWaveTypeMpegvideo(HWND hwnd)
     test_notification(hwnd,"play (aborted by close)",MCI_NOTIFY_ABORTED);
 }
 
+static DWORD CALLBACK thread_cb(void *p)
+{
+    HANDLE evt = p;
+    MCIERROR mr;
+
+    mr = mciSendStringA("play x", NULL, 0, NULL);
+    ok(mr == MCIERR_INVALID_DEVICE_NAME, "play gave: 0x%x\n", mr);
+
+    mr = mciSendStringA("close x", NULL, 0, NULL);
+    ok(mr == MCIERR_INVALID_DEVICE_NAME, "close gave: 0x%x\n", mr);
+
+    SetEvent(evt);
+
+    return 0;
+}
+
+static void test_threads(void)
+{
+    MCIERROR mr;
+    HANDLE evt;
+
+    mr = mciSendStringA("open tempfile.wav alias x", NULL, 0, NULL);
+    ok(mr == 0 || mr == ok_saved, "open gave: 0x%x\n", mr);
+    if(mr){
+        skip("Cannot open tempfile.wav for playing (%s), skipping\n", dbg_mcierr(mr));
+        return;
+    }
+
+    evt = CreateEventW(0, NULL, NULL, 0);
+
+    CloseHandle(CreateThread(NULL, 0, &thread_cb, evt, 0, NULL));
+
+    WaitForSingleObject(evt, INFINITE);
+
+    CloseHandle(evt);
+
+    mr = mciSendStringA("close x", NULL, 0, NULL);
+    ok(mr == 0, "close gave: 0x%x\n", mr);
+}
+
 START_TEST(mci)
 {
     char curdir[MAX_PATH], tmpdir[MAX_PATH];
@@ -1407,6 +1447,7 @@ START_TEST(mci)
     test_openCloseWAVE(hwnd);
     test_recordWAVE(hwnd);
     if(waveOutGetNumDevs()){
+        test_threads();
         test_playWAVE(hwnd);
         test_asyncWAVE(hwnd);
         test_AutoOpenWAVE(hwnd);
-- 
2.8.2




More information about the wine-patches mailing list