/************************************************************************** * DRIVER_AddToList [internal] * * Adds a driver struct to the list of open drivers. * Generates all the logic to handle driver creation / open. */ static BOOL DRIVER_AddToList(LPWINE_DRIVER lpNewDrv, LPARAM lParam1, LPARAM lParam2) { /* First driver to be loaded for this module, need to load correctly the module */ if (DRIVER_GetNumberOfModuleRefs(lpNewDrv) == 0) { if (DRIVER_SendMessage(lpNewDrv, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) { TRACE("DRV_LOAD failed on driver %p\n", lpNewDrv); return FALSE; } /* returned value is not checked */ DRIVER_SendMessage(lpNewDrv, DRV_ENABLE, 0L, 0L); } lpNewDrv->lpNextItem = NULL; if (lpDrvItemList == NULL) { lpDrvItemList = lpNewDrv; lpNewDrv->lpPrevItem = NULL; } else { LPWINE_DRIVER lpDrv = lpDrvItemList; /* find end of list */ while (lpDrv->lpNextItem != NULL) lpDrv = lpDrv->lpNextItem; lpDrv->lpNextItem = lpNewDrv; lpNewDrv->lpPrevItem = lpDrv; } /* Now just open a new instance of a driver on this module */ lpNewDrv->dwDriverID = DRIVER_SendMessage(lpNewDrv, DRV_OPEN, lParam1, lParam2); if (lpNewDrv->dwDriverID == 0) { TRACE("DRV_OPEN failed on driver %p\n", lpNewDrv); DRIVER_RemoveFromList(lpNewDrv); return FALSE; } return TRUE; }
/************************************************************************** * DRIVER_RemoveFromList [internal] * * Generates all the logic to handle driver closure / deletion * Removes a driver struct to the list of open drivers. */ static BOOL DRIVER_RemoveFromList(LPWINE_DRIVER lpDrv) { /* last of this driver in list ? */ if (DRIVER_GetNumberOfModuleRefs(lpDrv->hModule, NULL) == 1) { DRIVER_SendMessage(lpDrv, DRV_DISABLE, 0L, 0L); DRIVER_SendMessage(lpDrv, DRV_FREE, 0L, 0L); } EnterCriticalSection( &mmdriver_lock ); if (lpDrv->lpPrevItem) lpDrv->lpPrevItem->lpNextItem = lpDrv->lpNextItem; else lpDrvItemList = lpDrv->lpNextItem; if (lpDrv->lpNextItem) lpDrv->lpNextItem->lpPrevItem = lpDrv->lpPrevItem; /* trash magic number */ lpDrv->dwMagic ^= 0xa5a5a5a5; lpDrv->lpDrvProc = NULL; lpDrv->dwDriverID = 0; LeaveCriticalSection( &mmdriver_lock ); return TRUE; }
/************************************************************************** * DRIVER_RemoveFromList [internal] * * Generates all the logic to handle driver closure / deletion * Removes a driver struct to the list of open drivers. */ static BOOL DRIVER_RemoveFromList(LPWINE_DRIVER lpDrv) { lpDrv->dwDriverID = 0; if (DRIVER_GetNumberOfModuleRefs(lpDrv) == 1) { DRIVER_SendMessage(lpDrv, DRV_DISABLE, 0L, 0L); DRIVER_SendMessage(lpDrv, DRV_FREE, 0L, 0L); } if (lpDrv->lpPrevItem) lpDrv->lpPrevItem->lpNextItem = lpDrv->lpNextItem; else lpDrvItemList = lpDrv->lpNextItem; if (lpDrv->lpNextItem) lpDrv->lpNextItem->lpPrevItem = lpDrv->lpPrevItem; return TRUE; }
/************************************************************************** * CloseDriver [WINMM.@] * DrvClose [WINMM.@] */ LRESULT WINAPI CloseDriver(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2) { BOOL ret; LPWINE_DRIVER lpDrv; TRACE("(%p, %08lX, %08lX);\n", hDrvr, lParam1, lParam2); DRIVER_Dump("BEFORE:"); if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL) { LPWINE_DRIVER lpDrv0; DRIVER_SendMessage(lpDrv, DRV_CLOSE, lParam1, lParam2); DRIVER_RemoveFromList(lpDrv); if (lpDrv->dwFlags & WINE_GDF_SESSION) FIXME("WINE_GDF_SESSION: Shouldn't happen (%p)\n", lpDrv); /* if driver has an opened session instance, we have to close it too */ if (DRIVER_GetNumberOfModuleRefs(lpDrv->hModule, &lpDrv0) == 1 && (lpDrv0->dwFlags & WINE_GDF_SESSION)) { DRIVER_SendMessage(lpDrv0, DRV_CLOSE, 0, 0); DRIVER_RemoveFromList(lpDrv0); FreeLibrary(lpDrv0->hModule); HeapFree(GetProcessHeap(), 0, lpDrv0); } FreeLibrary(lpDrv->hModule); HeapFree(GetProcessHeap(), 0, lpDrv); ret = TRUE; } else { WARN("Failed to close driver\n"); ret = FALSE; } DRIVER_Dump("AFTER:"); return ret; }
/************************************************************************** * DRIVER_TryOpenDriver32 [internal] * * Tries to load a 32 bit driver whose DLL's (module) name is fn */ LPWINE_DRIVER DRIVER_TryOpenDriver32(LPCWSTR fn, LPARAM lParam2) { LPWINE_DRIVER lpDrv = NULL; HMODULE hModule = 0; LPWSTR ptr; LPCSTR cause = 0; TRACE("(%s, %08lX);\n", debugstr_w(fn), lParam2); if ((ptr = strchrW(fn, ' ')) != NULL) { *ptr++ = '\0'; while (*ptr == ' ') ptr++; if (*ptr == '\0') ptr = NULL; } lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER)); if (lpDrv == NULL) {cause = "OOM"; goto exit;} if ((hModule = LoadLibraryW(fn)) == 0) {cause = "Not a 32 bit lib"; goto exit;} lpDrv->lpDrvProc = (DRIVERPROC)GetProcAddress(hModule, "DriverProc"); if (lpDrv->lpDrvProc == NULL) {cause = "no DriverProc"; goto exit;} lpDrv->dwFlags = 0; lpDrv->hModule = hModule; lpDrv->dwDriverID = 0; /* 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 (DRIVER_GetNumberOfModuleRefs(lpDrv->hModule, NULL) == 0 && lParam2) { LPWINE_DRIVER ret; if (!DRIVER_AddToList(lpDrv, (LPARAM)ptr, 0L)) { cause = "load0 failed"; goto exit; } ret = DRIVER_TryOpenDriver32(fn, lParam2); if (!ret) { CloseDriver((HDRVR)lpDrv, 0L, 0L); cause = "load1 failed"; goto exit; } lpDrv->dwFlags |= WINE_GDF_SESSION; return ret; } if (!DRIVER_AddToList(lpDrv, (LPARAM)ptr, lParam2)) {cause = "load failed"; goto exit;} TRACE("=> %p\n", lpDrv); return lpDrv; exit: FreeLibrary(hModule); HeapFree(GetProcessHeap(), 0, lpDrv); TRACE("Unable to load 32 bit module %s: %s\n", debugstr_w(fn), cause); return NULL; }