Module: wine Branch: master Commit: 46d5973961fe2266074ac2855368c3fcf987c1b5 URL: http://source.winehq.org/git/wine.git/?a=commit;h=46d5973961fe2266074ac28553...
Author: Akihiro Sagawa sagawa.aki@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 */