📄 mci.c
字号:
}
} else {
dwRet = SendDriverMessage(wmd->hDriver, wMsg, dwParam1, dwParam2);
}
}
return dwRet;
}
/**************************************************************************
* MCI_Open [internal]
*/
static DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSW lpParms)
{
WCHAR strDevTyp[128];
DWORD dwRet;
LPWINE_MCIDRIVER wmd = NULL;
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);
}
#undef WINE_MCIDRIVER_SUPP
strDevTyp[0] = 0;
if (dwParam & MCI_OPEN_TYPE) {
if (dwParam & MCI_OPEN_TYPE_ID) {
WORD uDevType = LOWORD((DWORD)lpParms->lpstrDeviceType);
if (uDevType < MCI_DEVTYPE_FIRST ||
uDevType > MCI_DEVTYPE_LAST ||
!LoadStringW(WINMM_IData.hWinMM32Instance, uDevType,
strDevTyp, sizeof(strDevTyp) / sizeof(WCHAR))) {
dwRet = MCIERR_BAD_INTEGER;
goto errCleanUp;
}
} else {
LPWSTR ptr;
if (lpParms->lpstrDeviceType == NULL) {
dwRet = MCIERR_NULL_PARAMETER_BLOCK;
goto errCleanUp;
}
strcpyW(strDevTyp, lpParms->lpstrDeviceType);
ptr = strchrW(strDevTyp, '!');
if (ptr) {
/* this behavior is not documented in windows. However, since, in
* some occasions, MCI_OPEN handling is translated by WinMM into
* a call to mciSendString("open <type>"); this code shall be correct
*/
if (dwParam & MCI_OPEN_ELEMENT) {
ERR("Both MCI_OPEN_ELEMENT(%s) and %s are used\n",
debugstr_w(lpParms->lpstrElementName),
debugstr_w(strDevTyp));
dwRet = MCIERR_UNRECOGNIZED_KEYWORD;
goto errCleanUp;
}
dwParam |= MCI_OPEN_ELEMENT;
*ptr++ = 0;
/* FIXME: not a good idea to write in user supplied buffer */
lpParms->lpstrElementName = ptr;
}
}
TRACE("devType=%s !\n", debugstr_w(strDevTyp));
}
if (dwParam & MCI_OPEN_ELEMENT) {
TRACE("lpstrElementName=%s\n", debugstr_w(lpParms->lpstrElementName));
if (dwParam & MCI_OPEN_ELEMENT_ID) {
FIXME("Unsupported yet flag MCI_OPEN_ELEMENT_ID\n");
dwRet = MCIERR_UNRECOGNIZED_KEYWORD;
goto errCleanUp;
}
if (!lpParms->lpstrElementName) {
dwRet = MCIERR_NULL_PARAMETER_BLOCK;
goto errCleanUp;
}
/* type, if given as a parameter, supersedes file extension */
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);
}
}
if (strDevTyp[0] == 0) {
FIXME("Couldn't load driver\n");
dwRet = MCIERR_INVALID_DEVICE_NAME;
goto errCleanUp;
}
if (dwParam & MCI_OPEN_ALIAS) {
TRACE("Alias=%s !\n", debugstr_w(lpParms->lpstrAlias));
if (!lpParms->lpstrAlias) {
dwRet = MCIERR_NULL_PARAMETER_BLOCK;
goto errCleanUp;
}
}
if ((dwRet = MCI_LoadMciDriver(strDevTyp, &wmd))) {
goto errCleanUp;
}
if ((dwRet = MCI_FinishOpen(wmd, lpParms, dwParam))) {
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=%ld\n", wmd->wDeviceID, lpParms->wDeviceID, dwRet);
if (dwParam & MCI_NOTIFY)
mciDriverNotify((HWND)lpParms->dwCallback, wmd->wDeviceID, MCI_NOTIFY_SUCCESSFUL);
return 0;
errCleanUp:
if (wmd) MCI_UnLoadMciDriver(wmd);
if (dwParam & MCI_NOTIFY)
mciDriverNotify((HWND)lpParms->dwCallback, 0, MCI_NOTIFY_FAILURE);
return dwRet;
}
/**************************************************************************
* MCI_Close [internal]
*/
static DWORD MCI_Close(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
{
DWORD dwRet;
LPWINE_MCIDRIVER wmd;
TRACE("(%04x, %08lX, %p)\n", wDevID, dwParam, lpParms);
if (wDevID == MCI_ALL_DEVICE_ID) {
LPWINE_MCIDRIVER next;
EnterCriticalSection(&WINMM_IData.cs);
/* 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 ?
*/
for (wmd = WINMM_IData.lpMciDrvs; wmd; ) {
next = wmd->lpNext;
MCI_Close(wmd->wDeviceID, dwParam, lpParms);
wmd = next;
}
LeaveCriticalSection(&WINMM_IData.cs);
return 0;
}
if (!(wmd = MCI_GetDriver(wDevID))) {
return MCIERR_INVALID_DEVICE_ID;
}
dwRet = MCI_SendCommandFrom32(wDevID, MCI_CLOSE_DRIVER, dwParam, (DWORD)lpParms);
MCI_UnLoadMciDriver(wmd);
if (dwParam & MCI_NOTIFY)
mciDriverNotify((HWND)lpParms->dwCallback, wDevID,
(dwRet == 0) ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE);
return dwRet;
}
/**************************************************************************
* MCI_WriteString [internal]
*/
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);
ret = MCIERR_PARAM_OVERFLOW;
} else {
strcpyW(lpDstStr, lpSrcStr);
}
} else {
*lpDstStr = 0;
}
return ret;
}
/**************************************************************************
* MCI_Sysinfo [internal]
*/
static DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSW lpParms)
{
DWORD ret = MCIERR_INVALID_DEVICE_ID, cnt = 0;
WCHAR buf[2048], *s = buf, *p;
LPWINE_MCIDRIVER wmd;
HKEY hKey;
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
TRACE("(%08x, %08lX, %08lX[num=%ld, wDevTyp=%u])\n",
uDevID, dwFlags, (DWORD)lpParms, lpParms->dwNumber, lpParms->wDeviceType);
switch (dwFlags & ~MCI_SYSINFO_OPEN) {
case MCI_SYSINFO_QUANTITY:
if (lpParms->wDeviceType < MCI_DEVTYPE_FIRST || lpParms->wDeviceType > MCI_DEVTYPE_LAST) {
if (dwFlags & MCI_SYSINFO_OPEN) {
TRACE("MCI_SYSINFO_QUANTITY: # of open MCI drivers\n");
EnterCriticalSection(&WINMM_IData.cs);
for (wmd = WINMM_IData.lpMciDrvs; wmd; wmd = wmd->lpNext) {
cnt++;
}
LeaveCriticalSection(&WINMM_IData.cs);
} else {
TRACE("MCI_SYSINFO_QUANTITY: # of installed MCI drivers\n");
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, wszHklmMci,
0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS) {
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++;
}
} else {
if (dwFlags & MCI_SYSINFO_OPEN) {
TRACE("MCI_SYSINFO_QUANTITY: # of open MCI drivers of type %u\n", lpParms->wDeviceType);
EnterCriticalSection(&WINMM_IData.cs);
for (wmd = WINMM_IData.lpMciDrvs; wmd; wmd = wmd->lpNext) {
if (wmd->wType == lpParms->wDeviceType) cnt++;
}
LeaveCriticalSection(&WINMM_IData.cs);
} else {
TRACE("MCI_SYSINFO_QUANTITY: # of installed MCI drivers of type %u\n", lpParms->wDeviceType);
FIXME("Don't know how to get # of MCI devices of a given type\n");
cnt = 1;
}
}
*(DWORD*)lpParms->lpstrReturn = cnt;
TRACE("(%ld) => '%ld'\n", lpParms->dwNumber, *(DWORD*)lpParms->lpstrReturn);
ret = MCI_INTEGER_RETURNED;
break;
case MCI_SYSINFO_INSTALLNAME:
TRACE("MCI_SYSINFO_INSTALLNAME \n");
if ((wmd = MCI_GetDriver(uDevID))) {
ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize,
wmd->lpstrDeviceType);
} else {
*lpParms->lpstrReturn = 0;
ret = MCIERR_INVALID_DEVICE_ID;
}
TRACE("(%ld) => %s\n", lpParms->dwNumber, debugstr_w(lpParms->lpstrReturn));
break;
case MCI_SYSINFO_NAME:
TRACE("MCI_SYSINFO_NAME\n");
if (dwFlags & MCI_SYSINFO_OPEN) {
FIXME("Don't handle MCI_SYSINFO_NAME|MCI_SYSINFO_OPEN (yet)\n");
ret = MCIERR_UNRECOGNIZED_COMMAND;
} else {
s = NULL;
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);
if (RegEnumKeyExW(hKey, lpParms->dwNumber - 1,
buf, &bufLen, 0, 0, 0, 0) == ERROR_SUCCESS)
s = buf;
}
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("%ld: %s\n", cnt, debugstr_w(p));
if (cnt == lpParms->dwNumber - 1) {
s = p;
break;
}
}
}
}
ret = s ? MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize / sizeof(WCHAR), s) : MCIERR_OUTOFRANGE;
}
TRACE("(%ld) => %s\n", lpParms->dwNumber, debugstr_w(lpParms->lpstrReturn));
break;
default:
TRACE("Unsupported flag value=%08lx\n", dwFlags);
ret = MCIERR_UNRECOGNIZED_COMMAND;
}
return ret;
}
/**************************************************************************
* MCI_Break [internal]
*/
static DWORD MCI_Break(UINT wDevID, DWORD dwFlags, LPMCI_BREAK_PARMS lpParms)
{
DWORD dwRet = 0;
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);
return dwRet;
}
/**************************************************************************
* MCI_Sound [internal]
*/
static DWORD MCI_Sound(UINT wDevID, DWORD dwFlags, LPMCI_SOUND_PARMSW lpParms)
{
DWORD dwRet = 0;
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);
return dwRet;
}
/**************************************************************************
* MCI_SendCommand [internal]
*/
DWORD MCI_SendCommand(UINT wDevID, UINT16 wMsg, DWORD dwParam1,
DWORD dwParam2, BOOL bFrom32)
{
DWORD dwRet = MCIERR_UNRECOGNIZED_COMMAND;
switch (wMsg) {
case MCI_OPEN:
if (bFrom32) {
dwRet = MCI_Open(dwParam1, (LPMCI_OPEN_PARMSW)dwParam2);
} else if (pFnMciMapMsg16To32W) {
switch (pFnMciMapMsg16To32W(0, wMsg, dwParam1, &dwParam2)) {
case WINMM_MAP_OK:
case WINMM_MAP_OKMEM:
dwRet = MCI_Open(dwParam1, (LPMCI_OPEN_PARMSW)dwParam2);
pFnMciUnMapMsg16To32W(0, wMsg, dwParam1, dwParam2);
break;
default: break; /* so that gcc does not bark */
}
}
break;
case MCI_CLOSE:
if (bFrom32) {
dwRet = MCI_Close(wDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
} else if (pFnMciMapMsg16To32W) {
switch (pFnMciMapMsg16To32W(0, wMsg, dwParam1, &dwParam2)) {
case WINMM_MAP_OK:
case WINMM_MAP_OKMEM:
dwRet = MCI_Close(wDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
pFnMciUnMapMsg16To32W(0, wMsg, dwParam1, dwParam2);
break;
default: break; /* so that gcc does not bark */
}
}
break;
case MCI_SYSINFO:
if (bFrom32) {
dwRet = MCI_SysInfo(wDevID, dwParam1, (LPMCI_SYSINFO_PARMSW)dwParam2);
} else if (pFnMciMapMsg16To32W) {
switch (pFnMciMapMsg16To32W(0, wMsg, dwParam1, &dwParam2)) {
case WINMM_MAP_OK:
case WINMM_MAP_OKMEM:
dwRet = MCI_SysInfo(wDevID, dwParam1, (LPMCI_SYSINFO_PARMSW)dwParam2);
pFnMciUnMapMsg16To32W(0, wMsg, dwParam1, dwParam2);
break;
default: break; /* so that gcc does not bark */
}
}
break;
case MCI_BREAK:
if (bFrom32) {
dwRet = MCI_Break(wDevID, dwParam1, (LPMCI_BREAK_PARMS)dwParam2);
} else if (pFnMciMapMsg16To32W) {
switch (pFnMciMapMsg16To32W(0, wMsg, dwParam1, &dwParam2)) {
case WINMM_MAP_OK:
ca
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -