/*********************************************************************** * MSACM_UnregisterDriver() */ PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p) { PWINE_ACMDRIVERID pNextACMDriverID; while (p->pACMDriverList) acmDriverClose((HACMDRIVER) p->pACMDriverList, 0); HeapFree(MSACM_hHeap, 0, p->pszDriverAlias); HeapFree(MSACM_hHeap, 0, p->pszFileName); HeapFree(MSACM_hHeap, 0, p->aFormatTag); if (p == MSACM_pFirstACMDriverID) MSACM_pFirstACMDriverID = p->pNextACMDriverID; if (p == MSACM_pLastACMDriverID) MSACM_pLastACMDriverID = p->pPrevACMDriverID; if (p->pPrevACMDriverID) p->pPrevACMDriverID->pNextACMDriverID = p->pNextACMDriverID; if (p->pNextACMDriverID) p->pNextACMDriverID->pPrevACMDriverID = p->pPrevACMDriverID; pNextACMDriverID = p->pNextACMDriverID; if (p->pLocalDriver) MSACM_UnregisterLocalDriver(p->pLocalDriver); HeapFree(MSACM_hHeap, 0, p); return pNextACMDriverID; }
/*********************************************************************** * acmFilterTagEnumW (MSACM32.@) */ MMRESULT WINAPI acmFilterTagEnumW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd, ACMFILTERTAGENUMCBW fnCallback, DWORD_PTR dwInstance, DWORD fdwEnum) { PWINE_ACMDRIVERID padid; unsigned int i; TRACE("(%p, %p, %p, %ld, %d)\n", had, paftd, fnCallback, dwInstance, fdwEnum); if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM; if (had) FIXME("had != NULL, not supported\n"); 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->cFilterTags; i++) { paftd->dwFilterTagIndex = i; if (acmFilterTagDetailsW(had, paftd, ACM_FILTERTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) { if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) { padid = NULL; break; } } } acmDriverClose(had, 0); } } return MMSYSERR_NOERROR; }
/*********************************************************************** * MSACM_FillCache */ static BOOL MSACM_FillCache(PWINE_ACMDRIVERID padid) { HACMDRIVER had = 0; unsigned int ntag; ACMDRIVERDETAILSW add; ACMFORMATTAGDETAILSW aftd; if (acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != 0) return FALSE; padid->aFormatTag = NULL; add.cbStruct = sizeof(add); if (MSACM_Message(had, ACMDM_DRIVER_DETAILS, (LPARAM)&add, 0)) goto errCleanUp; if (add.cFormatTags > 0) { padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY, add.cFormatTags * sizeof(padid->aFormatTag[0])); if (!padid->aFormatTag) goto errCleanUp; } padid->cFormatTags = add.cFormatTags; padid->cFilterTags = add.cFilterTags; padid->fdwSupport = add.fdwSupport; aftd.cbStruct = sizeof(aftd); for (ntag = 0; ntag < add.cFormatTags; ntag++) { aftd.dwFormatTagIndex = ntag; if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)&aftd, ACM_FORMATTAGDETAILSF_INDEX)) { TRACE("IIOs (%s)\n", debugstr_w(padid->pszDriverAlias)); goto errCleanUp; } padid->aFormatTag[ntag].dwFormatTag = aftd.dwFormatTag; padid->aFormatTag[ntag].cbwfx = aftd.cbFormatSize; } acmDriverClose(had, 0); return TRUE; errCleanUp: if (had) acmDriverClose(had, 0); HeapFree(MSACM_hHeap, 0, padid->aFormatTag); padid->aFormatTag = NULL; return FALSE; }
/*********************************************************************** * acmFormatDetailsW (MSACM32.@) */ MMRESULT WINAPI acmFormatDetailsW(HACMDRIVER had, PACMFORMATDETAILSW pafd, DWORD fdwDetails) { MMRESULT mmr; static const WCHAR fmt1[] = {'%','d',' ','H','z',0}; static const WCHAR fmt2[] = {';',' ','%','d',' ','b','i','t','s',0}; TRACE("(%p, %p, %d)\n", had, pafd, fdwDetails); if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM; switch (fdwDetails) { case ACM_FORMATDETAILSF_FORMAT: if (pafd->dwFormatTag != pafd->pwfx->wFormatTag) { mmr = MMSYSERR_INVALPARAM; break; } if (had == NULL) { PWINE_ACMDRIVERID padid; mmr = ACMERR_NOTPOSSIBLE; for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { /* should check for codec only */ if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails); acmDriverClose(had, 0); if (mmr == MMSYSERR_NOERROR) break; } } } else { mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails); } break; case ACM_FORMATDETAILSF_INDEX: /* should check pafd->dwFormatIndex < aftd->cStandardFormats */ mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails); break; default: WARN("Unknown fdwDetails %08x\n", fdwDetails); mmr = MMSYSERR_INVALFLAG; break; } if (mmr == MMSYSERR_NOERROR && pafd->szFormat[0] == 0) { wsprintfW(pafd->szFormat, fmt1, pafd->pwfx->nSamplesPerSec); if (pafd->pwfx->wBitsPerSample) { wsprintfW(pafd->szFormat + lstrlenW(pafd->szFormat), fmt2, pafd->pwfx->wBitsPerSample); } MultiByteToWideChar( CP_ACP, 0, (pafd->pwfx->nChannels == 1) ? "; Mono" : "; Stereo", -1, pafd->szFormat + strlenW(pafd->szFormat), sizeof(pafd->szFormat)/sizeof(WCHAR) - strlenW(pafd->szFormat) ); } TRACE("=> %d\n", mmr); return mmr; }
MMRESULT WINAPI acmFormatEnumW(HACMDRIVER had, PACMFORMATDETAILSW pafd, ACMFORMATENUMCBW fnCallback, DWORD dwInstance, DWORD fdwEnum) { PWINE_ACMDRIVERID padid; WAVEFORMATEX wfxRef; BOOL ret; TRACE("(%p, %p, %p, %d, %d)\n", had, pafd, fnCallback, dwInstance, fdwEnum); if (!pafd) return MMSYSERR_INVALPARAM; if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM; if (fdwEnum & (ACM_FORMATENUMF_WFORMATTAG|ACM_FORMATENUMF_NCHANNELS| ACM_FORMATENUMF_NSAMPLESPERSEC|ACM_FORMATENUMF_WBITSPERSAMPLE| ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST)) wfxRef = *pafd->pwfx; if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) && !(fdwEnum & (ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT))) return MMSYSERR_INVALPARAM; if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) && (pafd->dwFormatTag != pafd->pwfx->wFormatTag)) return MMSYSERR_INVALPARAM; if (fdwEnum & (ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST| ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT)) FIXME("Unsupported fdwEnum values %08x\n", fdwEnum); if (had) { HACMDRIVERID hadid; if (acmDriverID((HACMOBJ)had, &hadid, 0) != MMSYSERR_NOERROR) return MMSYSERR_INVALHANDLE; MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid), had, pafd, &wfxRef, fnCallback, dwInstance, fdwEnum); 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) continue; ret = MSACM_FormatEnumHelper(padid, had, pafd, &wfxRef, fnCallback, dwInstance, fdwEnum); acmDriverClose(had, 0); if (!ret) break; } return MMSYSERR_NOERROR; }
/*********************************************************************** * acmFilterDetailsW (MSACM32.@) */ MMRESULT WINAPI acmFilterDetailsW(HACMDRIVER had, PACMFILTERDETAILSW pafd, DWORD fdwDetails) { MMRESULT mmr; ACMFILTERTAGDETAILSA aftd; TRACE("(%p, %p, %d)\n", had, pafd, fdwDetails); memset(&aftd, 0, sizeof(aftd)); aftd.cbStruct = sizeof(aftd); if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM; switch (fdwDetails) { case ACM_FILTERDETAILSF_FILTER: if (pafd->dwFilterTag != pafd->pwfltr->dwFilterTag) { mmr = MMSYSERR_INVALPARAM; break; } if (had == NULL) { PWINE_ACMDRIVERID padid; mmr = ACMERR_NOTPOSSIBLE; for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { /* should check for codec only */ if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, (LPARAM)pafd, (LPARAM)fdwDetails); acmDriverClose(had, 0); if (mmr == MMSYSERR_NOERROR) break; } } } else { mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, (LPARAM)pafd, fdwDetails); } break; case ACM_FILTERDETAILSF_INDEX: /* should check pafd->dwFilterIndex < aftd->cStandardFilters */ mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, (LPARAM)pafd, fdwDetails); break; default: WARN("Unknown fdwDetails %08x\n", fdwDetails); mmr = MMSYSERR_INVALFLAG; break; } TRACE("=> %d\n", mmr); return mmr; }
/*********************************************************************** * acmFormatSuggest (MSACM32.@) */ MMRESULT WINAPI acmFormatSuggest(HACMDRIVER had, PWAVEFORMATEX pwfxSrc, PWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest) { ACMDRVFORMATSUGGEST adfg; MMRESULT mmr; TRACE("(%p, %p, %p, %d, %d)\n", had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest); if (!pwfxSrc || !pwfxDst) return MMSYSERR_INVALPARAM; if (fdwSuggest & ~(ACM_FORMATSUGGESTF_NCHANNELS|ACM_FORMATSUGGESTF_NSAMPLESPERSEC| ACM_FORMATSUGGESTF_WBITSPERSAMPLE|ACM_FORMATSUGGESTF_WFORMATTAG)) return MMSYSERR_INVALFLAG; adfg.cbStruct = sizeof(adfg); adfg.fdwSuggest = fdwSuggest; adfg.pwfxSrc = pwfxSrc; adfg.cbwfxSrc = (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) ? sizeof(WAVEFORMATEX) : (sizeof(WAVEFORMATEX) + pwfxSrc->cbSize); adfg.pwfxDst = pwfxDst; adfg.cbwfxDst = cbwfxDst; if (had == NULL) { PWINE_ACMDRIVERID padid; /* MS doc says: ACM finds the best suggestion. * Well, first found will be the "best" */ mmr = ACMERR_NOTPOSSIBLE; 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) continue; if (MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L) == MMSYSERR_NOERROR) { mmr = MMSYSERR_NOERROR; break; } acmDriverClose(had, 0); } } else { mmr = MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L); } return mmr; }
BOOL CALLBACK acmDriverEnumCallback( HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport ){ MMRESULT mmr; HACMDRIVER driver; int i; ACMDRIVERDETAILS details; details.cbStruct = sizeof(ACMDRIVERDETAILS); mmr = acmDriverDetails( hadid, &details, 0 ); mmr = acmDriverOpen( &driver, hadid, 0 ); for(i = 0; i < details.cFormatTags; i++ ){ ACMFORMATTAGDETAILS fmtDetails; ZeroMemory( &fmtDetails, sizeof(fmtDetails) ); fmtDetails.cbStruct = sizeof(ACMFORMATTAGDETAILS); fmtDetails.dwFormatTagIndex = i; mmr = acmFormatTagDetails( driver, &fmtDetails, ACM_FORMATTAGDETAILSF_INDEX ); if( fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC ) { /* fprintf(stderr, "supported codec: %s\n" ,details.szLongName ); */ if( fmtDetails.dwFormatTag == WAVE_FORMAT_MSG723 ) { g_g723Drivers = /* 1 */ 0; /* ! fprintf(stderr, "Find Codec %s\n" ,details.szLongName ); */ #if 0 fprintf(stderr, "G723 cFormatTags %i\n" ,details.cFormatTags ); fprintf(stderr, "G723 cFilterTags %i\n" ,details.cFilterTags); #endif return -1; } else if( fmtDetails.dwFormatTag == WAVE_FORMAT_GSM610 ) { g_gsmDrivers = 1; /* ! fprintf(stderr, "Find Codec %s\n" ,details.szLongName ); */ return -1; } } else { /* ! fprintf(stderr, "Unsupported codec: %s\n" ,details.szLongName ); */ } } mmr = acmDriverClose( driver, 0 ); return -1; }
/*********************************************************************** * acmStreamClose (MSACM32.@) */ MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose) { PWINE_ACMSTREAM was; MMRESULT ret; TRACE("(%p, %d)\n", has, fdwClose); if ((was = ACM_GetStream(has)) == NULL) { WARN("invalid handle\n"); return MMSYSERR_INVALHANDLE; } ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_CLOSE, (LPARAM)&was->drvInst, 0); if (ret == MMSYSERR_NOERROR) { if (was->hAcmDriver) acmDriverClose(was->hAcmDriver, 0L); HeapFree(MSACM_hHeap, 0, was); } TRACE("=> (%d)\n", ret); return ret; }
MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose) { PWINE_ACMSTREAM was; MMRESULT ret; TRACE("(0x%08x, %ld)\n", has, fdwClose); if ((was = ACM_GetStream(has)) == NULL) { return MMSYSERR_INVALHANDLE; } ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CLOSE, (DWORD)&was->drvInst, 0); if (ret == MMSYSERR_NOERROR) { if (was->hAcmDriver) acmDriverClose(was->hAcmDriver, 0L); HeapFree(MSACM_hHeap, 0, was); CodecRelease(); } TRACE("=> (%d)\n", ret); return ret; }
/*********************************************************************** * acmDriverDetailsW (MSACM32.@) */ MMRESULT WINAPI acmDriverDetailsW(HACMDRIVERID hadid, PACMDRIVERDETAILSW padd, DWORD fdwDetails) { HACMDRIVER acmDrvr; MMRESULT mmr; TRACE("(%p, %p, %08x)\n", hadid, padd, fdwDetails); if (!padd) { WARN("invalid parameter\n"); return MMSYSERR_INVALPARAM; } if (padd->cbStruct < 4) { WARN("invalid parameter\n"); return MMSYSERR_INVALPARAM; } if (fdwDetails) { WARN("invalid flag\n"); return MMSYSERR_INVALFLAG; } mmr = acmDriverOpen(&acmDrvr, hadid, 0); if (mmr == MMSYSERR_NOERROR) { ACMDRIVERDETAILSW paddw; paddw.cbStruct = sizeof(paddw); mmr = MSACM_Message(acmDrvr, ACMDM_DRIVER_DETAILS, (LPARAM)&paddw, 0); acmDriverClose(acmDrvr, 0); paddw.cbStruct = min(padd->cbStruct, sizeof(*padd)); memcpy(padd, &paddw, paddw.cbStruct); } else if (mmr == MMSYSERR_NODRIVER) return MMSYSERR_NOTSUPPORTED; return mmr; }
/*********************************************************************** * acmFilterEnumW (MSACM32.@) */ MMRESULT WINAPI acmFilterEnumW(HACMDRIVER had, PACMFILTERDETAILSW pafd, ACMFILTERENUMCBW fnCallback, DWORD_PTR dwInstance, DWORD fdwEnum) { PWINE_ACMDRIVERID padid; BOOL ret; TRACE("(%p, %p, %p, %ld, %d)\n", had, pafd, fnCallback, dwInstance, fdwEnum); if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM; if (fdwEnum & ~(ACM_FILTERENUMF_DWFILTERTAG)) FIXME("Unsupported fdwEnum values\n"); if (had) { HACMDRIVERID hadid; if (acmDriverID((HACMOBJ)had, &hadid, 0) != MMSYSERR_NOERROR) return MMSYSERR_INVALHANDLE; MSACM_FilterEnumHelper(MSACM_GetDriverID(hadid), had, pafd, fnCallback, dwInstance, fdwEnum); 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) continue; ret = MSACM_FilterEnumHelper(padid, had, pafd, fnCallback, dwInstance, fdwEnum); acmDriverClose(had, 0); if (!ret) break; } return MMSYSERR_NOERROR; }
/*********************************************************************** * acmFormatTagEnumW (MSACM32.@) */ MMRESULT WINAPI acmFormatTagEnumW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd, ACMFORMATTAGENUMCBW fnCallback, DWORD dwInstance, DWORD fdwEnum) { PWINE_ACMDRIVERID padid; unsigned int i; BOOL bPcmDone = FALSE; TRACE("(%p, %p, %p, %d, %d)\n", had, paftd, fnCallback, dwInstance, fdwEnum); if (!paftd) return MMSYSERR_INVALPARAM; if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM; if (fdwEnum != 0) return MMSYSERR_INVALFLAG; /* (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; } } } /* 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; }
/*********************************************************************** * acmFormatTagDetailsW (MSACM32.@) */ MMRESULT WINAPI acmFormatTagDetailsW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd, DWORD fdwDetails) { PWINE_ACMDRIVERID padid; MMRESULT mmr = ACMERR_NOTPOSSIBLE; TRACE("(%p, %p, %d)\n", had, paftd, fdwDetails); if (fdwDetails & ~(ACM_FORMATTAGDETAILSF_FORMATTAG|ACM_FORMATTAGDETAILSF_INDEX| ACM_FORMATTAGDETAILSF_LARGESTSIZE)) return MMSYSERR_INVALFLAG; switch (fdwDetails) { case ACM_FORMATTAGDETAILSF_FORMATTAG: if (had == NULL) { for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { /* should check for codec only */ if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && MSACM_FindFormatTagInCache(padid, paftd->dwFormatTag, NULL) && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); acmDriverClose(had, 0); if (mmr == MMSYSERR_NOERROR) break; } } } else { PWINE_ACMDRIVER pad = MSACM_GetDriver(had); if (pad && MSACM_FindFormatTagInCache(pad->obj.pACMDriverID, paftd->dwFormatTag, NULL)) mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); } break; case ACM_FORMATTAGDETAILSF_INDEX: if (had != NULL) { PWINE_ACMDRIVER pad = MSACM_GetDriver(had); if (pad && paftd->dwFormatTagIndex < pad->obj.pACMDriverID->cFormatTags) mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); } break; case ACM_FORMATTAGDETAILSF_LARGESTSIZE: if (had == NULL) { ACMFORMATTAGDETAILSW tmp; DWORD ft = paftd->dwFormatTag; for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { /* should check for codec only */ if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { memset(&tmp, 0, sizeof(tmp)); tmp.cbStruct = sizeof(tmp); tmp.dwFormatTag = ft; if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) { if (mmr == ACMERR_NOTPOSSIBLE || paftd->cbFormatSize < tmp.cbFormatSize) { *paftd = tmp; mmr = MMSYSERR_NOERROR; } } acmDriverClose(had, 0); } } } else { mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); } break; default: WARN("Unsupported fdwDetails=%08x\n", fdwDetails); mmr = MMSYSERR_ERROR; } if (mmr == MMSYSERR_NOERROR && paftd->dwFormatTag == WAVE_FORMAT_PCM && paftd->szFormatTag[0] == 0) MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag, sizeof(paftd->szFormatTag)/sizeof(WCHAR) ); return mmr; }
static BOOL CALLBACK MSACM_FillFormatTagsCB(HACMDRIVERID hadid, PACMFORMATTAGDETAILSA paftd, DWORD dwInstance, DWORD fdwSupport) { struct MSACM_FillFormatData* affd = (struct MSACM_FillFormatData*)dwInstance; switch (affd->mode) { case WINE_ACMFF_TAG: if (SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)paftd->szFormatTag) == CB_ERR) SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_ADDSTRING, 0, (DWORD)paftd->szFormatTag); break; case WINE_ACMFF_FORMAT: if (strcmp(affd->szFormatTag, paftd->szFormatTag) == 0) { HACMDRIVER had; if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) { ACMFORMATDETAILSA afd; unsigned int i, len; MMRESULT mmr; char buffer[ACMFORMATDETAILS_FORMAT_CHARS+16]; afd.cbStruct = sizeof(afd); afd.dwFormatTag = paftd->dwFormatTag; afd.pwfx = HeapAlloc(MSACM_hHeap, 0, paftd->cbFormatSize); if (!afd.pwfx) return FALSE; afd.pwfx->wFormatTag = paftd->dwFormatTag; afd.pwfx->cbSize = paftd->cbFormatSize; afd.cbwfx = paftd->cbFormatSize; for (i = 0; i < paftd->cStandardFormats; i++) { afd.dwFormatIndex = i; mmr = acmFormatDetailsA(had, &afd, ACM_FORMATDETAILSF_INDEX); if (mmr == MMSYSERR_NOERROR) { lstrcpynA(buffer, afd.szFormat, ACMFORMATTAGDETAILS_FORMATTAG_CHARS + 1); len = strlen(buffer); memset(buffer+len, ' ', ACMFORMATTAGDETAILS_FORMATTAG_CHARS - len); wsprintfA(buffer + ACMFORMATTAGDETAILS_FORMATTAG_CHARS, "%d Ko/s", (afd.pwfx->nAvgBytesPerSec + 512) / 1024); SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_ADDSTRING, 0, (DWORD)buffer); } } acmDriverClose(had, 0); SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_SETCURSEL, 0, 0); HeapFree(MSACM_hHeap, 0, afd.pwfx); } } break; case WINE_ACMFF_WFX: if (strcmp(affd->szFormatTag, paftd->szFormatTag) == 0) { HACMDRIVER had; if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) { ACMFORMATDETAILSA afd; afd.cbStruct = sizeof(afd); afd.dwFormatTag = paftd->dwFormatTag; afd.pwfx = affd->afc->pwfx; afd.cbwfx = affd->afc->cbwfx; afd.dwFormatIndex = SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_GETCURSEL, 0, 0); affd->ret = acmFormatDetailsA(had, &afd, ACM_FORMATDETAILSF_INDEX); acmDriverClose(had, 0); return TRUE; } } break; default: FIXME("Unknown mode (%d)\n", affd->mode); break; } return TRUE; }
void acm_cv_shutdown (void) { if (hDrv) acmDriverClose(hDrv, 0); hDrv = 0; }
/*********************************************************************** * acmStreamOpen (MSACM32.@) */ MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc, PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) { PWINE_ACMSTREAM was; PWINE_ACMDRIVER wad; MMRESULT ret; int wfxSrcSize; int wfxDstSize; WAVEFORMATEX wfxSrc, wfxDst; TRACE("(%p, %p, %p, %p, %p, %ld, %ld, %d)\n", phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen); /* NOTE: pwfxSrc and/or pwfxDst can point to a structure smaller than * WAVEFORMATEX so don't use them directly when not sure */ if (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) { memcpy(&wfxSrc, pwfxSrc, sizeof(PCMWAVEFORMAT)); wfxSrc.wBitsPerSample = pwfxSrc->wBitsPerSample; wfxSrc.cbSize = 0; pwfxSrc = &wfxSrc; } if (pwfxDst->wFormatTag == WAVE_FORMAT_PCM) { memcpy(&wfxDst, pwfxDst, sizeof(PCMWAVEFORMAT)); wfxDst.wBitsPerSample = pwfxDst->wBitsPerSample; wfxDst.cbSize = 0; pwfxDst = &wfxDst; } TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n", pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec, pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize); TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n", pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec, pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize); /* (WS) In query mode, phas should be NULL. If it is not, then instead * of returning an error we are making sure it is NULL, preventing some * applications that pass garbage for phas from crashing. */ if (fdwOpen & ACM_STREAMOPENF_QUERY) phas = NULL; if (pwfltr && (pwfxSrc->wFormatTag != pwfxDst->wFormatTag)) { WARN("invalid parameter\n"); return MMSYSERR_INVALPARAM; } wfxSrcSize = wfxDstSize = sizeof(WAVEFORMATEX); if (pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) wfxSrcSize += pwfxSrc->cbSize; if (pwfxDst->wFormatTag != WAVE_FORMAT_PCM) wfxDstSize += pwfxDst->cbSize; was = HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + ((pwfltr) ? sizeof(WAVEFILTER) : 0)); if (was == NULL) { WARN("no memory\n"); return MMSYSERR_NOMEM; } was->drvInst.cbStruct = sizeof(was->drvInst); was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was)); memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize); was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize); memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize); if (pwfltr) { was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize); memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER)); } else { was->drvInst.pwfltr = NULL; } was->drvInst.dwCallback = dwCallback; was->drvInst.dwInstance = dwInstance; was->drvInst.fdwOpen = fdwOpen; was->drvInst.fdwDriver = 0L; was->drvInst.dwDriver = 0L; /* real value will be stored once ACMDM_STREAM_OPEN succeeds */ was->drvInst.has = 0L; if (had) { if (!(wad = MSACM_GetDriver(had))) { ret = MMSYSERR_INVALPARAM; goto errCleanUp; } was->obj.dwType = WINE_ACMOBJ_STREAM; was->obj.pACMDriverID = wad->obj.pACMDriverID; was->pDrv = wad; was->hAcmDriver = 0; /* not to close it in acmStreamClose */ ret = MSACM_Message((HACMDRIVER)wad, ACMDM_STREAM_OPEN, (LPARAM)&was->drvInst, 0L); if (ret != MMSYSERR_NOERROR) goto errCleanUp; } else { PWINE_ACMDRIVERID wadi; ret = ACMERR_NOTPOSSIBLE; for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID) { if ((wadi->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) || !MSACM_FindFormatTagInCache(wadi, pwfxSrc->wFormatTag, NULL) || !MSACM_FindFormatTagInCache(wadi, pwfxDst->wFormatTag, NULL)) continue; ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L); if (ret != MMSYSERR_NOERROR) continue; if ((wad = MSACM_GetDriver(had)) != 0) { was->obj.dwType = WINE_ACMOBJ_STREAM; was->obj.pACMDriverID = wad->obj.pACMDriverID; was->pDrv = wad; was->hAcmDriver = had; ret = MSACM_Message((HACMDRIVER)wad, ACMDM_STREAM_OPEN, (LPARAM)&was->drvInst, 0L); TRACE("%s => %08x\n", debugstr_w(wadi->pszDriverAlias), ret); if (ret == MMSYSERR_NOERROR) { if (fdwOpen & ACM_STREAMOPENF_QUERY) { MSACM_Message((HACMDRIVER)wad, ACMDM_STREAM_CLOSE, (LPARAM)&was->drvInst, 0); acmDriverClose(had, 0L); } break; } } /* no match, close this acm driver and try next one */ acmDriverClose(had, 0L); } if (ret != MMSYSERR_NOERROR) { ret = ACMERR_NOTPOSSIBLE; goto errCleanUp; } } ret = MMSYSERR_NOERROR; was->drvInst.has = (HACMSTREAM)was; if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) { if (phas) *phas = (HACMSTREAM)was; TRACE("=> (%d)\n", ret); return ret; } errCleanUp: if (phas) *phas = NULL; HeapFree(MSACM_hHeap, 0, was); TRACE("=> (%d)\n", ret); return ret; }
/*********************************************************************** * acmDriverMessage (MSACM32.@) * * Note: MSDN documentation (July 2001) is incomplete. This function * accepts sending messages to an HACMDRIVERID in addition to the * documented HACMDRIVER. In fact, for DRV_QUERYCONFIGURE and DRV_CONFIGURE, * this might actually be the required mode of operation. * * Note: For DRV_CONFIGURE, msacm supplies its own DRVCONFIGINFO structure * when the application fails to supply one. Some native drivers depend on * this and refuse to display unless a valid DRVCONFIGINFO structure is * built and supplied. */ LRESULT WINAPI acmDriverMessage(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2) { TRACE("(%p, %04x, %08lx, %08lx\n", had, uMsg, lParam1, lParam2); if ((uMsg >= ACMDM_USER && uMsg < ACMDM_RESERVED_LOW) || uMsg == ACMDM_DRIVER_ABOUT || uMsg == DRV_QUERYCONFIGURE || uMsg == DRV_CONFIGURE) { PWINE_ACMDRIVERID padid; LRESULT lResult; LPDRVCONFIGINFO pConfigInfo = NULL; LPWSTR section_name = NULL; LPWSTR alias_name = NULL; /* Check whether handle is an HACMDRIVERID */ padid = MSACM_GetDriverID((HACMDRIVERID)had); /* If the message is DRV_CONFIGURE, and the application provides no DRVCONFIGINFO structure, msacm must supply its own. */ if (uMsg == DRV_CONFIGURE && lParam2 == 0) { LPWSTR pAlias; /* Get the alias from the HACMDRIVERID */ if (padid) { pAlias = padid->pszDriverAlias; if (pAlias == NULL) { WARN("DRV_CONFIGURE: no alias for this driver, cannot self-supply alias\n"); } } else { FIXME("DRV_CONFIGURE: reverse lookup HACMDRIVER -> HACMDRIVERID not implemented\n"); pAlias = NULL; } if (pAlias != NULL) { /* DRVCONFIGINFO is only 12 bytes long, but native msacm * reports a 16-byte structure to codecs, so allocate 16 bytes, * just to be on the safe side. */ const unsigned int iStructSize = 16; pConfigInfo = HeapAlloc(MSACM_hHeap, 0, iStructSize); if (!pConfigInfo) { ERR("OOM while supplying DRVCONFIGINFO for DRV_CONFIGURE, using NULL\n"); } else { static const WCHAR drivers32[] = {'D','r','i','v','e','r','s','3','2','\0'}; pConfigInfo->dwDCISize = iStructSize; section_name = HeapAlloc(MSACM_hHeap, 0, (strlenW(drivers32) + 1) * sizeof(WCHAR)); if (section_name) strcpyW(section_name, drivers32); pConfigInfo->lpszDCISectionName = section_name; alias_name = HeapAlloc(MSACM_hHeap, 0, (strlenW(pAlias) + 1) * sizeof(WCHAR)); if (alias_name) strcpyW(alias_name, pAlias); pConfigInfo->lpszDCIAliasName = alias_name; if (pConfigInfo->lpszDCISectionName == NULL || pConfigInfo->lpszDCIAliasName == NULL) { HeapFree(MSACM_hHeap, 0, alias_name); HeapFree(MSACM_hHeap, 0, section_name); HeapFree(MSACM_hHeap, 0, pConfigInfo); pConfigInfo = NULL; ERR("OOM while supplying DRVCONFIGINFO for DRV_CONFIGURE, using NULL\n"); } } } lParam2 = (LPARAM)pConfigInfo; } if (padid) { /* Handle is really an HACMDRIVERID, must have an open session to get an HACMDRIVER */ if (padid->pACMDriverList != NULL) { lResult = MSACM_Message((HACMDRIVER)padid->pACMDriverList, uMsg, lParam1, lParam2); } else { MMRESULT mmr = acmDriverOpen(&had, (HACMDRIVERID)padid, 0); if (mmr != MMSYSERR_NOERROR) { lResult = MMSYSERR_INVALPARAM; } else { lResult = acmDriverMessage(had, uMsg, lParam1, lParam2); acmDriverClose(had, 0); } } } else { lResult = MSACM_Message(had, uMsg, lParam1, lParam2); } if (pConfigInfo) { HeapFree(MSACM_hHeap, 0, alias_name); HeapFree(MSACM_hHeap, 0, section_name); HeapFree(MSACM_hHeap, 0, pConfigInfo); } return lResult; } WARN("invalid parameter\n"); return MMSYSERR_INVALPARAM; }
static BOOL CALLBACK DriverEnumProc(HACMDRIVERID hadid, DWORD_PTR dwInstance, DWORD fdwSupport) { MMRESULT rc; ACMDRIVERDETAILSA dd; HACMDRIVER had; DWORD dwDriverPriority; DWORD dwDriverSupport; if (winetest_interactive) { trace("id: %p\n", hadid); trace(" Supports:\n"); if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_ASYNC) trace(" async conversions\n"); if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC) trace(" different format conversions\n"); if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CONVERTER) trace(" same format conversions\n"); if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_FILTER) trace(" filtering\n"); } /* try an invalid pointer */ rc = acmDriverDetailsA(hadid, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmDriverDetailsA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try an invalid structure size */ ZeroMemory(&dd, sizeof(dd)); rc = acmDriverDetailsA(hadid, &dd, 0); ok(rc == MMSYSERR_INVALPARAM, "acmDriverDetailsA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* MSDN says this should fail but it doesn't in practice */ dd.cbStruct = 4; rc = acmDriverDetailsA(hadid, &dd, 0); ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NOTSUPPORTED, "acmDriverDetailsA(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* try an invalid handle */ dd.cbStruct = sizeof(dd); rc = acmDriverDetailsA((HACMDRIVERID)1, &dd, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverDetailsA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try an invalid handle and pointer */ rc = acmDriverDetailsA((HACMDRIVERID)1, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmDriverDetailsA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try invalid details */ rc = acmDriverDetailsA(hadid, &dd, -1); ok(rc == MMSYSERR_INVALFLAG, "acmDriverDetailsA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALFLAG); /* try valid parameters */ rc = acmDriverDetailsA(hadid, &dd, 0); ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NOTSUPPORTED, "acmDriverDetailsA(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* cbStruct should contain size of returned data (at most sizeof(dd)) TODO: should it be *exactly* sizeof(dd), as tested here? */ if (rc == MMSYSERR_NOERROR) { static const struct { const char *shortname; WORD mid; WORD pid; WORD pid_alt; } *iter, expected_ids[] = { { "Microsoft IMA ADPCM", MM_MICROSOFT, MM_MSFT_ACM_IMAADPCM }, { "MS-ADPCM", MM_MICROSOFT, MM_MSFT_ACM_MSADPCM }, { "Microsoft CCITT G.711", MM_MICROSOFT, MM_MSFT_ACM_G711}, { "MPEG Layer-3 Codec", MM_FRAUNHOFER_IIS, MM_FHGIIS_MPEGLAYER3_DECODE, MM_FHGIIS_MPEGLAYER3_PROFESSIONAL }, { "MS-PCM", MM_MICROSOFT, MM_MSFT_ACM_PCM }, { 0 } }; ok(dd.cbStruct == sizeof(dd), "acmDriverDetailsA(): cbStruct = %08x\n", dd.cbStruct); for (iter = expected_ids; iter->shortname; ++iter) { if (!strcmp(iter->shortname, dd.szShortName)) { /* try alternative product id on mismatch */ if (iter->pid_alt && iter->pid != dd.wPid) ok(iter->mid == dd.wMid && iter->pid_alt == dd.wPid, "Got wrong manufacturer (0x%x vs 0x%x) or product (0x%x vs 0x%x)\n", dd.wMid, iter->mid, dd.wPid, iter->pid_alt); else ok(iter->mid == dd.wMid && iter->pid == dd.wPid, "Got wrong manufacturer (0x%x vs 0x%x) or product (0x%x vs 0x%x)\n", dd.wMid, iter->mid, dd.wPid, iter->pid); } } } if (rc == MMSYSERR_NOERROR && winetest_interactive) { trace(" Short name: %s\n", dd.szShortName); trace(" Long name: %s\n", dd.szLongName); trace(" Copyright: %s\n", dd.szCopyright); trace(" Licensing: %s\n", dd.szLicensing); trace(" Features: %s\n", dd.szFeatures); trace(" Supports %u formats\n", dd.cFormatTags); trace(" Supports %u filter formats\n", dd.cFilterTags); trace(" Mid: 0x%x\n", dd.wMid); trace(" Pid: 0x%x\n", dd.wPid); } /* try bad pointer */ rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_PRIORITY, 0); ok(rc == MMSYSERR_INVALPARAM, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_PRIORITY, &dwDriverPriority); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try bad pointer and handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_PRIORITY, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try valid parameters */ rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_PRIORITY, &dwDriverSupport); ok(rc == MMSYSERR_NOERROR, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* try bad pointer */ rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_SUPPORT, 0); ok(rc == MMSYSERR_INVALPARAM, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_SUPPORT, &dwDriverSupport); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try bad pointer and handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_SUPPORT, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try valid parameters */ rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_SUPPORT, &dwDriverSupport); ok(rc == MMSYSERR_NOERROR, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* try invalid pointer */ rc = acmDriverOpen(0, hadid, 0); ok(rc == MMSYSERR_INVALPARAM, "acmDriverOpen(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try invalid handle */ rc = acmDriverOpen(&had, (HACMDRIVERID)1, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverOpen(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try invalid open */ rc = acmDriverOpen(&had, hadid, -1); ok(rc == MMSYSERR_INVALFLAG, "acmDriverOpen(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALFLAG); /* try valid parameters */ rc = acmDriverOpen(&had, hadid, 0); ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NODRIVER, "acmDriverOpen(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); if (rc == MMSYSERR_NOERROR) { DWORD dwSize; HACMDRIVERID hid; /* try bad pointer */ rc = acmDriverID((HACMOBJ)had, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmDriverID(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad handle */ rc = acmDriverID((HACMOBJ)1, &hid, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverID(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try bad handle and pointer */ rc = acmDriverID((HACMOBJ)1, 0, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverID(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try bad flag */ rc = acmDriverID((HACMOBJ)had, &hid, 1); ok(rc == MMSYSERR_INVALFLAG, "acmDriverID(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALFLAG); /* try valid parameters */ rc = acmDriverID((HACMOBJ)had, &hid, 0); ok(rc == MMSYSERR_NOERROR, "acmDriverID(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); ok(hid == hadid, "acmDriverID() returned ID %p doesn't equal %p\n", hid, hadid); /* try bad pointer */ rc = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, 0); ok(rc == MMSYSERR_INVALPARAM, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try bad pointer and handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_MAX_SIZE_FORMAT, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try valid parameters */ rc = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize); ok(rc == MMSYSERR_NOERROR, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); if (rc == MMSYSERR_NOERROR) { ACMFORMATDETAILSA fd; WAVEFORMATEX * pwfx; ACMFORMATTAGDETAILSA aftd; /* try bad pointer */ rc = acmFormatEnumA(had, 0, FormatEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatEnumA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad structure size */ ZeroMemory(&fd, sizeof(fd)); rc = acmFormatEnumA(had, &fd, FormatEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatEnumA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); fd.cbStruct = sizeof(fd) - 1; rc = acmFormatEnumA(had, &fd, FormatEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatEnumA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); if (dwSize < sizeof(WAVEFORMATEX)) dwSize = sizeof(WAVEFORMATEX); pwfx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); pwfx->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX); pwfx->wFormatTag = WAVE_FORMAT_UNKNOWN; fd.cbStruct = sizeof(fd); fd.pwfx = pwfx; fd.cbwfx = dwSize; fd.dwFormatTag = WAVE_FORMAT_UNKNOWN; /* try valid parameters */ rc = acmFormatEnumA(had, &fd, FormatEnumProc, 0, 0); ok(rc == MMSYSERR_NOERROR, "acmFormatEnumA(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* try bad pointer */ rc = acmFormatTagEnumA(had, 0, FormatTagEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatTagEnumA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad structure size */ ZeroMemory(&aftd, sizeof(aftd)); rc = acmFormatTagEnumA(had, &aftd, FormatTagEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatTagEnumA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); aftd.cbStruct = sizeof(aftd) - 1; rc = acmFormatTagEnumA(had, &aftd, FormatTagEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatTagEnumA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); aftd.cbStruct = sizeof(aftd); aftd.dwFormatTag = WAVE_FORMAT_UNKNOWN; /* try bad flag */ rc = acmFormatTagEnumA(had, &aftd, FormatTagEnumProc, 0, 1); ok(rc == MMSYSERR_INVALFLAG, "acmFormatTagEnumA(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALFLAG); /* try valid parameters */ rc = acmFormatTagEnumA(had, &aftd, FormatTagEnumProc, 0, 0); ok(rc == MMSYSERR_NOERROR, "acmFormatTagEnumA(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); HeapFree(GetProcessHeap(), 0, pwfx); /* try invalid handle */ rc = acmDriverClose((HACMDRIVER)1, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverClose(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try invalid flag */ rc = acmDriverClose(had, 1); ok(rc == MMSYSERR_INVALFLAG, "acmDriverClose(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALFLAG); /* try valid parameters */ rc = acmDriverClose(had, 0); ok(rc == MMSYSERR_NOERROR, "acmDriverClose(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* try closing again */ rc = acmDriverClose(had, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverClose(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); } } return TRUE; }
bool VDAudioCodecW32::Init(const WAVEFORMATEX *pSrcFormat, const WAVEFORMATEX *pDstFormat, bool isCompression, const char *pDriverShortNameHint, bool throwOnError) { Shutdown(); SafeCopyWaveFormat(mSrcFormat, (const VDWaveFormat *)pSrcFormat); if (pDstFormat) SafeCopyWaveFormat(mDstFormat, (const VDWaveFormat *)pDstFormat); // enumerate IDs for all installed codecs ACMDriverList driverList(pDriverShortNameHint); // try one driver at a time MMRESULT res = 0; for(ACMDriverList::const_iterator it(driverList.begin()), itEnd(driverList.end()); it != itEnd; ++it) { const HACMDRIVERID driverId = *it; // open driver HACMDRIVER hDriver = NULL; if (acmDriverOpen(&hDriver, *it, 0)) continue; if (!pDstFormat) { VDASSERT(!isCompression); DWORD dwDstFormatSize = 0; VDVERIFY(!acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, (LPVOID)&dwDstFormatSize)); if (dwDstFormatSize < sizeof(WAVEFORMATEX)) dwDstFormatSize = sizeof(WAVEFORMATEX); mDstFormat.resize(dwDstFormatSize); memset(mDstFormat.data(), 0, dwDstFormatSize); mDstFormat->mTag = WAVE_FORMAT_PCM; if (acmFormatSuggest(hDriver, (WAVEFORMATEX *)pSrcFormat, (WAVEFORMATEX *)mDstFormat.data(), dwDstFormatSize, ACM_FORMATSUGGESTF_WFORMATTAG)) { acmDriverClose(hDriver, NULL); continue; } // sanitize the destination format a bit if (mDstFormat->mSampleBits != 8 && mDstFormat->mSampleBits != 16) mDstFormat->mSampleBits = 16; if (mDstFormat->mChannels != 1 && mDstFormat->mChannels !=2) mDstFormat->mChannels = 2; mDstFormat->mBlockSize = (uint16)((mDstFormat->mSampleBits >> 3) * mDstFormat->mChannels); mDstFormat->mDataRate = mDstFormat->mBlockSize * mDstFormat->mSamplingRate; mDstFormat->mExtraSize = 0; mDstFormat.resize(sizeof(WAVEFORMATEX)); } // open conversion stream res = acmStreamOpen(&mhStream, hDriver, (WAVEFORMATEX *)pSrcFormat, (WAVEFORMATEX *)mDstFormat.data(), NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME); if (!res) { mhDriver = hDriver; break; } // Aud-X accepts PCM/6ch but not WAVE_FORMAT_EXTENSIBLE/PCM/6ch. Argh. We attempt to work // around this by trying a PCM version if WFE doesn't work. if (isCompression) { // Need to put this somewhere. struct WaveFormatExtensibleW32 { WAVEFORMATEX mFormat; union { uint16 mBitDepth; uint16 mSamplesPerBlock; // may be zero, according to MSDN }; uint32 mChannelMask; GUID mGuid; }; static const GUID local_KSDATAFORMAT_SUBTYPE_PCM={ // so we don't have to bring in ksmedia.h WAVE_FORMAT_PCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }; if (pSrcFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE && pSrcFormat->cbSize >= sizeof(WaveFormatExtensibleW32) - sizeof(WAVEFORMATEX)) { const WaveFormatExtensibleW32& wfexex = *(const WaveFormatExtensibleW32 *)pSrcFormat; if (wfexex.mGuid == local_KSDATAFORMAT_SUBTYPE_PCM) { // Rewrite the format to be straight PCM and try again. vdstructex<VDWaveFormat> srcFormat2(mSrcFormat.data(), sizeof(VDWaveFormat)); srcFormat2->mExtraSize = 0; srcFormat2->mTag = WAVE_FORMAT_PCM; MMRESULT res2 = acmStreamOpen(&mhStream, hDriver, (WAVEFORMATEX *)srcFormat2.data(), (WAVEFORMATEX *)mDstFormat.data(), NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME); if (!res2) { res = res2; mSrcFormat = srcFormat2; pSrcFormat = (WAVEFORMATEX *)mSrcFormat.data(); mhDriver = hDriver; break; } } } } acmDriverClose(hDriver, 0); }
/*********************************************************************** * acmStreamOpen (MSACM32.40) */ MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc, PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD dwCallback, DWORD dwInstance, DWORD fdwOpen) { PWINE_ACMSTREAM was; PWINE_ACMDRIVER wad; MMRESULT ret; int wfxSrcSize; int wfxDstSize; TRACE("(%p, 0x%08x, %p, %p, %p, %ld, %ld, %ld)\n", phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen); TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n", pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec, pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize); TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n", pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec, pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize); #define SIZEOF_WFX(wfx) (sizeof(WAVEFORMATEX) + ((wfx->wFormatTag == WAVE_FORMAT_PCM) ? 0 : wfx->cbSize)) wfxSrcSize = SIZEOF_WFX(pwfxSrc); wfxDstSize = SIZEOF_WFX(pwfxDst); #undef SIZEOF_WFX was = (PWINE_ACMSTREAM) HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + ((pwfltr) ? sizeof(WAVEFILTER) : 0)); if (was == NULL) return MMSYSERR_NOMEM; was->drvInst.cbStruct = sizeof(was->drvInst); was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was)); memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize); // LHACM is checking for 0x1 // but if this will not help // was->drvInst.pwfxSrc->wFormatTag = 1; was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize); memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize); if (pwfltr) { was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize); memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER)); } else { was->drvInst.pwfltr = NULL; } was->drvInst.dwCallback = dwCallback; was->drvInst.dwInstance = dwInstance; was->drvInst.fdwOpen = fdwOpen; was->drvInst.fdwDriver = 0L; was->drvInst.dwDriver = 0L; was->drvInst.has = (HACMSTREAM)was; if (had) { if (!(wad = MSACM_GetDriver(had))) { ret = MMSYSERR_INVALPARAM; goto errCleanUp; } was->obj.pACMDriverID = wad->obj.pACMDriverID; was->pDrv = wad; was->hAcmDriver = 0; /* not to close it in acmStreamClose */ ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L); if (ret != MMSYSERR_NOERROR) goto errCleanUp; } else { PWINE_ACMDRIVERID wadi; /* short drv_tag; -- not used */ ret = ACMERR_NOTPOSSIBLE; /* if(pwfxSrc->wFormatTag==1)//compression drv_tag=pwfxDst->wFormatTag; else if(pwfxDst->wFormatTag==1)//decompression drv_tag=pwfxSrc->wFormatTag; else goto errCleanUp; ret=acmDriverOpen2(drv_tag); if (ret == MMSYSERR_NOERROR) { if ((wad = MSACM_GetDriver(had)) != 0) { was->obj.pACMDriverID = wad->obj.pACMDriverID; was->pDrv = wad; was->hAcmDriver = had; ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L); if (ret == MMSYSERR_NOERROR) { if (fdwOpen & ACM_STREAMOPENF_QUERY) { acmDriverClose(had, 0L); } break; } } acmDriverClose(had, 0L);*/ //if(MSACM_pFirstACMDriverID==NULL) // MSACM_RegisterAllDrivers(); for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID) { /* Check Format */ if ((int)wadi->wFormatTag != (int)pwfxSrc->wFormatTag) continue; ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L); if (ret == MMSYSERR_NOERROR) { if ((wad = MSACM_GetDriver(had)) != 0) { was->obj.pACMDriverID = wad->obj.pACMDriverID; was->pDrv = wad; was->hAcmDriver = had; ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L); //lhacm - crash printf("RETOPEN %d\n", ret); //ret = 0; if (ret == MMSYSERR_NOERROR) { if (fdwOpen & ACM_STREAMOPENF_QUERY) { acmDriverClose(had, 0L); } break; } } // no match, close this acm driver and try next one acmDriverClose(had, 0L); } } if (ret != MMSYSERR_NOERROR) { ret = ACMERR_NOTPOSSIBLE; goto errCleanUp; } } ret = MMSYSERR_NOERROR; if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) { if (phas) *phas = (HACMSTREAM)was; TRACE("=> (%d)\n", ret); CodecAlloc(); return ret; } errCleanUp: if (phas) *phas = (HACMSTREAM)0; HeapFree(MSACM_hHeap, 0, was); TRACE("=> (%d)\n", ret); return ret; }
static BOOL CALLBACK DriverEnumProc(HACMDRIVERID hadid, DWORD_PTR dwInstance, DWORD fdwSupport) { MMRESULT rc; ACMDRIVERDETAILS dd; HACMDRIVER had; DWORD dwDriverPriority; DWORD dwDriverSupport; if (winetest_interactive) { trace("id: %p\n", hadid); trace(" Supports:\n"); if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_ASYNC) trace(" async conversions\n"); if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC) trace(" different format conversions\n"); if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CONVERTER) trace(" same format conversions\n"); if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_FILTER) trace(" filtering\n"); } /* try an invalid pointer */ rc = acmDriverDetails(hadid, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmDriverDetails(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try an invalid structure size */ ZeroMemory(&dd, sizeof(dd)); rc = acmDriverDetails(hadid, &dd, 0); ok(rc == MMSYSERR_INVALPARAM, "acmDriverDetails(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* MSDN says this should fail but it doesn't in practice */ dd.cbStruct = 4; rc = acmDriverDetails(hadid, &dd, 0); ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NOTSUPPORTED, "acmDriverDetails(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* try an invalid handle */ dd.cbStruct = sizeof(dd); rc = acmDriverDetails((HACMDRIVERID)1, &dd, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverDetails(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try an invalid handle and pointer */ rc = acmDriverDetails((HACMDRIVERID)1, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmDriverDetails(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try invalid details */ rc = acmDriverDetails(hadid, &dd, -1); ok(rc == MMSYSERR_INVALFLAG, "acmDriverDetails(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALFLAG); /* try valid parameters */ rc = acmDriverDetails(hadid, &dd, 0); ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NOTSUPPORTED, "acmDriverDetails(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* cbStruct should contain size of returned data (at most sizeof(dd)) TODO: should it be *exactly* sizeof(dd), as tested here? */ if (rc == MMSYSERR_NOERROR) { ok(dd.cbStruct == sizeof(dd), "acmDriverDetails(): cbStruct = %08x\n", dd.cbStruct); } if (rc == MMSYSERR_NOERROR && winetest_interactive) { trace(" Short name: %s\n", dd.szShortName); trace(" Long name: %s\n", dd.szLongName); trace(" Copyright: %s\n", dd.szCopyright); trace(" Licensing: %s\n", dd.szLicensing); trace(" Features: %s\n", dd.szFeatures); trace(" Supports %u formats\n", dd.cFormatTags); trace(" Supports %u filter formats\n", dd.cFilterTags); } /* try bad pointer */ rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_PRIORITY, 0); ok(rc == MMSYSERR_INVALPARAM, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_PRIORITY, &dwDriverPriority); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try bad pointer and handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_PRIORITY, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try valid parameters */ rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_PRIORITY, &dwDriverSupport); ok(rc == MMSYSERR_NOERROR, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* try bad pointer */ rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_SUPPORT, 0); ok(rc == MMSYSERR_INVALPARAM, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_SUPPORT, &dwDriverSupport); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try bad pointer and handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_SUPPORT, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try valid parameters */ rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_SUPPORT, &dwDriverSupport); ok(rc == MMSYSERR_NOERROR, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* try invalid pointer */ rc = acmDriverOpen(0, hadid, 0); ok(rc == MMSYSERR_INVALPARAM, "acmDriverOpen(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try invalid handle */ rc = acmDriverOpen(&had, (HACMDRIVERID)1, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverOpen(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try invalid open */ rc = acmDriverOpen(&had, hadid, -1); ok(rc == MMSYSERR_INVALFLAG, "acmDriverOpen(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALFLAG); /* try valid parameters */ rc = acmDriverOpen(&had, hadid, 0); ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NODRIVER, "acmDriverOpen(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); if (rc == MMSYSERR_NOERROR) { DWORD dwSize; HACMDRIVERID hid; /* try bad pointer */ rc = acmDriverID((HACMOBJ)had, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmDriverID(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad handle */ rc = acmDriverID((HACMOBJ)1, &hid, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverID(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try bad handle and pointer */ rc = acmDriverID((HACMOBJ)1, 0, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverID(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try bad flag */ rc = acmDriverID((HACMOBJ)had, &hid, 1); ok(rc == MMSYSERR_INVALFLAG, "acmDriverID(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALFLAG); /* try valid parameters */ rc = acmDriverID((HACMOBJ)had, &hid, 0); ok(rc == MMSYSERR_NOERROR, "acmDriverID(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); ok(hid == hadid, "acmDriverID() returned ID %p doesn't equal %p\n", hid, hadid); /* try bad pointer */ rc = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, 0); ok(rc == MMSYSERR_INVALPARAM, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try bad pointer and handle */ rc = acmMetrics((HACMOBJ)1, ACM_METRIC_MAX_SIZE_FORMAT, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try valid parameters */ rc = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize); ok(rc == MMSYSERR_NOERROR, "acmMetrics(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); if (rc == MMSYSERR_NOERROR) { ACMFORMATDETAILS fd; WAVEFORMATEX * pwfx; ACMFORMATTAGDETAILS aftd; /* try bad pointer */ rc = acmFormatEnum(had, 0, FormatEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatEnum(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad structure size */ ZeroMemory(&fd, sizeof(fd)); rc = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatEnum(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); fd.cbStruct = sizeof(fd) - 1; rc = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatEnum(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); if (dwSize < sizeof(WAVEFORMATEX)) dwSize = sizeof(WAVEFORMATEX); pwfx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); pwfx->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX); pwfx->wFormatTag = WAVE_FORMAT_UNKNOWN; fd.cbStruct = sizeof(fd); fd.pwfx = pwfx; fd.cbwfx = dwSize; fd.dwFormatTag = WAVE_FORMAT_UNKNOWN; /* try valid parameters */ rc = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0); ok(rc == MMSYSERR_NOERROR, "acmFormatEnum(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* try bad pointer */ rc = acmFormatTagEnum(had, 0, FormatTagEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatTagEnum(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); /* try bad structure size */ ZeroMemory(&aftd, sizeof(aftd)); rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatTagEnum(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); aftd.cbStruct = sizeof(aftd) - 1; rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 0); ok(rc == MMSYSERR_INVALPARAM, "acmFormatTagEnum(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALPARAM); aftd.cbStruct = sizeof(aftd); aftd.dwFormatTag = WAVE_FORMAT_UNKNOWN; /* try bad flag */ rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 1); ok(rc == MMSYSERR_INVALFLAG, "acmFormatTagEnum(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALFLAG); /* try valid parameters */ rc = acmFormatTagEnum(had, &aftd, FormatTagEnumProc, 0, 0); ok(rc == MMSYSERR_NOERROR, "acmFormatTagEnum(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); HeapFree(GetProcessHeap(), 0, pwfx); /* try invalid handle */ rc = acmDriverClose((HACMDRIVER)1, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverClose(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); /* try invalid flag */ rc = acmDriverClose(had, 1); ok(rc == MMSYSERR_INVALFLAG, "acmDriverClose(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALFLAG); /* try valid parameters */ rc = acmDriverClose(had, 0); ok(rc == MMSYSERR_NOERROR, "acmDriverClose(): rc = %08x, should be %08x\n", rc, MMSYSERR_NOERROR); /* try closing again */ rc = acmDriverClose(had, 0); ok(rc == MMSYSERR_INVALHANDLE, "acmDriverClose(): rc = %08x, should be %08x\n", rc, MMSYSERR_INVALHANDLE); } } return TRUE; }