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; }
/************************************************************************** * 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; }
PWINE_ACMLOCALDRIVERINST MSACM_OpenLocalDriver(PWINE_ACMLOCALDRIVER paldrv, LPARAM lParam2) { PWINE_ACMLOCALDRIVERINST pDrvInst; pDrvInst = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMLOCALDRIVERINST)); if (!pDrvInst) return NULL; 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) { ERR("load1 failed\n"); /* If MSACM_CloseLocalDriver returns TRUE, * then pDrvInst has been freed */ if (!MSACM_CloseLocalDriver(pDrvInst)) goto exit; return NULL; } 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; }
/************************************************************************** * 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; }