1. Audio codecs were being incorrectly listed several times.
2. An ideosyncrasy of acmStreamOpen would occasioanally cause some applications to crash.
Waldeck
Index: wine/dlls/msacm/format.c =================================================================== RCS file: /home/wine/wine/dlls/msacm/format.c,v retrieving revision 1.20 diff -u -p -r1.20 format.c --- wine/dlls/msacm/format.c 2 Dec 2002 18:10:59 -0000 1.20 +++ wine/dlls/msacm/format.c 20 Jan 2003 20:02:45 -0000 @@ -758,36 +758,74 @@ MMRESULT WINAPI acmFormatTagEnumW(HACMDR if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM; - if (had) FIXME("had != NULL, not supported\n"); + /* (WS) MSDN info page says that if had != 0, then we should find + * the specific driver to get its tags from. Therefore I'm removing + * the FIXME call and adding a search block below. It also seems + * that the lack of this functionality was the responsible for + * codecs to be multiply and incorrectly listed. + */ + + /* if (had) FIXME("had != NULL, not supported\n"); */ + + if (had) { + + if (acmDriverID((HACMOBJ)had, (HACMDRIVERID *)&padid, 0) != MMSYSERR_NOERROR) + return MMSYSERR_INVALHANDLE; + + for (i = 0; i < padid->cFormatTags; i++) { + paftd->dwFormatTagIndex = i; + if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, + (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) { + if (paftd->dwFormatTag == WAVE_FORMAT_PCM) { + if (paftd->szFormatTag[0] == 0) + MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag, + sizeof(paftd->szFormatTag)/sizeof(WCHAR) ); + /* (WS) I'm preserving this PCM hack since it seems to be + * correct. Please notice this block was borrowed from + * below. + */ + if (bPcmDone) continue; + bPcmDone = TRUE; + } + if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) + return MMSYSERR_NOERROR; + } + } - for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { - /* should check for codec only */ - if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && - acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) { - for (i = 0; i < padid->cFormatTags; i++) { - paftd->dwFormatTagIndex = i; - if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, - (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) { - if (paftd->dwFormatTag == WAVE_FORMAT_PCM) { - if (paftd->szFormatTag[0] == 0) - MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag, - sizeof(paftd->szFormatTag)/sizeof(WCHAR) ); - /* FIXME (EPP): I'm not sure this is the correct - * algorithm (should make more sense to apply the same - * for all already loaded formats, but this will do - * for now - */ - if (bPcmDone) continue; - bPcmDone = TRUE; - } - if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) { - acmDriverClose(had, 0); - return MMSYSERR_NOERROR; - } - } - } - } - acmDriverClose(had, 0); + } + + /* if had==0 then search for the first suitable driver */ + else { + for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { + /* should check for codec only */ + if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && + acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) { + for (i = 0; i < padid->cFormatTags; i++) { + paftd->dwFormatTagIndex = i; + if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, + (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) { + if (paftd->dwFormatTag == WAVE_FORMAT_PCM) { + if (paftd->szFormatTag[0] == 0) + MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag, + sizeof(paftd->szFormatTag)/sizeof(WCHAR) ); + /* FIXME (EPP): I'm not sure this is the correct + * algorithm (should make more sense to apply the same + * for all already loaded formats, but this will do + * for now + */ + if (bPcmDone) continue; + bPcmDone = TRUE; + } + if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) { + acmDriverClose(had, 0); + return MMSYSERR_NOERROR; + } + } + } + } + acmDriverClose(had, 0); + } } return MMSYSERR_NOERROR; } + Index: wine/dlls/msacm/stream.c =================================================================== RCS file: /home/wine/wine/dlls/msacm/stream.c,v retrieving revision 1.12 diff -u -p -r1.12 stream.c --- wine/dlls/msacm/stream.c 2 Dec 2002 18:10:59 -0000 1.12 +++ wine/dlls/msacm/stream.c 20 Jan 2003 20:02:45 -0000 @@ -147,7 +147,14 @@ MMRESULT WINAPI acmStreamOpen(PHACMSTREA pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec, pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize); + /* (WS) I'm removing the following test and making some other changes + * herein because the info page on MSDN says that in query mode the + * parameter phas should (and not must) be NULL. Otherwise some + * applications will crash because phas is garbage. + if ((fdwOpen & ACM_STREAMOPENF_QUERY) && phas) return MMSYSERR_INVALPARAM; + */ + if (pwfltr && (pwfxSrc->wFormatTag != pwfxDst->wFormatTag)) return MMSYSERR_INVALPARAM; wfxSrcSize = wfxDstSize = sizeof(WAVEFORMATEX); @@ -230,14 +237,25 @@ MMRESULT WINAPI acmStreamOpen(PHACMSTREA ret = MMSYSERR_NOERROR; was->drvInst.has = (HACMSTREAM)was; if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) { - if (phas) - *phas = (HACMSTREAM)was; - TRACE("=> (%d)\n", ret); - return ret; + /* if not in query mode, return pointer to allocated heap */ + if (phas) + *phas = (HACMSTREAM)was; } + else + /* otherwise, release memory to avoid leaks */ + HeapFree(MSACM_hHeap, 0, was); + TRACE("=> (%d)\n", ret); + return ret; + errCleanUp: - if (phas) + if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) { + /* (WS) As I explained above, this is supposed to be closer to what + * is expected from this function. In query mode phas is not needed + * and hence will not be used at all. + */ + if (phas) *phas = NULL; + } HeapFree(MSACM_hHeap, 0, was); TRACE("=> (%d)\n", ret); return ret;