MCI #5: Much improved mciavi driver

Dmitry Timoshkov dmitry at baikal.ru
Tue Dec 30 10:48:19 CST 2003


Hello,

Please apply after MCI #4.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Much improved mciavi driver. Fixed synchronization, RIFF file
    with many streams parsing, added support for some MCI_PUT and
    MCI_WHERE cases.

diff -u cvs/hq/wine/dlls/winmm/mciavi/info.c wine/dlls/winmm/mciavi/info.c
--- cvs/hq/wine/dlls/winmm/mciavi/info.c        2003-12-30 22:44:20.000000000 +0800
+++ wine/dlls/winmm/mciavi/info.c       2003-12-30 23:28:23.000000000 +0800
@@ -82,6 +82,8 @@ DWORD MCIAVI_mciGetDevCaps(UINT wDevID, 
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
+
     if (dwFlags & MCI_GETDEVCAPS_ITEM) {
        switch (lpParms->dwItem) {
        case MCI_GETDEVCAPS_DEVICE_TYPE:
@@ -131,12 +133,15 @@ DWORD     MCIAVI_mciGetDevCaps(UINT wDevID, 
            break;
        default:
            FIXME("Unknown capability (%08lx) !\n", lpParms->dwItem);
-           return MCIERR_UNRECOGNIZED_COMMAND;
+           ret = MCIERR_UNRECOGNIZED_COMMAND;
+            break;
        }
     } else {
        WARN("No GetDevCaps-Item !\n");
-       return MCIERR_UNRECOGNIZED_COMMAND;
+       ret = MCIERR_UNRECOGNIZED_COMMAND;
     }
+
+    LeaveCriticalSection(&wma->cs);
     return ret;
 }
 
@@ -155,15 +160,18 @@ DWORD     MCIAVI_mciInfo(UINT wDevID, DWORD 
 
     TRACE("buf=%p, len=%lu\n", lpParms->lpstrReturn, lpParms->dwRetSize);
 
+    EnterCriticalSection(&wma->cs);
+
     switch (dwFlags) {
     case MCI_INFO_PRODUCT:
        str = "Wine's AVI player";
        break;
     case MCI_INFO_FILE:
-       str = wma->openParms.lpstrElementName;
+       str = wma->lpFileName;
        break;
     default:
        WARN("Don't know this info command (%lu)\n", dwFlags);
+        LeaveCriticalSection(&wma->cs);
        return MCIERR_UNRECOGNIZED_COMMAND;
     }
     if (str) {
@@ -175,6 +183,8 @@ DWORD       MCIAVI_mciInfo(UINT wDevID, DWORD 
     } else {
        lpParms->lpstrReturn[0] = 0;
     }
+
+    LeaveCriticalSection(&wma->cs);
     return ret;
 }
 
@@ -188,6 +198,8 @@ DWORD       MCIAVI_mciSet(UINT wDevID, DWORD d
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
+
     if (dwFlags & MCI_SET_TIME_FORMAT) {
        switch (lpParms->dwTimeFormat) {
        case MCI_FORMAT_MILLISECONDS:
@@ -200,18 +212,22 @@ DWORD     MCIAVI_mciSet(UINT wDevID, DWORD d
            break;
        default:
            WARN("Bad time format %lu!\n", lpParms->dwTimeFormat);
+            LeaveCriticalSection(&wma->cs);
            return MCIERR_BAD_TIME_FORMAT;
        }
     }
 
     if (dwFlags & MCI_SET_DOOR_OPEN) {
        TRACE("No support for door open !\n");
+        LeaveCriticalSection(&wma->cs);
        return MCIERR_UNSUPPORTED_FUNCTION;
     }
     if (dwFlags & MCI_SET_DOOR_CLOSED) {
        TRACE("No support for door close !\n");
+        LeaveCriticalSection(&wma->cs);
        return MCIERR_UNSUPPORTED_FUNCTION;
     }
+
     if (dwFlags & MCI_SET_ON) {
        char    buffer[256];
 
@@ -302,6 +318,7 @@ DWORD       MCIAVI_mciSet(UINT wDevID, DWORD d
        FIXME("Setting speed to %ld\n", lpParms->dwSpeed);
     }
 
+    LeaveCriticalSection(&wma->cs);
     return 0;
 }
 
@@ -316,6 +333,8 @@ DWORD       MCIAVI_mciStatus(UINT wDevID, DWOR
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
+
     if (dwFlags & MCI_STATUS_ITEM) {
        switch (lpParms->dwItem) {
        case MCI_STATUS_CURRENT_TRACK:
@@ -325,6 +344,7 @@ DWORD       MCIAVI_mciStatus(UINT wDevID, DWOR
        case MCI_STATUS_LENGTH:
            if (!wma->hFile) {
                lpParms->dwReturn = 0;
+                LeaveCriticalSection(&wma->cs);
                return MCIERR_UNSUPPORTED_FUNCTION;
            }
            /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
@@ -334,7 +354,7 @@ DWORD       MCIAVI_mciStatus(UINT wDevID, DWOR
        case MCI_STATUS_MODE:
            lpParms->dwReturn = MAKEMCIRESOURCE(wma->dwStatus, wma->dwStatus);
            ret = MCI_RESOURCE_RETURNED;
-           TRACE("MCI_STATUS_MODE => %u\n", LOWORD(lpParms->dwReturn));
+           TRACE("MCI_STATUS_MODE => 0x%04x\n", LOWORD(lpParms->dwReturn));
            break;
        case MCI_STATUS_MEDIA_PRESENT:
            TRACE("MCI_STATUS_MEDIA_PRESENT => TRUE\n");
@@ -348,6 +368,7 @@ DWORD       MCIAVI_mciStatus(UINT wDevID, DWOR
        case MCI_STATUS_POSITION:
            if (!wma->hFile) {
                lpParms->dwReturn = 0;
+                LeaveCriticalSection(&wma->cs);
                return MCIERR_UNSUPPORTED_FUNCTION;
            }
            /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
@@ -401,7 +422,7 @@ DWORD       MCIAVI_mciStatus(UINT wDevID, DWOR
            TRACE("MCI_DGV_STATUS_HPAL => %lx\n", lpParms->dwReturn);
            break;
        case MCI_DGV_STATUS_HWND:
-           lpParms->dwReturn = (DWORD)wma->hWndPaint;
+           lpParms->dwReturn = (DWORD_PTR)wma->hWndPaint;
            TRACE("MCI_DGV_STATUS_HWND => %p\n", wma->hWndPaint);
            break;
 #if 0
@@ -436,17 +457,20 @@ DWORD     MCIAVI_mciStatus(UINT wDevID, DWOR
        default:
            FIXME("Unknowm command %08lX !\n", lpParms->dwItem);
            TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
+            LeaveCriticalSection(&wma->cs);
            return MCIERR_UNRECOGNIZED_COMMAND;
        }
     } else {
        WARN("No Status-Item!\n");
+        LeaveCriticalSection(&wma->cs);
        return MCIERR_UNRECOGNIZED_COMMAND;
     }
+
     if (dwFlags & MCI_NOTIFY) {
        TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
        mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
-                       wma->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);
+                       wDevID, MCI_NOTIFY_SUCCESSFUL);
     }
-
+    LeaveCriticalSection(&wma->cs);
     return ret;
 }
diff -u cvs/hq/wine/dlls/winmm/mciavi/mciavi.c wine/dlls/winmm/mciavi/mciavi.c
--- cvs/hq/wine/dlls/winmm/mciavi/mciavi.c      2003-12-30 22:44:20.000000000 +0800
+++ wine/dlls/winmm/mciavi/mciavi.c     2003-12-30 23:28:23.000000000 +0800
@@ -4,6 +4,7 @@
  * Digital video MCI Wine Driver
  *
  * Copyright 1999, 2000 Eric POUECH
+ * Copyright 2003 Dmitry Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -26,24 +27,25 @@
  *     - lots of messages still need to be handled (cf FIXME)
  *     - synchronization between audio and video (especially for interleaved
  *       files)
- *     - synchronization (as in all the Wine MCI drivers (MCI_WAIT) messages)
  *     - robustness when reading file can be enhanced
  *     - better move the AVI handling part to avifile DLL and make use of it
  *     - some files appear to have more than one audio stream (we only play the
  *       first one)
  *     - some files contain an index of audio/video frame. Better use it,
  *       instead of rebuilding it
- *     - mciWindow (for setting the hWnd) is broken with media player
  *     - stopping while playing a file with sound blocks until all buffered
  *        audio is played... still should be stopped ASAP
  */
 
+#include <assert.h>
 #include <string.h>
 #include "private_mciavi.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
 
+static DWORD MCIAVI_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS);
+
 /* ===================================================================
  * ===================================================================
  * FIXME: should be using the new mmThreadXXXX functions from WINMM
@@ -54,10 +56,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
  * =================================================================== */
 
 struct SCA {
-    UINT       wDevID;
-    UINT       wMsg;
-    DWORD      dwParam1;
-    DWORD      dwParam2;
+    MCIDEVICEID wDevID;
+    UINT        wMsg;
+    DWORD_PTR   dwParam1;
+    DWORD_PTR   dwParam2;
 };
 
 /**************************************************************************
@@ -68,15 +70,15 @@ static DWORD CALLBACK       MCI_SCAStarter(LPV
     struct SCA*        sca = (struct SCA*)arg;
     DWORD      ret;
 
-    TRACE("In thread before async command (%08x,%u,%08lx,%08lx)\n",
+    TRACE("In thread before async command (%08x,%04x,%08lx,%08lx)\n",
          sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);
     ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);
-    TRACE("In thread after async command (%08x,%u,%08lx,%08lx)\n",
+    TRACE("In thread after async command (%08x,%04x,%08lx,%08lx)\n",
          sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);
     HeapFree(GetProcessHeap(), 0, sca);
     ExitThread(ret);
-    WARN("Should not happen ? what's wrong \n");
     /* should not go after this point */
+    assert(0);
     return ret;
 }
 
@@ -84,7 +86,7 @@ static DWORD CALLBACK MCI_SCAStarter(LPV
  *                             MCI_SendCommandAsync            [internal]
  */
 static DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1,
-                                  DWORD dwParam2, UINT size)
+                                  DWORD_PTR dwParam2, UINT size)
 {
     struct SCA*        sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA) + size);
 
@@ -96,7 +98,7 @@ static        DWORD MCI_SendCommandAsync(UINT w
     sca->dwParam1 = dwParam1;
 
     if (size && dwParam2) {
-       sca->dwParam2 = (DWORD)sca + sizeof(struct SCA);
+       sca->dwParam2 = (DWORD_PTR)sca + sizeof(struct SCA);
        /* copy structure passed by program in dwParam2 to be sure
         * we can still use it whatever the program does
         */
@@ -137,17 +139,22 @@ static    DWORD   MCIAVI_drvOpen(LPSTR str, L
     WINE_MCIAVI*       wma;
     static const WCHAR mciAviWStr[] = {'M','C','I','A','V','I',0};
 
+    TRACE("%s, %p\n", debugstr_a(str), modp);
+
+    /* session instance */
     if (!modp) return 0xFFFFFFFF;
 
     wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIAVI));
     if (!wma)
        return 0;
 
+    InitializeCriticalSection(&wma->cs);
     wma->wDevID = modp->wDeviceID;
-    mciSetDriverData(wma->wDevID, (DWORD)wma);
     wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0);
     modp->wCustomCommandTable = wma->wCommandTable;
     modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
+    mciSetDriverData(wma->wDevID, (DWORD)wma);
+
     return modp->wDeviceID;
 }
 
@@ -156,11 +163,24 @@ static    DWORD   MCIAVI_drvOpen(LPSTR str, L
  */
 static DWORD   MCIAVI_drvClose(DWORD dwDevID)
 {
-    WINE_MCIAVI*  wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
+    WINE_MCIAVI *wma;
+
+    TRACE("%04lx\n", dwDevID);
+
+    /* finish all outstanding things */
+    MCIAVI_mciClose(dwDevID, MCI_WAIT, NULL);
+
+    wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
 
     if (wma) {
+        EnterCriticalSection(&wma->cs);
+
        mciSetDriverData(dwDevID, 0);
        mciFreeCommandResource(wma->wCommandTable);
+
+        LeaveCriticalSection(&wma->cs);
+        DeleteCriticalSection(&wma->cs);
+
        HeapFree(GetProcessHeap(), 0, wma);
        return 1;
     }
@@ -172,7 +192,13 @@ static     DWORD   MCIAVI_drvClose(DWORD dwDev
  */
 static DWORD   MCIAVI_drvConfigure(DWORD dwDevID)
 {
-    WINE_MCIAVI*  wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
+    WINE_MCIAVI *wma;
+
+    TRACE("%04lx\n", dwDevID);
+
+    MCIAVI_mciStop(dwDevID, MCI_WAIT, NULL);
+
+    wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
 
     if (wma) {
        MessageBoxA(0, "Sample AVI Wine Driver !", "MM-Wine Driver", MB_OK);
@@ -202,6 +228,10 @@ static void MCIAVI_CleanUp(WINE_MCIAVI* 
     if (wma->hFile) {
        mmioClose(wma->hFile, 0);
        wma->hFile = 0;
+
+        if (wma->lpFileName) HeapFree(GetProcessHeap(), 0, wma->lpFileName);
+        wma->lpFileName = NULL;
+
        if (wma->lpVideoIndex)  HeapFree(GetProcessHeap(), 0, wma->lpVideoIndex);
        wma->lpVideoIndex = NULL;
        if (wma->lpAudioIndex)  HeapFree(GetProcessHeap(), 0, wma->lpAudioIndex);
@@ -231,22 +261,26 @@ static void MCIAVI_CleanUp(WINE_MCIAVI* 
     }
 }
 
-static DWORD   MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
-
 /***************************************************************************
  *                             MCIAVI_mciOpen                  [internal]
  */
 static DWORD   MCIAVI_mciOpen(UINT wDevID, DWORD dwFlags,
                            LPMCI_DGV_OPEN_PARMSA lpOpenParms)
 {
-    WINE_MCIAVI*       wma = (WINE_MCIAVI*)mciGetDriverData(wDevID);
+    WINE_MCIAVI *wma;
     LRESULT            dwRet = 0;
 
     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpOpenParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpOpenParms == NULL)           return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = (WINE_MCIAVI *)mciGetDriverData(wDevID);
     if (wma == NULL)                   return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
+
     if (wma->nUseCount > 0) {
        /* The driver is already open on this channel */
        /* If the driver was opened shareable before and this open specifies */
@@ -254,14 +288,16 @@ static    DWORD   MCIAVI_mciOpen(UINT wDevID,
        if (wma->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
            ++wma->nUseCount;
        else
+        {
+            LeaveCriticalSection(&wma->cs);
            return MCIERR_MUST_USE_SHAREABLE;
+        }
     } else {
        wma->nUseCount = 1;
        wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
     }
 
     wma->dwStatus = MCI_MODE_NOT_READY;
-    InitializeCriticalSection(&wma->cs);
 
     if (dwFlags & MCI_OPEN_ELEMENT) {
        if (dwFlags & MCI_OPEN_ELEMENT_ID) {
@@ -273,7 +309,11 @@ static     DWORD   MCIAVI_mciOpen(UINT wDevID,
            /* FIXME : what should be done id wma->hFile is already != 0, or the driver is playin' */
            TRACE("MCI_OPEN_ELEMENT '%s' !\n", lpOpenParms->lpstrElementName);
 
-           if (lpOpenParms->lpstrElementName && (strlen(lpOpenParms->lpstrElementName) > 0)) {
+           if (lpOpenParms->lpstrElementName && (strlen(lpOpenParms->lpstrElementName) > 0))
+            {
+                wma->lpFileName = HeapAlloc(GetProcessHeap(), 0, strlen(lpOpenParms->lpstrElementName) + 1);
+                strcpy(wma->lpFileName, lpOpenParms->lpstrElementName);
+
                wma->hFile = mmioOpenA(lpOpenParms->lpstrElementName, NULL,
                                       MMIO_ALLOCBUF | MMIO_DENYWRITE | MMIO_READWRITE);
 
@@ -295,44 +335,52 @@ static    DWORD   MCIAVI_mciOpen(UINT wDevID,
        }
     }
 
-    memcpy(&wma->openParms, lpOpenParms, sizeof(MCI_WAVE_OPEN_PARMSA));
-
     if (dwRet == 0) {
+        TRACE("lpOpenParms->wDeviceID = %04x\n", lpOpenParms->wDeviceID);
+
        wma->dwStatus = MCI_MODE_STOP;
        wma->dwMciTimeFormat = MCI_FORMAT_FRAMES;
     } else {
        MCIAVI_CleanUp(wma);
     }
-    return dwRet;
 
+    LeaveCriticalSection(&wma->cs);
+    return dwRet;
 }
 
 /***************************************************************************
  *                             MCIAVI_mciClose                 [internal]
  */
-static DWORD   MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
+DWORD MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
     DWORD              dwRet = 0;
 
     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
+    wma = (WINE_MCIAVI *)MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)   return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
+
     if (wma->nUseCount == 1) {
        if (wma->dwStatus != MCI_MODE_STOP)
-           dwRet = MCIAVI_mciStop(wDevID, MCI_WAIT, lpParms);
+           dwRet = MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
        MCIAVI_CleanUp(wma);
 
        if ((dwFlags & MCI_NOTIFY) && lpParms) {
            mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
-                           wma->openParms.wDeviceID,
+                           wDevID,
                            MCI_NOTIFY_SUCCESSFUL);
        }
-       HeapFree(GetProcessHeap(), 0, wma);
+        LeaveCriticalSection(&wma->cs);
        return dwRet;
     }
     wma->nUseCount--;
+
+    LeaveCriticalSection(&wma->cs);
     return dwRet;
 }
 
@@ -341,7 +389,7 @@ static      DWORD   MCIAVI_mciClose(UINT wDevID
  */
 static DWORD   MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
     DWORD              tc;
     DWORD              frameTime;
     DWORD              delta;
@@ -353,19 +401,34 @@ static    DWORD   MCIAVI_mciPlay(UINT wDevID,
     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
 
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = (WINE_MCIAVI *)MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
-    if (!wma->hFile)           return MCIERR_FILE_NOT_FOUND;
-    if (!wma->hWndPaint)       return MCIERR_NO_WINDOW;
+    EnterCriticalSection(&wma->cs);
+
+    if (!wma->hFile)
+    {
+        LeaveCriticalSection(&wma->cs);
+        return MCIERR_FILE_NOT_FOUND;
+    }
+    if (!wma->hWndPaint)
+    {
+        LeaveCriticalSection(&wma->cs);
+        return MCIERR_NO_WINDOW;
+    }
 
     wma->dwStatus = MCI_MODE_PLAY;
+    LeaveCriticalSection(&wma->cs);
 
     if (!(dwFlags & MCI_WAIT)) {
-       return MCI_SendCommandAsync(wma->openParms.wDeviceID, MCI_PLAY, dwFlags,
-                                   (DWORD)lpParms, sizeof(MCI_PLAY_PARMS));
+       return MCI_SendCommandAsync(wDevID, MCI_PLAY, dwFlags,
+                                   (DWORD_PTR)lpParms, sizeof(MCI_PLAY_PARMS));
     }
 
-    ShowWindow(wma->hWndPaint, SW_SHOW);
+    ShowWindow(wma->hWndPaint, SW_SHOWNA);
+
+    EnterCriticalSection(&wma->cs);
 
     dwFromFrame = wma->dwCurrVideoFrame;
     dwToFrame = wma->dwPlayableVideoFrames - 1;
@@ -381,10 +444,14 @@ static    DWORD   MCIAVI_mciPlay(UINT wDevID,
 
     TRACE("Playing from frame=%lu to frame=%lu\n", dwFromFrame, dwToFrame);
 
-    if (dwToFrame <= wma->dwCurrVideoFrame)
-       return TRUE;
     wma->dwCurrVideoFrame = dwFromFrame;
 
+    if (dwToFrame <= wma->dwCurrVideoFrame)
+    {
+        dwRet = 0;
+        goto mci_play_done;
+    }
+
     if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_DGV_PLAY_REVERSE|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN))
        FIXME("Unsupported flag %08lx\n", dwFlags);
 
@@ -392,13 +459,19 @@ static    DWORD   MCIAVI_mciPlay(UINT wDevID,
     frameTime = (wma->mah.dwMicroSecPerFrame + 500) / 1000;
 
     if (wma->lpWaveFormat) {
-       if ((dwRet = MCIAVI_OpenAudio(wma, &nHdr, &waveHdr)) != 0)
-           goto cleanUp;
+       if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0)
+        {
+            /* can't play audio */
+            HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
+            wma->lpWaveFormat = NULL;
+        }
+        else
        /* fill the queue with as many wave headers as possible */
        MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
     }
 
-    while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY) {
+    while (wma->dwStatus == MCI_MODE_PLAY)
+    {
        tc = GetTickCount();
 
        MCIAVI_DrawFrame(wma);
@@ -406,23 +479,36 @@ static    DWORD   MCIAVI_mciPlay(UINT wDevID,
        if (wma->lpWaveFormat) {
            MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
            delta = GetTickCount() - tc;
-           WaitForSingleObject(wma->hEvent, (delta >= frameTime) ? 0 : frameTime - delta);
+
+            LeaveCriticalSection(&wma->cs);
+           MsgWaitForMultipleObjects(1, &wma->hEvent, FALSE,
+                (delta >= frameTime) ? 0 : frameTime - delta, MWMO_INPUTAVAILABLE);
+            EnterCriticalSection(&wma->cs);
+
+            if (wma->dwStatus != MCI_MODE_PLAY) break;
        }
 
        delta = GetTickCount() - tc;
        if (delta < frameTime)
-           Sleep(frameTime - delta);
-
-       if (wma->dwCurrVideoFrame++ >= dwToFrame) {
-           wma->dwCurrVideoFrame--;
-           wma->dwStatus = MCI_MODE_STOP;
-       }
+        {
+            LeaveCriticalSection(&wma->cs);
+            MsgWaitForMultipleObjects(0, NULL, FALSE, frameTime - delta, MWMO_INPUTAVAILABLE);
+            EnterCriticalSection(&wma->cs);
+        }
+
+       if (wma->dwCurrVideoFrame < dwToFrame)
+           wma->dwCurrVideoFrame++;
+        else
+            break;
     }
 
     if (wma->lpWaveFormat) {
-       while (*(volatile DWORD*)&wma->dwEventCount != nHdr - 1) {
-           Sleep(100);
-       }
+       while (wma->dwEventCount != nHdr - 1)
+        {
+            LeaveCriticalSection(&wma->cs);
+            Sleep(100);
+            EnterCriticalSection(&wma->cs);
+        }
 
        /* just to get rid of some race conditions between play, stop and pause */
        waveOutReset(wma->hWave);
@@ -432,7 +518,7 @@ static      DWORD   MCIAVI_mciPlay(UINT wDevID,
     }
 
     dwRet = 0;
-cleanUp:
+
     if (wma->lpWaveFormat) {
        HeapFree(GetProcessHeap(), 0, waveHdr);
 
@@ -443,14 +529,15 @@ cleanUp:
        CloseHandle(wma->hEvent);
     }
 
+mci_play_done:
+    wma->dwStatus = MCI_MODE_STOP;
+
     if (lpParms && (dwFlags & MCI_NOTIFY)) {
        TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
        mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
-                       wma->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);
+                       wDevID, MCI_NOTIFY_SUCCESSFUL);
     }
-
-    wma->dwStatus = MCI_MODE_STOP;
-
+    LeaveCriticalSection(&wma->cs);
     return dwRet;
 }
 
@@ -459,14 +546,20 @@ cleanUp:
  */
 static DWORD   MCIAVI_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECORD_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lX, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
     wma->dwStatus = MCI_MODE_RECORD;
+    LeaveCriticalSection(&wma->cs);
     return 0;
 }
 
@@ -475,14 +568,16 @@ static    DWORD   MCIAVI_mciRecord(UINT wDevI
  */
 static DWORD   MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
     DWORD              dwRet = 0;
 
     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
 
-    if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
+
     switch (wma->dwStatus) {
     case MCI_MODE_PAUSE:
     case MCI_MODE_PLAY:
@@ -493,19 +588,26 @@ static    DWORD   MCIAVI_mciStop(UINT wDevID,
            if (oldStat == MCI_MODE_PAUSE)
                dwRet = waveOutReset(wma->hWave);
        }
-       while (wma->dwStatus != MCI_MODE_STOP)
-           Sleep(10);
-       break;
+    /* fall through */
     default:
-       wma->dwStatus = MCI_MODE_STOP;
+        do /* one more chance for an async thread to finish */
+        {
+            LeaveCriticalSection(&wma->cs);
+           Sleep(10);
+            EnterCriticalSection(&wma->cs);
+        } while (wma->dwStatus != MCI_MODE_STOP);
+
        break;
+
+    case MCI_MODE_NOT_READY:
+        break;        
     }
 
     if ((dwFlags & MCI_NOTIFY) && lpParms) {
        mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
-                       wma->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);
+                       wDevID, MCI_NOTIFY_SUCCESSFUL);
     }
-
+    LeaveCriticalSection(&wma->cs);
     return dwRet;
 }
 
@@ -514,15 +616,21 @@ static    DWORD   MCIAVI_mciStop(UINT wDevID,
  */
 static DWORD   MCIAVI_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
+    DWORD ret;
 
-    if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
+
     if (wma->dwStatus == MCI_MODE_PLAY)
        wma->dwStatus = MCI_MODE_PAUSE;
 
-    return (wma->lpWaveFormat) ? waveOutPause(wma->hWave) : 0;
+    ret = (wma->lpWaveFormat) ? waveOutPause(wma->hWave) : 0;
+    
+    LeaveCriticalSection(&wma->cs);
+    return ret;
 }
 
 /***************************************************************************
@@ -530,17 +638,23 @@ static    DWORD   MCIAVI_mciPause(UINT wDevID
  */
 static DWORD   MCIAVI_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
+    DWORD ret;
 
     FIXME("(%04x, %08lX, %p) : stub\n", wDevID, dwFlags, lpParms);
 
-    if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
+
     if (wma->dwStatus == MCI_MODE_PAUSE)
        wma->dwStatus = MCI_MODE_PLAY;
 
-    return (wma->lpWaveFormat) ? waveOutRestart(wma->hWave) : 0;
+    ret = (wma->lpWaveFormat) ? waveOutRestart(wma->hWave) : 0;
+
+    LeaveCriticalSection(&wma->cs);
+    return ret;
 }
 
 /***************************************************************************
@@ -548,17 +662,19 @@ static    DWORD   MCIAVI_mciResume(UINT wDevI
  */
 static DWORD   MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     EnterCriticalSection(&wma->cs);
 
-    MCIAVI_mciStop(wDevID, MCI_WAIT, 0);
-
     if (dwFlags & MCI_SEEK_TO_START) {
        wma->dwCurrVideoFrame = 0;
     } else if (dwFlags & MCI_SEEK_TO_END) {
@@ -575,11 +691,9 @@ static     DWORD   MCIAVI_mciSeek(UINT wDevID,
 
     if (dwFlags & MCI_NOTIFY) {
        mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
-                       wma->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);
+                       wDevID, MCI_NOTIFY_SUCCESSFUL);
     }
-
     LeaveCriticalSection(&wma->cs);
-
     return 0;
 }
 
@@ -588,11 +702,15 @@ static    DWORD   MCIAVI_mciSeek(UINT wDevID,
  */
 static DWORD   MCIAVI_mciLoad(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LOAD_PARMSA lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -603,11 +721,15 @@ static DWORD      MCIAVI_mciLoad(UINT wDevID,
  */
 static DWORD   MCIAVI_mciSave(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SAVE_PARMSA lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -618,11 +740,15 @@ static    DWORD   MCIAVI_mciSave(UINT wDevID,
  */
 static DWORD   MCIAVI_mciFreeze(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -633,11 +759,15 @@ static    DWORD   MCIAVI_mciFreeze(UINT wDevI
  */
 static DWORD   MCIAVI_mciRealize(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -648,11 +778,15 @@ static    DWORD   MCIAVI_mciRealize(UINT wDev
  */
 static DWORD   MCIAVI_mciUnFreeze(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -663,11 +797,15 @@ static    DWORD   MCIAVI_mciUnFreeze(UINT wDe
  */
 static DWORD   MCIAVI_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -678,11 +816,15 @@ static    DWORD   MCIAVI_mciUpdate(UINT wDevI
  */
 static DWORD   MCIAVI_mciStep(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STEP_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -693,11 +835,15 @@ static    DWORD   MCIAVI_mciStep(UINT wDevID,
  */
 static DWORD   MCIAVI_mciCopy(UINT wDevID, DWORD dwFlags, LPMCI_DGV_COPY_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -708,11 +854,15 @@ static    DWORD   MCIAVI_mciCopy(UINT wDevID,
  */
 static DWORD   MCIAVI_mciCut(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUT_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -723,11 +873,15 @@ static    DWORD   MCIAVI_mciCut(UINT wDevID, 
  */
 static DWORD   MCIAVI_mciDelete(UINT wDevID, DWORD dwFlags, LPMCI_DGV_DELETE_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -738,11 +892,15 @@ static    DWORD   MCIAVI_mciDelete(UINT wDevI
  */
 static DWORD   MCIAVI_mciPaste(UINT wDevID, DWORD dwFlags, LPMCI_DGV_PASTE_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -753,11 +911,15 @@ static    DWORD   MCIAVI_mciPaste(UINT wDevID
  */
 static DWORD   MCIAVI_mciCue(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUE_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -768,11 +930,15 @@ static    DWORD   MCIAVI_mciCue(UINT wDevID, 
  */
 static DWORD   MCIAVI_mciCapture(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CAPTURE_PARMSA lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -783,11 +949,15 @@ static    DWORD   MCIAVI_mciCapture(UINT wDev
  */
 static DWORD   MCIAVI_mciMonitor(UINT wDevID, DWORD dwFlags, LPMCI_DGV_MONITOR_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -798,11 +968,15 @@ static    DWORD   MCIAVI_mciMonitor(UINT wDev
  */
 static DWORD   MCIAVI_mciReserve(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RESERVE_PARMSA lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -813,11 +987,15 @@ static    DWORD   MCIAVI_mciReserve(UINT wDev
  */
 static DWORD   MCIAVI_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSA lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -828,11 +1006,15 @@ static   DWORD   MCIAVI_mciSetAudio(UINT wDe
  */
 static DWORD   MCIAVI_mciSignal(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SIGNAL_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -843,11 +1025,15 @@ static   DWORD   MCIAVI_mciSignal(UINT wDevI
  */
 static DWORD   MCIAVI_mciSetVideo(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETVIDEO_PARMSA lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -858,11 +1044,15 @@ static   DWORD   MCIAVI_mciSetVideo(UINT wDe
  */
 static DWORD   MCIAVI_mciQuality(UINT wDevID, DWORD dwFlags, LPMCI_DGV_QUALITY_PARMSA lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -873,11 +1063,15 @@ static   DWORD   MCIAVI_mciQuality(UINT wDev
  */
 static DWORD   MCIAVI_mciList(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LIST_PARMSA lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -888,11 +1082,15 @@ static   DWORD   MCIAVI_mciList(UINT wDevID,
  */
 static DWORD   MCIAVI_mciUndo(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -903,11 +1101,15 @@ static   DWORD   MCIAVI_mciUndo(UINT wDevID,
  */
 static DWORD   MCIAVI_mciConfigure(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -918,11 +1120,15 @@ static   DWORD   MCIAVI_mciConfigure(UINT wD
  */
 static DWORD   MCIAVI_mciRestore(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RESTORE_PARMSA lpParms)
 {
-    WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
+    WINE_MCIAVI *wma;
 
     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
 
+    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
+
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
+
+    wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
     return 0;
@@ -954,7 +1160,8 @@ LONG CALLBACK      MCIAVI_DriverProc(DWORD dw
     case DRV_REMOVE:           return DRVCNF_RESTART;
     }
 
-    if (dwDevID == 0xFFFFFFFF) return MCIERR_UNSUPPORTED_FUNCTION;
+    /* session instance */
+    if (dwDevID == 0xFFFFFFFF) return 1;
 
     switch (wMsg) {
     case MCI_OPEN_DRIVER:      return MCIAVI_mciOpen      (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSA)     dwParam2);
diff -u cvs/hq/wine/dlls/winmm/mciavi/mmoutput.c wine/dlls/winmm/mciavi/mmoutput.c
--- cvs/hq/wine/dlls/winmm/mciavi/mmoutput.c    2003-12-30 22:44:20.000000000 +0800
+++ wine/dlls/winmm/mciavi/mmoutput.c   2003-12-30 23:28:23.000000000 +0800
@@ -4,6 +4,7 @@
  * Digital video MCI Wine Driver
  *
  * Copyright 1999, 2000 Eric POUECH
+ * Copyright 2003 Dmitry Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -25,16 +26,10 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
 
-static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI* wma, const MMCKINFO* mmckList)
+static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCKINFO *mmckStream)
 {
     MMCKINFO   mmckInfo;
 
-    mmckInfo.ckid = ckidSTREAMHEADER;
-    if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
-       WARN("Can't find 'strh' chunk\n");
-       return FALSE;
-    }
-
     mmioRead(wma->hFile, (LPSTR)&wma->ash_audio, sizeof(wma->ash_audio));
 
     TRACE("ash.fccType='%c%c%c%c'\n",          LOBYTE(LOWORD(wma->ash_audio.fccType)),
@@ -59,11 +54,12 @@ static BOOL MCIAVI_GetInfoAudio(WINE_MCI
     TRACE("ash.rcFrame=(%d,%d,%d,%d)\n",       wma->ash_audio.rcFrame.top, wma->ash_audio.rcFrame.left,
          wma->ash_audio.rcFrame.bottom, wma->ash_audio.rcFrame.right);
 
-    mmioAscend(wma->hFile, &mmckInfo, 0);
+    /* rewind to the start of the stream */
+    mmioAscend(wma->hFile, mmckStream, 0);
 
     mmckInfo.ckid = ckidSTREAMFORMAT;
     if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
-       WARN("Can't find 'strh' chunk\n");
+       WARN("Can't find 'strf' chunk\n");
        return FALSE;
     }
     if (mmckInfo.cksize < sizeof(WAVEFORMAT)) {
@@ -87,21 +83,13 @@ static BOOL MCIAVI_GetInfoAudio(WINE_MCI
     if (mmckInfo.cksize >= sizeof(WAVEFORMATEX))
        TRACE("waveFormat.cbSize=%d\n",                 wma->lpWaveFormat->cbSize);
 
-    mmioAscend(wma->hFile, &mmckInfo, 0);
-
     return TRUE;
 }
 
-static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI* wma, const MMCKINFO* mmckList)
+static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCKINFO* mmckStream)
 {
     MMCKINFO   mmckInfo;
 
-    mmckInfo.ckid = ckidSTREAMHEADER;
-    if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
-       WARN("Can't find 'strh' chunk\n");
-       return FALSE;
-    }
-
     mmioRead(wma->hFile, (LPSTR)&wma->ash_video, sizeof(wma->ash_video));
 
     TRACE("ash.fccType='%c%c%c%c'\n",          LOBYTE(LOWORD(wma->ash_video.fccType)),
@@ -126,11 +114,12 @@ static BOOL MCIAVI_GetInfoVideo(WINE_MCI
     TRACE("ash.rcFrame=(%d,%d,%d,%d)\n",       wma->ash_video.rcFrame.top, wma->ash_video.rcFrame.left,
          wma->ash_video.rcFrame.bottom, wma->ash_video.rcFrame.right);
 
-    mmioAscend(wma->hFile, &mmckInfo, 0);
+    /* rewind to the start of the stream */
+    mmioAscend(wma->hFile, mmckStream, 0);
 
     mmckInfo.ckid = ckidSTREAMFORMAT;
     if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
-       WARN("Can't find 'strh' chunk\n");
+       WARN("Can't find 'strf' chunk\n");
        return FALSE;
     }
 
@@ -154,7 +143,12 @@ static BOOL MCIAVI_GetInfoVideo(WINE_MCI
     TRACE("bih.biClrUsed=%ld\n",       wma->inbih->biClrUsed);
     TRACE("bih.biClrImportant=%ld\n",  wma->inbih->biClrImportant);
 
-    mmioAscend(wma->hFile, &mmckInfo, 0);
+    wma->source.left = 0;
+    wma->source.top = 0;
+    wma->source.right = wma->inbih->biWidth;
+    wma->source.bottom = wma->inbih->biHeight;
+
+    wma->dest = wma->source;
 
     return TRUE;
 }
@@ -178,6 +172,9 @@ static BOOL MCIAVI_AddFrame(WINE_MCIAVI*
     case cktypePALchange:
        TRACE("Adding video frame[%ld]: %ld bytes\n",
              alb->numVideoFrames, mmck->cksize);
+        if (!mmck->cksize)
+            TRACE("got a zero sized frame\n");
+
        if (alb->numVideoFrames < wma->dwPlayableVideoFrames) {
            wma->lpVideoIndex[alb->numVideoFrames].dwOffset = mmck->dwDataOffset;
            wma->lpVideoIndex[alb->numVideoFrames].dwSize = mmck->cksize;
@@ -263,25 +260,43 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma)
 
     mmioAscend(wma->hFile, &mmckInfo, 0);
 
-    mmckList.fccType = listtypeSTREAMHEADER;
-    if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
-       WARN("Can't find 'strl' list\n");
-       return FALSE;
-    }
+    TRACE("Start of streams\n");
+    do
+    {
+        MMCKINFO mmckStream;
+
+        mmckList.fccType = listtypeSTREAMHEADER;
+        if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) != 0)
+            break;
+
+        mmckStream.ckid = ckidSTREAMHEADER;
+        if (mmioDescend(wma->hFile, &mmckStream, &mmckList, MMIO_FINDCHUNK) != 0)
+        {
+            WARN("Can't find 'strh' chunk\n");
+            continue;
+        }
+
+        TRACE("Stream fccType %4.4s\n", (LPSTR)&mmckStream.fccType);
+
+        if (mmckStream.fccType == streamtypeVIDEO)
+        {
+            TRACE("found video stream\n");
+            if (!MCIAVI_GetInfoVideo(wma, &mmckList, &mmckStream))
+                return FALSE;
+        }
+        else if (mmckStream.fccType == streamtypeAUDIO)
+        {
+            TRACE("found audio stream\n");
+            if (!MCIAVI_GetInfoAudio(wma, &mmckList, &mmckStream))
+                return FALSE;
+        }
+        else
+            TRACE("Unsupported stream type %4.4s\n", (LPSTR)&mmckStream.fccType);
 
-    if (!MCIAVI_GetInfoVideo(wma, &mmckList)) {
-       return FALSE;
-    }
+        mmioAscend(wma->hFile, &mmckList, 0);
+    } while(1);
 
-    mmioAscend(wma->hFile, &mmckList, 0);
-
-    mmckList.fccType = listtypeSTREAMHEADER;
-    if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
-       if (!MCIAVI_GetInfoAudio(wma, &mmckList)) {
-           return FALSE;
-       }
-       mmioAscend(wma->hFile, &mmckList, 0);
-    }
+    TRACE("End of streams\n");
 
     mmioAscend(wma->hFile, &mmckHead, 0);
 
@@ -351,6 +366,8 @@ BOOL    MCIAVI_OpenVideo(WINE_MCIAVI* wm
     DWORD      outSize;
     FOURCC     fcc = wma->ash_video.fccHandler;
 
+    TRACE("fcc %4.4s\n", (LPSTR)&fcc);
+
     /* check uncompressed AVI */
     if ((fcc == mmioFOURCC('D','I','B',' ')) ||
        (fcc == mmioFOURCC('R','L','E',' '))) {
@@ -411,10 +428,14 @@ BOOL    MCIAVI_OpenVideo(WINE_MCIAVI* wm
     return TRUE;
 }
 
-static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance,
-                                        DWORD dwParam1, DWORD dwParam2)
+static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
+                                        DWORD_PTR dwParam1, DWORD_PTR dwParam2)
 {
-    WINE_MCIAVI*       wma = (WINE_MCIAVI*)dwInstance;
+    WINE_MCIAVI *wma = (WINE_MCIAVI *)MCIAVI_mciGetOpenDev(dwInstance);
+
+    if (!wma) return;
+
+    EnterCriticalSection(&wma->cs);
 
     switch (uMsg) {
     case WOM_OPEN:
@@ -428,6 +449,8 @@ static void CALLBACK MCIAVI_waveCallback
     default:
        ERR("Unknown uMsg=%d\n", uMsg);
     }
+
+    LeaveCriticalSection(&wma->cs);
 }
 
 DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr)
@@ -437,7 +460,7 @@ DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma,
     unsigned   i;
 
     dwRet = waveOutOpen((HWAVEOUT *)&wma->hWave, WAVE_MAPPER, wma->lpWaveFormat,
-                       (DWORD)MCIAVI_waveCallback, (DWORD)wma, CALLBACK_FUNCTION);
+                       (DWORD_PTR)MCIAVI_waveCallback, wma->wDevID, CALLBACK_FUNCTION);
     if (dwRet != 0) {
        TRACE("Can't open low level audio device %ld\n", dwRet);
        dwRet = MCIERR_DEVICE_OPEN;
@@ -543,7 +566,11 @@ LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* w
     hdcMem = CreateCompatibleDC(hDC);
     hbmOld = SelectObject(hdcMem, wma->hbmFrame);
 
-    BitBlt(hDC, 0, 0, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY);
+    StretchBlt(hDC,
+               wma->dest.left, wma->dest.top, wma->dest.right, wma->dest.bottom,
+               hdcMem,
+               wma->source.left, wma->source.top, wma->source.right, wma->source.bottom,
+               SRCCOPY);
 
     SelectObject(hdcMem, hbmOld);
     DeleteDC(hdcMem);
@@ -559,8 +586,6 @@ LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wm
     if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset)
        return FALSE;
 
-    EnterCriticalSection(&wma->cs);
-
     mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET);
     mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize);
 
@@ -570,7 +595,6 @@ LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wm
     if (wma->hic &&
        ICDecompress(wma->hic, 0, wma->inbih, wma->indata,
                     wma->outbih, wma->outdata) != ICERR_OK) {
-       LeaveCriticalSection(&wma->cs);
        WARN("Decompression error\n");
        return FALSE;
     }
@@ -580,8 +604,5 @@ LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wm
        ReleaseDC(wma->hWndPaint, hDC);
     }
 
-    LeaveCriticalSection(&wma->cs);
-
     return TRUE;
 }
-
diff -u cvs/hq/wine/dlls/winmm/mciavi/private_mciavi.h wine/dlls/winmm/mciavi/private_mciavi.h
--- cvs/hq/wine/dlls/winmm/mciavi/private_mciavi.h      2003-12-30 22:44:20.000000000 +0800
+++ wine/dlls/winmm/mciavi/private_mciavi.h     2003-12-30 23:28:23.000000000 +0800
@@ -41,12 +41,12 @@ struct MMIOPos {
 };
 
 typedef struct {
-    UINT               wDevID;
+    MCIDEVICEID                wDevID;
     int                        nUseCount;              /* Incremented for each shared open          */
     BOOL               fShareable;             /* TRUE if first open was shareable          */
     WORD               wCommandTable;          /* custom MCI command table */
-    volatile DWORD     dwStatus;               /* One of MCI_MODE_XXX                       */
-    MCI_OPEN_PARMSA    openParms;
+    DWORD              dwStatus;               /* One of MCI_MODE_XXX                       */
+    LPSTR              lpFileName;
     DWORD              dwMciTimeFormat;        /* current time format */
     DWORD              dwSet;                  /* what's turned on: video & audio l&r */
     /* information on the loaded AVI file */
@@ -75,6 +75,7 @@ typedef struct {
     HWND               hWnd, hWndPaint;
     DWORD              dwCurrVideoFrame;       /* video frame to display and current position */
     DWORD              dwCurrAudioBlock;       /* current audio block being played */
+    RECT                source, dest;
     /* data for the background mechanism */
     CRITICAL_SECTION   cs;
 } WINE_MCIAVI;
@@ -99,6 +100,7 @@ LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* w
 
 /* mciavi.c */
 WINE_MCIAVI*   MCIAVI_mciGetOpenDev(UINT wDevID);
+DWORD MCIAVI_mciClose(UINT, DWORD, LPMCI_GENERIC_PARMS);
 
 /* window.c */
 BOOL    MCIAVI_CreateWindow(WINE_MCIAVI* wma, DWORD dwFlags, LPMCI_DGV_OPEN_PARMSA lpOpenParms);
diff -u cvs/hq/wine/dlls/winmm/mciavi/wnd.c wine/dlls/winmm/mciavi/wnd.c
--- cvs/hq/wine/dlls/winmm/mciavi/wnd.c 2003-12-30 22:44:20.000000000 +0800
+++ wine/dlls/winmm/mciavi/wnd.c        2003-12-30 23:28:23.000000000 +0800
@@ -4,6 +4,7 @@
  * Digital video MCI Wine Driver
  *
  * Copyright 1999, 2000 Eric POUECH
+ * Copyright 2003 Dmitry Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,15 +31,13 @@ static LRESULT WINAPI MCIAVI_WindowProc(
 {
     TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hWnd, uMsg, wParam, lParam);
 
-    if (!(WINE_MCIAVI*)GetWindowLongA(hWnd, 0) && uMsg != WM_CREATE)
-       return DefWindowProcA(hWnd, uMsg, wParam, lParam);
-
     switch (uMsg) {
     case WM_CREATE:
        SetWindowLongA(hWnd, 0, (LPARAM)((CREATESTRUCTA*)lParam)->lpCreateParams);
        return DefWindowProcA(hWnd, uMsg, wParam, lParam);
 
     case WM_DESTROY:
+        MCIAVI_mciClose(GetWindowLongA(hWnd, 0), MCI_WAIT, NULL);
        SetWindowLongA(hWnd, 0, 0);
        return DefWindowProcA(hWnd, uMsg, wParam, lParam);
 
@@ -48,32 +47,38 @@ static LRESULT WINAPI MCIAVI_WindowProc(
            GetClientRect(hWnd, &rect);
            FillRect((HDC)wParam, &rect, GetStockObject(BLACK_BRUSH));
        }
-       break;
+       return 1;
+
     case WM_PAINT:
         {
-            WINE_MCIAVI* wma = (WINE_MCIAVI*)GetWindowLongA(hWnd, 0);
+            WINE_MCIAVI *wma = (WINE_MCIAVI *)mciGetDriverData(GetWindowLongA(hWnd, 0));
+
+            if (!wma)
+                return DefWindowProcA(hWnd, uMsg, wParam, lParam);
+            
+            EnterCriticalSection(&wma->cs);
 
             /* the animation isn't playing, don't paint */
            if (wma->dwStatus == MCI_MODE_NOT_READY)
+            {
+                LeaveCriticalSection(&wma->cs);
                /* default paint handling */
                return DefWindowProcA(hWnd, uMsg, wParam, lParam);
+            }
 
-            if (wParam) {
-                EnterCriticalSection(&wma->cs);
+            if (wParam)
                 MCIAVI_PaintFrame(wma, (HDC)wParam);
-                LeaveCriticalSection(&wma->cs);
-            } else {
+            else
+            {
                PAINTSTRUCT ps;
                HDC hDC = BeginPaint(hWnd, &ps);
-
-                EnterCriticalSection(&wma->cs);
                 MCIAVI_PaintFrame(wma, hDC);
-                LeaveCriticalSection(&wma->cs);
-
                EndPaint(hWnd, &ps);
            }
+
+            LeaveCriticalSection(&wma->cs);
         }
-       break;
+       return 1;
 
     default:
        return DefWindowProcA(hWnd, uMsg, wParam, lParam);
@@ -93,15 +98,16 @@ BOOL    MCIAVI_CreateWindow(WINE_MCIAVI*
     if (wma->hWnd) return TRUE;
 
     ZeroMemory(&wndClass, sizeof(WNDCLASSA));
-    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
+    wndClass.style         = CS_DBLCLKS;
     wndClass.lpfnWndProc   = (WNDPROC)MCIAVI_WindowProc;
     wndClass.cbClsExtra    = 0;
-    wndClass.cbWndExtra    = sizeof(WINE_MCIAVI*);
+    wndClass.cbWndExtra    = sizeof(MCIDEVICEID);
+    wndClass.hInstance     = MCIAVI_hInstance;
     wndClass.hCursor       = LoadCursorA(0, (LPSTR)IDC_ARROW);
     wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
     wndClass.lpszClassName = "MCIAVI";
 
-    RegisterClassA(&wndClass);
+    if (!RegisterClassA(&wndClass)) return FALSE;
 
     if (dwFlags & MCI_DGV_OPEN_PARENT) hParent = lpOpenParms->hWndParent;
     if (dwFlags & MCI_DGV_OPEN_WS)     dwStyle = lpOpenParms->dwStyle;
@@ -116,7 +122,8 @@ BOOL    MCIAVI_CreateWindow(WINE_MCIAVI*
     wma->hWnd = CreateWindowA("MCIAVI", "Wine MCI-AVI player",
                              dwStyle, rc.left, rc.top,
                              rc.right, rc.bottom,
-                             hParent, 0, MCIAVI_hInstance, wma);
+                             hParent, 0, MCIAVI_hInstance,
+                              (LPVOID)wma->wDevID);
     wma->hWndPaint = wma->hWnd;
     return (BOOL)wma->hWnd;
 }
@@ -128,40 +135,49 @@ DWORD     MCIAVI_mciPut(UINT wDevID, DWORD d
 {
     WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
     RECT               rc;
-    char               buffer[256];
 
-    FIXME("(%04x, %08lX, %p) : stub\n", wDevID, dwFlags, lpParms);
+    TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
 
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
+
     if (dwFlags & MCI_DGV_RECT) {
        rc = lpParms->rc;
     } else {
-       SetRectEmpty(&rc);
+        GetClientRect(wma->hWndPaint, &rc);
     }
 
-    *buffer = 0;
     if (dwFlags & MCI_DGV_PUT_CLIENT) {
-       strncat(buffer, "PUT_CLIENT", sizeof(buffer));
+        FIXME("PUT_CLIENT %s\n", wine_dbgstr_rect(&rc));
+        LeaveCriticalSection(&wma->cs);
+        return MCIERR_UNRECOGNIZED_COMMAND;
     }
     if (dwFlags & MCI_DGV_PUT_DESTINATION) {
-       strncat(buffer, "PUT_DESTINATION", sizeof(buffer));
+        TRACE("PUT_DESTINATION %s\n", wine_dbgstr_rect(&rc));
+        wma->dest = rc;
     }
     if (dwFlags & MCI_DGV_PUT_FRAME) {
-       strncat(buffer, "PUT_FRAME", sizeof(buffer));
+        FIXME("PUT_FRAME %s\n", wine_dbgstr_rect(&rc));
+        LeaveCriticalSection(&wma->cs);
+        return MCIERR_UNRECOGNIZED_COMMAND;
     }
     if (dwFlags & MCI_DGV_PUT_SOURCE) {
-       strncat(buffer, "PUT_SOURCE", sizeof(buffer));
+        TRACE("PUT_SOURCE %s\n", wine_dbgstr_rect(&rc));
+        wma->source = rc;
     }
     if (dwFlags & MCI_DGV_PUT_VIDEO) {
-       strncat(buffer, "PUT_VIDEO", sizeof(buffer));
+        FIXME("PUT_VIDEO %s\n", wine_dbgstr_rect(&rc));
+        LeaveCriticalSection(&wma->cs);
+        return MCIERR_UNRECOGNIZED_COMMAND;
     }
     if (dwFlags & MCI_DGV_PUT_WINDOW) {
-       strncat(buffer, "PUT_WINDOW", sizeof(buffer));
+        FIXME("PUT_WINDOW %s\n", wine_dbgstr_rect(&rc));
+        LeaveCriticalSection(&wma->cs);
+        return MCIERR_UNRECOGNIZED_COMMAND;
     }
-    TRACE("%s (%ld,%ld,%ld,%ld)\n", buffer, rc.left, rc.top, rc.right, rc.bottom);
-
+    LeaveCriticalSection(&wma->cs);
     return 0;
 }
 
@@ -171,40 +187,43 @@ DWORD     MCIAVI_mciPut(UINT wDevID, DWORD d
 DWORD  MCIAVI_mciWhere(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
 {
     WINE_MCIAVI*       wma = MCIAVI_mciGetOpenDev(wDevID);
-    LPCSTR             x = "";
 
     TRACE("(%04x, %08lx, %p)\n", wDevID, dwFlags, lpParms);
 
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
-    if (dwFlags & MCI_DGV_WHERE_MAX) FIXME("Max NIY\n");
+    if (dwFlags & MCI_DGV_WHERE_MAX)
+    {
+        FIXME("WHERE_MAX\n");
+        return MCIERR_UNRECOGNIZED_COMMAND;
+    }
+
+    EnterCriticalSection(&wma->cs);
 
     if (dwFlags & MCI_DGV_WHERE_DESTINATION) {
-       x = "Dest";
-       GetClientRect(wma->hWnd, &lpParms->rc);
+        TRACE("WHERE_DESTINATION %s\n", wine_dbgstr_rect(&wma->dest));
+        lpParms->rc = wma->dest;
     }
     if (dwFlags & MCI_DGV_WHERE_FRAME) {
-       FIXME(x = "Frame\n");
+       FIXME("MCI_DGV_WHERE_FRAME\n");
+        LeaveCriticalSection(&wma->cs);
        return MCIERR_UNRECOGNIZED_COMMAND;
     }
     if (dwFlags & MCI_DGV_WHERE_SOURCE) {
-       x = "Source";
-       lpParms->rc.left = lpParms->rc.top = 0;
-       lpParms->rc.right = wma->mah.dwWidth;
-       lpParms->rc.bottom = wma->mah.dwHeight;
+        TRACE("WHERE_SOURCE %s\n", wine_dbgstr_rect(&wma->source));
+        lpParms->rc = wma->source;
     }
     if (dwFlags & MCI_DGV_WHERE_VIDEO) {
-       FIXME(x = "Video\n");
+       FIXME("WHERE_VIDEO\n");
+        LeaveCriticalSection(&wma->cs);
        return MCIERR_UNRECOGNIZED_COMMAND;
     }
     if (dwFlags & MCI_DGV_WHERE_WINDOW) {
-       x = "Window";
-       GetClientRect(wma->hWndPaint, &lpParms->rc);
+        GetClientRect(wma->hWndPaint, &lpParms->rc);
+        TRACE("WHERE_WINDOW %s\n", wine_dbgstr_rect(&lpParms->rc));
     }
-    TRACE("%s -> (%ld,%ld,%ld,%ld)\n",
-         x, lpParms->rc.left, lpParms->rc.top, lpParms->rc.right, lpParms->rc.bottom);
-
+    LeaveCriticalSection(&wma->cs);
     return 0;
 }
 
@@ -220,11 +239,16 @@ DWORD     MCIAVI_mciWindow(UINT wDevID, DWOR
     if (lpParms == NULL)       return MCIERR_NULL_PARAMETER_BLOCK;
     if (wma == NULL)           return MCIERR_INVALID_DEVICE_ID;
 
+    EnterCriticalSection(&wma->cs);
+
     if (dwFlags & MCI_DGV_WINDOW_HWND) {
-       TRACE("Setting hWnd to %p\n", lpParms->hWnd);
-       if (wma->hWnd) ShowWindow(wma->hWnd, SW_HIDE);
-       wma->hWndPaint = (lpParms->hWnd == MCI_DGV_WINDOW_DEFAULT) ? wma->hWnd : lpParms->hWnd;
-        InvalidateRect(wma->hWndPaint, NULL, FALSE);
+        if (IsWindow(lpParms->hWnd))
+        {
+            TRACE("Setting hWnd to %p\n", lpParms->hWnd);
+            if (wma->hWnd) ShowWindow(wma->hWnd, SW_HIDE);
+            wma->hWndPaint = (lpParms->hWnd == MCI_DGV_WINDOW_DEFAULT) ? wma->hWnd : lpParms->hWnd;
+            InvalidateRect(wma->hWndPaint, NULL, FALSE);
+        }
     }
     if (dwFlags & MCI_DGV_WINDOW_STATE) {
        TRACE("Setting nCmdShow to %d\n", lpParms->nCmdShow);
@@ -235,5 +259,6 @@ DWORD       MCIAVI_mciWindow(UINT wDevID, DWOR
        SetWindowTextA(wma->hWndPaint, lpParms->lpstrText);
     }
 
+    LeaveCriticalSection(&wma->cs);
     return 0;
 }
diff -u cvs/hq/wine/dlls/winmm/mci.c wine/dlls/winmm/mci.c
--- cvs/hq/wine/dlls/winmm/mci.c        2003-12-30 22:44:20.000000000 +0800
+++ wine/dlls/winmm/mci.c       2003-12-30 23:28:23.000000000 +0800
@@ -1027,7 +1027,7 @@ DWORD WINAPI mciSendStringA(LPCSTR lpstr
      */
     if (lpstrRet && uRetLen) *lpstrRet = '\0';
 
-#define        STR_OF(_x) (IsBadReadPtr((char*)_x,1)?"?":(char*)(_x))
+#define STR_OF(_x) ((!(_x) || IsBadReadPtr((char*)(_x),1)) ? "?" : (char*)(_x))
     TRACE("[%d, %s, %08lx, %08lx/%s %08lx/%s %08lx/%s %08lx/%s %08lx/%s %08lx/%s]\n",
          wmd->wDeviceID, MCI_MessageToString(MCI_GetMessage(lpCmd)), dwFlags,
          data[0], STR_OF(data[0]), data[1], STR_OF(data[1]),






More information about the wine-patches mailing list