Sync to Wine-20050419:
Robert Reif <reif@earthlink.net>
- Stub out DRVM_MAPPER_RECONFIGURE support.
- Correctly handle where waveOutGetPosition changes timepos.wType
  because the requested type is not supported.
- Added Jeremy White's waveOutGetPosition fix to waveInGetPosition.
- Fix memory leak in error path.
- Provide default implementation of waveInPrepareHeader and
  waveInUnprepareHeader if driver doesn't support them.
Jose Manuel Ferrer Ortiz <jmfo1982@yahoo.es>
- Spanish translations updated.
Peter Berg Larsen <pebl@math.ku.dk>
- Assorted memleak fixes. Found on Michael Stefaniuc smatch list.
Jeremy White <jwhite@codeweavers.com>
- Do not fallback to defaults if a driver, mapper, or midi is specified
  in the registry; consolidate MMDRV_Init() into a single function.
Robert Reif <reif@earthlink.net>
- Fix memory leak when there are too many drivers.
Vincent Beron <vberon@mecano.gme.usherb.ca>
- Correct and complete some api documentation.
Filip Navara <xnavara@volny.cz>
- Specify correct buffer size in GetPrivateProfileStringW calls.
Jakob Eriksson <jakov@vmlinux.org>
- Get rid of HeapAlloc casts.
Jason Edmeades <us@the-edmeades.demon.co.uk>
- Avoid trap in mixerGetLineControlsA when cControls is uninitialized
  and MIXER_GETLINECONTROLSSF_ONEBYTYPE requested.
Modified: trunk/reactos/lib/winmm/driver.c
Modified: trunk/reactos/lib/winmm/lolvldrv.c
Modified: trunk/reactos/lib/winmm/mci.c
Modified: trunk/reactos/lib/winmm/mmio.c
Modified: trunk/reactos/lib/winmm/mmsystem.c
Modified: trunk/reactos/lib/winmm/time.c
Modified: trunk/reactos/lib/winmm/wavemap/wavemap.c
Modified: trunk/reactos/lib/winmm/winemm.h
Modified: trunk/reactos/lib/winmm/winmm.c
Modified: trunk/reactos/lib/winmm/winmm_Es.rc

Modified: trunk/reactos/lib/winmm/driver.c
--- trunk/reactos/lib/winmm/driver.c	2005-05-06 19:11:20 UTC (rev 15055)
+++ trunk/reactos/lib/winmm/driver.c	2005-05-06 19:16:10 UTC (rev 15056)
@@ -308,13 +308,13 @@
     INT                 len;
     LPWSTR 		dn = NULL;
     LPWSTR 		sn = NULL;
-    HDRVR		ret;
+    HDRVR		ret = 0;
 
     if (lpDriverName)
     {
         len = MultiByteToWideChar( CP_ACP, 0, lpDriverName, -1, NULL, 0 );
         dn = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
-        if (!dn) return 0;
+        if (!dn) goto done;
         MultiByteToWideChar( CP_ACP, 0, lpDriverName, -1, dn, len );
     }
 
@@ -322,14 +322,15 @@
     {
         len = MultiByteToWideChar( CP_ACP, 0, lpSectionName, -1, NULL, 0 );
         sn = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
-        if (!sn) return 0;
+        if (!sn) goto done;
         MultiByteToWideChar( CP_ACP, 0, lpSectionName, -1, sn, len );
     }
 
     ret = OpenDriver(dn, sn, lParam);
 
-    if (dn) HeapFree(GetProcessHeap(), 0, dn);
-    if (sn) HeapFree(GetProcessHeap(), 0, sn);
+done:
+    HeapFree(GetProcessHeap(), 0, dn);
+    HeapFree(GetProcessHeap(), 0, sn);
     return ret;
 }
 

Modified: trunk/reactos/lib/winmm/lolvldrv.c
--- trunk/reactos/lib/winmm/lolvldrv.c	2005-05-06 19:11:20 UTC (rev 15055)
+++ trunk/reactos/lib/winmm/lolvldrv.c	2005-05-06 19:16:10 UTC (rev 15056)
@@ -309,6 +309,7 @@
     if (i == MAX_MM_MLDRVS) {
 	/* the MM_MLDrvs table could be made growable in the future if needed */
 	ERR("Too many open drivers\n");
+        HeapFree(GetProcessHeap(), 0, mld);
 	return NULL;
     }
     MM_MLDrvs[i] = mld;
@@ -714,80 +715,62 @@
 }
 
 /**************************************************************************
- * 				MMDRV_InitFromRegistry		[internal]
+ * 				MMDRV_Init
  */
-static BOOL	MMDRV_InitFromRegistry(void)
+BOOL	MMDRV_Init(void)
 {
     HKEY	hKey;
-    char	buffer[256];
+    char	driver_buffer[256];
+    char	mapper_buffer[256];
+    char	midi_buffer[256];
     char*	p1;
     char*	p2;
     DWORD	type, size;
     BOOL	ret = FALSE;
     TRACE("()\n");
 
-    if (RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\WinMM", &hKey)) {
-	TRACE("Cannot open WinMM config key\n");
-	return FALSE;
-    }
+    strcpy(driver_buffer, WINE_DEFAULT_WINMM_DRIVER);
+    strcpy(mapper_buffer, WINE_DEFAULT_WINMM_MAPPER);
+    strcpy(midi_buffer, WINE_DEFAULT_WINMM_MIDI);
 
-    size = sizeof(buffer);
-    if (!RegQueryValueExA(hKey, "Drivers", 0, &type, (LPVOID)buffer, &size)) {
-	p1 = buffer;
-	while (p1) {
-	    p2 = strchr(p1, ';');
-	    if (p2) *p2++ = '\0';
-	    ret |= MMDRV_Install(p1, p1, FALSE);
-	    p1 = p2;
-	}
-    }
+    if (! RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\WinMM", &hKey)) {
+        size = sizeof(driver_buffer);
+        if (RegQueryValueExA(hKey, "Drivers", 0, &type, (LPVOID)driver_buffer, &size)) 
+            strcpy(driver_buffer, WINE_DEFAULT_WINMM_DRIVER);
 
-    /* finish with mappers */
-    size = sizeof(buffer);
-    if (!RegQueryValueExA(hKey, "WaveMapper", 0, &type, (LPVOID)buffer, &size))
-	ret |= MMDRV_Install("wavemapper", buffer, TRUE);
-    size = sizeof(buffer);
-    if (!RegQueryValueExA(hKey, "MidiMapper", 0, &type, (LPVOID)buffer, &size))
-	ret |= MMDRV_Install("midimapper", buffer, TRUE);
+        /* finish with mappers */
+        size = sizeof(mapper_buffer);
+        if (RegQueryValueExA(hKey, "WaveMapper", 0, &type, (LPVOID)mapper_buffer, &size))
+            strcpy(mapper_buffer, WINE_DEFAULT_WINMM_MAPPER);
 
-    RegCloseKey(hKey);
+        size = sizeof(midi_buffer);
+        if (RegQueryValueExA(hKey, "MidiMapper", 0, &type, (LPVOID)midi_buffer, &size))
+            strcpy(midi_buffer, WINE_DEFAULT_WINMM_MIDI);
 
-    return ret;
-}
+        RegCloseKey(hKey);
+    }
 
-/**************************************************************************
- * 				MMDRV_InitHardcoded		[internal]
- */
-static BOOL	MMDRV_InitHardcoded(void)
-{
-    TRACE("()\n");
-    /* first load hardware drivers */
 #ifndef __REACTOS__
-    MMDRV_Install("wineoss.drv",   	"wineoss.drv",	FALSE);
-#endif /* __REACTOS__ */
+    p1 = driver_buffer;
+    while (p1) {
+        p2 = strchr(p1, ';');
+        if (p2) *p2++ = '\0';
+        ret |= MMDRV_Install(p1, p1, FALSE);
+        p1 = p2;
+    }
+#endif
 
 #ifdef __REACTOS__
     // AG: TESTING:
-    MMDRV_Install("mmdrv.dll", "mmdrv.dll", FALSE);
+    ret |= MMDRV_Install("mmdrv.dll", "mmdrv.dll", FALSE);
 #endif
 
-    /* finish with mappers */
-    MMDRV_Install("wavemapper",     "msacm32.dll",    TRUE);
-    MMDRV_Install("midimapper",     "midimap.dll",  TRUE);
+    ret |= MMDRV_Install("wavemapper", mapper_buffer, TRUE);
+    ret |= MMDRV_Install("midimapper", midi_buffer, TRUE);
+    return ret;
 
-    return TRUE;
 }
 
-/**************************************************************************
- * 				MMDRV_Init			[internal]
- */
-BOOL	MMDRV_Init(void)
-{
-    TRACE("()\n");
-    /* FIXME: MMDRV_InitFromRegistry shall be MMDRV_Init in a near future */
-    return MMDRV_InitFromRegistry() || MMDRV_InitHardcoded();
-}
-
 /******************************************************************
  *		ExitPerType
  *

Modified: trunk/reactos/lib/winmm/mci.c
--- trunk/reactos/lib/winmm/mci.c	2005-05-06 19:11:20 UTC (rev 15055)
+++ trunk/reactos/lib/winmm/mci.c	2005-05-06 19:16:10 UTC (rev 15056)
@@ -1458,7 +1458,11 @@
     if (lpstrRet)
     {
         lpwstrRet = HeapAlloc(GetProcessHeap(), 0, uRetLen * sizeof(WCHAR));
-        if (!lpwstrRet) return MCIERR_OUT_OF_MEMORY;
+        if (!lpwstrRet) {
+            WARN("no memory\n");
+            HeapFree( GetProcessHeap(), 0, lpwstrCommand );
+            return MCIERR_OUT_OF_MEMORY;
+        }
     }
     ret = mciSendStringW(lpwstrCommand, lpwstrRet, uRetLen, hwndCallback);
     if (lpwstrRet)

Modified: trunk/reactos/lib/winmm/mmio.c
--- trunk/reactos/lib/winmm/mmio.c	2005-05-06 19:11:20 UTC (rev 15055)
+++ trunk/reactos/lib/winmm/mmio.c	2005-05-06 19:16:10 UTC (rev 15056)
@@ -1360,26 +1360,27 @@
 {
     LPSTR	szFn = NULL;
     LPSTR	sznFn = NULL;
-    UINT	ret;
+    UINT	ret = MMSYSERR_NOMEM;
     INT         len;
 
     if (szFileName)
     {
         len = WideCharToMultiByte( CP_ACP, 0, szFileName, -1, NULL, 0, NULL, NULL );
         szFn = HeapAlloc( GetProcessHeap(), 0, len );
-        if (!szFn) return MMSYSERR_NOMEM;
+        if (!szFn) goto done;
         WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szFn, len, NULL, NULL );
     }
     if (szNewFileName)
     {
         len = WideCharToMultiByte( CP_ACP, 0, szNewFileName, -1, NULL, 0, NULL, NULL );
         sznFn = HeapAlloc( GetProcessHeap(), 0, len );
-        if (!sznFn) return MMSYSERR_NOMEM;
+        if (!sznFn) goto done;
         WideCharToMultiByte( CP_ACP, 0, szNewFileName, -1, sznFn, len, NULL, NULL );
     }
 
     ret = mmioRenameA(szFn, sznFn, lpmmioinfo, dwFlags);
 
+done:
     HeapFree(GetProcessHeap(),0,szFn);
     HeapFree(GetProcessHeap(),0,sznFn);
     return ret;

Modified: trunk/reactos/lib/winmm/mmsystem.c
--- trunk/reactos/lib/winmm/mmsystem.c	2005-05-06 19:11:20 UTC (rev 15055)
+++ trunk/reactos/lib/winmm/mmsystem.c	2005-05-06 19:16:10 UTC (rev 15056)
@@ -731,7 +731,7 @@
 
 /**************************************************************************
  * 				midiOutGetErrorText 	[MMSYSTEM.203]
- * 				midiInGetErrorText 	[MMSYSTEM.203]
+ * 				midiInGetErrorText 	[MMSYSTEM.303]
  */
 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
 {
@@ -1231,7 +1231,7 @@
 
 /**************************************************************************
  * 				waveOutGetErrorText 	[MMSYSTEM.403]
- * 				waveInGetErrorText 	[MMSYSTEM.403]
+ * 				waveInGetErrorText 	[MMSYSTEM.503]
  */
 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
 {
@@ -2260,7 +2260,7 @@
             LPDRVCONFIGINFO	dci32 = (LPDRVCONFIGINFO)(*lParam2);
 
 	    if (dci16) {
-		LPSTR str1;
+		LPSTR str1 = NULL,str2;
                 INT len;
 		dci16->dwDCISize = sizeof(DRVCONFIGINFO16);
 
@@ -2271,6 +2271,7 @@
                         WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCISectionName, -1, str1, len, NULL, NULL );
                         dci16->lpszDCISectionName = MapLS( str1 );
                     } else {
+                        HeapFree( GetProcessHeap(), 0, dci16);
                         return WINMM_MAP_NOMEM;
                     }
 		} else {
@@ -2278,11 +2279,13 @@
 		}
                 if (dci32->lpszDCIAliasName) {
                     len = WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, NULL, 0, NULL, NULL );
-                    str1 = HeapAlloc( GetProcessHeap(), 0, len );
-                    if (str1) {
-                        WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, str1, len, NULL, NULL );
-                        dci16->lpszDCIAliasName = MapLS( str1 );
+                    str2 = HeapAlloc( GetProcessHeap(), 0, len );
+                    if (str2) {
+                        WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, str2, len, NULL, NULL );
+                        dci16->lpszDCIAliasName = MapLS( str2 );
                     } else {
+                        HeapFree( GetProcessHeap(), 0, str1);
+                        HeapFree( GetProcessHeap(), 0, dci16);
                         return WINMM_MAP_NOMEM;
                     }
 		} else {

Modified: trunk/reactos/lib/winmm/time.c
--- trunk/reactos/lib/winmm/time.c	2005-05-06 19:11:20 UTC (rev 15055)
+++ trunk/reactos/lib/winmm/time.c	2005-05-06 19:16:10 UTC (rev 15056)
@@ -315,11 +315,11 @@
 
     TRACE("(%u, %u, %p, %08lX, %04X);\n", wDelay, wResol, lpFunc, dwUser, wFlags);
 
-    lpNewTimer = (LPWINE_TIMERENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_TIMERENTRY));
-    if (lpNewTimer == NULL)
+    if (wDelay < MMSYSTIME_MININTERVAL || wDelay > MMSYSTIME_MAXINTERVAL)
 	return 0;
 
-    if (wDelay < MMSYSTIME_MININTERVAL || wDelay > MMSYSTIME_MAXINTERVAL)
+    lpNewTimer = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_TIMERENTRY));
+    if (lpNewTimer == NULL)
 	return 0;
 
     TIME_MMTimeStart();

Modified: trunk/reactos/lib/winmm/wavemap/wavemap.c
--- trunk/reactos/lib/winmm/wavemap/wavemap.c	2005-05-06 19:11:20 UTC (rev 15055)
+++ trunk/reactos/lib/winmm/wavemap/wavemap.c	2005-05-06 19:16:10 UTC (rev 15056)
@@ -166,6 +166,7 @@
     if (dwFlags & WAVE_MAPPED) {
 	if (lpDesc->uMappedDeviceID >= ndhi) {
             WARN("invalid parameter: dwFlags WAVE_MAPPED\n");
+            HeapFree(GetProcessHeap(), 0, wom);
             return MMSYSERR_INVALPARAM;
         }
 	ndlo = lpDesc->uMappedDeviceID;
@@ -427,9 +428,10 @@
     if (lpTime->wType == TIME_MS)
         timepos.wType = TIME_BYTES;
 
+    /* This can change timepos.wType if the requested type is not supported */
     val = waveOutGetPosition(wom->u.out.hInnerWave, &timepos, dwParam2);
 
-    if (lpTime->wType == TIME_BYTES || lpTime->wType == TIME_MS)
+    if (timepos.wType == TIME_BYTES)
     {
         DWORD dwInnerSamplesPerOuter = wom->nSamplesPerSecInner / wom->nSamplesPerSecOuter;
         if (dwInnerSamplesPerOuter > 0)
@@ -463,10 +465,12 @@
 
         /* Once we have the TIME_BYTES right, we can easily convert to TIME_MS */
         if (lpTime->wType == TIME_MS)
-            lpTime->u.cb = MulDiv(lpTime->u.cb, 1000, wom->avgSpeedOuter);
+            lpTime->u.ms = MulDiv(lpTime->u.cb, 1000, wom->avgSpeedOuter);
+        else
+            lpTime->wType = TIME_BYTES;
     }
-    else if (lpTime->wType == TIME_SAMPLES)
-        lpTime->u.cb = MulDiv(timepos.u.cb, wom->nSamplesPerSecOuter, wom->nSamplesPerSecInner);
+    else if (lpTime->wType == TIME_SAMPLES && timepos.wType == TIME_SAMPLES)
+        lpTime->u.sample = MulDiv(timepos.u.sample, wom->nSamplesPerSecOuter, wom->nSamplesPerSecInner);
     else
         /* other time types don't require conversion */
         lpTime->u = timepos.u;
@@ -586,6 +590,13 @@
     return ret;
 }
 
