Jörg Höhle : winmm: Close MCI device after immediate auto-open commands.

Alexandre Julliard julliard at winehq.org
Thu Sep 2 12:01:27 CDT 2010


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

Author: Jörg Höhle <hoehle at users.sourceforge.net>
Date:   Wed Aug 25 07:32:28 2010 +0200

winmm: Close MCI device after immediate auto-open commands.

---

 dlls/winmm/mci.c       |   48 ++++++++++++++++++++++++++++++++++--------------
 dlls/winmm/tests/mci.c |   24 +++++++++++++-----------
 2 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/dlls/winmm/mci.c b/dlls/winmm/mci.c
index 2b47bd8..44a65a0 100644
--- a/dlls/winmm/mci.c
+++ b/dlls/winmm/mci.c
@@ -1214,12 +1214,13 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
 {
     LPWSTR		verb, dev, args;
     LPWINE_MCIDRIVER	wmd = 0;
-    MCIDEVICEID		uDevID;
+    MCIDEVICEID		uDevID, auto_open = 0;
     DWORD		dwFlags = 0, dwRet = 0;
     int			offset = 0;
     DWORD_PTR		data[MCI_DATA_SIZE];
     DWORD		retType;
     LPCWSTR		lpCmd = 0;
+    WORD		wMsg = 0;
     static const WCHAR  wszNew[] = {'n','e','w',0};
     static const WCHAR  wszSAliasS[] = {' ','a','l','i','a','s',' ',0};
     static const WCHAR  wszTypeS[]   = {'t','y','p','e',' ',0};
@@ -1229,6 +1230,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
 
     TRACE("(%s, %p, %d, %p)\n", 
           debugstr_w(lpstrCommand), lpstrRet, uRetLen, hwndCallback);
+    if (lpstrRet && uRetLen) *lpstrRet = '\0';
 
     /* format is <command> <device> <optargs> */
     if (!(verb = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpstrCommand)+1) * sizeof(WCHAR))))
@@ -1338,15 +1340,19 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
     } else if ((MCI_ALL_DEVICE_ID != uDevID) && !(wmd = MCI_GetDriver(mciGetDeviceIDW(dev)))) {
 	/* auto open */
         static const WCHAR wszOpenWait[] = {'o','p','e','n',' ','%','s',' ','w','a','i','t',0};
-	WCHAR   buf[128];
-	sprintfW(buf, wszOpenWait, dev);
-
-	if ((dwRet = mciSendStringW(buf, NULL, 0, 0)) != 0)
+	WCHAR   buf[138], retbuf[6];
+	snprintfW(buf, sizeof(buf)/sizeof(WCHAR), wszOpenWait, dev);
+	/* open via mciSendString handles quoting, dev!file syntax and alias creation */
+	if ((dwRet = mciSendStringW(buf, retbuf, sizeof(retbuf)/sizeof(WCHAR), 0)) != 0)
 	    goto errCleanUp;
+	auto_open = strtoulW(retbuf, NULL, 10);
+	TRACE("auto-opened %u\n", auto_open);
 
-	wmd = MCI_GetDriver(mciGetDeviceIDW(dev));
+	/* FIXME: test for notify flag (how to preparse?) before opening */
+	/* FIXME: Accept only core commands yet parse them with the specific table */
+	wmd = MCI_GetDriver(auto_open);
 	if (!wmd) {
-	    /* FIXME: memory leak, MCI driver is not closed */
+	    ERR("No auto-open device %d for %s\n", auto_open, debugstr_w(dev));
 	    dwRet = MCIERR_INVALID_DEVICE_ID;
 	    goto errCleanUp;
 	}
@@ -1372,6 +1378,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
 	dwRet = MCIERR_UNRECOGNIZED_COMMAND;
 	goto errCleanUp;
     }
