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