+static  DWORD   wodMapperReconfigure(WAVEMAPDATA* wom, DWORD dwParam1, DWORD dwParam2)
+{
+    FIXME("(%p %08lx %08lx) stub!\n", wom, dwParam1, dwParam2);
+
+    return MMSYSERR_NOERROR;
+}
+
 /**************************************************************************
  * 				wodMessage (MSACM.@)
  */
@@ -621,6 +632,7 @@
     case WODM_RESTART:		return wodRestart	((WAVEMAPDATA*)dwUser);
     case WODM_RESET:		return wodReset		((WAVEMAPDATA*)dwUser);
     case WODM_MAPPER_STATUS:	return wodMapperStatus  ((WAVEMAPDATA*)dwUser, dwParam1, (LPVOID)dwParam2);
+    case DRVM_MAPPER_RECONFIGURE: return wodMapperReconfigure((WAVEMAPDATA*)dwUser, dwParam1, dwParam2);
     /* known but not supported */
     case DRV_QUERYDEVICEINTERFACESIZE:
     case DRV_QUERYDEVICEINTERFACE:
@@ -961,15 +973,62 @@
 static	DWORD	widGetPosition(WAVEMAPDATA* wim, LPMMTIME lpTime, DWORD dwParam2)
 {
     DWORD       val;
-
+    MMTIME      timepos;
     TRACE("(%p %p %08lx)\n", wim, lpTime, dwParam2);
 
-    val = waveInGetPosition(wim->u.in.hInnerWave, lpTime, dwParam2);
-    if (lpTime->wType == TIME_BYTES)
-        lpTime->u.cb = MulDiv(lpTime->u.cb, wim->avgSpeedOuter, wim->avgSpeedInner);
-    if (lpTime->wType == TIME_SAMPLES)
-        lpTime->u.cb = MulDiv(lpTime->u.cb, wim->nSamplesPerSecOuter, wim->nSamplesPerSecInner);
-    /* other time types don't require conversion */
+    memcpy(&timepos, lpTime, sizeof(timepos));
+
+    /* For TIME_MS, we're going to recalculate using TIME_BYTES */
+    if (lpTime->wType == TIME_MS)
+        timepos.wType = TIME_BYTES;
+
+    /* This can change timepos.wType if the requested type is not supported */
+    val = waveInGetPosition(wim->u.in.hInnerWave, &timepos, dwParam2);
+
+    if (timepos.wType == TIME_BYTES)
+    {
+        DWORD dwInnerSamplesPerOuter = wim->nSamplesPerSecInner / wim->nSamplesPerSecOuter;
+        if (dwInnerSamplesPerOuter > 0)
+        {
+            DWORD dwInnerBytesPerSample = wim->avgSpeedInner / wim->nSamplesPerSecInner;
+            DWORD dwInnerBytesPerOuterSample = dwInnerBytesPerSample * dwInnerSamplesPerOuter;
+            DWORD remainder = 0;
+
+            /* If we are up sampling (going from lower sample rate to higher),
+            **   we need to make a special accomodation for times when we've
+            **   written a partial output sample.  This happens frequently
+            **   to us because we use msacm to do our up sampling, and it
+            **   will up sample on an unaligned basis.
+            ** For example, if you convert a 2 byte wide 8,000 'outer'
+            **   buffer to a 2 byte wide 48,000 inner device, you would
+            **   expect 2 bytes of input to produce 12 bytes of output.
+            **   Instead, msacm will produce 8 bytes of output.
+            **   But reporting our position as 1 byte of output is
+            **   nonsensical; the output buffer position needs to be
+            **   aligned on outer sample size, and aggressively rounded up.
+            */
+            remainder = timepos.u.cb % dwInnerBytesPerOuterSample;
+            if (remainder > 0)
+            {
+                timepos.u.cb -= remainder;
+                timepos.u.cb += dwInnerBytesPerOuterSample;
+            }
+        }
+
+        lpTime->u.cb = MulDiv(timepos.u.cb, wim->avgSpeedOuter, wim->avgSpeedInner);
+
+        /* Once we have the TIME_BYTES right, we can easily convert to TIME_MS */
+        if (lpTime->wType == TIME_MS)
+            lpTime->u.ms = MulDiv(lpTime->u.cb, 1000, wim->avgSpeedOuter);
+        else
+            lpTime->wType = TIME_BYTES;
+    }
+    else if (lpTime->wType == TIME_SAMPLES && timepos.wType == TIME_SAMPLES)
+        lpTime->u.sample = MulDiv(timepos.u.sample, wim->nSamplesPerSecOuter, wim->nSamplesPerSecInner);
+    else
+        /* other time types don't require conversion */
+        lpTime->u = timepos.u;
+
     return val;
 }
 
