msacm: acmDriverAdd() support for ACM_DRIVERADDF_FUNCTION, implemented

local drivers.
This commit is contained in:
Alex Villacís Lasso 2006-01-18 12:16:57 +01:00 committed by Alexandre Julliard
parent 07dc3c5403
commit 6c3707661b
3 changed files with 359 additions and 22 deletions

View File

@ -101,6 +101,8 @@ MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule,
MMRESULT WINAPI acmDriverAddW(PHACMDRIVERID phadid, HINSTANCE hinstModule,
LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
{
PWINE_ACMLOCALDRIVER pLocalDrv = NULL;
TRACE("(%p, %p, %08lx, %08lx, %08lx)\n",
phadid, hinstModule, lParam, dwPriority, fdwAdd);
@ -144,11 +146,17 @@ MMRESULT WINAPI acmDriverAddW(PHACMDRIVERID phadid, HINSTANCE hinstModule,
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;
/* FIXME: fdwAdd ignored */
/* Application-supplied acmDriverProc's are placed at the top of the priority unless
fdwAdd indicates ACM_DRIVERADDF_GLOBAL
*/
pLocalDrv = MSACM_RegisterLocalDriver(hinstModule, (DRIVERPROC)lParam);
*phadid = pLocalDrv ? (HACMDRIVERID) MSACM_RegisterDriver(NULL, NULL, pLocalDrv) : NULL;
if (!*phadid) {
ERR("Unable to register driver via ACM_DRIVERADDF_FUNCTION\n");
return MMSYSERR_INVALPARAM;
}
break;
case ACM_DRIVERADDF_NOTIFYHWND:
/*
hInstModule (unused)
@ -203,8 +211,10 @@ MMRESULT WINAPI acmDriverClose(HACMDRIVER had, DWORD fdwClose)
}
/* close driver if it has been opened */
if (pad->hDrvr && !padid->hInstModule)
if (pad->hDrvr && !pad->pLocalDrvrInst)
CloseDriver(pad->hDrvr, 0, 0);
else if (pad->pLocalDrvrInst)
MSACM_CloseLocalDriver(pad->pLocalDrvrInst);
HeapFree(MSACM_hHeap, 0, pad);
@ -506,8 +516,10 @@ MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpe
pad->obj.dwType = WINE_ACMOBJ_DRIVER;
pad->obj.pACMDriverID = padid;
pad->hDrvr = 0;
pad->pLocalDrvrInst = NULL;
if (!(pad->hDrvr = (HDRVR)padid->hInstModule))
if (padid->pLocalDriver == NULL)
{
ACMDRVOPENDESCW adod;
int len;
@ -540,6 +552,29 @@ MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpe
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)&adod);
if (!pad->pLocalDrvrInst)
{
ret = adod.dwError;
goto gotError;
}
}
/* insert new pad at beg of list */
pad->pNextACMDriver = padid->pACMDriverList;

View File

@ -281,12 +281,12 @@ static BOOL MSACM_WriteCache(PWINE_ACMDRIVERID padid)
* MSACM_RegisterDriver()
*/
PWINE_ACMDRIVERID MSACM_RegisterDriver(LPCWSTR pszDriverAlias, LPCWSTR pszFileName,
HINSTANCE hinstModule)
PWINE_ACMLOCALDRIVER pLocalDriver)
{
PWINE_ACMDRIVERID padid;
TRACE("(%s, %s, %p)\n",
debugstr_w(pszDriverAlias), debugstr_w(pszFileName), hinstModule);
debugstr_w(pszDriverAlias), debugstr_w(pszFileName), pLocalDriver);
padid = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVERID));
padid->obj.dwType = WINE_ACMOBJ_DRIVERID;
@ -303,22 +303,35 @@ PWINE_ACMDRIVERID MSACM_RegisterDriver(LPCWSTR pszDriverAlias, LPCWSTR pszFileNa
padid->pszFileName = HeapAlloc( MSACM_hHeap, 0, (strlenW(pszFileName)+1) * sizeof(WCHAR) );
strcpyW( padid->pszFileName, pszFileName );
}
padid->hInstModule = hinstModule;
padid->pLocalDriver = pLocalDriver;
padid->pACMDriverList = NULL;
padid->pNextACMDriverID = NULL;
padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
if (MSACM_pLastACMDriverID)
MSACM_pLastACMDriverID->pNextACMDriverID = padid;
MSACM_pLastACMDriverID = padid;
if (!MSACM_pFirstACMDriverID)
MSACM_pFirstACMDriverID = padid;
if (pLocalDriver) {
padid->pPrevACMDriverID = NULL;
padid->pNextACMDriverID = MSACM_pFirstACMDriverID;
if (MSACM_pFirstACMDriverID)
MSACM_pFirstACMDriverID->pPrevACMDriverID = padid;
MSACM_pFirstACMDriverID = padid;
if (!MSACM_pLastACMDriverID)
MSACM_pLastACMDriverID = padid;
} else {
padid->pNextACMDriverID = NULL;
padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
if (MSACM_pLastACMDriverID)
MSACM_pLastACMDriverID->pNextACMDriverID = padid;
MSACM_pLastACMDriverID = padid;
if (!MSACM_pFirstACMDriverID)
MSACM_pFirstACMDriverID = padid;
}
/* disable the driver if we cannot load the cache */
if (!MSACM_ReadCache(padid) && !MSACM_FillCache(padid)) {
if ((!padid->pszDriverAlias || !MSACM_ReadCache(padid)) && !MSACM_FillCache(padid)) {
WARN("Couldn't load cache for ACM driver (%s)\n", debugstr_w(pszFileName));
MSACM_UnregisterDriver(padid);
return NULL;
}
if (pLocalDriver) padid->fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_LOCAL;
return padid;
}
@ -724,6 +737,7 @@ PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)
pNextACMDriverID = p->pNextACMDriverID;
if (p->pLocalDriver) MSACM_UnregisterLocalDriver(p->pLocalDriver);
HeapFree(MSACM_hHeap, 0, p);
return pNextACMDriverID;
@ -744,7 +758,7 @@ void MSACM_UnregisterAllDrivers(void)
while (panwnd) {
panwnd = MSACM_UnRegisterNotificationWindow(panwnd);
}
}
}
/***********************************************************************
@ -784,6 +798,17 @@ PWINE_ACMNOTIFYWND MSACM_GetNotifyWnd(HACMDRIVERID hDriver)
return (PWINE_ACMNOTIFYWND)MSACM_GetObj((HACMOBJ)hDriver, WINE_ACMOBJ_NOTIFYWND);
}
/***********************************************************************
* MSACM_GetLocalDriver()
*/
/*
PWINE_ACMLOCALDRIVER MSACM_GetLocalDriver(HACMDRIVER hDriver)
{
return (PWINE_ACMLOCALDRIVER)MSACM_GetObj((HACMOBJ)hDriver, WINE_ACMOBJ_LOCALDRIVER);
}
*/
#define MSACM_DRIVER_SendMessage(PDRVRINST, msg, lParam1, lParam2) \
(PDRVRINST)->pLocalDriver->lpDrvProc((PDRVRINST)->dwDriverID, (HDRVR)(PDRVRINST), msg, lParam1, lParam2)
/***********************************************************************
* MSACM_Message()
@ -792,5 +817,252 @@ MMRESULT MSACM_Message(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2
{
PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
return pad ? SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2) : MMSYSERR_INVALHANDLE;
if (!pad) return MMSYSERR_INVALHANDLE;
if (pad->hDrvr) return SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2);
if (pad->pLocalDrvrInst) return MSACM_DRIVER_SendMessage(pad->pLocalDrvrInst, uMsg, lParam1, lParam2);
return MMSYSERR_INVALHANDLE;
}
PWINE_ACMLOCALDRIVER MSACM_pFirstACMLocalDriver = NULL;
PWINE_ACMLOCALDRIVER MSACM_pLastACMLocalDriver = NULL;
PWINE_ACMLOCALDRIVER MSACM_RegisterLocalDriver(HMODULE hModule, DRIVERPROC lpDriverProc)
{
PWINE_ACMLOCALDRIVER paldrv;
TRACE("(%p, %p)\n", hModule, lpDriverProc);
if (!hModule || !lpDriverProc) return NULL;
/* look up previous instance of local driver module */
for (paldrv = MSACM_pFirstACMLocalDriver; paldrv; paldrv = paldrv->pNextACMLocalDrv)
{
if (paldrv->hModule == hModule && paldrv->lpDrvProc == lpDriverProc) return paldrv;
}
paldrv = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMLOCALDRIVER));
paldrv->obj.dwType = WINE_ACMOBJ_LOCALDRIVER;
paldrv->obj.pACMDriverID = 0;
paldrv->hModule = hModule;
paldrv->lpDrvProc = lpDriverProc;
paldrv->pACMInstList = NULL;
paldrv->pNextACMLocalDrv = NULL;
paldrv->pPrevACMLocalDrv = MSACM_pLastACMLocalDriver;
if (MSACM_pLastACMLocalDriver)
MSACM_pLastACMLocalDriver->pNextACMLocalDrv = paldrv;
MSACM_pLastACMLocalDriver = paldrv;
if (!MSACM_pFirstACMLocalDriver)
MSACM_pFirstACMLocalDriver = paldrv;
return paldrv;
}
/**************************************************************************
* MSACM_GetNumberOfModuleRefs [internal]
*
* Returns the number of open drivers which share the same module.
* Inspired from implementation in dlls/winmm/driver.c
*/
static unsigned MSACM_GetNumberOfModuleRefs(HMODULE hModule, DRIVERPROC lpDrvProc, WINE_ACMLOCALDRIVERINST ** found)
{
PWINE_ACMLOCALDRIVER lpDrv;
unsigned count = 0;
if (found) *found = NULL;
for (lpDrv = MSACM_pFirstACMLocalDriver; lpDrv; lpDrv = lpDrv->pNextACMLocalDrv)
{
if (lpDrv->hModule == hModule && lpDrv->lpDrvProc == lpDrvProc)
{
PWINE_ACMLOCALDRIVERINST pInst = lpDrv->pACMInstList;
while (pInst) {
if (found && !*found) *found = pInst;
count++;
pInst = pInst->pNextACMInst;
}
}
}
return count;
}
/**************************************************************************
* MSACM_RemoveFromList [internal]
*
* Generates all the logic to handle driver closure / deletion
* Removes a driver struct to the list of open drivers.
*/
static BOOL MSACM_RemoveFromList(PWINE_ACMLOCALDRIVERINST lpDrv)
{
PWINE_ACMLOCALDRIVER pDriverBase = lpDrv->pLocalDriver;
PWINE_ACMLOCALDRIVERINST pPrevInst;
/* last of this driver in list ? */
if (MSACM_GetNumberOfModuleRefs(pDriverBase->hModule, pDriverBase->lpDrvProc, NULL) == 1) {
MSACM_DRIVER_SendMessage(lpDrv, DRV_DISABLE, 0L, 0L);
MSACM_DRIVER_SendMessage(lpDrv, DRV_FREE, 0L, 0L);
}
pPrevInst = NULL;
if (pDriverBase->pACMInstList != lpDrv) {
pPrevInst = pDriverBase->pACMInstList;
while (pPrevInst && pPrevInst->pNextACMInst != lpDrv)
pPrevInst = pPrevInst->pNextACMInst;
if (!pPrevInst) {
ERR("requested to remove invalid instance %p\n", pPrevInst);
return FALSE;
}
}
if (!pPrevInst) {
/* first driver instance on list */
pDriverBase->pACMInstList = lpDrv->pNextACMInst;
} else {
pPrevInst->pNextACMInst = lpDrv->pNextACMInst;
}
return TRUE;
}
/**************************************************************************
* MSACM_AddToList [internal]
*
* Adds a driver struct to the list of open drivers.
* Generates all the logic to handle driver creation / open.
*/
static BOOL MSACM_AddToList(PWINE_ACMLOCALDRIVERINST lpNewDrv, LPARAM lParam2)
{
PWINE_ACMLOCALDRIVER pDriverBase = lpNewDrv->pLocalDriver;
/* first of this driver in list ? */
if (MSACM_GetNumberOfModuleRefs(pDriverBase->hModule, pDriverBase->lpDrvProc, NULL) == 0) {
if (MSACM_DRIVER_SendMessage(lpNewDrv, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) {
FIXME("DRV_LOAD failed on driver %p\n", lpNewDrv);
return FALSE;
}
/* returned value is not checked */
MSACM_DRIVER_SendMessage(lpNewDrv, DRV_ENABLE, 0L, 0L);
}
lpNewDrv->pNextACMInst = NULL;
if (pDriverBase->pACMInstList == NULL) {
pDriverBase->pACMInstList = lpNewDrv;
} else {
PWINE_ACMLOCALDRIVERINST lpDrvInst = pDriverBase->pACMInstList;
while (lpDrvInst->pNextACMInst != NULL)
lpDrvInst = lpDrvInst->pNextACMInst;
lpDrvInst->pNextACMInst = lpNewDrv;
}
/* Now just open a new instance of a driver on this module */
lpNewDrv->dwDriverID = MSACM_DRIVER_SendMessage(lpNewDrv, DRV_OPEN, 0, lParam2);
if (lpNewDrv->dwDriverID == 0) {
FIXME("DRV_OPEN failed on driver %p\n", lpNewDrv);
MSACM_RemoveFromList(lpNewDrv);
return FALSE;
}
return TRUE;
}
PWINE_ACMLOCALDRIVERINST MSACM_OpenLocalDriver(PWINE_ACMLOCALDRIVER paldrv, LPARAM lParam2)
{
PWINE_ACMLOCALDRIVERINST pDrvInst;
pDrvInst = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMLOCALDRIVERINST));
pDrvInst->pLocalDriver = paldrv;
pDrvInst->dwDriverID = 0;
pDrvInst->pNextACMInst = NULL;
pDrvInst->bSession = FALSE;
/* Win32 installable drivers must support a two phase opening scheme:
* + first open with NULL as lParam2 (session instance),
* + then do a second open with the real non null lParam2)
*/
if (MSACM_GetNumberOfModuleRefs(paldrv->hModule, paldrv->lpDrvProc, NULL) == 0 && lParam2)
{
PWINE_ACMLOCALDRIVERINST ret;
if (!MSACM_AddToList(pDrvInst, 0L))
{
ERR("load0 failed\n");
goto exit;
}
ret = MSACM_OpenLocalDriver(paldrv, lParam2);
if (!ret)
{
MSACM_CloseLocalDriver(pDrvInst);
ERR("load1 failed\n");
goto exit;
}
pDrvInst->bSession = TRUE;
return ret;
}
if (!MSACM_AddToList(pDrvInst, lParam2))
{
ERR("load failed\n");
goto exit;
}
TRACE("=> %p\n", pDrvInst);
return pDrvInst;
exit:
HeapFree(MSACM_hHeap, 0, pDrvInst);
return NULL;
}
LRESULT MSACM_CloseLocalDriver(PWINE_ACMLOCALDRIVERINST paldrv)
{
if (MSACM_RemoveFromList(paldrv)) {
PWINE_ACMLOCALDRIVERINST lpDrv0;
PWINE_ACMLOCALDRIVER pDriverBase = paldrv->pLocalDriver;
MSACM_DRIVER_SendMessage(paldrv, DRV_CLOSE, 0, 0);
paldrv->dwDriverID = 0;
if (paldrv->bSession)
ERR("should not directly close session instance (%p)\n", paldrv);
/* if driver has an opened session instance, we have to close it too */
if (MSACM_GetNumberOfModuleRefs(pDriverBase->hModule, pDriverBase->lpDrvProc, &lpDrv0) == 1 &&
lpDrv0->bSession)
{
MSACM_DRIVER_SendMessage(lpDrv0, DRV_CLOSE, 0L, 0L);
lpDrv0->dwDriverID = 0;
MSACM_RemoveFromList(lpDrv0);
HeapFree(GetProcessHeap(), 0, lpDrv0);
}
HeapFree(MSACM_hHeap, 0, paldrv);
return TRUE;
}
ERR("unable to close driver instance\n");
return FALSE;
}
PWINE_ACMLOCALDRIVER MSACM_UnregisterLocalDriver(PWINE_ACMLOCALDRIVER paldrv)
{
PWINE_ACMLOCALDRIVER pNextACMLocalDriver;
if (paldrv->pACMInstList) {
ERR("local driver instances still present after closing all drivers - memory leak\n");
return NULL;
}
if (paldrv == MSACM_pFirstACMLocalDriver)
MSACM_pFirstACMLocalDriver = paldrv->pNextACMLocalDrv;
if (paldrv == MSACM_pLastACMLocalDriver)
MSACM_pLastACMLocalDriver = paldrv->pPrevACMLocalDrv;
if (paldrv->pPrevACMLocalDrv)
paldrv->pPrevACMLocalDrv->pNextACMLocalDrv = paldrv->pNextACMLocalDrv;
if (paldrv->pNextACMLocalDrv)
paldrv->pNextACMLocalDrv->pPrevACMLocalDrv = paldrv->pPrevACMLocalDrv;
pNextACMLocalDriver = paldrv->pNextACMLocalDrv;
HeapFree(MSACM_hHeap, 0, paldrv);
return pNextACMLocalDriver;
}

View File

@ -292,6 +292,7 @@ typedef struct _WINE_ACMDRIVER *PWINE_ACMDRIVER;
#define WINE_ACMOBJ_DRIVER 0x5EED0002
#define WINE_ACMOBJ_STREAM 0x5EED0003
#define WINE_ACMOBJ_NOTIFYWND 0x5EED0004
#define WINE_ACMOBJ_LOCALDRIVER 0x5EED0005
typedef struct _WINE_ACMOBJ
{
@ -299,10 +300,32 @@ typedef struct _WINE_ACMOBJ
PWINE_ACMDRIVERID pACMDriverID;
} WINE_ACMOBJ, *PWINE_ACMOBJ;
typedef struct _WINE_ACMLOCALDRIVER * PWINE_ACMLOCALDRIVER;
typedef struct _WINE_ACMLOCALDRIVERINST * PWINE_ACMLOCALDRIVERINST;
typedef struct _WINE_ACMLOCALDRIVER
{
WINE_ACMOBJ obj;
HMODULE hModule;
DRIVERPROC lpDrvProc;
PWINE_ACMLOCALDRIVERINST pACMInstList;
PWINE_ACMLOCALDRIVER pNextACMLocalDrv;
PWINE_ACMLOCALDRIVER pPrevACMLocalDrv;
} WINE_ACMLOCALDRIVER;
typedef struct _WINE_ACMLOCALDRIVERINST
{
PWINE_ACMLOCALDRIVER pLocalDriver;
DWORD dwDriverID;
BOOL bSession;
PWINE_ACMLOCALDRIVERINST pNextACMInst;
} WINE_ACMLOCALDRIVERINST;
typedef struct _WINE_ACMDRIVER
{
WINE_ACMOBJ obj;
HDRVR hDrvr;
PWINE_ACMLOCALDRIVERINST pLocalDrvrInst;
PWINE_ACMDRIVER pNextACMDriver;
} WINE_ACMDRIVER;
@ -319,7 +342,7 @@ typedef struct _WINE_ACMDRIVERID
WINE_ACMOBJ obj;
LPWSTR pszDriverAlias;
LPWSTR pszFileName;
HINSTANCE hInstModule; /* NULL if global */
PWINE_ACMLOCALDRIVER pLocalDriver; /* NULL if global */
PWINE_ACMDRIVER pACMDriverList;
PWINE_ACMDRIVERID pNextACMDriverID;
PWINE_ACMDRIVERID pPrevACMDriverID;
@ -349,7 +372,7 @@ extern HANDLE MSACM_hHeap;
extern PWINE_ACMDRIVERID MSACM_pFirstACMDriverID;
extern PWINE_ACMDRIVERID MSACM_pLastACMDriverID;
extern PWINE_ACMDRIVERID MSACM_RegisterDriver(LPCWSTR pszDriverAlias, LPCWSTR pszFileName,
HINSTANCE hinstModule);
PWINE_ACMLOCALDRIVER pLocalDriver);
extern void MSACM_RegisterAllDrivers(void);
extern PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p);
extern void MSACM_UnregisterAllDrivers(void);
@ -371,6 +394,13 @@ extern PWINE_ACMNOTIFYWND MSACM_UnRegisterNotificationWindow(PWINE_ACMNOTIFYWND)
extern PWINE_ACMDRIVERID MSACM_RegisterDriverFromRegistry(LPCWSTR pszRegEntry);
extern PWINE_ACMLOCALDRIVER MSACM_RegisterLocalDriver(HMODULE hModule, DRIVERPROC lpDriverProc);
extern PWINE_ACMLOCALDRIVERINST MSACM_OpenLocalDriver(PWINE_ACMLOCALDRIVER, LPARAM);
extern LRESULT MSACM_CloseLocalDriver(PWINE_ACMLOCALDRIVERINST);
extern PWINE_ACMLOCALDRIVER MSACM_UnregisterLocalDriver(PWINE_ACMLOCALDRIVER);
/*
extern PWINE_ACMLOCALDRIVER MSACM_GetLocalDriver(HACMDRIVER hDriver);
*/
/* From msacm32.c */
extern HINSTANCE MSACM_hInstance32;