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
562 size
= sizeof(MCI_BREAK_PARMS
);
564 /* case MCI_CAPTURE */
566 case MCI_CLOSE_DRIVER
:
567 size
= sizeof(MCI_GENERIC_PARMS
);
569 /* case MCI_CONFIGURE:*/
573 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_CUE_PARMS
); break;
574 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_CUE_PARMS); break;*/ FIXME("NIY vcr\n"); return MCI_MAP_NOMEM
;
575 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
581 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_DELETE_PARMS16
); map
= 0x0F1111FB; break;
582 case MCI_DEVTYPE_WAVEFORM_AUDIO
:size
= sizeof(MCI_WAVE_DELETE_PARMS
); break;
583 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
586 /* case MCI_ESCAPE: */
589 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_FREEZE_PARMS
); map
= 0x0001111B; break;
590 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_RECT_PARMS
); map
= 0x0001111B; break;
591 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
596 size
= sizeof(MCI_GETDEVCAPS_PARMS
);
598 /* case MCI_INDEX: */
601 LPMCI_INFO_PARMSA mip32a
= (LPMCI_INFO_PARMSA
)(*lParam
);
603 LPMCI_INFO_PARMS16 mip16
;
606 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_INFO_PARMS16
); break;
607 default: size
= sizeof(MCI_INFO_PARMS16
); break;
609 ptr
= SEGPTR_ALLOC(sizeof(LPMCI_INFO_PARMSA
) + size
);
612 *(LPMCI_INFO_PARMSA
*)ptr
= mip32a
;
613 mip16
= (LPMCI_INFO_PARMS16
)(ptr
+ sizeof(LPMCI_INFO_PARMSA
));
614 mip16
->dwCallback
= mip32a
->dwCallback
;
615 mip16
->lpstrReturn
= (LPSTR
)SEGPTR_GET(SEGPTR_ALLOC(mip32a
->dwRetSize
));
616 mip16
->dwRetSize
= mip32a
->dwRetSize
;
617 if (uDevType
== MCI_DEVTYPE_DIGITAL_VIDEO
) {
618 ((LPMCI_DGV_INFO_PARMS16
)mip16
)->dwItem
= ((LPMCI_DGV_INFO_PARMSA
)mip32a
)->dwItem
;
621 return MCI_MAP_NOMEM
;
623 *lParam
= (LPARAM
)SEGPTR_GET(ptr
) + sizeof(LPMCI_INFO_PARMSA
);
625 return MCI_MAP_OKMEM
;
627 /* case MCI_MONITOR: */
629 case MCI_OPEN_DRIVER
:
631 LPMCI_OPEN_PARMSA mop32a
= (LPMCI_OPEN_PARMSA
)(*lParam
);
632 char* ptr
= SEGPTR_ALLOC(sizeof(LPMCI_OPEN_PARMSA
) + sizeof(MCI_OPEN_PARMS16
) + 2 * sizeof(DWORD
));
633 LPMCI_OPEN_PARMS16 mop16
;
637 *(LPMCI_OPEN_PARMSA
*)(ptr
) = mop32a
;
638 mop16
= (LPMCI_OPEN_PARMS16
)(ptr
+ sizeof(LPMCI_OPEN_PARMSA
));
639 mop16
->dwCallback
= mop32a
->dwCallback
;
640 mop16
->wDeviceID
= mop32a
->wDeviceID
;
641 if (dwFlags
& MCI_OPEN_TYPE
) {
642 if (dwFlags
& MCI_OPEN_TYPE_ID
) {
643 /* dword "transparent" value */
644 mop16
->lpstrDeviceType
= mop32a
->lpstrDeviceType
;
647 mop16
->lpstrDeviceType
= mop32a
->lpstrDeviceType
? (LPSTR
)SEGPTR_GET(SEGPTR_STRDUP(mop32a
->lpstrDeviceType
)) : 0;
651 mop16
->lpstrDeviceType
= 0;
653 if (dwFlags
& MCI_OPEN_ELEMENT
) {
654 if (dwFlags
& MCI_OPEN_ELEMENT_ID
) {
655 mop16
->lpstrElementName
= mop32a
->lpstrElementName
;
657 mop16
->lpstrElementName
= mop32a
->lpstrElementName
? (LPSTR
)SEGPTR_GET(SEGPTR_STRDUP(mop32a
->lpstrElementName
)) : 0;
660 mop16
->lpstrElementName
= 0;
662 if (dwFlags
& MCI_OPEN_ALIAS
) {
663 mop16
->lpstrAlias
= mop32a
->lpstrAlias
? (LPSTR
)SEGPTR_GET(SEGPTR_STRDUP(mop32a
->lpstrAlias
)) : 0;
665 mop16
->lpstrAlias
= 0;
667 /* copy extended information if any...
668 * FIXME: this may seg fault if initial structure does not contain them and
669 * the reads after msip16 fail under LDT limits...
670 * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
671 * should not take care of extended parameters, and should be used by MCI_Open
672 * to fetch uDevType. When, this is known, the mapping for sending the
673 * MCI_OPEN_DRIVER shall be done depending on uDevType.
675 memcpy(mop16
+ 1, mop32a
+ 1, 2 * sizeof(DWORD
));
677 return MCI_MAP_NOMEM
;
679 *lParam
= (LPARAM
)SEGPTR_GET(ptr
) + sizeof(LPMCI_OPEN_PARMSA
);
681 return MCI_MAP_OKMEM
;
684 size
= sizeof(MCI_GENERIC_PARMS
);
687 size
= sizeof(MCI_PLAY_PARMS
);
691 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_RECT_PARMS16
); map
= 0x0001111B; break;
692 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_RECT_PARMS
); map
= 0x0001111B; break;
693 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
697 size
= sizeof(MCI_GENERIC_PARMS
);
701 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_RECORD_PARMS16
); map
= 0x0F1111FB; break;
702 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_RECORD_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM
;
703 default: size
= sizeof(MCI_RECORD_PARMS
); break;
707 size
= sizeof(MCI_GENERIC_PARMS
);
711 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_SEEK_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM
;
712 default: size
= sizeof(MCI_SEEK_PARMS
); break;
717 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_SET_PARMS
); break;
718 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_SET_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM
;
719 case MCI_DEVTYPE_SEQUENCER
: size
= sizeof(MCI_SEQ_SET_PARMS
); break;
720 /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
721 * so not doing anything should work...
723 case MCI_DEVTYPE_WAVEFORM_AUDIO
:size
= sizeof(MCI_WAVE_SET_PARMS
); break;
724 default: size
= sizeof(MCI_SET_PARMS
); break;
727 /* case MCI_SETTIMECODE:*/
728 /* case MCI_SIGNAL:*/
730 size
= sizeof(MCI_SET_PARMS
);
736 * don't know if buffer for value is the one passed thru lpstrDevice
737 * or is provided by MCI driver.
738 * Assuming solution 2: provided by MCI driver, so zeroing on entry
740 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_STATUS_PARMS16
); map
= 0x0B6FF; break;
741 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM
;
742 default: size
= sizeof(MCI_STATUS_PARMS
); break;
747 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_STEP_PARMS
); break;
748 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_STEP_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM
;
749 case MCI_DEVTYPE_VIDEODISC
: size
= sizeof(MCI_VD_STEP_PARMS
); break;
750 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
754 size
= sizeof(MCI_SET_PARMS
);
758 LPMCI_SYSINFO_PARMSA msip32a
= (LPMCI_SYSINFO_PARMSA
)(*lParam
);
759 char* ptr
= SEGPTR_ALLOC(sizeof(LPMCI_SYSINFO_PARMSA
) + sizeof(MCI_SYSINFO_PARMS16
));
760 LPMCI_SYSINFO_PARMS16 msip16
;
763 *(LPMCI_SYSINFO_PARMSA
*)(ptr
) = msip32a
;
764 msip16
= (LPMCI_SYSINFO_PARMS16
)(ptr
+ sizeof(LPMCI_SYSINFO_PARMSA
));
766 msip16
->dwCallback
= msip32a
->dwCallback
;
767 msip16
->lpstrReturn
= (LPSTR
)SEGPTR_GET(SEGPTR_ALLOC(msip32a
->dwRetSize
));
768 msip16
->dwRetSize
= msip32a
->dwRetSize
;
769 msip16
->dwNumber
= msip32a
->dwNumber
;
770 msip16
->wDeviceType
= msip32a
->wDeviceType
;
772 return MCI_MAP_NOMEM
;
774 *lParam
= (LPARAM
)SEGPTR_GET(ptr
) + sizeof(LPMCI_SYSINFO_PARMSA
);
776 return MCI_MAP_OKMEM
;
780 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_RECT_PARMS16
); map
= 0x0001111B; break;
781 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_RECT_PARMS16
); map
= 0x0001111B; break;
782 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
787 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_UPDATE_PARMS16
); map
= 0x000B1111B; break;
788 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
793 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_RECT_PARMS16
); map
= 0x0001111B; keep
= TRUE
; break;
794 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_RECT_PARMS16
); map
= 0x0001111B; keep
= TRUE
; break;
795 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
800 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_WINDOW_PARMS16
); if (dwFlags
& MCI_DGV_WINDOW_TEXT
) map
= 0x7FB; break;
801 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_WINDOW_PARMS16
); if (dwFlags
& MCI_OVLY_WINDOW_TEXT
) map
= 0x7FB; break;
802 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
812 case DRV_QUERYCONFIGURE
:
815 case DRV_EXITSESSION
:
816 case DRV_EXITAPPLICATION
:
821 WARN("Don't know how to map msg=%s\n", MCI_CommandToString(wMsg
));
822 return MCI_MAP_MSGERROR
;
824 return MCI_MsgMapper32To16_Create((void**)lParam
, size
, map
, keep
);
827 /**************************************************************************
828 * MCI_UnMapMsg32ATo16 [internal]
830 MCI_MapType
MCI_UnMapMsg32ATo16(WORD uDevType
, WORD wMsg
, DWORD dwFlags
, DWORD lParam
)
833 BOOLEAN kept
= FALSE
; /* there is no need to compute size when kept is FALSE */
839 /* case MCI_CAPTURE */
841 case MCI_CLOSE_DRIVER
:
843 /* case MCI_CONFIGURE:*/
850 /* case MCI_ESCAPE: */
855 size
= sizeof(MCI_GETDEVCAPS_PARMS
);
857 /* case MCI_INDEX: */
860 LPMCI_INFO_PARMS16 mip16
= (LPMCI_INFO_PARMS16
)PTR_SEG_TO_LIN(lParam
);
861 LPMCI_INFO_PARMSA mip32a
= *(LPMCI_INFO_PARMSA
*)((char*)mip16
- sizeof(LPMCI_INFO_PARMSA
));
863 memcpy(mip32a
->lpstrReturn
, PTR_SEG_TO_LIN(mip16
->lpstrReturn
), mip32a
->dwRetSize
);
865 if (!SEGPTR_FREE(PTR_SEG_TO_LIN(mip16
->lpstrReturn
)))
866 FIXME("bad free line=%d\n", __LINE__
);
867 if (!SEGPTR_FREE((char*)mip16
- sizeof(LPMCI_INFO_PARMSA
)))
868 FIXME("bad free line=%d\n", __LINE__
);
872 /* case MCI_MONITOR: */
874 case MCI_OPEN_DRIVER
:
876 LPMCI_OPEN_PARMS16 mop16
= (LPMCI_OPEN_PARMS16
)PTR_SEG_TO_LIN(lParam
);
877 LPMCI_OPEN_PARMSA mop32a
= *(LPMCI_OPEN_PARMSA
*)((char*)mop16
- sizeof(LPMCI_OPEN_PARMSA
));
879 mop32a
->wDeviceID
= mop16
->wDeviceID
;
880 if ((dwFlags
& MCI_OPEN_TYPE
) && !
881 (dwFlags
& MCI_OPEN_TYPE_ID
) &&
882 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16
->lpstrDeviceType
)))
883 FIXME("bad free line=%d\n", __LINE__
);
884 if ((dwFlags
& MCI_OPEN_ELEMENT
) &&
885 !(dwFlags
& MCI_OPEN_ELEMENT_ID
) &&
886 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16
->lpstrElementName
)))
887 FIXME("bad free line=%d\n", __LINE__
);
888 if ((dwFlags
& MCI_OPEN_ALIAS
) &&
889 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16
->lpstrAlias
)))
890 FIXME("bad free line=%d\n", __LINE__
);
892 if (!SEGPTR_FREE((char*)mop16
- sizeof(LPMCI_OPEN_PARMSA
)))
893 FIXME("bad free line=%d\n", __LINE__
);
913 /* case MCI_SETTIMECODE:*/
914 /* case MCI_SIGNAL:*/
920 case MCI_DEVTYPE_DIGITAL_VIDEO
:
922 LPMCI_DGV_STATUS_PARMS16 mdsp16
= (LPMCI_DGV_STATUS_PARMS16
)PTR_SEG_TO_LIN(lParam
);
923 LPMCI_DGV_STATUS_PARMSA mdsp32a
= *(LPMCI_DGV_STATUS_PARMSA
*)((char*)mdsp16
- sizeof(LPMCI_DGV_STATUS_PARMSA
));
926 mdsp32a
->dwReturn
= mdsp16
->dwReturn
;
927 if (dwFlags
& MCI_DGV_STATUS_DISKSPACE
) {
928 TRACE("MCI_STATUS (DGV) lpstrDrive=%p\n", mdsp16
->lpstrDrive
);
929 TRACE("MCI_STATUS (DGV) lpstrDrive=%s\n", (LPSTR
)PTR_SEG_TO_LIN(mdsp16
->lpstrDrive
));
931 /* FIXME: see map function */
932 strcpy(mdsp32a
->lpstrDrive
, (LPSTR
)PTR_SEG_TO_LIN(mdsp16
->lpstrDrive
));
935 if (!SEGPTR_FREE((char*)mdsp16
- sizeof(LPMCI_DGV_STATUS_PARMSA
)))
936 FIXME("bad free line=%d\n", __LINE__
);
938 return MCI_MAP_NOMEM
;
941 return MCI_MAP_OKMEM
;
942 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME("NIY vcr\n"); return MCI_MAP_NOMEM
;
943 default: size
= sizeof(MCI_STATUS_PARMS
); break;
952 LPMCI_SYSINFO_PARMS16 msip16
= (LPMCI_SYSINFO_PARMS16
)PTR_SEG_TO_LIN(lParam
);
953 LPMCI_SYSINFO_PARMSA msip32a
= *(LPMCI_SYSINFO_PARMSA
*)((char*)msip16
- sizeof(LPMCI_SYSINFO_PARMSA
));
956 msip16
->dwCallback
= msip32a
->dwCallback
;
957 memcpy(msip32a
->lpstrReturn
, PTR_SEG_TO_LIN(msip16
->lpstrReturn
), msip32a
->dwRetSize
);
958 if (!SEGPTR_FREE(PTR_SEG_TO_LIN(msip16
->lpstrReturn
)))
959 FIXME("bad free line=%d\n", __LINE__
);
961 if (!SEGPTR_FREE((char*)msip16
- sizeof(LPMCI_SYSINFO_PARMSA
)))
962 FIXME("bad free line=%d\n", __LINE__
);
964 return MCI_MAP_NOMEM
;
967 return MCI_MAP_OKMEM
;
975 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_RECT_PARMS16
); map
= 0x0001111B; kept
= TRUE
; break;
976 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_RECT_PARMS16
); map
= 0x0001111B; kept
= TRUE
; break;
982 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_WINDOW_PARMS16
); if (dwFlags
& MCI_DGV_WINDOW_TEXT
) map
= 0x7666; break;
983 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_WINDOW_PARMS16
); if (dwFlags
& MCI_OVLY_WINDOW_TEXT
) map
= 0x7666; break;
986 /* FIXME: see map function */
996 case DRV_QUERYCONFIGURE
:
999 case DRV_EXITSESSION
:
1000 case DRV_EXITAPPLICATION
:
1002 FIXME("This is a hack\n");
1003 return MCI_MAP_PASS
;
1005 FIXME("Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg
));
1006 return MCI_MAP_MSGERROR
;
1008 return MCI_MsgMapper32To16_Destroy((void*)lParam
, size
, map
, kept
);
1011 /**************************************************************************
1012 * MCI_SendCommandFrom32 [internal]
1014 DWORD
MCI_SendCommandFrom32(UINT wDevID
, UINT16 wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1016 DWORD dwRet
= MCIERR_DEVICE_NOT_INSTALLED
;
1018 if (!MCI_DevIDValid(wDevID
)) {
1019 dwRet
= MCIERR_INVALID_DEVICE_ID
;
1021 switch (DRIVER_GetType(MCI_GetDrv(wDevID
)->hDrv
)) {
1022 case WINE_DI_TYPE_16
:
1026 switch (res
= MCI_MapMsg32ATo16(MCI_GetDrv(wDevID
)->modp
.wType
, wMsg
, dwParam1
, &dwParam2
)) {
1027 case MCI_MAP_MSGERROR
:
1028 TRACE("Not handled yet (%s)\n", MCI_CommandToString(wMsg
));
1029 dwRet
= MCIERR_DRIVER_INTERNAL
;
1032 TRACE("Problem mapping msg=%s from 32a to 16\n", MCI_CommandToString(wMsg
));
1033 dwRet
= MCIERR_OUT_OF_MEMORY
;
1037 dwRet
= SendDriverMessage16(MCI_GetDrv(wDevID
)->hDrv
, wMsg
, dwParam1
, dwParam2
);
1038 if (res
== MCI_MAP_OKMEM
)
1039 MCI_UnMapMsg32ATo16(MCI_GetDrv(wDevID
)->modp
.wType
, wMsg
, dwParam1
, dwParam2
);
1042 dwRet
= SendDriverMessage(MCI_GetDrv(wDevID
)->hDrv
, wMsg
, dwParam1
, dwParam2
);
1047 case WINE_DI_TYPE_32
:
1048 dwRet
= SendDriverMessage(MCI_GetDrv(wDevID
)->hDrv
, wMsg
, dwParam1
, dwParam2
);
1051 WARN("Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID
)->hDrv
));
1052 dwRet
= MCIERR_DRIVER_INTERNAL
;
1058 /**************************************************************************
1059 * MCI_SendCommandFrom16 [internal]
1061 DWORD
MCI_SendCommandFrom16(UINT wDevID
, UINT16 wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1063 DWORD dwRet
= MCIERR_DEVICE_NOT_INSTALLED
;
1065 if (!MCI_DevIDValid(wDevID
)) {
1066 dwRet
= MCIERR_INVALID_DEVICE_ID
;
1070 switch (DRIVER_GetType(MCI_GetDrv(wDevID
)->hDrv
)) {
1071 case WINE_DI_TYPE_16
:
1072 dwRet
= SendDriverMessage16(MCI_GetDrv(wDevID
)->hDrv
, wMsg
, dwParam1
, dwParam2
);
1074 case WINE_DI_TYPE_32
:
1075 switch (res
= MCI_MapMsg16To32A(MCI_GetDrv(wDevID
)->modp
.wType
, wMsg
, &dwParam2
)) {
1076 case MCI_MAP_MSGERROR
:
1077 TRACE("Not handled yet (%s)\n", MCI_CommandToString(wMsg
));
1078 dwRet
= MCIERR_DRIVER_INTERNAL
;
1081 TRACE("Problem mapping msg=%s from 16 to 32a\n", MCI_CommandToString(wMsg
));
1082 dwRet
= MCIERR_OUT_OF_MEMORY
;
1086 dwRet
= SendDriverMessage(wDevID
, wMsg
, dwParam1
, dwParam2
);
1087 if (res
== MCI_MAP_OKMEM
)
1088 MCI_UnMapMsg16To32A(MCI_GetDrv(wDevID
)->modp
.wType
, wMsg
, dwParam2
);
1091 dwRet
= SendDriverMessage16(MCI_GetDrv(wDevID
)->hDrv
, wMsg
, dwParam1
, dwParam2
);
1096 WARN("Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID
)->hDrv
));
1097 dwRet
= MCIERR_DRIVER_INTERNAL
;
1103 /**************************************************************************
1104 * MCI_Open [internal]
1106 DWORD
MCI_Open(DWORD dwParam
, LPMCI_OPEN_PARMSA lpParms
)
1108 char strDevTyp
[128];
1109 UINT16 uDevType
= 0;
1110 UINT16 wDevID
= MCI_FirstDevID();
1113 MCI_OPEN_DRIVER_PARMSA modp
;
1116 TRACE("(%08lX, %p)\n", dwParam
, lpParms
);
1117 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
1119 /* only two low bytes are generic, the other ones are dev type specific */
1120 #define WINE_MCI_SUPP (0xFFFF0000|MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY|MCI_WAIT)
1121 if ((dwParam
& ~WINE_MCI_SUPP
) != 0) {
1122 FIXME("Unsupported yet dwFlags=%08lX\n", dwParam
& ~WINE_MCI_SUPP
);
1124 #undef WINE_MCI_SUPP
1126 while (MCI_GetDrv(wDevID
)->modp
.wType
!= 0) {
1127 wDevID
= MCI_NextDevID(wDevID
);
1128 if (!MCI_DevIDValid(wDevID
)) {
1129 TRACE("MAXMCIDRIVERS reached !\n");
1130 return MCIERR_OUT_OF_MEMORY
;
1134 TRACE("wDevID=%04X \n", wDevID
);
1135 memcpy(MCI_GetOpenDrv(wDevID
), lpParms
, sizeof(*lpParms
));
1139 if (dwParam
& MCI_OPEN_ELEMENT
) {
1142 TRACE("lpstrElementName='%s'\n", lpParms
->lpstrElementName
);
1143 t
= strrchr(lpParms
->lpstrElementName
, '.');
1145 GetProfileStringA("mci extensions", t
+1, "*", strDevTyp
, sizeof(strDevTyp
));
1146 if (strcmp(strDevTyp
, "*") == 0) {
1147 TRACE("No [mci extensions] entry for %s found.\n", t
);
1148 return MCIERR_EXTENSION_NOT_FOUND
;
1150 TRACE("Extension %s is mapped to type %s\n", t
, strDevTyp
);
1151 } else if (GetDriveTypeA(lpParms
->lpstrElementName
) == DRIVE_CDROM
) {
1152 /* FIXME: this will not work if several CDROM drives are installed on the machine */
1153 strcpy(strDevTyp
, "CDAUDIO");
1155 return MCIERR_EXTENSION_NOT_FOUND
;
1159 if (dwParam
& MCI_OPEN_ALIAS
) {
1160 TRACE("Alias='%s' !\n", lpParms
->lpstrAlias
);
1161 /* FIXME is there any memory leak here ? */
1162 MCI_GetOpenDrv(wDevID
)->lpstrAlias
= strdup(lpParms
->lpstrAlias
);
1163 /* mplayer does allocate alias to CDAUDIO */
1165 MCI_GetOpenDrv(wDevID
)->lpstrAlias
= NULL
;
1166 if (dwParam
& MCI_OPEN_TYPE
) {
1167 if (dwParam
& MCI_OPEN_TYPE_ID
) {
1169 TRACE("Dev=%08lx!\n", (DWORD
)lpParms
->lpstrDeviceType
);
1170 uDevType
= LOWORD((DWORD
)lpParms
->lpstrDeviceType
);
1171 MCI_GetOpenDrv(wDevID
)->lpstrDeviceType
= lpParms
->lpstrDeviceType
;
1173 if (LOWORD((DWORD
)lpParms
->lpstrDeviceType
) != MCI_DEVTYPE_CD_AUDIO
) {
1174 FIXME("MCI_OPEN_TYPE_ID is no longer properly supported\n");
1176 strcpy(strDevTyp
, "CDAUDIO");
1178 if (lpParms
->lpstrDeviceType
== NULL
)
1179 return MCIERR_NULL_PARAMETER_BLOCK
;
1180 TRACE("Dev='%s' !\n", lpParms
->lpstrDeviceType
);
1181 strcpy(strDevTyp
, lpParms
->lpstrDeviceType
);
1185 if (strDevTyp
[0] == 0) {
1186 FIXME("Couldn't load driver\n");
1187 return MCIERR_DRIVER_INTERNAL
;
1190 CharUpperA(strDevTyp
);
1192 modp
.wDeviceID
= wDevID
;
1193 modp
.lpstrParams
= NULL
;
1195 /* FIXME: this is a hack... some MCI drivers, while being open, call
1196 * mciSetData, which lookup for non empty slots in MCI table list
1197 * Unfortunatly, open slots are known when wType == 0...
1198 * so use a dummy type, just to keep on going. May be wType == 0 is
1199 * not the best solution to indicate empty slot in MCI drivers table
1201 MCI_GetDrv(wDevID
)->modp
.wType
= MCI_DEVTYPE_CD_AUDIO
;
1202 hDrv
= OpenDriverA(strDevTyp
, "mci", (LPARAM
)&modp
);
1205 FIXME("Couldn't load driver for type %s.\n", strDevTyp
);
1206 return MCIERR_DEVICE_NOT_INSTALLED
;
1208 uDevType
= modp
.wType
;
1209 MCI_GetDrv(wDevID
)->hDrv
= hDrv
;
1211 TRACE("Loaded driver %u (%s), type is %d\n", hDrv
, strDevTyp
, uDevType
);
1213 MCI_GetDrv(wDevID
)->mop
.lpstrDeviceType
= strdup(strDevTyp
);
1214 MCI_GetDrv(wDevID
)->modp
.wType
= uDevType
;
1215 MCI_GetDrv(wDevID
)->modp
.wDeviceID
= 0; /* FIXME? for multiple devices */
1217 lpParms
->wDeviceID
= wDevID
;
1219 TRACE("mcidev=%d, uDevType=%04X wDeviceID=%04X !\n",
1220 wDevID
, uDevType
, lpParms
->wDeviceID
);
1222 MCI_GetDrv(wDevID
)->lpfnYieldProc
= MCI_DefYieldProc
;
1223 MCI_GetDrv(wDevID
)->dwYieldData
= VK_CANCEL
;
1224 MCI_GetDrv(wDevID
)->hCreatorTask
= GetCurrentTask();
1225 MCI_GetDrv(wDevID
)->dwPrivate
= 0;
1227 dwRet
= MCI_SendCommandFrom32(wDevID
, MCI_OPEN_DRIVER
, dwParam
, (DWORD
)lpParms
);
1230 /* only handled devices fall through */
1231 TRACE("wDevID = %04X wDeviceID = %d dwRet = %ld\n", wDevID
, lpParms
->wDeviceID
, dwRet
);
1233 TRACE("Failed to open driver (MCI_OPEN_DRIVER msg) [%08lx], closing\n", dwRet
);
1234 MCI_GetDrv(wDevID
)->modp
.wType
= 0;
1236 if (dwParam
& MCI_NOTIFY
)
1237 mciDriverNotify16(lpParms
->dwCallback
, wDevID
, dwRet
== 0 ? MCI_NOTIFY_SUCCESSFUL
: MCI_NOTIFY_FAILURE
);
1242 /**************************************************************************
1243 * MCI_Close [internal]
1245 DWORD
MCI_Close(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
1249 TRACE("(%04x, %08lX, %p)\n", wDevID
, dwParam
, lpParms
);
1251 if (wDevID
== MCI_ALL_DEVICE_ID
) {
1252 FIXME("unhandled MCI_ALL_DEVICE_ID\n");
1253 return MCIERR_CANNOT_USE_ALL
;
1256 dwRet
= MCI_SendCommandFrom32(wDevID
, MCI_CLOSE_DRIVER
, dwParam
, (DWORD
)lpParms
);
1257 if (MCI_GetDrv(wDevID
)->hDrv
) {
1259 CloseDriver(MCI_GetDrv(wDevID
)->hDrv
, 0, 0);
1262 MCI_GetDrv(wDevID
)->modp
.wType
= 0;
1263 free(MCI_GetDrv(wDevID
)->mop
.lpstrDeviceType
);
1265 if (dwParam
& MCI_NOTIFY
)
1266 mciDriverNotify16(lpParms
->dwCallback
, wDevID
,
1267 (dwRet
== 0) ? MCI_NOTIFY_SUCCESSFUL
: MCI_NOTIFY_FAILURE
);
1272 /**************************************************************************
1273 * MCI_WriteString [internal]
1275 DWORD
MCI_WriteString(LPSTR lpDstStr
, DWORD dstSize
, LPCSTR lpSrcStr
)
1279 if (dstSize
<= strlen(lpSrcStr
)) {
1280 lstrcpynA(lpDstStr
, lpSrcStr
, dstSize
- 1);
1281 ret
= MCIERR_PARAM_OVERFLOW
;
1283 strcpy(lpDstStr
, lpSrcStr
);
1289 /**************************************************************************
1290 * MCI_Sysinfo [internal]
1292 DWORD
MCI_SysInfo(UINT uDevID
, DWORD dwFlags
, LPMCI_SYSINFO_PARMSA lpParms
)
1294 DWORD ret
= MCIERR_INVALID_DEVICE_ID
;
1296 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
1298 TRACE("(%08x, %08lX, %08lX[num=%ld, wDevTyp=%u])\n",
1299 uDevID
, dwFlags
, (DWORD
)lpParms
, lpParms
->dwNumber
, lpParms
->wDeviceType
);
1301 switch (dwFlags
& ~MCI_SYSINFO_OPEN
) {
1302 case MCI_SYSINFO_QUANTITY
:
1307 if (lpParms
->wDeviceType
< MCI_DEVTYPE_FIRST
|| lpParms
->wDeviceType
> MCI_DEVTYPE_LAST
) {
1308 if (dwFlags
& MCI_SYSINFO_OPEN
) {
1309 TRACE("MCI_SYSINFO_QUANTITY: # of open MCI drivers\n");
1310 for (i
= 0; i
< MAXMCIDRIVERS
; i
++) {
1311 if (mciDrv
[i
].modp
.wType
!= 0) cnt
++;
1314 TRACE("MCI_SYSINFO_QUANTITY: # of installed MCI drivers\n");
1315 cnt
= mciInstalledCount
;
1318 if (dwFlags
& MCI_SYSINFO_OPEN
) {
1319 TRACE("MCI_SYSINFO_QUANTITY: # of open MCI drivers of type %u\n", lpParms
->wDeviceType
);
1320 for (i
= 0; i
< MAXMCIDRIVERS
; i
++) {
1321 if (mciDrv
[i
].modp
.wType
== lpParms
->wDeviceType
) cnt
++;
1324 TRACE("MCI_SYSINFO_QUANTITY: # of installed MCI drivers of type %u\n", lpParms
->wDeviceType
);
1325 FIXME("Don't know how to get # of MCI devices of a given type\n");
1329 *(DWORD
*)lpParms
->lpstrReturn
= cnt
;
1331 TRACE("(%ld) => '%ld'\n", lpParms
->dwNumber
, *(DWORD
*)lpParms
->lpstrReturn
);
1334 case MCI_SYSINFO_INSTALLNAME
:
1335 TRACE("MCI_SYSINFO_INSTALLNAME \n");
1336 if (MCI_DevIDValid(uDevID
)) {
1337 ret
= MCI_WriteString(lpParms
->lpstrReturn
, lpParms
->dwRetSize
, MCI_GetDrv(uDevID
)->mop
.lpstrDeviceType
);
1339 *lpParms
->lpstrReturn
= 0;
1340 ret
= MCIERR_INVALID_DEVICE_ID
;
1342 TRACE("(%ld) => '%s'\n", lpParms
->dwNumber
, lpParms
->lpstrReturn
);
1344 case MCI_SYSINFO_NAME
:
1345 TRACE("MCI_SYSINFO_NAME\n");
1346 if (dwFlags
& MCI_SYSINFO_OPEN
) {
1347 FIXME("Don't handle MCI_SYSINFO_NAME|MCI_SYSINFO_OPEN (yet)\n");
1348 ret
= MCIERR_UNRECOGNIZED_COMMAND
;
1349 } else if (lpParms
->dwNumber
> mciInstalledCount
) {
1350 ret
= MCIERR_OUTOFRANGE
;
1352 DWORD count
= lpParms
->dwNumber
;
1353 LPSTR ptr
= lpmciInstallNames
;
1355 while (--count
> 0) ptr
+= strlen(ptr
) + 1;
1356 ret
= MCI_WriteString(lpParms
->lpstrReturn
, lpParms
->dwRetSize
, ptr
);
1358 TRACE("(%ld) => '%s'\n", lpParms
->dwNumber
, lpParms
->lpstrReturn
);
1361 TRACE("Unsupported flag value=%08lx\n", dwFlags
);
1362 ret
= MCIERR_UNRECOGNIZED_COMMAND
;
1367 /**************************************************************************
1368 * MCI_Break [internal]
1370 DWORD
MCI_Break(UINT wDevID
, DWORD dwFlags
, LPMCI_BREAK_PARMS lpParms
)
1374 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
1376 if (dwFlags
& MCI_NOTIFY
)
1377 mciDriverNotify16(lpParms
->dwCallback
, wDevID
,
1378 (dwRet
== 0) ? MCI_NOTIFY_SUCCESSFUL
: MCI_NOTIFY_FAILURE
);
1391 DWORD WINAPI
mciSendCommandA(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
);
1393 /**************************************************************************
1394 * MCI_SCAStarter [internal]
1396 static DWORD CALLBACK
MCI_SCAStarter(LPVOID arg
)
1398 struct SCA
* sca
= (struct SCA
*)arg
;
1401 TRACE("In thread before async command (%08x,%s,%08lx,%08lx)\n",
1402 sca
->wDevID
, MCI_CommandToString(sca
->wMsg
), sca
->dwParam1
, sca
->dwParam2
);
1403 ret
= mciSendCommandA(sca
->wDevID
, sca
->wMsg
, sca
->dwParam1
| MCI_WAIT
, sca
->dwParam2
);
1404 TRACE("In thread after async command (%08x,%s,%08lx,%08lx)\n",
1405 sca
->wDevID
, MCI_CommandToString(sca
->wMsg
), sca
->dwParam1
, sca
->dwParam2
);
1406 if (sca
->allocatedCopy
)
1407 HeapFree(GetProcessHeap(), 0, (LPVOID
)sca
->dwParam2
);
1408 HeapFree(GetProcessHeap(), 0, sca
);
1410 WARN("Should not happen ? what's wrong \n");
1411 /* should not go after this point */
1415 /**************************************************************************
1416 * MCI_SendCommandAsync [internal]
1418 DWORD
MCI_SendCommandAsync(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
, UINT size
)
1420 struct SCA
* sca
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA
));
1423 return MCIERR_OUT_OF_MEMORY
;
1425 sca
->wDevID
= wDevID
;
1427 sca
->dwParam1
= dwParam1
;
1430 sca
->dwParam2
= (DWORD
)HeapAlloc(GetProcessHeap(), 0, size
);
1431 if (sca
->dwParam2
== 0) {
1432 HeapFree(GetProcessHeap(), 0, sca
);
1433 return MCIERR_OUT_OF_MEMORY
;
1435 sca
->allocatedCopy
= TRUE
;
1436 /* copy structure passed by program in dwParam2 to be sure
1437 * we can still use it whatever the program does
1439 memcpy((LPVOID
)sca
->dwParam2
, (LPVOID
)dwParam2
, size
);
1441 sca
->dwParam2
= dwParam2
;
1442 sca
->allocatedCopy
= FALSE
;
1445 if (CreateThread(NULL
, 0, MCI_SCAStarter
, sca
, 0, NULL
) == 0) {
1446 WARN("Couldn't allocate thread for async command handling, sending synchonously\n");
1447 return MCI_SCAStarter(&sca
);
1452 /**************************************************************************
1453 * MCI_CleanUp [internal]
1455 * Some MCI commands need to be cleaned-up (when not called from
1456 * mciSendString), because MCI drivers return extra information for string
1457 * transformation. This function gets read of them.
1459 LRESULT
MCI_CleanUp(LRESULT dwRet
, UINT wMsg
, DWORD dwParam2
, BOOL bIs32
)
1462 case MCI_GETDEVCAPS
:
1463 switch (dwRet
& 0xFFFF0000ul
) {
1466 case MCI_RESOURCE_RETURNED
:
1467 case MCI_RESOURCE_RETURNED
|MCI_RESOURCE_DRIVER
:
1468 case MCI_COLONIZED3_RETURN
:
1469 case MCI_COLONIZED4_RETURN
:
1470 case MCI_INTEGER_RETURNED
:
1472 LPMCI_GETDEVCAPS_PARMS lmgp
= (LPMCI_GETDEVCAPS_PARMS
)(bIs32
? (void*)dwParam2
: PTR_SEG_TO_LIN(dwParam2
));
1474 dwRet
= LOWORD(dwRet
);
1475 TRACE("Changing %08lx to %08lx\n", lmgp
->dwReturn
, (DWORD
)LOWORD(lmgp
->dwReturn
));
1477 lmgp
->dwReturn
= LOWORD(lmgp
->dwReturn
);
1481 FIXME("Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet
));
1485 switch (dwRet
& 0xFFFF0000ul
) {
1488 case MCI_RESOURCE_RETURNED
:
1489 case MCI_RESOURCE_RETURNED
|MCI_RESOURCE_DRIVER
:
1490 case MCI_COLONIZED3_RETURN
:
1491 case MCI_COLONIZED4_RETURN
:
1492 case MCI_INTEGER_RETURNED
:
1494 LPMCI_STATUS_PARMS lsp
= (LPMCI_STATUS_PARMS
)(bIs32
? (void*)dwParam2
: PTR_SEG_TO_LIN(dwParam2
));
1496 dwRet
= LOWORD(dwRet
);
1497 TRACE("Changing %08lx to %08lx\n", lsp
->dwReturn
,(DWORD
) LOWORD(lsp
->dwReturn
));
1498 lsp
->dwReturn
= LOWORD(lsp
->dwReturn
);
1502 FIXME("Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet
));
1511 /**************************************************************************
1512 * MULTIMEDIA_MciInit [internal]
1514 * Initializes the MCI internal variables.
1517 BOOL
MULTIMEDIA_MciInit(void)
1521 mciInstalledCount
= 0;
1522 ptr1
= lpmciInstallNames
= malloc(2048);
1524 if (!lpmciInstallNames
)
1527 /* FIXME: should do also some registry diving here */
1528 if (PROFILE_GetWineIniString("options", "mci", "", lpmciInstallNames
, 2048) > 0) {
1529 TRACE_(mci
)("Wine => '%s' \n", ptr1
);
1530 while ((ptr2
= strchr(ptr1
, ':')) != 0) {
1532 TRACE_(mci
)("---> '%s' \n", ptr1
);
1533 mciInstalledCount
++;
1536 mciInstalledCount
++;
1537 TRACE_(mci
)("---> '%s' \n", ptr1
);
1538 ptr1
+= strlen(ptr1
) + 1;
1540 GetPrivateProfileStringA("mci", NULL
, "", lpmciInstallNames
, 2048, "SYSTEM.INI");
1541 while (strlen(ptr1
) > 0) {
1542 TRACE_(mci
)("---> '%s' \n", ptr1
);
1543 ptr1
+= (strlen(ptr1
) + 1);
1544 mciInstalledCount
++;
1547 mciInstalledListLen
= ptr1
- lpmciInstallNames
;