/*********************************************************************** * acmDriverRemove (MSACM32.@) */ MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove) { PWINE_ACMDRIVERID padid; PWINE_ACMNOTIFYWND panwnd; TRACE("(%p, %08x)\n", hadid, fdwRemove); padid = MSACM_GetDriverID(hadid); panwnd = MSACM_GetNotifyWnd(hadid); if (!padid && !panwnd) { WARN("invalid handle\n"); return MMSYSERR_INVALHANDLE; } if (fdwRemove) { WARN("invalid flag\n"); return MMSYSERR_INVALFLAG; } if (padid) MSACM_UnregisterDriver(padid); if (panwnd) MSACM_UnRegisterNotificationWindow(panwnd); MSACM_BroadcastNotification(); return MMSYSERR_NOERROR; }
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; }
/*********************************************************************** * acmDriverOpen (MSACM32.10) */ MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen) { PWINE_ACMDRIVERID padid; PWINE_ACMDRIVER pad; ICOPEN icopen; /* HDRVR hdrv; -- not used */ TRACE("(%p, %x, %08lu)\n", phad, hadid, fdwOpen); if (!phad) return MMSYSERR_INVALPARAM; padid = MSACM_GetDriverID(hadid); if (!padid) return MMSYSERR_INVALHANDLE; if (fdwOpen) return MMSYSERR_INVALFLAG; pad = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER)); if (!pad) return MMSYSERR_NOMEM; pad->obj.pACMDriverID = padid; icopen.fccType = mmioFOURCC('a', 'u', 'd', 'c'); icopen.fccHandler = (long)padid->pszFileName; icopen.dwSize = sizeof(ICOPEN); icopen.dwFlags = 0; icopen.pV1Reserved = padid->pszFileName; if (!padid->hInstModule) pad->hDrvr = OpenDriverA((long)&icopen); else pad->hDrvr = padid->hInstModule; if (!pad->hDrvr) { HeapFree(MSACM_hHeap, 0, pad); return MMSYSERR_ERROR; } pad->pfnDriverProc = GetProcAddress(pad->hDrvr, "DriverProc"); /* insert new pad at beg of list */ pad->pNextACMDriver = padid->pACMDriverList; padid->pACMDriverList = pad; /* FIXME: Create a WINE_ACMDRIVER32 */ *phad = (HACMDRIVER)pad; return MMSYSERR_NOERROR; }
/*********************************************************************** * acmDriverRemove (MSACM32.12) */ MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove) { PWINE_ACMDRIVERID padid; padid = MSACM_GetDriverID(hadid); if (!padid) return MMSYSERR_INVALHANDLE; if (fdwRemove) return MMSYSERR_INVALFLAG; MSACM_UnregisterDriver(padid); return MMSYSERR_NOERROR; }
/*********************************************************************** * 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; }
/*********************************************************************** * acmDriverPriority (MSACM32.@) */ MMRESULT WINAPI acmDriverPriority(HACMDRIVERID hadid, DWORD dwPriority, DWORD fdwPriority) { TRACE("(%p, %08x, %08x)\n", hadid, dwPriority, fdwPriority); /* Check for unknown flags */ if (fdwPriority & ~(ACM_DRIVERPRIORITYF_ENABLE|ACM_DRIVERPRIORITYF_DISABLE| ACM_DRIVERPRIORITYF_BEGIN|ACM_DRIVERPRIORITYF_END)) { WARN("invalid flag\n"); return MMSYSERR_INVALFLAG; } /* Check for incompatible flags */ if ((fdwPriority & ACM_DRIVERPRIORITYF_ENABLE) && (fdwPriority & ACM_DRIVERPRIORITYF_DISABLE)) { WARN("invalid flag\n"); return MMSYSERR_INVALFLAG; } /* Check for incompatible flags */ if ((fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) && (fdwPriority & ACM_DRIVERPRIORITYF_END)) { WARN("invalid flag\n"); return MMSYSERR_INVALFLAG; } /* According to MSDN, ACM_DRIVERPRIORITYF_BEGIN and ACM_DRIVERPRIORITYF_END may only appear by themselves, and in addition, hadid and dwPriority must both be zero */ if ((fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) || (fdwPriority & ACM_DRIVERPRIORITYF_END)) { if (fdwPriority & ~(ACM_DRIVERPRIORITYF_BEGIN|ACM_DRIVERPRIORITYF_END)) { WARN("ACM_DRIVERPRIORITYF_[BEGIN|END] cannot be used with any other flags\n"); return MMSYSERR_INVALPARAM; } if (dwPriority) { WARN("priority invalid with ACM_DRIVERPRIORITYF_[BEGIN|END]\n"); return MMSYSERR_INVALPARAM; } if (hadid) { WARN("non-null hadid invalid with ACM_DRIVERPRIORITYF_[BEGIN|END]\n"); return MMSYSERR_INVALPARAM; } /* FIXME: MSDN wording suggests that deferred notification should be implemented as a system-wide lock held by a calling task, and that re-enabling notifications should broadcast them across all processes. This implementation uses a simple DWORD counter. One consequence of the current implementation is that applications will never see MMSYSERR_ALLOCATED as a return error. */ if (fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) { MSACM_DisableNotifications(); } else if (fdwPriority & ACM_DRIVERPRIORITYF_END) { MSACM_EnableNotifications(); } return MMSYSERR_NOERROR; } else { PWINE_ACMDRIVERID padid; PWINE_ACMNOTIFYWND panwnd; BOOL bPerformBroadcast = FALSE; /* Fetch driver ID */ padid = MSACM_GetDriverID(hadid); panwnd = MSACM_GetNotifyWnd(hadid); if (!padid && !panwnd) { WARN("invalid handle\n"); return MMSYSERR_INVALHANDLE; } if (padid) { /* Check whether driver ID is appropriate for requested op */ if (dwPriority) { if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL) { return MMSYSERR_NOTSUPPORTED; } if (dwPriority != 1 && dwPriority != (DWORD)-1) { FIXME("unexpected priority %d, using sign only\n", dwPriority); if ((signed)dwPriority < 0) dwPriority = (DWORD)-1; if (dwPriority > 0) dwPriority = 1; } if (dwPriority == 1 && (padid->pPrevACMDriverID == NULL || (padid->pPrevACMDriverID->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL))) { /* do nothing - driver is first of list, or first after last local driver */ } else if (dwPriority == (DWORD)-1 && padid->pNextACMDriverID == NULL) { /* do nothing - driver is last of list */ } else { MSACM_RePositionDriver(padid, dwPriority); bPerformBroadcast = TRUE; } } /* Check whether driver ID should be enabled or disabled */ if (fdwPriority & ACM_DRIVERPRIORITYF_DISABLE) { if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED)) { padid->fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED; bPerformBroadcast = TRUE; } } else if (fdwPriority & ACM_DRIVERPRIORITYF_ENABLE) { if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) { padid->fdwSupport &= ~ACMDRIVERDETAILS_SUPPORTF_DISABLED; bPerformBroadcast = TRUE; } } } if (panwnd) { if (dwPriority) { return MMSYSERR_NOTSUPPORTED; } /* Check whether notify window should be enabled or disabled */ if (fdwPriority & ACM_DRIVERPRIORITYF_DISABLE) { if (!(panwnd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED)) { panwnd->fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED; bPerformBroadcast = TRUE; } } else if (fdwPriority & ACM_DRIVERPRIORITYF_ENABLE) { if (panwnd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) { panwnd->fdwSupport &= ~ACMDRIVERDETAILS_SUPPORTF_DISABLED; bPerformBroadcast = TRUE; } } } /* Perform broadcast of changes */ if (bPerformBroadcast) { MSACM_WriteCurrentPriorities(); MSACM_BroadcastNotification(); } return MMSYSERR_NOERROR; } }
/*********************************************************************** * acmDriverOpen (MSACM32.@) */ MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen) { PWINE_ACMDRIVERID padid; PWINE_ACMDRIVER pad = NULL; MMRESULT ret; TRACE("(%p, %p, %08u)\n", phad, hadid, fdwOpen); if (!phad) { WARN("invalid parameter\n"); return MMSYSERR_INVALPARAM; } if (fdwOpen) { WARN("invalid flag\n"); return MMSYSERR_INVALFLAG; } padid = MSACM_GetDriverID(hadid); if (!padid) { WARN("invalid handle\n"); return MMSYSERR_INVALHANDLE; } pad = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER)); if (!pad) { WARN("no memory\n"); return MMSYSERR_NOMEM; } pad->obj.dwType = WINE_ACMOBJ_DRIVER; pad->obj.pACMDriverID = padid; pad->hDrvr = 0; pad->pLocalDrvrInst = NULL; if (padid->pLocalDriver == NULL) { ACMDRVOPENDESCW adod; int len; LPWSTR section_name; /* this is not an externally added driver... need to actually load it */ if (!padid->pszDriverAlias) { ret = MMSYSERR_ERROR; goto gotError; } adod.cbStruct = sizeof(adod); adod.fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; adod.fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; adod.dwVersion = acmGetVersion(); adod.dwFlags = fdwOpen; adod.dwError = 0; len = strlen("Drivers32") + 1; section_name = HeapAlloc(MSACM_hHeap, 0, len * sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, "Drivers32", -1, section_name, len); adod.pszSectionName = section_name; adod.pszAliasName = padid->pszDriverAlias; adod.dnDevNode = 0; pad->hDrvr = OpenDriver(padid->pszDriverAlias, NULL, (DWORD_PTR)&adod); HeapFree(MSACM_hHeap, 0, section_name); if (!pad->hDrvr) { ret = adod.dwError; if (ret == MMSYSERR_NOERROR) ret = MMSYSERR_NODRIVER; goto gotError; } } else { ACMDRVOPENDESCW adod; pad->hDrvr = NULL; adod.cbStruct = sizeof(adod); adod.fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; adod.fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; adod.dwVersion = acmGetVersion(); adod.dwFlags = fdwOpen; adod.dwError = 0; adod.pszSectionName = NULL; adod.pszAliasName = NULL; adod.dnDevNode = 0; pad->pLocalDrvrInst = MSACM_OpenLocalDriver(padid->pLocalDriver, (DWORD_PTR)&adod); if (!pad->pLocalDrvrInst) { ret = adod.dwError; if (ret == MMSYSERR_NOERROR) ret = MMSYSERR_NODRIVER; goto gotError; } } /* insert new pad at beg of list */ pad->pNextACMDriver = padid->pACMDriverList; padid->pACMDriverList = pad; /* FIXME: Create a WINE_ACMDRIVER32 */ *phad = (HACMDRIVER)pad; TRACE("%s => %p\n", debugstr_w(padid->pszDriverAlias), pad); return MMSYSERR_NOERROR; gotError: WARN("failed: ret = %08x\n", ret); if (pad && !pad->hDrvr) HeapFree(MSACM_hHeap, 0, pad); 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; }