Akihiro Sagawa : mciqtz32: Guarantee that CoInitialize and CoUninitialize run on the same thread.

Alexandre Julliard julliard at wine.codeweavers.com
Tue May 12 09:08:19 CDT 2015


Module: wine
Branch: master
Commit: 46d5973961fe2266074ac2855368c3fcf987c1b5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=46d5973961fe2266074ac2855368c3fcf987c1b5

Author: Akihiro Sagawa <sagawa.aki at gmail.com>
Date:   Fri May  8 00:37:21 2015 +0900

mciqtz32: Guarantee that CoInitialize and CoUninitialize run on the same thread.

---

 dlls/mciqtz32/mciqtz.c         | 147 ++++++++++++++++++++++++++++++++++++-----
 dlls/mciqtz32/mciqtz_private.h |  13 ++++
 2 files changed, 145 insertions(+), 15 deletions(-)

diff --git a/dlls/mciqtz32/mciqtz.c b/dlls/mciqtz32/mciqtz.c
index a1c3450..479ae00 100644
--- a/dlls/mciqtz32/mciqtz.c
+++ b/dlls/mciqtz32/mciqtz.c
@@ -30,7 +30,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(mciqtz);
 
-static DWORD MCIQTZ_mciClose(UINT, DWORD, LPMCI_GENERIC_PARMS);
+static DWORD CALLBACK MCIQTZ_taskThread(LPVOID arg);
 static DWORD MCIQTZ_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS);
 
 /*======================================================================*
@@ -67,6 +67,34 @@ 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;
+    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);
+    if (WaitForSingleObject(wma->task.done, INFINITE) == WAIT_OBJECT_0)
+        res = wma->task.res;
+    else
+        res = MCIERR_INTERNAL;
+    LeaveCriticalSection(&wma->cs);
+
+    return res;
+}
+
 /**************************************************************************
  *                              MCIQTZ_drvOpen                  [internal]
  */
@@ -86,12 +114,25 @@ 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;
 }
 
 /**************************************************************************
@@ -107,9 +148,15 @@ static DWORD MCIQTZ_drvClose(DWORD dwDevID)
 
     if (wma) {
         /* finish all outstanding things */
-        MCIQTZ_mciClose(dwDevID, MCI_WAIT, NULL);
+        MCIQTZ_relayTaskMessage(dwDevID, MCI_CLOSE_DRIVER, MCI_WAIT, 0);
 
         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);
+        DeleteCriticalSection(&wma->cs);
         mciSetDriverData(dwDevID, 0);
         CloseHandle(wma->stop_event);
         HeapFree(GetProcessHeap(), 0, wma);
@@ -1021,6 +1068,76 @@ 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_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_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                        *
  *======================================================================*/
@@ -1052,22 +1169,22 @@ LRESULT CALLBACK MCIQTZ_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
         return 1;
 
     switch (wMsg) {
-        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_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);
+        case MCI_OPEN_DRIVER:
+        case MCI_CLOSE_DRIVER:
+        case MCI_PLAY:
+        case MCI_SEEK:
+        case MCI_STOP:
+        case MCI_PAUSE:
+        case MCI_GETDEVCAPS:
+        case MCI_SET:
+        case MCI_STATUS:
+        case MCI_WHERE:
+            return MCIQTZ_relayTaskMessage(dwDevID, wMsg, dwParam1, dwParam2);
         /* Digital Video specific */
-        case MCI_SETAUDIO:      return MCIQTZ_mciSetAudio  (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSW) dwParam2);
+        case MCI_SETAUDIO:
         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);
+            return MCIQTZ_relayTaskMessage(dwDevID, wMsg, dwParam1, dwParam2);
         case MCI_PUT:
         case MCI_RECORD:
         case MCI_RESUME:
diff --git a/dlls/mciqtz32/mciqtz_private.h b/dlls/mciqtz32/mciqtz_private.h
index 27939aa..6a3ca45 100644
--- a/dlls/mciqtz32/mciqtz_private.h
+++ b/dlls/mciqtz32/mciqtz_private.h
@@ -26,6 +26,17 @@
 #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;
@@ -43,6 +54,8 @@ typedef struct {
     HANDLE         callback;
     HANDLE         thread;
     HANDLE         stop_event;
+    CRITICAL_SECTION cs;
+    WINE_MCIQTZ_TASK task;
 } WINE_MCIQTZ;
 
 #endif  /* __WINE_PRIVATE_MCIQTZ_H */




More information about the wine-cvs mailing list