📄 mci.c
字号:
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;
mci_loadW = HeapAlloc(GetProcessHeap(), 0, sizeof(*mci_loadW));
if (!mci_loadW) return -1;
*dwParam2 = (DWORD_PTR)mci_loadW;
if (dwParam1 & MCI_NOTIFY)
mci_loadW->dwCallback = mci_loadA->dwCallback;
mci_loadW->lpfilename = MCI_strdupAtoW(mci_loadA->lpfilename);
return 1;
}
case MCI_ESCAPE:
{
MCI_VD_ESCAPE_PARMSA *mci_vd_escapeA = (MCI_VD_ESCAPE_PARMSA *)*dwParam2;
MCI_VD_ESCAPE_PARMSW *mci_vd_escapeW;
mci_vd_escapeW = HeapAlloc(GetProcessHeap(), 0, sizeof(*mci_vd_escapeW));
if (!mci_vd_escapeW) return -1;
*dwParam2 = (DWORD_PTR)mci_vd_escapeW;
if (dwParam1 & MCI_NOTIFY)
mci_vd_escapeW->dwCallback = mci_vd_escapeA->dwCallback;
mci_vd_escapeW->lpstrCommand = MCI_strdupAtoW(mci_vd_escapeA->lpstrCommand);
return 1;
}
default:
FIXME("Message %s needs translation\n", MCI_MessageToString(msg));
return -1;
}
}
static DWORD MCI_UnmapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2,
DWORD result)
{
switch (msg)
{
case MCI_OPEN:
{
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_openA->wDeviceID = mci_openW->wDeviceID;
if (dwParam1 & MCI_OPEN_TYPE)
{
if (!(dwParam1 & MCI_OPEN_TYPE_ID))
HeapFree(GetProcessHeap(), 0, (PVOID)mci_openW->lpstrDeviceType);
}
if (dwParam1 & MCI_OPEN_ELEMENT)
{
if (!(dwParam1 & MCI_OPEN_ELEMENT_ID))
HeapFree(GetProcessHeap(), 0, (PVOID)mci_openW->lpstrElementName);
}
if (dwParam1 & MCI_OPEN_ALIAS)
HeapFree(GetProcessHeap(), 0, (PVOID)mci_openW->lpstrAlias);
HeapFree(GetProcessHeap(), 0, ptr);
}
break;
case MCI_WINDOW:
if (dwParam1 & MCI_ANIM_WINDOW_TEXT)
{
MCI_ANIM_WINDOW_PARMSW *mci_windowW = (MCI_ANIM_WINDOW_PARMSW *)dwParam2;
HeapFree(GetProcessHeap(), 0, (void*)mci_windowW->lpstrText);
HeapFree(GetProcessHeap(), 0, mci_windowW);
}
break;
case MCI_SYSINFO:
{
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);
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);
}
HeapFree(GetProcessHeap(), 0, mci_sysinfoW->lpstrReturn);
HeapFree(GetProcessHeap(), 0, ptr);
}
break;
case MCI_INFO:
{
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);
if (!result)
{
WideCharToMultiByte(CP_ACP, 0,
mci_infoW->lpstrReturn, mci_infoW->dwRetSize / sizeof(WCHAR),
mci_infoA->lpstrReturn, mci_infoA->dwRetSize,
NULL, NULL);
}
HeapFree(GetProcessHeap(), 0, mci_infoW->lpstrReturn);
HeapFree(GetProcessHeap(), 0, ptr);
}
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;
HeapFree(GetProcessHeap(), 0, (void*)mci_loadW->lpfilename);
HeapFree(GetProcessHeap(), 0, mci_loadW);
}
break;
case MCI_ESCAPE:
{
MCI_VD_ESCAPE_PARMSW *mci_vd_escapeW = (MCI_VD_ESCAPE_PARMSW *)dwParam2;
HeapFree(GetProcessHeap(), 0, (void*)mci_vd_escapeW->lpstrCommand);
HeapFree(GetProcessHeap(), 0, mci_vd_escapeW);
}
break;
default:
FIXME("Message %s needs unmapping\n", MCI_MessageToString(msg));
break;
}
return result;
}
/**************************************************************************
* MCI_GetDevTypeFromFileName [internal]
*/
static DWORD MCI_GetDevTypeFromFileName(LPCWSTR fileName, LPCWSTR 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,
0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS) {
DWORD dwLen = len;
LONG lRet = RegQueryValueExW( hKey, tmp + 1, 0, 0, (void*)buf, &dwLen );
RegCloseKey( hKey );
if (lRet == ERROR_SUCCESS) return 0;
}
TRACE("No ...\\MCI Extensions entry for %s found.\n", debugstr_w(tmp));
}
return MCIERR_EXTENSION_NOT_FOUND;
}
#define MAX_MCICMDTABLE 20
#define MCI_COMMAND_TABLE_NOT_LOADED 0xFFFE
typedef struct tagWINE_MCICMDTABLE {
UINT uDevType;
const BYTE* lpTable;
UINT nVerbs; /* number of verbs in command table */
LPCWSTR* aVerbs; /* array of verbs to speed up the verb look up process */
} WINE_MCICMDTABLE, *LPWINE_MCICMDTABLE;
static WINE_MCICMDTABLE S_MciCmdTable[MAX_MCICMDTABLE];
/**************************************************************************
* MCI_IsCommandTableValid [internal]
*/
static BOOL MCI_IsCommandTableValid(UINT uTbl)
{
const BYTE* lmem;
LPCWSTR str;
DWORD flg;
WORD eid;
int idx = 0;
BOOL inCst = FALSE;
TRACE("Dumping cmdTbl=%d [lpTable=%p devType=%d]\n",
uTbl, S_MciCmdTable[uTbl].lpTable, S_MciCmdTable[uTbl].uDevType);
if (uTbl >= MAX_MCICMDTABLE || !S_MciCmdTable[uTbl].lpTable)
return FALSE;
lmem = S_MciCmdTable[uTbl].lpTable;
do {
str = (LPCWSTR)lmem;
lmem += (strlenW(str) + 1) * sizeof(WCHAR);
flg = *(const DWORD*)lmem;
eid = *(const WORD*)(lmem + sizeof(DWORD));
lmem += sizeof(DWORD) + sizeof(WORD);
idx ++;
/* TRACE("cmd=%s %08lx %04x\n", debugstr_w(str), flg, eid); */
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_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;
case MCI_FLAG: if (!*str) return FALSE; break;
case MCI_END_COMMAND_LIST: if (*str || flg) return FALSE; idx = 0; break;
case MCI_RECT: if (!*str || inCst) return FALSE; break;
case MCI_CONSTANT: if (inCst) return FALSE; inCst = TRUE; break;
case MCI_END_CONSTANT: if (*str || flg || !inCst) return FALSE; inCst = FALSE; break;
default: return FALSE;
}
} while (eid != MCI_END_COMMAND_LIST);
return TRUE;
}
/**************************************************************************
* MCI_DumpCommandTable [internal]
*/
static BOOL MCI_DumpCommandTable(UINT uTbl)
{
const BYTE* lmem;
LPCWSTR str;
DWORD flg;
WORD eid;
if (!MCI_IsCommandTableValid(uTbl)) {
ERR("Ooops: %d is not valid\n", uTbl);
return FALSE;
}
lmem = S_MciCmdTable[uTbl].lpTable;
do {
do {
str = (LPCWSTR)lmem;
lmem += (strlenW(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);
} while (eid != MCI_END_COMMAND && eid != MCI_END_COMMAND_LIST);
/* EPP TRACE(" => end of command%s\n", (eid == MCI_END_COMMAND_LIST) ? " list" : ""); */
} while (eid != MCI_END_COMMAND_LIST);
return TRUE;
}
/**************************************************************************
* MCI_GetCommandTable [internal]
*/
static UINT MCI_GetCommandTable(UINT uDevType)
{
UINT uTbl;
WCHAR buf[32];
LPCWSTR str = NULL;
/* first look up existing for existing devType */
for (uTbl = 0; uTbl < MAX_MCICMDTABLE; uTbl++) {
if (S_MciCmdTable[uTbl].lpTable && S_MciCmdTable[uTbl].uDevType == uDevType)
return uTbl;
}
/* well try to load id */
if (uDevType >= MCI_DEVTYPE_FIRST && uDevType <= MCI_DEVTYPE_LAST) {
if (LoadStringW(WINMM_IData.hWinMM32Instance, uDevType, buf, sizeof(buf) / sizeof(WCHAR))) {
str = buf;
}
} else if (uDevType == 0) {
static const WCHAR wszCore[] = {'C','O','R','E',0};
str = wszCore;
}
uTbl = MCI_NO_COMMAND_TABLE;
if (str) {
HRSRC hRsrc = FindResourceW(WINMM_IData.hWinMM32Instance, str, (LPCWSTR)RT_RCDATA);
HANDLE hMem = 0;
if (hRsrc) hMem = LoadResource(WINMM_IData.hWinMM32Instance, hRsrc);
if (hMem) {
uTbl = MCI_SetCommandTable(LockResource(hMem), uDevType);
} else {
WARN("No command table found in resource %p[%s]\n",
WINMM_IData.hWinMM32Instance, debugstr_w(str));
}
}
TRACE("=> %d\n", uTbl);
return uTbl;
}
/**************************************************************************
* MCI_SetCommandTable [internal]
*/
UINT MCI_SetCommandTable(void *table, UINT uDevType)
{
int uTbl;
static BOOL bInitDone = FALSE;
/* <HACK>
* The CORE command table must be loaded first, so that MCI_GetCommandTable()
* can be called with 0 as a uDevType to retrieve it.
* </HACK>
*/
if (!bInitDone) {
bInitDone = TRUE;
MCI_GetCommandTable(0);
}
TRACE("(%p, %u)\n", table, uDevType);
for (uTbl = 0; uTbl < MAX_MCICMDTABLE; uTbl++) {
if (!S_MciCmdTable[uTbl].lpTable) {
const BYTE* lmem;
LPCWSTR str;
WORD eid;
WORD count;
S_MciCmdTable[uTbl].uDevType = uDevType;
S_MciCmdTable[uTbl].lpTable = table;
if (TRACE_ON(mci)) {
MCI_DumpCommandTable(uTbl);
}
/* create the verbs table */
/* get # of entries */
lmem = S_MciCmdTable[uTbl].lpTable;
count = 0;
do {
str = (LPCWSTR)lmem;
lmem += (strlenW(str) + 1) * sizeof(WCHAR);
eid = *(const WORD*)(lmem + sizeof(DWORD));
lmem += sizeof(DWORD) + sizeof(WORD);
if (eid == MCI_COMMAND_HEAD)
count++;
} while (eid != MCI_END_COMMAND_LIST);
S_MciCmdTable[uTbl].aVerbs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(LPCWSTR));
S_MciCmdTable[uTbl].nVerbs = count;
lmem = S_MciCmdTable[uTbl].lpTable;
count = 0;
do {
str = (LPCWSTR)lmem;
lmem += (strlenW(str) + 1) * sizeof(WCHAR);
eid = *(const WORD*)(lmem + sizeof(DWORD));
lmem += sizeof(DWORD) + sizeof(WORD);
if (eid == MCI_COMMAND_HEAD)
S_MciCmdTable[uTbl].aVerbs[count++] = str;
} while (eid != MCI_END_COMMAND_LIST);
/* assert(count == S_MciCmdTable[uTbl].nVerbs); */
return uTbl;
}
}
return MCI_NO_COMMAND_TABLE;
}
/**************************************************************************
* MCI_DeleteCommandTable [internal]
*/
BOOL MCI_DeleteCommandTable(UINT uTbl, BOOL delete)
{
if (uTbl >= MAX_MCICMDTABLE || !S_MciCmdTable[uTbl].lpTable)
return FALSE;
if (delete) HeapFree(GetProcessHeap(), 0, (void*)S_MciCmdTable[uTbl].lpTable);
S_MciCmdTable[uTbl].lpTable = NULL;
HeapFree(GetProcessHeap(), 0, S_MciCmdTable[uTbl].aVerbs);
S_MciCmdTable[uTbl].aVerbs = 0;
return TRUE;
}
/**************************************************************************
* MCI_UnLoadMciDriver [internal]
*/
static BOOL MCI_UnLoadMciDriver(LPWINE_MCIDRIVER wmd)
{
LPWINE_MCIDRIVER* tmp;
if (!wmd)
return TRUE;
CloseDriver(wmd->hDriver, 0, 0);
if (wmd->dwPrivate != 0)
WARN("Unloading mci driver with non nul dwPrivate field\n");
EnterCriticalSection(&WINMM_IData.cs);
for (tmp = &WINMM_IData.lpMciDrvs; *tmp; tmp = &(*tmp)->lpNext) {
if (*tmp == wmd) {
*tmp = wmd->lpNext;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -