Added parsing & storing of command tables.
Merged some MCI functions from mmsystem.c.
diff --git a/multimedia/mci.c b/multimedia/mci.c
index 3bc823f..70fe73e 100644
--- a/multimedia/mci.c
+++ b/multimedia/mci.c
@@ -6,6 +6,7 @@
* Copyright 1998/1999 Eric Pouech
*/
+#include <stdlib.h>
#include <string.h>
#include "winbase.h"
@@ -17,65 +18,15 @@
#include "digitalv.h"
#include "options.h"
#include "wine/winbase16.h"
+#include "winuser.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(mci)
-static int mciInstalledCount;
-static int mciInstalledListLen;
-static LPSTR lpmciInstallNames = NULL;
+static int MCI_InstalledCount;
+static LPSTR MCI_lpInstallNames = NULL;
-static struct MCI_StringType {
- LPCSTR str;
- UINT type;
- LPVOID lpCmdTable;
-} MCI_StringType_List[] = {
- /* MCI types that are working */
- {"CDAUDIO", MCI_DEVTYPE_CD_AUDIO, NULL},
- {"WAVEAUDIO", MCI_DEVTYPE_WAVEFORM_AUDIO, NULL},
- {"SEQUENCER", MCI_DEVTYPE_SEQUENCER, NULL},
-
- /* MCI types that should be working */
- {"ANIMATION1", MCI_DEVTYPE_ANIMATION, NULL},
- {"MPEGVIDEO", MCI_DEVTYPE_DIGITAL_VIDEO, NULL},
- {"AVIVIDEO", MCI_DEVTYPE_DIGITAL_VIDEO, NULL},
-
- /* MCI types not likely to be supported */
- {"VCR", MCI_DEVTYPE_VCR, NULL},
- {"VIDEODISC", MCI_DEVTYPE_VIDEODISC, NULL},
- {"OVERLAY", MCI_DEVTYPE_OVERLAY, NULL},
- {"DAT", MCI_DEVTYPE_DAT, NULL},
- {"SCANNER", MCI_DEVTYPE_SCANNER, NULL},
-
- {NULL, 0, NULL}
-};
-
-WORD MCI_GetDevTypeFromString(LPCSTR str)
-{
- struct MCI_StringType* mst = MCI_StringType_List;
-
- while (mst->str && strcmp(mst->str, str)) mst++;
- return mst->type;
-}
-
-LPCSTR MCI_GetStringFromDevType(WORD type)
-{
- struct MCI_StringType* mst = MCI_StringType_List;
-
- while (mst->str && mst->type != type) mst++;
- return mst->str;
-}
-
-/* FIXME: comment is obsolete */
-/* The wDevID's returned by wine were originally in the range
- * 0 - (MAXMCIDRIVERS - 1) and used directly as array indices.
- * Unfortunately, ms-windows uses wDevID of zero to indicate
- * errors. Now, multimedia drivers must pass the wDevID through
- * MCI_DevIDToIndex to get an index in that range. An
- * arbitrary value, MCI_MAGIC is added to the wDevID seen
- * by the windows programs.
- */
-
+/* First MCI valid device ID (0 means error) */
#define MCI_MAGIC 0x0001
/**************************************************************************
@@ -86,12 +37,14 @@
LPWINE_MCIDRIVER wmd = 0;
LPWINE_MM_IDATA iData = MULTIMEDIA_GetIData();
+ EnterCriticalSection(&iData->cs);
if (iData) {
for (wmd = iData->lpMciDrv; wmd; wmd = wmd->lpNext) {
if (wmd->wDeviceID == wDevID)
break;
}
}
+ LeaveCriticalSection(&iData->cs);
return wmd;
}
@@ -102,6 +55,7 @@
{
LPWINE_MCIDRIVER wmd;
LPWINE_MM_IDATA iData;
+ UINT ret = 0;
if (!lpstrName)
return 0;
@@ -110,25 +64,33 @@
return MCI_ALL_DEVICE_ID;
if ((iData = MULTIMEDIA_GetIData())) {
+ EnterCriticalSection(&iData->cs);
for (wmd = iData->lpMciDrv; wmd; wmd = wmd->lpNext) {
- if (wmd->lpstrElementName && strcmp(wmd->lpstrElementName, lpstrName) == 0)
- return wmd->wDeviceID;
+ if (wmd->lpstrElementName && strcmp(wmd->lpstrElementName, lpstrName) == 0) {
+ ret = wmd->wDeviceID;
+ break;
+ }
- if (wmd->lpstrDeviceType && strcmp(wmd->lpstrDeviceType, lpstrName) == 0)
- return wmd->wDeviceID;
+ if (wmd->lpstrDeviceType && strcmp(wmd->lpstrDeviceType, lpstrName) == 0) {
+ ret = wmd->wDeviceID;
+ break;
+ }
- if (wmd->lpstrAlias && strcmp(wmd->lpstrAlias, lpstrName) == 0)
- return wmd->wDeviceID;
+ if (wmd->lpstrAlias && strcmp(wmd->lpstrAlias, lpstrName) == 0) {
+ ret = wmd->wDeviceID;
+ break;
+ }
}
+ LeaveCriticalSection(&iData->cs);
}
- return 0;
+ return ret;
}
/**************************************************************************
- * MCI_CommandToString [internal]
+ * MCI_MessageToString [internal]
*/
-const char* MCI_CommandToString(UINT16 wMsg)
+const char* MCI_MessageToString(UINT16 wMsg)
{
static char buffer[100];
@@ -168,17 +130,912 @@
CASE(MCI_UPDATE);
CASE(MCI_WHERE);
CASE(MCI_WINDOW);
+ /* constants for digital video */
+ CASE(MCI_CAPTURE);
+ CASE(MCI_MONITOR);
+ CASE(MCI_RESERVE);
+ CASE(MCI_SETAUDIO);
+ CASE(MCI_SIGNAL);
+ CASE(MCI_SETVIDEO);
+ CASE(MCI_QUALITY);
+ CASE(MCI_LIST);
+ CASE(MCI_UNDO);
+ CASE(MCI_CONFIGURE);
+ CASE(MCI_RESTORE);
+#undef CASE
default:
sprintf(buffer, "MCI_<<%04X>>", wMsg);
return buffer;
}
-#undef CASE
+}
+
+/**************************************************************************
+ * MCI_GetDevTypeFromFileName [internal]
+ */
+static DWORD MCI_GetDevTypeFromFileName(LPCSTR fileName, LPSTR buf, UINT len)
+{
+ LPSTR tmp;
+
+ if ((tmp = strrchr(fileName, '.'))) {
+ GetProfileStringA("mci extensions", tmp + 1, "*", buf, len);
+ if (strcmp(buf, "*") != 0) {
+ return 0;
+ }
+ TRACE("No [mci extensions] entry for '%s' found.\n", tmp);
+ }
+ return MCIERR_EXTENSION_NOT_FOUND;
+}
+
+#define MAX_MCICMDTABLE 20
+#define MCI_COMMAND_TABLE_NOT_LOADED 0xFFFE
+
+typedef struct tagWINE_MCICMDTABLE {
+ HANDLE hMem;
+ UINT uDevType;
+ LPSTR lpTable;
+ /* could also some more info to parse faster the lpTable
+ * an array of indexes to lpTable for all the commands
+ * could be a good start
+ */
+} WINE_MCICMDTABLE, *LPWINE_MCICMDTABLE;
+WINE_MCICMDTABLE S_MciCmdTable[MAX_MCICMDTABLE];
+
+/**************************************************************************
+ * MCI_IsCommandTableValid [internal]
+ */
+static BOOL MCI_IsCommandTableValid(UINT uTbl)
+{
+ LPCSTR lmem, str;
+ DWORD flg;
+ WORD eid;
+ int idx = 0;
+ BOOL inCst = FALSE;
+
+ TRACE("Dumping cmdTbl=%d [hMem=%08x devType=%d]\n",
+ uTbl, S_MciCmdTable[uTbl].hMem, S_MciCmdTable[uTbl].uDevType);
+
+ if (uTbl >= MAX_MCICMDTABLE || !S_MciCmdTable[uTbl].hMem || !S_MciCmdTable[uTbl].lpTable)
+ return FALSE;
+
+ lmem = S_MciCmdTable[uTbl].lpTable;
+ do {
+ do {
+ str = lmem;
+ lmem += strlen(lmem) + 1;
+ flg = *(LPDWORD)lmem;
+ eid = *(LPWORD)(lmem + sizeof(DWORD));
+ lmem += sizeof(DWORD) + sizeof(WORD);
+ idx ++;
+ /* EPP TRACE("cmd='%s' %08lx %04x\n", 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);
+ } while (eid != MCI_END_COMMAND_LIST);
+ return TRUE;
+}
+
+/**************************************************************************
+ * MCI_DumpCommandTable [internal]
+ */
+static BOOL MCI_DumpCommandTable(UINT uTbl)
+{
+ LPCSTR lmem;
+ LPCSTR 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 = lmem;
+ lmem += strlen(lmem) + 1;
+ flg = *(LPDWORD)lmem;
+ eid = *(LPWORD)(lmem + sizeof(DWORD));
+ TRACE("cmd='%s' %08lx %04x\n", str, flg, eid);
+ lmem += sizeof(DWORD) + sizeof(WORD);
+ } while (eid != MCI_END_COMMAND && eid != MCI_END_COMMAND_LIST);
+ TRACE(" => end of command%s\n", (eid == MCI_END_COMMAND_LIST) ? " list" : "");
+ } while (eid != MCI_END_COMMAND_LIST);
+ return TRUE;
+}
+
+static UINT MCI_SetCommandTable(LPWINE_MM_IDATA iData, HANDLE hMem, UINT uDevType);
+
+/**************************************************************************
+ * MCI_GetCommandTable [internal]
+ */
+static UINT MCI_GetCommandTable(LPWINE_MM_IDATA iData, UINT uDevType)
+{
+ UINT uTbl;
+ char buf[32];
+ LPSTR str = NULL;
+
+ /* first look up existing for existing devType */
+ for (uTbl = 0; uTbl < MAX_MCICMDTABLE; uTbl++) {
+ if (S_MciCmdTable[uTbl].hMem && S_MciCmdTable[uTbl].uDevType == uDevType)
+ return uTbl;
+ }
+
+ /* well try to load id */
+ if (uDevType >= MCI_DEVTYPE_FIRST && uDevType <= MCI_DEVTYPE_LAST) {
+ if (LoadStringA(iData->hWinMM32Instance, uDevType, buf, sizeof(buf))) {
+ str = buf;
+ }
+ } else if (uDevType == 0) {
+ str = "CORE";
+ }
+ uTbl = MCI_NO_COMMAND_TABLE;
+ if (str) {
+ HRSRC hRsrc = FindResourceA(iData->hWinMM32Instance, str, (LPCSTR)RT_RCDATAA);
+ HANDLE hMem = 0;
+
+ if (hRsrc) hMem = LoadResource(iData->hWinMM32Instance, hRsrc);
+ if (hMem) {
+ uTbl = MCI_SetCommandTable(iData, hMem, uDevType);
+ } else {
+ WARN("No command table found in resource %04x[%s]\n",
+ iData->hWinMM32Instance, str);
+ }
+ }
+ TRACE("=> %d\n", uTbl);
+ return uTbl;
+}
+
+/**************************************************************************
+ * MCI_SetCommandTable [internal]
+ */
+static UINT MCI_SetCommandTable(LPWINE_MM_IDATA iData, HANDLE hMem,
+ 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;
+ for (uTbl = 0; uTbl < MAX_MCICMDTABLE; uTbl++) {
+ S_MciCmdTable[uTbl].hMem = 0;
+ }
+ MCI_GetCommandTable(iData, 0);
+ }
+
+ for (uTbl = 0; uTbl < MAX_MCICMDTABLE; uTbl++) {
+ if (S_MciCmdTable[uTbl].hMem == 0) {
+ S_MciCmdTable[uTbl].hMem = hMem;
+ S_MciCmdTable[uTbl].uDevType = uDevType;
+ S_MciCmdTable[uTbl].lpTable = LockResource(hMem);
+
+ if (TRACE_ON(mci)) {
+ MCI_DumpCommandTable(uTbl);
+ }
+ return uTbl;
+ }
+
+ }
+
+ return MCI_NO_COMMAND_TABLE;
+}
+
+/**************************************************************************
+ * MCI_DeleteCommandTable [internal]
+ */
+static BOOL MCI_DeleteCommandTable(UINT uTbl)
+{
+ if (uTbl >= MAX_MCICMDTABLE || !S_MciCmdTable[uTbl].hMem)
+ return FALSE;
+
+ FreeResource16(S_MciCmdTable[uTbl].hMem);
+ S_MciCmdTable[uTbl].hMem = 0;
+ return TRUE;
+}
+
+/**************************************************************************
+ * MCI_UnLoadMciDriver [internal]
+ */
+static BOOL MCI_UnLoadMciDriver(LPWINE_MM_IDATA iData, LPWINE_MCIDRIVER wmd)
+{
+ LPWINE_MCIDRIVER* tmp;
+
+ if (!wmd)
+ return TRUE;
+
+ if (wmd->hDrv)
+ CloseDriver(wmd->hDrv, 0, 0);
+
+ if (wmd->dwPrivate != 0)
+ WARN("Unloading mci driver with non nul dwPrivate field\n");
+
+ EnterCriticalSection(&iData->cs);
+ for (tmp = &iData->lpMciDrv; *tmp; tmp = &(*tmp)->lpNext) {
+ if (*tmp == wmd) {
+ *tmp = wmd->lpNext;
+ break;
+ }
+ }
+ LeaveCriticalSection(&iData->cs);
+
+ HeapFree(GetProcessHeap(), 0, wmd->lpstrDeviceType);
+ HeapFree(GetProcessHeap(), 0, wmd->lpstrAlias);
+ HeapFree(GetProcessHeap(), 0, wmd->lpstrElementName);
+
+ HeapFree(GetProcessHeap(), 0, wmd);
+ return TRUE;
+}
+
+/**************************************************************************
+ * MCI_LoadMciDriver [internal]
+ */
+static DWORD MCI_LoadMciDriver(LPWINE_MM_IDATA iData, LPCSTR _strDevTyp,
+ LPWINE_MCIDRIVER* lpwmd)
+{
+ LPSTR strDevTyp = CharUpperA(HEAP_strdupA(GetProcessHeap(), 0, _strDevTyp));
+ LPWINE_MCIDRIVER wmd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wmd));
+ MCI_OPEN_DRIVER_PARMSA modp;
+ DWORD dwRet = 0;
+ HDRVR hDrv = 0;
+
+ if (!wmd || !strDevTyp) {
+ dwRet = MCIERR_OUT_OF_MEMORY;
+ goto errCleanUp;
+ }
+
+ EnterCriticalSection(&iData->cs);
+ /* wmd must be inserted in list before sending opening the driver, coz' it
+ * may want to lookup at wDevID
+ */
+ wmd->lpNext = iData->lpMciDrv;
+ iData->lpMciDrv = wmd;
+
+ for (modp.wDeviceID = MCI_MAGIC;
+ MCI_GetDriver(modp.wDeviceID) != 0;
+ modp.wDeviceID++);
+
+ wmd->wDeviceID = modp.wDeviceID;
+ wmd->lpfnYieldProc = MCI_DefYieldProc;
+ wmd->dwYieldData = VK_CANCEL;
+ wmd->hCreatorTask = GetCurrentTask();
+
+ LeaveCriticalSection(&iData->cs);
+
+ TRACE("wDevID=%04X \n", modp.wDeviceID);
+
+ modp.lpstrParams = NULL;
+
+ hDrv = OpenDriverA(strDevTyp, "mci", (LPARAM)&modp);
+
+ if (!hDrv) {
+ FIXME("Couldn't load driver for type %s.\n", strDevTyp);
+ dwRet = MCIERR_DEVICE_NOT_INSTALLED;
+ goto errCleanUp;
+ }
+
+ /* FIXME: should also check that module's description is of the form
+ * MODULENAME:[MCI] comment
+ */
+
+ wmd->hDrv = hDrv;
+ /* some drivers will return 0x0000FFFF, some others 0xFFFFFFFF */
+ wmd->uSpecificCmdTable = LOWORD(modp.wCustomCommandTable);
+ wmd->uTypeCmdTable = MCI_COMMAND_TABLE_NOT_LOADED;
+
+ TRACE("Loaded driver %u (%s), type is %d, cmdTable=%08x\n",
+ hDrv, 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(iData, wmd);
+ HeapFree(GetProcessHeap(), 0, strDevTyp);
+ *lpwmd = 0;
+ return dwRet;
+}
+
+/**************************************************************************
+ * MCI_FinishOpen [internal]
+ */
+static DWORD MCI_FinishOpen(LPWINE_MCIDRIVER wmd, LPMCI_OPEN_PARMSA lpParms,
+ DWORD dwParam)
+{
+ if (dwParam & MCI_OPEN_ELEMENT)
+ wmd->lpstrElementName = HEAP_strdupA(GetProcessHeap(), 0,
+ lpParms->lpstrElementName);
+
+ if (dwParam & MCI_OPEN_ALIAS)
+ wmd->lpstrAlias = HEAP_strdupA(GetProcessHeap(), 0, lpParms->lpstrAlias);
+
+ lpParms->wDeviceID = wmd->wDeviceID;
+
+ return MCI_SendCommandFrom32(wmd->wDeviceID, MCI_OPEN_DRIVER, dwParam,
+ (DWORD)lpParms);
+}
+
+/**************************************************************************
+ * MCI_FindCommand [internal]
+ */
+static LPCSTR MCI_FindCommand(UINT uTbl, LPCSTR verb)
+{
+ LPCSTR lmem, str;
+ DWORD flg;
+ WORD eid;
+
+ if (uTbl >= MAX_MCICMDTABLE || S_MciCmdTable[uTbl].hMem == 0)
+ return NULL;
+
+ lmem = S_MciCmdTable[uTbl].lpTable;
+
+ do {
+ do {
+ str = lmem;
+ lmem += strlen(lmem) + 1;
+ flg = *(LPDWORD)lmem;
+ eid = *(LPWORD)(lmem + sizeof(DWORD));
+ lmem += sizeof(DWORD) + sizeof(WORD);
+ if (eid == MCI_COMMAND_HEAD && strcmp(str, verb) == 0)
+ return str;
+ } while (eid != MCI_END_COMMAND_LIST);
+ } while (eid != MCI_END_COMMAND_LIST);
+ return NULL;
+}
+
+/**************************************************************************
+ * MCI_GetReturnType [internal]
+ */
+static DWORD MCI_GetReturnType(LPCSTR lpCmd)
+{
+ lpCmd += strlen(lpCmd) + 1 + sizeof(DWORD) + sizeof(WORD);
+ if (*lpCmd == '\0' && *(LPWORD)(lpCmd + 1 + sizeof(DWORD)) == MCI_RETURN) {
+ return *(LPDWORD)(lpCmd + 1);
+ }
+ return 0L;
+}
+
+/**************************************************************************
+ * MCI_GetMessage [internal]
+ */
+static WORD MCI_GetMessage(LPCSTR lpCmd)
+{
+ return (WORD)*(LPDWORD)(lpCmd + strlen(lpCmd) + 1);
+}
+
+/**************************************************************************
+ * MCI_GetDWord [internal]
+ */
+static BOOL MCI_GetDWord(LPDWORD data, LPSTR* ptr)
+{
+ DWORD val;
+ LPSTR ret;
+
+ val = strtoul(*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(LPSTR* str, LPSTR* args)
+{
+ LPSTR ptr = *args;
+
+ /* see if we have a quoted string */
+ if (*ptr == '"') {
+ ptr = strchr(*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 = strchr(ptr, ' ');
+
+ if (ptr) {
+ *ptr++ = '\0';
+ } else {
+ ptr = *args + strlen(*args);
+ }
+ *str = *args;
+ }
+
+ *args = ptr;
+ return 0;
+}
+
+#define MCI_DATA_SIZE 16
+
+/**************************************************************************
+ * MCI_ParseOptArgs [internal]
+ */
+static DWORD MCI_ParseOptArgs(LPDWORD data, int _offset, LPCSTR lpCmd,
+ LPSTR args, LPDWORD dwFlags)
+{
+ int len, offset;
+ LPCSTR lmem, str;
+ DWORD dwRet, flg, cflg = 0;
+ WORD eid;
+ BOOL inCst, found;
+
+ /* loop on arguments */
+ while (*args) {
+ lmem = lpCmd;
+ found = inCst = FALSE;
+ offset = _offset;
+ TRACE("args='%s' offset=%d\n", args, offset);
+
+ do { /* loop on options for command table for the requested verb */
+ str = lmem;
+ lmem += (len = strlen(lmem)) + 1;
+ flg = *(LPDWORD)lmem;
+ eid = *(LPWORD)(lmem + sizeof(DWORD));
+ lmem += sizeof(DWORD) + sizeof(WORD);
+/* EPP TRACE("\tcmd='%s' inCst=%s\n", str, inCst ? "Y" : "N"); */
+
+ 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 (strncasecmp(args, str, len) == 0 &&
+ (args[len] == 0 || args[len] == ' ')) {
+ /* store good values into data[] */
+ args += len;
+ if (*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", args);
+ return MCIERR_BAD_INTEGER;
+ }
+ break;
+ case MCI_STRING:
+ *dwFlags |= flg;
+ if ((dwRet = MCI_GetString((LPSTR*)&data[offset], &args)))
+ return dwRet;
+ break;
+ default: ERR("oops");
+ }
+ /* exit inside while loop */
+ 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");
+ }
+ }
+ } while (eid != MCI_END_COMMAND);
+ if (!found) {
+ TRACE("Optarg '%s' not found\n", 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(LPWINE_MM_IDATA iData, DWORD dwRet, LPWINE_MCIDRIVER wmd,
+ LPCSTR lpCmd, LPDWORD data, LPSTR lpstrRet, UINT uRetLen)
+{
+ if (lpstrRet) {
+ switch (MCI_GetReturnType(lpCmd)) {
+ case 0: /* nothing to return */
+ break;
+ case MCI_INTEGER:
+ switch (dwRet & 0xFFFF0000ul) {
+ case 0:
+ case MCI_INTEGER_RETURNED:
+ snprintf(lpstrRet, uRetLen, "%d", data[1]);
+ break;
+ case MCI_RESOURCE_RETURNED:
+ /* return string which ID is HIWORD(data[1]),
+ * string is loaded from mmsystem.dll */
+ LoadStringA(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 */
+ LoadStringA(wmd->hDrv, HIWORD(data[1]), lpstrRet, uRetLen);
+ break;
+ case MCI_COLONIZED3_RETURN:
+ snprintf(lpstrRet, uRetLen, "%d:%d:%d",
+ LOBYTE(LOWORD(data[1])), HIBYTE(LOWORD(data[1])),
+ LOBYTE(HIWORD(data[1])));
+ break;
+ case MCI_COLONIZED4_RETURN:
+ snprintf(lpstrRet, uRetLen, "%d:%d:%d:%d",
+ 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;
+ snprintf(lpstrRet, uRetLen, "%d", 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));
+ snprintf(lpstrRet, uRetLen, "%d %d %d %d",
+ data[1], data[2], data[3], data[4]);
+ break;
+ default: ERR("oops\n");
+ }
+ }
+ return LOWORD(dwRet);
+}
+
+/**************************************************************************
+ * mciSendStringA [MMSYSTEM.702][WINMM.51]
+ */
+DWORD WINAPI mciSendStringA(LPCSTR lpstrCommand, LPSTR lpstrRet,
+ UINT uRetLen, HWND hwndCallback)
+{
+ LPSTR verb, dev, args;
+ LPWINE_MCIDRIVER wmd = 0;
+ DWORD dwFlags = 0, dwRet = 0;
+ int offset = 0;
+ DWORD data[MCI_DATA_SIZE];
+ LPCSTR lpCmd = 0;
+ LPWINE_MM_IDATA iData;
+
+ TRACE("('%s', %p, %d, %X)\n", lpstrCommand, lpstrRet, uRetLen, hwndCallback);
+
+ if (!(iData = MULTIMEDIA_GetIData()))
+ return MCIERR_INTERNAL;
+
+ /* format is <command> <device> <optargs> */
+ if (!(verb = HEAP_strdupA(GetProcessHeap(), 0, lpstrCommand)))
+ return MCIERR_OUT_OF_MEMORY;
+
+ memset(data, 0, sizeof(data));
+
+ if (!(args = strchr(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 (!strcasecmp(dev, "new")) {
+ FIXME("'new': NIY as device name\n");
+ dwRet = MCIERR_MISSING_DEVICE_NAME;
+ goto errCleanUp;
+ }
+
+ /* otherwise, try to grab devType from open */
+ if (!strcmp(verb, "open")) {
+ LPSTR devType, tmp;
+
+ if ((devType = strchr(dev, '!')) != NULL) {
+ *devType++ = '\0';
+ tmp = devType; devType = dev; dev = tmp;
+
+ dwFlags |= MCI_OPEN_TYPE;
+ data[2] = (DWORD)devType;
+ devType = CharUpperA(HEAP_strdupA(GetProcessHeap(), 0, devType));
+ } else {
+ if ((devType = strstr(args, "type ")) != NULL) {
+ devType += 5;
+ tmp = strchr(devType, ' ');
+ if (tmp) *tmp = '\0';
+ devType = CharUpperA(HEAP_strdupA(GetProcessHeap(), 0, devType));
+ if (tmp) *tmp = ' ';
+ /* dwFlags and data[2] will be correctly set in ParseOpt loop */
+ } else {
+ char buf[32];
+ if ((dwRet = MCI_GetDevTypeFromFileName(dev, buf, sizeof(buf))))
+ goto errCleanUp;
+
+ devType = CharUpperA(HEAP_strdupA(GetProcessHeap(), 0, buf));
+ }
+ dwFlags |= MCI_OPEN_ELEMENT;
+ data[3] = (DWORD)dev;
+ }
+ dwRet = MCI_LoadMciDriver(iData, devType, &wmd);
+ HeapFree(GetProcessHeap(), 0, devType);
+ if (dwRet) {
+ MCI_UnLoadMciDriver(iData, wmd);
+ goto errCleanUp;
+ }
+ } else {
+ wmd = MCI_GetDriver(mciGetDeviceIDA(dev));
+ if (!wmd)
+ FIXME("Oooch: couldn't find driver for '%s'; automatic open not implemented\n", dev);
+ }
+
+ /* get the verb in the different command tables */
+ /* try the device specific command table */
+ if (wmd) lpCmd = MCI_FindCommand(wmd->uSpecificCmdTable, verb);
+ /* try the type specific command table */
+ if (!lpCmd) {
+ if (wmd && wmd->uTypeCmdTable == MCI_COMMAND_TABLE_NOT_LOADED)
+ wmd->uTypeCmdTable = MCI_GetCommandTable(iData, wmd->wType);
+ if (wmd && wmd->uTypeCmdTable != MCI_NO_COMMAND_TABLE)
+ lpCmd = MCI_FindCommand(wmd->uTypeCmdTable, verb);
+ }
+ /* try core command table */
+ if (!lpCmd) lpCmd = MCI_FindCommand(MCI_GetCommandTable(iData, 0), verb);
+
+ if (!lpCmd) {
+ TRACE("Command '%s' not found!\n", 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 (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", verb, dev, offset);
+
+ if ((dwRet = MCI_ParseOptArgs(data, offset, lpCmd, args, &dwFlags)))
+ goto errCleanUp;
+
+ if (lpstrRet && uRetLen) *lpstrRet = '\0';
+
+#define STR_OF(_x) (((_x)&0xFF000000)?(char*)(_x):"?")
+ 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], STR_OF(data[0]), data[1], STR_OF(data[1]),
+ data[2], STR_OF(data[2]), data[3], STR_OF(data[3]),
+ data[4], STR_OF(data[4]), data[5], STR_OF(data[5]));
+#undef STR_OF
+
+ if (strcmp(verb, "open") == 0) {
+ if ((dwRet = MCI_FinishOpen(wmd, (LPMCI_OPEN_PARMSA)data, dwFlags)))
+ MCI_UnLoadMciDriver(iData, 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, lpstrRet);
+ if (dwRet) goto errCleanUp;
+
+ dwRet = MCI_HandleReturnValues(iData, dwRet, wmd, lpCmd, data, lpstrRet, uRetLen);
+ TRACE("=> 2/ %lx (%s)\n", dwRet, lpstrRet);
+
+errCleanUp:
+ HeapFree(GetProcessHeap(), 0, verb);
+ return dwRet;
+}
+
+/**************************************************************************
+ * mciSendStringW [WINMM.52]
+ */
+DWORD WINAPI mciSendStringW(LPCWSTR lpwstrCommand, LPSTR lpstrRet,
+ UINT uRetLen, HWND hwndCallback)
+{
+ LPSTR lpstrCommand;
+ UINT ret;
+
+ /* FIXME: is there something to do with lpstrReturnString ? */
+ lpstrCommand = HEAP_strdupWtoA(GetProcessHeap(), 0, lpwstrCommand);
+ ret = mciSendStringA(lpstrCommand, lpstrRet, uRetLen, hwndCallback);
+ HeapFree(GetProcessHeap(), 0, lpstrCommand);
+ return ret;
+}
+
+/**************************************************************************
+ * mciSendString16 [MMSYSTEM.702]
+ */
+DWORD WINAPI mciSendString16(LPCSTR lpstrCommand, LPSTR lpstrRet,
+ UINT16 uRetLen, HWND16 hwndCallback)
+{
+ return mciSendStringA(lpstrCommand, lpstrRet, uRetLen, hwndCallback);
+}
+
+/**************************************************************************
+ * mciExecute [WINMM.38]
+ */
+DWORD WINAPI mciExecute(LPCSTR lpstrCommand)
+{
+ char strRet[256];
+ DWORD ret;
+
+ TRACE("(%s)!\n", lpstrCommand);
+
+ ret = mciSendString16(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 0;
+}
+
+/**************************************************************************
+ * mciLoadCommandResource [MMSYSTEM.705]
+ */
+UINT16 WINAPI mciLoadCommandResource16(HANDLE16 hInst, LPCSTR resname, UINT16 type)
+{
+ HRSRC hRsrc = 0;
+ HGLOBAL hMem;
+ UINT16 ret = MCI_NO_COMMAND_TABLE;
+ LPWINE_MM_IDATA iData = MULTIMEDIA_GetIData();
+
+ TRACE("(%04x, %s, %d)!\n", hInst, resname, type);
+
+ if (!iData)
+ return ret;
+
+ /* if file exists "resname.mci", 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) {
+ 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);
+ }
+ }
+ if (!(hRsrc = FindResourceA(hInst, resname, (LPCSTR)RT_RCDATAA))) {
+ WARN("No command table found in resource\n");
+ } else if ((hMem = LoadResource(hInst, hRsrc))) {
+ ret = MCI_SetCommandTable(iData, hMem, type);
+ } else {
+ WARN("Couldn't load resource.\n");
+ }
+ TRACE("=> %04x\n", ret);
+ return ret;
+}
+
+/**************************************************************************
+ * mciFreeCommandResource [MMSYSTEM.713]
+ */
+BOOL16 WINAPI mciFreeCommandResource16(UINT16 uTable)
+{
+ TRACE("(%04x)!\n", uTable);
+
+ return MCI_DeleteCommandTable(uTable);
+}
+
+/**************************************************************************
+ * mciLoadCommandResource [WINMM.48]
+ *
+ * Strangely, this function only exists as an UNICODE one.
+ */
+UINT WINAPI mciLoadCommandResource(HINSTANCE hinst, LPCWSTR resNameW, UINT type)
+{
+ LPSTR resNameA;
+ UINT ret;
+
+ TRACE("(%04x, %s, %d)!\n", hinst, debugstr_w(resNameW), type);
+
+ resNameA = HEAP_strdupWtoA(GetProcessHeap(), 0, resNameW);
+ ret = mciLoadCommandResource16(hinst, resNameA, type);
+ HeapFree(GetProcessHeap(), 0, resNameA);
+ return ret;
+}
+
+/**************************************************************************
+ * mciFreeCommandResource [WINMM.39]
+ */
+BOOL WINAPI mciFreeCommandResource(UINT uTable)
+{
+ TRACE("(%08x)!\n", uTable);
+
+ return mciFreeCommandResource16(uTable);
}
/**************************************************************************
* MCI_MapMsg16To32A [internal]
*/
-MCI_MapType MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
+static MCI_MapType MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
{
if (*lParam == 0)
return MCI_MAP_OK;
@@ -338,7 +1195,7 @@
return MCI_MAP_OK;
default:
- WARN("Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
+ WARN("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
}
return MCI_MAP_MSGERROR;
}
@@ -346,7 +1203,7 @@
/**************************************************************************
* MCI_UnMapMsg16To32A [internal]
*/
-MCI_MapType MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
+static MCI_MapType MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
{
switch (wMsg) {
/* case MCI_CAPTURE */
@@ -420,7 +1277,7 @@
FIXME("This is a hack\n");
return MCI_MAP_OK;
default:
- FIXME("Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
+ FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
}
return MCI_MAP_MSGERROR;
}
@@ -557,7 +1414,7 @@
*
* Map a 32-A bit MCI message to a 16 bit MCI message.
*/
-MCI_MapType MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
+static MCI_MapType MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
{
int size;
BOOLEAN keep = FALSE;
@@ -831,7 +1688,7 @@
return MCI_MAP_PASS;
default:
- WARN("Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
+ WARN("Don't know how to map msg=%s\n", MCI_MessageToString(wMsg));
return MCI_MAP_MSGERROR;
}
return MCI_MsgMapper32To16_Create((void**)lParam, size, map, keep);
@@ -840,7 +1697,7 @@
/**************************************************************************
* MCI_UnMapMsg32ATo16 [internal]
*/
-MCI_MapType MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
+static MCI_MapType MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
{
int size = 0;
BOOLEAN kept = FALSE; /* there is no need to compute size when kept is FALSE */
@@ -1015,7 +1872,7 @@
FIXME("This is a hack\n");
return MCI_MAP_PASS;
default:
- FIXME("Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
+ FIXME("Map/Unmap internal error on msg=%s\n", MCI_MessageToString(wMsg));
return MCI_MAP_MSGERROR;
}
return MCI_MsgMapper32To16_Destroy((void*)lParam, size, map, kept);
@@ -1039,17 +1896,17 @@
switch (res = MCI_MapMsg32ATo16(wmd->wType, wMsg, dwParam1, &dwParam2)) {
case MCI_MAP_MSGERROR:
- TRACE("Not handled yet (%s)\n", MCI_CommandToString(wMsg));
+ TRACE("Not handled yet (%s)\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_DRIVER_INTERNAL;
break;
case MCI_MAP_NOMEM:
- TRACE("Problem mapping msg=%s from 32a to 16\n", MCI_CommandToString(wMsg));
+ TRACE("Problem mapping msg=%s from 32a to 16\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_OUT_OF_MEMORY;
break;
case MCI_MAP_OK:
case MCI_MAP_OKMEM:
dwRet = SendDriverMessage16(wmd->hDrv, wMsg, dwParam1, dwParam2);
- if (res == MCI_MAP_OKMEM)
+ if (res == MCI_MAP_OKMEM)
MCI_UnMapMsg32ATo16(wmd->wType, wMsg, dwParam1, dwParam2);
break;
case MCI_MAP_PASS:
@@ -1089,11 +1946,11 @@
case WINE_DI_TYPE_32:
switch (res = MCI_MapMsg16To32A(wmd->wType, wMsg, &dwParam2)) {
case MCI_MAP_MSGERROR:
- TRACE("Not handled yet (%s)\n", MCI_CommandToString(wMsg));
+ TRACE("Not handled yet (%s)\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_DRIVER_INTERNAL;
break;
case MCI_MAP_NOMEM:
- TRACE("Problem mapping msg=%s from 16 to 32a\n", MCI_CommandToString(wMsg));
+ TRACE("Problem mapping msg=%s from 16 to 32a\n", MCI_MessageToString(wMsg));
dwRet = MCIERR_OUT_OF_MEMORY;
break;
case MCI_MAP_OK:
@@ -1118,14 +1975,10 @@
/**************************************************************************
* MCI_Open [internal]
*/
-DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms)
+static DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms)
{
char strDevTyp[128];
- UINT16 uDevType = 0;
- UINT16 wDevID = MCI_MAGIC;
DWORD dwRet;
- HDRVR hDrv;
- MCI_OPEN_DRIVER_PARMSA modp;
LPWINE_MCIDRIVER wmd;
LPWINE_MM_IDATA iData;
@@ -1142,167 +1995,99 @@
}
#undef WINE_MCI_SUPP
- wmd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wmd));
- if (!wmd) {
- return MCIERR_OUT_OF_MEMORY;
- }
-
- while (MCI_GetDriver(wDevID) != 0) {
- wDevID++;
- }
- TRACE("wDevID=%04X \n", wDevID);
-
strDevTyp[0] = 0;
if (dwParam & MCI_OPEN_ELEMENT) {
- char* t;
-
TRACE("lpstrElementName='%s'\n", 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;
}
- t = strrchr(lpParms->lpstrElementName, '.');
- if (t) {
- GetProfileStringA("mci extensions", t+1, "*", strDevTyp, sizeof(strDevTyp));
- if (strcmp(strDevTyp, "*") == 0) {
- TRACE("No [mci extensions] entry for %s found.\n", t);
+ if (MCI_GetDevTypeFromFileName(lpParms->lpstrElementName, strDevTyp, sizeof(strDevTyp))) {
+ if (GetDriveTypeA(lpParms->lpstrElementName) == DRIVE_CDROM) {
+ /* FIXME: this will not work if several CDROM drives are installed on the machine */
+ strcpy(strDevTyp, "CDAUDIO");
+ } else {
dwRet = MCIERR_EXTENSION_NOT_FOUND;
goto errCleanUp;
}
- TRACE("Extension %s is mapped to type %s\n", t, strDevTyp);
-
- wmd->lpstrElementName = HEAP_strdupA(GetProcessHeap(), 0, lpParms->lpstrElementName);
- } else if (GetDriveTypeA(lpParms->lpstrElementName) == DRIVE_CDROM) {
- /* FIXME: this will not work if several CDROM drives are installed on the machine */
- strcpy(strDevTyp, "CDAUDIO");
- } else {
- dwRet = MCIERR_EXTENSION_NOT_FOUND;
- goto errCleanUp;
}
}
- if (dwParam & MCI_OPEN_ALIAS) {
- TRACE("Alias='%s' !\n", lpParms->lpstrAlias);
-
- if (!lpParms->lpstrAlias) {
- dwRet = MCIERR_NULL_PARAMETER_BLOCK;
- goto errCleanUp;
- }
-
- wmd->lpstrAlias = HEAP_strdupA(GetProcessHeap(), 0, lpParms->lpstrAlias);
- /* mplayer does allocate alias to CDAUDIO */
- }
-
if (dwParam & MCI_OPEN_TYPE) {
if (dwParam & MCI_OPEN_TYPE_ID) {
-#if 0
- TRACE("Dev=%08lx!\n", (DWORD)lpParms->lpstrDeviceType);
- uDevType = LOWORD((DWORD)lpParms->lpstrDeviceType);
- wmd->lpstrDeviceType = lpParms->lpstrDeviceType;
-#endif
- if (LOWORD((DWORD)lpParms->lpstrDeviceType) != MCI_DEVTYPE_CD_AUDIO) {
- FIXME("MCI_OPEN_TYPE_ID is no longer properly supported\n");
+ WORD uDevType = LOWORD((DWORD)lpParms->lpstrDeviceType);
+
+ if (uDevType < MCI_DEVTYPE_FIRST ||
+ uDevType > MCI_DEVTYPE_LAST ||
+ !LoadStringA(iData->hWinMM32Instance, uDevType, strDevTyp, sizeof(strDevTyp))) {
+ dwRet = MCIERR_BAD_INTEGER;
+ goto errCleanUp;
}
- strcpy(strDevTyp, "CDAUDIO");
} else {
- if (lpParms->lpstrDeviceType == NULL)
- return MCIERR_NULL_PARAMETER_BLOCK;
- TRACE("Dev='%s' !\n", lpParms->lpstrDeviceType);
+ if (lpParms->lpstrDeviceType == NULL) {
+ dwRet = MCIERR_NULL_PARAMETER_BLOCK;
+ goto errCleanUp;
+ }
strcpy(strDevTyp, lpParms->lpstrDeviceType);
}
+ TRACE("devType='%s' !\n", strDevTyp);
}
if (strDevTyp[0] == 0) {
FIXME("Couldn't load driver\n");
- dwRet = MCIERR_DRIVER_INTERNAL;
+ dwRet = MCIERR_INVALID_DEVICE_NAME;
goto errCleanUp;
}
- CharUpperA(strDevTyp);
-
- modp.wDeviceID = wDevID;
- modp.lpstrParams = NULL;
-
- wmd->wDeviceID = wDevID;
- wmd->lpfnYieldProc = MCI_DefYieldProc;
- wmd->dwYieldData = VK_CANCEL;
- wmd->hCreatorTask = GetCurrentTask();
+ if (dwParam & MCI_OPEN_ALIAS) {
+ TRACE("Alias='%s' !\n", lpParms->lpstrAlias);
+ if (!lpParms->lpstrAlias) {
+ dwRet = MCIERR_NULL_PARAMETER_BLOCK;
+ goto errCleanUp;
+ }
+ }
- /* wmd must be inserted in list before sending opening the driver, coz' it
- * may want to lookup at wDevID
- */
- wmd->lpNext = iData->lpMciDrv;
- iData->lpMciDrv = wmd;
-
- hDrv = OpenDriverA(strDevTyp, "mci", (LPARAM)&modp);
-
- if (!hDrv) {
- FIXME("Couldn't load driver for type %s.\n", strDevTyp);
- dwRet = MCIERR_DEVICE_NOT_INSTALLED;
+ if ((dwRet = MCI_LoadMciDriver(iData, strDevTyp, &wmd))) {
goto errCleanUp;
- }
- uDevType = modp.wType;
- wmd->hDrv = hDrv;
-
- TRACE("Loaded driver %u (%s), type is %d\n", hDrv, strDevTyp, uDevType);
-
- wmd->lpstrDeviceType = HEAP_strdupA(GetProcessHeap(), 0, strDevTyp);
- wmd->wType = uDevType;
+ }
- lpParms->wDeviceID = wDevID;
-
- TRACE("mcidev=%d, uDevType=%04X wDeviceID=%04X !\n",
- wDevID, uDevType, lpParms->wDeviceID);
-
- dwRet = MCI_SendCommandFrom32(wDevID, MCI_OPEN_DRIVER, dwParam, (DWORD)lpParms);
-
- if (dwRet) {
+ if ((dwRet = MCI_FinishOpen(wmd, lpParms, dwParam))) {
TRACE("Failed to open driver (MCI_OPEN_DRIVER msg) [%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", wDevID, lpParms->wDeviceID, dwRet);
+ TRACE("wDevID=%04X wDeviceID=%d dwRet=%ld\n", wmd->wDeviceID, lpParms->wDeviceID, dwRet);
if (dwParam & MCI_NOTIFY)
- mciDriverNotify16(lpParms->dwCallback, wDevID, MCI_NOTIFY_SUCCESSFUL);
+ mciDriverNotify16(lpParms->dwCallback, wmd->wDeviceID, MCI_NOTIFY_SUCCESSFUL);
return 0;
errCleanUp:
- if (wmd->hDrv)
- CloseDriver(wmd->hDrv, 0, 0);
-
- /* remove wmd from list if it has been inserted */
- {
- LPWINE_MCIDRIVER* tmp;
- for (tmp = &iData->lpMciDrv; *tmp; tmp = &(*tmp)->lpNext) {
- if (*tmp == wmd) {
- *tmp = wmd->lpNext;
- break;
- }
- }
- }
- HeapFree(GetProcessHeap(), 0, wmd->lpstrDeviceType);
- HeapFree(GetProcessHeap(), 0, wmd->lpstrElementName);
- HeapFree(GetProcessHeap(), 0, wmd->lpstrAlias);
- HeapFree(GetProcessHeap(), 0, wmd);
+ MCI_UnLoadMciDriver(iData, wmd);
+
if (dwParam & MCI_NOTIFY)
- mciDriverNotify16(lpParms->dwCallback, wDevID, MCI_NOTIFY_FAILURE);
+ mciDriverNotify16(lpParms->dwCallback, 0, MCI_NOTIFY_FAILURE);
return dwRet;
}
/**************************************************************************
* MCI_Close [internal]
*/
-DWORD MCI_Close(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
+static DWORD MCI_Close(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
{
DWORD dwRet;
LPWINE_MCIDRIVER wmd;
- LPWINE_MCIDRIVER* tmp;
LPWINE_MM_IDATA iData;
TRACE("(%04x, %08lX, %p)\n", wDevID, dwParam, lpParms);
@@ -1313,6 +2098,7 @@
if (wDevID == MCI_ALL_DEVICE_ID) {
LPWINE_MCIDRIVER next;
+ EnterCriticalSection(&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 ?
@@ -1322,6 +2108,7 @@
MCI_Close(wmd->wDeviceID, dwParam, lpParms);
wmd = next;
}
+ LeaveCriticalSection(&iData->cs);
return 0;
}
@@ -1331,26 +2118,7 @@
dwRet = MCI_SendCommandFrom32(wDevID, MCI_CLOSE_DRIVER, dwParam, (DWORD)lpParms);
- if (wmd->hDrv) {
- CloseDriver(wmd->hDrv, 0, 0);
- }
-
- if (wmd->dwPrivate != 0) {
- WARN("Closing mci driver with non nul dwPrivate field\n");
- }
-
- for (tmp = &iData->lpMciDrv; *tmp; tmp = &(*tmp)->lpNext) {
- if (*tmp == wmd) {
- *tmp = wmd->lpNext;
- break;
- }
- }
-
- HeapFree(GetProcessHeap(), 0, wmd->lpstrDeviceType);
- HeapFree(GetProcessHeap(), 0, wmd->lpstrAlias);
- HeapFree(GetProcessHeap(), 0, wmd->lpstrElementName);
-
- HeapFree(GetProcessHeap(), 0, wmd);
+ MCI_UnLoadMciDriver(iData, wmd);
if (dwParam & MCI_NOTIFY)
mciDriverNotify16(lpParms->dwCallback, wDevID,
@@ -1364,14 +2132,17 @@
*/
DWORD MCI_WriteString(LPSTR lpDstStr, DWORD dstSize, LPCSTR lpSrcStr)
{
- DWORD ret;
+ DWORD ret = 0;
- if (dstSize <= strlen(lpSrcStr)) {
- lstrcpynA(lpDstStr, lpSrcStr, dstSize - 1);
- ret = MCIERR_PARAM_OVERFLOW;
+ if (lpSrcStr) {
+ if (dstSize <= strlen(lpSrcStr)) {
+ lstrcpynA(lpDstStr, lpSrcStr, dstSize - 1);
+ ret = MCIERR_PARAM_OVERFLOW;
+ } else {
+ strcpy(lpDstStr, lpSrcStr);
+ }
} else {
- strcpy(lpDstStr, lpSrcStr);
- ret = 0;
+ *lpDstStr = 0;
}
return ret;
}
@@ -1379,7 +2150,7 @@
/**************************************************************************
* MCI_Sysinfo [internal]
*/
-DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSA lpParms)
+static DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSA lpParms)
{
DWORD ret = MCIERR_INVALID_DEVICE_ID;
LPWINE_MCIDRIVER wmd;
@@ -1396,25 +2167,32 @@
{
DWORD cnt = 0;
- if (lpParms->wDeviceType < MCI_DEVTYPE_FIRST || lpParms->wDeviceType > MCI_DEVTYPE_LAST) {
+ 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(&iData->cs);
for (wmd = iData->lpMciDrv; wmd; wmd = wmd->lpNext) {
cnt++;
}
+ LeaveCriticalSection(&iData->cs);
} else {
TRACE("MCI_SYSINFO_QUANTITY: # of installed MCI drivers\n");
- cnt = mciInstalledCount;
+ cnt = MCI_InstalledCount;
}
} else {
if (dwFlags & MCI_SYSINFO_OPEN) {
- TRACE("MCI_SYSINFO_QUANTITY: # of open MCI drivers of type %u\n", lpParms->wDeviceType);
+ TRACE("MCI_SYSINFO_QUANTITY: # of open MCI drivers of type %u\n",
+ lpParms->wDeviceType);
+ EnterCriticalSection(&iData->cs);
for (wmd = iData->lpMciDrv; wmd; wmd = wmd->lpNext) {
if (wmd->wType == lpParms->wDeviceType)
cnt++;
}
+ LeaveCriticalSection(&iData->cs);
} else {
- TRACE("MCI_SYSINFO_QUANTITY: # of installed MCI drivers of type %u\n", lpParms->wDeviceType);
+ 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;
}
@@ -1422,12 +2200,13 @@
*(DWORD*)lpParms->lpstrReturn = cnt;
}
TRACE("(%ld) => '%ld'\n", lpParms->dwNumber, *(DWORD*)lpParms->lpstrReturn);
- ret = 0;
+ 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);
+ ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize,
+ wmd->lpstrDeviceType);
} else {
*lpParms->lpstrReturn = 0;
ret = MCIERR_INVALID_DEVICE_ID;
@@ -1439,11 +2218,11 @@
if (dwFlags & MCI_SYSINFO_OPEN) {
FIXME("Don't handle MCI_SYSINFO_NAME|MCI_SYSINFO_OPEN (yet)\n");
ret = MCIERR_UNRECOGNIZED_COMMAND;
- } else if (lpParms->dwNumber > mciInstalledCount) {
+ } else if (lpParms->dwNumber > MCI_InstalledCount) {
ret = MCIERR_OUTOFRANGE;
} else {
DWORD count = lpParms->dwNumber;
- LPSTR ptr = lpmciInstallNames;
+ LPSTR ptr = MCI_lpInstallNames;
while (--count > 0) ptr += strlen(ptr) + 1;
ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize, ptr);
@@ -1460,7 +2239,7 @@
/**************************************************************************
* MCI_Break [internal]
*/
-DWORD MCI_Break(UINT wDevID, DWORD dwFlags, LPMCI_BREAK_PARMS lpParms)
+static DWORD MCI_Break(UINT wDevID, DWORD dwFlags, LPMCI_BREAK_PARMS lpParms)
{
DWORD dwRet = 0;
@@ -1473,6 +2252,96 @@
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_PARMSA)dwParam2);
+ } else {
+ switch (MCI_MapMsg16To32A(0, wMsg, &dwParam2)) {
+ case MCI_MAP_OK:
+ case MCI_MAP_OKMEM:
+ dwRet = MCI_Open(dwParam1, (LPMCI_OPEN_PARMSA)dwParam2);
+ MCI_UnMapMsg16To32A(0, wMsg, 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 {
+ switch (MCI_MapMsg16To32A(0, wMsg, &dwParam2)) {
+ case MCI_MAP_OK:
+ case MCI_MAP_OKMEM:
+ dwRet = MCI_Close(wDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
+ MCI_UnMapMsg16To32A(0, wMsg, dwParam2);
+ break;
+ default: break; /* so that gcc does not bark */
+ }
+ }
+ break;
+ case MCI_SYSINFO:
+ if (bFrom32) {
+ dwRet = MCI_SysInfo(wDevID, dwParam1, (LPMCI_SYSINFO_PARMSA)dwParam2);
+ } else {
+ switch (MCI_MapMsg16To32A(0, wDevID, &dwParam2)) {
+ case MCI_MAP_OK:
+ case MCI_MAP_OKMEM:
+ dwRet = MCI_SysInfo(wDevID, dwParam1, (LPMCI_SYSINFO_PARMSA)dwParam2);
+ MCI_UnMapMsg16To32A(0, wDevID, dwParam2);
+ break;
+ default: break; /* so that gcc doesnot bark */
+ }
+ }
+ break;
+ case MCI_BREAK:
+ if (bFrom32) {
+ dwRet = MCI_Break(wDevID, dwParam1, (LPMCI_BREAK_PARMS)dwParam2);
+ } else {
+ switch (MCI_MapMsg16To32A(0, wDevID, &dwParam2)) {
+ case MCI_MAP_OK:
+ case MCI_MAP_OKMEM:
+ dwRet = MCI_Break(wDevID, dwParam1, (LPMCI_BREAK_PARMS)dwParam2);
+ MCI_UnMapMsg16To32A(0, wDevID, dwParam2);
+ break;
+ default: break; /* so that gcc does not bark */
+ }
+ }
+ break;
+ case MCI_SOUND:
+ /* FIXME: it seems that MCI_SOUND needs the same handling as MCI_BREAK
+ * but I couldn't get any doc on this MCI message
+ */
+ break;
+ default:
+ if (wDevID == MCI_ALL_DEVICE_ID) {
+ FIXME("unhandled MCI_ALL_DEVICE_ID\n");
+ dwRet = MCIERR_CANNOT_USE_ALL;
+ } else {
+ dwRet = (bFrom32) ?
+ MCI_SendCommandFrom32(wDevID, wMsg, dwParam1, dwParam2) :
+ MCI_SendCommandFrom16(wDevID, wMsg, dwParam1, dwParam2);
+ }
+ break;
+ }
+ return dwRet;
+}
+
+/* FIXME: should be using the new mmThreadXXXX functions from WINMM
+ * instead of those
+ * it would require to add a wine internal flag to mmThreadCreate
+ * in order to pass a 32 bit function instead of a 16 bit
+ */
+
struct SCA {
UINT wDevID;
UINT wMsg;
@@ -1492,10 +2361,10 @@
DWORD ret;
TRACE("In thread before async command (%08x,%s,%08lx,%08lx)\n",
- sca->wDevID, MCI_CommandToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
+ sca->wDevID, MCI_MessageToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);
TRACE("In thread after async command (%08x,%s,%08lx,%08lx)\n",
- sca->wDevID, MCI_CommandToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
+ sca->wDevID, MCI_MessageToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
if (sca->allocatedCopy)
HeapFree(GetProcessHeap(), 0, (LPVOID)sca->dwParam2);
HeapFree(GetProcessHeap(), 0, sca);
@@ -1508,7 +2377,8 @@
/**************************************************************************
* MCI_SendCommandAsync [internal]
*/
-DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2, UINT size)
+DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1,
+ DWORD dwParam2, UINT size)
{
struct SCA* sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA));
@@ -1551,6 +2421,9 @@
*/
LRESULT MCI_CleanUp(LRESULT dwRet, UINT wMsg, DWORD dwParam2, BOOL bIs32)
{
+ if (LOWORD(dwRet))
+ return LOWORD(dwRet);
+
switch (wMsg) {
case MCI_GETDEVCAPS:
switch (dwRet & 0xFFFF0000ul) {
@@ -1562,16 +2435,17 @@
case MCI_COLONIZED4_RETURN:
case MCI_INTEGER_RETURNED:
{
- LPMCI_GETDEVCAPS_PARMS lmgp = (LPMCI_GETDEVCAPS_PARMS)(bIs32 ? (void*)dwParam2 : PTR_SEG_TO_LIN(dwParam2));
+ LPMCI_GETDEVCAPS_PARMS lmgp;
+ lmgp = (LPMCI_GETDEVCAPS_PARMS)(bIs32 ? (void*)dwParam2 : PTR_SEG_TO_LIN(dwParam2));
dwRet = LOWORD(dwRet);
TRACE("Changing %08lx to %08lx\n", lmgp->dwReturn, (DWORD)LOWORD(lmgp->dwReturn));
-
lmgp->dwReturn = LOWORD(lmgp->dwReturn);
}
break;
default:
- FIXME("Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet));
+ FIXME("Unsupported value for hiword (%04x) returned by DriverProc(%s)\n",
+ HIWORD(dwRet), MCI_MessageToString(wMsg));
}
break;
case MCI_STATUS:
@@ -1584,21 +2458,34 @@
case MCI_COLONIZED4_RETURN:
case MCI_INTEGER_RETURNED:
{
- LPMCI_STATUS_PARMS lsp = (LPMCI_STATUS_PARMS)(bIs32 ? (void*)dwParam2 : PTR_SEG_TO_LIN(dwParam2));
+ LPMCI_STATUS_PARMS lsp;
+ lsp = (LPMCI_STATUS_PARMS)(bIs32 ? (void*)dwParam2 : PTR_SEG_TO_LIN(dwParam2));
dwRet = LOWORD(dwRet);
TRACE("Changing %08lx to %08lx\n", lsp->dwReturn, (DWORD)LOWORD(lsp->dwReturn));
lsp->dwReturn = LOWORD(lsp->dwReturn);
}
break;
default:
- FIXME("Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet));
+ FIXME("Unsupported value for hiword (%04x) returned by DriverProc(%s)\n",
+ HIWORD(dwRet), MCI_MessageToString(wMsg));
+ }
+ break;
+ case MCI_SYSINFO:
+ switch (dwRet & 0xFFFF0000ul) {
+ case 0:
+ break;
+ case MCI_INTEGER_RETURNED:
+ dwRet = LOWORD(dwRet);
+ break;
+ default:
+ FIXME("Unsupported value for hiword (%04x)\n", HIWORD(dwRet));
}
break;
default:
if (dwRet & 0xFFFF0000ul) {
FIXME("Got non null hiword for dwRet=0x%08lx for command %s\n",
- dwRet, MCI_CommandToString(wMsg));
+ dwRet, MCI_MessageToString(wMsg));
}
break;
}
@@ -1615,34 +2502,32 @@
{
LPSTR ptr1, ptr2;
- mciInstalledCount = 0;
- ptr1 = lpmciInstallNames = HeapAlloc(SystemHeap, 0, 2048);
+ MCI_InstalledCount = 0;
+ ptr1 = MCI_lpInstallNames = HeapAlloc(SystemHeap, 0, 2048);
- if (!lpmciInstallNames)
+ if (!MCI_lpInstallNames)
return FALSE;
- /* FIXME: should do also some registry diving here */
- if (PROFILE_GetWineIniString("options", "mci", "", lpmciInstallNames, 2048) > 0) {
- TRACE_(mci)("Wine => '%s' \n", ptr1);
+ /* FIXME: should do also some registry diving here ? */
+ if (PROFILE_GetWineIniString("options", "mci", "", MCI_lpInstallNames, 2048) > 0) {
+ TRACE("Wine => '%s' \n", ptr1);
while ((ptr2 = strchr(ptr1, ':')) != 0) {
*ptr2++ = 0;
- TRACE_(mci)("---> '%s' \n", ptr1);
- mciInstalledCount++;
+ TRACE("---> '%s' \n", ptr1);
+ MCI_InstalledCount++;
ptr1 = ptr2;
}
- mciInstalledCount++;
- TRACE_(mci)("---> '%s' \n", ptr1);
+ MCI_InstalledCount++;
+ TRACE("---> '%s' \n", ptr1);
ptr1 += strlen(ptr1) + 1;
} else {
- GetPrivateProfileStringA("mci", NULL, "", lpmciInstallNames, 2048, "SYSTEM.INI");
+ GetPrivateProfileStringA("mci", NULL, "", MCI_lpInstallNames, 2048, "SYSTEM.INI");
while (strlen(ptr1) > 0) {
- TRACE_(mci)("---> '%s' \n", ptr1);
- ptr1 += (strlen(ptr1) + 1);
- mciInstalledCount++;
+ TRACE("---> '%s' \n", ptr1);
+ ptr1 += strlen(ptr1) + 1;
+ MCI_InstalledCount++;
}
}
- mciInstalledListLen = ptr1 - lpmciInstallNames;
-
return TRUE;
}