Merge from HEAD: r14202
Specify correct buffer size in GetPrivateProfileStringW calls.
Modified: branches/ros-branch-0_2_6/reactos/lib/winmm/driver.c
Modified: branches/ros-branch-0_2_6/reactos/lib/winmm/mci.c
_____
Modified: branches/ros-branch-0_2_6/reactos/lib/winmm/driver.c
--- branches/ros-branch-0_2_6/reactos/lib/winmm/driver.c
2005-03-23 17:11:18 UTC (rev 14281)
+++ branches/ros-branch-0_2_6/reactos/lib/winmm/driver.c
2005-03-23 17:12:03 UTC (rev 14282)
@@ -1,572 +1,572 @@
-/*
- * WINE Drivers functions
- *
- * Copyright 1994 Martin Ayotte
- * Copyright 1998 Marcus Meissner
- * Copyright 1999 Eric Pouech
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
- */
-
-#include <string.h>
-#include <stdarg.h>
-#include "windef.h"
-#include "winbase.h"
-#include "wingdi.h"
-#include "winuser.h"
-#include "winnls.h"
-#include "winreg.h"
-#include "mmddk.h"
-#include "winemm.h"
-#include "wine/debug.h"
-#include "wine/unicode.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(driver);
-
-static LPWINE_DRIVER lpDrvItemList /* = NULL */;
-static const WCHAR HKLM_BASE[] =
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t
','\\',
-
'W','i','n','d','o','w','s','
','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n',0
};
-
-WINE_MMTHREAD* (*pFnGetMMThread16)(UINT16 h) /* = NULL */;
-LPWINE_DRIVER (*pFnOpenDriver16)(LPCWSTR,LPCWSTR,LPARAM) /* = NULL
*/;
-LRESULT (*pFnCloseDriver16)(UINT16,LPARAM,LPARAM) /* = NULL */;
-LRESULT (*pFnSendMessage16)(UINT16,UINT,LPARAM,LPARAM) /* =
NULL */;
-
-/**********************************************************************
****
- * DRIVER_GetNumberOfModuleRefs
[internal]
- *
- * Returns the number of open drivers which share the same module.
- */
-static unsigned DRIVER_GetNumberOfModuleRefs(HMODULE hModule,
WINE_DRIVER** found)
-{
- LPWINE_DRIVER lpDrv;
- unsigned count = 0;
-
- 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++;
- }
- }
- return count;
-}
-
-/**********************************************************************
****
- * DRIVER_FindFromHDrvr
[internal]
- *
- * From a hDrvr being 32 bits, returns the WINE internal structure.
- */
-LPWINE_DRIVER DRIVER_FindFromHDrvr(HDRVR hDrvr)
-{
- LPWINE_DRIVER d = (LPWINE_DRIVER)hDrvr;
-
- if (hDrvr && HeapValidate(GetProcessHeap(), 0, d) && d->dwMagic
==
WINE_DI_MAGIC) {
- return d;
- }
- return NULL;
-}
-
-/**********************************************************************
****
- * DRIVER_SendMessage
[internal]
- */
-static LRESULT inline DRIVER_SendMessage(LPWINE_DRIVER lpDrv, UINT msg,
- LPARAM lParam1, LPARAM
lParam2)
-{
- LRESULT ret = 0;
-
- if (lpDrv->dwFlags & WINE_GDF_16BIT) {
- /* no need to check mmsystem presence: the driver must have
been opened as a 16 bit one,
- */
- if (pFnSendMessage16)
- ret = pFnSendMessage16(lpDrv->d.d16.hDriver16, msg,
lParam1, lParam2);
- } else {
- TRACE("Before call32 proc=%p drvrID=%08lx hDrv=%p wMsg=%04x
p1=%08lx p2=%08lx\n",
- lpDrv->d.d32.lpDrvProc, lpDrv->d.d32.dwDriverID,
(HDRVR)lpDrv, msg, lParam1, lParam2);
- ret = lpDrv->d.d32.lpDrvProc(lpDrv->d.d32.dwDriverID,
(HDRVR)lpDrv, msg, lParam1, lParam2);
- TRACE("After call32 proc=%p drvrID=%08lx hDrv=%p wMsg=%04x
p1=%08lx p2=%08lx => %08lx\n",
- lpDrv->d.d32.lpDrvProc, lpDrv->d.d32.dwDriverID,
(HDRVR)lpDrv, msg, lParam1, lParam2, ret);
- }
- return ret;
-}
-
-/**********************************************************************
****
- * SendDriverMessage
[WINMM.@]
- * DrvSendMessage
[WINMM.@]
- */
-LRESULT WINAPI SendDriverMessage(HDRVR hDriver, UINT msg, LPARAM
lParam1,
- LPARAM lParam2)
-{
- LPWINE_DRIVER lpDrv;
- LRESULT retval = 0;
-
- TRACE("(%p, %04X, %08lX, %08lX)\n", hDriver, msg, lParam1,
lParam2);
-
- if ((lpDrv = DRIVER_FindFromHDrvr(hDriver)) != NULL) {
- retval = DRIVER_SendMessage(lpDrv, msg, lParam1, lParam2);
- } else {
- WARN("Bad driver handle %p\n", hDriver);
- }
- TRACE("retval = %ld\n", retval);
-
- return retval;
-}
-
-/**********************************************************************
****
- * 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)
-{
- if (!(lpDrv->dwFlags & WINE_GDF_16BIT)) {
- /* 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);
- }
- }
-
- 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;
-
- return TRUE;
-}
-
-/**********************************************************************
****
- * 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)
-{
- 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)) {
- /* 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;
- }
- /* 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;
- }
-
- if (!(lpNewDrv->dwFlags & WINE_GDF_16BIT)) {
- /* Now just open a new instance of a driver on this module */
- lpNewDrv->d.d32.dwDriverID = DRIVER_SendMessage(lpNewDrv,
DRV_OPEN, lParam1, lParam2);
-
- if (lpNewDrv->d.d32.dwDriverID == 0) {
- TRACE("DRV_OPEN failed on driver 0x%08lx\n",
(DWORD)lpNewDrv);
- DRIVER_RemoveFromList(lpNewDrv);
- return FALSE;
- }
- }
- return TRUE;
-}
-
-/**********************************************************************
****
- * DRIVER_GetLibName
[internal]
- *
- */
-BOOL DRIVER_GetLibName(LPCWSTR keyName, LPCWSTR sectName, LPWSTR buf,
int sz)
-{
- HKEY hKey, hSecKey;
- DWORD bufLen, lRet;
- static const WCHAR wszSystemIni[] =
{'S','Y','S','T','E','M','.','I','N','I',0};
- WCHAR wsznull = '\0';
-
- lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, HKLM_BASE, 0,
KEY_QUERY_VALUE, &hKey);
- if (lRet == ERROR_SUCCESS) {
- lRet = RegOpenKeyExW(hKey, sectName, 0, KEY_QUERY_VALUE,
&hSecKey);
- if (lRet == ERROR_SUCCESS) {
- bufLen = sz;
- lRet = RegQueryValueExW(hSecKey, keyName, 0, 0, (void*)buf,
&bufLen);
- RegCloseKey( hSecKey );
- }
- RegCloseKey( hKey );
- }
- if (lRet == ERROR_SUCCESS) return TRUE;
- /* default to system.ini if we can't find it in the registry,
- * to support native installations where system.ini is still used
*/
- return GetPrivateProfileStringW(sectName, keyName, &wsznull, buf,
sz, wszSystemIni);
-}
-
-/**********************************************************************
****
- * 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->d.d32.lpDrvProc = (DRIVERPROC)GetProcAddress(hModule,
"DriverProc");
- if (lpDrv->d.d32.lpDrvProc == NULL) {cause = "no DriverProc"; goto
exit;}
-
- lpDrv->dwFlags = 0;
- lpDrv->d.d32.hModule = hModule;
- lpDrv->d.d32.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->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;
- exit:
- FreeLibrary(hModule);
- HeapFree(GetProcessHeap(), 0, lpDrv);
- TRACE("Unable to load 32 bit module %s: %s\n", debugstr_w(fn),
cause);
- return NULL;
-}
-
-/**********************************************************************
****
- * OpenDriverA
[WINMM.@]
- * DrvOpenA
[WINMM.@]
- * (0,1,DRV_LOAD ,0 ,0)
- * (0,1,DRV_ENABLE,0 ,0)
- * (0,1,DRV_OPEN ,buf[256],0)
- */
-HDRVR WINAPI OpenDriverA(LPCSTR lpDriverName, LPCSTR lpSectionName,
LPARAM lParam)
-{
- INT len;
- LPWSTR dn = NULL;
- LPWSTR sn = NULL;
- HDRVR ret;
-
- if (lpDriverName)
- {
- len = MultiByteToWideChar( CP_ACP, 0, lpDriverName, -1, NULL, 0
);
- dn = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
- if (!dn) return 0;
- MultiByteToWideChar( CP_ACP, 0, lpDriverName, -1, dn, len );
- }
-
- if (lpSectionName)
- {
- len = MultiByteToWideChar( CP_ACP, 0, lpSectionName, -1, NULL,
0 );
- sn = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
- if (!sn) return 0;
- MultiByteToWideChar( CP_ACP, 0, lpSectionName, -1, sn, len );
- }
-
- ret = OpenDriver(dn, sn, lParam);
-
- if (dn) HeapFree(GetProcessHeap(), 0, dn);
- if (sn) HeapFree(GetProcessHeap(), 0, sn);
- return ret;
-}
-
-/**********************************************************************
****
- * OpenDriver
[WINMM.@]
- * DrvOpen
[WINMM.@]
- */
-HDRVR WINAPI OpenDriver(LPCWSTR lpDriverName, LPCWSTR lpSectionName,
LPARAM lParam)
-{
- LPWINE_DRIVER lpDrv = NULL;
- WCHAR libName[128];
- LPCWSTR lsn = lpSectionName;
-
- TRACE("(%s, %s, 0x%08lx);\n",
- debugstr_w(lpDriverName), debugstr_w(lpSectionName), lParam);
-
- if (lsn == NULL) {
- static const WCHAR wszDrivers32[] =
{'D','r','i','v','e','r','s','3','2',0};
- lstrcpynW(libName, lpDriverName, sizeof(libName) /
sizeof(WCHAR));
-
- if ((lpDrv = DRIVER_TryOpenDriver32(libName, lParam)))
- goto the_end;
- lsn = wszDrivers32;
- }
- if (DRIVER_GetLibName(lpDriverName, lsn, libName, sizeof(libName))
&&
- (lpDrv = DRIVER_TryOpenDriver32(libName, lParam)))
- goto the_end;
-
- /* now we will try a 16 bit driver (and add all the glue to make it
work... which
- * is located in our mmsystem implementation)
- * so ensure, we can load our mmsystem, otherwise just fail
- */
- WINMM_CheckForMMSystem();
- if (pFnOpenDriver16 &&
- (lpDrv = pFnOpenDriver16(lpDriverName, lpSectionName, lParam)))
- {
- if (DRIVER_AddToList(lpDrv, 0, lParam)) goto the_end;
- HeapFree(GetProcessHeap(), 0, lpDrv);
- }
- TRACE("Failed to open driver %s from system.ini file, section
%s\n",
- debugstr_w(lpDriverName), debugstr_w(lpSectionName));
- return 0;
-
- the_end:
- if (lpDrv) TRACE("=> %08lx\n", (DWORD)lpDrv);
- return (HDRVR)lpDrv;
-}
-
-/**********************************************************************
****
- * CloseDriver
[WINMM.@]
- * DrvClose
[WINMM.@]
- */
-LRESULT WINAPI CloseDriver(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2)
-{
- LPWINE_DRIVER lpDrv;
-
- TRACE("(%p, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
-
- if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL)
- {
- if (lpDrv->dwFlags & WINE_GDF_16BIT)
- {
- if (pFnCloseDriver16)
- pFnCloseDriver16(lpDrv->d.d16.hDriver16, lParam1,
lParam2);
- }
- else
- {
- DRIVER_SendMessage(lpDrv, DRV_CLOSE, lParam1, lParam2);
- lpDrv->d.d32.dwDriverID = 0;
- }
- if (DRIVER_RemoveFromList(lpDrv)) {
- 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(lpDrv0->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;
-}
-
-/**********************************************************************
****
- * GetDriverFlags [WINMM.@]
- * [in] hDrvr handle to the driver
- *
- * Returns:
- * 0x00000000 if hDrvr is an invalid handle
- * 0x80000000 if hDrvr is a valid 32 bit driver
- * 0x90000000 if hDrvr is a valid 16 bit driver
- *
- * native WINMM doesn't return those flags
- * 0x80000000 for a valid 32 bit driver and that's it
- * (I may have mixed up the two flags :-(
- */
-DWORD WINAPI GetDriverFlags(HDRVR hDrvr)
-{
- LPWINE_DRIVER lpDrv;
- DWORD ret = 0;
-
- TRACE("(%p)\n", hDrvr);
-
- if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL) {
- ret = WINE_GDF_EXIST | lpDrv->dwFlags;
- }
- return ret;
-}
-
-/**********************************************************************
****
- * GetDriverModuleHandle [WINMM.@]
- * DrvGetModuleHandle [WINMM.@]
- */
-HMODULE WINAPI GetDriverModuleHandle(HDRVR hDrvr)
-{
- LPWINE_DRIVER lpDrv;
- HMODULE hModule = 0;
-
- TRACE("(%p);\n", hDrvr);
-
- if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL) {
- if (!(lpDrv->dwFlags & WINE_GDF_16BIT))
- hModule = lpDrv->d.d32.hModule;
- }
- TRACE("=> %p\n", hModule);
- return hModule;
-}
-
-/**********************************************************************
****
- * DefDriverProc
[WINMM.@]
- * DrvDefDriverProc
[WINMM.@]
- */
-LRESULT WINAPI DefDriverProc(DWORD_PTR dwDriverIdentifier, HDRVR hDrv,
- UINT Msg, LPARAM lParam1, LPARAM lParam2)
-{
- switch (Msg) {
- case DRV_LOAD:
- case DRV_FREE:
- case DRV_ENABLE:
- case DRV_DISABLE:
- return 1;
- case DRV_INSTALL:
- case DRV_REMOVE:
- return DRV_SUCCESS;
- default:
- return 0;
- }
-}
-
-/**********************************************************************
****
- * DriverCallback
[WINMM.@]
- */
-BOOL WINAPI DriverCallback(DWORD dwCallBack, UINT uFlags, HDRVR hDev,
- UINT wMsg, DWORD dwUser, DWORD dwParam1,
- DWORD dwParam2)
-{
- TRACE("(%08lX, %04X, %p, %04X, %08lX, %08lX, %08lX); !\n",
- dwCallBack, uFlags, hDev, wMsg, dwUser, dwParam1, dwParam2);
-
- switch (uFlags & DCB_TYPEMASK) {
- case DCB_NULL:
- TRACE("Null !\n");
- if (dwCallBack)
- WARN("uFlags=%04X has null DCB value, but dwCallBack=%08lX
is not null !\n", uFlags, dwCallBack);
- break;
- case DCB_WINDOW:
- TRACE("Window(%04lX) handle=%p!\n", dwCallBack, hDev);
- PostMessageA((HWND)dwCallBack, wMsg, (WPARAM)hDev, dwParam1);
- break;
- case DCB_TASK: /* aka DCB_THREAD */
- TRACE("Task(%04lx) !\n", dwCallBack);
- PostThreadMessageA(dwCallBack, wMsg, (WPARAM)hDev, dwParam1);
- break;
- case DCB_FUNCTION:
- TRACE("Function (32 bit) !\n");
- ((LPDRVCALLBACK)dwCallBack)(hDev, wMsg, dwUser, dwParam1,
dwParam2);
- break;
- case DCB_EVENT:
- TRACE("Event(%08lx) !\n", dwCallBack);
- SetEvent((HANDLE)dwCallBack);
- break;
- case 6: /* I would dub it DCB_MMTHREADSIGNAL */
- /* this is an undocumented DCB_ value used for mmThreads
- * loword of dwCallBack contains the handle of the lpMMThd block
- * which dwSignalCount has to be incremented
- */
- if (pFnGetMMThread16)
- {
- WINE_MMTHREAD* lpMMThd =
pFnGetMMThread16(LOWORD(dwCallBack));
-
- TRACE("mmThread (%04x, %p) !\n", LOWORD(dwCallBack),
lpMMThd);
- /* same as mmThreadSignal16 */
- InterlockedIncrement(&lpMMThd->dwSignalCount);
- SetEvent(lpMMThd->hEvent);
- /* some other stuff on lpMMThd->hVxD */
- }
- break;
-#if 0
- case 4:
- /* this is an undocumented DCB_ value for... I don't know */
- break;
-#endif
- default:
- WARN("Unknown callback type %d\n", uFlags & DCB_TYPEMASK);
- return FALSE;
- }
- 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);
-}
+/*
+ * WINE Drivers functions
+ *
+ * Copyright 1994 Martin Ayotte
+ * Copyright 1998 Marcus Meissner
+ * Copyright 1999 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "mmddk.h"
+#include "winemm.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(driver);
+
+static LPWINE_DRIVER lpDrvItemList /* = NULL */;
+static const WCHAR HKLM_BASE[] =
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t
','\\',
+
'W','i','n','d','o','w','s','
','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n',0
};
+
+WINE_MMTHREAD* (*pFnGetMMThread16)(UINT16 h) /* = NULL */;
+LPWINE_DRIVER (*pFnOpenDriver16)(LPCWSTR,LPCWSTR,LPARAM) /* = NULL
*/;
+LRESULT (*pFnCloseDriver16)(UINT16,LPARAM,LPARAM) /* = NULL */;
+LRESULT (*pFnSendMessage16)(UINT16,UINT,LPARAM,LPARAM) /* =
NULL */;
+
+/**********************************************************************
****
+ * DRIVER_GetNumberOfModuleRefs
[internal]
+ *
+ * Returns the number of open drivers which share the same module.
+ */
+static unsigned DRIVER_GetNumberOfModuleRefs(HMODULE hModule,
WINE_DRIVER** found)
+{
+ LPWINE_DRIVER lpDrv;
+ unsigned count = 0;
+
+ 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++;
+ }
+ }
+ return count;
+}
+
+/**********************************************************************
****
+ * DRIVER_FindFromHDrvr
[internal]
+ *
+ * From a hDrvr being 32 bits, returns the WINE internal structure.
+ */
+LPWINE_DRIVER DRIVER_FindFromHDrvr(HDRVR hDrvr)
+{
+ LPWINE_DRIVER d = (LPWINE_DRIVER)hDrvr;
+
+ if (hDrvr && HeapValidate(GetProcessHeap(), 0, d) && d->dwMagic
==
WINE_DI_MAGIC) {
+ return d;
+ }
+ return NULL;
+}
+
+/**********************************************************************
****
+ * DRIVER_SendMessage
[internal]
+ */
+static LRESULT inline DRIVER_SendMessage(LPWINE_DRIVER lpDrv, UINT msg,
+ LPARAM lParam1, LPARAM
lParam2)
+{
+ LRESULT ret = 0;
+
+ if (lpDrv->dwFlags & WINE_GDF_16BIT) {
+ /* no need to check mmsystem presence: the driver must have
been opened as a 16 bit one,
+ */
+ if (pFnSendMessage16)
+ ret = pFnSendMessage16(lpDrv->d.d16.hDriver16, msg,
lParam1, lParam2);
+ } else {
+ TRACE("Before call32 proc=%p drvrID=%08lx hDrv=%p wMsg=%04x
p1=%08lx p2=%08lx\n",
+ lpDrv->d.d32.lpDrvProc, lpDrv->d.d32.dwDriverID,
(HDRVR)lpDrv, msg, lParam1, lParam2);
+ ret = lpDrv->d.d32.lpDrvProc(lpDrv->d.d32.dwDriverID,
(HDRVR)lpDrv, msg, lParam1, lParam2);
+ TRACE("After call32 proc=%p drvrID=%08lx hDrv=%p wMsg=%04x
p1=%08lx p2=%08lx => %08lx\n",
+ lpDrv->d.d32.lpDrvProc, lpDrv->d.d32.dwDriverID,
(HDRVR)lpDrv, msg, lParam1, lParam2, ret);
+ }
+ return ret;
+}
+
+/**********************************************************************
****
+ * SendDriverMessage
[WINMM.@]
+ * DrvSendMessage
[WINMM.@]
+ */
+LRESULT WINAPI SendDriverMessage(HDRVR hDriver, UINT msg, LPARAM
lParam1,
+ LPARAM lParam2)
+{
+ LPWINE_DRIVER lpDrv;
+ LRESULT retval = 0;
+
+ TRACE("(%p, %04X, %08lX, %08lX)\n", hDriver, msg, lParam1,
lParam2);
+
+ if ((lpDrv = DRIVER_FindFromHDrvr(hDriver)) != NULL) {
+ retval = DRIVER_SendMessage(lpDrv, msg, lParam1, lParam2);
+ } else {
+ WARN("Bad driver handle %p\n", hDriver);
+ }
+ TRACE("retval = %ld\n", retval);
+
+ return retval;
+}
+
+/**********************************************************************
****
+ * 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)
+{
+ if (!(lpDrv->dwFlags & WINE_GDF_16BIT)) {
+ /* 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);
+ }
+ }
+
+ 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;
+
+ return TRUE;
+}
+
+/**********************************************************************
****
+ * 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)
+{
+ 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)) {
+ /* 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;
+ }
+ /* 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;
+ }
+
+ if (!(lpNewDrv->dwFlags & WINE_GDF_16BIT)) {
+ /* Now just open a new instance of a driver on this module */
+ lpNewDrv->d.d32.dwDriverID = DRIVER_SendMessage(lpNewDrv,
DRV_OPEN, lParam1, lParam2);
+
+ if (lpNewDrv->d.d32.dwDriverID == 0) {
+ TRACE("DRV_OPEN failed on driver 0x%08lx\n",
(DWORD)lpNewDrv);
+ DRIVER_RemoveFromList(lpNewDrv);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**********************************************************************
****
+ * DRIVER_GetLibName
[internal]
+ *
+ */
+BOOL DRIVER_GetLibName(LPCWSTR keyName, LPCWSTR sectName, LPWSTR buf,
int sz)
+{
+ HKEY hKey, hSecKey;
+ DWORD bufLen, lRet;
+ static const WCHAR wszSystemIni[] =
{'S','Y','S','T','E','M','.','I','N','I',0};
+ WCHAR wsznull = '\0';
+
+ lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, HKLM_BASE, 0,
KEY_QUERY_VALUE, &hKey);
+ if (lRet == ERROR_SUCCESS) {
+ lRet = RegOpenKeyExW(hKey, sectName, 0, KEY_QUERY_VALUE,
&hSecKey);
+ if (lRet == ERROR_SUCCESS) {
+ bufLen = sz;
+ lRet = RegQueryValueExW(hSecKey, keyName, 0, 0, (void*)buf,
&bufLen);
+ RegCloseKey( hSecKey );
+ }
+ RegCloseKey( hKey );
+ }
+ if (lRet == ERROR_SUCCESS) return TRUE;
+ /* default to system.ini if we can't find it in the registry,
+ * to support native installations where system.ini is still used
*/
+ return GetPrivateProfileStringW(sectName, keyName, &wsznull, buf,
sz / sizeof(WCHAR), wszSystemIni);
+}
+
+/**********************************************************************
****
+ * 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->d.d32.lpDrvProc = (DRIVERPROC)GetProcAddress(hModule,
"DriverProc");
+ if (lpDrv->d.d32.lpDrvProc == NULL) {cause = "no DriverProc"; goto
exit;}
+
+ lpDrv->dwFlags = 0;
+ lpDrv->d.d32.hModule = hModule;
+ lpDrv->d.d32.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->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;
+ exit:
+ FreeLibrary(hModule);
+ HeapFree(GetProcessHeap(), 0, lpDrv);
+ TRACE("Unable to load 32 bit module %s: %s\n", debugstr_w(fn),
cause);
+ return NULL;
+}
+
+/**********************************************************************
****
+ * OpenDriverA
[WINMM.@]
+ * DrvOpenA
[WINMM.@]
+ * (0,1,DRV_LOAD ,0 ,0)
+ * (0,1,DRV_ENABLE,0 ,0)
+ * (0,1,DRV_OPEN ,buf[256],0)
+ */
+HDRVR WINAPI OpenDriverA(LPCSTR lpDriverName, LPCSTR lpSectionName,
LPARAM lParam)
+{
+ INT len;
+ LPWSTR dn = NULL;
+ LPWSTR sn = NULL;
+ HDRVR ret;
+
+ if (lpDriverName)
+ {
+ len = MultiByteToWideChar( CP_ACP, 0, lpDriverName, -1, NULL, 0
);
+ dn = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+ if (!dn) return 0;
+ MultiByteToWideChar( CP_ACP, 0, lpDriverName, -1, dn, len );
+ }
+
+ if (lpSectionName)
+ {
+ len = MultiByteToWideChar( CP_ACP, 0, lpSectionName, -1, NULL,
0 );
+ sn = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+ if (!sn) return 0;
+ MultiByteToWideChar( CP_ACP, 0, lpSectionName, -1, sn, len );
+ }
+
+ ret = OpenDriver(dn, sn, lParam);
+
+ if (dn) HeapFree(GetProcessHeap(), 0, dn);
+ if (sn) HeapFree(GetProcessHeap(), 0, sn);
+ return ret;
+}
+
+/**********************************************************************
****
+ * OpenDriver
[WINMM.@]
+ * DrvOpen
[WINMM.@]
+ */
+HDRVR WINAPI OpenDriver(LPCWSTR lpDriverName, LPCWSTR lpSectionName,
LPARAM lParam)
+{
+ LPWINE_DRIVER lpDrv = NULL;
+ WCHAR libName[128];
+ LPCWSTR lsn = lpSectionName;
+
+ TRACE("(%s, %s, 0x%08lx);\n",
+ debugstr_w(lpDriverName), debugstr_w(lpSectionName), lParam);
+
+ if (lsn == NULL) {
+ static const WCHAR wszDrivers32[] =
{'D','r','i','v','e','r','s','3','2',0};
+ lstrcpynW(libName, lpDriverName, sizeof(libName) /
sizeof(WCHAR));
+
+ if ((lpDrv = DRIVER_TryOpenDriver32(libName, lParam)))
+ goto the_end;
+ lsn = wszDrivers32;
+ }
+ if (DRIVER_GetLibName(lpDriverName, lsn, libName, sizeof(libName))
&&
+ (lpDrv = DRIVER_TryOpenDriver32(libName, lParam)))
+ goto the_end;
+
+ /* now we will try a 16 bit driver (and add all the glue to make it
work... which
+ * is located in our mmsystem implementation)
+ * so ensure, we can load our mmsystem, otherwise just fail
+ */
+ WINMM_CheckForMMSystem();
+ if (pFnOpenDriver16 &&
+ (lpDrv = pFnOpenDriver16(lpDriverName, lpSectionName, lParam)))
+ {
+ if (DRIVER_AddToList(lpDrv, 0, lParam)) goto the_end;
+ HeapFree(GetProcessHeap(), 0, lpDrv);
+ }
+ TRACE("Failed to open driver %s from system.ini file, section
%s\n",
+ debugstr_w(lpDriverName), debugstr_w(lpSectionName));
+ return 0;
+
+ the_end:
+ if (lpDrv) TRACE("=> %08lx\n", (DWORD)lpDrv);
+ return (HDRVR)lpDrv;
+}
+
+/**********************************************************************
****
+ * CloseDriver
[WINMM.@]
+ * DrvClose
[WINMM.@]
+ */
+LRESULT WINAPI CloseDriver(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2)
+{
+ LPWINE_DRIVER lpDrv;
+
+ TRACE("(%p, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
+
+ if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL)
+ {
+ if (lpDrv->dwFlags & WINE_GDF_16BIT)
+ {
+ if (pFnCloseDriver16)
+ pFnCloseDriver16(lpDrv->d.d16.hDriver16, lParam1,
lParam2);
+ }
+ else
+ {
+ DRIVER_SendMessage(lpDrv, DRV_CLOSE, lParam1, lParam2);
+ lpDrv->d.d32.dwDriverID = 0;
+ }
+ if (DRIVER_RemoveFromList(lpDrv)) {
+ 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(lpDrv0->d.d32.hModule);
+ HeapFree(GetProcessHeap(), 0, lpDrv0);
+ }
+ FreeLibrary(lpDrv->d.d32.hModule);
+ }
+ HeapFree(GetProcessHeap(), 0, lpDrv);
+ return TRUE;
+ }
+ }
+ WARN("Failed to close driver\n");
[truncated at 1000 lines; 4984 more skipped]