1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
4 * MCI internal functions
6 * Copyright 1998/1999 Eric Pouech
17 #include "multimedia.h"
18 #include "selectors.h"
21 #include "wine/winbase16.h"
22 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(mci)
26 WINE_MCIDRIVER mciDrv[MAXMCIDRIVERS];
28 int mciInstalledCount;
29 int mciInstalledListLen;
30 LPSTR lpmciInstallNames = NULL;
32 static struct MCI_StringType {
35 } MCI_StringType_List[] = {
36 /* MCI types that are working */
37 {"CDAUDIO", MCI_DEVTYPE_CD_AUDIO},
38 {"WAVEAUDIO", MCI_DEVTYPE_WAVEFORM_AUDIO},
39 {"SEQUENCER", MCI_DEVTYPE_SEQUENCER},
41 /* MCI types that should be working */
42 {"ANIMATION1", MCI_DEVTYPE_ANIMATION},
43 {"MPEGVIDEO", MCI_DEVTYPE_DIGITAL_VIDEO},
44 {"AVIVIDEO", MCI_DEVTYPE_DIGITAL_VIDEO},
46 /* MCI types not likely to be supported */
47 {"VCR", MCI_DEVTYPE_VCR},
48 {"VIDEODISC", MCI_DEVTYPE_VIDEODISC},
49 {"OVERLAY", MCI_DEVTYPE_OVERLAY},
50 {"DAT", MCI_DEVTYPE_DAT},
51 {"SCANNER", MCI_DEVTYPE_SCANNER},
56 WORD MCI_GetDevTypeFromString(LPCSTR str)
58 struct MCI_StringType* mst = MCI_StringType_List;
60 while (mst->str && strcmp(mst->str, str)) mst++;
64 LPCSTR MCI_GetStringFromDevType(WORD type)
66 struct MCI_StringType* mst = MCI_StringType_List;
68 while (mst->str && mst->type != type) mst++;
72 /* The wDevID's returned by wine were originally in the range
73 * 0 - (MAXMCIDRIVERS - 1) and used directly as array indices.
74 * Unfortunately, ms-windows uses wDevID of zero to indicate
75 * errors. Now, multimedia drivers must pass the wDevID through
76 * MCI_DevIDToIndex to get an index in that range. An
77 * arbitrary value, MCI_MAGIC is added to the wDevID seen
78 * by the windows programs.
81 #define MCI_MAGIC 0x0F00
83 /**************************************************************************
84 * MCI_DevIDToIndex [internal]
86 int MCI_DevIDToIndex(UINT16 wDevID)
88 return wDevID - MCI_MAGIC;
91 /**************************************************************************
92 * MCI_FirstDevId [internal]
94 UINT16 MCI_FirstDevID(void)
99 /**************************************************************************
100 * MCI_NextDevId [internal]
102 UINT16 MCI_NextDevID(UINT16 wDevID)
107 /**************************************************************************
108 * MCI_DevIDValid [internal]
110 BOOL MCI_DevIDValid(UINT16 wDevID)
112 return wDevID >= MCI_MAGIC && wDevID < (MCI_MAGIC + MAXMCIDRIVERS);
115 /**************************************************************************
116 * MCI_CommandToString [internal]
118 const char* MCI_CommandToString(UINT16 wMsg)
120 static char buffer[100];
122 #define CASE(s) case (s): return #s
127 CASE(MCI_CLOSE_DRIVER);
136 CASE(MCI_GETDEVCAPS);
140 CASE(MCI_OPEN_DRIVER);
159 sprintf(buffer, "MCI_<<%04X>>", wMsg);
165 /**************************************************************************
166 * MCI_MapMsg16To32A [internal]
168 MCI_MapType MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
172 /* FIXME: to add also (with seg/linear modifications to do):
173 * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
174 * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
177 /* case MCI_CAPTURE */
179 case MCI_CLOSE_DRIVER:
180 /* case MCI_CONFIGURE:*/
187 /* case MCI_INDEX: */
189 /* case MCI_MONITOR: */
199 /* case MCI_SETTIMECODE:*/
200 /* case MCI_SIGNAL:*/
202 case MCI_STATUS: /* FIXME: is wrong for digital video */
209 *lParam = (DWORD)PTR_SEG_TO_LIN(*lParam);
212 /* in fact, I would also need the dwFlags... to see
213 * which members of lParam are effectively used
215 *lParam = (DWORD)PTR_SEG_TO_LIN(*lParam);
216 FIXME("Current mapping may be wrong\n");
220 LPMCI_BREAK_PARMS mbp32 = HeapAlloc(SystemHeap, 0, sizeof(MCI_BREAK_PARMS));
221 LPMCI_BREAK_PARMS16 mbp16 = PTR_SEG_TO_LIN(*lParam);
224 mbp32->dwCallback = mbp16->dwCallback;
225 mbp32->nVirtKey = mbp16->nVirtKey;
226 mbp32->hwndBreak = mbp16->hwndBreak;
228 return MCI_MAP_NOMEM;
230 *lParam = (DWORD)mbp32;
232 return MCI_MAP_OKMEM;
235 LPMCI_VD_ESCAPE_PARMSA mvep32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_VD_ESCAPE_PARMSA));
236 LPMCI_VD_ESCAPE_PARMS16 mvep16 = PTR_SEG_TO_LIN(*lParam);
239 mvep32a->dwCallback = mvep16->dwCallback;
240 mvep32a->lpstrCommand = PTR_SEG_TO_LIN(mvep16->lpstrCommand);
242 return MCI_MAP_NOMEM;
244 *lParam = (DWORD)mvep32a;
246 return MCI_MAP_OKMEM;
249 LPMCI_INFO_PARMSA mip32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_INFO_PARMSA));
250 LPMCI_INFO_PARMS16 mip16 = PTR_SEG_TO_LIN(*lParam);
252 /* FIXME this is wrong if device is of type
253 * MCI_DEVTYPE_DIGITAL_VIDEO, some members are not mapped
256 mip32a->dwCallback = mip16->dwCallback;
257 mip32a->lpstrReturn = PTR_SEG_TO_LIN(mip16->lpstrReturn);
258 mip32a->dwRetSize = mip16->dwRetSize;
260 return MCI_MAP_NOMEM;
262 *lParam = (DWORD)mip32a;
264 return MCI_MAP_OKMEM;
266 case MCI_OPEN_DRIVER:
268 LPMCI_OPEN_PARMSA mop32a = HeapAlloc(SystemHeap, 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_OPEN_PARMSA) + 2 * sizeof(DWORD));
269 LPMCI_OPEN_PARMS16 mop16 = PTR_SEG_TO_LIN(*lParam);
272 *(LPMCI_OPEN_PARMS16*)(mop32a) = mop16;
273 mop32a = (LPMCI_OPEN_PARMSA)((char*)mop32a + sizeof(LPMCI_OPEN_PARMS16));
274 mop32a->dwCallback = mop16->dwCallback;
275 mop32a->wDeviceID = mop16->wDeviceID;
276 mop32a->lpstrDeviceType = PTR_SEG_TO_LIN(mop16->lpstrDeviceType);
277 mop32a->lpstrElementName = PTR_SEG_TO_LIN(mop16->lpstrElementName);
278 mop32a->lpstrAlias = PTR_SEG_TO_LIN(mop16->lpstrAlias);
279 /* copy extended information if any...
280 * FIXME: this may seg fault if initial structure does not contain them and
281 * the reads after msip16 fail under LDT limits...
282 * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
283 * should not take care of extended parameters, and should be used by MCI_Open
284 * to fetch uDevType. When, this is known, the mapping for sending the
285 * MCI_OPEN_DRIVER shall be done depending on uDevType.
287 memcpy(mop32a + 1, mop16 + 1, 2 * sizeof(DWORD));
289 return MCI_MAP_NOMEM;
291 *lParam = (DWORD)mop32a;
293 return MCI_MAP_OKMEM;
296 LPMCI_SYSINFO_PARMSA msip32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_SYSINFO_PARMSA));
297 LPMCI_SYSINFO_PARMS16 msip16 = PTR_SEG_TO_LIN(*lParam);
300 msip32a->dwCallback = msip16->dwCallback;
301 msip32a->lpstrReturn = PTR_SEG_TO_LIN(msip16->lpstrReturn);
302 msip32a->dwRetSize = msip16->dwRetSize;
303 msip32a->dwNumber = msip16->dwNumber;
304 msip32a->wDeviceType = msip16->wDeviceType;
306 return MCI_MAP_NOMEM;
308 *lParam = (DWORD)msip32a;
310 return MCI_MAP_OKMEM;
318 case DRV_QUERYCONFIGURE:
321 case DRV_EXITSESSION:
322 case DRV_EXITAPPLICATION:
324 FIXME("This is a hack\n");
328 WARN("Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
330 return MCI_MAP_MSGERROR;
333 /**************************************************************************
334 * MCI_UnMapMsg16To32A [internal]
336 MCI_MapType MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
339 /* case MCI_CAPTURE */
341 case MCI_CLOSE_DRIVER:
342 /* case MCI_CONFIGURE:*/
349 /* case MCI_INDEX: */
351 /* case MCI_MONITOR: */
361 /* case MCI_SETTIMECODE:*/
362 /* case MCI_SIGNAL:*/
374 /* FIXME ?? see Map function */
381 HeapFree(SystemHeap, 0, (LPVOID)lParam);
384 case MCI_OPEN_DRIVER:
386 LPMCI_OPEN_PARMSA mop32a = (LPMCI_OPEN_PARMSA)lParam;
387 LPMCI_OPEN_PARMS16 mop16 = *(LPMCI_OPEN_PARMS16*)((char*)mop32a - sizeof(LPMCI_OPEN_PARMS16*));
389 mop16->wDeviceID = mop32a->wDeviceID;
390 if (!HeapFree(SystemHeap, 0, (LPVOID)(lParam - sizeof(LPMCI_OPEN_PARMS16))))
391 FIXME("bad free line=%d\n", __LINE__);
401 case DRV_QUERYCONFIGURE:
404 case DRV_EXITSESSION:
405 case DRV_EXITAPPLICATION:
407 FIXME("This is a hack\n");
410 FIXME("Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
412 return MCI_MAP_MSGERROR;
417 * 0001 squeeze signed 4 bytes to 2 bytes *( LPINT16)D = ( INT16)*( LPINT16)S; D += 2; S += 4
418 * 0010 squeeze unsigned 4 bytes to 2 bytes *(LPUINT16)D = (UINT16)*(LPUINT16)S; D += 2; S += 4
421 * 0110 zero 4 bytes *(DWORD)D = 0 D += 4; S += 4
422 * 0111 copy string *(LPSTR*)D = seg dup(*(LPSTR*)S) D += 4; S += 4
423 * 1xxx copy xxx + 1 bytes memcpy(D, S, xxx + 1); D += xxx+1; S += xxx+1
426 /**************************************************************************
427 * MCI_MsgMapper32To16_Create [internal]
429 * Helper for MCI_MapMsg32ATo16.
430 * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit
432 * map contains a list of action to be performed for the mapping (see list
434 * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
436 static MCI_MapType MCI_MsgMapper32To16_Create(void** ptr, int size16, DWORD map, BOOLEAN keep)
438 void* lp = SEGPTR_ALLOC((keep ? sizeof(void**) : 0) + size16);
442 return MCI_MAP_NOMEM;
444 p32 = (LPBYTE)(*ptr);
447 p16 = (LPBYTE)lp + sizeof(void**);
448 *ptr = (char*)SEGPTR_GET(lp) + sizeof(void**);
451 *ptr = (void*)SEGPTR_GET(lp);
455 memcpy(p16, p32, size16);
463 sz = (nibble & 7) + 1;
464 memcpy(p16, p32, sz);
467 size16 -= sz; /* DEBUG only */
470 case 0x1: *( LPINT16)p16 = ( INT16)*( LPINT16)p32; p16 += 2; p32 += 4; size16 -= 2; break;
471 case 0x2: *(LPUINT16)p16 = (UINT16)*(LPUINT16)p32; p16 += 2; p32 += 4; size16 -= 2; break;
472 case 0x6: *(LPDWORD)p16 = 0; p16 += 4; p32 += 4; size16 -= 4; break;
473 case 0x7: *(LPDWORD)p16 = SEGPTR_GET(SEGPTR_STRDUP(*(LPSTR*)p32));p16 += 4; p32 += 4; size16 -= 4; break;
474 default: FIXME("Unknown nibble for mapping (%x)\n", nibble);
479 if (size16 != 0) /* DEBUG only */
480 FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
482 return MCI_MAP_OKMEM;
485 /**************************************************************************
486 * MCI_MsgMapper32To16_Destroy [internal]
488 * Helper for MCI_UnMapMsg32ATo16.
490 static MCI_MapType MCI_MsgMapper32To16_Destroy(void* ptr, int size16, DWORD map, BOOLEAN kept)
493 void* msg16 = PTR_SEG_TO_LIN(ptr);
499 alloc = (char*)msg16 - sizeof(void**);
500 p32 = *(void**)alloc;
504 memcpy(p32, p16, size16);
509 memcpy(p32, p16, (nibble & 7) + 1);
510 p16 += (nibble & 7) + 1;
511 p32 += (nibble & 7) + 1;
512 size16 -= (nibble & 7) + 1;
515 case 0x1: *( LPINT)p32 = *( LPINT16)p16; p16 += 2; p32 += 4; size16 -= 2; break;
516 case 0x2: *(LPUINT)p32 = *(LPUINT16)p16; p16 += 2; p32 += 4; size16 -= 2; break;
517 case 0x6: p16 += 4; p32 += 4; size16 -= 4; break;
518 case 0x7: strcpy(*(LPSTR*)p32, PTR_SEG_TO_LIN(*(DWORD*)p16));
519 if (!SEGPTR_FREE(PTR_SEG_TO_LIN(*(DWORD*)p16))) {
520 FIXME("bad free line=%d\n", __LINE__);
522 p16 += 4; p32 += 4; size16 -= 4; break;
523 default: FIXME("Unknown nibble for mapping (%x)\n", nibble);
528 if (size16 != 0) /* DEBUG only */
529 FIXME("Mismatch between 16 bit struct size and map nibbles serie\n");
535 if (!SEGPTR_FREE(alloc)) {
536 FIXME("bad free line=%d\n", __LINE__);
542 /**************************************************************************
543 * MCI_MapMsg32ATo16 [internal]
545 * Map a 32-A bit MCI message to a 16 bit MCI message.
547 MCI_MapType MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
550 BOOLEAN keep = FALSE;
556 /* FIXME: to add also (with seg/linear modifications to do):
557 * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
558 * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
561 /* case MCI_BREAK: */
562 /* case MCI_CAPTURE */
564 case MCI_CLOSE_DRIVER:
565 size = sizeof(MCI_GENERIC_PARMS);
567 /* case MCI_CONFIGURE:*/
571 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_CUE_PARMS); break;
572 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_CUE_PARMS); break;*/ FIXME("NIY vcr\n"); return MCI_MAP_NOMEM;
573 default: size = sizeof(MCI_GENERIC_PARMS); break;
579 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_DELETE_PARMS16); map = 0x0F1111FB; break;
580 case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_DELETE_PARMS); break;
581 default: size = sizeof(MCI_GENERIC_PARMS); break;
584 /* case MCI_ESCAPE: */
587 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_FREEZE_PARMS); map = 0x0001111B; break;
588 case MCI_DEVTYPE_OVERLAY: size = sizeof(MCI_OVLY_RECT_PARMS); map = 0x0001111B; break;
589 default: size = sizeof(MCI_GENERIC_PARMS); break;
594 size = sizeof(MCI_GETDEVCAPS_PARMS);
596 /* case MCI_INDEX: */
599 LPMCI_INFO_PARMSA mip32a = (LPMCI_INFO_PARMSA)(*lParam);
601 LPMCI_INFO_PARMS16 mip16;
604 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_INFO_PARMS16); break;
605 default: size = sizeof(MCI_INFO_PARMS16); break;
607 ptr = SEGPTR_ALLOC(sizeof(LPMCI_INFO_PARMSA) + size);
610 *(LPMCI_INFO_PARMSA*)ptr = mip32a;
611 mip16 = (LPMCI_INFO_PARMS16)(ptr + sizeof(LPMCI_INFO_PARMSA));
612 mip16->dwCallback = mip32a->dwCallback;
613 mip16->lpstrReturn = (LPSTR)SEGPTR_GET(SEGPTR_ALLOC(mip32a->dwRetSize));
614 mip16->dwRetSize = mip32a->dwRetSize;
615 if (uDevType == MCI_DEVTYPE_DIGITAL_VIDEO) {
616 ((LPMCI_DGV_INFO_PARMS16)mip16)->dwItem = ((LPMCI_DGV_INFO_PARMSA)mip32a)->dwItem;
619 return MCI_MAP_NOMEM;
621 *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_INFO_PARMSA);
623 return MCI_MAP_OKMEM;
625 /* case MCI_MONITOR: */
627 case MCI_OPEN_DRIVER:
629 LPMCI_OPEN_PARMSA mop32a = (LPMCI_OPEN_PARMSA)(*lParam);
630 char* ptr = SEGPTR_ALLOC(sizeof(LPMCI_OPEN_PARMSA) + sizeof(MCI_OPEN_PARMS16) + 2 * sizeof(DWORD));
631 LPMCI_OPEN_PARMS16 mop16;
635 *(LPMCI_OPEN_PARMSA*)(ptr) = mop32a;
636 mop16 = (LPMCI_OPEN_PARMS16)(ptr + sizeof(LPMCI_OPEN_PARMSA));
637 mop16->dwCallback = mop32a->dwCallback;
638 mop16->wDeviceID = mop32a->wDeviceID;
639 if (dwFlags & MCI_OPEN_TYPE) {
640 if (dwFlags & MCI_OPEN_TYPE_ID) {
641 /* dword "transparent" value */
642 mop16->lpstrDeviceType = mop32a->lpstrDeviceType;
645 mop16->lpstrDeviceType = mop32a->lpstrDeviceType ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrDeviceType)) : 0;
649 mop16->lpstrDeviceType = 0;
651 if (dwFlags & MCI_OPEN_ELEMENT) {
652 if (dwFlags & MCI_OPEN_ELEMENT_ID) {
653 mop16->lpstrElementName = mop32a->lpstrElementName;
655 mop16->lpstrElementName = mop32a->lpstrElementName ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrElementName)) : 0;
658 mop16->lpstrElementName = 0;
660 if (dwFlags & MCI_OPEN_ALIAS) {
661 mop16->lpstrAlias = mop32a->lpstrAlias ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrAlias)) : 0;
663 mop16->lpstrAlias = 0;
665 /* copy extended information if any...
666 * FIXME: this may seg fault if initial structure does not contain them and
667 * the reads after msip16 fail under LDT limits...
668 * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
669 * should not take care of extended parameters, and should be used by MCI_Open
670 * to fetch uDevType. When, this is known, the mapping for sending the
671 * MCI_OPEN_DRIVER shall be done depending on uDevType.
673 memcpy(mop16 + 1, mop32a + 1, 2 * sizeof(DWORD));
675 return MCI_MAP_NOMEM;
677 *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_OPEN_PARMSA);
679 return MCI_MAP_OKMEM;
682 size = sizeof(MCI_GENERIC_PARMS);
685 size = sizeof(MCI_PLAY_PARMS);
689 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16); map = 0x0001111B; break;
690 case MCI_DEVTYPE_OVERLAY: size = sizeof(MCI_OVLY_RECT_PARMS); map = 0x0001111B; break;
691 default: size = sizeof(MCI_GENERIC_PARMS); break;
695 size = sizeof(MCI_GENERIC_PARMS);
699 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECORD_PARMS16); map = 0x0F1111FB; break;
700 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_RECORD_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM;
701 default: size = sizeof(MCI_RECORD_PARMS); break;
705 size = sizeof(MCI_GENERIC_PARMS);
709 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_SEEK_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM;
710 default: size = sizeof(MCI_SEEK_PARMS); break;
715 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SET_PARMS); break;
716 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_SET_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM;
717 case MCI_DEVTYPE_SEQUENCER: size = sizeof(MCI_SEQ_SET_PARMS); break;
718 /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
719 * so not doing anything should work...
721 case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_SET_PARMS); break;
722 default: size = sizeof(MCI_SET_PARMS); break;
725 /* case MCI_SETTIMECODE:*/
726 /* case MCI_SIGNAL:*/
728 size = sizeof(MCI_SET_PARMS);
734 * don't know if buffer for value is the one passed thru lpstrDevice
735 * or is provided by MCI driver.
736 * Assuming solution 2: provided by MCI driver, so zeroing on entry
738 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16); map = 0x0B6FF; break;
739 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM;
740 default: size = sizeof(MCI_STATUS_PARMS); break;
745 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STEP_PARMS); break;
746 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STEP_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM;
747 case MCI_DEVTYPE_VIDEODISC: size = sizeof(MCI_VD_STEP_PARMS); break;
748 default: size = sizeof(MCI_GENERIC_PARMS); break;
752 size = sizeof(MCI_SET_PARMS);
756 LPMCI_SYSINFO_PARMSA msip32a = (LPMCI_SYSINFO_PARMSA)(*lParam);
757 char* ptr = SEGPTR_ALLOC(sizeof(LPMCI_SYSINFO_PARMSA) + sizeof(MCI_SYSINFO_PARMS16));
758 LPMCI_SYSINFO_PARMS16 msip16;
761 *(LPMCI_SYSINFO_PARMSA*)(ptr) = msip32a;
762 msip16 = (LPMCI_SYSINFO_PARMS16)(ptr + sizeof(LPMCI_SYSINFO_PARMSA));
764 msip16->dwCallback = msip32a->dwCallback;
765 msip16->lpstrReturn = (LPSTR)SEGPTR_GET(SEGPTR_ALLOC(msip32a->dwRetSize));
766 msip16->dwRetSize = msip32a->dwRetSize;
767 msip16->dwNumber = msip32a->dwNumber;
768 msip16->wDeviceType = msip32a->wDeviceType;
770 return MCI_MAP_NOMEM;
772 *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_SYSINFO_PARMSA);
774 return MCI_MAP_OKMEM;
778 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16); map = 0x0001111B; break;
779 case MCI_DEVTYPE_OVERLAY: size = sizeof(MCI_OVLY_RECT_PARMS16); map = 0x0001111B; break;
780 default: size = sizeof(MCI_GENERIC_PARMS); break;
785 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_UPDATE_PARMS16); map = 0x000B1111B; break;
786 default: size = sizeof(MCI_GENERIC_PARMS); break;
791 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16); map = 0x0001111B; keep = TRUE; break;
792 case MCI_DEVTYPE_OVERLAY: size = sizeof(MCI_OVLY_RECT_PARMS16); map = 0x0001111B; keep = TRUE; break;
793 default: size = sizeof(MCI_GENERIC_PARMS); break;
798 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16); if (dwFlags & MCI_DGV_WINDOW_TEXT) map = 0x7FB; break;
799 case MCI_DEVTYPE_OVERLAY: size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7FB; break;
800 default: size = sizeof(MCI_GENERIC_PARMS); break;
810 case DRV_QUERYCONFIGURE:
813 case DRV_EXITSESSION:
814 case DRV_EXITAPPLICATION:
819 WARN("Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
820 return MCI_MAP_MSGERROR;
822 return MCI_MsgMapper32To16_Create((void**)lParam, size, map, keep);
825 /**************************************************************************
826 * MCI_UnMapMsg32ATo16 [internal]
828 MCI_MapType MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
831 BOOLEAN kept = FALSE; /* there is no need to compute size when kept is FALSE */
835 /* case MCI_CAPTURE */
837 case MCI_CLOSE_DRIVER:
839 /* case MCI_CONFIGURE:*/
846 /* case MCI_ESCAPE: */
851 size = sizeof(MCI_GETDEVCAPS_PARMS);
853 /* case MCI_INDEX: */
856 LPMCI_INFO_PARMS16 mip16 = (LPMCI_INFO_PARMS16)PTR_SEG_TO_LIN(lParam);
857 LPMCI_INFO_PARMSA mip32a = *(LPMCI_INFO_PARMSA*)((char*)mip16 - sizeof(LPMCI_INFO_PARMSA));
859 memcpy(mip32a->lpstrReturn, PTR_SEG_TO_LIN(mip16->lpstrReturn), mip32a->dwRetSize);
861 if (!SEGPTR_FREE(PTR_SEG_TO_LIN(mip16->lpstrReturn)))
862 FIXME("bad free line=%d\n", __LINE__);
863 if (!SEGPTR_FREE((char*)mip16 - sizeof(LPMCI_INFO_PARMSA)))
864 FIXME("bad free line=%d\n", __LINE__);
868 /* case MCI_MONITOR: */
870 case MCI_OPEN_DRIVER:
872 LPMCI_OPEN_PARMS16 mop16 = (LPMCI_OPEN_PARMS16)PTR_SEG_TO_LIN(lParam);
873 LPMCI_OPEN_PARMSA mop32a = *(LPMCI_OPEN_PARMSA*)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSA));
875 mop32a->wDeviceID = mop16->wDeviceID;
876 if ((dwFlags & MCI_OPEN_TYPE) && !
877 (dwFlags & MCI_OPEN_TYPE_ID) &&
878 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16->lpstrDeviceType)))
879 FIXME("bad free line=%d\n", __LINE__);
880 if ((dwFlags & MCI_OPEN_ELEMENT) &&
881 !(dwFlags & MCI_OPEN_ELEMENT_ID) &&
882 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16->lpstrElementName)))
883 FIXME("bad free line=%d\n", __LINE__);
884 if ((dwFlags & MCI_OPEN_ALIAS) &&
885 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16->lpstrAlias)))
886 FIXME("bad free line=%d\n", __LINE__);
888 if (!SEGPTR_FREE((char*)mop16 - sizeof(LPMCI_OPEN_PARMSA)))
889 FIXME("bad free line=%d\n", __LINE__);
909 /* case MCI_SETTIMECODE:*/
910 /* case MCI_SIGNAL:*/
916 case MCI_DEVTYPE_DIGITAL_VIDEO:
918 LPMCI_DGV_STATUS_PARMS16 mdsp16 = (LPMCI_DGV_STATUS_PARMS16)PTR_SEG_TO_LIN(lParam);
919 LPMCI_DGV_STATUS_PARMSA mdsp32a = *(LPMCI_DGV_STATUS_PARMSA*)((char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA));
922 mdsp32a->dwReturn = mdsp16->dwReturn;
923 if (dwFlags & MCI_DGV_STATUS_DISKSPACE) {
924 TRACE("MCI_STATUS (DGV) lpstrDrive=%p\n", mdsp16->lpstrDrive);
925 TRACE("MCI_STATUS (DGV) lpstrDrive=%s\n", (LPSTR)PTR_SEG_TO_LIN(mdsp16->lpstrDrive));
927 /* FIXME: see map function */
928 strcpy(mdsp32a->lpstrDrive, (LPSTR)PTR_SEG_TO_LIN(mdsp16->lpstrDrive));
931 if (!SEGPTR_FREE((char*)mdsp16 - sizeof(LPMCI_DGV_STATUS_PARMSA)))
932 FIXME("bad free line=%d\n", __LINE__);
934 return MCI_MAP_NOMEM;
937 return MCI_MAP_OKMEM;
938 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM;
939 default: size = sizeof(MCI_STATUS_PARMS); break;
948 LPMCI_SYSINFO_PARMS16 msip16 = (LPMCI_SYSINFO_PARMS16)PTR_SEG_TO_LIN(lParam);
949 LPMCI_SYSINFO_PARMSA msip32a = *(LPMCI_SYSINFO_PARMSA*)((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA));
952 msip16->dwCallback = msip32a->dwCallback;
953 memcpy(msip32a->lpstrReturn, PTR_SEG_TO_LIN(msip16->lpstrReturn), msip32a->dwRetSize);
954 if (!SEGPTR_FREE(PTR_SEG_TO_LIN(msip16->lpstrReturn)))
955 FIXME("bad free line=%d\n", __LINE__);
957 if (!SEGPTR_FREE((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA)))
958 FIXME("bad free line=%d\n", __LINE__);
960 return MCI_MAP_NOMEM;
963 return MCI_MAP_OKMEM;
971 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS16); map = 0x0001111B; kept = TRUE; break;
972 case MCI_DEVTYPE_OVERLAY: size = sizeof(MCI_OVLY_RECT_PARMS16); map = 0x0001111B; kept = TRUE; break;
978 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16); if (dwFlags & MCI_DGV_WINDOW_TEXT) map = 0x7666; break;
979 case MCI_DEVTYPE_OVERLAY: size = sizeof(MCI_OVLY_WINDOW_PARMS16); if (dwFlags & MCI_OVLY_WINDOW_TEXT) map = 0x7666; break;
982 /* FIXME: see map function */
992 case DRV_QUERYCONFIGURE:
995 case DRV_EXITSESSION:
996 case DRV_EXITAPPLICATION:
998 FIXME("This is a hack\n");
1001 FIXME("Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
1002 return MCI_MAP_MSGERROR;
1004 return MCI_MsgMapper32To16_Destroy((void*)lParam, size, map, kept);
1007 /**************************************************************************
1008 * MCI_SendCommandFrom32 [internal]
1010 DWORD MCI_SendCommandFrom32(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
1012 DWORD dwRet = MCIERR_DEVICE_NOT_INSTALLED;
1014 if (!MCI_DevIDValid(wDevID)) {
1015 dwRet = MCIERR_INVALID_DEVICE_ID;
1017 switch (DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv)) {
1018 case WINE_DI_TYPE_16:
1022 switch (res = MCI_MapMsg32ATo16(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam1, &dwParam2)) {
1023 case MCI_MAP_MSGERROR:
1024 TRACE("Not handled yet (%s)\n", MCI_CommandToString(wMsg));
1025 dwRet = MCIERR_DRIVER_INTERNAL;
1028 TRACE("Problem mapping msg=%s from 32a to 16\n", MCI_CommandToString(wMsg));
1029 dwRet = MCIERR_OUT_OF_MEMORY;
1033 dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
1034 if (res == MCI_MAP_OKMEM)
1035 MCI_UnMapMsg32ATo16(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam1, dwParam2);
1038 dwRet = SendDriverMessage(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
1043 case WINE_DI_TYPE_32:
1044 dwRet = SendDriverMessage(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
1047 WARN("Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv));
1048 dwRet = MCIERR_DRIVER_INTERNAL;
1054 /**************************************************************************
1055 * MCI_SendCommandFrom16 [internal]
1057 DWORD MCI_SendCommandFrom16(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
1059 DWORD dwRet = MCIERR_DEVICE_NOT_INSTALLED;
1061 if (!MCI_DevIDValid(wDevID)) {
1062 dwRet = MCIERR_INVALID_DEVICE_ID;
1066 switch (DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv)) {
1067 case WINE_DI_TYPE_16:
1068 dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
1070 case WINE_DI_TYPE_32:
1071 switch (res = MCI_MapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, &dwParam2)) {
1072 case MCI_MAP_MSGERROR:
1073 TRACE("Not handled yet (%s)\n", MCI_CommandToString(wMsg));
1074 dwRet = MCIERR_DRIVER_INTERNAL;
1077 TRACE("Problem mapping msg=%s from 16 to 32a\n", MCI_CommandToString(wMsg));
1078 dwRet = MCIERR_OUT_OF_MEMORY;
1082 dwRet = SendDriverMessage(wDevID, wMsg, dwParam1, dwParam2);
1083 if (res == MCI_MAP_OKMEM)
1084 MCI_UnMapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam2);
1087 dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
1092 WARN("Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv));
1093 dwRet = MCIERR_DRIVER_INTERNAL;
1099 /**************************************************************************
1100 * MCI_Open [internal]
1102 DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms)
1104 char strDevTyp[128];
1105 UINT16 uDevType = 0;
1106 UINT16 wDevID = MCI_FirstDevID();
1109 MCI_OPEN_DRIVER_PARMSA modp;
1112 TRACE("(%08lX, %p)\n", dwParam, lpParms);
1113 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1115 if ((dwParam & ~(MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY|MCI_WAIT)) != 0) {
1116 FIXME("Unsupported yet dwFlags=%08lX\n",
1117 (dwParam & ~(MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY|MCI_WAIT)));
1120 while (MCI_GetDrv(wDevID)->modp.wType != 0) {
1121 wDevID = MCI_NextDevID(wDevID);
1122 if (!MCI_DevIDValid(wDevID)) {
1123 TRACE("MAXMCIDRIVERS reached !\n");
1124 return MCIERR_OUT_OF_MEMORY;
1128 TRACE("wDevID=%04X \n", wDevID);
1129 memcpy(MCI_GetOpenDrv(wDevID), lpParms, sizeof(*lpParms));
1133 if (dwParam & MCI_OPEN_ELEMENT) {
1136 TRACE("lpstrElementName='%s'\n", lpParms->lpstrElementName);
1137 t = strrchr(lpParms->lpstrElementName, '.');
1139 GetProfileStringA("mci extensions", t+1, "*", strDevTyp, sizeof(strDevTyp));
1140 if (strcmp(strDevTyp, "*") == 0) {
1141 TRACE("No [mci extensions] entry for %s found.\n", t);
1142 return MCIERR_EXTENSION_NOT_FOUND;
1144 TRACE("Extension %s is mapped to type %s\n", t, strDevTyp);
1145 } else if (GetDriveTypeA(lpParms->lpstrElementName) == DRIVE_CDROM) {
1146 /* FIXME: this will not work if several CDROM drives are installed on the machine */
1147 strcpy(strDevTyp, "CDAUDIO");
1149 return MCIERR_EXTENSION_NOT_FOUND;
1153 if (dwParam & MCI_OPEN_ALIAS) {
1154 TRACE("Alias='%s' !\n", lpParms->lpstrAlias);
1155 /* FIXME is there any memory leak here ? */
1156 MCI_GetOpenDrv(wDevID)->lpstrAlias = strdup(lpParms->lpstrAlias);
1157 /* mplayer does allocate alias to CDAUDIO */
1159 if (dwParam & MCI_OPEN_TYPE) {
1160 if (dwParam & MCI_OPEN_TYPE_ID) {
1162 TRACE("Dev=%08lx!\n", (DWORD)lpParms->lpstrDeviceType);
1163 uDevType = LOWORD((DWORD)lpParms->lpstrDeviceType);
1164 MCI_GetOpenDrv(wDevID)->lpstrDeviceType = lpParms->lpstrDeviceType;
1166 if (LOWORD((DWORD)lpParms->lpstrDeviceType) != MCI_DEVTYPE_CD_AUDIO) {
1167 FIXME("MCI_OPEN_TYPE_ID is no longer properly supported\n");
1169 strcpy(strDevTyp, "CDAUDIO");
1171 if (lpParms->lpstrDeviceType == NULL)
1172 return MCIERR_NULL_PARAMETER_BLOCK;
1173 TRACE("Dev='%s' !\n", lpParms->lpstrDeviceType);
1174 strcpy(strDevTyp, lpParms->lpstrDeviceType);
1178 if (strDevTyp[0] == 0) {
1179 FIXME("Couldn't load driver\n");
1180 return MCIERR_DRIVER_INTERNAL;
1183 CharUpperA(strDevTyp);
1185 modp.wDeviceID = wDevID;
1186 modp.lpstrParams = NULL;
1188 /* FIXME: this is a hack... some MCI drivers, while being open, call
1189 * mciSetData, which lookup for non empty slots in MCI table list
1190 * Unfortunatly, open slots are known when wType == 0...
1191 * so use a dummy type, just to keep on going. May be wType == 0 is
1192 * not the best solution to indicate empty slot in MCI drivers table
1194 MCI_GetDrv(wDevID)->modp.wType = MCI_DEVTYPE_CD_AUDIO;
1195 hDrv = OpenDriverA(strDevTyp, "mci", (LPARAM)&modp);
1198 FIXME("Couldn't load driver for type %s.\n", strDevTyp);
1199 return MCIERR_DEVICE_NOT_INSTALLED;
1201 uDevType = modp.wType;
1202 MCI_GetDrv(wDevID)->hDrv = hDrv;
1204 TRACE("Loaded driver %u (%s), type is %d\n", hDrv, strDevTyp, uDevType);
1206 MCI_GetDrv(wDevID)->mop.lpstrDeviceType = strdup(strDevTyp);
1207 MCI_GetDrv(wDevID)->modp.wType = uDevType;
1208 MCI_GetDrv(wDevID)->modp.wDeviceID = 0; /* FIXME? for multiple devices */
1210 lpParms->wDeviceID = wDevID;
1212 TRACE("mcidev=%d, uDevType=%04X wDeviceID=%04X !\n",
1213 wDevID, uDevType, lpParms->wDeviceID);
1215 MCI_GetDrv(wDevID)->lpfnYieldProc = MCI_DefYieldProc;
1216 MCI_GetDrv(wDevID)->dwYieldData = VK_CANCEL;
1217 MCI_GetDrv(wDevID)->hCreatorTask = GetCurrentTask();
1218 MCI_GetDrv(wDevID)->dwPrivate = 0;
1220 dwRet = MCI_SendCommandFrom32(wDevID, MCI_OPEN_DRIVER, dwParam, (DWORD)lpParms);
1223 /* only handled devices fall through */
1224 TRACE("wDevID = %04X wDeviceID = %d dwRet = %ld\n", wDevID, lpParms->wDeviceID, dwRet);
1226 TRACE("Failed to open driver (MCI_OPEN_DRIVER msg) [%08lx], closing\n", dwRet);
1227 MCI_GetDrv(wDevID)->modp.wType = 0;
1229 if (dwParam & MCI_NOTIFY)
1230 mciDriverNotify16(lpParms->dwCallback, wDevID, dwRet == 0 ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE);
1235 /**************************************************************************
1236 * MCI_Close [internal]
1238 DWORD MCI_Close(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
1242 TRACE("(%04x, %08lX, %p)\n", wDevID, dwParam, lpParms);
1244 if (wDevID == MCI_ALL_DEVICE_ID) {
1245 FIXME("unhandled MCI_ALL_DEVICE_ID\n");
1246 return MCIERR_CANNOT_USE_ALL;
1249 dwRet = MCI_SendCommandFrom32(wDevID, MCI_CLOSE_DRIVER, dwParam, (DWORD)lpParms);
1250 if (MCI_GetDrv(wDevID)->hDrv) {
1252 CloseDriver(MCI_GetDrv(wDevID)->hDrv, 0, 0);
1255 MCI_GetDrv(wDevID)->modp.wType = 0;
1256 free(MCI_GetDrv(wDevID)->mop.lpstrDeviceType);
1258 if (dwParam & MCI_NOTIFY)
1259 mciDriverNotify16(lpParms->dwCallback, wDevID,
1260 (dwRet == 0) ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE);
1265 /**************************************************************************
1266 * MCI_WriteString [internal]
1268 DWORD MCI_WriteString(LPSTR lpDstStr, DWORD dstSize, LPCSTR lpSrcStr)
1272 if (dstSize <= strlen(lpSrcStr)) {
1273 lstrcpynA(lpDstStr, lpSrcStr, dstSize - 1);
1274 ret = MCIERR_PARAM_OVERFLOW;
1276 strcpy(lpDstStr, lpSrcStr);
1282 /**************************************************************************
1283 * MCI_Sysinfo [internal]
1285 DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSA lpParms)
1287 DWORD ret = MCIERR_INVALID_DEVICE_ID;
1289 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1291 TRACE("(%08x, %08lX, %08lX[num=%ld, wDevTyp=%u])\n",
1292 uDevID, dwFlags, (DWORD)lpParms, lpParms->dwNumber, lpParms->wDeviceType);
1294 switch (dwFlags & ~MCI_SYSINFO_OPEN) {
1295 case MCI_SYSINFO_QUANTITY:
1300 if (lpParms->wDeviceType < MCI_DEVTYPE_FIRST || lpParms->wDeviceType > MCI_DEVTYPE_LAST) {
1301 if (dwFlags & MCI_SYSINFO_OPEN) {
1302 TRACE("MCI_SYSINFO_QUANTITY: # of open MCI drivers\n");
1303 for (i = 0; i < MAXMCIDRIVERS; i++) {
1304 if (mciDrv[i].modp.wType != 0) cnt++;
1307 TRACE("MCI_SYSINFO_QUANTITY: # of installed MCI drivers\n");
1308 cnt = mciInstalledCount;
1311 if (dwFlags & MCI_SYSINFO_OPEN) {
1312 TRACE("MCI_SYSINFO_QUANTITY: # of open MCI drivers of type %u\n", lpParms->wDeviceType);
1313 for (i = 0; i < MAXMCIDRIVERS; i++) {
1314 if (mciDrv[i].modp.wType == lpParms->wDeviceType) cnt++;
1317 TRACE("MCI_SYSINFO_QUANTITY: # of installed MCI drivers of type %u\n", lpParms->wDeviceType);
1318 FIXME("Don't know how to get # of MCI devices of a given type\n");
1322 *(DWORD*)lpParms->lpstrReturn = cnt;
1324 TRACE("(%ld) => '%ld'\n", lpParms->dwNumber, *(DWORD*)lpParms->lpstrReturn);
1327 case MCI_SYSINFO_INSTALLNAME:
1328 TRACE("MCI_SYSINFO_INSTALLNAME \n");
1329 if (MCI_DevIDValid(uDevID)) {
1330 ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize, MCI_GetDrv(uDevID)->mop.lpstrDeviceType);
1332 *lpParms->lpstrReturn = 0;
1333 ret = MCIERR_INVALID_DEVICE_ID;
1335 TRACE("(%ld) => '%s'\n", lpParms->dwNumber, lpParms->lpstrReturn);
1337 case MCI_SYSINFO_NAME:
1338 TRACE("MCI_SYSINFO_NAME\n");
1339 if (dwFlags & MCI_SYSINFO_OPEN) {
1340 FIXME("Don't handle MCI_SYSINFO_NAME|MCI_SYSINFO_OPEN (yet)\n");
1341 ret = MCIERR_UNRECOGNIZED_COMMAND;
1342 } else if (lpParms->dwNumber > mciInstalledCount) {
1343 ret = MCIERR_OUTOFRANGE;
1345 DWORD count = lpParms->dwNumber;
1346 LPSTR ptr = lpmciInstallNames;
1348 while (--count > 0) ptr += strlen(ptr) + 1;
1349 ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize, ptr);
1351 TRACE("(%ld) => '%s'\n", lpParms->dwNumber, lpParms->lpstrReturn);
1354 TRACE("Unsupported flag value=%08lx\n", dwFlags);
1355 ret = MCIERR_UNRECOGNIZED_COMMAND;
1368 DWORD WINAPI mciSendCommandA(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2);
1370 /**************************************************************************
1371 * MCI_SCAStarter [internal]
1373 static DWORD CALLBACK MCI_SCAStarter(LPVOID arg)
1375 struct SCA* sca = (struct SCA*)arg;
1378 TRACE("In thread before async command (%08x,%s,%08lx,%08lx)\n",
1379 sca->wDevID, MCI_CommandToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
1380 ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);
1381 TRACE("In thread after async command (%08x,%s,%08lx,%08lx)\n",
1382 sca->wDevID, MCI_CommandToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
1383 if (sca->allocatedCopy)
1384 HeapFree(GetProcessHeap(), 0, (LPVOID)sca->dwParam2);
1385 HeapFree(GetProcessHeap(), 0, sca);
1387 WARN("Should not happen ? what's wrong \n");
1388 /* should not go after this point */
1392 /**************************************************************************
1393 * MCI_SendCommandAsync [internal]
1395 DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2, UINT size)
1397 struct SCA* sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA));
1400 return MCIERR_OUT_OF_MEMORY;
1402 sca->wDevID = wDevID;
1404 sca->dwParam1 = dwParam1;
1407 sca->dwParam2 = (DWORD)HeapAlloc(GetProcessHeap(), 0, size);
1408 if (sca->dwParam2 == 0) {
1409 HeapFree(GetProcessHeap(), 0, sca);
1410 return MCIERR_OUT_OF_MEMORY;
1412 sca->allocatedCopy = TRUE;
1413 /* copy structure passed by program in dwParam2 to be sure
1414 * we can still use it whatever the program does
1416 memcpy((LPVOID)sca->dwParam2, (LPVOID)dwParam2, size);
1418 sca->dwParam2 = dwParam2;
1419 sca->allocatedCopy = FALSE;
1422 if (CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL) == 0) {
1423 WARN("Couldn't allocate thread for async command handling, sending synchonously\n");
1424 return MCI_SCAStarter(&sca);
1429 /**************************************************************************
1430 * MCI_CleanUp [internal]
1432 * Some MCI commands need to be cleaned-up (when not called from
1433 * mciSendString), because MCI drivers return extra information for string
1434 * transformation. This function gets read of them.
1436 LRESULT MCI_CleanUp(LRESULT dwRet, UINT wMsg, DWORD dwParam2, BOOL bIs32)
1439 case MCI_GETDEVCAPS:
1440 switch (dwRet & 0xFFFF0000ul) {
1443 case MCI_RESOURCE_RETURNED:
1444 case MCI_RESOURCE_RETURNED|MCI_RESOURCE_DRIVER:
1445 case MCI_COLONIZED3_RETURN:
1446 case MCI_COLONIZED4_RETURN:
1447 case MCI_INTEGER_RETURNED:
1449 LPMCI_GETDEVCAPS_PARMS lmgp = (LPMCI_GETDEVCAPS_PARMS)(bIs32 ? (void*)dwParam2 : PTR_SEG_TO_LIN(dwParam2));
1451 dwRet = LOWORD(dwRet);
1452 TRACE("Changing %08lx to %08lx\n", lmgp->dwReturn, (DWORD)LOWORD(lmgp->dwReturn));
1454 lmgp->dwReturn = LOWORD(lmgp->dwReturn);
1458 FIXME("Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet));
1462 switch (dwRet & 0xFFFF0000ul) {
1465 case MCI_RESOURCE_RETURNED:
1466 case MCI_RESOURCE_RETURNED|MCI_RESOURCE_DRIVER:
1467 case MCI_COLONIZED3_RETURN:
1468 case MCI_COLONIZED4_RETURN:
1469 case MCI_INTEGER_RETURNED:
1471 LPMCI_STATUS_PARMS lsp = (LPMCI_STATUS_PARMS)(bIs32 ? (void*)dwParam2 : PTR_SEG_TO_LIN(dwParam2));
1473 dwRet = LOWORD(dwRet);
1474 TRACE("Changing %08lx to %08lx\n", lsp->dwReturn,(DWORD) LOWORD(lsp->dwReturn));
1475 lsp->dwReturn = LOWORD(lsp->dwReturn);
1479 FIXME("Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet));
1488 /**************************************************************************
1489 * MULTIMEDIA_MciInit [internal]
1491 * Initializes the MCI internal variables.
1494 BOOL MULTIMEDIA_MciInit(void)
1498 mciInstalledCount = 0;
1499 ptr1 = lpmciInstallNames = malloc(2048);
1501 if (!lpmciInstallNames)
1504 /* FIXME: should do also some registry diving here */
1505 if (PROFILE_GetWineIniString("options", "mci", "", lpmciInstallNames, 2048) > 0) {
1506 TRACE_(mci)("Wine => '%s' \n", ptr1);
1507 while ((ptr2 = strchr(ptr1, ':')) != 0) {
1509 TRACE_(mci)("---> '%s' \n", ptr1);
1510 mciInstalledCount++;
1513 mciInstalledCount++;
1514 TRACE_(mci)("---> '%s' \n", ptr1);
1515 ptr1 += strlen(ptr1) + 1;
1517 GetPrivateProfileStringA("mci", NULL, "", lpmciInstallNames, 2048, "SYSTEM.INI");
1518 while (strlen(ptr1) > 0) {
1519 TRACE_(mci)("---> '%s' \n", ptr1);
1520 ptr1 += (strlen(ptr1) + 1);
1521 mciInstalledCount++;
1524 mciInstalledListLen = ptr1 - lpmciInstallNames;