@@ -1058,6 +1117,13 @@
     return ret;
 }
 
+static  DWORD   widMapperReconfigure(WAVEMAPDATA* wim, DWORD dwParam1, DWORD dwParam2)
+{
+    FIXME("(%p %08lx %08lx) stub!\n", wim, dwParam1, dwParam2);
+
+    return MMSYSERR_NOERROR;
+}
+
 /**************************************************************************
  * 				widMessage (MSACM.@)
  */
@@ -1088,6 +1154,7 @@
     case WIDM_START:		return widStart         ((WAVEMAPDATA*)dwUser);
     case WIDM_STOP:		return widStop          ((WAVEMAPDATA*)dwUser);
     case WIDM_MAPPER_STATUS:	return widMapperStatus  ((WAVEMAPDATA*)dwUser, dwParam1, (LPVOID)dwParam2);
+    case DRVM_MAPPER_RECONFIGURE: return widMapperReconfigure((WAVEMAPDATA*)dwUser, dwParam1, dwParam2);
     /* known but not supported */
     case DRV_QUERYDEVICEINTERFACESIZE:
     case DRV_QUERYDEVICEINTERFACE:

Modified: trunk/reactos/lib/winmm/winemm.h
--- trunk/reactos/lib/winmm/winemm.h	2005-05-06 19:11:20 UTC (rev 15055)
+++ trunk/reactos/lib/winmm/winemm.h	2005-05-06 19:16:10 UTC (rev 15056)
@@ -28,6 +28,10 @@
 #include "winbase.h"
 #include "mmddk.h"
 
+#define WINE_DEFAULT_WINMM_DRIVER     "wineoss.drv"
+#define WINE_DEFAULT_WINMM_MAPPER     "msacm.drv"
+#define WINE_DEFAULT_WINMM_MIDI       "midimap.drv"
+
 typedef DWORD (WINAPI *MessageProc16)(UINT16 wDevID, UINT16 wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2);
 typedef DWORD (WINAPI *MessageProc32)(UINT wDevID, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2);
 

Modified: trunk/reactos/lib/winmm/winmm.c
--- trunk/reactos/lib/winmm/winmm.c	2005-05-06 19:11:20 UTC (rev 15055)
+++ trunk/reactos/lib/winmm/winmm.c	2005-05-06 19:16:10 UTC (rev 15056)
@@ -441,7 +441,7 @@
 	    if (lpmcdA->u.cMultipleItems != 0) {
 		size *= lpmcdA->u.cMultipleItems;
 	    }
-	    pDetailsW = (MIXERCONTROLDETAILS_LISTTEXTW *)HeapAlloc(GetProcessHeap(), 0, size);
+	    pDetailsW = HeapAlloc(GetProcessHeap(), 0, size);
             lpmcdA->paDetails = pDetailsW;
             lpmcdA->cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXTW);
 	    /* set up lpmcd->paDetails */
@@ -492,7 +492,15 @@
     mlcW.dwLineID = lpmlcA->dwLineID;
     mlcW.u.dwControlID = lpmlcA->u.dwControlID;
     mlcW.u.dwControlType = lpmlcA->u.dwControlType;
