From 689312b15e355b94d148ef56900810279e40d189 Mon Sep 17 00:00:00 2001
From: Eric Pouech <eric.pouech@wanadoo.fr>
Date: Mon, 11 Nov 2002 19:53:01 +0000
Subject: [PATCH] Now properly unloading multimedia drivers when winmm unloads.

---
 dlls/winmm/driver.c   | 20 +++++++++++++
 dlls/winmm/lolvldrv.c | 67 +++++++++++++++++++++++++++++++++++++++++++
 dlls/winmm/winemm.h   |  5 ++--
 dlls/winmm/winmm.c    |  6 ++++
 4 files changed, 96 insertions(+), 2 deletions(-)

diff --git a/dlls/winmm/driver.c b/dlls/winmm/driver.c
index 9bd44dfbd3a..9b212ed629b 100644
--- a/dlls/winmm/driver.c
+++ b/dlls/winmm/driver.c
@@ -507,3 +507,23 @@ BOOL WINAPI DriverCallback(DWORD dwCallBack, UINT uFlags, HDRVR hDev,
     TRACE("Done\n");
     return TRUE;
 }
+
+/******************************************************************
+ *		DRIVER_UnloadAll
+ *
+ *
+ */
+void    DRIVER_UnloadAll(void)
+{
+    LPWINE_DRIVER 	lpDrv;
+    LPWINE_DRIVER 	lpNextDrv = NULL;
+    unsigned            count = 0;
+
+    for (lpDrv = lpDrvItemList; lpDrv != NULL; lpDrv = lpNextDrv)
+    {
+        lpNextDrv = lpDrv->lpNextItem;
+        CloseDriver((HDRVR)lpDrv, 0, 0);
+        count++;
+    }
+    TRACE("Unloaded %u drivers\n", count);
+}
diff --git a/dlls/winmm/lolvldrv.c b/dlls/winmm/lolvldrv.c
index 76ea31f6e8c..a0a4ceb8c90 100644
--- a/dlls/winmm/lolvldrv.c
+++ b/dlls/winmm/lolvldrv.c
@@ -733,3 +733,70 @@ BOOL	MMDRV_Init(void)
     /* FIXME: MMDRV_InitFromRegistry shall be MMDRV_Init in a near future */
     return MMDRV_InitFromRegistry() || MMDRV_InitHardcoded();
 }
