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]