📄 mci.c
字号:
}
}
LeaveCriticalSection(&WINMM_IData.cs);
HeapFree(GetProcessHeap(), 0, wmd->lpstrDeviceType);
HeapFree(GetProcessHeap(), 0, wmd->lpstrAlias);
HeapFree(GetProcessHeap(), 0, wmd->lpstrElementName);
HeapFree(GetProcessHeap(), 0, wmd);
return TRUE;
}
/**************************************************************************
* MCI_OpenMciDriver [internal]
*/
static BOOL MCI_OpenMciDriver(LPWINE_MCIDRIVER wmd, LPCWSTR drvTyp, LPARAM lp)
{
WCHAR libName[128];
if (!DRIVER_GetLibName(drvTyp, wszMci, libName, sizeof(libName)))
return FALSE;
wmd->bIs32 = 0xFFFF;
/* First load driver */
if ((wmd->hDriver = (HDRVR)DRIVER_TryOpenDriver32(libName, lp))) {
wmd->bIs32 = TRUE;
} else if (WINMM_CheckForMMSystem() && pFnMciMapMsg32WTo16) {
WINMM_MapType res;
switch (res = pFnMciMapMsg32WTo16(0, DRV_OPEN, 0, &lp)) {
case WINMM_MAP_MSGERROR:
TRACE("Not handled yet (DRV_OPEN)\n");
break;
case WINMM_MAP_NOMEM:
TRACE("Problem mapping msg=DRV_OPEN from 32W to 16\n");
break;
case WINMM_MAP_OK:
case WINMM_MAP_OKMEM:
if ((wmd->hDriver = OpenDriver(drvTyp, wszMci, lp)))
wmd->bIs32 = FALSE;
if (res == WINMM_MAP_OKMEM)
pFnMciUnMapMsg32WTo16(0, DRV_OPEN, 0, lp);
break;
}
}
return (wmd->bIs32 == 0xFFFF) ? FALSE : TRUE;
}
/**************************************************************************
* MCI_LoadMciDriver [internal]
*/
static DWORD MCI_LoadMciDriver(LPCWSTR _strDevTyp, LPWINE_MCIDRIVER* lpwmd)
{
LPWSTR strDevTyp = str_dup_upper(_strDevTyp);
LPWINE_MCIDRIVER wmd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wmd));
MCI_OPEN_DRIVER_PARMSW modp;
DWORD dwRet = 0;
if (!wmd || !strDevTyp) {
dwRet = MCIERR_OUT_OF_MEMORY;
goto errCleanUp;
}
wmd->lpfnYieldProc = MCI_DefYieldProc;
wmd->dwYieldData = VK_CANCEL;
wmd->CreatorThread = GetCurrentThreadId();
EnterCriticalSection(&WINMM_IData.cs);
/* wmd must be inserted in list before sending opening the driver, coz' it
* may want to lookup at wDevID
*/
wmd->lpNext = WINMM_IData.lpMciDrvs;
WINMM_IData.lpMciDrvs = wmd;
for (modp.wDeviceID = MCI_MAGIC;
MCI_GetDriver(modp.wDeviceID) != 0;
modp.wDeviceID++);
wmd->wDeviceID = modp.wDeviceID;
LeaveCriticalSection(&WINMM_IData.cs);
TRACE("wDevID=%04X \n", modp.wDeviceID);
modp.lpstrParams = NULL;
if (!MCI_OpenMciDriver(wmd, strDevTyp, (LPARAM)&modp)) {
/* silence warning if all is used... some bogus program use commands like
* 'open all'...
*/
if (strcmpiW(strDevTyp, wszAll) == 0) {
dwRet = MCIERR_CANNOT_USE_ALL;
} else {
FIXME("Couldn't load driver for type %s.\n"
"If you don't have a windows installation accessible from Wine,\n"
"you perhaps forgot to create a [mci] section in system.ini\n",
debugstr_w(strDevTyp));
dwRet = MCIERR_DEVICE_NOT_INSTALLED;
}
goto errCleanUp;
}
/* FIXME: should also check that module's description is of the form
* MODULENAME:[MCI] comment
*/
/* some drivers will return 0x0000FFFF, some others 0xFFFFFFFF */
wmd->uSpecificCmdTable = LOWORD(modp.wCustomCommandTable);
wmd->uTypeCmdTable = MCI_COMMAND_TABLE_NOT_LOADED;
TRACE("Loaded driver %p (%s), type is %d, cmdTable=%08x\n",
wmd->hDriver, debugstr_w(strDevTyp), modp.wType, modp.wCustomCommandTable);
wmd->lpstrDeviceType = strDevTyp;
wmd->wType = modp.wType;
TRACE("mcidev=%d, uDevTyp=%04X wDeviceID=%04X !\n",
modp.wDeviceID, modp.wType, modp.wDeviceID);
*lpwmd = wmd;
return 0;
errCleanUp:
MCI_UnLoadMciDriver(wmd);
HeapFree(GetProcessHeap(), 0, strDevTyp);
*lpwmd = 0;
return dwRet;
}
/**************************************************************************
* MCI_FinishOpen [internal]
*/
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 );
}
if (dwParam & MCI_OPEN_ALIAS)
{
wmd->lpstrAlias = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpParms->lpstrAlias)+1) * sizeof(WCHAR));
strcpyW( wmd->lpstrAlias, lpParms->lpstrAlias);
}
lpParms->wDeviceID = wmd->wDeviceID;
return MCI_SendCommandFrom32(wmd->wDeviceID, MCI_OPEN_DRIVER, dwParam,
(DWORD)lpParms);
}
/**************************************************************************
* MCI_FindCommand [internal]
*/
static LPCWSTR MCI_FindCommand(UINT uTbl, LPCWSTR verb)
{
UINT idx;
if (uTbl >= MAX_MCICMDTABLE || !S_MciCmdTable[uTbl].lpTable)
return NULL;
/* another improvement would be to have the aVerbs array sorted,
* so that we could use a dichotomic search on it, rather than this dumb
* array look up
*/
for (idx = 0; idx < S_MciCmdTable[uTbl].nVerbs; idx++) {
if (strcmpiW(S_MciCmdTable[uTbl].aVerbs[idx], verb) == 0)
return S_MciCmdTable[uTbl].aVerbs[idx];
}
return NULL;
}
/**************************************************************************
* MCI_GetReturnType [internal]
*/
static DWORD MCI_GetReturnType(LPCWSTR lpCmd)
{
lpCmd = (LPCWSTR)((BYTE*)(lpCmd + strlenW(lpCmd) + 1) + sizeof(DWORD) + sizeof(WORD));
if (*lpCmd == '\0' && *(const WORD*)((BYTE*)(lpCmd + 1) + sizeof(DWORD)) == MCI_RETURN) {
return *(const DWORD*)(lpCmd + 1);
}
return 0L;
}
/**************************************************************************
* MCI_GetMessage [internal]
*/
static WORD MCI_GetMessage(LPCWSTR lpCmd)
{
return (WORD)*(const DWORD*)(lpCmd + strlenW(lpCmd) + 1);
}
/**************************************************************************
* MCI_GetDWord [internal]
*/
static BOOL MCI_GetDWord(LPDWORD data, LPWSTR* ptr)
{
DWORD val;
LPWSTR ret;
val = strtoulW(*ptr, &ret, 0);
switch (*ret) {
case '\0': break;
case ' ': ret++; break;
default: return FALSE;
}
*data |= val;
*ptr = ret;
return TRUE;
}
/**************************************************************************
* MCI_GetString [internal]
*/
static DWORD MCI_GetString(LPWSTR* str, LPWSTR* args)
{
LPWSTR ptr = *args;
/* see if we have a quoted string */
if (*ptr == '"') {
ptr = strchrW(*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;
*ptr++ = '\0';
} else {
ptr = strchrW(ptr, ' ');
if (ptr) {
*ptr++ = '\0';
} else {
ptr = *args + strlenW(*args);
}
*str = *args;
}
*args = ptr;
return 0;
}
#define MCI_DATA_SIZE 16
/**************************************************************************
* MCI_ParseOptArgs [internal]
*/
static DWORD MCI_ParseOptArgs(LPDWORD data, int _offset, LPCWSTR lpCmd,
LPWSTR args, LPDWORD dwFlags)
{
int len, offset;
const char* lmem;
LPCWSTR str;
DWORD dwRet, flg, cflg = 0;
WORD eid;
BOOL inCst, found;
/* loop on arguments */
while (*args) {
lmem = (const char*)lpCmd;
found = inCst = FALSE;
offset = _offset;
/* skip any leading white space(s) */
while (*args == ' ') args++;
TRACE("args=%s offset=%d\n", debugstr_w(args), offset);
do { /* loop on options for command table for the requested verb */
str = (LPCWSTR)lmem;
lmem += ((len = strlenW(str)) + 1) * sizeof(WCHAR);
flg = *(const DWORD*)lmem;
eid = *(const WORD*)(lmem + sizeof(DWORD));
lmem += sizeof(DWORD) + sizeof(WORD);
/* TRACE("\tcmd=%s inCst=%c eid=%04x\n", debugstr_w(str), inCst ? 'Y' : 'N', eid); */
switch (eid) {
case MCI_CONSTANT:
inCst = TRUE; cflg = flg; break;
case MCI_END_CONSTANT:
/* there may be additional integral values after flag in constant */
if (inCst && MCI_GetDWord(&(data[offset]), &args)) {
*dwFlags |= cflg;
}
inCst = FALSE; cflg = 0;
break;
}
if (strncmpiW(args, str, len) == 0 &&
(args[len] == 0 || args[len] == ' ')) {
/* store good values into data[] */
args += len;
while (*args == ' ') args++;
found = TRUE;
switch (eid) {
case MCI_COMMAND_HEAD:
case MCI_RETURN:
case MCI_END_COMMAND:
case MCI_END_COMMAND_LIST:
case MCI_CONSTANT: /* done above */
case MCI_END_CONSTANT: /* done above */
break;
case MCI_FLAG:
*dwFlags |= flg;
break;
case MCI_INTEGER:
if (inCst) {
data[offset] |= flg;
*dwFlags |= cflg;
inCst = FALSE;
} else {
*dwFlags |= flg;
if (!MCI_GetDWord(&(data[offset]), &args)) {
return MCIERR_BAD_INTEGER;
}
}
break;
case MCI_RECT:
/* store rect in data (offset...offset+3) */
*dwFlags |= flg;
if (!MCI_GetDWord(&(data[offset+0]), &args) ||
!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;
}
break;
case MCI_STRING:
*dwFlags |= flg;
if ((dwRet = MCI_GetString((LPWSTR*)&data[offset], &args)))
return dwRet;
break;
default: ERR("oops\n");
}
/* exit inside while loop, except if just entered in constant area definition */
if (!inCst || eid != MCI_CONSTANT) eid = MCI_END_COMMAND;
} else {
/* have offset incremented if needed */
switch (eid) {
case MCI_COMMAND_HEAD:
case MCI_RETURN:
case MCI_END_COMMAND:
case MCI_END_COMMAND_LIST:
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_RECT: offset += 4; break;
default: ERR("oops\n");
}
}
} while (eid != MCI_END_COMMAND);
if (!found) {
WARN("Optarg %s not found\n", debugstr_w(args));
return MCIERR_UNRECOGNIZED_COMMAND;
}
if (offset == MCI_DATA_SIZE) {
ERR("Internal data[] buffer overflow\n");
return MCIERR_PARSER_INTERNAL;
}
}
return 0;
}
/**************************************************************************
* MCI_HandleReturnValues [internal]
*/
static DWORD MCI_HandleReturnValues(DWORD dwRet, LPWINE_MCIDRIVER wmd, DWORD retType,
LPDWORD data, 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:
switch (dwRet & 0xFFFF0000ul) {
case 0:
case MCI_INTEGER_RETURNED:
snprintfW(lpstrRet, uRetLen, wszLd, data[1]);
break;
case MCI_RESOURCE_RETURNED:
/* return string which ID is HIWORD(data[1]),
* string is loaded from mmsystem.dll */
LoadStringW(WINMM_IData.hWinMM32Instance, HIWORD(data[1]),
lpstrRet, uRetLen);
break;
case MCI_RESOURCE_RETURNED|MCI_RESOURCE_DRIVER:
/* return string which ID is HIWORD(data[1]),
* string is loaded from driver */
/* FIXME: this is wrong for a 16 bit handle */
LoadStringW(GetDriverModuleHandle(wmd->hDriver),
HIWORD(data[1]), lpstrRet, uRetLen);
break;
case MCI_COLONIZED3_RETURN:
snprintfW(lpstrRet, uRetLen, wszCol3,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -