📄 mci.c
字号:
LOBYTE(LOWORD(data[1])), HIBYTE(LOWORD(data[1])),
LOBYTE(HIWORD(data[1])));
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])));
break;
default: ERR("Ooops (%04X)\n", HIWORD(dwRet));
}
break;
case MCI_STRING:
switch (dwRet & 0xFFFF0000ul) {
case 0:
/* nothing to do data[1] == lpstrRet */
break;
case MCI_INTEGER_RETURNED:
data[1] = *(LPDWORD)lpstrRet;
snprintfW(lpstrRet, uRetLen, wszLd, data[1]);
break;
default:
WARN("Oooch. MCI_STRING and HIWORD(dwRet)=%04x\n", HIWORD(dwRet));
break;
}
break;
case MCI_RECT:
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]);
break;
default: ERR("oops\n");
}
}
return LOWORD(dwRet);
}
/**************************************************************************
* mciSendStringW [WINMM.@]
*/
DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
UINT uRetLen, HWND hwndCallback)
{
LPWSTR verb, dev, args;
LPWINE_MCIDRIVER wmd = 0;
DWORD dwFlags = 0, dwRet = 0;
int offset = 0;
DWORD data[MCI_DATA_SIZE];
DWORD retType;
LPCWSTR lpCmd = 0;
LPWSTR devAlias = NULL;
BOOL bAutoOpen = FALSE;
static const WCHAR wszNew[] = {'n','e','w',0};
static const WCHAR wszSAliasS[] = {' ','a','l','i','a','s',' ',0};
TRACE("(%s, %p, %d, %p)\n",
debugstr_w(lpstrCommand), lpstrRet, uRetLen, hwndCallback);
/* format is <command> <device> <optargs> */
if (!(verb = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpstrCommand)+1) * sizeof(WCHAR))))
return MCIERR_OUT_OF_MEMORY;
strcpyW( verb, lpstrCommand );
CharLowerW(verb);
memset(data, 0, sizeof(data));
if (!(args = strchrW(verb, ' '))) {
dwRet = MCIERR_MISSING_DEVICE_NAME;
goto errCleanUp;
}
*args++ = '\0';
if ((dwRet = MCI_GetString(&dev, &args))) {
goto errCleanUp;
}
/* case dev == 'new' has to be handled */
if (!strcmpW(dev, wszNew)) {
FIXME("'new': NIY as device name\n");
dwRet = MCIERR_MISSING_DEVICE_NAME;
goto errCleanUp;
}
/* otherwise, try to grab devType from open */
if (!strcmpW(verb, wszOpen)) {
LPWSTR devType, tmp;
if ((devType = strchrW(dev, '!')) != NULL) {
*devType++ = '\0';
tmp = devType; devType = dev; dev = tmp;
dwFlags |= MCI_OPEN_TYPE;
data[2] = (DWORD)devType;
devType = str_dup_upper(devType);
dwFlags |= MCI_OPEN_ELEMENT;
data[3] = (DWORD)dev;
} else if (strchrW(dev, '.') == NULL) {
tmp = strchrW(dev,' ');
if (tmp) *tmp = '\0';
data[2] = (DWORD)dev;
devType = str_dup_upper(dev);
if (tmp) *tmp = ' ';
dwFlags |= MCI_OPEN_TYPE;
} else {
static const WCHAR wszTypeS[] = {'t','y','p','e',' ',0};
if ((devType = strstrW(args, wszTypeS)) != NULL) {
devType += 5;
tmp = strchrW(devType, ' ');
if (tmp) *tmp = '\0';
devType = str_dup_upper(devType);
if (tmp) *tmp = ' ';
/* dwFlags and data[2] will be correctly set in ParseOpt loop */
} else {
WCHAR buf[32];
if ((dwRet = MCI_GetDevTypeFromFileName(dev, buf, sizeof(buf))))
goto errCleanUp;
devType = str_dup_upper(buf);
}
dwFlags |= MCI_OPEN_ELEMENT;
data[3] = (DWORD)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)tmp2;
/* should be done in regular options parsing */
/* dwFlags |= MCI_OPEN_ALIAS; */
}
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);
goto errCleanUp;
}
} else if (!(wmd = MCI_GetDriver(mciGetDeviceIDW(dev)))) {
/* auto open */
static WCHAR wszOpenWait[] = {'o','p','e','n',' ','%','s',' ','w','a','i','t',0};
WCHAR buf[128];
sprintfW(buf, wszOpenWait, 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;
}
}
/* get the verb in the different command tables */
if (wmd) {
/* try the device specific command table */
lpCmd = MCI_FindCommand(wmd->uSpecificCmdTable, verb);
if (!lpCmd) {
/* try the type specific command table */
if (wmd->uTypeCmdTable == MCI_COMMAND_TABLE_NOT_LOADED)
wmd->uTypeCmdTable = MCI_GetCommandTable(wmd->wType);
if (wmd->uTypeCmdTable != MCI_NO_COMMAND_TABLE)
lpCmd = MCI_FindCommand(wmd->uTypeCmdTable, verb);
}
}
/* try core command table */
if (!lpCmd) lpCmd = MCI_FindCommand(MCI_GetCommandTable(0), verb);
if (!lpCmd) {
TRACE("Command %s not found!\n", debugstr_w(verb));
dwRet = MCIERR_UNRECOGNIZED_COMMAND;
goto errCleanUp;
}
/* set up call back */
if (hwndCallback != 0) {
dwFlags |= MCI_NOTIFY;
data[0] = (DWORD)hwndCallback;
}
/* set return information */
switch (retType = MCI_GetReturnType(lpCmd)) {
case 0: offset = 1; break;
case MCI_INTEGER: offset = 2; break;
case MCI_STRING: data[1] = (DWORD)lpstrRet; data[2] = uRetLen; offset = 3; break;
case MCI_RECT: offset = 5; break;
default: ERR("oops\n");
}
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)))
goto errCleanUp;
if (bAutoOpen && (dwFlags & MCI_NOTIFY)) {
dwRet = MCIERR_NOTIFY_ON_AUTO_OPEN;
goto errCleanUp;
}
/* 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';
TRACE("[%d, %s, %08lx, %08lx/%s %08lx/%s %08lx/%s %08lx/%s %08lx/%s %08lx/%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]));
if (strcmpW(verb, wszOpen) == 0) {
if ((dwRet = MCI_FinishOpen(wmd, (LPMCI_OPEN_PARMSW)data, dwFlags)))
MCI_UnLoadMciDriver(wmd);
/* FIXME: notification is not properly shared across two opens */
} else {
dwRet = MCI_SendCommand(wmd->wDeviceID, MCI_GetMessage(lpCmd), dwFlags, (DWORD)data, TRUE);
}
TRACE("=> 1/ %lx (%s)\n", dwRet, debugstr_w(lpstrRet));
dwRet = MCI_HandleReturnValues(dwRet, wmd, retType, data, lpstrRet, uRetLen);
TRACE("=> 2/ %lx (%s)\n", dwRet, debugstr_w(lpstrRet));
errCleanUp:
HeapFree(GetProcessHeap(), 0, verb);
HeapFree(GetProcessHeap(), 0, devAlias);
return dwRet;
}
/**************************************************************************
* mciSendStringA [WINMM.@]
*/
DWORD WINAPI mciSendStringA(LPCSTR lpstrCommand, LPSTR lpstrRet,
UINT uRetLen, HWND hwndCallback)
{
LPWSTR lpwstrCommand;
LPWSTR lpwstrRet = NULL;
UINT ret;
INT len;
/* FIXME: is there something to do with lpstrReturnString ? */
len = MultiByteToWideChar( CP_ACP, 0, lpstrCommand, -1, NULL, 0 );
lpwstrCommand = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, lpstrCommand, -1, lpwstrCommand, len );
if (lpstrRet)
{
lpwstrRet = HeapAlloc(GetProcessHeap(), 0, uRetLen * sizeof(WCHAR));
if (!lpwstrRet) {
WARN("no memory\n");
HeapFree( GetProcessHeap(), 0, lpwstrCommand );
return MCIERR_OUT_OF_MEMORY;
}
}
ret = mciSendStringW(lpwstrCommand, lpwstrRet, uRetLen, hwndCallback);
if (lpwstrRet)
WideCharToMultiByte( CP_ACP, 0, lpwstrRet, -1, lpstrRet, uRetLen, NULL, NULL );
HeapFree(GetProcessHeap(), 0, lpwstrCommand);
HeapFree(GetProcessHeap(), 0, lpwstrRet);
return ret;
}
/**************************************************************************
* mciExecute [WINMM.@]
* mciExecute [MMSYSTEM.712]
*/
BOOL WINAPI mciExecute(LPCSTR lpstrCommand)
{
char strRet[256];
DWORD ret;
TRACE("(%s)!\n", lpstrCommand);
ret = mciSendStringA(lpstrCommand, strRet, sizeof(strRet), 0);
if (ret != 0) {
if (!mciGetErrorStringA(ret, strRet, sizeof(strRet))) {
sprintf(strRet, "Unknown MCI error (%ld)", ret);
}
MessageBoxA(0, strRet, "Error in mciExecute()", MB_OK);
}
/* FIXME: what shall I return ? */
return TRUE;
}
/**************************************************************************
* mciLoadCommandResource [WINMM.@]
*
* Strangely, this function only exists as an UNICODE one.
*/
UINT WINAPI mciLoadCommandResource(HINSTANCE hInst, LPCWSTR resNameW, UINT type)
{
HRSRC hRsrc = 0;
HGLOBAL hMem;
UINT16 ret = MCI_NO_COMMAND_TABLE;
TRACE("(%p, %s, %d)!\n", hInst, debugstr_w(resNameW), type);
/* if a file named "resname.mci" exits, then load resource "resname" from it
* otherwise directly from driver
* We don't support it (who uses this feature ?), but we check anyway
*/
if (!type) {
#if 0
/* FIXME: we should put this back into order, but I never found a program
* actually using this feature, so we may not need it
*/
char buf[128];
OFSTRUCT ofs;
strcat(strcpy(buf, resname), ".mci");
if (OpenFile(buf, &ofs, OF_EXIST) != HFILE_ERROR) {
FIXME("NIY: command table to be loaded from '%s'\n", ofs.szPathName);
}
#endif
}
if (!(hRsrc = FindResourceW(hInst, resNameW, (LPWSTR)RT_RCDATA))) {
WARN("No command table found in resource\n");
} else if ((hMem = LoadResource(hInst, hRsrc))) {
ret = MCI_SetCommandTable(LockResource(hMem), type);
} else {
WARN("Couldn't load resource.\n");
}
TRACE("=> %04x\n", ret);
return ret;
}
/**************************************************************************
* mciFreeCommandResource [WINMM.@]
*/
BOOL WINAPI mciFreeCommandResource(UINT uTable)
{
TRACE("(%08x)!\n", uTable);
return MCI_DeleteCommandTable(uTable, FALSE);
}
/**************************************************************************
* MCI_SendCommandFrom32 [internal]
*/
DWORD MCI_SendCommandFrom32(MCIDEVICEID wDevID, UINT16 wMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
DWORD dwRet = MCIERR_INVALID_DEVICE_ID;
LPWINE_MCIDRIVER wmd = MCI_GetDriver(wDevID);
if (wmd) {
if (wmd->bIs32) {
dwRet = SendDriverMessage(wmd->hDriver, wMsg, dwParam1, dwParam2);
} else if (pFnMciMapMsg32WTo16) {
WINMM_MapType res;
switch (res = pFnMciMapMsg32WTo16(wmd->wType, wMsg, dwParam1, &dwParam2)) {
case WINMM_MAP_MSGERROR:
TRACE("Not handled yet (%s)\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_DRIVER_INTERNAL;
break;
case WINMM_MAP_NOMEM:
TRACE("Problem mapping msg=%s from 32a to 16\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_OUT_OF_MEMORY;
break;
case WINMM_MAP_OK:
case WINMM_MAP_OKMEM:
dwRet = SendDriverMessage(wmd->hDriver, wMsg, dwParam1, dwParam2);
if (res == WINMM_MAP_OKMEM)
pFnMciUnMapMsg32WTo16(wmd->wType, wMsg, dwParam1, dwParam2);
break;
}
}
}
return dwRet;
}
/**************************************************************************
* MCI_SendCommandFrom16 [internal]
*/
DWORD MCI_SendCommandFrom16(MCIDEVICEID wDevID, UINT16 wMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
DWORD dwRet = MCIERR_INVALID_DEVICE_ID;
LPWINE_MCIDRIVER wmd = MCI_GetDriver(wDevID);
if (wmd) {
dwRet = MCIERR_INVALID_DEVICE_ID;
if (wmd->bIs32 && pFnMciMapMsg16To32W) {
WINMM_MapType res;
switch (res = pFnMciMapMsg16To32W(wmd->wType, wMsg, dwParam1, &dwParam2)) {
case WINMM_MAP_MSGERROR:
TRACE("Not handled yet (%s)\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_DRIVER_INTERNAL;
break;
case WINMM_MAP_NOMEM:
TRACE("Problem mapping msg=%s from 16 to 32a\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_OUT_OF_MEMORY;
break;
case WINMM_MAP_OK:
case WINMM_MAP_OKMEM:
dwRet = SendDriverMessage(wmd->hDriver, wMsg, dwParam1, dwParam2);
if (res == WINMM_MAP_OKMEM)
pFnMciUnMapMsg16To32W(wmd->wType, wMsg, dwParam1, dwParam2);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -