From 01f2426dcf11290fb1dfc388db47ec3e99cd6c07 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sat, 24 Dec 2022 10:05:08 +0200 Subject: [PATCH] [WINMM] Sync mci.c with wine Date: 2022-02-22 Author: Eric Pouech Commit: "winmm: Enable compilation with long types." Hash 71189f62604c2cb8208c85372a0e027dd2b79055 --- dll/win32/winmm/mci.c | 854 +++++++++++++++++++++++---------------- dll/win32/winmm/winemm.h | 7 +- 2 files changed, 508 insertions(+), 353 deletions(-) diff --git a/dll/win32/winmm/mci.c b/dll/win32/winmm/mci.c index b5ee88de9cf..8a5f221e349 100644 --- a/dll/win32/winmm/mci.c +++ b/dll/win32/winmm/mci.c @@ -37,11 +37,24 @@ * - command table handling isn't thread safe */ +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "mmsystem.h" +#include "winuser.h" +#include "winnls.h" +#include "winreg.h" +#include "wownt32.h" + +#include "digitalv.h" #include "winemm.h" -#include -#include -#include +#include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(mci); @@ -49,12 +62,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mci); #define MCI_MAGIC 0x0001 /* MCI settings */ -static const WCHAR wszHklmMci [] = {'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','\\','M','C','I',0}; -static const WCHAR wszNull [] = {0}; -static const WCHAR wszAll [] = {'A','L','L',0}; -static const WCHAR wszMci [] = {'M','C','I',0}; -static const WCHAR wszOpen [] = {'o','p','e','n',0}; -static const WCHAR wszSystemIni[] = {'s','y','s','t','e','m','.','i','n','i',0}; +static const WCHAR wszHklmMci [] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\MCI"; static WINE_MCIDRIVER *MciDrivers; @@ -64,7 +72,7 @@ static UINT MCI_SetCommandTable(HGLOBAL hMem, UINT uDevType); /* dup a string and uppercase it */ static inline LPWSTR str_dup_upper( LPCWSTR str ) { - INT len = (strlenW(str) + 1) * sizeof(WCHAR); + INT len = (lstrlenW(str) + 1) * sizeof(WCHAR); LPWSTR p = HeapAlloc( GetProcessHeap(), 0, len ); if (p) { @@ -101,20 +109,12 @@ static UINT MCI_GetDriverFromString(LPCWSTR lpstrName) if (!lpstrName) return 0; - if (!strcmpiW(lpstrName, wszAll)) + if (!wcsicmp(lpstrName, L"ALL")) return MCI_ALL_DEVICE_ID; EnterCriticalSection(&WINMM_cs); for (wmd = MciDrivers; wmd; wmd = wmd->lpNext) { - if (wmd->lpstrElementName && strcmpW(wmd->lpstrElementName, lpstrName) == 0) { - ret = wmd->wDeviceID; - break; - } - if (wmd->lpstrDeviceType && strcmpiW(wmd->lpstrDeviceType, lpstrName) == 0) { - ret = wmd->wDeviceID; - break; - } - if (wmd->lpstrAlias && strcmpiW(wmd->lpstrAlias, lpstrName) == 0) { + if (wmd->lpstrAlias && wcsicmp(wmd->lpstrAlias, lpstrName) == 0) { ret = wmd->wDeviceID; break; } @@ -127,10 +127,8 @@ static UINT MCI_GetDriverFromString(LPCWSTR lpstrName) /************************************************************************** * MCI_MessageToString [internal] */ -const char* MCI_MessageToString(UINT wMsg) +static const char* MCI_MessageToString(UINT wMsg) { - static char buffer[100]; - #define CASE(s) case (s): return #s switch (wMsg) { @@ -171,6 +169,7 @@ const char* MCI_MessageToString(UINT wMsg) CASE(MCI_SAVE); CASE(MCI_SEEK); CASE(MCI_SET); + CASE(MCI_SOUND); CASE(MCI_SPIN); CASE(MCI_STATUS); CASE(MCI_STEP); @@ -194,12 +193,11 @@ const char* MCI_MessageToString(UINT wMsg) CASE(MCI_RESTORE); #undef CASE default: - sprintf(buffer, "MCI_<<%04X>>", wMsg); - return buffer; + return wine_dbg_sprintf("MCI_<<%04X>>", wMsg); } } -LPWSTR MCI_strdupAtoW( LPCSTR str ) +static LPWSTR MCI_strdupAtoW( LPCSTR str ) { LPWSTR ret; INT len; @@ -211,18 +209,6 @@ LPWSTR MCI_strdupAtoW( LPCSTR str ) return ret; } -LPSTR MCI_strdupWtoA( LPCWSTR str ) -{ - LPSTR ret; - INT len; - - if (!str) return NULL; - len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL ); - ret = HeapAlloc( GetProcessHeap(), 0, len ); - if (ret) WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); - return ret; -} - static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2) { if (msg < DRV_RESERVED) return 0; @@ -241,7 +227,6 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2) case MCI_STEP: case MCI_RECORD: case MCI_BREAK: - case MCI_SOUND: case MCI_STATUS: case MCI_CUE: case MCI_REALIZE: @@ -256,24 +241,23 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2) case MCI_RESUME: case MCI_DELETE: case MCI_MONITOR: - case MCI_SETAUDIO: case MCI_SIGNAL: - case MCI_SETVIDEO: - case MCI_LIST: + case MCI_UNDO: return 0; case MCI_OPEN: - { - MCI_OPEN_PARMSA *mci_openA = (MCI_OPEN_PARMSA*)*dwParam2; - MCI_OPEN_PARMSW *mci_openW; + { /* MCI_ANIM_OPEN_PARMS is the largest known MCI_OPEN_PARMS + * structure, larger than MCI_WAVE_OPEN_PARMS */ + MCI_ANIM_OPEN_PARMSA *mci_openA = (MCI_ANIM_OPEN_PARMSA*)*dwParam2; + MCI_ANIM_OPEN_PARMSW *mci_openW; DWORD_PTR *ptr; - ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD_PTR) + sizeof(*mci_openW) + 2 * sizeof(DWORD)); + ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD_PTR) + sizeof(*mci_openW)); if (!ptr) return -1; *ptr++ = *dwParam2; /* save the previous pointer */ *dwParam2 = (DWORD_PTR)ptr; - mci_openW = (MCI_OPEN_PARMSW *)ptr; + mci_openW = (MCI_ANIM_OPEN_PARMSW *)ptr; if (dwParam1 & MCI_NOTIFY) mci_openW->dwCallback = mci_openA->dwCallback; @@ -294,11 +278,10 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2) } if (dwParam1 & MCI_OPEN_ALIAS) mci_openW->lpstrAlias = MCI_strdupAtoW(mci_openA->lpstrAlias); - /* FIXME: this is only needed for specific types of MCI devices, and - * may cause a segfault if the two DWORD:s don't exist at the end of - * mci_openA - */ - memcpy(mci_openW + 1, mci_openA + 1, 2 * sizeof(DWORD)); + /* We don't know how many DWORD follow, as + * the structure depends on the device. */ + if (HIWORD(dwParam1)) + memcpy(&mci_openW->dwStyle, &mci_openA->dwStyle, sizeof(MCI_ANIM_OPEN_PARMSW) - sizeof(MCI_OPEN_PARMSW)); } return 1; @@ -327,6 +310,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2) return 0; case MCI_SYSINFO: + if (dwParam1 & (MCI_SYSINFO_INSTALLNAME | MCI_SYSINFO_NAME)) { MCI_SYSINFO_PARMSA *mci_sysinfoA = (MCI_SYSINFO_PARMSA *)*dwParam2; MCI_SYSINFO_PARMSW *mci_sysinfoW; @@ -342,16 +326,18 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2) if (dwParam1 & MCI_NOTIFY) mci_sysinfoW->dwCallback = mci_sysinfoA->dwCallback; + /* Size is measured in numbers of characters, despite what MSDN says. */ mci_sysinfoW->dwRetSize = mci_sysinfoA->dwRetSize; - mci_sysinfoW->lpstrReturn = HeapAlloc(GetProcessHeap(), 0, mci_sysinfoW->dwRetSize); + mci_sysinfoW->lpstrReturn = HeapAlloc(GetProcessHeap(), 0, mci_sysinfoW->dwRetSize * sizeof(WCHAR)); mci_sysinfoW->dwNumber = mci_sysinfoA->dwNumber; mci_sysinfoW->wDeviceType = mci_sysinfoA->wDeviceType; return 1; } + return 0; case MCI_INFO: { - MCI_INFO_PARMSA *mci_infoA = (MCI_INFO_PARMSA *)*dwParam2; - MCI_INFO_PARMSW *mci_infoW; + MCI_DGV_INFO_PARMSA *mci_infoA = (MCI_DGV_INFO_PARMSA *)*dwParam2; + MCI_DGV_INFO_PARMSW *mci_infoW; DWORD_PTR *ptr; ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(*mci_infoW) + sizeof(DWORD_PTR)); @@ -359,33 +345,25 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2) *ptr++ = *dwParam2; /* save the previous pointer */ *dwParam2 = (DWORD_PTR)ptr; - mci_infoW = (MCI_INFO_PARMSW *)ptr; + mci_infoW = (MCI_DGV_INFO_PARMSW *)ptr; if (dwParam1 & MCI_NOTIFY) mci_infoW->dwCallback = mci_infoA->dwCallback; - mci_infoW->dwRetSize = mci_infoA->dwRetSize * sizeof(WCHAR); /* it's not the same as SYSINFO !!! */ - mci_infoW->lpstrReturn = HeapAlloc(GetProcessHeap(), 0, mci_infoW->dwRetSize); + /* Size is measured in numbers of characters. */ + mci_infoW->dwRetSize = mci_infoA->dwRetSize; + mci_infoW->lpstrReturn = HeapAlloc(GetProcessHeap(), 0, mci_infoW->dwRetSize * sizeof(WCHAR)); + if (dwParam1 & MCI_DGV_INFO_ITEM) + mci_infoW->dwItem = mci_infoA->dwItem; return 1; } case MCI_SAVE: - { - MCI_SAVE_PARMSA *mci_saveA = (MCI_SAVE_PARMSA *)*dwParam2; - MCI_SAVE_PARMSW *mci_saveW; - - mci_saveW = HeapAlloc(GetProcessHeap(), 0, sizeof(*mci_saveW)); - if (!mci_saveW) return -1; - - *dwParam2 = (DWORD_PTR)mci_saveW; - if (dwParam1 & MCI_NOTIFY) - mci_saveW->dwCallback = mci_saveA->dwCallback; - mci_saveW->lpfilename = MCI_strdupAtoW(mci_saveA->lpfilename); - return 1; - } case MCI_LOAD: - { - MCI_LOAD_PARMSA *mci_loadA = (MCI_LOAD_PARMSA *)*dwParam2; - MCI_LOAD_PARMSW *mci_loadW; + case MCI_CAPTURE: + case MCI_RESTORE: + { /* All these commands have the same layout: callback + string + optional rect */ + MCI_OVLY_LOAD_PARMSA *mci_loadA = (MCI_OVLY_LOAD_PARMSA *)*dwParam2; + MCI_OVLY_LOAD_PARMSW *mci_loadW; mci_loadW = HeapAlloc(GetProcessHeap(), 0, sizeof(*mci_loadW)); if (!mci_loadW) return -1; @@ -394,11 +372,16 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2) if (dwParam1 & MCI_NOTIFY) mci_loadW->dwCallback = mci_loadA->dwCallback; mci_loadW->lpfilename = MCI_strdupAtoW(mci_loadA->lpfilename); + if ((MCI_SAVE == msg && dwParam1 & MCI_DGV_RECT) || + (MCI_LOAD == msg && dwParam1 & MCI_OVLY_RECT) || + (MCI_CAPTURE == msg && dwParam1 & MCI_DGV_CAPTURE_AT) || + (MCI_RESTORE == msg && dwParam1 & MCI_DGV_RESTORE_AT)) + mci_loadW->rc = mci_loadA->rc; return 1; } - + case MCI_SOUND: case MCI_ESCAPE: - { + { /* All these commands have the same layout: callback + string */ MCI_VD_ESCAPE_PARMSA *mci_vd_escapeA = (MCI_VD_ESCAPE_PARMSA *)*dwParam2; MCI_VD_ESCAPE_PARMSW *mci_vd_escapeW; @@ -411,13 +394,22 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2) mci_vd_escapeW->lpstrCommand = MCI_strdupAtoW(mci_vd_escapeA->lpstrCommand); return 1; } + case MCI_SETAUDIO: + case MCI_SETVIDEO: + if (!(dwParam1 & (MCI_DGV_SETVIDEO_QUALITY | MCI_DGV_SETVIDEO_ALG + | MCI_DGV_SETAUDIO_QUALITY | MCI_DGV_SETAUDIO_ALG))) + return 0; + /* fall through to default */ + case MCI_RESERVE: + case MCI_QUALITY: + case MCI_LIST: default: FIXME("Message %s needs translation\n", MCI_MessageToString(msg)); - return -1; + return 0; /* pass through untouched */ } } -static DWORD MCI_UnmapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, +static void MCI_UnmapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, DWORD result) { switch (msg) @@ -426,7 +418,7 @@ static DWORD MCI_UnmapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, { DWORD_PTR *ptr = (DWORD_PTR *)dwParam2 - 1; MCI_OPEN_PARMSA *mci_openA = (MCI_OPEN_PARMSA *)*ptr; - MCI_OPEN_PARMSW *mci_openW = (MCI_OPEN_PARMSW *)(ptr + 1); + MCI_OPEN_PARMSW *mci_openW = (MCI_OPEN_PARMSW *)dwParam2; mci_openA->wDeviceID = mci_openW->wDeviceID; @@ -456,22 +448,18 @@ static DWORD MCI_UnmapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, break; case MCI_SYSINFO: + if (dwParam1 & (MCI_SYSINFO_INSTALLNAME | MCI_SYSINFO_NAME)) { DWORD_PTR *ptr = (DWORD_PTR *)dwParam2 - 1; MCI_SYSINFO_PARMSA *mci_sysinfoA = (MCI_SYSINFO_PARMSA *)*ptr; - MCI_SYSINFO_PARMSW *mci_sysinfoW = (MCI_SYSINFO_PARMSW *)(ptr + 1); + MCI_SYSINFO_PARMSW *mci_sysinfoW = (MCI_SYSINFO_PARMSW *)dwParam2; if (!result) { - mci_sysinfoA->dwNumber = mci_sysinfoW->dwNumber; - mci_sysinfoA->wDeviceType = mci_sysinfoW->wDeviceType; - if (dwParam1 & MCI_SYSINFO_QUANTITY) - *(DWORD*)mci_sysinfoA->lpstrReturn = *(DWORD*)mci_sysinfoW->lpstrReturn; - else - WideCharToMultiByte(CP_ACP, 0, - mci_sysinfoW->lpstrReturn, mci_sysinfoW->dwRetSize, - mci_sysinfoA->lpstrReturn, mci_sysinfoA->dwRetSize, - NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, + mci_sysinfoW->lpstrReturn, -1, + mci_sysinfoA->lpstrReturn, mci_sysinfoA->dwRetSize, + NULL, NULL); } HeapFree(GetProcessHeap(), 0, mci_sysinfoW->lpstrReturn); @@ -482,12 +470,12 @@ static DWORD MCI_UnmapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, { DWORD_PTR *ptr = (DWORD_PTR *)dwParam2 - 1; MCI_INFO_PARMSA *mci_infoA = (MCI_INFO_PARMSA *)*ptr; - MCI_INFO_PARMSW *mci_infoW = (MCI_INFO_PARMSW *)(ptr + 1); + MCI_INFO_PARMSW *mci_infoW = (MCI_INFO_PARMSW *)dwParam2; if (!result) { WideCharToMultiByte(CP_ACP, 0, - mci_infoW->lpstrReturn, mci_infoW->dwRetSize / sizeof(WCHAR), + mci_infoW->lpstrReturn, -1, mci_infoA->lpstrReturn, mci_infoA->dwRetSize, NULL, NULL); } @@ -497,23 +485,19 @@ static DWORD MCI_UnmapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, } break; case MCI_SAVE: - { - MCI_SAVE_PARMSW *mci_saveW = (MCI_SAVE_PARMSW *)dwParam2; - - HeapFree(GetProcessHeap(), 0, (void*)mci_saveW->lpfilename); - HeapFree(GetProcessHeap(), 0, mci_saveW); - } - break; case MCI_LOAD: - { - MCI_LOAD_PARMSW *mci_loadW = (MCI_LOAD_PARMSW *)dwParam2; + case MCI_CAPTURE: + case MCI_RESTORE: + { /* All these commands have the same layout: callback + string + optional rect */ + MCI_OVLY_LOAD_PARMSW *mci_loadW = (MCI_OVLY_LOAD_PARMSW *)dwParam2; HeapFree(GetProcessHeap(), 0, (void*)mci_loadW->lpfilename); HeapFree(GetProcessHeap(), 0, mci_loadW); } break; + case MCI_SOUND: case MCI_ESCAPE: - { + { /* All these commands have the same layout: callback + string */ MCI_VD_ESCAPE_PARMSW *mci_vd_escapeW = (MCI_VD_ESCAPE_PARMSW *)dwParam2; HeapFree(GetProcessHeap(), 0, (void*)mci_vd_escapeW->lpstrCommand); @@ -525,8 +509,6 @@ static DWORD MCI_UnmapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, FIXME("Message %s needs unmapping\n", MCI_MessageToString(msg)); break; } - - return result; } /************************************************************************** @@ -536,11 +518,9 @@ static DWORD MCI_GetDevTypeFromFileName(LPCWSTR fileName, LPWSTR buf, UINT len) { LPCWSTR tmp; HKEY hKey; - static const WCHAR keyW[] = {'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','\\', - 'M','C','I',' ','E','x','t','e','n','s','i','o','n','s',0}; - if ((tmp = strrchrW(fileName, '.'))) { - if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, keyW, + if ((tmp = wcsrchr(fileName, '.'))) { + if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI Extensions", 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS) { DWORD dwLen = len; LONG lRet = RegQueryValueExW( hKey, tmp + 1, 0, 0, (void*)buf, &dwLen ); @@ -552,6 +532,23 @@ static DWORD MCI_GetDevTypeFromFileName(LPCWSTR fileName, LPWSTR buf, UINT len) return MCIERR_EXTENSION_NOT_FOUND; } +/************************************************************************** + * MCI_GetDevTypeFromResource [internal] + */ +static UINT MCI_GetDevTypeFromResource(LPCWSTR lpstrName) +{ + WCHAR buf[32]; + UINT uDevType; + for (uDevType = MCI_DEVTYPE_FIRST; uDevType <= MCI_DEVTYPE_LAST; uDevType++) { + if (LoadStringW(hWinMM32Instance, uDevType, buf, ARRAY_SIZE(buf))) { + /* FIXME: ignore digits suffix */ + if (!wcsicmp(buf, lpstrName)) + return uDevType; + } + } + return 0; +} + #define MAX_MCICMDTABLE 20 #define MCI_COMMAND_TABLE_NOT_LOADED 0xFFFE @@ -586,7 +583,7 @@ static BOOL MCI_IsCommandTableValid(UINT uTbl) lmem = S_MciCmdTable[uTbl].lpTable; do { str = (LPCWSTR)lmem; - lmem += (strlenW(str) + 1) * sizeof(WCHAR); + lmem += (lstrlenW(str) + 1) * sizeof(WCHAR); flg = *(const DWORD*)lmem; eid = *(const WORD*)(lmem + sizeof(DWORD)); lmem += sizeof(DWORD) + sizeof(WORD); @@ -595,6 +592,9 @@ static BOOL MCI_IsCommandTableValid(UINT uTbl) switch (eid) { case MCI_COMMAND_HEAD: if (!*str || !flg) return FALSE; idx = 0; break; /* check unicity of str in table */ case MCI_STRING: if (inCst) return FALSE; break; + case MCI_HWND: /* Occurs inside MCI_CONSTANT as in "window handle default" */ + case MCI_HPAL: + case MCI_HDC: case MCI_INTEGER: if (!*str) return FALSE; break; case MCI_END_COMMAND: if (*str || flg || idx == 0) return FALSE; idx = 0; break; case MCI_RETURN: if (*str || idx != 1) return FALSE; break; @@ -616,7 +616,6 @@ static BOOL MCI_DumpCommandTable(UINT uTbl) { const BYTE* lmem; LPCWSTR str; - DWORD flg; WORD eid; if (!MCI_IsCommandTableValid(uTbl)) { @@ -627,9 +626,10 @@ static BOOL MCI_DumpCommandTable(UINT uTbl) lmem = S_MciCmdTable[uTbl].lpTable; do { do { + /* DWORD flg; */ str = (LPCWSTR)lmem; - lmem += (strlenW(str) + 1) * sizeof(WCHAR); - flg = *(const DWORD*)lmem; + lmem += (lstrlenW(str) + 1) * sizeof(WCHAR); + /* flg = *(const DWORD*)lmem; */ eid = *(const WORD*)(lmem + sizeof(DWORD)); /* TRACE("cmd=%s %08lx %04x\n", debugstr_w(str), flg, eid); */ lmem += sizeof(DWORD) + sizeof(WORD); @@ -657,12 +657,11 @@ static UINT MCI_GetCommandTable(UINT uDevType) /* well try to load id */ if (uDevType >= MCI_DEVTYPE_FIRST && uDevType <= MCI_DEVTYPE_LAST) { - if (LoadStringW(hWinMM32Instance, uDevType, buf, sizeof(buf) / sizeof(WCHAR))) { + if (LoadStringW(hWinMM32Instance, uDevType, buf, ARRAY_SIZE(buf))) { str = buf; } } else if (uDevType == 0) { - static const WCHAR wszCore[] = {'C','O','R','E',0}; - str = wszCore; + str = L"CORE"; } uTbl = MCI_NO_COMMAND_TABLE; if (str) { @@ -720,7 +719,7 @@ static UINT MCI_SetCommandTable(HGLOBAL hMem, UINT uDevType) count = 0; do { str = (LPCWSTR)lmem; - lmem += (strlenW(str) + 1) * sizeof(WCHAR); + lmem += (lstrlenW(str) + 1) * sizeof(WCHAR); eid = *(const WORD*)(lmem + sizeof(DWORD)); lmem += sizeof(DWORD) + sizeof(WORD); if (eid == MCI_COMMAND_HEAD) @@ -734,7 +733,7 @@ static UINT MCI_SetCommandTable(HGLOBAL hMem, UINT uDevType) count = 0; do { str = (LPCWSTR)lmem; - lmem += (strlenW(str) + 1) * sizeof(WCHAR); + lmem += (lstrlenW(str) + 1) * sizeof(WCHAR); eid = *(const WORD*)(lmem + sizeof(DWORD)); lmem += sizeof(DWORD) + sizeof(WORD); if (eid == MCI_COMMAND_HEAD) @@ -774,7 +773,6 @@ static BOOL MCI_UnLoadMciDriver(LPWINE_MCIDRIVER wmd) HeapFree(GetProcessHeap(), 0, wmd->lpstrDeviceType); HeapFree(GetProcessHeap(), 0, wmd->lpstrAlias); - HeapFree(GetProcessHeap(), 0, wmd->lpstrElementName); HeapFree(GetProcessHeap(), 0, wmd); return TRUE; @@ -787,7 +785,7 @@ static BOOL MCI_OpenMciDriver(LPWINE_MCIDRIVER wmd, LPCWSTR drvTyp, DWORD_PTR lp { WCHAR libName[128]; - if (!DRIVER_GetLibName(drvTyp, wszMci, libName, sizeof(libName))) + if (!DRIVER_GetLibName(drvTyp, L"MCI", libName, sizeof(libName))) return FALSE; /* First load driver */ @@ -837,7 +835,7 @@ static DWORD MCI_LoadMciDriver(LPCWSTR _strDevTyp, LPWINE_MCIDRIVER* lpwmd) /* silence warning if all is used... some bogus program use commands like * 'open all'... */ - if (strcmpiW(strDevTyp, wszAll) == 0) { + if (wcsicmp(strDevTyp, L"ALL") == 0) { dwRet = MCIERR_CANNOT_USE_ALL; } else { FIXME("Couldn't load driver for type %s.\n", @@ -881,6 +879,9 @@ static DWORD MCI_SendCommandFrom32(MCIDEVICEID wDevID, UINT16 wMsg, DWORD_PTR dw LPWINE_MCIDRIVER wmd = MCI_GetDriver(wDevID); if (wmd) { + if(wmd->CreatorThread != GetCurrentThreadId()) + return MCIERR_INVALID_DEVICE_NAME; + dwRet = SendDriverMessage(wmd->hDriver, wMsg, dwParam1, dwParam2); } return dwRet; @@ -888,19 +889,38 @@ static DWORD MCI_SendCommandFrom32(MCIDEVICEID wDevID, UINT16 wMsg, DWORD_PTR dw /************************************************************************** * MCI_FinishOpen [internal] + * + * Three modes of operation: + * 1 open foo.ext ... -> OPEN_ELEMENT with lpstrElementName=foo.ext + * open sequencer!foo.ext same with lpstrElementName=foo.ext + * 2 open new type waveaudio -> OPEN_ELEMENT with empty ("") lpstrElementName + * 3 open sequencer -> OPEN_ELEMENT unset, and + * capability sequencer (auto-open) likewise */ static DWORD MCI_FinishOpen(LPWINE_MCIDRIVER wmd, LPMCI_OPEN_PARMSW lpParms, DWORD dwParam) { - if (dwParam & MCI_OPEN_ELEMENT) - { - wmd->lpstrElementName = HeapAlloc(GetProcessHeap(),0,(strlenW(lpParms->lpstrElementName)+1) * sizeof(WCHAR)); - strcpyW( wmd->lpstrElementName, lpParms->lpstrElementName ); + LPCWSTR alias = NULL; + /* Open always defines an alias for further reference */ + if (dwParam & MCI_OPEN_ALIAS) { /* open ... alias */ + alias = lpParms->lpstrAlias; + if (MCI_GetDriverFromString(alias)) + return MCIERR_DUPLICATE_ALIAS; + } else { + if ((dwParam & MCI_OPEN_ELEMENT) /* open file.wav */ + && !(dwParam & MCI_OPEN_ELEMENT_ID)) + alias = lpParms->lpstrElementName; + else if (dwParam & MCI_OPEN_TYPE ) /* open cdaudio */ + alias = wmd->lpstrDeviceType; + if (alias && MCI_GetDriverFromString(alias)) + return MCIERR_DEVICE_OPEN; } - if (dwParam & MCI_OPEN_ALIAS) - { - wmd->lpstrAlias = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpParms->lpstrAlias)+1) * sizeof(WCHAR)); - strcpyW( wmd->lpstrAlias, lpParms->lpstrAlias); + if (alias) { + wmd->lpstrAlias = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(alias)+1) * sizeof(WCHAR)); + if (!wmd->lpstrAlias) return MCIERR_OUT_OF_MEMORY; + lstrcpyW( wmd->lpstrAlias, alias); + /* In most cases, natives adds MCI_OPEN_ALIAS to the flags passed to the driver. + * Don't. The drivers don't care about the winmm alias. */ } lpParms->wDeviceID = wmd->wDeviceID; @@ -923,7 +943,7 @@ static LPCWSTR MCI_FindCommand(UINT uTbl, LPCWSTR verb) * array look up */ for (idx = 0; idx < S_MciCmdTable[uTbl].nVerbs; idx++) { - if (strcmpiW(S_MciCmdTable[uTbl].aVerbs[idx], verb) == 0) + if (wcsicmp(S_MciCmdTable[uTbl].aVerbs[idx], verb) == 0) return S_MciCmdTable[uTbl].aVerbs[idx]; } @@ -935,7 +955,7 @@ static LPCWSTR MCI_FindCommand(UINT uTbl, LPCWSTR verb) */ static DWORD MCI_GetReturnType(LPCWSTR lpCmd) { - lpCmd = (LPCWSTR)((const BYTE*)(lpCmd + strlenW(lpCmd) + 1) + sizeof(DWORD) + sizeof(WORD)); + lpCmd = (LPCWSTR)((const BYTE*)(lpCmd + lstrlenW(lpCmd) + 1) + sizeof(DWORD) + sizeof(WORD)); if (*lpCmd == '\0' && *(const WORD*)((const BYTE*)(lpCmd + 1) + sizeof(DWORD)) == MCI_RETURN) { return *(const DWORD*)(lpCmd + 1); } @@ -947,28 +967,52 @@ static DWORD MCI_GetReturnType(LPCWSTR lpCmd) */ static WORD MCI_GetMessage(LPCWSTR lpCmd) { - return (WORD)*(const DWORD*)(lpCmd + strlenW(lpCmd) + 1); + return (WORD)*(const DWORD*)(lpCmd + lstrlenW(lpCmd) + 1); } /************************************************************************** * MCI_GetDWord [internal] + * + * Accept 0 -1 255 255:0 255:255:255:255 :::1 1::: 2::3 ::4: 12345678 + * Refuse -1:0 0:-1 :: 256:0 1:256 0::::1 */ -static BOOL MCI_GetDWord(DWORD_PTR *data, LPWSTR* ptr) +static BOOL MCI_GetDWord(DWORD* data, LPWSTR* ptr) { - DWORD val; - LPWSTR ret; + LPWSTR ret = *ptr; + DWORD total = 0, shift = 0; + BOOL sign = FALSE, digits = FALSE; - val = strtoulW(*ptr, &ret, 0); - - switch (*ret) { - case '\0': break; - case ' ': ret++; break; - default: return FALSE; + while (*ret == ' ' || *ret == '\t') ret++; + if (*ret == '-') { + ret++; + sign = TRUE; } + for(;;) { + DWORD val = 0; + while ('0' <= *ret && *ret <= '9') { + val = *ret++ - '0' + 10 * val; + digits = TRUE; + } + switch (*ret) { + case '\0': break; + case '\t': + case ' ': ret++; break; + default: return FALSE; + case ':': + if ((val >= 256) || (shift >= 24)) return FALSE; + total |= val << shift; + shift += 8; + ret++; + continue; + } - *data |= val; - *ptr = ret; - return TRUE; + if (!digits) return FALSE; + if (shift && (val >= 256 || sign)) return FALSE; + total |= val << shift; + *data = sign ? -total : total; + *ptr = ret; + return TRUE; + } } /************************************************************************** @@ -980,19 +1024,19 @@ static DWORD MCI_GetString(LPWSTR* str, LPWSTR* args) /* see if we have a quoted string */ if (*ptr == '"') { - ptr = strchrW(*str = ptr + 1, '"'); + ptr = wcschr(*str = ptr + 1, '"'); if (!ptr) return MCIERR_NO_CLOSING_QUOTE; /* FIXME: shall we escape \" from string ?? */ if (ptr[-1] == '\\') TRACE("Ooops: un-escaped \"\n"); *ptr++ = '\0'; /* remove trailing " */ if (*ptr != ' ' && *ptr != '\0') return MCIERR_EXTRA_CHARACTERS; } else { - ptr = strchrW(ptr, ' '); + ptr = wcschr(ptr, ' '); if (ptr) { *ptr++ = '\0'; } else { - ptr = *args + strlenW(*args); + ptr = *args + lstrlenW(*args); } *str = *args; } @@ -1006,7 +1050,7 @@ static DWORD MCI_GetString(LPWSTR* str, LPWSTR* args) /************************************************************************** * MCI_ParseOptArgs [internal] */ -static DWORD MCI_ParseOptArgs(DWORD_PTR *data, int _offset, LPCWSTR lpCmd, +static DWORD MCI_ParseOptArgs(DWORD* data, int _offset, LPCWSTR lpCmd, LPWSTR args, LPDWORD dwFlags) { int len, offset; @@ -1024,11 +1068,11 @@ static DWORD MCI_ParseOptArgs(DWORD_PTR *data, int _offset, LPCWSTR lpCmd, /* skip any leading white space(s) */ while (*args == ' ') args++; - TRACE("args=%s offset=%d\n", debugstr_w(args), offset); + TRACE("args=%s\n", debugstr_w(args)); do { /* loop on options for command table for the requested verb */ str = (LPCWSTR)lmem; - lmem += ((len = strlenW(str)) + 1) * sizeof(WCHAR); + lmem += ((len = lstrlenW(str)) + 1) * sizeof(WCHAR); flg = *(const DWORD*)lmem; eid = *(const WORD*)(lmem + sizeof(DWORD)); lmem += sizeof(DWORD) + sizeof(WORD); @@ -1044,9 +1088,14 @@ static DWORD MCI_ParseOptArgs(DWORD_PTR *data, int _offset, LPCWSTR lpCmd, } inCst = FALSE; cflg = 0; break; + case MCI_RETURN: + if (offset != _offset) { + FIXME("MCI_RETURN not in first position\n"); + return MCIERR_PARSER_INTERNAL; + } } - if (strncmpiW(args, str, len) == 0 && + if (wcsnicmp(args, str, len) == 0 && ((eid == MCI_STRING && len == 0) || args[len] == 0 || args[len] == ' ')) { /* store good values into data[] */ args += len; @@ -1063,17 +1112,23 @@ static DWORD MCI_ParseOptArgs(DWORD_PTR *data, int _offset, LPCWSTR lpCmd, break; case MCI_FLAG: *dwFlags |= flg; + TRACE("flag=%08lx\n", flg); break; + case MCI_HWND: + case MCI_HPAL: + case MCI_HDC: case MCI_INTEGER: if (inCst) { data[offset] |= flg; *dwFlags |= cflg; inCst = FALSE; + TRACE("flag=%08lx constant=%08lx\n", cflg, flg); } else { *dwFlags |= flg; if (!MCI_GetDWord(&(data[offset]), &args)) { return MCIERR_BAD_INTEGER; } + TRACE("flag=%08lx int=%ld\n", flg, data[offset]); } break; case MCI_RECT: @@ -1083,14 +1138,15 @@ static DWORD MCI_ParseOptArgs(DWORD_PTR *data, int _offset, LPCWSTR lpCmd, !MCI_GetDWord(&(data[offset+1]), &args) || !MCI_GetDWord(&(data[offset+2]), &args) || !MCI_GetDWord(&(data[offset+3]), &args)) { - ERR("Bad rect %s\n", debugstr_w(args)); return MCIERR_BAD_INTEGER; } + TRACE("flag=%08lx for rectangle\n", flg); break; case MCI_STRING: *dwFlags |= flg; if ((dwRet = MCI_GetString((LPWSTR*)&data[offset], &args))) return dwRet; + TRACE("flag=%08lx string=%s\n", flg, debugstr_w(*(LPWSTR*)&data[offset])); break; default: ERR("oops\n"); } @@ -1105,9 +1161,12 @@ static DWORD MCI_ParseOptArgs(DWORD_PTR *data, int _offset, LPCWSTR lpCmd, case MCI_END_COMMAND_LIST: case MCI_CONSTANT: case MCI_FLAG: break; + case MCI_HWND: + case MCI_HPAL: + case MCI_HDC: if (!inCst) offset += sizeof(HANDLE)/sizeof(DWORD); break; case MCI_INTEGER: if (!inCst) offset++; break; - case MCI_END_CONSTANT: - case MCI_STRING: offset++; break; + case MCI_END_CONSTANT: offset++; break; + case MCI_STRING: offset += sizeof(LPWSTR)/sizeof(DWORD); break; case MCI_RECT: offset += 4; break; default: ERR("oops\n"); } @@ -1118,7 +1177,7 @@ static DWORD MCI_ParseOptArgs(DWORD_PTR *data, int _offset, LPCWSTR lpCmd, return MCIERR_UNRECOGNIZED_COMMAND; } if (offset == MCI_DATA_SIZE) { - ERR("Internal data[] buffer overflow\n"); + FIXME("Internal data[] buffer overflow\n"); return MCIERR_PARSER_INTERNAL; } } @@ -1128,70 +1187,107 @@ static DWORD MCI_ParseOptArgs(DWORD_PTR *data, int _offset, LPCWSTR lpCmd, /************************************************************************** * MCI_HandleReturnValues [internal] */ -static DWORD MCI_HandleReturnValues(DWORD dwRet, LPWINE_MCIDRIVER wmd, DWORD retType, - DWORD_PTR *data, LPWSTR lpstrRet, UINT uRetLen) +static DWORD MCI_HandleReturnValues(DWORD dwRet, LPWINE_MCIDRIVER wmd, DWORD retType, + MCI_GENERIC_PARMS *params, LPWSTR lpstrRet, UINT uRetLen) { - static const WCHAR wszLd [] = {'%','l','d',0}; - static const WCHAR wszLd4 [] = {'%','l','d',' ','%','l','d',' ','%','l','d',' ','%','l','d',0}; - static const WCHAR wszCol3[] = {'%','d',':','%','d',':','%','d',0}; - static const WCHAR wszCol4[] = {'%','d',':','%','d',':','%','d',':','%','d',0}; - if (lpstrRet) { switch (retType) { case 0: /* nothing to return */ break; case MCI_INTEGER: + { + DWORD data = *(DWORD *)(params + 1); switch (dwRet & 0xFFFF0000ul) { case 0: case MCI_INTEGER_RETURNED: - snprintfW(lpstrRet, uRetLen, wszLd, data[1]); + swprintf(lpstrRet, uRetLen, L"%d", data); break; case MCI_RESOURCE_RETURNED: - /* return string which ID is HIWORD(data[1]), + /* return string which ID is HIWORD(data), * string is loaded from mmsystem.dll */ - LoadStringW(hWinMM32Instance, HIWORD(data[1]), lpstrRet, uRetLen); + LoadStringW(hWinMM32Instance, HIWORD(data), lpstrRet, uRetLen); break; case MCI_RESOURCE_RETURNED|MCI_RESOURCE_DRIVER: - /* return string which ID is HIWORD(data[1]), + /* return string which ID is HIWORD(data), * string is loaded from driver */ /* FIXME: this is wrong for a 16 bit handle */ LoadStringW(GetDriverModuleHandle(wmd->hDriver), - HIWORD(data[1]), lpstrRet, uRetLen); + HIWORD(data), lpstrRet, uRetLen); break; case MCI_COLONIZED3_RETURN: - snprintfW(lpstrRet, uRetLen, wszCol3, - LOBYTE(LOWORD(data[1])), HIBYTE(LOWORD(data[1])), - LOBYTE(HIWORD(data[1]))); + swprintf(lpstrRet, uRetLen, L"%02d:%02d:%02d", + LOBYTE(LOWORD(data)), HIBYTE(LOWORD(data)), + LOBYTE(HIWORD(data))); break; case MCI_COLONIZED4_RETURN: - snprintfW(lpstrRet, uRetLen, wszCol4, - LOBYTE(LOWORD(data[1])), HIBYTE(LOWORD(data[1])), - LOBYTE(HIWORD(data[1])), HIBYTE(HIWORD(data[1]))); + swprintf(lpstrRet, uRetLen, L"%02d:%02d:%02d:%02d", + LOBYTE(LOWORD(data)), HIBYTE(LOWORD(data)), + LOBYTE(HIWORD(data)), HIBYTE(HIWORD(data))); break; default: ERR("Ooops (%04X)\n", HIWORD(dwRet)); } break; + } + case 13: /* MCI_INTEGER64 */ + { + DWORD_PTR data = *(DWORD_PTR *)(params + 1); + switch (dwRet & 0xFFFF0000ul) { + case 0: + case MCI_INTEGER_RETURNED: + swprintf(lpstrRet, uRetLen, L"%Id", data); + break; + case MCI_RESOURCE_RETURNED: + /* return string which ID is HIWORD(data), + * string is loaded from mmsystem.dll */ + LoadStringW(hWinMM32Instance, HIWORD(data), lpstrRet, uRetLen); + break; + case MCI_RESOURCE_RETURNED|MCI_RESOURCE_DRIVER: + /* return string which ID is HIWORD(data), + * string is loaded from driver */ + /* FIXME: this is wrong for a 16 bit handle */ + LoadStringW(GetDriverModuleHandle(wmd->hDriver), + HIWORD(data), lpstrRet, uRetLen); + break; + case MCI_COLONIZED3_RETURN: + swprintf(lpstrRet, uRetLen, L"%02d:%02d:%02d", + LOBYTE(LOWORD(data)), HIBYTE(LOWORD(data)), + LOBYTE(HIWORD(data))); + break; + case MCI_COLONIZED4_RETURN: + swprintf(lpstrRet, uRetLen, L"%02d:%02d:%02d:%02d", + LOBYTE(LOWORD(data)), HIBYTE(LOWORD(data)), + LOBYTE(HIWORD(data)), HIBYTE(HIWORD(data))); + break; + default: ERR("Ooops (%04X)\n", HIWORD(dwRet)); + } + break; + } case MCI_STRING: switch (dwRet & 0xFFFF0000ul) { case 0: - /* nothing to do data[1] == lpstrRet */ + /* nothing to do data[0] == lpstrRet */ break; case MCI_INTEGER_RETURNED: - data[1] = *(LPDWORD)lpstrRet; - snprintfW(lpstrRet, uRetLen, wszLd, data[1]); + { + DWORD *data = (DWORD *)(params + 1); + *data = *(LPDWORD)lpstrRet; + swprintf(lpstrRet, uRetLen, L"%d", *data); break; + } default: WARN("Oooch. MCI_STRING and HIWORD(dwRet)=%04x\n", HIWORD(dwRet)); break; } break; case MCI_RECT: + { + DWORD *data = (DWORD *)(params + 1); if (dwRet & 0xFFFF0000ul) WARN("Oooch. MCI_STRING and HIWORD(dwRet)=%04x\n", HIWORD(dwRet)); - snprintfW(lpstrRet, uRetLen, wszLd4, - data[1], data[2], data[3], data[4]); + swprintf(lpstrRet, uRetLen, L"%d %d %d %d", data[0], data[1], data[2], data[3]); break; - default: ERR("oops\n"); + } + default: FIXME("Unknown MCI return type %ld\n", retType); } } return LOWORD(dwRet); @@ -1203,30 +1299,39 @@ static DWORD MCI_HandleReturnValues(DWORD dwRet, LPWINE_MCIDRIVER wmd, DWORD ret DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, UINT uRetLen, HWND hwndCallback) { - LPWSTR verb, dev, args; + LPWSTR verb, dev, args, devType = NULL; LPWINE_MCIDRIVER wmd = 0; + MCIDEVICEID uDevID, auto_open = 0; DWORD dwFlags = 0, dwRet = 0; int offset = 0; - DWORD_PTR data[MCI_DATA_SIZE]; DWORD retType; LPCWSTR lpCmd = 0; - LPWSTR devAlias = NULL; - static const WCHAR wszNew[] = {'n','e','w',0}; - static const WCHAR wszSAliasS[] = {' ','a','l','i','a','s',' ',0}; - static const WCHAR wszTypeS[] = {'t','y','p','e',' ',0}; + WORD wMsg = 0; + union + { + MCI_GENERIC_PARMS generic; + MCI_OPEN_PARMSW open; + MCI_SOUND_PARMSW sound; + MCI_SYSINFO_PARMSW sysinfo; + DWORD dw[MCI_DATA_SIZE]; + } data; TRACE("(%s, %p, %d, %p)\n", debugstr_w(lpstrCommand), lpstrRet, uRetLen, hwndCallback); + if (lpstrRet && uRetLen) *lpstrRet = '\0'; + + if (!lpstrCommand[0]) + return MCIERR_MISSING_COMMAND_STRING; /* format is */ - if (!(verb = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpstrCommand)+1) * sizeof(WCHAR)))) + if (!(verb = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(lpstrCommand)+1) * sizeof(WCHAR)))) return MCIERR_OUT_OF_MEMORY; - strcpyW( verb, lpstrCommand ); + lstrcpyW( verb, lpstrCommand ); CharLowerW(verb); - memset(data, 0, sizeof(data)); + memset(&data, 0, sizeof(data)); - if (!(args = strchrW(verb, ' '))) { + if (!(args = wcschr(verb, ' '))) { dwRet = MCIERR_MISSING_DEVICE_NAME; goto errCleanUp; } @@ -1234,18 +1339,19 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, if ((dwRet = MCI_GetString(&dev, &args))) { goto errCleanUp; } + uDevID = wcsicmp(dev, L"ALL") ? 0 : MCI_ALL_DEVICE_ID; /* Determine devType from open */ - if (!strcmpW(verb, wszOpen)) { - LPWSTR devType, tmp; + if (!wcscmp(verb, L"open")) { + LPWSTR tmp; WCHAR buf[128]; /* case dev == 'new' has to be handled */ - if (!strcmpW(dev, wszNew)) { + if (!wcscmp(dev, L"new")) { dev = 0; - if ((devType = strstrW(args, wszTypeS)) != NULL) { + if ((devType = wcsstr(args, L"type ")) != NULL) { devType += 5; - tmp = strchrW(devType, ' '); + tmp = wcschr(devType, ' '); if (tmp) *tmp = '\0'; devType = str_dup_upper(devType); if (tmp) *tmp = ' '; @@ -1255,31 +1361,33 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, dwRet = MCIERR_MISSING_DEVICE_NAME; goto errCleanUp; } - } else if ((devType = strchrW(dev, '!')) != NULL) { + dwFlags |= MCI_OPEN_ELEMENT; + data.open.lpstrElementName = &L""[0]; + } else if ((devType = wcschr(dev, '!')) != NULL) { *devType++ = '\0'; tmp = devType; devType = dev; dev = tmp; dwFlags |= MCI_OPEN_TYPE; - data[2] = (DWORD_PTR)devType; + data.open.lpstrDeviceType = devType; devType = str_dup_upper(devType); dwFlags |= MCI_OPEN_ELEMENT; - data[3] = (DWORD_PTR)dev; - } else if (DRIVER_GetLibName(dev, wszMci, buf, sizeof(buf))) { + data.open.lpstrElementName = dev; + } else if (DRIVER_GetLibName(dev, L"MCI", buf, sizeof(buf))) { /* this is the name of a mci driver's type */ - tmp = strchrW(dev, ' '); + tmp = wcschr(dev, ' '); if (tmp) *tmp = '\0'; - data[2] = (DWORD_PTR)dev; + data.open.lpstrDeviceType = dev; devType = str_dup_upper(dev); if (tmp) *tmp = ' '; dwFlags |= MCI_OPEN_TYPE; } else { - if ((devType = strstrW(args, wszTypeS)) != NULL) { + if ((devType = wcsstr(args, L"type ")) != NULL) { devType += 5; - tmp = strchrW(devType, ' '); + tmp = wcschr(devType, ' '); if (tmp) *tmp = '\0'; devType = str_dup_upper(devType); if (tmp) *tmp = ' '; - /* dwFlags and data[2] will be correctly set in ParseOpt loop */ + /* dwFlags and lpstrDeviceType will be correctly set in ParseOpt loop */ } else { if ((dwRet = MCI_GetDevTypeFromFileName(dev, buf, sizeof(buf)))) goto errCleanUp; @@ -1287,21 +1395,13 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, devType = str_dup_upper(buf); } dwFlags |= MCI_OPEN_ELEMENT; - data[3] = (DWORD_PTR)dev; + data.open.lpstrElementName = dev; } - if ((devAlias = strstrW(args, wszSAliasS))) { - WCHAR* tmp2; - devAlias += 7; - if (!(tmp = strchrW(devAlias,' '))) tmp = devAlias + strlenW(devAlias); - if (tmp) *tmp = '\0'; - tmp2 = HeapAlloc(GetProcessHeap(), 0, (tmp - devAlias + 1) * sizeof(WCHAR) ); - memcpy( tmp2, devAlias, (tmp - devAlias) * sizeof(WCHAR) ); - tmp2[tmp - devAlias] = 0; - data[4] = (DWORD_PTR)tmp2; - /* should be done in regular options parsing */ - /* dwFlags |= MCI_OPEN_ALIAS; */ - } else if (dev == 0) { - /* "open new" requires alias */ + if (MCI_ALL_DEVICE_ID == uDevID) { + dwRet = MCIERR_CANNOT_USE_ALL; + goto errCleanUp; + } + if (!wcsstr(args, L" alias ") && !dev) { dwRet = MCIERR_NEW_REQUIRES_ALIAS; goto errCleanUp; } @@ -1309,25 +1409,38 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, dwRet = MCI_LoadMciDriver(devType, &wmd); if (dwRet == MCIERR_DEVICE_NOT_INSTALLED) dwRet = MCIERR_INVALID_DEVICE_NAME; - HeapFree(GetProcessHeap(), 0, devType); - if (dwRet) { - MCI_UnLoadMciDriver(wmd); + if (dwRet) goto errCleanUp; - } - } else if (!(wmd = MCI_GetDriver(mciGetDeviceIDW(dev)))) { - /* auto open */ - static const WCHAR wszOpenWait[] = {'o','p','e','n',' ','%','s',' ','w','a','i','t',0}; - WCHAR buf[128]; - sprintfW(buf, wszOpenWait, dev); + } else if ((MCI_ALL_DEVICE_ID != uDevID) && !(wmd = MCI_GetDriver(mciGetDeviceIDW(dev))) + && (lpCmd = MCI_FindCommand(MCI_GetCommandTable(0), verb))) { + /* auto-open uses the core command table */ + switch (MCI_GetMessage(lpCmd)) { + case MCI_SOUND: /* command does not use a device name */ + case MCI_SYSINFO: + break; + case MCI_CLOSE: /* don't auto-open for close */ + case MCI_BREAK: /* no auto-open for system commands */ + dwRet = MCIERR_INVALID_DEVICE_NAME; + goto errCleanUp; + break; + default: + { + WCHAR buf[138], retbuf[6]; + swprintf(buf, ARRAY_SIZE(buf), L"open %s wait", dev); + /* open via mciSendString handles quoting, dev!file syntax and alias creation */ + if ((dwRet = mciSendStringW(buf, retbuf, ARRAY_SIZE(retbuf), 0)) != 0) + goto errCleanUp; + auto_open = wcstoul(retbuf, NULL, 10); + TRACE("auto-opened %u for %s\n", auto_open, debugstr_w(dev)); - if ((dwRet = mciSendStringW(buf, NULL, 0, 0)) != 0) - goto errCleanUp; - - wmd = MCI_GetDriver(mciGetDeviceIDW(dev)); - if (!wmd) { - /* FIXME: memory leak, MCI driver is not closed */ - dwRet = MCIERR_INVALID_DEVICE_ID; - goto errCleanUp; + /* FIXME: test for notify flag (how to preparse?) before opening */ + wmd = MCI_GetDriver(auto_open); + if (!wmd) { + ERR("No auto-open device %u\n", auto_open); + dwRet = MCIERR_INVALID_DEVICE_ID; + goto errCleanUp; + } + } } } @@ -1351,50 +1464,118 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, dwRet = MCIERR_UNRECOGNIZED_COMMAND; goto errCleanUp; } + wMsg = MCI_GetMessage(lpCmd); /* set return information */ + offset = sizeof(data.generic); switch (retType = MCI_GetReturnType(lpCmd)) { - case 0: offset = 1; break; - case MCI_INTEGER: offset = 2; break; - case MCI_STRING: data[1] = (DWORD_PTR)lpstrRet; data[2] = uRetLen; offset = 3; break; - case MCI_RECT: offset = 5; break; - default: ERR("oops\n"); + case 0: + break; + case MCI_INTEGER: + offset += sizeof(DWORD); + break; + case MCI_STRING: + data.sysinfo.lpstrReturn = lpstrRet; + data.sysinfo.dwRetSize = uRetLen; + offset = FIELD_OFFSET( MCI_SYSINFO_PARMSW, dwNumber ); + break; + case MCI_RECT: + offset += 4 * sizeof(DWORD); + break; + case 13: /* MCI_INTEGER64 */ + offset += sizeof(DWORD_PTR); + break; + default: + FIXME("Unknown MCI return type %ld\n", retType); + dwRet = MCIERR_PARSER_INTERNAL; + goto errCleanUp; } TRACE("verb=%s on dev=%s; offset=%d\n", debugstr_w(verb), debugstr_w(dev), offset); - if ((dwRet = MCI_ParseOptArgs(data, offset, lpCmd, args, &dwFlags))) + if ((dwRet = MCI_ParseOptArgs(data.dw, offset / sizeof(DWORD), lpCmd, args, &dwFlags))) goto errCleanUp; /* set up call back */ + if (auto_open) { + if (dwFlags & MCI_NOTIFY) { + dwRet = MCIERR_NOTIFY_ON_AUTO_OPEN; + goto errCleanUp; + } + /* FIXME: the command should get its own notification window set up and + * ask for device closing while processing the notification mechanism. + * hwndCallback = ... + * dwFlags |= MCI_NOTIFY; + * In the meantime special-case all commands but PLAY and RECORD below. */ + } if (dwFlags & MCI_NOTIFY) { - data[0] = (DWORD_PTR)hwndCallback; + data.generic.dwCallback = (DWORD_PTR)hwndCallback; } - /* FIXME: the command should get it's own notification window set up and - * ask for device closing while processing the notification mechanism - */ - if (lpstrRet && uRetLen) *lpstrRet = '\0'; + switch (wMsg) { + case MCI_OPEN: + if (wcscmp(verb, L"open")) { + FIXME("Cannot open with command %s\n", debugstr_w(verb)); + dwRet = MCIERR_DRIVER_INTERNAL; + wMsg = 0; + goto errCleanUp; + } + break; + case MCI_SYSINFO: + /* Requirements on dev depend on the flags: + * alias with INSTALLNAME, name like "digitalvideo" + * with QUANTITY and NAME. */ + { + data.sysinfo.wDeviceType = MCI_ALL_DEVICE_ID; + if (uDevID != MCI_ALL_DEVICE_ID) { + if (dwFlags & MCI_SYSINFO_INSTALLNAME) + wmd = MCI_GetDriver(mciGetDeviceIDW(dev)); + else if (!(data.sysinfo.wDeviceType = MCI_GetDevTypeFromResource(dev))) { + dwRet = MCIERR_DEVICE_TYPE_REQUIRED; + goto errCleanUp; + } + } + } + break; + case MCI_SOUND: + /* FIXME: name is optional, "sound" is a valid command. + * FIXME: Parse "sound notify" as flag, not as name. */ + data.sound.lpstrSoundName = dev; + dwFlags |= MCI_SOUND_NAME; + break; + } - TRACE("[%d, %s, %08x, %08x/%s %08x/%s %08x/%s %08x/%s %08x/%s %08x/%s]\n", - wmd->wDeviceID, MCI_MessageToString(MCI_GetMessage(lpCmd)), dwFlags, - data[0], debugstr_w((WCHAR *)data[0]), data[1], debugstr_w((WCHAR *)data[1]), - data[2], debugstr_w((WCHAR *)data[2]), data[3], debugstr_w((WCHAR *)data[3]), - data[4], debugstr_w((WCHAR *)data[4]), data[5], debugstr_w((WCHAR *)data[5])); + TRACE("[%d, %s, %08lx, %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx]\n", + wmd ? wmd->wDeviceID : uDevID, MCI_MessageToString(wMsg), dwFlags, + data.dw[0], data.dw[1], data.dw[2], data.dw[3], data.dw[4], + data.dw[5], data.dw[6], data.dw[7], data.dw[8], data.dw[9]); - if (strcmpW(verb, wszOpen) == 0) { - if ((dwRet = MCI_FinishOpen(wmd, (LPMCI_OPEN_PARMSW)data, dwFlags))) - MCI_UnLoadMciDriver(wmd); + if (wMsg == MCI_OPEN) { + if ((dwRet = MCI_FinishOpen(wmd, &data.open, dwFlags))) + goto errCleanUp; /* FIXME: notification is not properly shared across two opens */ } else { - dwRet = MCI_SendCommand(wmd->wDeviceID, MCI_GetMessage(lpCmd), dwFlags, (DWORD_PTR)data); + dwRet = MCI_SendCommand(wmd ? wmd->wDeviceID : uDevID, wMsg, dwFlags, (DWORD_PTR)&data); } - TRACE("=> 1/ %x (%s)\n", dwRet, debugstr_w(lpstrRet)); - dwRet = MCI_HandleReturnValues(dwRet, wmd, retType, data, lpstrRet, uRetLen); - TRACE("=> 2/ %x (%s)\n", dwRet, debugstr_w(lpstrRet)); + if (!LOWORD(dwRet)) { + TRACE("=> 1/ %lx (%s)\n", dwRet, debugstr_w(lpstrRet)); + dwRet = MCI_HandleReturnValues(dwRet, wmd, retType, &data.generic, lpstrRet, uRetLen); + TRACE("=> 2/ %lx (%s)\n", dwRet, debugstr_w(lpstrRet)); + } else + TRACE("=> %lx\n", dwRet); errCleanUp: + if (auto_open) { + /* PLAY and RECORD are the only known non-immediate commands */ + if (LOWORD(dwRet) || !(wMsg == MCI_PLAY || wMsg == MCI_RECORD)) + MCI_SendCommand(auto_open, MCI_CLOSE, 0, 0); + else + FIXME("leaking auto-open device %u\n", auto_open); + } + if (wMsg == MCI_OPEN && LOWORD(dwRet) && wmd) + MCI_UnLoadMciDriver(wmd); + HeapFree(GetProcessHeap(), 0, devType); HeapFree(GetProcessHeap(), 0, verb); return dwRet; } @@ -1416,9 +1597,9 @@ DWORD WINAPI mciSendStringA(LPCSTR lpstrCommand, LPSTR lpstrRet, MultiByteToWideChar( CP_ACP, 0, lpstrCommand, -1, lpwstrCommand, len ); if (lpstrRet) { + if (uRetLen) *lpstrRet = '\0'; /* NT-w2k3 use memset(lpstrRet, 0, uRetLen); */ lpwstrRet = HeapAlloc(GetProcessHeap(), 0, uRetLen * sizeof(WCHAR)); if (!lpwstrRet) { - WARN("no memory\n"); HeapFree( GetProcessHeap(), 0, lpwstrCommand ); return MCIERR_OUT_OF_MEMORY; } @@ -1444,7 +1625,7 @@ BOOL WINAPI mciExecute(LPCSTR lpstrCommand) ret = mciSendStringA(lpstrCommand, strRet, sizeof(strRet), 0); if (ret != 0) { if (!mciGetErrorStringA(ret, strRet, sizeof(strRet))) { - sprintf(strRet, "Unknown MCI error (%lu)", ret); + sprintf(strRet, "Unknown MCI error (%ld)", ret); } MessageBoxA(0, strRet, "Error in mciExecute()", MB_OK); } @@ -1522,16 +1703,15 @@ static DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSW lpParms) DWORD dwRet; LPWINE_MCIDRIVER wmd = NULL; - TRACE("(%08X, %p)\n", dwParam, lpParms); + TRACE("(%08lX, %p)\n", dwParam, lpParms); if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; /* only two low bytes are generic, the other ones are dev type specific */ #define WINE_MCIDRIVER_SUPP (0xFFFF0000|MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT| \ MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID| \ MCI_NOTIFY|MCI_WAIT) - if ((dwParam & ~WINE_MCIDRIVER_SUPP) != 0) { - FIXME("Unsupported yet dwFlags=%08lX\n", dwParam & ~WINE_MCIDRIVER_SUPP); - } + if ((dwParam & ~WINE_MCIDRIVER_SUPP) != 0) + FIXME("Unsupported yet dwFlags=%08lX\n", dwParam); #undef WINE_MCIDRIVER_SUPP strDevTyp[0] = 0; @@ -1540,10 +1720,8 @@ static DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSW lpParms) if (dwParam & MCI_OPEN_TYPE_ID) { WORD uDevType = LOWORD(lpParms->lpstrDeviceType); - if (uDevType < MCI_DEVTYPE_FIRST || - uDevType > MCI_DEVTYPE_LAST || - !LoadStringW(hWinMM32Instance, uDevType, - strDevTyp, sizeof(strDevTyp) / sizeof(WCHAR))) { + if (uDevType < MCI_DEVTYPE_FIRST || uDevType > MCI_DEVTYPE_LAST || + !LoadStringW(hWinMM32Instance, uDevType, strDevTyp, ARRAY_SIZE(strDevTyp))) { dwRet = MCIERR_BAD_INTEGER; goto errCleanUp; } @@ -1553,8 +1731,8 @@ static DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSW lpParms) dwRet = MCIERR_NULL_PARAMETER_BLOCK; goto errCleanUp; } - strcpyW(strDevTyp, lpParms->lpstrDeviceType); - ptr = strchrW(strDevTyp, '!'); + lstrcpyW(strDevTyp, lpParms->lpstrDeviceType); + ptr = wcschr(strDevTyp, '!'); if (ptr) { /* this behavior is not documented in windows. However, since, in * some occasions, MCI_OPEN handling is translated by WinMM into @@ -1595,13 +1773,12 @@ static DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSW lpParms) if (!strDevTyp[0] && MCI_GetDevTypeFromFileName(lpParms->lpstrElementName, strDevTyp, sizeof(strDevTyp))) { - static const WCHAR wszCdAudio[] = {'C','D','A','U','D','I','O',0}; if (GetDriveTypeW(lpParms->lpstrElementName) != DRIVE_CDROM) { dwRet = MCIERR_EXTENSION_NOT_FOUND; goto errCleanUp; } /* FIXME: this will not work if several CDROM drives are installed on the machine */ - strcpyW(strDevTyp, wszCdAudio); + lstrcpyW(strDevTyp, L"CDAUDIO"); } } @@ -1624,23 +1801,17 @@ static DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSW lpParms) } if ((dwRet = MCI_FinishOpen(wmd, lpParms, dwParam))) { - TRACE("Failed to open driver (MCI_OPEN_DRIVER) [%08x], closing\n", dwRet); + TRACE("Failed to open driver (MCI_OPEN_DRIVER) [%08lx], closing\n", dwRet); /* FIXME: is dwRet the correct ret code ? */ goto errCleanUp; } /* only handled devices fall through */ - TRACE("wDevID=%04X wDeviceID=%d dwRet=%d\n", wmd->wDeviceID, lpParms->wDeviceID, dwRet); - - if (dwParam & MCI_NOTIFY) - mciDriverNotify((HWND)lpParms->dwCallback, wmd->wDeviceID, MCI_NOTIFY_SUCCESSFUL); - + TRACE("wDevID=%04X wDeviceID=%d dwRet=%ld\n", wmd->wDeviceID, lpParms->wDeviceID, dwRet); return 0; + errCleanUp: if (wmd) MCI_UnLoadMciDriver(wmd); - - if (dwParam & MCI_NOTIFY) - mciDriverNotify((HWND)lpParms->dwCallback, 0, MCI_NOTIFY_FAILURE); return dwRet; } @@ -1652,14 +1823,10 @@ static DWORD MCI_Close(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms) DWORD dwRet; LPWINE_MCIDRIVER wmd; - TRACE("(%04x, %08X, %p)\n", wDevID, dwParam, lpParms); + TRACE("(%04x, %08lX, %p)\n", wDevID, dwParam, lpParms); /* Every device must handle MCI_NOTIFY on its own. */ if ((UINT16)wDevID == (UINT16)MCI_ALL_DEVICE_ID) { - /* FIXME: shall I notify once after all is done, or for - * each of the open drivers ? if the latest, which notif - * to return when only one fails ? - */ while (MciDrivers) { /* Retrieve the device ID under lock, but send the message without, * the driver might be calling some winmm functions from another @@ -1682,15 +1849,13 @@ static DWORD MCI_Close(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms) return MCIERR_INVALID_DEVICE_ID; } + if(wmd->CreatorThread != GetCurrentThreadId()) + return MCIERR_INVALID_DEVICE_NAME; + dwRet = MCI_SendCommandFrom32(wDevID, MCI_CLOSE_DRIVER, dwParam, (DWORD_PTR)lpParms); MCI_UnLoadMciDriver(wmd); - if (dwParam & MCI_NOTIFY) - mciDriverNotify(lpParms ? (HWND)lpParms->dwCallback : 0, - wDevID, - dwRet ? MCI_NOTIFY_FAILURE : MCI_NOTIFY_SUCCESSFUL); - return dwRet; } @@ -1702,12 +1867,10 @@ static DWORD MCI_WriteString(LPWSTR lpDstStr, DWORD dstSize, LPCWSTR lpSrcStr) DWORD ret = 0; if (lpSrcStr) { - dstSize /= sizeof(WCHAR); - if (dstSize <= strlenW(lpSrcStr)) { - lstrcpynW(lpDstStr, lpSrcStr, dstSize - 1); + if (dstSize <= lstrlenW(lpSrcStr)) { ret = MCIERR_PARAM_OVERFLOW; } else { - strcpyW(lpDstStr, lpSrcStr); + lstrcpyW(lpDstStr, lpSrcStr); } } else { *lpDstStr = 0; @@ -1728,7 +1891,7 @@ static DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSW lpParm if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; if (lpParms->lpstrReturn == NULL) return MCIERR_PARAM_OVERFLOW; - TRACE("(%08x, %08X, %p[num=%d, wDevTyp=%u])\n", + TRACE("(%08x, %08lX, %p[num=%ld, wDevTyp=%u])\n", uDevID, dwFlags, lpParms, lpParms->dwNumber, lpParms->wDeviceType); if ((WORD)MCI_ALL_DEVICE_ID == LOWORD(uDevID)) uDevID = MCI_ALL_DEVICE_ID; /* Be compatible with Win9x */ @@ -1754,8 +1917,8 @@ static DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSW lpParm RegQueryInfoKeyW( hKey, 0, 0, 0, &cnt, 0, 0, 0, 0, 0, 0, 0); RegCloseKey( hKey ); } - if (GetPrivateProfileStringW(wszMci, 0, wszNull, buf, sizeof(buf) / sizeof(buf[0]), wszSystemIni)) - for (s = buf; *s; s += strlenW(s) + 1) cnt++; + if (GetPrivateProfileStringW(L"MCI", 0, L"", buf, ARRAY_SIZE(buf), L"system.ini")) + for (s = buf; *s; s += lstrlenW(s) + 1) cnt++; } } else { if (dwFlags & MCI_SYSINFO_OPEN) { @@ -1782,7 +1945,7 @@ static DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSW lpParm } } *(DWORD*)lpParms->lpstrReturn = cnt; - TRACE("(%d) => '%d'\n", lpParms->dwNumber, *(DWORD*)lpParms->lpstrReturn); + TRACE("(%ld) => '%ld'\n", lpParms->dwNumber, *(DWORD*)lpParms->lpstrReturn); ret = MCI_INTEGER_RETURNED; /* return ret; Only Win9x sends a notification in this case. */ break; @@ -1795,7 +1958,7 @@ static DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSW lpParm ret = (uDevID == MCI_ALL_DEVICE_ID) ? MCIERR_CANNOT_USE_ALL : MCIERR_INVALID_DEVICE_NAME; } - TRACE("(%d) => %s\n", lpParms->dwNumber, debugstr_w(lpParms->lpstrReturn)); + TRACE("(%ld) => %s\n", lpParms->dwNumber, debugstr_w(lpParms->lpstrReturn)); break; case MCI_SYSINFO_NAME: s = NULL; @@ -1818,13 +1981,13 @@ static DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSW lpParm LeaveCriticalSection(&WINMM_cs); ret = s ? MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize, s) : MCIERR_OUTOFRANGE; } else if (MCI_ALL_DEVICE_ID == uDevID) { - TRACE("MCI_SYSINFO_NAME: device #%d\n", lpParms->dwNumber); + TRACE("MCI_SYSINFO_NAME: device #%ld\n", lpParms->dwNumber); if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, wszHklmMci, 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS) { if (RegQueryInfoKeyW( hKey, 0, 0, 0, &cnt, 0, 0, 0, 0, 0, 0, 0) == ERROR_SUCCESS && lpParms->dwNumber <= cnt) { - DWORD bufLen = sizeof(buf)/sizeof(buf[0]); + DWORD bufLen = ARRAY_SIZE(buf); if (RegEnumKeyExW(hKey, lpParms->dwNumber - 1, buf, &bufLen, 0, 0, 0, 0) == ERROR_SUCCESS) s = buf; @@ -1832,9 +1995,9 @@ static DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSW lpParm RegCloseKey( hKey ); } if (!s) { - if (GetPrivateProfileStringW(wszMci, 0, wszNull, buf, sizeof(buf) / sizeof(buf[0]), wszSystemIni)) { - for (p = buf; *p; p += strlenW(p) + 1, cnt++) { - TRACE("%d: %s\n", cnt, debugstr_w(p)); + if (GetPrivateProfileStringW(L"MCI", 0, L"", buf, ARRAY_SIZE(buf), L"system.ini")) { + for (p = buf; *p; p += lstrlenW(p) + 1, cnt++) { + TRACE("%ld: %s\n", cnt, debugstr_w(p)); if (cnt == lpParms->dwNumber - 1) { s = p; break; @@ -1855,10 +2018,10 @@ static DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSW lpParm ret = 0; } } - TRACE("(%d) => %s\n", lpParms->dwNumber, debugstr_w(lpParms->lpstrReturn)); + TRACE("(%ld) => %s\n", lpParms->dwNumber, debugstr_w(lpParms->lpstrReturn)); break; default: - TRACE("Unsupported flag value=%08x\n", dwFlags); + TRACE("Unsupported flag value=%08lx\n", dwFlags); ret = MCIERR_UNRECOGNIZED_KEYWORD; } if ((dwFlags & MCI_NOTIFY) && HRESULT_CODE(ret)==0) @@ -1871,14 +2034,17 @@ static DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSW lpParm */ static DWORD MCI_Break(UINT wDevID, DWORD dwFlags, LPMCI_BREAK_PARMS lpParms) { - DWORD dwRet = 0; + DWORD dwRet; - if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; + if (lpParms == NULL) + return MCIERR_NULL_PARAMETER_BLOCK; - if (dwFlags & MCI_NOTIFY) - mciDriverNotify((HWND)lpParms->dwCallback, wDevID, - (dwRet == 0) ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE); + TRACE("(%08x, %08lX, vkey %04X, hwnd %p)\n", wDevID, dwFlags, + lpParms->nVirtKey, lpParms->hwndBreak); + dwRet = MCI_SendCommandFrom32(wDevID, MCI_BREAK, dwFlags, (DWORD_PTR)lpParms); + if (!dwRet && (dwFlags & MCI_NOTIFY)) + mciDriverNotify((HWND)lpParms->dwCallback, wDevID, MCI_NOTIFY_SUCCESSFUL); return dwRet; } @@ -1887,18 +2053,19 @@ static DWORD MCI_Break(UINT wDevID, DWORD dwFlags, LPMCI_BREAK_PARMS lpParms) */ static DWORD MCI_Sound(UINT wDevID, DWORD dwFlags, LPMCI_SOUND_PARMSW lpParms) { - DWORD dwRet = 0; + DWORD dwRet; - if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; - - if (dwFlags & MCI_SOUND_NAME) - dwRet = sndPlaySoundW(lpParms->lpstrSoundName, SND_SYNC) ? MMSYSERR_NOERROR : MMSYSERR_ERROR; - else - dwRet = MMSYSERR_ERROR; /* what should be done ??? */ - if (dwFlags & MCI_NOTIFY) - mciDriverNotify((HWND)lpParms->dwCallback, wDevID, - (dwRet == 0) ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE); + if (dwFlags & MCI_SOUND_NAME) { + if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; + else dwRet = PlaySoundW(lpParms->lpstrSoundName, NULL, + SND_ALIAS | (dwFlags & MCI_WAIT ? SND_SYNC : SND_ASYNC)) + ? 0 : MCIERR_HARDWARE; + } else dwRet = PlaySoundW((LPCWSTR)SND_ALIAS_SYSTEMDEFAULT, NULL, + SND_ALIAS_ID | (dwFlags & MCI_WAIT ? SND_SYNC : SND_ASYNC)) + ? 0 : MCIERR_HARDWARE; + if (!dwRet && lpParms && (dwFlags & MCI_NOTIFY)) + mciDriverNotify((HWND)lpParms->dwCallback, wDevID, MCI_NOTIFY_SUCCESSFUL); return dwRet; } @@ -1964,7 +2131,7 @@ static LRESULT MCI_CleanUp(LRESULT dwRet, UINT wMsg, DWORD_PTR dwParam2) LPMCI_GETDEVCAPS_PARMS lmgp; lmgp = (LPMCI_GETDEVCAPS_PARMS)dwParam2; - TRACE("Changing %08x to %08x\n", lmgp->dwReturn, LOWORD(lmgp->dwReturn)); + TRACE("Changing %08lx to %08x\n", lmgp->dwReturn, LOWORD(lmgp->dwReturn)); lmgp->dwReturn = LOWORD(lmgp->dwReturn); } break; @@ -1987,7 +2154,7 @@ static LRESULT MCI_CleanUp(LRESULT dwRet, UINT wMsg, DWORD_PTR dwParam2) LPMCI_STATUS_PARMS lsp; lsp = (LPMCI_STATUS_PARMS)dwParam2; - TRACE("Changing %08lx to %08x\n", lsp->dwReturn, LOWORD(lsp->dwReturn)); + TRACE("Changing %08Ix to %08x\n", lsp->dwReturn, LOWORD(lsp->dwReturn)); lsp->dwReturn = LOWORD(lsp->dwReturn); } break; @@ -2008,7 +2175,7 @@ static LRESULT MCI_CleanUp(LRESULT dwRet, UINT wMsg, DWORD_PTR dwParam2) break; default: if (HIWORD(dwRet)) { - FIXME("Got non null hiword for dwRet=0x%08lx for command %s\n", + FIXME("Got non null hiword for dwRet=0x%08Ix for command %s\n", dwRet, MCI_MessageToString(wMsg)); } break; @@ -2086,7 +2253,7 @@ BOOL WINAPI mciSetDriverData(MCIDEVICEID uDeviceID, DWORD_PTR data) { LPWINE_MCIDRIVER wmd; - TRACE("(%04x, %08lx)\n", uDeviceID, data); + TRACE("(%04x, %08Ix)\n", uDeviceID, data); wmd = MCI_GetDriver(uDeviceID); @@ -2107,12 +2274,12 @@ DWORD WINAPI mciSendCommandW(MCIDEVICEID wDevID, UINT wMsg, DWORD_PTR dwParam1, { DWORD dwRet; - TRACE("(%08x, %s, %08lx, %08lx)\n", + TRACE("(%08x, %s, %08Ix, %08Ix)\n", wDevID, MCI_MessageToString(wMsg), dwParam1, dwParam2); dwRet = MCI_SendCommand(wDevID, wMsg, dwParam1, dwParam2); dwRet = MCI_CleanUp(dwRet, wMsg, dwParam2); - TRACE("=> %08x\n", dwRet); + TRACE("=> %08lx\n", dwRet); return dwRet; } @@ -2124,14 +2291,14 @@ DWORD WINAPI mciSendCommandA(MCIDEVICEID wDevID, UINT wMsg, DWORD_PTR dwParam1, DWORD ret; int mapped; - TRACE("(%08x, %s, %08lx, %08lx)\n", + TRACE("(%08x, %s, %08Ix, %08Ix)\n", wDevID, MCI_MessageToString(wMsg), dwParam1, dwParam2); mapped = MCI_MapMsgAtoW(wMsg, dwParam1, &dwParam2); if (mapped == -1) { FIXME("message %04x mapping failed\n", wMsg); - return MMSYSERR_NOMEM; + return MCIERR_OUT_OF_MEMORY; } ret = mciSendCommandW(wDevID, wMsg, dwParam1, dwParam2); if (mapped) @@ -2163,37 +2330,21 @@ UINT WINAPI mciGetDeviceIDW(LPCWSTR lpwstrName) return MCI_GetDriverFromString(lpwstrName); } -/****************************************************************** - * MyUserYield - * - * Internal wrapper to call USER.UserYield16 (in fact through a Wine only export from USER32). - */ -static void MyUserYield(void) -{ - HMODULE mod = GetModuleHandleA( "user32.dll" ); - if (mod) - { - FARPROC proc = GetProcAddress( mod, "UserYield16" ); - if (proc) proc(); - } -} - /************************************************************************** * MCI_DefYieldProc [internal] */ static UINT WINAPI MCI_DefYieldProc(MCIDEVICEID wDevID, DWORD data) { INT16 ret; + MSG msg; - TRACE("(0x%04x, 0x%08x)\n", wDevID, data); + TRACE("(0x%04x, 0x%08lx)\n", wDevID, data); if ((HIWORD(data) != 0 && HWND_16(GetActiveWindow()) != HIWORD(data)) || (GetAsyncKeyState(LOWORD(data)) & 1) == 0) { - MyUserYield(); + PeekMessageW(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE); ret = 0; } else { - MSG msg; - msg.hwnd = HWND_32(HIWORD(data)); while (!PeekMessageW(&msg, msg.hwnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)); ret = -1; @@ -2208,7 +2359,7 @@ BOOL WINAPI mciSetYieldProc(MCIDEVICEID uDeviceID, YIELDPROC fpYieldProc, DWORD { LPWINE_MCIDRIVER wmd; - TRACE("(%u, %p, %08x)\n", uDeviceID, fpYieldProc, dwYieldData); + TRACE("(%u, %p, %08lx)\n", uDeviceID, fpYieldProc, dwYieldData); if (!(wmd = MCI_GetDriver(uDeviceID))) { WARN("Bad uDeviceID\n"); @@ -2245,7 +2396,7 @@ UINT WINAPI mciGetDeviceIDFromElementIDW(DWORD dwElementID, LPCWSTR lpstrType) /* FIXME: that's rather strange, there is no * mciGetDeviceIDFromElementID32A in winmm.spec */ - FIXME("(%u, %s) stub\n", dwElementID, debugstr_w(lpstrType)); + FIXME("(%lu, %s) stub\n", dwElementID, debugstr_w(lpstrType)); return 0; } @@ -2278,7 +2429,7 @@ HTASK WINAPI mciGetCreatorTask(MCIDEVICEID uDeviceID) LPWINE_MCIDRIVER wmd; HTASK ret = 0; - if ((wmd = MCI_GetDriver(uDeviceID))) ret = (HTASK)wmd->CreatorThread; + if ((wmd = MCI_GetDriver(uDeviceID))) ret = (HTASK)(DWORD_PTR)wmd->CreatorThread; TRACE("(%u) => %p\n", uDeviceID, ret); return ret; @@ -2295,7 +2446,8 @@ UINT WINAPI mciDriverYield(MCIDEVICEID uDeviceID) TRACE("(%04x)\n", uDeviceID); if (!(wmd = MCI_GetDriver(uDeviceID)) || !wmd->lpfnYieldProc) { - MyUserYield(); + MSG msg; + PeekMessageW(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE); } else { ret = wmd->lpfnYieldProc(uDeviceID, wmd->dwYieldData); } diff --git a/dll/win32/winmm/winemm.h b/dll/win32/winmm/winemm.h index b6efa8e1160..640c8036a3c 100644 --- a/dll/win32/winmm/winemm.h +++ b/dll/win32/winmm/winemm.h @@ -170,9 +170,7 @@ LPWINE_MLD MMDRV_GetRelated(HANDLE hndl, UINT srcType, BOOL bSrcCanBeID, UINT ds DWORD MMDRV_Message(LPWINE_MLD mld, UINT wMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2); UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2); -const char* MCI_MessageToString(UINT wMsg); DWORD MCI_SendCommand(UINT wDevID, UINT16 wMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2); -LPWSTR MCI_strdupAtoW(LPCSTR str); LPSTR MCI_strdupWtoA(LPCWSTR str); const char* WINMM_ErrorToString(MMRESULT error); @@ -205,4 +203,9 @@ extern HANDLE psStopEvent; INT LoadRegistryMMEDrivers(char* key); +// REACTOS: +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#define wcsnicmp strncmpiW +#define swprintf snprintfW + #endif /* _WINEMM_H_ */