Clear invalid selectors also in CallTo16 relay code.
[wine] / multimedia / mci.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  * MCI internal functions
5  *
6  * Copyright 1998/1999 Eric Pouech
7  */
8
9 #include <string.h>
10
11 #include "winbase.h"
12 #include "winuser.h"
13 #include "heap.h"
14 #include "driver.h"
15 #include "mmsystem.h"
16 #include "multimedia.h"
17 #include "selectors.h"
18 #include "debug.h"
19 #include "digitalv.h"
20 #include "wine/winbase16.h"
21
22 struct WINE_MCIDRIVER mciDrv[MAXMCIDRIVERS];
23
24 int     mciInstalledCount;
25 int     mciInstalledListLen;
26 LPSTR   lpmciInstallNames = NULL;
27
28 /* The wDevID's returned by wine were originally in the range 
29  * 0 - (MAXMCIDRIVERS - 1) and used directly as array indices.
30  * Unfortunately, ms-windows uses wDevID of zero to indicate
31  * errors.  Now, multimedia drivers must pass the wDevID through
32  * MCI_DevIDToIndex to get an index in that range.  An
33  * arbitrary value, MCI_MAGIC is added to the wDevID seen
34  * by the windows programs.
35  */
36
37 #define MCI_MAGIC 0x0F00
38
39 MCI_WineDesc    MCI_InternalDescriptors[] = {
40     {MCI_DEVTYPE_CD_AUDIO,              "CDAUDIO",      MCICDAUDIO_DriverProc},
41     {MCI_DEVTYPE_WAVEFORM_AUDIO,        "WAVEAUDIO",    MCIWAVE_DriverProc},
42     {MCI_DEVTYPE_SEQUENCER,             "SEQUENCER",    MCIMIDI_DriverProc},
43     {MCI_DEVTYPE_ANIMATION,             "ANIMATION1",   MCIANIM_DriverProc},
44     {MCI_DEVTYPE_DIGITAL_VIDEO,         "AVIVIDEO",     MCIAVI_DriverProc},
45
46     {0xFFFF,                            NULL,           NULL}   /* sentinel */
47 };
48
49 /**************************************************************************
50  *                              MCI_GetDevTypeString            [internal]
51  */
52 static  LPCSTR          MCI_GetDevTypeString(WORD uDevType)
53 {
54     LPCSTR      str = "??? MCI ???";
55     int         i;
56
57     for (i = 0; MCI_InternalDescriptors[i].uDevType != 0xFFFF; i++) {
58         if (MCI_InternalDescriptors[i].uDevType != 0 && MCI_InternalDescriptors[i].uDevType == uDevType) {
59             str = MCI_InternalDescriptors[i].lpstrName;
60             break;
61         }
62     }
63     /*    TRACE(mci, "devType=%u => %s\n", uDevType, str);*/
64     return str;
65 }
66
67 /**************************************************************************
68  *                              MCI_GetProc                     [internal]
69  */
70 static  MCIPROC         MCI_GetProc(UINT16 uDevType)
71 {
72     MCIPROC     proc = 0;
73     int         i;
74
75     for (i = 0; MCI_InternalDescriptors[i].uDevType != 0xFFFF; i++) {
76         if (MCI_InternalDescriptors[i].uDevType != 0 && 
77             MCI_InternalDescriptors[i].uDevType == uDevType) {
78             proc = MCI_InternalDescriptors[i].lpfnProc;
79             break;
80         }
81     }
82     return proc;
83 }
84
85 /**************************************************************************
86  *                              MCI_GetDevType                  [internal]
87  */
88 WORD            MCI_GetDevType(LPCSTR str)
89 {
90     WORD        uDevType = 0;
91     int         i;
92
93     for (i = 0; MCI_InternalDescriptors[i].uDevType != 0xFFFF; i++) {
94         if (MCI_InternalDescriptors[i].uDevType != 0 && 
95             strcmp(str, MCI_InternalDescriptors[i].lpstrName) == 0) {
96             uDevType = MCI_InternalDescriptors[i].uDevType;
97             break;
98         }
99     }
100     return uDevType;
101 }
102
103 /**************************************************************************
104  *                              MCI_DevIDToIndex                [internal]
105  */
106 int MCI_DevIDToIndex(UINT16 wDevID) 
107 {
108     return wDevID - MCI_MAGIC;
109 }
110
111 /**************************************************************************
112  *                              MCI_FirstDevId                  [internal]
113  */
114 UINT16 MCI_FirstDevID(void)
115 {
116     return MCI_MAGIC;
117 }
118
119 /**************************************************************************
120  *                              MCI_NextDevId                   [internal]
121  */
122 UINT16 MCI_NextDevID(UINT16 wDevID) 
123 {
124     return wDevID + 1;
125 }
126
127 /**************************************************************************
128  *                              MCI_DevIDValid                  [internal]
129  */
130 BOOL MCI_DevIDValid(UINT16 wDevID) 
131 {
132     return wDevID >= MCI_MAGIC && wDevID < (MCI_MAGIC + MAXMCIDRIVERS);
133 }
134
135 /**************************************************************************
136  *                      MCI_CommandToString                     [internal]
137  */
138 const char* MCI_CommandToString(UINT16 wMsg)
139 {
140     static char buffer[100];
141     
142 #define CASE(s) case (s): return #s
143     
144     switch (wMsg) {
145         CASE(MCI_BREAK);
146         CASE(MCI_CLOSE);
147         CASE(MCI_CLOSE_DRIVER);
148         CASE(MCI_COPY);
149         CASE(MCI_CUE);
150         CASE(MCI_CUT);
151         CASE(MCI_DELETE);
152         CASE(MCI_ESCAPE);
153         CASE(MCI_FREEZE);
154         CASE(MCI_PAUSE);
155         CASE(MCI_PLAY);
156         CASE(MCI_GETDEVCAPS);
157         CASE(MCI_INFO);
158         CASE(MCI_LOAD);
159         CASE(MCI_OPEN);
160         CASE(MCI_OPEN_DRIVER);
161         CASE(MCI_PASTE);
162         CASE(MCI_PUT);
163         CASE(MCI_REALIZE);
164         CASE(MCI_RECORD);
165         CASE(MCI_RESUME);
166         CASE(MCI_SAVE);
167         CASE(MCI_SEEK);
168         CASE(MCI_SET);
169         CASE(MCI_SPIN);
170         CASE(MCI_STATUS);
171         CASE(MCI_STEP);
172         CASE(MCI_STOP);
173         CASE(MCI_SYSINFO);
174         CASE(MCI_UNFREEZE);
175         CASE(MCI_UPDATE);
176         CASE(MCI_WHERE);
177         CASE(MCI_WINDOW);
178     default:
179         sprintf(buffer, "MCI_<<%04X>>", wMsg);
180         return buffer;
181     }
182 #undef CASE
183 }
184
185 /**************************************************************************
186  *                      MCI_MapMsg16To32A                       [internal]
187  */
188 int     MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
189 {
190     if (*lParam == 0)
191         return 0;
192     /* FIXME: to add also (with seg/linear modifications to do):
193      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
194      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
195      */
196     switch (wMsg) {
197         /* case MCI_CAPTURE */
198     case MCI_CLOSE:             
199     case MCI_CLOSE_DRIVER:      
200         /* case MCI_CONFIGURE:*/
201     case MCI_COPY:
202     case MCI_CUE:
203     case MCI_CUT:
204     case MCI_DELETE:
205     case MCI_FREEZE:
206     case MCI_GETDEVCAPS:
207         /* case MCI_INDEX: */
208         /* case MCI_MARK: */
209         /* case MCI_MONITOR: */
210     case MCI_PASTE:
211     case MCI_PAUSE:             
212     case MCI_PLAY:              
213     case MCI_PUT:
214     case MCI_REALIZE:
215     case MCI_RECORD:            
216     case MCI_RESUME:            
217     case MCI_SEEK:              
218     case MCI_SET:
219         /* case MCI_SETTIMECODE:*/
220         /* case MCI_SIGNAL:*/
221     case MCI_SPIN:
222     case MCI_STATUS:            /* FIXME: is wrong for digital video */
223     case MCI_STEP:
224     case MCI_STOP:              
225         /* case MCI_UNDO: */
226     case MCI_UNFREEZE:
227     case MCI_UPDATE:
228     case MCI_WHERE:
229         *lParam = (DWORD)PTR_SEG_TO_LIN(*lParam);
230         return 0;
231     case MCI_WINDOW:
232         /* in fact, I would also need the dwFlags... to see 
233          * which members of lParam are effectively used 
234          */
235         *lParam = (DWORD)PTR_SEG_TO_LIN(*lParam);
236         FIXME(mci, "Current mapping may be wrong\n");
237         break;
238     case MCI_BREAK:
239         {
240             LPMCI_BREAK_PARMS           mbp32 = HeapAlloc(SystemHeap, 0, sizeof(MCI_BREAK_PARMS));
241             LPMCI_BREAK_PARMS16         mbp16 = PTR_SEG_TO_LIN(*lParam);
242
243             if (mbp32) {
244                 mbp32->dwCallback = mbp16->dwCallback;
245                 mbp32->nVirtKey = mbp16->nVirtKey;
246                 mbp32->hwndBreak = mbp16->hwndBreak;
247             } else {
248                 return -2;
249             }
250             *lParam = (DWORD)mbp32;
251         }
252         return 1;
253     case MCI_ESCAPE:
254         {
255             LPMCI_VD_ESCAPE_PARMSA      mvep32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_VD_ESCAPE_PARMSA));
256             LPMCI_VD_ESCAPE_PARMS16     mvep16  = PTR_SEG_TO_LIN(*lParam);
257
258             if (mvep32a) {
259                 mvep32a->dwCallback       = mvep16->dwCallback;
260                 mvep32a->lpstrCommand     = PTR_SEG_TO_LIN(mvep16->lpstrCommand);
261             } else {
262                 return -2;
263             }
264             *lParam = (DWORD)mvep32a;
265         }
266         return 1;
267     case MCI_INFO:
268         {
269             LPMCI_INFO_PARMSA   mip32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_INFO_PARMSA));
270             LPMCI_INFO_PARMS16  mip16  = PTR_SEG_TO_LIN(*lParam);
271
272             /* FIXME this is wrong if device is of type 
273              * MCI_DEVTYPE_DIGITAL_VIDEO, some members are not mapped
274              */
275             if (mip32a) {
276                 mip32a->dwCallback  = mip16->dwCallback;
277                 mip32a->lpstrReturn = PTR_SEG_TO_LIN(mip16->lpstrReturn);
278                 mip32a->dwRetSize   = mip16->dwRetSize;
279             } else {
280                 return -2;
281             }
282             *lParam = (DWORD)mip32a;
283         }
284         return 1;
285     case MCI_OPEN:
286     case MCI_OPEN_DRIVER:       
287         {
288             LPMCI_OPEN_PARMSA   mop32a = HeapAlloc(SystemHeap, 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_OPEN_PARMSA) + 2 * sizeof(DWORD));
289             LPMCI_OPEN_PARMS16  mop16  = PTR_SEG_TO_LIN(*lParam);
290
291             if (mop32a) {
292                 *(LPMCI_OPEN_PARMS16*)(mop32a) = mop16;
293                 mop32a = (LPMCI_OPEN_PARMSA)((char*)mop32a + sizeof(LPMCI_OPEN_PARMS16));
294                 mop32a->dwCallback       = mop16->dwCallback;
295                 mop32a->wDeviceID        = mop16->wDeviceID;
296                 mop32a->lpstrDeviceType  = PTR_SEG_TO_LIN(mop16->lpstrDeviceType);
297                 mop32a->lpstrElementName = PTR_SEG_TO_LIN(mop16->lpstrElementName);
298                 mop32a->lpstrAlias       = PTR_SEG_TO_LIN(mop16->lpstrAlias);
299                 /* copy extended information if any...
300                  * FIXME: this may seg fault if initial structure does not contain them and
301                  * the reads after msip16 fail under LDT limits...
302                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and 
303                  * should not take care of extended parameters, and should be used by MCI_Open
304                  * to fetch uDevType. When, this is known, the mapping for sending the 
305                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
306                  */
307                 memcpy(mop32a + 1, mop16 + 1, 2 * sizeof(DWORD));
308             } else {
309                 return -2;
310             }
311             *lParam = (DWORD)mop32a;
312         }
313         return 1;
314     case MCI_SYSINFO:
315         {
316             LPMCI_SYSINFO_PARMSA        msip32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_SYSINFO_PARMSA));
317             LPMCI_SYSINFO_PARMS16       msip16  = PTR_SEG_TO_LIN(*lParam);
318
319             if (msip32a) {
320                 msip32a->dwCallback       = msip16->dwCallback;
321                 msip32a->lpstrReturn      = PTR_SEG_TO_LIN(msip16->lpstrReturn);
322                 msip32a->dwRetSize        = msip16->dwRetSize;
323                 msip32a->dwNumber         = msip16->dwNumber;
324                 msip32a->wDeviceType      = msip16->wDeviceType;
325             } else {
326                 return -2;
327             }
328             *lParam = (DWORD)msip32a;
329         }
330         return 1;
331     case DRV_LOAD:
332     case DRV_ENABLE:
333     case DRV_OPEN:
334     case DRV_CLOSE:
335     case DRV_DISABLE:
336     case DRV_FREE:
337     case DRV_CONFIGURE:
338     case DRV_QUERYCONFIGURE:
339     case DRV_INSTALL:
340     case DRV_REMOVE:
341     case DRV_EXITSESSION:
342     case DRV_EXITAPPLICATION:
343     case DRV_POWER:
344         FIXME(mci, "This is a hack\n");
345         return 0;
346
347     default:
348         WARN(mci, "Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
349     }
350     return -1;
351 }
352
353 /**************************************************************************
354  *                      MCI_UnMapMsg16To32A                     [internal]
355  */
356 int     MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
357 {
358     switch (wMsg) {
359         /* case MCI_CAPTURE */
360     case MCI_CLOSE:
361     case MCI_CLOSE_DRIVER:      
362         /* case MCI_CONFIGURE:*/
363     case MCI_COPY:
364     case MCI_CUE:
365     case MCI_CUT:
366     case MCI_DELETE:
367     case MCI_FREEZE:
368     case MCI_GETDEVCAPS:
369         /* case MCI_INDEX: */
370         /* case MCI_MARK: */
371         /* case MCI_MONITOR: */
372     case MCI_PASTE:
373     case MCI_PAUSE:             
374     case MCI_PLAY:              
375     case MCI_PUT:
376     case MCI_REALIZE:
377     case MCI_RECORD:            
378     case MCI_RESUME:            
379     case MCI_SEEK:              
380     case MCI_SET:
381         /* case MCI_SETTIMECODE:*/
382         /* case MCI_SIGNAL:*/
383     case MCI_SPIN:
384     case MCI_STATUS:            
385     case MCI_STEP:
386     case MCI_STOP:              
387         /* case MCI_UNDO: */
388     case MCI_UNFREEZE:
389     case MCI_UPDATE:
390     case MCI_WHERE:
391         return 0;
392
393     case MCI_WINDOW:
394         /* FIXME ?? see Map function */
395         return 0;
396
397     case MCI_BREAK:
398     case MCI_ESCAPE:
399     case MCI_INFO:
400     case MCI_SYSINFO:
401         HeapFree(SystemHeap, 0, (LPVOID)lParam);
402         return 0;
403     case MCI_OPEN:
404     case MCI_OPEN_DRIVER:       
405         if (lParam) {
406             LPMCI_OPEN_PARMSA   mop32a = (LPMCI_OPEN_PARMSA)lParam;
407             LPMCI_OPEN_PARMS16  mop16  = *(LPMCI_OPEN_PARMS16*)((char*)mop32a - sizeof(LPMCI_OPEN_PARMS16*));
408             
409             mop16->wDeviceID = mop32a->wDeviceID;
410             if (!HeapFree(SystemHeap, 0, (LPVOID)(lParam - sizeof(LPMCI_OPEN_PARMS16))))
411                 FIXME(mci, "bad free line=%d\n", __LINE__);
412         }
413         return 0;
414     case DRV_LOAD:
415     case DRV_ENABLE:
416     case DRV_OPEN:
417     case DRV_CLOSE:
418     case DRV_DISABLE:
419     case DRV_FREE:
420     case DRV_CONFIGURE:
421     case DRV_QUERYCONFIGURE:
422     case DRV_INSTALL:
423     case DRV_REMOVE:
424     case DRV_EXITSESSION:
425     case DRV_EXITAPPLICATION:
426     case DRV_POWER:
427         FIXME(mci, "This is a hack\n");
428         return 0;
429     default:
430         FIXME(mci, "Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
431     }
432     return -1;
433 }
434
435 /**************************************************************************
436  *                      MCI_MsgMapper32To16_Create              [internal]
437  *
438  * Helper for MCI_MapMsg32ATo16. 
439  * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit segmented pointer.
440  * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
441  *  1 : ok, some memory allocated
442  * -2 : ko, memory problem
443  */
444 static  int     MCI_MsgMapper32To16_Create(void** ptr, int size, BOOLEAN keep)
445 {
446     void*       lp = SEGPTR_ALLOC(sizeof(void**) + size);
447
448     if (!lp) {
449         return -2;
450     }
451     if (keep) {
452         *(void**)lp = *ptr;
453         memcpy((char*)lp + sizeof(void**), *ptr, size);
454         *ptr = (char*)SEGPTR_GET(lp) + sizeof(void**);
455     } else {
456         memcpy((char*)lp, *ptr, size);
457         *ptr = (void*)SEGPTR_GET(lp);
458     }
459     return 1;
460    
461 }
462
463 /**************************************************************************
464  *                      MCI_MsgMapper32To16_Destroy             [internal]
465  *
466  * Helper for MCI_UnMapMsg32ATo16. 
467  */
468 static  int     MCI_MsgMapper32To16_Destroy(void* ptr, int size, BOOLEAN kept)
469 {
470     if (ptr) {
471         void*   msg16 = PTR_SEG_TO_LIN(ptr);
472         void*   alloc;
473
474         if (kept) {
475             alloc = (char*)msg16 - sizeof(void**);
476             memcpy(*(void**)alloc, msg16, size);
477         } else {
478             alloc = msg16;
479         }
480
481         if (!SEGPTR_FREE(alloc)) {
482             FIXME(mci, "bad free\n");
483         } 
484     }   
485     return 0;
486 }
487
488 /**************************************************************************
489  *                      MCI_MapMsg32ATo16                       [internal]
490  *
491  * Map a 32-A bit MCI message to a 16 bit MCI message.
492  *  1 : ok, some memory allocated, need to call MCI_UnMapMsg32ATo16
493  *  0 : ok, no memory allocated
494  * -1 : ko, unknown message
495  * -2 : ko, memory problem
496  */
497 int     MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
498 {
499     int         size;
500     BOOLEAN     keep = FALSE;
501
502     if (*lParam == 0)
503         return 0;
504     /* FIXME: to add also (with seg/linear modifications to do):
505      * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
506      * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
507      */
508     switch (wMsg) {
509         /* case MCI_BREAK: */
510         /* case MCI_CAPTURE */
511     case MCI_CLOSE:
512     case MCI_CLOSE_DRIVER:      
513         size = sizeof(MCI_GENERIC_PARMS);       
514         break;
515         /* case MCI_CONFIGURE:*/
516         /* case MCI_COPY: */
517     case MCI_CUE:
518         switch (uDevType) {
519         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_CUE_PARMS);       break;
520         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_CUE_PARMS);     break;*/        FIXME(mci, "NIY vcr\n");        return -2;
521         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
522         }
523         break;
524         /* case MCI_CUT:*/
525     case MCI_DELETE:
526         switch (uDevType) {
527         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_DELETE_PARMS);    FIXME(mci, "NIY rect\n");       return -2;
528         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_DELETE_PARMS);   break;
529         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
530         }
531         break;
532         /* case MCI_ESCAPE: */
533     case MCI_FREEZE:
534         switch (uDevType) {
535         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_FREEZE_PARMS);    FIXME(mci, "NIY rect\n");       return -2;
536         case MCI_DEVTYPE_OVERLAY:       /*size = sizeof(MCI_OVLY_FREEZE_PARMS); FIXME(mci, "NIY rect\n");       return -2;*/
537                                         FIXME(mci, "NIY ovly\n");       return -2;
538         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
539         }
540         break;
541     case MCI_GETDEVCAPS:
542         keep = TRUE;
543         size = sizeof(MCI_GETDEVCAPS_PARMS);
544         break;
545         /* case MCI_INDEX: */
546     case MCI_INFO:
547         {
548             LPMCI_INFO_PARMSA   mip32a = (LPMCI_INFO_PARMSA)(*lParam);
549             char*               ptr;
550             LPMCI_INFO_PARMS16  mip16;
551             
552             switch (uDevType) {
553             case MCI_DEVTYPE_DIGITAL_VIDEO:     size = sizeof(MCI_DGV_INFO_PARMS16);    break;
554             default:                            size = sizeof(MCI_INFO_PARMS16);        break;
555             }
556             ptr = SEGPTR_ALLOC(sizeof(LPMCI_INFO_PARMSA) + size);
557
558             if (ptr) {
559                 *(LPMCI_INFO_PARMSA*)ptr = mip32a;
560                 mip16 = (LPMCI_INFO_PARMS16)(ptr + sizeof(LPMCI_INFO_PARMSA));
561                 mip16->dwCallback  = mip32a->dwCallback;
562                 mip16->lpstrReturn = (LPSTR)SEGPTR_GET(SEGPTR_ALLOC(mip32a->dwRetSize));
563                 mip16->dwRetSize   = mip32a->dwRetSize;
564                 if (uDevType == MCI_DEVTYPE_DIGITAL_VIDEO) {
565                     ((LPMCI_DGV_INFO_PARMS16)mip16)->dwItem = ((LPMCI_DGV_INFO_PARMSA)mip32a)->dwItem;
566                 }
567             } else {
568                 return -2;
569             }
570             *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_INFO_PARMSA);
571         }
572         return 1;
573         /* case MCI_MARK: */
574         /* case MCI_MONITOR: */
575     case MCI_OPEN:
576     case MCI_OPEN_DRIVER:       
577         {
578             LPMCI_OPEN_PARMSA   mop32a = (LPMCI_OPEN_PARMSA)(*lParam);
579             char*               ptr    = SEGPTR_ALLOC(sizeof(LPMCI_OPEN_PARMSA) + sizeof(MCI_OPEN_PARMS16) + 2 * sizeof(DWORD));
580             LPMCI_OPEN_PARMS16  mop16;
581
582
583             if (ptr) {
584                 *(LPMCI_OPEN_PARMSA*)(ptr) = mop32a;
585                 mop16 = (LPMCI_OPEN_PARMS16)(ptr + sizeof(LPMCI_OPEN_PARMSA));
586                 mop16->dwCallback       = mop32a->dwCallback;
587                 mop16->wDeviceID        = mop32a->wDeviceID;
588                 if (dwFlags & MCI_OPEN_TYPE) {
589                     if (dwFlags & MCI_OPEN_TYPE_ID) {
590                         /* dword "transparent" value */
591                         mop16->lpstrDeviceType = mop32a->lpstrDeviceType;
592                     } else {
593                         /* string */
594                         mop16->lpstrDeviceType = mop32a->lpstrDeviceType ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrDeviceType)) : 0;
595                     }
596                 } else {
597                     /* nuthin' */
598                     mop16->lpstrDeviceType = 0;
599                 }
600                 if (dwFlags & MCI_OPEN_ELEMENT) {
601                     if (dwFlags & MCI_OPEN_ELEMENT_ID) {
602                         mop16->lpstrElementName = mop32a->lpstrElementName;
603                     } else {
604                         mop16->lpstrElementName = mop32a->lpstrElementName ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrElementName)) : 0;
605                     }
606                 } else {
607                     mop16->lpstrElementName = 0;
608                 }
609                 if (dwFlags & MCI_OPEN_ALIAS) {
610                     mop16->lpstrAlias = mop32a->lpstrAlias ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrAlias)) : 0;
611                 } else {
612                     mop16->lpstrAlias = 0;
613                 }
614                 /* copy extended information if any...
615                  * FIXME: this may seg fault if initial structure does not contain them and
616                  * the reads after msip16 fail under LDT limits...
617                  * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and 
618                  * should not take care of extended parameters, and should be used by MCI_Open
619                  * to fetch uDevType. When, this is known, the mapping for sending the 
620                  * MCI_OPEN_DRIVER shall be done depending on uDevType.
621                  */
622                 memcpy(mop16 + 1, mop32a + 1, 2 * sizeof(DWORD));
623             } else {
624                 return -2;
625             }
626             *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_OPEN_PARMSA);
627         }
628         return 1;
629         /* case MCI_PASTE:*/
630     case MCI_PAUSE:
631         size = sizeof(MCI_GENERIC_PARMS);
632         break;
633     case MCI_PLAY:
634         switch (uDevType) {
635         case MCI_DEVTYPE_OVERLAY:       /*size = sizeof(MCI_OVLY_PLAY_PARMS);   break;*/FIXME(mci, "NIY ovly\n");       return -2;
636         default:                        size = sizeof(MCI_PLAY_PARMS);          break;
637         }
638         break;
639     case MCI_PUT:
640         switch (uDevType) {
641         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_PUT_PARMS);       FIXME(mci, "NIY rect\n");       return -2;
642         case MCI_DEVTYPE_OVERLAY:       /*size = sizeof(MCI_OVLY_PUT_PARMS);    FIXME(mci, "NIY rect\n");       return -2;*/
643                                         FIXME(mci, "NIY ovly\n");       return -2;
644         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
645         }
646         break;
647     case MCI_REALIZE:
648         size = sizeof(MCI_GENERIC_PARMS);
649         break;
650     case MCI_RECORD:
651         switch (uDevType) {
652         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECORD_PARMS);    FIXME(mci, "NIY rect\n");       return -2;
653         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_RECORD_PARMS);  break;*/FIXME(mci, "NIY vcr\n");        return -2;
654         default:                        size = sizeof(MCI_RECORD_PARMS);        break;
655         }
656         break;
657     case MCI_RESUME:            
658         size = sizeof(MCI_GENERIC_PARMS);
659         break;
660     case MCI_SEEK:
661         switch (uDevType) {
662         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SEEK_PARMS);    break;*/FIXME(mci, "NIY vcr\n");        return -2;
663         default:                        size = sizeof(MCI_SEEK_PARMS);          break;
664         }
665         break;
666     case MCI_SET:
667         switch (uDevType) {
668         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SET_PARMS);       break;
669         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_SET_PARMS);     break;*/FIXME(mci, "NIY vcr\n");        return -2;
670         case MCI_DEVTYPE_SEQUENCER:     size = sizeof(MCI_SEQ_SET_PARMS);       break;
671         /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned, 
672          * so not doing anything should work...
673          */
674         case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_SET_PARMS);      break;
675         default:                        size = sizeof(MCI_SET_PARMS);           break;
676         }
677         break;  
678         /* case MCI_SETTIMECODE:*/
679         /* case MCI_SIGNAL:*/
680     case MCI_SPIN:
681         size = sizeof(MCI_SET_PARMS);           
682         break;
683     case MCI_STATUS:
684         keep = TRUE;
685         switch (uDevType) {
686         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16);  FIXME(mci, "NIY lpstrDevice\n");return -2;
687         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME(mci, "NIY vcr\n");        return -2;
688         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
689         }
690         break;
691     case MCI_STEP:
692         switch (uDevType) {
693         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STEP_PARMS);      break;
694         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STEP_PARMS);    break;*/FIXME(mci, "NIY vcr\n");        return -2;
695         case MCI_DEVTYPE_VIDEODISC:     size = sizeof(MCI_VD_STEP_PARMS);       break;
696         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
697         }
698         break;  
699     case MCI_STOP:              
700         size = sizeof(MCI_SET_PARMS);           
701         break;
702     case MCI_SYSINFO:
703         {
704             LPMCI_SYSINFO_PARMSA        msip32a = (LPMCI_SYSINFO_PARMSA)(*lParam);
705             char*                       ptr     = SEGPTR_ALLOC(sizeof(LPMCI_SYSINFO_PARMSA) + sizeof(MCI_SYSINFO_PARMS16));
706             LPMCI_SYSINFO_PARMS16       msip16;
707
708             if (ptr) {
709                 *(LPMCI_SYSINFO_PARMSA*)(ptr) = msip32a;
710                 msip16 = (LPMCI_SYSINFO_PARMS16)(ptr + sizeof(LPMCI_SYSINFO_PARMSA));
711
712                 msip16->dwCallback       = msip32a->dwCallback;
713                 msip16->lpstrReturn      = (LPSTR)SEGPTR_GET(SEGPTR_ALLOC(msip32a->dwRetSize));
714                 msip16->dwRetSize        = msip32a->dwRetSize;
715                 msip16->dwNumber         = msip32a->dwNumber;
716                 msip16->wDeviceType      = msip32a->wDeviceType;
717             } else {
718                 return -2;
719             }
720             *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_SYSINFO_PARMSA);
721         }
722         return 1;
723         /* case MCI_UNDO: */
724     case MCI_UNFREEZE:
725         switch (uDevType) {
726         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS);      FIXME(mci, "NIY rect\n");       return -2;
727         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     FIXME(mci, "NIY rect\n");       return -2;
728         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
729         }
730         break;
731     case MCI_UPDATE:
732         switch (uDevType) {
733         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_UPDATE_PARMS);    FIXME(mci, "NIY rect\n");       return -2;
734         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
735         }
736         break;
737     case MCI_WHERE:
738         switch (uDevType) {
739         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS);      FIXME(mci, "NIY rect\n");       return -2;
740         case MCI_DEVTYPE_OVERLAY:       size = sizeof(MCI_OVLY_RECT_PARMS);     FIXME(mci, "NIY rect\n");       return -2;
741         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
742         }
743         break;
744     case MCI_WINDOW:
745         switch (uDevType) {
746         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16);  FIXME(mci, "NIY lpstrText\n");  return -2;
747         case MCI_DEVTYPE_OVERLAY:       /*size = sizeof(MCI_OVLY_WINDOW_PARMS); FIXME(mci, "NIY lpstrText\n");  return -2;*/
748                                         FIXME(mci, "NIY ovly\n");       return -2;
749         default:                        size = sizeof(MCI_GENERIC_PARMS);       break;
750         }
751         break;
752     case DRV_LOAD:
753     case DRV_ENABLE:
754     case DRV_OPEN:
755     case DRV_CLOSE:
756     case DRV_DISABLE:
757     case DRV_FREE:
758     case DRV_CONFIGURE:
759     case DRV_QUERYCONFIGURE:
760     case DRV_INSTALL:
761     case DRV_REMOVE:
762     case DRV_EXITSESSION:
763     case DRV_EXITAPPLICATION:
764     case DRV_POWER:
765         FIXME(mci, "This is a hack\n");
766         return 0;
767
768     default:
769         WARN(mci, "Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
770         return -1;
771     }
772     return MCI_MsgMapper32To16_Create((void**)lParam, size, keep);
773 }
774
775 /**************************************************************************
776  *                      MCI_UnMapMsg32ATo16                     [internal]
777  */
778 int     MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
779 {
780     int         size = 0;
781     BOOLEAN     kept = FALSE;   /* there is no need to compute size when kept is FALSE */
782
783     switch (wMsg) {
784         /* case MCI_CAPTURE */
785     case MCI_CLOSE:     
786     case MCI_CLOSE_DRIVER:      
787         break;
788         /* case MCI_CONFIGURE:*/
789         /* case MCI_COPY: */
790     case MCI_CUE:       
791         break;
792         /* case MCI_CUT: */
793     case MCI_DELETE:
794         break;
795         /* case MCI_ESCAPE: */
796     case MCI_FREEZE:
797         break;
798     case MCI_GETDEVCAPS:
799         kept = TRUE;
800         size = sizeof(MCI_GETDEVCAPS_PARMS);
801         break;
802         /* case MCI_INDEX: */
803     case MCI_INFO:
804         {
805             LPMCI_INFO_PARMS16  mip16  = (LPMCI_INFO_PARMS16)PTR_SEG_TO_LIN(lParam);
806             LPMCI_INFO_PARMSA   mip32a = *(LPMCI_INFO_PARMSA*)((char*)mip16 - sizeof(LPMCI_INFO_PARMSA));
807
808             memcpy(mip32a->lpstrReturn, PTR_SEG_TO_LIN(mip16->lpstrReturn), mip32a->dwRetSize);
809
810             if (!SEGPTR_FREE(PTR_SEG_TO_LIN(mip16->lpstrReturn)))
811                 FIXME(mci, "bad free line=%d\n", __LINE__);
812             if (!SEGPTR_FREE((char*)mip16 - sizeof(LPMCI_INFO_PARMSA)))
813                 FIXME(mci, "bad free line=%d\n", __LINE__);
814         }
815         return 0;
816         /* case MCI_MARK: */
817         /* case MCI_MONITOR: */
818     case MCI_OPEN:
819     case MCI_OPEN_DRIVER:       
820         if (lParam) {
821             LPMCI_OPEN_PARMS16  mop16  = (LPMCI_OPEN_PARMS16)PTR_SEG_TO_LIN(lParam);
822             LPMCI_OPEN_PARMSA   mop32a = *(LPMCI_OPEN_PARMSA*)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSA));
823             
824             mop32a->wDeviceID = mop16->wDeviceID;
825             if ((dwFlags & MCI_OPEN_TYPE) && ! 
826                 (dwFlags & MCI_OPEN_TYPE_ID) && 
827                 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16->lpstrDeviceType)))
828                 FIXME(mci, "bad free line=%d\n", __LINE__);
829             if ((dwFlags & MCI_OPEN_ELEMENT) && 
830                 !(dwFlags & MCI_OPEN_ELEMENT_ID) && 
831                 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16->lpstrElementName)))
832                 FIXME(mci, "bad free line=%d\n", __LINE__);
833             if ((dwFlags & MCI_OPEN_ALIAS) && 
834                 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16->lpstrAlias)))
835                 FIXME(mci, "bad free line=%d\n", __LINE__);
836
837             if (!SEGPTR_FREE((LPVOID)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSA))))
838                 FIXME(mci, "bad free line=%d\n", __LINE__);
839         }
840         return 0;
841         /* case MCI_PASTE:*/
842     case MCI_PAUSE:
843         break;
844     case MCI_PLAY:              
845         break;
846     case MCI_PUT:
847         break;
848     case MCI_REALIZE:
849         break;
850     case MCI_RECORD:
851         break;
852     case MCI_RESUME:
853         break;
854     case MCI_SEEK:
855         break;
856     case MCI_SET:
857         break;
858         /* case MCI_SETTIMECODE:*/
859         /* case MCI_SIGNAL:*/
860     case MCI_SPIN:
861         break;
862     case MCI_STATUS:
863         kept = TRUE;
864         switch (uDevType) {
865         case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16);  FIXME(mci, "NIY lpstrDevice\n");return -2;
866         case MCI_DEVTYPE_VCR:           /*size = sizeof(MCI_VCR_STATUS_PARMS);  break;*/FIXME(mci, "NIY vcr\n");        return -2;
867         default:                        size = sizeof(MCI_STATUS_PARMS);        break;
868         }
869         break;
870     case MCI_STEP:
871         break;
872     case MCI_STOP:
873         break;
874     case MCI_SYSINFO:
875         if (lParam) {
876             LPMCI_SYSINFO_PARMS16       msip16  = (LPMCI_SYSINFO_PARMS16)PTR_SEG_TO_LIN(lParam);
877             LPMCI_SYSINFO_PARMSA        msip32a = *(LPMCI_SYSINFO_PARMSA*)((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA));
878
879             if (msip16) {
880                 msip16->dwCallback       = msip32a->dwCallback;
881                 memcpy(msip32a->lpstrReturn, PTR_SEG_TO_LIN(msip16->lpstrReturn), msip32a->dwRetSize);
882                 if (!SEGPTR_FREE(msip16->lpstrReturn))
883                     FIXME(mci, "bad free line=%d\n", __LINE__);
884
885                 if (!SEGPTR_FREE((LPVOID)(lParam - sizeof(LPMCI_SYSINFO_PARMSA))))
886                     FIXME(mci, "bad free line=%d\n", __LINE__);
887             } else {
888                 return -2;
889             }
890         }
891         return 1;
892         /* case MCI_UNDO: */
893     case MCI_UNFREEZE:
894         break;
895     case MCI_UPDATE:
896         break;
897     case MCI_WHERE:
898         break;
899     case MCI_WINDOW:
900         /* FIXME: see map function */
901         break;
902
903     case DRV_LOAD:
904     case DRV_ENABLE:
905     case DRV_OPEN:
906     case DRV_CLOSE:
907     case DRV_DISABLE:
908     case DRV_FREE:
909     case DRV_CONFIGURE:
910     case DRV_QUERYCONFIGURE:
911     case DRV_INSTALL:
912     case DRV_REMOVE:
913     case DRV_EXITSESSION:
914     case DRV_EXITAPPLICATION:
915     case DRV_POWER:
916         FIXME(mci, "This is a hack\n");
917         return 0;
918     default:
919         FIXME(mci, "Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
920         return -1;
921     }
922     return MCI_MsgMapper32To16_Destroy((void*)lParam, size, kept);
923 }
924
925 /**************************************************************************
926  *                      MCI_SendCommand                         [internal]
927  */
928 DWORD MCI_SendCommand(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
929 {
930     DWORD               dwRet = MCIERR_DEVICE_NOT_INSTALLED;
931     
932     if (!MCI_DevIDValid(wDevID)) {
933         dwRet = MCIERR_INVALID_DEVICE_ID;
934     } else {
935         MCIPROC         proc = MCI_GetProc(MCI_GetDrv(wDevID)->modp.wType);
936         
937         if (proc) {
938             dwRet = (*proc)(MCI_GetDrv(wDevID)->modp.wDeviceID, 
939                             MCI_GetDrv(wDevID)->hDrv, 
940                             wMsg, dwParam1, dwParam2);
941         } else if (MCI_GetDrv(wDevID)->hDrv) {
942             switch (DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv)) {
943             case WINE_DI_TYPE_16:
944                 {
945                     int                 res;
946                     
947                     switch (res = MCI_MapMsg32ATo16(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam1, &dwParam2)) {
948                     case -1:
949                         TRACE(mci, "Not handled yet (%s)\n", MCI_CommandToString(wMsg));
950                         dwRet = MCIERR_DRIVER_INTERNAL;
951                         break;
952                     case -2:
953                         TRACE(mci, "Problem mapping msg=%s from 16 to 32a\n", MCI_CommandToString(wMsg));
954                         dwRet = MCIERR_OUT_OF_MEMORY;
955                         break;
956                     case 0:
957                     case 1:
958                         dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
959                         if (res)
960                             MCI_UnMapMsg32ATo16(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam1, dwParam2);
961                         break;
962                     }
963                 }
964                 break;
965             case WINE_DI_TYPE_32:
966                 dwRet = SendDriverMessage(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
967                 break;
968             default:
969                 WARN(mci, "Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv));
970                 dwRet = MCIERR_DRIVER_INTERNAL;
971             }
972         } else {
973             WARN(mci, "unknown device type=%04X !\n", MCI_GetDrv(wDevID)->modp.wType);
974         }
975     }
976     return dwRet;
977 }
978
979 /**************************************************************************
980  *                      MCI_Open                                [internal]
981  */
982 DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms)
983 {
984     char                strDevTyp[128];
985     UINT16              uDevType = 0;
986     UINT16              wDevID = MCI_FirstDevID();
987     DWORD               dwRet;
988     
989     TRACE(mci, "(%08lX, %p)\n", dwParam, lpParms);
990     if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
991     
992     if ((dwParam & ~(MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY|MCI_WAIT)) != 0) {
993         FIXME(mci, "unsupported yet dwFlags=%08lX\n", 
994               (dwParam & ~(MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY|MCI_WAIT)));
995     }
996
997     while (MCI_GetDrv(wDevID)->modp.wType != 0) {
998         wDevID = MCI_NextDevID(wDevID);
999         if (!MCI_DevIDValid(wDevID)) {
1000             TRACE(mci, "MAXMCIDRIVERS reached !\n");
1001             return MCIERR_OUT_OF_MEMORY;
1002         }
1003     }
1004
1005     TRACE(mci, "wDevID=%04X \n", wDevID);
1006     memcpy(MCI_GetOpenDrv(wDevID), lpParms, sizeof(*lpParms));
1007     
1008     strDevTyp[0] = 0;
1009
1010     if (dwParam & MCI_OPEN_ELEMENT) {
1011         char*   t;
1012         
1013         TRACE(mci, "lpstrElementName='%s'\n", lpParms->lpstrElementName);
1014         t = strrchr(lpParms->lpstrElementName, '.');
1015         if (t) {
1016             GetProfileStringA("mci extensions", t+1, "*", strDevTyp, sizeof(strDevTyp));
1017             if (strcmp(strDevTyp, "*") == 0) {
1018                 TRACE(mci,"No [mci extensions] entry for %s found.\n", t);
1019                 return MCIERR_EXTENSION_NOT_FOUND;
1020             }
1021             TRACE(mci, "Extension %s is mapped to type %s\n", t, strDevTyp);
1022         } else if (GetDriveTypeA(lpParms->lpstrElementName) == DRIVE_CDROM) {
1023             /* FIXME: this will not work if several CDROM drives are installed on the machine */
1024             strcpy(strDevTyp, "CDAUDIO");
1025         } else {
1026             return MCIERR_EXTENSION_NOT_FOUND;
1027         }
1028     }
1029     
1030     if (dwParam & MCI_OPEN_ALIAS) {
1031         TRACE(mci, "Alias='%s' !\n", lpParms->lpstrAlias);
1032         /* FIXME is there any memory leak here ? */
1033         MCI_GetOpenDrv(wDevID)->lpstrAlias = strdup(lpParms->lpstrAlias);
1034         /* mplayer does allocate alias to CDAUDIO */
1035     }
1036     if (dwParam & MCI_OPEN_TYPE) {
1037         if (dwParam & MCI_OPEN_TYPE_ID) {
1038 #if 0
1039             TRACE(mci, "Dev=%08lx!\n", (DWORD)lpParms->lpstrDeviceType);
1040             uDevType = LOWORD((DWORD)lpParms->lpstrDeviceType);
1041             MCI_GetOpenDrv(wDevID)->lpstrDeviceType = lpParms->lpstrDeviceType;
1042 #endif
1043             if (LOWORD((DWORD)lpParms->lpstrDeviceType) != MCI_DEVTYPE_CD_AUDIO) {
1044                 FIXME(mci, "MCI_OPEN_TYPE_ID is no longer properly supported\n");
1045             }
1046             uDevType = LOWORD((DWORD)lpParms->lpstrDeviceType);
1047         } else {
1048             if (lpParms->lpstrDeviceType == NULL) 
1049                 return MCIERR_NULL_PARAMETER_BLOCK;
1050             TRACE(mci, "Dev='%s' !\n", lpParms->lpstrDeviceType);
1051             /* FIXME is there any memory leak here ? */
1052             MCI_GetOpenDrv(wDevID)->lpstrDeviceType = strdup(lpParms->lpstrDeviceType);
1053             strcpy(strDevTyp, lpParms->lpstrDeviceType);
1054         }
1055     }
1056
1057     if (uDevType == 0 && strDevTyp[0] != 0) {
1058         CharUpperA(strDevTyp);
1059         /* try Wine internal MCI drivers */
1060         uDevType = MCI_GetDevType(strDevTyp);
1061         if (uDevType == 0) { /* Nope, load external */
1062             HDRVR                       hDrv;
1063             MCI_OPEN_DRIVER_PARMSA      modp;
1064             
1065             modp.wDeviceID = wDevID;
1066             modp.lpstrParams = NULL;
1067
1068             /* FIXME: this is a hack... some MCI drivers, while being open, call
1069              * mciSetData, which lookup for non empty slots in MCI table list
1070              * Unfortunatly, open slots are known when wType == 0...
1071              * so use a dummy type, just to keep on going. May be wType == 0 is 
1072              * not the best solution to indicate empty slot in MCI drivers table
1073              */
1074             MCI_GetDrv(wDevID)->modp.wType = MCI_DEVTYPE_CD_AUDIO;
1075             hDrv = OpenDriverA(strDevTyp, "mci", (LPARAM)&modp);
1076
1077             if (!hDrv) {
1078                 FIXME(mci, "Couldn't load driver for type %s.\n", strDevTyp);
1079                 return MCIERR_DEVICE_NOT_INSTALLED;
1080             }                   
1081             uDevType = modp.wType;
1082             MCI_GetDrv(wDevID)->hDrv = hDrv;
1083
1084             TRACE(mci, "Loaded driver %u (%s), type is %d\n", hDrv, strDevTyp, uDevType);
1085         }
1086     } else {
1087         MCI_GetDrv(wDevID)->hDrv = 0;
1088     }
1089
1090     MCI_GetDrv(wDevID)->modp.wType = uDevType;
1091     MCI_GetDrv(wDevID)->modp.wDeviceID = 0;  /* FIXME? for multiple devices */
1092
1093     lpParms->wDeviceID = wDevID;
1094
1095     TRACE(mci, "mcidev=%d, uDevType=%04X wDeviceID=%04X !\n", 
1096           wDevID, uDevType, lpParms->wDeviceID);
1097
1098     dwRet = MCI_SendCommand(wDevID, MCI_OPEN_DRIVER, dwParam, (DWORD)lpParms);
1099     MCI_GetDrv(wDevID)->lpfnYieldProc = 0;
1100     MCI_GetDrv(wDevID)->dwYieldData = 0;
1101     MCI_GetDrv(wDevID)->hCreatorTask = GetCurrentTask();
1102     
1103     if (dwRet == 0) {
1104         /* only handled devices fall through */
1105         TRACE(mci, "wDevID = %04X wDeviceID = %d dwRet = %ld\n", wDevID, lpParms->wDeviceID, dwRet);
1106     } else {
1107         TRACE(mci, "failed to open driver (MCI_OPEN_DRIVER msg) [%08lx], closing\n", dwRet);
1108         MCI_GetDrv(wDevID)->modp.wType = 0;
1109     }
1110     if (dwParam & MCI_NOTIFY)
1111         mciDriverNotify16(lpParms->dwCallback, wDevID, dwRet == 0 ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE);
1112     
1113     return dwRet;
1114 }
1115
1116 /**************************************************************************
1117  *                      MCI_Close                               [internal]
1118  */
1119 DWORD MCI_Close(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
1120 {
1121     DWORD       dwRet;
1122     
1123     TRACE(mci, "(%04x, %08lX, %p)\n", wDevID, dwParam, lpParms);
1124
1125     if (wDevID == MCI_ALL_DEVICE_ID) {
1126         FIXME(mci, "unhandled MCI_ALL_DEVICE_ID\n");
1127         return MCIERR_CANNOT_USE_ALL;
1128     }
1129
1130     dwRet = MCI_SendCommand(wDevID, MCI_CLOSE_DRIVER, dwParam, (DWORD)lpParms);
1131     if (MCI_GetDrv(wDevID)->hDrv) {
1132 #if 0
1133         CloseDriver(MCI_GetDrv(wDevID)->hDrv, 0, 0);
1134 #endif
1135     }
1136     MCI_GetDrv(wDevID)->modp.wType = 0;
1137     
1138     if (dwParam & MCI_NOTIFY)
1139         mciDriverNotify16(lpParms->dwCallback, wDevID,
1140                           (dwRet == 0) ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE);
1141     
1142     return dwRet;
1143 }
1144
1145 /**************************************************************************
1146  *                      MCI_WriteString                         [internal]
1147  */
1148 DWORD   MCI_WriteString(LPSTR lpDstStr, DWORD dstSize, LPCSTR lpSrcStr)
1149 {
1150     DWORD       ret;
1151
1152     if (dstSize <= strlen(lpSrcStr)) {
1153         lstrcpynA(lpDstStr, lpSrcStr, dstSize - 1);
1154         ret = MCIERR_PARAM_OVERFLOW;
1155     } else {
1156         strcpy(lpDstStr, lpSrcStr);
1157         ret = 0;
1158     }
1159     return ret;
1160 }
1161
1162 /**************************************************************************
1163  *                      MCI_Sysinfo                             [internal]
1164  */
1165 DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSA lpParms)
1166 {
1167     DWORD       ret = MCIERR_INVALID_DEVICE_ID;
1168     
1169     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1170     
1171     TRACE(mci, "(%08x, %08lX, %08lX[num=%ld, wDevTyp=%u])\n", 
1172           uDevID, dwFlags, (DWORD)lpParms, lpParms->dwNumber, lpParms->wDeviceType);
1173     
1174     switch (dwFlags & ~MCI_SYSINFO_OPEN) {
1175     case MCI_SYSINFO_QUANTITY:
1176         {
1177             DWORD       cnt = 0;
1178             WORD        i;
1179             
1180             if (lpParms->wDeviceType < MCI_DEVTYPE_FIRST || lpParms->wDeviceType > MCI_DEVTYPE_LAST) {
1181                 if (dwFlags & MCI_SYSINFO_OPEN) {
1182                     TRACE(mci, "MCI_SYSINFO_QUANTITY: # of open MCI drivers\n");
1183                     for (i = 0; i < MAXMCIDRIVERS; i++) {
1184                         if (mciDrv[i].modp.wType != 0) cnt++;
1185                     }
1186                 } else {
1187                     TRACE(mci, "MCI_SYSINFO_QUANTITY: # of installed MCI drivers\n");
1188                     cnt = mciInstalledCount;
1189                 }
1190             } else {
1191                 if (dwFlags & MCI_SYSINFO_OPEN) {
1192                     TRACE(mci, "MCI_SYSINFO_QUANTITY: # of open MCI drivers of type %u\n", lpParms->wDeviceType);
1193                     for (i = 0; i < MAXMCIDRIVERS; i++) {
1194                         if (mciDrv[i].modp.wType == lpParms->wDeviceType) cnt++;
1195                     }
1196                 } else {
1197                     TRACE(mci, "MCI_SYSINFO_QUANTITY: # of installed MCI drivers of type %u\n", lpParms->wDeviceType);
1198                     FIXME(mci, "Don't know how to get # of MCI devices of a given type\n");
1199                     cnt = 1;
1200                 }
1201             }
1202             *(DWORD*)lpParms->lpstrReturn = cnt;
1203         }
1204         TRACE(mci, "(%ld) => '%ld'\n", lpParms->dwNumber, *(DWORD*)lpParms->lpstrReturn);
1205         ret = 0;
1206         break;
1207     case MCI_SYSINFO_INSTALLNAME:
1208         TRACE(mci, "MCI_SYSINFO_INSTALLNAME \n");
1209         if (MCI_DevIDValid(uDevID)) {
1210             LPCSTR      str = MCI_GetDevTypeString(MCI_GetDrv(uDevID)->modp.wType);
1211             ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize, str);
1212         } else {
1213             *lpParms->lpstrReturn = 0;
1214             ret = MCIERR_INVALID_DEVICE_ID;
1215         }
1216         TRACE(mci, "(%ld) => '%s'\n", lpParms->dwNumber, lpParms->lpstrReturn);
1217         break;
1218     case MCI_SYSINFO_NAME:
1219         TRACE(mci, "MCI_SYSINFO_NAME\n");
1220         if (dwFlags & MCI_SYSINFO_OPEN) {
1221             FIXME(mci, "Don't handle MCI_SYSINFO_NAME|MCI_SYSINFO_OPEN (yet)\n");
1222             ret = MCIERR_UNRECOGNIZED_COMMAND;
1223         } else if (lpParms->dwNumber > mciInstalledCount) {
1224             ret = MCIERR_OUTOFRANGE;
1225         } else {
1226             DWORD       count = lpParms->dwNumber;
1227             LPSTR       ptr = lpmciInstallNames;
1228
1229             while (--count > 0) ptr += strlen(ptr) + 1;
1230             ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize, ptr);
1231         }
1232         TRACE(mci, "(%ld) => '%s'\n", lpParms->dwNumber, lpParms->lpstrReturn);
1233         break;
1234     default:
1235         TRACE(mci, "Unsupported flag value=%08lx\n", dwFlags);
1236         ret = MCIERR_UNRECOGNIZED_COMMAND;
1237     }
1238     return ret;
1239 }
1240
1241 struct SCA {
1242     UINT        wDevID;
1243     UINT        wMsg;
1244     DWORD       dwParam1;
1245     DWORD       dwParam2;
1246     BOOL        allocatedCopy;
1247 };
1248
1249 DWORD WINAPI mciSendCommandA(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2);
1250
1251 /**************************************************************************
1252  *                              MCI_SCAStarter                  [internal]
1253  */
1254 static DWORD WINAPI MCI_SCAStarter(LPVOID arg)
1255 {
1256     struct SCA* sca = (struct SCA*)arg;
1257     DWORD               ret;
1258
1259     TRACE(mci, "In thread before async command (%08x,%s,%08lx,%08lx)\n",
1260           sca->wDevID, MCI_CommandToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
1261     ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);
1262     TRACE(mci, "In thread after async command (%08x,%s,%08lx,%08lx)\n",
1263           sca->wDevID, MCI_CommandToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
1264     if (sca->allocatedCopy)
1265         HeapFree(GetProcessHeap(), 0, (LPVOID)sca->dwParam2);
1266     HeapFree(GetProcessHeap(), 0, sca);
1267     ExitThread(ret);
1268     WARN(mci, "Should not happen ? what's wrong \n");
1269     /* should not go after this point */
1270     return ret;
1271 }
1272
1273 /**************************************************************************
1274  *                              MCI_SendCommandAsync            [internal]
1275  */
1276 DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2, UINT size)
1277 {
1278     struct SCA* sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA));
1279
1280     if (sca == 0)
1281         return MCIERR_OUT_OF_MEMORY;
1282
1283     sca->wDevID   = wDevID;
1284     sca->wMsg     = wMsg;
1285     sca->dwParam1 = dwParam1;
1286     
1287     if (size) {
1288         sca->dwParam2 = (DWORD)HeapAlloc(GetProcessHeap(), 0, size);
1289         if (sca->dwParam2 == 0) {
1290             HeapFree(GetProcessHeap(), 0, sca);
1291             return MCIERR_OUT_OF_MEMORY;
1292         }
1293         sca->allocatedCopy = TRUE;
1294         /* copy structure passed by program in dwParam2 to be sure 
1295          * we can still use it whatever the program does 
1296          */
1297         memcpy((LPVOID)sca->dwParam2, (LPVOID)dwParam2, size);
1298     } else {
1299         sca->dwParam2 = dwParam2;
1300         sca->allocatedCopy = FALSE;
1301     }
1302
1303     if (CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL) == 0) {
1304         WARN(mci, "Couldn't allocate thread for async command handling, sending synchonously\n");
1305         return MCI_SCAStarter(&sca);
1306     }
1307     return 0;
1308 }
1309
1310 /**************************************************************************
1311  *                              MCI_CleanUp                     [internal]
1312  *
1313  * Some MCI commands need to be cleaned-up (when not called from 
1314  * mciSendString), because MCI drivers return extra information for string
1315  * transformation. This function gets read of them.
1316  */
1317 LRESULT         MCI_CleanUp(LRESULT dwRet, UINT wMsg, DWORD dwParam2, BOOL bIs32)
1318 {
1319     switch (wMsg) {
1320     case MCI_GETDEVCAPS:
1321         switch (dwRet & 0xFFFF0000ul) {
1322         case 0:
1323             break;
1324         case MCI_RESOURCE_RETURNED:
1325         case MCI_RESOURCE_RETURNED|MCI_RESOURCE_DRIVER:
1326         case MCI_COLONIZED3_RETURN:
1327         case MCI_COLONIZED4_RETURN:
1328         case MCI_INTEGER_RETURNED:
1329             {
1330                 LPMCI_GETDEVCAPS_PARMS  lmgp = (LPMCI_GETDEVCAPS_PARMS)(bIs32 ? (void*)dwParam2 : PTR_SEG_TO_LIN(dwParam2));
1331
1332                 dwRet = LOWORD(dwRet);
1333                 TRACE(mci, "Changing %08lx to %08lx\n", lmgp->dwReturn, (DWORD)LOWORD(lmgp->dwReturn));
1334
1335                 lmgp->dwReturn = LOWORD(lmgp->dwReturn);
1336             } 
1337             break;
1338         default:
1339             FIXME(mci, "Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet));
1340         }
1341         break;
1342     case MCI_STATUS:
1343         switch (dwRet & 0xFFFF0000ul) {
1344         case 0:
1345             break;
1346         case MCI_RESOURCE_RETURNED:
1347         case MCI_RESOURCE_RETURNED|MCI_RESOURCE_DRIVER:
1348         case MCI_COLONIZED3_RETURN:
1349         case MCI_COLONIZED4_RETURN:
1350         case MCI_INTEGER_RETURNED:
1351             {
1352                 LPMCI_STATUS_PARMS      lsp = (LPMCI_STATUS_PARMS)(bIs32 ? (void*)dwParam2 : PTR_SEG_TO_LIN(dwParam2));
1353
1354                 dwRet = LOWORD(dwRet);
1355                 TRACE(mci, "Changing %08lx to %08lx\n", lsp->dwReturn,(DWORD) LOWORD(lsp->dwReturn));
1356                 lsp->dwReturn = LOWORD(lsp->dwReturn);
1357             }
1358             break;
1359         default:
1360             FIXME(mci, "Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet));
1361         }
1362         break;
1363     default:
1364         break;
1365     }
1366     return dwRet;
1367 }
1368