Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbejy@wpi.edu>
[wine/multimedia.git] / multimedia / mci.c
blobd78c00d98932449f0e6778550aa6c0785947c29f
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * MCI internal functions
6 * Copyright 1998/1999 Eric Pouech
7 */
9 #include <string.h>
10 #include <stdlib.h>
12 #include "winbase.h"
13 #include "winuser.h"
14 #include "heap.h"
15 #include "driver.h"
16 #include "mmsystem.h"
17 #include "multimedia.h"
18 #include "selectors.h"
19 #include "debug.h"
20 #include "digitalv.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 */
52 #if 0
53 /**************************************************************************
54 * MCI_GetDevTypeString [internal]
56 static LPCSTR MCI_GetDevTypeString(WORD uDevType)
58 LPCSTR str = "??? MCI ???";
59 int i;
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;
65 break;
68 /* TRACE(mci, "devType=%u => %s\n", uDevType, str);*/
69 return str;
71 #endif
73 /**************************************************************************
74 * MCI_GetProc [internal]
76 static MCIPROC MCI_GetProc(UINT16 uDevType)
78 MCIPROC proc = 0;
79 int i;
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;
85 break;
88 return proc;
91 /**************************************************************************
92 * MCI_GetDevType [internal]
94 WORD MCI_GetDevType(LPCSTR str)
96 WORD uDevType = 0;
97 int i;
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;
103 break;
106 return 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)
122 return MCI_MAGIC;
125 /**************************************************************************
126 * MCI_NextDevId [internal]
128 UINT16 MCI_NextDevID(UINT16 wDevID)
130 return wDevID + 1;
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
150 switch (wMsg) {
151 CASE(MCI_BREAK);
152 CASE(MCI_CLOSE);
153 CASE(MCI_CLOSE_DRIVER);
154 CASE(MCI_COPY);
155 CASE(MCI_CUE);
156 CASE(MCI_CUT);
157 CASE(MCI_DELETE);
158 CASE(MCI_ESCAPE);
159 CASE(MCI_FREEZE);
160 CASE(MCI_PAUSE);
161 CASE(MCI_PLAY);
162 CASE(MCI_GETDEVCAPS);
163 CASE(MCI_INFO);
164 CASE(MCI_LOAD);
165 CASE(MCI_OPEN);
166 CASE(MCI_OPEN_DRIVER);
167 CASE(MCI_PASTE);
168 CASE(MCI_PUT);
169 CASE(MCI_REALIZE);
170 CASE(MCI_RECORD);
171 CASE(MCI_RESUME);
172 CASE(MCI_SAVE);
173 CASE(MCI_SEEK);
174 CASE(MCI_SET);
175 CASE(MCI_SPIN);
176 CASE(MCI_STATUS);
177 CASE(MCI_STEP);
178 CASE(MCI_STOP);
179 CASE(MCI_SYSINFO);
180 CASE(MCI_UNFREEZE);
181 CASE(MCI_UPDATE);
182 CASE(MCI_WHERE);
183 CASE(MCI_WINDOW);
184 default:
185 sprintf(buffer, "MCI_<<%04X>>", wMsg);
186 return buffer;
188 #undef CASE
191 /**************************************************************************
192 * MCI_MapMsg16To32A [internal]
194 int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
196 if (*lParam == 0)
197 return 0;
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
202 switch (wMsg) {
203 /* case MCI_CAPTURE */
204 case MCI_CLOSE:
205 case MCI_CLOSE_DRIVER:
206 /* case MCI_CONFIGURE:*/
207 case MCI_COPY:
208 case MCI_CUE:
209 case MCI_CUT:
210 case MCI_DELETE:
211 case MCI_FREEZE:
212 case MCI_GETDEVCAPS:
213 /* case MCI_INDEX: */
214 /* case MCI_MARK: */
215 /* case MCI_MONITOR: */
216 case MCI_PASTE:
217 case MCI_PAUSE:
218 case MCI_PLAY:
219 case MCI_PUT:
220 case MCI_REALIZE:
221 case MCI_RECORD:
222 case MCI_RESUME:
223 case MCI_SEEK:
224 case MCI_SET:
225 /* case MCI_SETTIMECODE:*/
226 /* case MCI_SIGNAL:*/
227 case MCI_SPIN:
228 case MCI_STATUS: /* FIXME: is wrong for digital video */
229 case MCI_STEP:
230 case MCI_STOP:
231 /* case MCI_UNDO: */
232 case MCI_UNFREEZE:
233 case MCI_UPDATE:
234 case MCI_WHERE:
235 *lParam = (DWORD)PTR_SEG_TO_LIN(*lParam);
236 return 0;
237 case MCI_WINDOW:
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");
243 break;
244 case MCI_BREAK:
246 LPMCI_BREAK_PARMS mbp32 = HeapAlloc(SystemHeap, 0, sizeof(MCI_BREAK_PARMS));
247 LPMCI_BREAK_PARMS16 mbp16 = PTR_SEG_TO_LIN(*lParam);
249 if (mbp32) {
250 mbp32->dwCallback = mbp16->dwCallback;
251 mbp32->nVirtKey = mbp16->nVirtKey;
252 mbp32->hwndBreak = mbp16->hwndBreak;
253 } else {
254 return -2;
256 *lParam = (DWORD)mbp32;
258 return 1;
259 case MCI_ESCAPE:
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);
264 if (mvep32a) {
265 mvep32a->dwCallback = mvep16->dwCallback;
266 mvep32a->lpstrCommand = PTR_SEG_TO_LIN(mvep16->lpstrCommand);
267 } else {
268 return -2;
270 *lParam = (DWORD)mvep32a;
272 return 1;
273 case MCI_INFO:
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
281 if (mip32a) {
282 mip32a->dwCallback = mip16->dwCallback;
283 mip32a->lpstrReturn = PTR_SEG_TO_LIN(mip16->lpstrReturn);
284 mip32a->dwRetSize = mip16->dwRetSize;
285 } else {
286 return -2;
288 *lParam = (DWORD)mip32a;
290 return 1;
291 case MCI_OPEN:
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);
297 if (mop32a) {
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));
314 } else {
315 return -2;
317 *lParam = (DWORD)mop32a;
319 return 1;
320 case MCI_SYSINFO:
322 LPMCI_SYSINFO_PARMSA msip32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_SYSINFO_PARMSA));
323 LPMCI_SYSINFO_PARMS16 msip16 = PTR_SEG_TO_LIN(*lParam);
325 if (msip32a) {
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;
331 } else {
332 return -2;
334 *lParam = (DWORD)msip32a;
336 return 1;
337 case DRV_LOAD:
338 case DRV_ENABLE:
339 case DRV_OPEN:
340 case DRV_CLOSE:
341 case DRV_DISABLE:
342 case DRV_FREE:
343 case DRV_CONFIGURE:
344 case DRV_QUERYCONFIGURE:
345 case DRV_INSTALL:
346 case DRV_REMOVE:
347 case DRV_EXITSESSION:
348 case DRV_EXITAPPLICATION:
349 case DRV_POWER:
350 FIXME(mci, "This is a hack\n");
351 return 0;
353 default:
354 WARN(mci, "Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
356 return -1;
359 /**************************************************************************
360 * MCI_UnMapMsg16To32A [internal]
362 int MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
364 switch (wMsg) {
365 /* case MCI_CAPTURE */
366 case MCI_CLOSE:
367 case MCI_CLOSE_DRIVER:
368 /* case MCI_CONFIGURE:*/
369 case MCI_COPY:
370 case MCI_CUE:
371 case MCI_CUT:
372 case MCI_DELETE:
373 case MCI_FREEZE:
374 case MCI_GETDEVCAPS:
375 /* case MCI_INDEX: */
376 /* case MCI_MARK: */
377 /* case MCI_MONITOR: */
378 case MCI_PASTE:
379 case MCI_PAUSE:
380 case MCI_PLAY:
381 case MCI_PUT:
382 case MCI_REALIZE:
383 case MCI_RECORD:
384 case MCI_RESUME:
385 case MCI_SEEK:
386 case MCI_SET:
387 /* case MCI_SETTIMECODE:*/
388 /* case MCI_SIGNAL:*/
389 case MCI_SPIN:
390 case MCI_STATUS:
391 case MCI_STEP:
392 case MCI_STOP:
393 /* case MCI_UNDO: */
394 case MCI_UNFREEZE:
395 case MCI_UPDATE:
396 case MCI_WHERE:
397 return 0;
399 case MCI_WINDOW:
400 /* FIXME ?? see Map function */
401 return 0;
403 case MCI_BREAK:
404 case MCI_ESCAPE:
405 case MCI_INFO:
406 case MCI_SYSINFO:
407 HeapFree(SystemHeap, 0, (LPVOID)lParam);
408 return 0;
409 case MCI_OPEN:
410 case MCI_OPEN_DRIVER:
411 if (lParam) {
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__);
419 return 0;
420 case DRV_LOAD:
421 case DRV_ENABLE:
422 case DRV_OPEN:
423 case DRV_CLOSE:
424 case DRV_DISABLE:
425 case DRV_FREE:
426 case DRV_CONFIGURE:
427 case DRV_QUERYCONFIGURE:
428 case DRV_INSTALL:
429 case DRV_REMOVE:
430 case DRV_EXITSESSION:
431 case DRV_EXITAPPLICATION:
432 case DRV_POWER:
433 FIXME(mci, "This is a hack\n");
434 return 0;
435 default:
436 FIXME(mci, "Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
438 return -1;
441 #if 0
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);
455 if (!lp) {
456 return -2;
458 if (keep) {
459 *(void**)lp = *ptr;
460 memcpy((char*)lp + sizeof(void**), *ptr, size);
461 *ptr = (char*)SEGPTR_GET(lp) + sizeof(void**);
462 } else {
463 memcpy((char*)lp, *ptr, size);
464 *ptr = (void*)SEGPTR_GET(lp);
466 return 1;
470 /**************************************************************************
471 * MCI_MsgMapper32To16_Destroy [internal]
473 * Helper for MCI_UnMapMsg32ATo16.
475 static int MCI_MsgMapper32To16_Destroy(void* ptr, int size, BOOLEAN kept)
477 if (ptr) {
478 void* msg16 = PTR_SEG_TO_LIN(ptr);
479 void* alloc;
481 if (kept) {
482 alloc = (char*)msg16 - sizeof(void**);
483 memcpy(*(void**)alloc, msg16, size);
484 } else {
485 alloc = msg16;
488 if (!SEGPTR_FREE(alloc)) {
489 FIXME(mci, "bad free line=%d\n", __LINE__);
492 return 0;
494 #endif
497 * 0000 stop
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
500 * 0100
501 * 0101
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
512 * segmented pointer.
513 * map contains a list of action to be performed for the mapping (see list
514 * above)
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);
522 LPBYTE p16, p32;
524 if (!lp) {
525 return -2;
527 p32 = (LPBYTE)(*ptr);
528 if (keep) {
529 *(void**)lp = *ptr;
530 p16 = (LPBYTE)lp + sizeof(void**);
531 *ptr = (char*)SEGPTR_GET(lp) + sizeof(void**);
532 } else {
533 p16 = lp;
534 *ptr = (void*)SEGPTR_GET(lp);
537 if (map == 0) {
538 memcpy(p16, p32, size16);
539 } else {
540 unsigned nibble;
541 unsigned sz;
543 while (map & 0xF) {
544 nibble = map & 0xF;
545 if (nibble & 0x8) {
546 sz = (nibble & 7) + 1;
547 memcpy(p16, p32, sz);
548 p16 += sz;
549 p32 += sz;
550 size16 -= sz; /* DEBUG only */
551 } else {
552 switch (nibble) {
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);
560 map >>= 4;
562 if (size16 != 0) /* DEBUG only */
563 FIXME(mci, "Mismatch between 16 bit struct size and map nibbles serie\n");
565 return 1;
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)
575 if (ptr) {
576 void* msg16 = PTR_SEG_TO_LIN(ptr);
577 void* alloc;
578 LPBYTE p32, p16;
579 unsigned nibble;
581 if (kept) {
582 alloc = (char*)msg16 - sizeof(void**);
583 p32 = *(void**)alloc;
584 p16 = msg16;
586 if (map == 0) {
587 memcpy(p32, p16, size16);
588 } else {
589 while (map & 0xF) {
590 nibble = map & 0xF;
591 if (nibble & 0x8) {
592 memcpy(p32, p16, (nibble & 7) + 1);
593 p16 += (nibble & 7) + 1;
594 p32 += (nibble & 7) + 1;
595 size16 -= (nibble & 7) + 1;
596 } else {
597 switch (nibble) {
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);
609 map >>= 4;
611 if (size16 != 0) /* DEBUG only */
612 FIXME(mci, "Mismatch between 16 bit struct size and map nibbles serie\n");
614 } else {
615 alloc = msg16;
618 if (!SEGPTR_FREE(alloc)) {
619 FIXME(mci, "bad free line=%d\n", __LINE__);
622 return 0;
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)
636 int size;
637 BOOLEAN keep = FALSE;
638 DWORD map = 0;
640 if (*lParam == 0)
641 return 0;
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
647 switch (wMsg) {
648 /* case MCI_BREAK: */
649 /* case MCI_CAPTURE */
650 case MCI_CLOSE:
651 case MCI_CLOSE_DRIVER:
652 size = sizeof(MCI_GENERIC_PARMS);
653 break;
654 /* case MCI_CONFIGURE:*/
655 /* case MCI_COPY: */
656 case MCI_CUE:
657 switch (uDevType) {
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;
662 break;
663 /* case MCI_CUT:*/
664 case MCI_DELETE:
665 switch (uDevType) {
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;
670 break;
671 /* case MCI_ESCAPE: */
672 case MCI_FREEZE:
673 switch (uDevType) {
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;
678 break;
679 case MCI_GETDEVCAPS:
680 keep = TRUE;
681 size = sizeof(MCI_GETDEVCAPS_PARMS);
682 break;
683 /* case MCI_INDEX: */
684 case MCI_INFO:
686 LPMCI_INFO_PARMSA mip32a = (LPMCI_INFO_PARMSA)(*lParam);
687 char* ptr;
688 LPMCI_INFO_PARMS16 mip16;
690 switch (uDevType) {
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);
696 if (ptr) {
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;
705 } else {
706 return -2;
708 *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_INFO_PARMSA);
710 return 1;
711 /* case MCI_MARK: */
712 /* case MCI_MONITOR: */
713 case MCI_OPEN:
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;
721 if (ptr) {
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;
730 } else {
731 /* string */
732 mop16->lpstrDeviceType = mop32a->lpstrDeviceType ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrDeviceType)) : 0;
734 } else {
735 /* nuthin' */
736 mop16->lpstrDeviceType = 0;
738 if (dwFlags & MCI_OPEN_ELEMENT) {
739 if (dwFlags & MCI_OPEN_ELEMENT_ID) {
740 mop16->lpstrElementName = mop32a->lpstrElementName;
741 } else {
742 mop16->lpstrElementName = mop32a->lpstrElementName ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrElementName)) : 0;
744 } else {
745 mop16->lpstrElementName = 0;
747 if (dwFlags & MCI_OPEN_ALIAS) {
748 mop16->lpstrAlias = mop32a->lpstrAlias ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrAlias)) : 0;
749 } else {
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));
761 } else {
762 return -2;
764 *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_OPEN_PARMSA);
766 return 1;
767 /* case MCI_PASTE:*/
768 case MCI_PAUSE:
769 size = sizeof(MCI_GENERIC_PARMS);
770 break;
771 case MCI_PLAY:
772 size = sizeof(MCI_PLAY_PARMS);
773 break;
774 case MCI_PUT:
775 switch (uDevType) {
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;
780 break;
781 case MCI_REALIZE:
782 size = sizeof(MCI_GENERIC_PARMS);
783 break;
784 case MCI_RECORD:
785 switch (uDevType) {
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;
790 break;
791 case MCI_RESUME:
792 size = sizeof(MCI_GENERIC_PARMS);
793 break;
794 case MCI_SEEK:
795 switch (uDevType) {
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;
799 break;
800 case MCI_SET:
801 switch (uDevType) {
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;
811 break;
812 /* case MCI_SETTIMECODE:*/
813 /* case MCI_SIGNAL:*/
814 case MCI_SPIN:
815 size = sizeof(MCI_SET_PARMS);
816 break;
817 case MCI_STATUS:
818 keep = TRUE;
819 switch (uDevType) {
820 /* FIXME:
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;
829 break;
830 case MCI_STEP:
831 switch (uDevType) {
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;
837 break;
838 case MCI_STOP:
839 size = sizeof(MCI_SET_PARMS);
840 break;
841 case MCI_SYSINFO:
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;
847 if (ptr) {
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;
856 } else {
857 return -2;
859 *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_SYSINFO_PARMSA);
861 return 1;
862 /* case MCI_UNDO: */
863 case MCI_UNFREEZE:
864 switch (uDevType) {
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;
869 break;
870 case MCI_UPDATE:
871 switch (uDevType) {
872 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_UPDATE_PARMS16); map = 0x000B1111B; break;
873 default: size = sizeof(MCI_GENERIC_PARMS); break;
875 break;
876 case MCI_WHERE:
877 switch (uDevType) {
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;
882 break;
883 case MCI_WINDOW:
884 switch (uDevType) {
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;
889 break;
890 case DRV_LOAD:
891 case DRV_ENABLE:
892 case DRV_OPEN:
893 case DRV_CLOSE:
894 case DRV_DISABLE:
895 case DRV_FREE:
896 case DRV_CONFIGURE:
897 case DRV_QUERYCONFIGURE:
898 case DRV_INSTALL:
899 case DRV_REMOVE:
900 case DRV_EXITSESSION:
901 case DRV_EXITAPPLICATION:
902 case DRV_POWER:
903 FIXME(mci, "This is a hack\n");
904 return 0;
906 default:
907 WARN(mci, "Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
908 return -1;
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)
918 int size = 0;
919 BOOLEAN kept = FALSE; /* there is no need to compute size when kept is FALSE */
920 DWORD map = 0;
922 switch (wMsg) {
923 /* case MCI_CAPTURE */
924 case MCI_CLOSE:
925 case MCI_CLOSE_DRIVER:
926 break;
927 /* case MCI_CONFIGURE:*/
928 /* case MCI_COPY: */
929 case MCI_CUE:
930 break;
931 /* case MCI_CUT: */
932 case MCI_DELETE:
933 break;
934 /* case MCI_ESCAPE: */
935 case MCI_FREEZE:
936 break;
937 case MCI_GETDEVCAPS:
938 kept = TRUE;
939 size = sizeof(MCI_GETDEVCAPS_PARMS);
940 break;
941 /* case MCI_INDEX: */
942 case MCI_INFO:
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__);
954 return 0;
955 /* case MCI_MARK: */
956 /* case MCI_MONITOR: */
957 case MCI_OPEN:
958 case MCI_OPEN_DRIVER:
959 if (lParam) {
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__);
979 return 0;
980 /* case MCI_PASTE:*/
981 case MCI_PAUSE:
982 break;
983 case MCI_PLAY:
984 break;
985 case MCI_PUT:
986 break;
987 case MCI_REALIZE:
988 break;
989 case MCI_RECORD:
990 break;
991 case MCI_RESUME:
992 break;
993 case MCI_SEEK:
994 break;
995 case MCI_SET:
996 break;
997 /* case MCI_SETTIMECODE:*/
998 /* case MCI_SIGNAL:*/
999 case MCI_SPIN:
1000 break;
1001 case MCI_STATUS:
1002 kept = TRUE;
1003 switch (uDevType) {
1004 case MCI_DEVTYPE_DIGITAL_VIDEO:
1005 if (lParam) {
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));
1009 if (mdsp16) {
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__);
1021 } else {
1022 return -2;
1025 return 1;
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;
1029 break;
1030 case MCI_STEP:
1031 break;
1032 case MCI_STOP:
1033 break;
1034 case MCI_SYSINFO:
1035 if (lParam) {
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));
1039 if (msip16) {
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__);
1047 } else {
1048 return -2;
1051 return 1;
1052 /* case MCI_UNDO: */
1053 case MCI_UNFREEZE:
1054 break;
1055 case MCI_UPDATE:
1056 break;
1057 case MCI_WHERE:
1058 switch (uDevType) {
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;
1061 default: break;
1063 break;
1064 case MCI_WINDOW:
1065 switch (uDevType) {
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;
1068 default: break;
1070 /* FIXME: see map function */
1071 break;
1073 case DRV_LOAD:
1074 case DRV_ENABLE:
1075 case DRV_OPEN:
1076 case DRV_CLOSE:
1077 case DRV_DISABLE:
1078 case DRV_FREE:
1079 case DRV_CONFIGURE:
1080 case DRV_QUERYCONFIGURE:
1081 case DRV_INSTALL:
1082 case DRV_REMOVE:
1083 case DRV_EXITSESSION:
1084 case DRV_EXITAPPLICATION:
1085 case DRV_POWER:
1086 FIXME(mci, "This is a hack\n");
1087 return 0;
1088 default:
1089 FIXME(mci, "Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
1090 return -1;
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;
1104 } else {
1105 MCIPROC proc = MCI_GetProc(MCI_GetDrv(wDevID)->modp.wType);
1107 if (proc) {
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:
1115 int res;
1117 switch (res = MCI_MapMsg32ATo16(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam1, &dwParam2)) {
1118 case -1:
1119 TRACE(mci, "Not handled yet (%s)\n", MCI_CommandToString(wMsg));
1120 dwRet = MCIERR_DRIVER_INTERNAL;
1121 break;
1122 case -2:
1123 TRACE(mci, "Problem mapping msg=%s from 32a to 16\n", MCI_CommandToString(wMsg));
1124 dwRet = MCIERR_OUT_OF_MEMORY;
1125 break;
1126 case 0:
1127 case 1:
1128 dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
1129 if (res)
1130 MCI_UnMapMsg32ATo16(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam1, dwParam2);
1131 break;
1134 break;
1135 case WINE_DI_TYPE_32:
1136 dwRet = SendDriverMessage(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
1137 break;
1138 default:
1139 WARN(mci, "Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv));
1140 dwRet = MCIERR_DRIVER_INTERNAL;
1142 } else {
1143 WARN(mci, "unknown device type=%04X !\n", MCI_GetDrv(wDevID)->modp.wType);
1146 return dwRet;
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();
1157 DWORD dwRet;
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));
1178 strDevTyp[0] = 0;
1180 if (dwParam & MCI_OPEN_ELEMENT) {
1181 char* t;
1183 TRACE(mci, "lpstrElementName='%s'\n", lpParms->lpstrElementName);
1184 t = strrchr(lpParms->lpstrElementName, '.');
1185 if (t) {
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");
1195 } else {
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) {
1208 #if 0
1209 TRACE(mci, "Dev=%08lx!\n", (DWORD)lpParms->lpstrDeviceType);
1210 uDevType = LOWORD((DWORD)lpParms->lpstrDeviceType);
1211 MCI_GetOpenDrv(wDevID)->lpstrDeviceType = lpParms->lpstrDeviceType;
1212 #endif
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");
1217 } else {
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 */
1236 HDRVR hDrv;
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);
1251 if (!hDrv) {
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);
1259 } else {
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();
1277 if (dwRet == 0) {
1278 /* only handled devices fall through */
1279 TRACE(mci, "wDevID = %04X wDeviceID = %d dwRet = %ld\n", wDevID, lpParms->wDeviceID, dwRet);
1280 } else {
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);
1287 return dwRet;
1290 /**************************************************************************
1291 * MCI_Close [internal]
1293 DWORD MCI_Close(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
1295 DWORD dwRet;
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) {
1306 #if 0
1307 CloseDriver(MCI_GetDrv(wDevID)->hDrv, 0, 0);
1308 #endif
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);
1317 return dwRet;
1320 /**************************************************************************
1321 * MCI_WriteString [internal]
1323 DWORD MCI_WriteString(LPSTR lpDstStr, DWORD dstSize, LPCSTR lpSrcStr)
1325 DWORD ret;
1327 if (dstSize <= strlen(lpSrcStr)) {
1328 lstrcpynA(lpDstStr, lpSrcStr, dstSize - 1);
1329 ret = MCIERR_PARAM_OVERFLOW;
1330 } else {
1331 strcpy(lpDstStr, lpSrcStr);
1332 ret = 0;
1334 return ret;
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:
1352 DWORD cnt = 0;
1353 WORD i;
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++;
1361 } else {
1362 TRACE(mci, "MCI_SYSINFO_QUANTITY: # of installed MCI drivers\n");
1363 cnt = mciInstalledCount;
1365 } else {
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++;
1371 } else {
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");
1374 cnt = 1;
1377 *(DWORD*)lpParms->lpstrReturn = cnt;
1379 TRACE(mci, "(%ld) => '%ld'\n", lpParms->dwNumber, *(DWORD*)lpParms->lpstrReturn);
1380 ret = 0;
1381 break;
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);
1386 } else {
1387 *lpParms->lpstrReturn = 0;
1388 ret = MCIERR_INVALID_DEVICE_ID;
1390 TRACE(mci, "(%ld) => '%s'\n", lpParms->dwNumber, lpParms->lpstrReturn);
1391 break;
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;
1399 } else {
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);
1407 break;
1408 default:
1409 TRACE(mci, "Unsupported flag value=%08lx\n", dwFlags);
1410 ret = MCIERR_UNRECOGNIZED_COMMAND;
1412 return ret;
1415 struct SCA {
1416 UINT wDevID;
1417 UINT wMsg;
1418 DWORD dwParam1;
1419 DWORD dwParam2;
1420 BOOL allocatedCopy;
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;
1431 DWORD ret;
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);
1441 ExitThread(ret);
1442 WARN(mci, "Should not happen ? what's wrong \n");
1443 /* should not go after this point */
1444 return ret;
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));
1454 if (sca == 0)
1455 return MCIERR_OUT_OF_MEMORY;
1457 sca->wDevID = wDevID;
1458 sca->wMsg = wMsg;
1459 sca->dwParam1 = dwParam1;
1461 if (size) {
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);
1472 } else {
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);
1481 return 0;
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)
1493 switch (wMsg) {
1494 case MCI_GETDEVCAPS:
1495 switch (dwRet & 0xFFFF0000ul) {
1496 case 0:
1497 break;
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);
1511 break;
1512 default:
1513 FIXME(mci, "Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet));
1515 break;
1516 case MCI_STATUS:
1517 switch (dwRet & 0xFFFF0000ul) {
1518 case 0:
1519 break;
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);
1532 break;
1533 default:
1534 FIXME(mci, "Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet));
1536 break;
1537 default:
1538 break;
1540 return dwRet;