Created session instance for installable drivers.

Now properly freeing library upon driver exit.
This commit is contained in:
Eric Pouech 2002-05-11 22:55:29 +00:00 committed by Alexandre Julliard
parent 218faf39a2
commit bf98cf8404
1 changed files with 62 additions and 18 deletions

View File

@ -34,25 +34,22 @@ WINE_DEFAULT_DEBUG_CHANNEL(driver);
static LPWINE_DRIVER lpDrvItemList = NULL; static LPWINE_DRIVER lpDrvItemList = NULL;
/* TODO list :
* - LoadModule count and clean up is not handled correctly (it's not a
* problem as long as FreeLibrary is not working correctly)
*/
/************************************************************************** /**************************************************************************
* DRIVER_GetNumberOfModuleRefs [internal] * DRIVER_GetNumberOfModuleRefs [internal]
* *
* Returns the number of open drivers which share the same module. * Returns the number of open drivers which share the same module.
*/ */
static WORD DRIVER_GetNumberOfModuleRefs(LPWINE_DRIVER lpNewDrv) static unsigned DRIVER_GetNumberOfModuleRefs(HMODULE hModule, WINE_DRIVER** found)
{ {
LPWINE_DRIVER lpDrv; LPWINE_DRIVER lpDrv;
WORD count = 0; unsigned count = 0;
if (lpNewDrv->dwFlags & WINE_GDF_16BIT) ERR("OOOch\n"); if (found) *found = NULL;
for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem) { for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem)
if (!(lpDrv->dwFlags & WINE_GDF_16BIT) && {
lpDrv->d.d32.hModule == lpNewDrv->d.d32.hModule) { if (!(lpDrv->dwFlags & WINE_GDF_16BIT) && lpDrv->d.d32.hModule == hModule)
{
if (found && !*found) *found = lpDrv;
count++; count++;
} }
} }
@ -253,7 +250,8 @@ LRESULT WINAPI SendDriverMessage(HDRVR hDriver, UINT msg, LPARAM lParam1,
static BOOL DRIVER_RemoveFromList(LPWINE_DRIVER lpDrv) static BOOL DRIVER_RemoveFromList(LPWINE_DRIVER lpDrv)
{ {
if (!(lpDrv->dwFlags & WINE_GDF_16BIT)) { if (!(lpDrv->dwFlags & WINE_GDF_16BIT)) {
if (DRIVER_GetNumberOfModuleRefs(lpDrv) == 1) { /* last of this driver in list ? */
if (DRIVER_GetNumberOfModuleRefs(lpDrv->d.d32.hModule, NULL) == 1) {
DRIVER_SendMessage(lpDrv, DRV_DISABLE, 0L, 0L); DRIVER_SendMessage(lpDrv, DRV_DISABLE, 0L, 0L);
DRIVER_SendMessage(lpDrv, DRV_FREE, 0L, 0L); DRIVER_SendMessage(lpDrv, DRV_FREE, 0L, 0L);
} }
@ -265,6 +263,8 @@ static BOOL DRIVER_RemoveFromList(LPWINE_DRIVER lpDrv)
lpDrvItemList = lpDrv->lpNextItem; lpDrvItemList = lpDrv->lpNextItem;
if (lpDrv->lpNextItem) if (lpDrv->lpNextItem)
lpDrv->lpNextItem->lpPrevItem = lpDrv->lpPrevItem; lpDrv->lpNextItem->lpPrevItem = lpDrv->lpPrevItem;
/* trash magic number */
lpDrv->dwMagic ^= 0xa5a5a5a5;
return TRUE; return TRUE;
} }
@ -280,7 +280,8 @@ static BOOL DRIVER_AddToList(LPWINE_DRIVER lpNewDrv, LPARAM lParam1, LPARAM lPar
lpNewDrv->dwMagic = WINE_DI_MAGIC; lpNewDrv->dwMagic = WINE_DI_MAGIC;
/* First driver to be loaded for this module, need to load correctly the module */ /* First driver to be loaded for this module, need to load correctly the module */
if (!(lpNewDrv->dwFlags & WINE_GDF_16BIT)) { if (!(lpNewDrv->dwFlags & WINE_GDF_16BIT)) {
if (DRIVER_GetNumberOfModuleRefs(lpNewDrv) == 0) { /* first of this driver in list ? */
if (DRIVER_GetNumberOfModuleRefs(lpNewDrv->d.d32.hModule, NULL) == 0) {
if (DRIVER_SendMessage(lpNewDrv, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) { if (DRIVER_SendMessage(lpNewDrv, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) {
TRACE("DRV_LOAD failed on driver 0x%08lx\n", (DWORD)lpNewDrv); TRACE("DRV_LOAD failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
return FALSE; return FALSE;
@ -358,7 +359,31 @@ LPWINE_DRIVER DRIVER_TryOpenDriver32(LPCSTR fn, LPARAM lParam2)
lpDrv->d.d32.hModule = hModule; lpDrv->d.d32.hModule = hModule;
lpDrv->d.d32.dwDriverID = 0; lpDrv->d.d32.dwDriverID = 0;
if (!DRIVER_AddToList(lpDrv, (LPARAM)ptr, lParam2)) {cause = "load failed"; goto exit;} /* 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->d.d32.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;
}
return ret;
}
if (!DRIVER_AddToList(lpDrv, (LPARAM)ptr, lParam2))
{cause = "load failed"; goto exit;}
TRACE("=> %p\n", lpDrv); TRACE("=> %p\n", lpDrv);
return lpDrv; return lpDrv;
@ -461,15 +486,34 @@ LRESULT WINAPI CloseDriver(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2)
TRACE("(%04x, %08lX, %08lX);\n", hDrvr, lParam1, lParam2); TRACE("(%04x, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL) { if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL)
{
if (lpDrv->dwFlags & WINE_GDF_16BIT) if (lpDrv->dwFlags & WINE_GDF_16BIT)
CloseDriver16(lpDrv->d.d16.hDriver16, lParam1, lParam2); CloseDriver16(lpDrv->d.d16.hDriver16, lParam1, lParam2);
else else
{
DRIVER_SendMessage(lpDrv, DRV_CLOSE, lParam1, lParam2); DRIVER_SendMessage(lpDrv, DRV_CLOSE, lParam1, lParam2);
lpDrv->d.d32.dwDriverID = 0;
}
if (DRIVER_RemoveFromList(lpDrv)) { if (DRIVER_RemoveFromList(lpDrv)) {
HeapFree(GetProcessHeap(), 0, lpDrv); if (!(lpDrv->dwFlags & WINE_GDF_16BIT))
return TRUE; {
} LPWINE_DRIVER lpDrv0;
/* if driver has an opened session instance, we have to close it too */
if (DRIVER_GetNumberOfModuleRefs(lpDrv->d.d32.hModule, &lpDrv0) == 1)
{
DRIVER_SendMessage(lpDrv0, DRV_CLOSE, 0L, 0L);
lpDrv0->d.d32.dwDriverID = 0;
DRIVER_RemoveFromList(lpDrv0);
FreeLibrary(lpDrv->d.d32.hModule);
HeapFree(GetProcessHeap(), 0, lpDrv0);
}
FreeLibrary(lpDrv->d.d32.hModule);
}
HeapFree(GetProcessHeap(), 0, lpDrv);
return TRUE;
}
} }
WARN("Failed to close driver\n"); WARN("Failed to close driver\n");
return FALSE; return FALSE;