diff --git a/dlls/msacm/driver.c b/dlls/msacm/driver.c index 302cfee39ae..43562733f70 100644 --- a/dlls/msacm/driver.c +++ b/dlls/msacm/driver.c @@ -49,6 +49,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(msacm); MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule, LPARAM lParam, DWORD dwPriority, DWORD fdwAdd) { + MMRESULT resultW; + WCHAR * driverW = NULL; + LPARAM lParamW = lParam; + TRACE("(%p, %p, %08lx, %08lx, %08lx)\n", phadid, hinstModule, lParam, dwPriority, fdwAdd); @@ -72,30 +76,95 @@ MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule, return MMSYSERR_INVALFLAG; } - /* FIXME: in fact, should GetModuleFileName(hinstModule) and do a - * LoadDriver on it, to be sure we can call SendDriverMessage on the - * hDrvr handle. - */ - *phadid = (HACMDRIVERID) MSACM_RegisterDriver(NULL, NULL, hinstModule); + /* A->W translation of name */ + if ((fdwAdd & ACM_DRIVERADDF_TYPEMASK) == ACM_DRIVERADDF_NAME) { + unsigned long len; + + if (lParam == 0) return MMSYSERR_INVALPARAM; + len = MultiByteToWideChar(CP_ACP, 0, (LPSTR)lParam, -1, NULL, 0); + driverW = HeapAlloc(MSACM_hHeap, 0, len * sizeof(WCHAR)); + if (!driverW) return MMSYSERR_NOMEM; + MultiByteToWideChar(CP_ACP, 0, (LPSTR)lParam, -1, driverW, len); + lParamW = (LPARAM)driverW; + } - /* FIXME: lParam, dwPriority and fdwAdd ignored */ - - return MMSYSERR_NOERROR; + resultW = acmDriverAddW(phadid, hinstModule, lParamW, dwPriority, fdwAdd); + HeapFree(MSACM_hHeap, 0, driverW); + return resultW; } /*********************************************************************** * acmDriverAddW (MSACM32.@) - * FIXME - * Not implemented + * */ MMRESULT WINAPI acmDriverAddW(PHACMDRIVERID phadid, HINSTANCE hinstModule, LPARAM lParam, DWORD dwPriority, DWORD fdwAdd) { - FIXME("(%p, %p, %ld, %ld, %ld): stub\n", - phadid, hinstModule, lParam, dwPriority, fdwAdd); + TRACE("(%p, %p, %08lx, %08lx, %08lx)\n", + phadid, hinstModule, lParam, dwPriority, fdwAdd); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return MMSYSERR_ERROR; + if (!phadid) { + WARN("invalid parameter\n"); + return MMSYSERR_INVALPARAM; + } + + /* Check if any unknown flags */ + if (fdwAdd & + ~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND| + ACM_DRIVERADDF_GLOBAL)) { + WARN("invalid flag\n"); + return MMSYSERR_INVALFLAG; + } + + /* Check if any incompatible flags */ + if ((fdwAdd & ACM_DRIVERADDF_FUNCTION) && + (fdwAdd & ACM_DRIVERADDF_NOTIFYHWND)) { + WARN("invalid flag\n"); + return MMSYSERR_INVALFLAG; + } + + switch (fdwAdd & ACM_DRIVERADDF_TYPEMASK) { + case ACM_DRIVERADDF_NAME: + /* + hInstModule (unused) + lParam name of value in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32 + dwPriority (unused, set to 0) + */ + *phadid = (HACMDRIVERID) MSACM_RegisterDriverFromRegistry((LPCWSTR)lParam); + if (!*phadid) { + ERR("Unable to register driver via ACM_DRIVERADDF_NAME\n"); + return MMSYSERR_INVALPARAM; + } + break; + case ACM_DRIVERADDF_FUNCTION: + /* + hInstModule Handle of module which contains driver entry proc + lParam Driver function address + dwPriority (unused, set to 0) + */ + fdwAdd &= ~ACM_DRIVERADDF_TYPEMASK; + + *phadid = 0; + FIXME("(%p, %p, %ld, %ld, %ld): ACM_DRIVERADDF_FUNCTION: stub\n", phadid, hinstModule, lParam, dwPriority, fdwAdd); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return MMSYSERR_ERROR; + case ACM_DRIVERADDF_NOTIFYHWND: + /* + hInstModule (unused) + lParam Handle of notification window + dwPriority Window message to send for notification broadcasts + */ + *phadid = 0; + FIXME("(%p, %p, %ld, %ld, %ld): ACM_DRIVERADDF_NOTIFYHWND: stub\n", phadid, hinstModule, lParam, dwPriority, fdwAdd); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return MMSYSERR_ERROR; + default: + ERR("invalid flag value 0x%08lx for fdwAdd\n", fdwAdd & ACM_DRIVERADDF_TYPEMASK); + return MMSYSERR_INVALFLAG; + } + + MSACM_BroadcastNotification(); + return MMSYSERR_NOERROR; } /*********************************************************************** diff --git a/dlls/msacm/internal.c b/dlls/msacm/internal.c index a5eb350991f..b83f6324e3a 100644 --- a/dlls/msacm/internal.c +++ b/dlls/msacm/internal.c @@ -51,6 +51,43 @@ static BOOL MSACM_pendingBroadcast = FALSE; static void MSACM_ReorderDriversByPriority(void); +/*********************************************************************** + * MSACM_RegisterDriverFromRegistry() + */ +PWINE_ACMDRIVERID MSACM_RegisterDriverFromRegistry(LPCWSTR pszRegEntry) +{ + static const WCHAR msacmW[] = {'M','S','A','C','M','.'}; + static const WCHAR drvkey[] = {'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s',' ','N','T','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'D','r','i','v','e','r','s','3','2','\0'}; + WCHAR buf[2048]; + DWORD bufLen, lRet; + HKEY hKey; + PWINE_ACMDRIVERID padid = NULL; + + /* The requested registry entry must have the format msacm.XXXXX in order to + be recognized in any future sessions of msacm + */ + if (0 == strncmpiW(buf, msacmW, sizeof(msacmW)/sizeof(WCHAR))) { + lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, drvkey, 0, KEY_QUERY_VALUE, &hKey); + if (lRet != ERROR_SUCCESS) { + WARN("unable to open registry key - 0x%08lx\n", lRet); + } else { + bufLen = sizeof(buf); + lRet = RegQueryValueExW(hKey, pszRegEntry, NULL, NULL, (LPBYTE)buf, &bufLen); + if (lRet != ERROR_SUCCESS) { + WARN("unable to query requested subkey %s - 0x%08lx\n", debugstr_w(pszRegEntry), lRet); + } else { + MSACM_RegisterDriver(pszRegEntry, buf, 0); + } + RegCloseKey( hKey ); + } + } + return padid; +} + #if 0 /*********************************************************************** * MSACM_DumpCache diff --git a/dlls/msacm/wineacm.h b/dlls/msacm/wineacm.h index 0a3af41da77..e9b9247d98e 100644 --- a/dlls/msacm/wineacm.h +++ b/dlls/msacm/wineacm.h @@ -354,6 +354,8 @@ extern void MSACM_BroadcastNotification(void); extern void MSACM_DisableNotifications(void); extern void MSACM_EnableNotifications(void); +extern PWINE_ACMDRIVERID MSACM_RegisterDriverFromRegistry(LPCWSTR pszRegEntry); + /* From msacm32.c */ extern HINSTANCE MSACM_hInstance32;