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"
23 DEFAULT_DEBUG_CHANNEL(mci
)
25 WINE_MCIDRIVER mciDrv
[MAXMCIDRIVERS
];
27 int mciInstalledCount
;
28 int mciInstalledListLen
;
29 LPSTR lpmciInstallNames
= NULL
;
31 /* The wDevID's returned by wine were originally in the range
32 * 0 - (MAXMCIDRIVERS - 1) and used directly as array indices.
33 * Unfortunately, ms-windows uses wDevID of zero to indicate
34 * errors. Now, multimedia drivers must pass the wDevID through
35 * MCI_DevIDToIndex to get an index in that range. An
36 * arbitrary value, MCI_MAGIC is added to the wDevID seen
37 * by the windows programs.
40 #define MCI_MAGIC 0x0F00
42 MCI_WineDesc MCI_InternalDescriptors
[] = {
43 {MCI_DEVTYPE_CD_AUDIO
, "CDAUDIO", MCICDAUDIO_DriverProc
},
44 {MCI_DEVTYPE_WAVEFORM_AUDIO
, "WAVEAUDIO", MCIWAVE_DriverProc
},
45 {MCI_DEVTYPE_SEQUENCER
, "SEQUENCER", MCIMIDI_DriverProc
},
46 {MCI_DEVTYPE_ANIMATION
, "ANIMATION1", MCIANIM_DriverProc
},
47 {MCI_DEVTYPE_DIGITAL_VIDEO
, "AVIVIDEO", MCIAVI_DriverProc
},
49 {0xFFFF, NULL
, NULL
} /* sentinel */
53 /**************************************************************************
54 * MCI_GetDevTypeString [internal]
56 static LPCSTR
MCI_GetDevTypeString(WORD uDevType
)
58 LPCSTR str
= "??? MCI ???";
61 for (i
= 0; MCI_InternalDescriptors
[i
].uDevType
!= 0xFFFF; i
++) {
62 if (MCI_InternalDescriptors
[i
].uDevType
!= 0 &&
63 MCI_InternalDescriptors
[i
].uDevType
== uDevType
) {
64 str
= MCI_InternalDescriptors
[i
].lpstrName
;
68 /* TRACE(mci, "devType=%u => %s\n", uDevType, str);*/
73 /**************************************************************************
74 * MCI_GetProc [internal]
76 static MCIPROC
MCI_GetProc(UINT16 uDevType
)
81 for (i
= 0; MCI_InternalDescriptors
[i
].uDevType
!= 0xFFFF; i
++) {
82 if (MCI_InternalDescriptors
[i
].uDevType
!= 0 &&
83 MCI_InternalDescriptors
[i
].uDevType
== uDevType
) {
84 proc
= MCI_InternalDescriptors
[i
].lpfnProc
;
91 /**************************************************************************
92 * MCI_GetDevType [internal]
94 WORD
MCI_GetDevType(LPCSTR str
)
99 for (i
= 0; MCI_InternalDescriptors
[i
].uDevType
!= 0xFFFF; i
++) {
100 if (MCI_InternalDescriptors
[i
].uDevType
!= 0 &&
101 strcmp(str
, MCI_InternalDescriptors
[i
].lpstrName
) == 0) {
102 uDevType
= MCI_InternalDescriptors
[i
].uDevType
;
109 /**************************************************************************
110 * MCI_DevIDToIndex [internal]
112 int MCI_DevIDToIndex(UINT16 wDevID
)
114 return wDevID
- MCI_MAGIC
;
117 /**************************************************************************
118 * MCI_FirstDevId [internal]
120 UINT16
MCI_FirstDevID(void)
125 /**************************************************************************
126 * MCI_NextDevId [internal]
128 UINT16
MCI_NextDevID(UINT16 wDevID
)
133 /**************************************************************************
134 * MCI_DevIDValid [internal]
136 BOOL
MCI_DevIDValid(UINT16 wDevID
)
138 return wDevID
>= MCI_MAGIC
&& wDevID
< (MCI_MAGIC
+ MAXMCIDRIVERS
);
141 /**************************************************************************
142 * MCI_CommandToString [internal]
144 const char* MCI_CommandToString(UINT16 wMsg
)
146 static char buffer
[100];
148 #define CASE(s) case (s): return #s
153 CASE(MCI_CLOSE_DRIVER
);
162 CASE(MCI_GETDEVCAPS
);
166 CASE(MCI_OPEN_DRIVER
);
185 sprintf(buffer
, "MCI_<<%04X>>", wMsg
);
191 /**************************************************************************
192 * MCI_MapMsg16To32A [internal]
194 int MCI_MapMsg16To32A(WORD uDevType
, WORD wMsg
, DWORD
* lParam
)
198 /* FIXME: to add also (with seg/linear modifications to do):
199 * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
200 * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
203 /* case MCI_CAPTURE */
205 case MCI_CLOSE_DRIVER
:
206 /* case MCI_CONFIGURE:*/
213 /* case MCI_INDEX: */
215 /* case MCI_MONITOR: */
225 /* case MCI_SETTIMECODE:*/
226 /* case MCI_SIGNAL:*/
228 case MCI_STATUS
: /* FIXME: is wrong for digital video */
235 *lParam
= (DWORD
)PTR_SEG_TO_LIN(*lParam
);
238 /* in fact, I would also need the dwFlags... to see
239 * which members of lParam are effectively used
241 *lParam
= (DWORD
)PTR_SEG_TO_LIN(*lParam
);
242 FIXME(mci
, "Current mapping may be wrong\n");
246 LPMCI_BREAK_PARMS mbp32
= HeapAlloc(SystemHeap
, 0, sizeof(MCI_BREAK_PARMS
));
247 LPMCI_BREAK_PARMS16 mbp16
= PTR_SEG_TO_LIN(*lParam
);
250 mbp32
->dwCallback
= mbp16
->dwCallback
;
251 mbp32
->nVirtKey
= mbp16
->nVirtKey
;
252 mbp32
->hwndBreak
= mbp16
->hwndBreak
;
256 *lParam
= (DWORD
)mbp32
;
261 LPMCI_VD_ESCAPE_PARMSA mvep32a
= HeapAlloc(SystemHeap
, 0, sizeof(MCI_VD_ESCAPE_PARMSA
));
262 LPMCI_VD_ESCAPE_PARMS16 mvep16
= PTR_SEG_TO_LIN(*lParam
);
265 mvep32a
->dwCallback
= mvep16
->dwCallback
;
266 mvep32a
->lpstrCommand
= PTR_SEG_TO_LIN(mvep16
->lpstrCommand
);
270 *lParam
= (DWORD
)mvep32a
;
275 LPMCI_INFO_PARMSA mip32a
= HeapAlloc(SystemHeap
, 0, sizeof(MCI_INFO_PARMSA
));
276 LPMCI_INFO_PARMS16 mip16
= PTR_SEG_TO_LIN(*lParam
);
278 /* FIXME this is wrong if device is of type
279 * MCI_DEVTYPE_DIGITAL_VIDEO, some members are not mapped
282 mip32a
->dwCallback
= mip16
->dwCallback
;
283 mip32a
->lpstrReturn
= PTR_SEG_TO_LIN(mip16
->lpstrReturn
);
284 mip32a
->dwRetSize
= mip16
->dwRetSize
;
288 *lParam
= (DWORD
)mip32a
;
292 case MCI_OPEN_DRIVER
:
294 LPMCI_OPEN_PARMSA mop32a
= HeapAlloc(SystemHeap
, 0, sizeof(LPMCI_OPEN_PARMS16
) + sizeof(MCI_OPEN_PARMSA
) + 2 * sizeof(DWORD
));
295 LPMCI_OPEN_PARMS16 mop16
= PTR_SEG_TO_LIN(*lParam
);
298 *(LPMCI_OPEN_PARMS16
*)(mop32a
) = mop16
;
299 mop32a
= (LPMCI_OPEN_PARMSA
)((char*)mop32a
+ sizeof(LPMCI_OPEN_PARMS16
));
300 mop32a
->dwCallback
= mop16
->dwCallback
;
301 mop32a
->wDeviceID
= mop16
->wDeviceID
;
302 mop32a
->lpstrDeviceType
= PTR_SEG_TO_LIN(mop16
->lpstrDeviceType
);
303 mop32a
->lpstrElementName
= PTR_SEG_TO_LIN(mop16
->lpstrElementName
);
304 mop32a
->lpstrAlias
= PTR_SEG_TO_LIN(mop16
->lpstrAlias
);
305 /* copy extended information if any...
306 * FIXME: this may seg fault if initial structure does not contain them and
307 * the reads after msip16 fail under LDT limits...
308 * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
309 * should not take care of extended parameters, and should be used by MCI_Open
310 * to fetch uDevType. When, this is known, the mapping for sending the
311 * MCI_OPEN_DRIVER shall be done depending on uDevType.
313 memcpy(mop32a
+ 1, mop16
+ 1, 2 * sizeof(DWORD
));
317 *lParam
= (DWORD
)mop32a
;
322 LPMCI_SYSINFO_PARMSA msip32a
= HeapAlloc(SystemHeap
, 0, sizeof(MCI_SYSINFO_PARMSA
));
323 LPMCI_SYSINFO_PARMS16 msip16
= PTR_SEG_TO_LIN(*lParam
);
326 msip32a
->dwCallback
= msip16
->dwCallback
;
327 msip32a
->lpstrReturn
= PTR_SEG_TO_LIN(msip16
->lpstrReturn
);
328 msip32a
->dwRetSize
= msip16
->dwRetSize
;
329 msip32a
->dwNumber
= msip16
->dwNumber
;
330 msip32a
->wDeviceType
= msip16
->wDeviceType
;
334 *lParam
= (DWORD
)msip32a
;
344 case DRV_QUERYCONFIGURE
:
347 case DRV_EXITSESSION
:
348 case DRV_EXITAPPLICATION
:
350 FIXME(mci
, "This is a hack\n");
354 WARN(mci
, "Don't know how to map msg=%s\n", MCI_CommandToString(wMsg
));
359 /**************************************************************************
360 * MCI_UnMapMsg16To32A [internal]
362 int MCI_UnMapMsg16To32A(WORD uDevType
, WORD wMsg
, DWORD lParam
)
365 /* case MCI_CAPTURE */
367 case MCI_CLOSE_DRIVER
:
368 /* case MCI_CONFIGURE:*/
375 /* case MCI_INDEX: */
377 /* case MCI_MONITOR: */
387 /* case MCI_SETTIMECODE:*/
388 /* case MCI_SIGNAL:*/
400 /* FIXME ?? see Map function */
407 HeapFree(SystemHeap
, 0, (LPVOID
)lParam
);
410 case MCI_OPEN_DRIVER
:
412 LPMCI_OPEN_PARMSA mop32a
= (LPMCI_OPEN_PARMSA
)lParam
;
413 LPMCI_OPEN_PARMS16 mop16
= *(LPMCI_OPEN_PARMS16
*)((char*)mop32a
- sizeof(LPMCI_OPEN_PARMS16
*));
415 mop16
->wDeviceID
= mop32a
->wDeviceID
;
416 if (!HeapFree(SystemHeap
, 0, (LPVOID
)(lParam
- sizeof(LPMCI_OPEN_PARMS16
))))
417 FIXME(mci
, "bad free line=%d\n", __LINE__
);
427 case DRV_QUERYCONFIGURE
:
430 case DRV_EXITSESSION
:
431 case DRV_EXITAPPLICATION
:
433 FIXME(mci
, "This is a hack\n");
436 FIXME(mci
, "Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg
));
442 /**************************************************************************
443 * MCI_MsgMapper32To16_Create [internal]
445 * Helper for MCI_MapMsg32ATo16.
446 * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit segmented pointer.
447 * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
448 * 1 : ok, some memory allocated
449 * -2 : ko, memory problem
451 static int MCI_MsgMapper32To16_Create(void** ptr
, int size
, BOOLEAN keep
)
453 void* lp
= SEGPTR_ALLOC(sizeof(void**) + size
);
460 memcpy((char*)lp
+ sizeof(void**), *ptr
, size
);
461 *ptr
= (char*)SEGPTR_GET(lp
) + sizeof(void**);
463 memcpy((char*)lp
, *ptr
, size
);
464 *ptr
= (void*)SEGPTR_GET(lp
);
470 /**************************************************************************
471 * MCI_MsgMapper32To16_Destroy [internal]
473 * Helper for MCI_UnMapMsg32ATo16.
475 static int MCI_MsgMapper32To16_Destroy(void* ptr
, int size
, BOOLEAN kept
)
478 void* msg16
= PTR_SEG_TO_LIN(ptr
);
482 alloc
= (char*)msg16
- sizeof(void**);
483 memcpy(*(void**)alloc
, msg16
, size
);
488 if (!SEGPTR_FREE(alloc
)) {
489 FIXME(mci
, "bad free line=%d\n", __LINE__
);
498 * 0001 squeeze signed 4 bytes to 2 bytes *( LPINT16)D = ( INT16)*( LPINT16)S; D += 2; S += 4
499 * 0010 squeeze unsigned 4 bytes to 2 bytes *(LPUINT16)D = (UINT16)*(LPUINT16)S; D += 2; S += 4
502 * 0110 zero 4 bytes *(DWORD)D = 0 D += 4; S += 4
503 * 0111 copy string *(LPSTR*)D = seg dup(*(LPSTR*)S) D += 4; S += 4
504 * 1xxx copy xxx + 1 bytes memcpy(D, S, xxx + 1); D += xxx+1; S += xxx+1
507 /**************************************************************************
508 * MCI_MsgMapper32To16_CreateV2 [internal]
510 * Helper for MCI_MapMsg32ATo16.
511 * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit
513 * map contains a list of action to be performed for the mapping (see list
515 * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
516 * 1 : ok, some memory allocated
517 * -2 : ko, memory problem
519 static int MCI_MsgMapper32To16_CreateV2(void** ptr
, int size16
, DWORD map
, BOOLEAN keep
)
521 void* lp
= SEGPTR_ALLOC((keep
? sizeof(void**) : 0) + size16
);
527 p32
= (LPBYTE
)(*ptr
);
530 p16
= (LPBYTE
)lp
+ sizeof(void**);
531 *ptr
= (char*)SEGPTR_GET(lp
) + sizeof(void**);
534 *ptr
= (void*)SEGPTR_GET(lp
);
538 memcpy(p16
, p32
, size16
);
546 sz
= (nibble
& 7) + 1;
547 memcpy(p16
, p32
, sz
);
550 size16
-= sz
; /* DEBUG only */
553 case 0x1: *( LPINT16
)p16
= ( INT16
)*( LPINT16
)p32
; p16
+= 2; p32
+= 4; size16
-= 2; break;
554 case 0x2: *(LPUINT16
)p16
= (UINT16
)*(LPUINT16
)p32
; p16
+= 2; p32
+= 4; size16
-= 2; break;
555 case 0x6: *(LPDWORD
)p16
= 0; p16
+= 4; p32
+= 4; size16
-= 4; break;
556 case 0x7: *(LPDWORD
)p16
= SEGPTR_GET(SEGPTR_STRDUP(*(LPSTR
*)p32
));p16
+= 4; p32
+= 4; size16
-= 4; break;
557 default: FIXME(mci
, "Unknown nibble for mapping (%x)\n", nibble
);
562 if (size16
!= 0) /* DEBUG only */
563 FIXME(mci
, "Mismatch between 16 bit struct size and map nibbles serie\n");
568 /**************************************************************************
569 * MCI_MsgMapper32To16_DestroyV2 [internal]
571 * Helper for MCI_UnMapMsg32ATo16.
573 static int MCI_MsgMapper32To16_DestroyV2(void* ptr
, int size16
, DWORD map
, BOOLEAN kept
)
576 void* msg16
= PTR_SEG_TO_LIN(ptr
);
582 alloc
= (char*)msg16
- sizeof(void**);
583 p32
= *(void**)alloc
;
587 memcpy(p32
, p16
, size16
);
592 memcpy(p32
, p16
, (nibble
& 7) + 1);
593 p16
+= (nibble
& 7) + 1;
594 p32
+= (nibble
& 7) + 1;
595 size16
-= (nibble
& 7) + 1;
598 case 0x1: *( LPINT
)p32
= *( LPINT16
)p16
; p16
+= 2; p32
+= 4; size16
-= 2; break;
599 case 0x2: *(LPUINT
)p32
= *(LPUINT16
)p16
; p16
+= 2; p32
+= 4; size16
-= 2; break;
600 case 0x6: p16
+= 4; p32
+= 4; size16
-= 4; break;
601 case 0x7: strcpy(*(LPSTR
*)p32
, PTR_SEG_TO_LIN(*(DWORD
*)p16
));
602 if (!SEGPTR_FREE(PTR_SEG_TO_LIN(*(DWORD
*)p16
))) {
603 FIXME(mci
, "bad free line=%d\n", __LINE__
);
605 p16
+= 4; p32
+= 4; size16
-= 4; break;
606 default: FIXME(mci
, "Unknown nibble for mapping (%x)\n", nibble
);
611 if (size16
!= 0) /* DEBUG only */
612 FIXME(mci
, "Mismatch between 16 bit struct size and map nibbles serie\n");
618 if (!SEGPTR_FREE(alloc
)) {
619 FIXME(mci
, "bad free line=%d\n", __LINE__
);
625 /**************************************************************************
626 * MCI_MapMsg32ATo16 [internal]
628 * Map a 32-A bit MCI message to a 16 bit MCI message.
629 * 1 : ok, some memory allocated, need to call MCI_UnMapMsg32ATo16
630 * 0 : ok, no memory allocated
631 * -1 : ko, unknown message
632 * -2 : ko, memory problem
634 int MCI_MapMsg32ATo16(WORD uDevType
, WORD wMsg
, DWORD dwFlags
, DWORD
* lParam
)
637 BOOLEAN keep
= FALSE
;
643 /* FIXME: to add also (with seg/linear modifications to do):
644 * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
645 * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
648 /* case MCI_BREAK: */
649 /* case MCI_CAPTURE */
651 case MCI_CLOSE_DRIVER
:
652 size
= sizeof(MCI_GENERIC_PARMS
);
654 /* case MCI_CONFIGURE:*/
658 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_CUE_PARMS
); break;
659 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_CUE_PARMS); break;*/ FIXME(mci
, "NIY vcr\n"); return -2;
660 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
666 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_DELETE_PARMS16
); map
= 0x0F1111FB; break;
667 case MCI_DEVTYPE_WAVEFORM_AUDIO
:size
= sizeof(MCI_WAVE_DELETE_PARMS
); break;
668 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
671 /* case MCI_ESCAPE: */
674 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_FREEZE_PARMS
); map
= 0x0001111B; break;
675 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_RECT_PARMS
); map
= 0x0001111B; break;
676 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
681 size
= sizeof(MCI_GETDEVCAPS_PARMS
);
683 /* case MCI_INDEX: */
686 LPMCI_INFO_PARMSA mip32a
= (LPMCI_INFO_PARMSA
)(*lParam
);
688 LPMCI_INFO_PARMS16 mip16
;
691 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_INFO_PARMS16
); break;
692 default: size
= sizeof(MCI_INFO_PARMS16
); break;
694 ptr
= SEGPTR_ALLOC(sizeof(LPMCI_INFO_PARMSA
) + size
);
697 *(LPMCI_INFO_PARMSA
*)ptr
= mip32a
;
698 mip16
= (LPMCI_INFO_PARMS16
)(ptr
+ sizeof(LPMCI_INFO_PARMSA
));
699 mip16
->dwCallback
= mip32a
->dwCallback
;
700 mip16
->lpstrReturn
= (LPSTR
)SEGPTR_GET(SEGPTR_ALLOC(mip32a
->dwRetSize
));
701 mip16
->dwRetSize
= mip32a
->dwRetSize
;
702 if (uDevType
== MCI_DEVTYPE_DIGITAL_VIDEO
) {
703 ((LPMCI_DGV_INFO_PARMS16
)mip16
)->dwItem
= ((LPMCI_DGV_INFO_PARMSA
)mip32a
)->dwItem
;
708 *lParam
= (LPARAM
)SEGPTR_GET(ptr
) + sizeof(LPMCI_INFO_PARMSA
);
712 /* case MCI_MONITOR: */
714 case MCI_OPEN_DRIVER
:
716 LPMCI_OPEN_PARMSA mop32a
= (LPMCI_OPEN_PARMSA
)(*lParam
);
717 char* ptr
= SEGPTR_ALLOC(sizeof(LPMCI_OPEN_PARMSA
) + sizeof(MCI_OPEN_PARMS16
) + 2 * sizeof(DWORD
));
718 LPMCI_OPEN_PARMS16 mop16
;
722 *(LPMCI_OPEN_PARMSA
*)(ptr
) = mop32a
;
723 mop16
= (LPMCI_OPEN_PARMS16
)(ptr
+ sizeof(LPMCI_OPEN_PARMSA
));
724 mop16
->dwCallback
= mop32a
->dwCallback
;
725 mop16
->wDeviceID
= mop32a
->wDeviceID
;
726 if (dwFlags
& MCI_OPEN_TYPE
) {
727 if (dwFlags
& MCI_OPEN_TYPE_ID
) {
728 /* dword "transparent" value */
729 mop16
->lpstrDeviceType
= mop32a
->lpstrDeviceType
;
732 mop16
->lpstrDeviceType
= mop32a
->lpstrDeviceType
? (LPSTR
)SEGPTR_GET(SEGPTR_STRDUP(mop32a
->lpstrDeviceType
)) : 0;
736 mop16
->lpstrDeviceType
= 0;
738 if (dwFlags
& MCI_OPEN_ELEMENT
) {
739 if (dwFlags
& MCI_OPEN_ELEMENT_ID
) {
740 mop16
->lpstrElementName
= mop32a
->lpstrElementName
;
742 mop16
->lpstrElementName
= mop32a
->lpstrElementName
? (LPSTR
)SEGPTR_GET(SEGPTR_STRDUP(mop32a
->lpstrElementName
)) : 0;
745 mop16
->lpstrElementName
= 0;
747 if (dwFlags
& MCI_OPEN_ALIAS
) {
748 mop16
->lpstrAlias
= mop32a
->lpstrAlias
? (LPSTR
)SEGPTR_GET(SEGPTR_STRDUP(mop32a
->lpstrAlias
)) : 0;
750 mop16
->lpstrAlias
= 0;
752 /* copy extended information if any...
753 * FIXME: this may seg fault if initial structure does not contain them and
754 * the reads after msip16 fail under LDT limits...
755 * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
756 * should not take care of extended parameters, and should be used by MCI_Open
757 * to fetch uDevType. When, this is known, the mapping for sending the
758 * MCI_OPEN_DRIVER shall be done depending on uDevType.
760 memcpy(mop16
+ 1, mop32a
+ 1, 2 * sizeof(DWORD
));
764 *lParam
= (LPARAM
)SEGPTR_GET(ptr
) + sizeof(LPMCI_OPEN_PARMSA
);
769 size
= sizeof(MCI_GENERIC_PARMS
);
772 size
= sizeof(MCI_PLAY_PARMS
);
776 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_RECT_PARMS16
); map
= 0x0001111B; break;
777 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_RECT_PARMS
); map
= 0x0001111B; break;
778 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
782 size
= sizeof(MCI_GENERIC_PARMS
);
786 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_RECORD_PARMS16
); map
= 0x0F1111FB; break;
787 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_RECORD_PARMS); break;*/FIXME(mci
, "NIY vcr\n"); return -2;
788 default: size
= sizeof(MCI_RECORD_PARMS
); break;
792 size
= sizeof(MCI_GENERIC_PARMS
);
796 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_SEEK_PARMS); break;*/FIXME(mci
, "NIY vcr\n"); return -2;
797 default: size
= sizeof(MCI_SEEK_PARMS
); break;
802 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_SET_PARMS
); break;
803 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_SET_PARMS); break;*/FIXME(mci
, "NIY vcr\n"); return -2;
804 case MCI_DEVTYPE_SEQUENCER
: size
= sizeof(MCI_SEQ_SET_PARMS
); break;
805 /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
806 * so not doing anything should work...
808 case MCI_DEVTYPE_WAVEFORM_AUDIO
:size
= sizeof(MCI_WAVE_SET_PARMS
); break;
809 default: size
= sizeof(MCI_SET_PARMS
); break;
812 /* case MCI_SETTIMECODE:*/
813 /* case MCI_SIGNAL:*/
815 size
= sizeof(MCI_SET_PARMS
);
821 * don't know if buffer for value is the one passed thru lpstrDevice
822 * or is provided by MCI driver.
823 * Assuming solution 2: provided by MCI driver, so zeroing on entry
825 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_STATUS_PARMS16
); map
= 0x0B6FF; break;
826 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME(mci
, "NIY vcr\n"); return -2;
827 default: size
= sizeof(MCI_STATUS_PARMS
); break;
832 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_STEP_PARMS
); break;
833 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_STEP_PARMS); break;*/FIXME(mci
, "NIY vcr\n"); return -2;
834 case MCI_DEVTYPE_VIDEODISC
: size
= sizeof(MCI_VD_STEP_PARMS
); break;
835 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
839 size
= sizeof(MCI_SET_PARMS
);
843 LPMCI_SYSINFO_PARMSA msip32a
= (LPMCI_SYSINFO_PARMSA
)(*lParam
);
844 char* ptr
= SEGPTR_ALLOC(sizeof(LPMCI_SYSINFO_PARMSA
) + sizeof(MCI_SYSINFO_PARMS16
));
845 LPMCI_SYSINFO_PARMS16 msip16
;
848 *(LPMCI_SYSINFO_PARMSA
*)(ptr
) = msip32a
;
849 msip16
= (LPMCI_SYSINFO_PARMS16
)(ptr
+ sizeof(LPMCI_SYSINFO_PARMSA
));
851 msip16
->dwCallback
= msip32a
->dwCallback
;
852 msip16
->lpstrReturn
= (LPSTR
)SEGPTR_GET(SEGPTR_ALLOC(msip32a
->dwRetSize
));
853 msip16
->dwRetSize
= msip32a
->dwRetSize
;
854 msip16
->dwNumber
= msip32a
->dwNumber
;
855 msip16
->wDeviceType
= msip32a
->wDeviceType
;
859 *lParam
= (LPARAM
)SEGPTR_GET(ptr
) + sizeof(LPMCI_SYSINFO_PARMSA
);
865 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_RECT_PARMS16
); map
= 0x0001111B; break;
866 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_RECT_PARMS16
); map
= 0x0001111B; break;
867 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
872 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_UPDATE_PARMS16
); map
= 0x000B1111B; break;
873 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
878 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_RECT_PARMS16
); map
= 0x0001111B; keep
= TRUE
; break;
879 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_RECT_PARMS16
); map
= 0x0001111B; keep
= TRUE
; break;
880 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
885 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_WINDOW_PARMS16
); if (dwFlags
& MCI_DGV_WINDOW_TEXT
) map
= 0x7FB; break;
886 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_WINDOW_PARMS16
); if (dwFlags
& MCI_OVLY_WINDOW_TEXT
) map
= 0x7FB; break;
887 default: size
= sizeof(MCI_GENERIC_PARMS
); break;
897 case DRV_QUERYCONFIGURE
:
900 case DRV_EXITSESSION
:
901 case DRV_EXITAPPLICATION
:
903 FIXME(mci
, "This is a hack\n");
907 WARN(mci
, "Don't know how to map msg=%s\n", MCI_CommandToString(wMsg
));
910 return MCI_MsgMapper32To16_CreateV2((void**)lParam
, size
, map
, keep
);
913 /**************************************************************************
914 * MCI_UnMapMsg32ATo16 [internal]
916 int MCI_UnMapMsg32ATo16(WORD uDevType
, WORD wMsg
, DWORD dwFlags
, DWORD lParam
)
919 BOOLEAN kept
= FALSE
; /* there is no need to compute size when kept is FALSE */
923 /* case MCI_CAPTURE */
925 case MCI_CLOSE_DRIVER
:
927 /* case MCI_CONFIGURE:*/
934 /* case MCI_ESCAPE: */
939 size
= sizeof(MCI_GETDEVCAPS_PARMS
);
941 /* case MCI_INDEX: */
944 LPMCI_INFO_PARMS16 mip16
= (LPMCI_INFO_PARMS16
)PTR_SEG_TO_LIN(lParam
);
945 LPMCI_INFO_PARMSA mip32a
= *(LPMCI_INFO_PARMSA
*)((char*)mip16
- sizeof(LPMCI_INFO_PARMSA
));
947 memcpy(mip32a
->lpstrReturn
, PTR_SEG_TO_LIN(mip16
->lpstrReturn
), mip32a
->dwRetSize
);
949 if (!SEGPTR_FREE(PTR_SEG_TO_LIN(mip16
->lpstrReturn
)))
950 FIXME(mci
, "bad free line=%d\n", __LINE__
);
951 if (!SEGPTR_FREE((char*)mip16
- sizeof(LPMCI_INFO_PARMSA
)))
952 FIXME(mci
, "bad free line=%d\n", __LINE__
);
956 /* case MCI_MONITOR: */
958 case MCI_OPEN_DRIVER
:
960 LPMCI_OPEN_PARMS16 mop16
= (LPMCI_OPEN_PARMS16
)PTR_SEG_TO_LIN(lParam
);
961 LPMCI_OPEN_PARMSA mop32a
= *(LPMCI_OPEN_PARMSA
*)((char*)mop16
- sizeof(LPMCI_OPEN_PARMSA
));
963 mop32a
->wDeviceID
= mop16
->wDeviceID
;
964 if ((dwFlags
& MCI_OPEN_TYPE
) && !
965 (dwFlags
& MCI_OPEN_TYPE_ID
) &&
966 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16
->lpstrDeviceType
)))
967 FIXME(mci
, "bad free line=%d\n", __LINE__
);
968 if ((dwFlags
& MCI_OPEN_ELEMENT
) &&
969 !(dwFlags
& MCI_OPEN_ELEMENT_ID
) &&
970 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16
->lpstrElementName
)))
971 FIXME(mci
, "bad free line=%d\n", __LINE__
);
972 if ((dwFlags
& MCI_OPEN_ALIAS
) &&
973 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16
->lpstrAlias
)))
974 FIXME(mci
, "bad free line=%d\n", __LINE__
);
976 if (!SEGPTR_FREE((char*)mop16
- sizeof(LPMCI_OPEN_PARMSA
)))
977 FIXME(mci
, "bad free line=%d\n", __LINE__
);
997 /* case MCI_SETTIMECODE:*/
998 /* case MCI_SIGNAL:*/
1004 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1006 LPMCI_DGV_STATUS_PARMS16 mdsp16
= (LPMCI_DGV_STATUS_PARMS16
)PTR_SEG_TO_LIN(lParam
);
1007 LPMCI_DGV_STATUS_PARMSA mdsp32a
= *(LPMCI_DGV_STATUS_PARMSA
*)((char*)mdsp16
- sizeof(LPMCI_DGV_STATUS_PARMSA
));
1010 mdsp32a
->dwReturn
= mdsp16
->dwReturn
;
1011 if (dwFlags
& MCI_DGV_STATUS_DISKSPACE
) {
1012 TRACE(mci
, "MCI_STATUS (DGV) lpstrDrive=%p\n", mdsp16
->lpstrDrive
);
1013 TRACE(mci
, "MCI_STATUS (DGV) lpstrDrive=%s\n", (LPSTR
)PTR_SEG_TO_LIN(mdsp16
->lpstrDrive
));
1015 /* FIXME: see map function */
1016 strcpy(mdsp32a
->lpstrDrive
, (LPSTR
)PTR_SEG_TO_LIN(mdsp16
->lpstrDrive
));
1019 if (!SEGPTR_FREE((char*)mdsp16
- sizeof(LPMCI_DGV_STATUS_PARMSA
)))
1020 FIXME(mci
, "bad free line=%d\n", __LINE__
);
1026 case MCI_DEVTYPE_VCR
: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME(mci
, "NIY vcr\n"); return -2;
1027 default: size
= sizeof(MCI_STATUS_PARMS
); break;
1036 LPMCI_SYSINFO_PARMS16 msip16
= (LPMCI_SYSINFO_PARMS16
)PTR_SEG_TO_LIN(lParam
);
1037 LPMCI_SYSINFO_PARMSA msip32a
= *(LPMCI_SYSINFO_PARMSA
*)((char*)msip16
- sizeof(LPMCI_SYSINFO_PARMSA
));
1040 msip16
->dwCallback
= msip32a
->dwCallback
;
1041 memcpy(msip32a
->lpstrReturn
, PTR_SEG_TO_LIN(msip16
->lpstrReturn
), msip32a
->dwRetSize
);
1042 if (!SEGPTR_FREE(PTR_SEG_TO_LIN(msip16
->lpstrReturn
)))
1043 FIXME(mci
, "bad free line=%d\n", __LINE__
);
1045 if (!SEGPTR_FREE((char*)msip16
- sizeof(LPMCI_SYSINFO_PARMSA
)))
1046 FIXME(mci
, "bad free line=%d\n", __LINE__
);
1052 /* case MCI_UNDO: */
1059 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_RECT_PARMS16
); map
= 0x0001111B; kept
= TRUE
; break;
1060 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_RECT_PARMS16
); map
= 0x0001111B; kept
= TRUE
; break;
1066 case MCI_DEVTYPE_DIGITAL_VIDEO
: size
= sizeof(MCI_DGV_WINDOW_PARMS16
); if (dwFlags
& MCI_DGV_WINDOW_TEXT
) map
= 0x7666; break;
1067 case MCI_DEVTYPE_OVERLAY
: size
= sizeof(MCI_OVLY_WINDOW_PARMS16
); if (dwFlags
& MCI_OVLY_WINDOW_TEXT
) map
= 0x7666; break;
1070 /* FIXME: see map function */
1080 case DRV_QUERYCONFIGURE
:
1083 case DRV_EXITSESSION
:
1084 case DRV_EXITAPPLICATION
:
1086 FIXME(mci
, "This is a hack\n");
1089 FIXME(mci
, "Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg
));
1092 return MCI_MsgMapper32To16_DestroyV2((void*)lParam
, size
, map
, kept
);
1095 /**************************************************************************
1096 * MCI_SendCommand [internal]
1098 DWORD
MCI_SendCommand(UINT wDevID
, UINT16 wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1100 DWORD dwRet
= MCIERR_DEVICE_NOT_INSTALLED
;
1102 if (!MCI_DevIDValid(wDevID
)) {
1103 dwRet
= MCIERR_INVALID_DEVICE_ID
;
1105 MCIPROC proc
= MCI_GetProc(MCI_GetDrv(wDevID
)->modp
.wType
);
1108 dwRet
= (*proc
)(MCI_GetDrv(wDevID
)->modp
.wDeviceID
,
1109 MCI_GetDrv(wDevID
)->hDrv
,
1110 wMsg
, dwParam1
, dwParam2
);
1111 } else if (MCI_GetDrv(wDevID
)->hDrv
) {
1112 switch (DRIVER_GetType(MCI_GetDrv(wDevID
)->hDrv
)) {
1113 case WINE_DI_TYPE_16
:
1117 switch (res
= MCI_MapMsg32ATo16(MCI_GetDrv(wDevID
)->modp
.wType
, wMsg
, dwParam1
, &dwParam2
)) {
1119 TRACE(mci
, "Not handled yet (%s)\n", MCI_CommandToString(wMsg
));
1120 dwRet
= MCIERR_DRIVER_INTERNAL
;
1123 TRACE(mci
, "Problem mapping msg=%s from 32a to 16\n", MCI_CommandToString(wMsg
));
1124 dwRet
= MCIERR_OUT_OF_MEMORY
;
1128 dwRet
= SendDriverMessage16(MCI_GetDrv(wDevID
)->hDrv
, wMsg
, dwParam1
, dwParam2
);
1130 MCI_UnMapMsg32ATo16(MCI_GetDrv(wDevID
)->modp
.wType
, wMsg
, dwParam1
, dwParam2
);
1135 case WINE_DI_TYPE_32
:
1136 dwRet
= SendDriverMessage(MCI_GetDrv(wDevID
)->hDrv
, wMsg
, dwParam1
, dwParam2
);
1139 WARN(mci
, "Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID
)->hDrv
));
1140 dwRet
= MCIERR_DRIVER_INTERNAL
;
1143 WARN(mci
, "unknown device type=%04X !\n", MCI_GetDrv(wDevID
)->modp
.wType
);
1149 /**************************************************************************
1150 * MCI_Open [internal]
1152 DWORD
MCI_Open(DWORD dwParam
, LPMCI_OPEN_PARMSA lpParms
)
1154 char strDevTyp
[128];
1155 UINT16 uDevType
= 0;
1156 UINT16 wDevID
= MCI_FirstDevID();
1159 TRACE(mci
, "(%08lX, %p)\n", dwParam
, lpParms
);
1160 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
1162 if ((dwParam
& ~(MCI_OPEN_SHAREABLE
|MCI_OPEN_ELEMENT
|MCI_OPEN_ALIAS
|MCI_OPEN_TYPE
|MCI_OPEN_TYPE_ID
|MCI_NOTIFY
|MCI_WAIT
)) != 0) {
1163 FIXME(mci
, "unsupported yet dwFlags=%08lX\n",
1164 (dwParam
& ~(MCI_OPEN_SHAREABLE
|MCI_OPEN_ELEMENT
|MCI_OPEN_ALIAS
|MCI_OPEN_TYPE
|MCI_OPEN_TYPE_ID
|MCI_NOTIFY
|MCI_WAIT
)));
1167 while (MCI_GetDrv(wDevID
)->modp
.wType
!= 0) {
1168 wDevID
= MCI_NextDevID(wDevID
);
1169 if (!MCI_DevIDValid(wDevID
)) {
1170 TRACE(mci
, "MAXMCIDRIVERS reached !\n");
1171 return MCIERR_OUT_OF_MEMORY
;
1175 TRACE(mci
, "wDevID=%04X \n", wDevID
);
1176 memcpy(MCI_GetOpenDrv(wDevID
), lpParms
, sizeof(*lpParms
));
1180 if (dwParam
& MCI_OPEN_ELEMENT
) {
1183 TRACE(mci
, "lpstrElementName='%s'\n", lpParms
->lpstrElementName
);
1184 t
= strrchr(lpParms
->lpstrElementName
, '.');
1186 GetProfileStringA("mci extensions", t
+1, "*", strDevTyp
, sizeof(strDevTyp
));
1187 if (strcmp(strDevTyp
, "*") == 0) {
1188 TRACE(mci
,"No [mci extensions] entry for %s found.\n", t
);
1189 return MCIERR_EXTENSION_NOT_FOUND
;
1191 TRACE(mci
, "Extension %s is mapped to type %s\n", t
, strDevTyp
);
1192 } else if (GetDriveTypeA(lpParms
->lpstrElementName
) == DRIVE_CDROM
) {
1193 /* FIXME: this will not work if several CDROM drives are installed on the machine */
1194 strcpy(strDevTyp
, "CDAUDIO");
1196 return MCIERR_EXTENSION_NOT_FOUND
;
1200 if (dwParam
& MCI_OPEN_ALIAS
) {
1201 TRACE(mci
, "Alias='%s' !\n", lpParms
->lpstrAlias
);
1202 /* FIXME is there any memory leak here ? */
1203 MCI_GetOpenDrv(wDevID
)->lpstrAlias
= strdup(lpParms
->lpstrAlias
);
1204 /* mplayer does allocate alias to CDAUDIO */
1206 if (dwParam
& MCI_OPEN_TYPE
) {
1207 if (dwParam
& MCI_OPEN_TYPE_ID
) {
1209 TRACE(mci
, "Dev=%08lx!\n", (DWORD
)lpParms
->lpstrDeviceType
);
1210 uDevType
= LOWORD((DWORD
)lpParms
->lpstrDeviceType
);
1211 MCI_GetOpenDrv(wDevID
)->lpstrDeviceType
= lpParms
->lpstrDeviceType
;
1213 if (LOWORD((DWORD
)lpParms
->lpstrDeviceType
) != MCI_DEVTYPE_CD_AUDIO
) {
1214 FIXME(mci
, "MCI_OPEN_TYPE_ID is no longer properly supported\n");
1216 strcpy(strDevTyp
, "CDAUDIO");
1218 if (lpParms
->lpstrDeviceType
== NULL
)
1219 return MCIERR_NULL_PARAMETER_BLOCK
;
1220 TRACE(mci
, "Dev='%s' !\n", lpParms
->lpstrDeviceType
);
1221 /* FIXME is there any memory leak here ? */
1222 strcpy(strDevTyp
, lpParms
->lpstrDeviceType
);
1226 if (strDevTyp
[0] == 0) {
1227 FIXME(mci
, "Couldn't load driver\n");
1228 return MCIERR_DRIVER_INTERNAL
;
1231 CharUpperA(strDevTyp
);
1233 /* try Wine internal MCI drivers */
1234 uDevType
= MCI_GetDevType(strDevTyp
);
1235 if (uDevType
== 0) { /* Nope, load external */
1237 MCI_OPEN_DRIVER_PARMSA modp
;
1239 modp
.wDeviceID
= wDevID
;
1240 modp
.lpstrParams
= NULL
;
1242 /* FIXME: this is a hack... some MCI drivers, while being open, call
1243 * mciSetData, which lookup for non empty slots in MCI table list
1244 * Unfortunatly, open slots are known when wType == 0...
1245 * so use a dummy type, just to keep on going. May be wType == 0 is
1246 * not the best solution to indicate empty slot in MCI drivers table
1248 MCI_GetDrv(wDevID
)->modp
.wType
= MCI_DEVTYPE_CD_AUDIO
;
1249 hDrv
= OpenDriverA(strDevTyp
, "mci", (LPARAM
)&modp
);
1252 FIXME(mci
, "Couldn't load driver for type %s.\n", strDevTyp
);
1253 return MCIERR_DEVICE_NOT_INSTALLED
;
1255 uDevType
= modp
.wType
;
1256 MCI_GetDrv(wDevID
)->hDrv
= hDrv
;
1258 TRACE(mci
, "Loaded driver %u (%s), type is %d\n", hDrv
, strDevTyp
, uDevType
);
1260 MCI_GetDrv(wDevID
)->hDrv
= 0;
1263 MCI_GetDrv(wDevID
)->mop
.lpstrDeviceType
= strdup(strDevTyp
);
1264 MCI_GetDrv(wDevID
)->modp
.wType
= uDevType
;
1265 MCI_GetDrv(wDevID
)->modp
.wDeviceID
= 0; /* FIXME? for multiple devices */
1267 lpParms
->wDeviceID
= wDevID
;
1269 TRACE(mci
, "mcidev=%d, uDevType=%04X wDeviceID=%04X !\n",
1270 wDevID
, uDevType
, lpParms
->wDeviceID
);
1272 dwRet
= MCI_SendCommand(wDevID
, MCI_OPEN_DRIVER
, dwParam
, (DWORD
)lpParms
);
1273 MCI_GetDrv(wDevID
)->lpfnYieldProc
= MCI_DefYieldProc
;
1274 MCI_GetDrv(wDevID
)->dwYieldData
= VK_CANCEL
;
1275 MCI_GetDrv(wDevID
)->hCreatorTask
= GetCurrentTask();
1278 /* only handled devices fall through */
1279 TRACE(mci
, "wDevID = %04X wDeviceID = %d dwRet = %ld\n", wDevID
, lpParms
->wDeviceID
, dwRet
);
1281 TRACE(mci
, "failed to open driver (MCI_OPEN_DRIVER msg) [%08lx], closing\n", dwRet
);
1282 MCI_GetDrv(wDevID
)->modp
.wType
= 0;
1284 if (dwParam
& MCI_NOTIFY
)
1285 mciDriverNotify16(lpParms
->dwCallback
, wDevID
, dwRet
== 0 ? MCI_NOTIFY_SUCCESSFUL
: MCI_NOTIFY_FAILURE
);
1290 /**************************************************************************
1291 * MCI_Close [internal]
1293 DWORD
MCI_Close(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
1297 TRACE(mci
, "(%04x, %08lX, %p)\n", wDevID
, dwParam
, lpParms
);
1299 if (wDevID
== MCI_ALL_DEVICE_ID
) {
1300 FIXME(mci
, "unhandled MCI_ALL_DEVICE_ID\n");
1301 return MCIERR_CANNOT_USE_ALL
;
1304 dwRet
= MCI_SendCommand(wDevID
, MCI_CLOSE_DRIVER
, dwParam
, (DWORD
)lpParms
);
1305 if (MCI_GetDrv(wDevID
)->hDrv
) {
1307 CloseDriver(MCI_GetDrv(wDevID
)->hDrv
, 0, 0);
1310 MCI_GetDrv(wDevID
)->modp
.wType
= 0;
1311 free(MCI_GetDrv(wDevID
)->mop
.lpstrDeviceType
);
1313 if (dwParam
& MCI_NOTIFY
)
1314 mciDriverNotify16(lpParms
->dwCallback
, wDevID
,
1315 (dwRet
== 0) ? MCI_NOTIFY_SUCCESSFUL
: MCI_NOTIFY_FAILURE
);
1320 /**************************************************************************
1321 * MCI_WriteString [internal]
1323 DWORD
MCI_WriteString(LPSTR lpDstStr
, DWORD dstSize
, LPCSTR lpSrcStr
)
1327 if (dstSize
<= strlen(lpSrcStr
)) {
1328 lstrcpynA(lpDstStr
, lpSrcStr
, dstSize
- 1);
1329 ret
= MCIERR_PARAM_OVERFLOW
;
1331 strcpy(lpDstStr
, lpSrcStr
);
1337 /**************************************************************************
1338 * MCI_Sysinfo [internal]
1340 DWORD
MCI_SysInfo(UINT uDevID
, DWORD dwFlags
, LPMCI_SYSINFO_PARMSA lpParms
)
1342 DWORD ret
= MCIERR_INVALID_DEVICE_ID
;
1344 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
1346 TRACE(mci
, "(%08x, %08lX, %08lX[num=%ld, wDevTyp=%u])\n",
1347 uDevID
, dwFlags
, (DWORD
)lpParms
, lpParms
->dwNumber
, lpParms
->wDeviceType
);
1349 switch (dwFlags
& ~MCI_SYSINFO_OPEN
) {
1350 case MCI_SYSINFO_QUANTITY
:
1355 if (lpParms
->wDeviceType
< MCI_DEVTYPE_FIRST
|| lpParms
->wDeviceType
> MCI_DEVTYPE_LAST
) {
1356 if (dwFlags
& MCI_SYSINFO_OPEN
) {
1357 TRACE(mci
, "MCI_SYSINFO_QUANTITY: # of open MCI drivers\n");
1358 for (i
= 0; i
< MAXMCIDRIVERS
; i
++) {
1359 if (mciDrv
[i
].modp
.wType
!= 0) cnt
++;
1362 TRACE(mci
, "MCI_SYSINFO_QUANTITY: # of installed MCI drivers\n");
1363 cnt
= mciInstalledCount
;
1366 if (dwFlags
& MCI_SYSINFO_OPEN
) {
1367 TRACE(mci
, "MCI_SYSINFO_QUANTITY: # of open MCI drivers of type %u\n", lpParms
->wDeviceType
);
1368 for (i
= 0; i
< MAXMCIDRIVERS
; i
++) {
1369 if (mciDrv
[i
].modp
.wType
== lpParms
->wDeviceType
) cnt
++;
1372 TRACE(mci
, "MCI_SYSINFO_QUANTITY: # of installed MCI drivers of type %u\n", lpParms
->wDeviceType
);
1373 FIXME(mci
, "Don't know how to get # of MCI devices of a given type\n");
1377 *(DWORD
*)lpParms
->lpstrReturn
= cnt
;
1379 TRACE(mci
, "(%ld) => '%ld'\n", lpParms
->dwNumber
, *(DWORD
*)lpParms
->lpstrReturn
);
1382 case MCI_SYSINFO_INSTALLNAME
:
1383 TRACE(mci
, "MCI_SYSINFO_INSTALLNAME \n");
1384 if (MCI_DevIDValid(uDevID
)) {
1385 ret
= MCI_WriteString(lpParms
->lpstrReturn
, lpParms
->dwRetSize
, MCI_GetDrv(uDevID
)->mop
.lpstrDeviceType
);
1387 *lpParms
->lpstrReturn
= 0;
1388 ret
= MCIERR_INVALID_DEVICE_ID
;
1390 TRACE(mci
, "(%ld) => '%s'\n", lpParms
->dwNumber
, lpParms
->lpstrReturn
);
1392 case MCI_SYSINFO_NAME
:
1393 TRACE(mci
, "MCI_SYSINFO_NAME\n");
1394 if (dwFlags
& MCI_SYSINFO_OPEN
) {
1395 FIXME(mci
, "Don't handle MCI_SYSINFO_NAME|MCI_SYSINFO_OPEN (yet)\n");
1396 ret
= MCIERR_UNRECOGNIZED_COMMAND
;
1397 } else if (lpParms
->dwNumber
> mciInstalledCount
) {
1398 ret
= MCIERR_OUTOFRANGE
;
1400 DWORD count
= lpParms
->dwNumber
;
1401 LPSTR ptr
= lpmciInstallNames
;
1403 while (--count
> 0) ptr
+= strlen(ptr
) + 1;
1404 ret
= MCI_WriteString(lpParms
->lpstrReturn
, lpParms
->dwRetSize
, ptr
);
1406 TRACE(mci
, "(%ld) => '%s'\n", lpParms
->dwNumber
, lpParms
->lpstrReturn
);
1409 TRACE(mci
, "Unsupported flag value=%08lx\n", dwFlags
);
1410 ret
= MCIERR_UNRECOGNIZED_COMMAND
;
1423 DWORD WINAPI
mciSendCommandA(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
);
1425 /**************************************************************************
1426 * MCI_SCAStarter [internal]
1428 static DWORD WINAPI
MCI_SCAStarter(LPVOID arg
)
1430 struct SCA
* sca
= (struct SCA
*)arg
;
1433 TRACE(mci
, "In thread before async command (%08x,%s,%08lx,%08lx)\n",
1434 sca
->wDevID
, MCI_CommandToString(sca
->wMsg
), sca
->dwParam1
, sca
->dwParam2
);
1435 ret
= mciSendCommandA(sca
->wDevID
, sca
->wMsg
, sca
->dwParam1
| MCI_WAIT
, sca
->dwParam2
);
1436 TRACE(mci
, "In thread after async command (%08x,%s,%08lx,%08lx)\n",
1437 sca
->wDevID
, MCI_CommandToString(sca
->wMsg
), sca
->dwParam1
, sca
->dwParam2
);
1438 if (sca
->allocatedCopy
)
1439 HeapFree(GetProcessHeap(), 0, (LPVOID
)sca
->dwParam2
);
1440 HeapFree(GetProcessHeap(), 0, sca
);
1442 WARN(mci
, "Should not happen ? what's wrong \n");
1443 /* should not go after this point */
1447 /**************************************************************************
1448 * MCI_SendCommandAsync [internal]
1450 DWORD
MCI_SendCommandAsync(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
, UINT size
)
1452 struct SCA
* sca
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA
));
1455 return MCIERR_OUT_OF_MEMORY
;
1457 sca
->wDevID
= wDevID
;
1459 sca
->dwParam1
= dwParam1
;
1462 sca
->dwParam2
= (DWORD
)HeapAlloc(GetProcessHeap(), 0, size
);
1463 if (sca
->dwParam2
== 0) {
1464 HeapFree(GetProcessHeap(), 0, sca
);
1465 return MCIERR_OUT_OF_MEMORY
;
1467 sca
->allocatedCopy
= TRUE
;
1468 /* copy structure passed by program in dwParam2 to be sure
1469 * we can still use it whatever the program does
1471 memcpy((LPVOID
)sca
->dwParam2
, (LPVOID
)dwParam2
, size
);
1473 sca
->dwParam2
= dwParam2
;
1474 sca
->allocatedCopy
= FALSE
;
1477 if (CreateThread(NULL
, 0, MCI_SCAStarter
, sca
, 0, NULL
) == 0) {
1478 WARN(mci
, "Couldn't allocate thread for async command handling, sending synchonously\n");
1479 return MCI_SCAStarter(&sca
);
1484 /**************************************************************************
1485 * MCI_CleanUp [internal]
1487 * Some MCI commands need to be cleaned-up (when not called from
1488 * mciSendString), because MCI drivers return extra information for string
1489 * transformation. This function gets read of them.
1491 LRESULT
MCI_CleanUp(LRESULT dwRet
, UINT wMsg
, DWORD dwParam2
, BOOL bIs32
)
1494 case MCI_GETDEVCAPS
:
1495 switch (dwRet
& 0xFFFF0000ul
) {
1498 case MCI_RESOURCE_RETURNED
:
1499 case MCI_RESOURCE_RETURNED
|MCI_RESOURCE_DRIVER
:
1500 case MCI_COLONIZED3_RETURN
:
1501 case MCI_COLONIZED4_RETURN
:
1502 case MCI_INTEGER_RETURNED
:
1504 LPMCI_GETDEVCAPS_PARMS lmgp
= (LPMCI_GETDEVCAPS_PARMS
)(bIs32
? (void*)dwParam2
: PTR_SEG_TO_LIN(dwParam2
));
1506 dwRet
= LOWORD(dwRet
);
1507 TRACE(mci
, "Changing %08lx to %08lx\n", lmgp
->dwReturn
, (DWORD
)LOWORD(lmgp
->dwReturn
));
1509 lmgp
->dwReturn
= LOWORD(lmgp
->dwReturn
);
1513 FIXME(mci
, "Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet
));
1517 switch (dwRet
& 0xFFFF0000ul
) {
1520 case MCI_RESOURCE_RETURNED
:
1521 case MCI_RESOURCE_RETURNED
|MCI_RESOURCE_DRIVER
:
1522 case MCI_COLONIZED3_RETURN
:
1523 case MCI_COLONIZED4_RETURN
:
1524 case MCI_INTEGER_RETURNED
:
1526 LPMCI_STATUS_PARMS lsp
= (LPMCI_STATUS_PARMS
)(bIs32
? (void*)dwParam2
: PTR_SEG_TO_LIN(dwParam2
));
1528 dwRet
= LOWORD(dwRet
);
1529 TRACE(mci
, "Changing %08lx to %08lx\n", lsp
->dwReturn
,(DWORD
) LOWORD(lsp
->dwReturn
));
1530 lsp
->dwReturn
= LOWORD(lsp
->dwReturn
);
1534 FIXME(mci
, "Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet
));