+    wMsg = MCI_GetMessage(lpCmd);
 
     /* set return information */
     switch (retType = MCI_GetReturnType(lpCmd)) {
@@ -1389,17 +1396,23 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
 	goto errCleanUp;
 
     /* set up call back */
+    if (auto_open) {
+	if (dwFlags & MCI_NOTIFY) {
+	    dwRet = MCIERR_NOTIFY_ON_AUTO_OPEN;
+	    goto errCleanUp;
+	}
+	/* FIXME: the command should get its own notification window set up and
+	 * ask for device closing while processing the notification mechanism.
+	 * hwndCallback = ...
+	 * dwFlags |= MCI_NOTIFY;
+	 * In the meantime special-case all commands but PLAY and RECORD below. */
+    }
     if (dwFlags & MCI_NOTIFY) {
 	data[0] = (DWORD_PTR)hwndCallback;
     }
 
-    /* FIXME: the command should get it's own notification window set up and
-     * ask for device closing while processing the notification mechanism
-     */
-    if (lpstrRet && uRetLen) *lpstrRet = '\0';
-
     TRACE("[%d, %s, %08x, %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx]\n",
-	  wmd ? wmd->wDeviceID : uDevID, MCI_MessageToString(MCI_GetMessage(lpCmd)), dwFlags,
+	  wmd ? wmd->wDeviceID : uDevID, MCI_MessageToString(wMsg), dwFlags,
 	  data[0], data[1], data[2], data[3], data[4],
 	  data[5], data[6], data[7], data[8], data[9]);
 
@@ -1408,13 +1421,20 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
 	    MCI_UnLoadMciDriver(wmd);
 	/* FIXME: notification is not properly shared across two opens */
     } else {
-	dwRet = MCI_SendCommand(wmd ? wmd->wDeviceID : uDevID, MCI_GetMessage(lpCmd), dwFlags, (DWORD_PTR)data);
+	dwRet = MCI_SendCommand(wmd ? wmd->wDeviceID : uDevID, wMsg, dwFlags, (DWORD_PTR)data);
     }
     TRACE("=> 1/ %x (%s)\n", dwRet, debugstr_w(lpstrRet));
     dwRet = MCI_HandleReturnValues(dwRet, wmd, retType, data, lpstrRet, uRetLen);
     TRACE("=> 2/ %x (%s)\n", dwRet, debugstr_w(lpstrRet));
 
 errCleanUp:
+    if (auto_open) {
+	/* PLAY and RECORD are the only known non-immediate commands */
+	if (LOWORD(dwRet) || !(wMsg == MCI_PLAY || wMsg == MCI_RECORD))
+	    MCI_SendCommand(auto_open, MCI_CLOSE, 0, 0);
+	else
+	    FIXME("leaking auto-open device %u\n", auto_open);
+    }
     HeapFree(GetProcessHeap(), 0, verb);
     return dwRet;
 }
diff --git a/dlls/winmm/tests/mci.c b/dlls/winmm/tests/mci.c
index 642e346..19082e8 100644
--- a/dlls/winmm/tests/mci.c
+++ b/dlls/winmm/tests/mci.c
@@ -851,16 +851,13 @@ static void test_AutoOpenWAVE(HWND hwnd)
     test_notification(hwnd, "sysinfo name outofrange\n", err ? 0 : MCI_NOTIFY_SUCCESSFUL);
 
     err = mciSendString("play no-such-file-exists.wav notify", buf, sizeof(buf), NULL);
-    if(err==MCIERR_FILE_NOT_FOUND) { /* a Wine detector */
-        /* Unsupported auto-open leaves the file open, preventing clean-up */
-        skip("Skipping auto-open tests in Wine\n");
-        return;
-    }
+    todo_wine ok(err==MCIERR_NOTIFY_ON_AUTO_OPEN,"mci auto-open notify returned %s\n", dbg_mcierr(err));
+    /* FILE_NOT_FOUND in Wine because auto-open fails before testing the notify flag */
 
     test_notification(hwnd, "-prior to auto-open-", 0);
 
     err = mciSendString("play tempfile.wav notify", buf, sizeof(buf), hwnd);
-    todo_wine ok(err==MCIERR_NOTIFY_ON_AUTO_OPEN,"mci auto-open play notify returned %s\n", dbg_mcierr(err));
+    ok(err==MCIERR_NOTIFY_ON_AUTO_OPEN,"mci auto-open play notify returned %s\n", dbg_mcierr(err));
 
     if(err) /* FIXME: don't open twice yet, it confuses Wine. */
     err = mciSendString("play tempfile.wav", buf, sizeof(buf), hwnd);
@@ -874,7 +871,7 @@ static void test_AutoOpenWAVE(HWND hwnd)
     buf[0]=0;
     err = mciSendString("sysinfo waveaudio quantity open", buf, sizeof(buf), NULL);
     ok(!err,"mci sysinfo waveaudio quantity after auto-open returned %s\n", dbg_mcierr(err));
-    if(!err) todo_wine ok(!strcmp(buf,"1"), "sysinfo quantity open expected 1, got: %s\n", buf);
+    if(!err) ok(!strcmp(buf,"1"), "sysinfo quantity open expected 1, got: %s\n", buf);
 
     parm.sys.lpstrReturn = (LPSTR)&intbuf[1];
     parm.sys.dwRetSize = 2*sizeof(DWORD); /* only one DWORD is used */
@@ -907,9 +904,10 @@ static void test_AutoOpenWAVE(HWND hwnd)
     ok(!err,"mci status tempfile.wav mode returned %s\n", dbg_mcierr(err));
     if(!err) ok(!strcmp(buf,"playing"), "mci auto-open status mode, got: %s\n", buf);
 
+    if (0) { /* FIXME: wait until this no more confuses Wine */
     err = mciSendString("open tempfile.wav", buf, sizeof(buf), NULL);
     todo_wine ok(err==MCIERR_DEVICE_OPEN, "mci open from auto-open returned %s\n", dbg_mcierr(err));
-
+    }
     /* w2k/xp and Wine differ. While the device is busy playing, it is
      * regularly open and accessible via the filename: subsequent
      * commands must not cause auto-open each.  In Wine, a subsequent
@@ -927,11 +925,15 @@ static void test_AutoOpenWAVE(HWND hwnd)
         trace("Wine style MCI auto-close upon notification\n");
 
         /* "playing" because auto-close comes after the status call. */
-        todo_wine ok(!strcmp(buf,"playing"), "mci auto-open status mode notify, got: %s\n", buf);
+        ok(!strcmp(buf,"playing"), "mci auto-open status mode notify, got: %s\n", buf);
         /* fixme:winmm:MMDRV_Exit Closing while ll-driver open
          *  is explained by failure to auto-close a device. */
         test_notification(hwnd,"status notify",MCI_NOTIFY_SUCCESSFUL);
         /* MCI received NOTIFY_SUPERSEDED and auto-closed the device. */
+
+        /* Until this is implemented, force closing the device */
+        err = mciSendString("close tempfile.wav", NULL, 0, hwnd);
+        ok(!err,"mci auto-still-open stop returned %s\n", dbg_mcierr(err));
         Sleep(16);
         test_notification(hwnd,"auto-open",0);
     } else if(err==MCIERR_NOTIFY_ON_AUTO_OPEN) { /* MS style */
@@ -945,14 +947,14 @@ static void test_AutoOpenWAVE(HWND hwnd)
         if(!err) ok(!strcmp(buf,"paused"), "mci auto-open status mode, got: %s\n", buf);
 
         /* Auto-close */
-        err = mciSendString("stop tempfile.wav", NULL, 0, hwnd);
+        err = mciSendString("stop tempfile.wav wait", NULL, 0, hwnd);
         ok(!err,"mci auto-still-open stop returned %s\n", dbg_mcierr(err));
         Sleep(16); /* makes sysinfo quantity open below succeed */
     }
 
     err = mciSendString("sysinfo waveaudio quantity open", buf, sizeof(buf), NULL);
     ok(!err,"mci sysinfo waveaudio quantity open after close returned %s\n", dbg_mcierr(err));
-    if(!err) todo_wine ok(!strcmp(buf,"0"), "sysinfo quantity open expected 0 after auto-close, got: %s\n", buf);
+    if(!err) ok(!strcmp(buf,"0"), "sysinfo quantity open expected 0 after auto-close, got: %s\n", buf);
 
     /* w95-WinME (not w2k/XP) switch to C:\ after auto-playing once.  Prevent
      * MCIERR_FILE_NOT_FOUND by using the full path name from the Info file command.




More information about the wine-cvs mailing list