-    mlcW.cControls = lpmlcA->cControls;
+
+    /* Debugging on Windows shows for MIXER_GETLINECONTROLSF_ONEBYTYPE only,
+       the control count is assumed to be 1 - This is relied upon by a game,
+       "Dynomite Deluze"                                                    */
+    if (MIXER_GETLINECONTROLSF_ONEBYTYPE == fdwControls) {
+        mlcW.cControls = 1;
+    } else {
+        mlcW.cControls = lpmlcA->cControls;
+    }
     mlcW.cbmxctrl = sizeof(MIXERCONTROLW);
     mlcW.pamxctrl = HeapAlloc(GetProcessHeap(), 0,
 			      mlcW.cControls * mlcW.cbmxctrl);
@@ -2580,6 +2588,7 @@
 				UINT uSize)
 {
     LPWINE_MLD		wmld;
+    UINT                result;
 
     TRACE("(%p, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
 
@@ -2589,9 +2598,18 @@
     if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
 	return MMSYSERR_INVALHANDLE;
 
+    if ((result = MMDRV_Message(wmld, WIDM_PREPARE, (DWORD_PTR)lpWaveInHdr,
+                                uSize, TRUE)) != MMSYSERR_NOTSUPPORTED)
+        return result;
+
+    if (lpWaveInHdr->dwFlags & WHDR_INQUEUE)
+        return WAVERR_STILLPLAYING;
+
+    lpWaveInHdr->dwFlags |= WHDR_PREPARED;
+    lpWaveInHdr->dwFlags &= ~WHDR_DONE;
     lpWaveInHdr->dwBytesRecorded = 0;
 
-    return MMDRV_Message(wmld, WIDM_PREPARE, (DWORD_PTR)lpWaveInHdr, uSize, TRUE);
+    return MMSYSERR_NOERROR;
 }
 
 /**************************************************************************
@@ -2601,20 +2619,30 @@
 				  UINT uSize)
 {
     LPWINE_MLD		wmld;
+    UINT                result;
 
     TRACE("(%p, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
 
     if (lpWaveInHdr == NULL || uSize < sizeof (WAVEHDR))
 	return MMSYSERR_INVALPARAM;
 
-    if (!(lpWaveInHdr->dwFlags & WHDR_PREPARED)) {
+    if (!(lpWaveInHdr->dwFlags & WHDR_PREPARED))
 	return MMSYSERR_NOERROR;
-    }
 
     if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
 	return MMSYSERR_INVALHANDLE;
 
-    return MMDRV_Message(wmld, WIDM_UNPREPARE, (DWORD_PTR)lpWaveInHdr, uSize, TRUE);
+    if ((result = MMDRV_Message(wmld, WIDM_UNPREPARE, (DWORD_PTR)lpWaveInHdr,
+                                uSize, TRUE)) != MMSYSERR_NOTSUPPORTED)
+        return result;
+
+    if (lpWaveInHdr->dwFlags & WHDR_INQUEUE)
+        return WAVERR_STILLPLAYING;
+
+    lpWaveInHdr->dwFlags &= ~WHDR_PREPARED;
+    lpWaveInHdr->dwFlags |= WHDR_DONE;
+
+    return MMSYSERR_NOERROR;
 }
 
 /**************************************************************************

Modified: trunk/reactos/lib/winmm/winmm_Es.rc
--- trunk/reactos/lib/winmm/winmm_Es.rc	2005-05-06 19:11:20 UTC (rev 15055)
+++ trunk/reactos/lib/winmm/winmm_Es.rc	2005-05-06 19:16:10 UTC (rev 15056)
@@ -1,5 +1,6 @@
 /*
  * Copyright 1999 Julio Cesar Gazquez
+ * Copyright 2005 JosÚ Manuel Ferrer Ortiz
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -17,30 +18,30 @@
  */
 
 STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
-   BEGIN
+BEGIN
 
-   /* MMSYS errors */
+/* MMSYS errors */
    MMSYSERR_NOERROR, "El comando especificado fue ejecutado."
    MMSYSERR_ERROR, "Error externo indefinido."
    MMSYSERR_BADDEVICEID, "Un identificador de dispositivo que ha sido usado estß fuera de rango para su sistema."
-   MMSYSERR_NOTENABLED, "El controlador no fue activado."
+   MMSYSERR_NOTENABLED, "El manejador no fue activado."
    MMSYSERR_ALLOCATED, "El dispositivo especificado a·n estß en uso. Espere hasta que estÚ libre e intente nuevamente."
    MMSYSERR_INVALHANDLE, "El handle de dispositivo especificado es invßlido."
-   MMSYSERR_NODRIVER, "No hay un controlador instalado en su sistema !\n"
-   MMSYSERR_NOMEM, "No hay suficiente memoria disponible para esta tarea. Cierre una o mßs aplicaciones para aumentar la memoria disponible e intente nuevamente."
-   MMSYSERR_NOTSUPPORTED, "Esta funci¾n no estß soportada. Use la funci¾n Capacidades para determinar que funciones y mensajes soporta el controlador."
+   MMSYSERR_NODRIVER, "íNo hay un manejador instalado en su sistema!\n"
+   MMSYSERR_NOMEM, "No hay suficiente memoria disponible para esta tarea. Cierre una o mßs aplicaciones para aumentar la memoria disponible e intÚntelo de nuevo."
+   MMSYSERR_NOTSUPPORTED, "Esta funci¾n no estß soportada. Use la funci¾n Capacidades para determinar quÚ funciones y mensajes soporta el manejador."
    MMSYSERR_BADERRNUM, "Se ha especificado un n·mero de error que no estß definido en el sistema."
-   MMSYSERR_INVALFLAG, "Se ha pasado un flag no vßlido a una funci¾n del sistema."
+   MMSYSERR_INVALFLAG, "Se ha pasado una bandera no vßlida a una funci¾n del sistema."
    MMSYSERR_INVALPARAM, "Se ha pasado un parßmetro no vßlido a una funci¾n del sistema."
 
-   /* WAVE errors */
+/* WAVE errors */
    WAVERR_BADFORMAT, "El formato especificado no estß soportado o no puede ser traducido. Use la funci¾n Capacidades para determinar los formatos soportados."
    WAVERR_STILLPLAYING, "Esta operaci¾n no puede ejecutarse mientras contin·a la reproducci¾n. Reinicie el dispositivo, o espere hasta que la reproducci¾n termine."
-   WAVERR_UNPREPARED, "La cabecera del forma de onda no estß preparada. Use la funci¾n Preparar para preparar la cabecera, e intente nuevamente."
-   WAVERR_SYNC, "No puede abrirse el dispositivo sin usar el flag WAVE_ALLOWSYNC. Use el flag, e intente nuevamente."
+   WAVERR_UNPREPARED, "La cabecera de onda no estß preparada. Use la funci¾n Preparar para prepararla, e intÚntelo de nuevo."
+   WAVERR_SYNC, "No puede abrirse el dispositivo sin usar la bandera WAVE_ALLOWSYNC. UtilÝcela, e intÚntelo de nuevo."
 
-   /* MIDI errors */
-   MIDIERR_UNPREPARED, "La cabecera MIDI no estß preparada. Use la funci¾n Preparar para preparar la cabecera, e intente nuevamente."
+/* MIDI errors */
+   MIDIERR_UNPREPARED, "La cabecera MIDI no estß preparada. Use la funci¾n Preparar para prepararla, e intÚntelo de nuevo."
    MIDIERR_STILLPLAYING, "Esta operaci¾n no puede ejecutarse mientras se contin·a tocando. Reinicie el dispositivo, o espera hasta que termine de tocar."
    MIDIERR_NOMAP, "No se encontr¾ un mapa MIDI. Puede haber un problema con el controlador, el el fichero MIDIMAP.CFG puede faltar o estar corrupto."
    MIDIERR_NOTREADY, "El puerto estß transmitiendo datos al dispositivo. Espera hasta que los datos hayan sido transmitidos, e intente nuevamente."
@@ -123,4 +124,4 @@
    MCIERR_SEQ_PORTUNSPECIFIED, "El sistema no tiene actualmente un puerto MIDI especificado."
    MCIERR_SEQ_TIMER, "Todos los temporizadores de multimedia estßn siendo usados por otras aplicaciones. Cierre una de esas aplicaciones e intente nuevamente."
 
-   END
+END