+
+/******************************************************************
+ *		ExitPerType
+ *
+ *
+ */
+static  BOOL	MMDRV_ExitPerType(LPWINE_MM_DRIVER lpDrv, UINT type)
+{
+    WINE_MM_DRIVER_PART*	part = &lpDrv->parts[type];
+    DWORD			ret;
+
+    if (lpDrv->bIs32 && part->u.fnMessage32) {
+#if 0
+	ret = part->u.fnMessage32(0, DRVM_DISABLE, 0L, 0L, 0L);
+	TRACE("DRVM_DISABLE => %08lx\n", ret);
+#endif
+	ret = part->u.fnMessage32(0, DRVM_EXIT, 0L, 0L, 0L);
+	TRACE("DRVM_EXIT => %08lx\n", ret);
+    } else if (!lpDrv->bIs32 && part->u.fnMessage16 && pFnCallMMDrvFunc16) {
+#if 0
+	ret = pFnCallMMDrvFunc16((FARPROC16)part->u.fnMessage16,
+                                 0, DRVM_DISABLE, 0L, 0L, 0L);
+	TRACE("DRVM_DISABLE => %08lx\n", ret);
+#endif
+        ret = pFnCallMMDrvFunc16((FARPROC16)part->u.fnMessage16,
+                                 0, DRVM_EXIT, 0L, 0L, 0L);
+	TRACE("DRVM_EXIT => %08lx\n", ret);
+    } else {
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+/******************************************************************
+ *		Exit
+ *
+ *
+ */
+void    MMDRV_Exit(void)
+{
+    int i;
+
+    for (i = 0; i < sizeof(MM_MLDrvs) / sizeof(MM_MLDrvs[0]); i++)
+    {
+        if (MM_MLDrvs[i] != NULL)
+        {
+            FIXME("Closing while ll-driver open\n");
+#if 0
+            /* FIXME: should generate a message depending on type */
+            MMDRV_Free((HANDLE)(i | 0x8000), MM_MLDrvs[i]);
+#endif
+        }
+    }
+
+    /* unload driver, in reverse order of loading */
+    for (i = sizeof(MMDrvs) / sizeof(MMDrvs[0]) - 1; i >= 0; i--)
+    {
+        MMDRV_ExitPerType(&MMDrvs[i], MMDRV_AUX);
+        MMDRV_ExitPerType(&MMDrvs[i], MMDRV_MIXER);
+        MMDRV_ExitPerType(&MMDrvs[i], MMDRV_MIDIIN);
+        MMDRV_ExitPerType(&MMDrvs[i], MMDRV_MIDIOUT);
+        MMDRV_ExitPerType(&MMDrvs[i], MMDRV_WAVEIN);
+        MMDRV_ExitPerType(&MMDrvs[i], MMDRV_WAVEOUT);
+        CloseDriver(MMDrvs[i].hDriver, 0, 0);
+    }
+}
diff --git a/dlls/winmm/winemm.h b/dlls/winmm/winemm.h
index 16b4c5ca5c6..077b578cf43 100644
--- a/dlls/winmm/winemm.h
+++ b/dlls/winmm/winemm.h
@@ -90,8 +90,6 @@ typedef struct tagWINE_MM_DRIVER {
     WINE_MM_DRIVER_PART		parts[MMDRV_MAX];/* Information for all known types */
 } WINE_MM_DRIVER, *LPWINE_MM_DRIVER;
 
-typedef	WINMM_MapType	(*MMDRV_MAPFUNC)(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2);
-
 typedef struct tagWINE_MLD {
 /* EPP struct tagWINE_MLD*	lpNext; */		/* not used so far */
        UINT			uDeviceID;
@@ -226,12 +224,15 @@ typedef struct tagWINE_MM_IDATA {
 
 typedef LONG			(*MCIPROC16)(DWORD, HDRVR16, WORD, DWORD, DWORD);
 typedef LONG			(*MCIPROC)(DWORD, HDRVR, DWORD, DWORD, DWORD);
+typedef	WINMM_MapType	        (*MMDRV_MAPFUNC)(UINT wMsg, LPDWORD lpdwUser, LPDWORD lpParam1, LPDWORD lpParam2);
 
 LPWINE_DRIVER	DRIVER_FindFromHDrvr(HDRVR hDrvr);
 BOOL		DRIVER_GetLibName(LPCSTR keyName, LPCSTR sectName, LPSTR buf, int sz);
 LPWINE_DRIVER	DRIVER_TryOpenDriver32(LPCSTR fn, LPARAM lParam2);
+void            DRIVER_UnloadAll(void);
 
 BOOL		MMDRV_Init(void);
+void            MMDRV_Exit(void);
 UINT		MMDRV_GetNum(UINT);
 LPWINE_MLD	MMDRV_Alloc(UINT size, UINT type, LPHANDLE hndl, DWORD* dwFlags,
                             DWORD* dwCallback, DWORD* dwInstance, BOOL bFrom32);
diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c
index 7f0a62e6ef7..d9e7fd3aaea 100644
--- a/dlls/winmm/winmm.c
+++ b/dlls/winmm/winmm.c
@@ -127,6 +127,12 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
 	}
 	break;
     case DLL_PROCESS_DETACH:
+        /* close all opened MCI drivers */
+        MCI_SendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_WAIT, 0L, TRUE);
+        MMDRV_Exit();
+        /* now unload all remaining drivers... */
+        DRIVER_UnloadAll();
+
 	WINMM_DeleteIData();
 	break;
     case DLL_THREAD_ATTACH:
-- 
GitLab