Commit 66b4468b authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

Split driver functions into USER (16 bit part) and WINMM (32 bit part).

Fixed some bugs in 16 bit part as well. Now correctly parsing the system.ini extra parameters.
parent af5ff94f
......@@ -8,6 +8,7 @@ ALTNAMES = mmsystem sound
IMPORTS = user32 kernel32 ntdll
C_SRCS = \
driver.c \
joystick.c \
lolvldrv.c \
mci.c \
......
......@@ -35,7 +35,7 @@ typedef struct tagWINE_MM_DRIVER_PART {
/* each low-level .drv will be associated with an instance of this structure */
typedef struct tagWINE_MM_DRIVER {
HDRVR hDrvr; /* handle of loader driver */
HDRVR hDriver;
LPSTR name; /* name of the driver */
BOOL bIs32 : 1, /* TRUE if 32 bit driver, FALSE for 16 */
bIsMapper : 1; /* TRUE if mapper */
......@@ -2244,32 +2244,33 @@ static BOOL MMDRV_Install(LPCSTR name, int num, BOOL bIsMapper)
{
int count = 0;
char buffer[128];
HMODULE hModule;
LPWINE_MM_DRIVER lpDrv = &MMDrvs[num];
LPWINE_DRIVER d;
TRACE("('%s');\n", name);
memset(lpDrv, 0, sizeof(*lpDrv));
/* First load driver */
if ((lpDrv->hDrvr = OpenDriverA(name, 0, 0)) == 0) {
if (!(lpDrv->hDriver = OpenDriverA(name, 0, 0))) {
WARN("Couldn't open driver '%s'\n", name);
return FALSE;
}
d = DRIVER_FindFromHDrvr(lpDrv->hDriver);
lpDrv->bIs32 = (d->dwFlags & WINE_GDF_16BIT) ? FALSE : TRUE;
/* Then look for xxxMessage functions */
#define AA(_w,_x,_y,_z) \
func = (WINEMM_msgFunc##_y) _z (hModule, #_x); \
#define AA(_h,_w,_x,_y,_z) \
func = (WINEMM_msgFunc##_y) _z ((_h), #_x); \
if (func != NULL) \
{ lpDrv->parts[_w].u.fnMessage##_y = func; count++; \
TRACE("Got %d bit func '%s'\n", _y, #_x); }
if ((GetDriverFlags(lpDrv->hDrvr) & (WINE_GDF_EXIST|WINE_GDF_16BIT)) == WINE_GDF_EXIST) {
if (lpDrv->bIs32) {
WINEMM_msgFunc32 func;
lpDrv->bIs32 = TRUE;
if ((hModule = GetDriverModuleHandle(lpDrv->hDrvr))) {
#define A(_x,_y) AA(_x,_y,32,GetProcAddress)
if (d->d.d32.hModule) {
#define A(_x,_y) AA(d->d.d32.hModule,_x,_y,32,GetProcAddress)
A(MMDRV_AUX, auxMessage);
A(MMDRV_MIXER, mixMessage);
A(MMDRV_MIDIIN, midMessage);
......@@ -2297,9 +2298,8 @@ static BOOL MMDRV_Install(LPCSTR name, int num, BOOL bIsMapper)
* mixer for mixer devices
*/
lpDrv->bIs32 = FALSE;
if ((hModule = GetDriverModuleHandle16(lpDrv->hDrvr))) {
#define A(_x,_y) AA(_x,_y,16,GetProcAddress16)
if (d->d.d16.hDriver16) {
#define A(_x,_y) AA(d->d.d16.hDriver16,_x,_y,16,GetProcAddress16)
A(MMDRV_AUX, auxMessage);
A(MMDRV_MIXER, mixMessage);
A(MMDRV_MIDIIN, midMessage);
......@@ -2320,7 +2320,7 @@ static BOOL MMDRV_Install(LPCSTR name, int num, BOOL bIsMapper)
}
if (!count) {
CloseDriver(lpDrv->hDrvr, 0, 0);
CloseDriver(lpDrv->hDriver, 0, 0);
WARN("No message functions found\n");
return FALSE;
}
......
......@@ -26,6 +26,18 @@ DEFAULT_DEBUG_CHANNEL(mci);
static int MCI_InstalledCount;
static LPSTR MCI_lpInstallNames = NULL;
typedef enum {
MCI_MAP_NOMEM, /* ko, memory problem */
MCI_MAP_MSGERROR, /* ko, unknown message */
MCI_MAP_OK, /* ok, no memory allocated. to be sent to the proc. */
MCI_MAP_OKMEM, /* ok, some memory allocated, need to call UnMapMsg. to be sent to the proc. */
} MCI_MapType;
static MCI_MapType MCI_MapMsg16To32A (WORD uDevType, WORD wMsg, DWORD* lParam);
static MCI_MapType MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam);
static MCI_MapType MCI_MapMsg32ATo16 (WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam);
static MCI_MapType MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam);
/* First MCI valid device ID (0 means error) */
#define MCI_MAGIC 0x0001
......@@ -387,8 +399,7 @@ static BOOL MCI_UnLoadMciDriver(LPWINE_MM_IDATA iData, LPWINE_MCIDRIVER wmd)
if (!wmd)
return TRUE;
if (wmd->hDrv)
CloseDriver(wmd->hDrv, 0, 0);
CloseDriver(wmd->hDriver, 0, 0);
if (wmd->dwPrivate != 0)
WARN("Unloading mci driver with non nul dwPrivate field\n");
......@@ -411,6 +422,42 @@ static BOOL MCI_UnLoadMciDriver(LPWINE_MM_IDATA iData, LPWINE_MCIDRIVER wmd)
}
/**************************************************************************
* MCI_OpenMciDriver [internal]
*/
static BOOL MCI_OpenMciDriver(LPWINE_MCIDRIVER wmd, LPCSTR drvTyp, LPARAM lp)
{
char libName[128];
if (!DRIVER_GetLibName(drvTyp, "mci", libName, sizeof(libName)))
return FALSE;
wmd->bIs32 = 0xFFFF;
/* First load driver */
if ((wmd->hDriver = (HDRVR)DRIVER_TryOpenDriver32(libName, lp))) {
wmd->bIs32 = TRUE;
} else {
MCI_MapType res;
switch (res = MCI_MapMsg32ATo16(0, MCI_OPEN_DRIVER, 0, &lp)) {
case MCI_MAP_MSGERROR:
TRACE("Not handled yet (MCI_OPEN_DRIVER)\n");
break;
case MCI_MAP_NOMEM:
TRACE("Problem mapping msg=MCI_OPEN_DRIVER from 32a to 16\n");
break;
case MCI_MAP_OK:
case MCI_MAP_OKMEM:
if ((wmd->hDriver = OpenDriverA(drvTyp, "mci", lp)))
wmd->bIs32 = FALSE;
if (res == MCI_MAP_OKMEM)
MCI_UnMapMsg32ATo16(0, MCI_OPEN_DRIVER, 0, lp);
break;
}
}
return (wmd->bIs32 == 0xFFFF) ? FALSE : TRUE;
}
/**************************************************************************
* MCI_LoadMciDriver [internal]
*/
static DWORD MCI_LoadMciDriver(LPWINE_MM_IDATA iData, LPCSTR _strDevTyp,
......@@ -420,8 +467,7 @@ static DWORD MCI_LoadMciDriver(LPWINE_MM_IDATA iData, LPCSTR _strDevTyp,
LPWINE_MCIDRIVER wmd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wmd));
MCI_OPEN_DRIVER_PARMSA modp;
DWORD dwRet = 0;
HDRVR hDrv = 0;
if (!wmd || !strDevTyp) {
dwRet = MCIERR_OUT_OF_MEMORY;
goto errCleanUp;
......@@ -450,28 +496,25 @@ static DWORD MCI_LoadMciDriver(LPWINE_MM_IDATA iData, LPCSTR _strDevTyp,
modp.lpstrParams = NULL;
hDrv = OpenDriverA(strDevTyp, "mci", (LPARAM)&modp);
if (!hDrv) {
if (!MCI_OpenMciDriver(wmd, strDevTyp, (LPARAM)&modp)) {
FIXME("Couldn't load driver for type %s.\n"
"If you don't have a windows installation accessible from Wine,\n"
"you perhaps forgot to create a [mci] section in system.ini\n",
strDevTyp);
dwRet = MCIERR_DEVICE_NOT_INSTALLED;
goto errCleanUp;
}
}
/* FIXME: should also check that module's description is of the form
* MODULENAME:[MCI] comment
*/
wmd->hDrv = hDrv;
/* some drivers will return 0x0000FFFF, some others 0xFFFFFFFF */
wmd->uSpecificCmdTable = LOWORD(modp.wCustomCommandTable);
wmd->uTypeCmdTable = MCI_COMMAND_TABLE_NOT_LOADED;
TRACE("Loaded driver %x (%s), type is %d, cmdTable=%08x\n",
hDrv, strDevTyp, modp.wType, modp.wCustomCommandTable);
wmd->hDriver, strDevTyp, modp.wType, modp.wCustomCommandTable);
wmd->lpstrDeviceType = strDevTyp;
wmd->wType = modp.wType;
......@@ -746,7 +789,9 @@ static DWORD MCI_HandleReturnValues(LPWINE_MM_IDATA iData, DWORD dwRet,
case MCI_RESOURCE_RETURNED|MCI_RESOURCE_DRIVER:
/* return string which ID is HIWORD(data[1]),
* string is loaded from driver */
LoadStringA(wmd->hDrv, HIWORD(data[1]), lpstrRet, uRetLen);
/* FIXME: this is wrong for a 16 bit handle */
LoadStringA(GetDriverModuleHandle(wmd->hDriver),
HIWORD(data[1]), lpstrRet, uRetLen);
break;
case MCI_COLONIZED3_RETURN:
snprintf(lpstrRet, uRetLen, "%d:%d:%d",
......@@ -1078,14 +1123,6 @@ BOOL WINAPI mciFreeCommandResource(UINT uTable)
return mciFreeCommandResource16(uTable);
}
typedef enum {
MCI_MAP_NOMEM, /* ko, memory problem */
MCI_MAP_MSGERROR, /* ko, unknown message */
MCI_MAP_OK, /* ok, no memory allocated. to be sent to the proc. */
MCI_MAP_OKMEM, /* ok, some memory allocated, need to call UnMapMsg. to be sent to the proc. */
MCI_MAP_PASS /* not handled (no memory allocated) to be sent to the driver */
} MCI_MapType;
/**************************************************************************
* MCI_MapMsg16To32A [internal]
*/
......@@ -1739,7 +1776,7 @@ static MCI_MapType MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DW
case DRV_EXITSESSION:
case DRV_EXITAPPLICATION:
case DRV_POWER:
return MCI_MAP_PASS;
return MCI_MAP_OK;
default:
WARN("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
......@@ -1924,7 +1961,7 @@ static MCI_MapType MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags,
case DRV_EXITAPPLICATION:
case DRV_POWER:
FIXME("This is a hack\n");
return MCI_MAP_PASS;
return MCI_MAP_OK;
default:
FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
return MCI_MAP_MSGERROR;
......@@ -1937,44 +1974,31 @@ static MCI_MapType MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags,
*/
DWORD MCI_SendCommandFrom32(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
{
DWORD dwRet = MCIERR_DEVICE_NOT_INSTALLED;
DWORD dwRet = MCIERR_INVALID_DEVICE_ID;
LPWINE_MCIDRIVER wmd = MCI_GetDriver(wDevID);
if (!wmd) {
dwRet = MCIERR_INVALID_DEVICE_ID;
} else {
switch (GetDriverFlags(wmd->hDrv) & (WINE_GDF_EXIST|WINE_GDF_16BIT)) {
case WINE_GDF_EXIST|WINE_GDF_16BIT:
{
MCI_MapType res;
if (wmd) {
if (wmd->bIs32) {
dwRet = SendDriverMessage(wmd->hDriver, wMsg, dwParam1, dwParam2);
} else {
MCI_MapType res;
switch (res = MCI_MapMsg32ATo16(wmd->wType, wMsg, dwParam1, &dwParam2)) {
case MCI_MAP_MSGERROR:
TRACE("Not handled yet (%s)\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_DRIVER_INTERNAL;
break;
case MCI_MAP_NOMEM:
TRACE("Problem mapping msg=%s from 32a to 16\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_OUT_OF_MEMORY;
break;
case MCI_MAP_OK:
case MCI_MAP_OKMEM:
dwRet = SendDriverMessage16(wmd->hDrv, wMsg, dwParam1, dwParam2);
if (res == MCI_MAP_OKMEM)
MCI_UnMapMsg32ATo16(wmd->wType, wMsg, dwParam1, dwParam2);
break;
case MCI_MAP_PASS:
dwRet = SendDriverMessage(wmd->hDrv, wMsg, dwParam1, dwParam2);
break;
}
switch (res = MCI_MapMsg32ATo16(wmd->wType, wMsg, dwParam1, &dwParam2)) {
case MCI_MAP_MSGERROR:
TRACE("Not handled yet (%s)\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_DRIVER_INTERNAL;
break;
case MCI_MAP_NOMEM:
TRACE("Problem mapping msg=%s from 32a to 16\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_OUT_OF_MEMORY;
break;
case MCI_MAP_OK:
case MCI_MAP_OKMEM:
dwRet = SendDriverMessage(wmd->hDriver, wMsg, dwParam1, dwParam2);
if (res == MCI_MAP_OKMEM)
MCI_UnMapMsg32ATo16(wmd->wType, wMsg, dwParam1, dwParam2);
break;
}
break;
case WINE_GDF_EXIST:
dwRet = SendDriverMessage(wmd->hDrv, wMsg, dwParam1, dwParam2);
break;
default:
WARN("Unknown driver %u\n", wmd->hDrv);
dwRet = MCIERR_DRIVER_INTERNAL;
}
}
return dwRet;
......@@ -1985,19 +2009,15 @@ DWORD MCI_SendCommandFrom32(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwPa
*/
DWORD MCI_SendCommandFrom16(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
{
DWORD dwRet = MCIERR_DEVICE_NOT_INSTALLED;
DWORD dwRet = MCIERR_INVALID_DEVICE_ID;
LPWINE_MCIDRIVER wmd = MCI_GetDriver(wDevID);
if (!wmd) {
if (wmd) {
dwRet = MCIERR_INVALID_DEVICE_ID;
} else {
MCI_MapType res;
switch (GetDriverFlags(wmd->hDrv) & (WINE_GDF_EXIST|WINE_GDF_16BIT)) {
case WINE_GDF_EXIST|WINE_GDF_16BIT:
dwRet = SendDriverMessage16(wmd->hDrv, wMsg, dwParam1, dwParam2);
break;
case WINE_GDF_EXIST:
if (wmd->bIs32) {
MCI_MapType res;
switch (res = MCI_MapMsg16To32A(wmd->wType, wMsg, &dwParam2)) {
case MCI_MAP_MSGERROR:
TRACE("Not handled yet (%s)\n", MCI_MessageToString(wMsg));
......@@ -2009,18 +2029,13 @@ DWORD MCI_SendCommandFrom16(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwPa
break;
case MCI_MAP_OK:
case MCI_MAP_OKMEM:
dwRet = SendDriverMessage(wmd->hDrv, wMsg, dwParam1, dwParam2);
dwRet = SendDriverMessage(wmd->hDriver, wMsg, dwParam1, dwParam2);
if (res == MCI_MAP_OKMEM)
MCI_UnMapMsg16To32A(wmd->wType, wMsg, dwParam2);
break;
case MCI_MAP_PASS:
dwRet = SendDriverMessage16(wmd->hDrv, wMsg, dwParam1, dwParam2);
break;
}
break;
default:
WARN("Unknown driver %u\n", wmd->hDrv);
dwRet = MCIERR_DRIVER_INTERNAL;
} else {
dwRet = SendDriverMessage(wmd->hDriver, wMsg, dwParam1, dwParam2);
}
}
return dwRet;
......
......@@ -32,9 +32,6 @@
DEFAULT_DEBUG_CHANNEL(mmsys);
LONG WINAPI DrvDefDriverProc(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
DWORD dwParam1, DWORD dwParam2);
static LPWINE_MM_IDATA lpFirstIData = NULL;
static LPWINE_MM_IDATA MULTIMEDIA_GetIDataNoCheck(void)
......@@ -637,18 +634,6 @@ UINT16 WINAPI mmsystemGetVersion16(void)
}
/**************************************************************************
* DriverProc [MMSYSTEM.6]
*/
LRESULT WINAPI DriverProc16(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
DWORD dwParam1, DWORD dwParam2)
{
TRACE("dwDevID=%08lx hDrv=%04x wMsg=%04x dwParam1=%08lx dwParam2=%08lx\n",
dwDevID, hDrv, wMsg, dwParam1, dwParam2);
return DrvDefDriverProc(dwDevID, hDrv, wMsg, dwParam1, dwParam2);
}
/**************************************************************************
* DriverCallback [MMSYSTEM.31]
*/
BOOL WINAPI DriverCallback(DWORD dwCallBack, UINT uFlags, HDRVR hDev,
......@@ -4857,73 +4842,6 @@ DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, TRUE);
}
/**************************************************************************
* DrvOpen [MMSYSTEM.1100]
*/
HDRVR16 WINAPI DrvOpen(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
{
TRACE("('%s','%s', %08lX);\n", lpDriverName, lpSectionName, lParam);
return OpenDriver16(lpDriverName, lpSectionName, lParam);
}
/**************************************************************************
* DrvClose [MMSYSTEM.1101]
*/
LRESULT WINAPI DrvClose(HDRVR16 hDrv, LPARAM lParam1, LPARAM lParam2)
{
TRACE("(%04X, %08lX, %08lX);\n", hDrv, lParam1, lParam2);
return CloseDriver16(hDrv, lParam1, lParam2);
}
/**************************************************************************
* DrvSendMessage [MMSYSTEM.1102]
*/
LRESULT WINAPI DrvSendMessage(HDRVR16 hDrv, WORD msg, LPARAM lParam1,
LPARAM lParam2)
{
return SendDriverMessage(hDrv, msg, lParam1, lParam2);
}
/**************************************************************************
* DrvGetModuleHandle [MMSYSTEM.1103]
*/
HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrv)
{
return GetDriverModuleHandle16(hDrv);
}
/**************************************************************************
* DrvDefDriverProc [MMSYSTEM.1104]
*/
LRESULT WINAPI DrvDefDriverProc(DWORD dwDriverID, HDRVR16 hDrv, WORD wMsg,
DWORD dwParam1, DWORD dwParam2)
{
/* FIXME : any mapping from 32 to 16 bit structure ? */
return DefDriverProc16(dwDriverID, hDrv, wMsg, dwParam1, dwParam2);
}
/**************************************************************************
* DefDriverProc [WINMM.5]
*/
LRESULT WINAPI DefDriverProc(DWORD 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;
}
}
/*#define USE_MM_TSK_WINE*/
/**************************************************************************
......
......@@ -137,11 +137,11 @@ owner winmm
903 pascal mmTaskSignal(word) mmTaskSignal16
904 pascal mmGetCurrentTask() WIN16_GetCurrentTask #just the same
905 pascal mmTaskYield() mmTaskYield16
1100 pascal DrvOpen(str str long) DrvOpen
1101 pascal DrvClose(word long long) DrvClose
1102 pascal DrvSendMessage(word word long long) DrvSendMessage
1100 pascal DrvOpen(str str long) DrvOpen16
1101 pascal DrvClose(word long long) DrvClose16
1102 pascal DrvSendMessage(word word long long) DrvSendMessage16
1103 pascal DrvGetModuleHandle(word) DrvGetModuleHandle16
1104 pascal DrvDefDriverProc(long word word long long) DrvDefDriverProc
1104 pascal DrvDefDriverProc(long word word long long) DrvDefDriverProc16
1120 pascal mmThreadCreate(segptr ptr long long) mmThreadCreate16
1121 pascal mmThreadSignal(word) mmThreadSignal16
1122 pascal mmThreadBlock(word) mmThreadBlock16
......@@ -176,5 +176,5 @@ owner winmm
#2006 stub WINMMSL_THUNKDATA16
2046 pascal DllEntryPoint(long word word word long word) MMSYSTEM_LibMain
# this is a wine only exported function. Is there another way to do it ?
2047 pascal WINE_mmThreadEntryPoint(long) WINE_mmThreadEntryPoint
# these are Wine only exported functions. Is there another way to do it ?
2047 pascal __wine_mmThreadEntryPoint(long) WINE_mmThreadEntryPoint
......@@ -15,6 +15,28 @@
typedef DWORD WINAPI (*MessageProc16)(UINT16 wDevID, UINT16 wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2);
typedef DWORD WINAPI (*MessageProc32)(UINT wDevID, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2);
/* Who said goofy boy ? */
#define WINE_DI_MAGIC 0x900F1B01
typedef struct tagWINE_DRIVER
{
DWORD dwMagic;
/* as usual LPWINE_DRIVER == hDriver32 */
DWORD dwFlags;
union {
struct {
HMODULE hModule;
DRIVERPROC lpDrvProc;
DWORD dwDriverID;
} d32;
struct {
HDRVR16 hDriver16;
} d16;
} d;
struct tagWINE_DRIVER* lpPrevItem;
struct tagWINE_DRIVER* lpNextItem;
} WINE_DRIVER, *LPWINE_DRIVER;
typedef struct tagWINE_MLD {
/* EPP struct tagWINE_MLD* lpNext; */ /* not used so far */
UINT uDeviceID;
......@@ -85,7 +107,7 @@ typedef struct tagWINE_MCIDRIVER {
LPSTR lpstrElementName;
LPSTR lpstrDeviceType;
LPSTR lpstrAlias;
HDRVR hDrv;
HDRVR hDriver;
DRIVERPROC16 driverProc;
DWORD dwPrivate;
YIELDPROC lpfnYieldProc;
......@@ -150,6 +172,10 @@ typedef struct tagWINE_MM_IDATA {
typedef LONG (*MCIPROC16)(DWORD, HDRVR16, WORD, DWORD, DWORD);
typedef LONG (*MCIPROC)(DWORD, HDRVR, DWORD, DWORD, DWORD);
extern LPWINE_DRIVER DRIVER_FindFromHDrvr(HDRVR hDrvr);
extern BOOL DRIVER_GetLibName(LPCSTR keyName, LPCSTR sectName, LPSTR buf, int sz);
extern LPWINE_DRIVER DRIVER_TryOpenDriver32(LPCSTR fn, LPARAM lParam2);
extern LPWINE_MCIDRIVER MCI_GetDriver(UINT16 uDevID);
extern UINT MCI_GetDriverFromString(LPCSTR str);
extern DWORD MCI_WriteString(LPSTR lpDstStr, DWORD dstSize, LPCSTR lpSrcStr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment