Multimedia "session instance" session for drivers [1/3]
Eric Pouech
eric.pouech at wanadoo.fr
Fri May 10 16:08:42 CDT 2002
this serie of three patches implement what Microsoft calls
"session instance"
basically, when a driver is loaded:
1/ a first instance is created, with no argument in the
creation (this aka session instance)
2/ this instance is kept opened as long as the driver is
loaded, and is closed when the last "real" instance is
closed
3/ any "real" opening of the driver (with parameters) is
done as another instance of the driver
this "feature" was already present in msacm32.dll (on top
of winmm driver API)
this serie of patches let wine behave as specified by MS:
- patch #1: implement "first driver instance" session in
winmm.dll. this patch also allows to unload a no longer
needed driver
- patch #2: removes the "session instance" code from
MSACM (since now it's handled by winmm)
- patch #3: most builtin MCI drivers need to support this
feature...
A+
-------------- next part --------------
Name: instdrv
ChangeLog: created session instance for installable drivers
now properly freeing library upon driver exit
License: X11
GenDate: 2002/05/10 20:43:50 UTC
ModifiedFiles: dlls/winmm/driver.c
AddedFiles:
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/winmm/driver.c,v
retrieving revision 1.14
diff -u -u -r1.14 driver.c
--- dlls/winmm/driver.c 9 Mar 2002 23:44:33 -0000 1.14
+++ dlls/winmm/driver.c 23 Apr 2002 19:16:57 -0000
@@ -34,25 +34,22 @@
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]
*
* 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;
- WORD count = 0;
+ unsigned count = 0;
- if (lpNewDrv->dwFlags & WINE_GDF_16BIT) ERR("OOOch\n");
- for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem) {
- if (!(lpDrv->dwFlags & WINE_GDF_16BIT) &&
- lpDrv->d.d32.hModule == lpNewDrv->d.d32.hModule) {
+ if (found) *found = NULL;
+ for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem)
+ {
+ if (!(lpDrv->dwFlags & WINE_GDF_16BIT) && lpDrv->d.d32.hModule == hModule)
+ {
+ if (found && !*found) *found = lpDrv;
count++;
}
}
@@ -253,7 +309,8 @@
static BOOL DRIVER_RemoveFromList(LPWINE_DRIVER lpDrv)
{
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_FREE, 0L, 0L);
}
@@ -265,6 +322,8 @@
lpDrvItemList = lpDrv->lpNextItem;
if (lpDrv->lpNextItem)
lpDrv->lpNextItem->lpPrevItem = lpDrv->lpPrevItem;
+ /* trash magic number */
+ lpDrv->dwMagic ^= 0xa5a5a5a5;
return TRUE;
}
@@ -280,7 +339,8 @@
lpNewDrv->dwMagic = WINE_DI_MAGIC;
/* First driver to be loaded for this module, need to load correctly the module */
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) {
TRACE("DRV_LOAD failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
return FALSE;
@@ -358,7 +418,31 @@
lpDrv->d.d32.hModule = hModule;
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);
return lpDrv;
@@ -461,15 +545,34 @@
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)
CloseDriver16(lpDrv->d.d16.hDriver16, lParam1, lParam2);
else
+ {
DRIVER_SendMessage(lpDrv, DRV_CLOSE, lParam1, lParam2);
+ lpDrv->d.d32.dwDriverID = 0;
+ }
if (DRIVER_RemoveFromList(lpDrv)) {
- HeapFree(GetProcessHeap(), 0, lpDrv);
- return TRUE;
- }
+ if (!(lpDrv->dwFlags & WINE_GDF_16BIT))
+ {
+ 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");
return FALSE;
More information about the wine-patches
mailing list