winmm: Use proper structure where possible to fix command string parsing on 64-bit.

This commit is contained in:
Alexandre Julliard 2010-09-29 14:47:55 +02:00
parent 5029331f55
commit 41a5b37b7a

View file

@ -970,7 +970,7 @@ static WORD MCI_GetMessage(LPCWSTR lpCmd)
/**************************************************************************
* MCI_GetDWord [internal]
*/
static BOOL MCI_GetDWord(DWORD_PTR* data, LPWSTR* ptr)
static BOOL MCI_GetDWord(DWORD* data, LPWSTR* ptr)
{
DWORD val;
LPWSTR ret;
@ -1023,7 +1023,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;
@ -1098,7 +1098,7 @@ static DWORD MCI_ParseOptArgs(DWORD_PTR* data, int _offset, LPCWSTR lpCmd,
if (!MCI_GetDWord(&(data[offset]), &args)) {
return MCIERR_BAD_INTEGER;
}
TRACE("flag=%08x int=%ld\n", flg, data[offset]);
TRACE("flag=%08x int=%d\n", flg, data[offset]);
}
break;
case MCI_RECT:
@ -1117,7 +1117,7 @@ static DWORD MCI_ParseOptArgs(DWORD_PTR* data, int _offset, LPCWSTR lpCmd,
*dwFlags |= flg;
if ((dwRet = MCI_GetString((LPWSTR*)&data[offset], &args)))
return dwRet;
TRACE("flag=%08x string=%s\n", flg, debugstr_w((LPWSTR)data[offset]));
TRACE("flag=%08x string=%s\n", flg, debugstr_w(*(LPWSTR*)&data[offset]));
break;
default: ERR("oops\n");
}
@ -1133,8 +1133,8 @@ static DWORD MCI_ParseOptArgs(DWORD_PTR* data, int _offset, LPCWSTR lpCmd,
case MCI_CONSTANT:
case MCI_FLAG: 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");
}
@ -1156,10 +1156,10 @@ 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)
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 fmt_d [] = {'%','d',0};
static const WCHAR fmt_d4 [] = {'%','d',' ','%','d',' ','%','d',' ','%','d',0};
static const WCHAR wszCol3[] = {'%','0','2','d',':','%','0','2','d',':','%','0','2','d',0};
static const WCHAR wszCol4[] = {'%','0','2','d',':','%','0','2','d',':','%','0','2','d',':','%','0','2','d',0};
@ -1168,56 +1168,64 @@ static DWORD MCI_HandleReturnValues(DWORD dwRet, LPWINE_MCIDRIVER wmd, DWORD ret
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]);
snprintfW(lpstrRet, uRetLen, fmt_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])));
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])));
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;
snprintfW(lpstrRet, uRetLen, fmt_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]);
snprintfW(lpstrRet, uRetLen, fmt_d4, data[0], data[1], data[2], data[3]);
break;
}
default: ERR("oops\n");
}
}
@ -1235,13 +1243,20 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
MCIDEVICEID uDevID, auto_open = 0;
DWORD dwFlags = 0, dwRet = 0;
int offset = 0;
DWORD_PTR data[MCI_DATA_SIZE];
DWORD retType;
LPCWSTR lpCmd = 0;
WORD wMsg = 0;
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};
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);
@ -1253,7 +1268,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
strcpyW( verb, lpstrCommand );
CharLowerW(verb);
memset(data, 0, sizeof(data));
memset(&data, 0, sizeof(data));
if (!(args = strchrW(verb, ' '))) {
dwRet = MCIERR_MISSING_DEVICE_NAME;
@ -1290,15 +1305,15 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
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;
data.open.lpstrElementName = dev;
} else if (DRIVER_GetLibName(dev, wszMci, buf, sizeof(buf))) {
/* this is the name of a mci driver's type */
tmp = strchrW(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;
@ -1309,7 +1324,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
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;
@ -1317,7 +1332,7 @@ 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 (MCI_ALL_DEVICE_ID == uDevID) {
dwRet = MCIERR_CANNOT_USE_ALL;
@ -1391,18 +1406,29 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
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;
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)))
if ((dwRet = MCI_ParseOptArgs(data.dw, offset / sizeof(DWORD), lpCmd, args, &dwFlags)))
goto errCleanUp;
/* set up call back */
@ -1418,7 +1444,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
* 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;
}
switch (wMsg) {
@ -1435,12 +1461,11 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
* alias with INSTALLNAME, name like "digitalvideo"
* with QUANTITY and NAME. */
{
LPMCI_SYSINFO_PARMSW lpParms = (LPMCI_SYSINFO_PARMSW)data;
lpParms->wDeviceType = MCI_ALL_DEVICE_ID;
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 (!(lpParms->wDeviceType = MCI_GetDevTypeFromResource(dev))) {
else if (!(data.sysinfo.wDeviceType = MCI_GetDevTypeFromResource(dev))) {
dwRet = MCIERR_DEVICE_TYPE_REQUIRED;
goto errCleanUp;
}
@ -1450,25 +1475,25 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
case MCI_SOUND:
/* FIXME: name is optional, "sound" is a valid command.
* FIXME: Parse "sound notify" as flag, not as name. */
((LPMCI_SOUND_PARMSW)data)->lpstrSoundName = dev;
data.sound.lpstrSoundName = dev;
dwFlags |= MCI_SOUND_NAME;
break;
}
TRACE("[%d, %s, %08x, %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx]\n",
TRACE("[%d, %s, %08x, %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x]\n",
wmd ? wmd->wDeviceID : uDevID, MCI_MessageToString(wMsg), dwFlags,
data[0], data[1], data[2], data[3], data[4],
data[5], data[6], data[7], data[8], data[9]);
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 (wMsg == MCI_OPEN) {
if ((dwRet = MCI_FinishOpen(wmd, (LPMCI_OPEN_PARMSW)data, dwFlags)))
if ((dwRet = MCI_FinishOpen(wmd, &data.open, dwFlags)))
goto errCleanUp;
/* FIXME: notification is not properly shared across two opens */
} else {
dwRet = MCI_SendCommand(wmd ? wmd->wDeviceID : uDevID, wMsg, 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);
dwRet = MCI_HandleReturnValues(dwRet, wmd, retType, &data.generic, lpstrRet, uRetLen);
TRACE("=> 2/ %x (%s)\n", dwRet, debugstr_w(lpstrRet));
errCleanUp: