Added support of source and destination rectangles in Blit function.
[wine] / multimedia / mmsystem.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  * MMSYTEM functions
5  *
6  * Copyright 1993 Martin Ayotte
7  */
8
9 /* 
10  * Eric POUECH : 
11  * 98/9 added support for Win32 MCI
12  */
13
14 /* FIXME: I think there are some segmented vs. linear pointer weirdnesses 
15  *        and long term pointers to 16 bit space in here
16  */
17
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <fcntl.h>
22 #include <errno.h>
23 #include <sys/ioctl.h>
24 #include "windows.h"
25 #include "win.h"
26 #include "heap.h"
27 #include "ldt.h"
28 #include "user.h"
29 #include "driver.h"
30 #include "file.h"
31 #include "mmsystem.h"
32 #include "multimedia.h"
33 #include "xmalloc.h"
34 #include "callback.h"
35 #include "module.h"
36 #include "selectors.h"
37 #include "debug.h"
38
39 int     mciInstalledCount;
40 int     mciInstalledListLen;
41 LPSTR   lpmciInstallNames = NULL;
42
43 struct WINE_MCIDRIVER mciDrv[MAXMCIDRIVERS];
44
45 UINT16 WINAPI midiGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize);
46 static UINT16 waveGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize);
47 LONG   WINAPI DrvDefDriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, 
48                                DWORD dwParam1, DWORD dwParam2);
49
50 #define mciGetDrv(wDevID)       (&mciDrv[MMSYSTEM_DevIDToIndex(wDevID)])
51 #define mciGetOpenDrv(wDevID)   (&(mciGetDrv(wDevID)->mop))
52
53 /* The wDevID's returned by wine were originally in the range 
54  * 0 - (MAXMCIDRIVERS - 1) and used directly as array indices.
55  * Unfortunately, ms-windows uses wDevID of zero to indicate
56  * errors.  Now, multimedia drivers must pass the wDevID through
57  * MMSYSTEM_DevIDToIndex to get an index in that range.  An
58  * arbitrary value, MMSYSTEM_MAGIC is added to the wDevID seen
59  * by the windows programs.
60  */
61
62 #define MMSYSTEM_MAGIC 0x0F00
63
64 /**************************************************************************
65  *                              MMSYSTEM_DevIDToIndex   [internal]
66  */
67 int MMSYSTEM_DevIDToIndex(UINT16 wDevID) 
68 {
69     return wDevID - MMSYSTEM_MAGIC;
70 }
71
72 /**************************************************************************
73  *                              MMSYSTEM_FirstDevId     [internal]
74  */
75 UINT16 MMSYSTEM_FirstDevID(void)
76 {
77     return MMSYSTEM_MAGIC;
78 }
79
80 /**************************************************************************
81  *                              MMSYSTEM_NextDevId      [internal]
82  */
83 UINT16 MMSYSTEM_NextDevID(UINT16 wDevID) 
84 {
85     return wDevID + 1;
86 }
87
88 /**************************************************************************
89  *                              MMSYSTEM_DevIDValid     [internal]
90  */
91 BOOL32 MMSYSTEM_DevIDValid(UINT16 wDevID) 
92 {
93     return wDevID >= 0x0F00 && wDevID < (0x0F00 + MAXMCIDRIVERS);
94 }
95
96 /**************************************************************************
97  *                              MMSYSTEM_WEP            [MMSYSTEM.1]
98  */
99 int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
100                         WORD cbHeapSize, LPSTR lpCmdLine)
101 {
102     FIXME(mmsys, "STUB: Unloading MMSystem DLL ... hInst=%04X \n", hInstance);
103     return(TRUE);
104 }
105
106 static void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16,LPMMTIME32 mmt32) 
107 {
108     mmt16->wType = mmt32->wType;
109     /* layout of rest is the same for 32/16 */
110     memcpy(&(mmt32->u),&(mmt16->u),sizeof(mmt16->u));
111 }
112
113 static void MMSYSTEM_MMTIME16to32(LPMMTIME32 mmt32,LPMMTIME16 mmt16) 
114 {
115     mmt32->wType = mmt16->wType;
116     /* layout of rest is the same for 32/16,
117      * Note: mmt16->u is 2 bytes smaller than mmt32->u
118      */
119     memcpy(&(mmt16->u),&(mmt32->u),sizeof(mmt16->u));
120 }
121
122 static HANDLE32         PlaySound_hThread = 0;
123 static HANDLE32         PlaySound_hPlayEvent = 0;
124 static HANDLE32         PlaySound_hReadyEvent = 0;
125 static HANDLE32         PlaySound_hMiddleEvent = 0;
126 static BOOL32           PlaySound_Result = FALSE;
127 static int              PlaySound_Stop = FALSE;
128 static int              PlaySound_Playing = FALSE;
129
130 static LPCSTR           PlaySound_pszSound = NULL;
131 static HMODULE32        PlaySound_hmod = 0;
132 static DWORD            PlaySound_fdwSound = 0;
133 static int              PlaySound_Loop = FALSE;
134 static int              PlaySound_SearchMode = 0; /* 1 - sndPlaySound search order
135                                                      2 - PlaySound order */
136
137 static HMMIO16  get_mmioFromFile(LPCSTR lpszName)
138 {
139     return mmioOpen16((LPSTR)lpszName, NULL,
140                       MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
141 }
142
143 static HMMIO16 get_mmioFromProfile(UINT32 uFlags, LPCSTR lpszName) 
144 {
145     char        str[128];
146     LPSTR       ptr;
147     HMMIO16     hmmio;
148     
149     TRACE(mmsys, "searching in SystemSound List !\n");
150     GetProfileString32A("Sounds", (LPSTR)lpszName, "", str, sizeof(str));
151     if (strlen(str) == 0) {
152         if (uFlags & SND_NODEFAULT) return 0;
153         GetProfileString32A("Sounds", "Default", "", str, sizeof(str));
154         if (strlen(str) == 0) return 0;
155     }
156     if ( (ptr = (LPSTR)strchr(str, ',')) != NULL) *ptr = '\0';
157     hmmio = get_mmioFromFile(str);
158     if (hmmio == 0) {
159         WARN(mmsys, "can't find SystemSound='%s' !\n", str);
160         return 0;
161     }
162     return hmmio;
163 }
164
165 static BOOL16 WINAPI proc_PlaySound(LPCSTR lpszSoundName, UINT32 uFlags)
166 {
167     BOOL16              bRet = FALSE;
168     HMMIO16             hmmio;
169     MMCKINFO            ckMainRIFF;
170     
171     TRACE(mmsys, "SoundName='%s' uFlags=%04X !\n", lpszSoundName, uFlags);
172     if (lpszSoundName == NULL) {
173         TRACE(mmsys, "Stop !\n");
174         return FALSE;
175     }
176     if (uFlags & SND_MEMORY) {
177         MMIOINFO16 mminfo;
178         memset(&mminfo, 0, sizeof(mminfo));
179         mminfo.fccIOProc = FOURCC_MEM;
180         mminfo.pchBuffer = (LPSTR)lpszSoundName;
181         mminfo.cchBuffer = -1;
182         TRACE(mmsys, "Memory sound %p\n",lpszSoundName);
183         hmmio = mmioOpen16(NULL, &mminfo, MMIO_READ);
184     } else {
185         hmmio = 0;
186         if (uFlags & SND_ALIAS)
187             if ((hmmio=get_mmioFromProfile(uFlags, lpszSoundName)) == 0) 
188                 return FALSE;
189         
190         if (uFlags & SND_FILENAME)
191             if ((hmmio=get_mmioFromFile(lpszSoundName)) == 0) return FALSE;
192         
193         if (PlaySound_SearchMode == 1) {
194             PlaySound_SearchMode = 0;
195             if ((hmmio=get_mmioFromFile(lpszSoundName)) == 0) 
196                 if ((hmmio=get_mmioFromProfile(uFlags, lpszSoundName)) == 0) 
197                     return FALSE;
198         }
199         
200         if (PlaySound_SearchMode == 2) {
201             PlaySound_SearchMode = 0;
202             if ((hmmio=get_mmioFromProfile(uFlags | SND_NODEFAULT, lpszSoundName)) == 0) 
203                 if ((hmmio=get_mmioFromFile(lpszSoundName)) == 0)       
204                     if ((hmmio=get_mmioFromProfile(uFlags, lpszSoundName)) == 0) return FALSE;
205         }
206     }
207     
208     if (mmioDescend(hmmio, &ckMainRIFF, NULL, 0) == 0) 
209         do {
210             TRACE(mmsys, "ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
211                   (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType, ckMainRIFF.cksize);
212             
213             if ((ckMainRIFF.ckid == FOURCC_RIFF) &&
214                 (ckMainRIFF.fccType == mmioFOURCC('W', 'A', 'V', 'E'))) {
215                 MMCKINFO        mmckInfo;
216                 
217                 mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
218                 
219                 if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) == 0) {
220                     PCMWAVEFORMAT           pcmWaveFormat;
221                     
222                     TRACE(mmsys, "Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
223                           (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType, mmckInfo.cksize);
224                     
225                     if (mmioRead32(hmmio,(HPSTR)&pcmWaveFormat,
226                                    (long) sizeof(PCMWAVEFORMAT)) == (long) sizeof(PCMWAVEFORMAT)) {
227                         TRACE(mmsys, "wFormatTag=%04X !\n", pcmWaveFormat.wf.wFormatTag);
228                         TRACE(mmsys, "nChannels=%d \n", pcmWaveFormat.wf.nChannels);
229                         TRACE(mmsys, "nSamplesPerSec=%ld\n", pcmWaveFormat.wf.nSamplesPerSec);
230                         TRACE(mmsys, "nAvgBytesPerSec=%ld\n", pcmWaveFormat.wf.nAvgBytesPerSec);
231                         TRACE(mmsys, "nBlockAlign=%d \n", pcmWaveFormat.wf.nBlockAlign);
232                         TRACE(mmsys, "wBitsPerSample=%u !\n", pcmWaveFormat.wBitsPerSample);
233                         
234                         mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
235                         if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) == 0) {
236                             WAVEOPENDESC        waveDesc;
237                             DWORD               dwRet;
238                             
239                             TRACE(mmsys, "Chunk Found \
240 ckid=%.4s fccType=%.4s cksize=%08lX \n", (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType, mmckInfo.cksize);
241                             
242                             pcmWaveFormat.wf.nAvgBytesPerSec = pcmWaveFormat.wf.nSamplesPerSec * 
243                                 pcmWaveFormat.wf.nBlockAlign;
244                             waveDesc.hWave    = 0;
245                             waveDesc.lpFormat = (LPWAVEFORMAT)&pcmWaveFormat;
246                             
247                             dwRet = wodMessage( 0, WODM_OPEN, 0, (DWORD)&waveDesc, CALLBACK_NULL);
248                             if (dwRet == MMSYSERR_NOERROR) {
249                                 WAVEHDR         waveHdr;
250                                 HGLOBAL16       hData;
251                                 INT32           count, bufsize, left = mmckInfo.cksize;
252                                 
253                                 bufsize = 64000;
254                                 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
255                                 waveHdr.lpData = (LPSTR)GlobalLock16(hData);
256                                 waveHdr.dwBufferLength = bufsize;
257                                 waveHdr.dwUser = 0L;
258                                 waveHdr.dwFlags = 0L;
259                                 waveHdr.dwLoops = 0L;
260                                 
261                                 dwRet = wodMessage(0,WODM_PREPARE,0,(DWORD)&waveHdr,sizeof(WAVEHDR));
262                                 if (dwRet == MMSYSERR_NOERROR) {
263                                     while (left) {
264                                         if (PlaySound_Stop) {
265                                             PlaySound_Stop = FALSE;
266                                             PlaySound_Loop = FALSE;
267                                             break;
268                                         }
269                                         if (bufsize > left) bufsize = left;
270                                         count = mmioRead32(hmmio,waveHdr.lpData,bufsize);
271                                         if (count < 1) break;
272                                         left -= count;
273                                         waveHdr.dwBufferLength = count;
274                                 /*      waveHdr.dwBytesRecorded = count; */
275                                         /* FIXME: doesn't expect async ops */ 
276                                         wodMessage( 0, WODM_WRITE, 0, (DWORD)&waveHdr, sizeof(WAVEHDR));
277                                     }
278                                     wodMessage( 0, WODM_UNPREPARE, 0, (DWORD)&waveHdr, sizeof(WAVEHDR));
279                                     wodMessage( 0, WODM_CLOSE, 0, 0L, 0L);
280                                     
281                                     bRet = TRUE;
282                                 } else 
283                                     WARN(mmsys, "can't prepare WaveOut device !\n");
284                                 
285                                 GlobalUnlock16(hData);
286                                 GlobalFree16(hData);
287                             }
288                         }
289                     }
290                 }
291             }
292         } while (PlaySound_Loop);
293     
294     if (hmmio != 0) mmioClose32(hmmio, 0);
295     return bRet;
296 }
297
298 static DWORD WINAPI PlaySound_Thread(LPVOID arg) 
299 {
300     DWORD     res;
301     
302     for (;;) {
303         PlaySound_Playing = FALSE;
304         SetEvent(PlaySound_hReadyEvent);
305         res = WaitForSingleObject(PlaySound_hPlayEvent, INFINITE32);
306         ResetEvent(PlaySound_hReadyEvent);
307         SetEvent(PlaySound_hMiddleEvent);
308         if (res == WAIT_FAILED) ExitThread(2);
309         if (res != WAIT_OBJECT_0) continue;
310         PlaySound_Playing = TRUE;
311         
312         if ((PlaySound_fdwSound & SND_RESOURCE) == SND_RESOURCE) {
313             HRSRC32   hRES;
314             HGLOBAL32 hGLOB;
315             void      *ptr;
316
317             if ((hRES = FindResource32A(PlaySound_hmod, PlaySound_pszSound, "WAVE")) == 0) {
318                 PlaySound_Result = FALSE;
319                 continue;
320             }
321             if ((hGLOB = LoadResource32(PlaySound_hmod, hRES)) == 0) {
322                 PlaySound_Result = FALSE;
323                 continue;
324             }
325             if ((ptr = LockResource32(hGLOB)) == NULL) {
326                 FreeResource32(hGLOB);
327                 PlaySound_Result = FALSE;
328                 continue;
329             }
330             PlaySound_Result = proc_PlaySound(ptr, 
331                                               ((UINT16)PlaySound_fdwSound ^ SND_RESOURCE) | SND_MEMORY);
332             FreeResource32(hGLOB);
333             continue;
334         }
335         PlaySound_Result=proc_PlaySound(PlaySound_pszSound, (UINT16)PlaySound_fdwSound);
336     }
337 }
338
339 /**************************************************************************
340  *                              PlaySoundA              [WINMM.1]
341  */
342 BOOL32 WINAPI PlaySound32A(LPCSTR pszSound, HMODULE32 hmod, DWORD fdwSound)
343 {
344     static LPSTR StrDup = NULL;
345     
346     TRACE(mmsys, "pszSound='%p' hmod=%04X fdwSound=%08lX\n",
347           pszSound, hmod, fdwSound);
348     
349     if (PlaySound_hThread == 0) { /* This is the first time they called us */
350         DWORD   id;
351         if ((PlaySound_hReadyEvent = CreateEvent32A(NULL, TRUE, FALSE, NULL)) == 0)
352             return FALSE;
353         if ((PlaySound_hMiddleEvent = CreateEvent32A(NULL, FALSE, FALSE, NULL)) == 0)
354             return FALSE;
355         if ((PlaySound_hPlayEvent = CreateEvent32A(NULL, FALSE, FALSE, NULL)) == 0)
356             return FALSE;
357         if ((PlaySound_hThread = CreateThread(NULL, 0, PlaySound_Thread, 0, 0, &id)) == 0) 
358             return FALSE;
359     }
360     
361     /* FIXME? I see no difference between SND_WAIT and SND_NOSTOP ! */ 
362     if ((fdwSound & (SND_NOWAIT | SND_NOSTOP)) && PlaySound_Playing) 
363         return FALSE;
364     
365     /* Trying to stop if playing */
366     if (PlaySound_Playing) PlaySound_Stop = TRUE;
367     
368     /* Waiting playing thread to get ready. I think 10 secs is ok & if not then leave*/
369     if (WaitForSingleObject(PlaySound_hReadyEvent, 1000*10) != WAIT_OBJECT_0)
370         return FALSE;
371     
372     if (!pszSound || (fdwSound & SND_PURGE)) 
373         return FALSE; /* We stoped playing so leaving */
374     
375     if (PlaySound_SearchMode != 1) PlaySound_SearchMode = 2;
376     if (!(fdwSound & SND_ASYNC)) {
377         if (fdwSound & SND_LOOP) 
378             return FALSE;
379         PlaySound_pszSound = pszSound;
380         PlaySound_hmod = hmod;
381         PlaySound_fdwSound = fdwSound;
382         PlaySound_Result = FALSE;
383         SetEvent(PlaySound_hPlayEvent);
384         if (WaitForSingleObject(PlaySound_hMiddleEvent, INFINITE32) != WAIT_OBJECT_0) 
385             return FALSE;
386         if (WaitForSingleObject(PlaySound_hReadyEvent, INFINITE32) != WAIT_OBJECT_0) 
387             return FALSE;
388         return PlaySound_Result;
389     } else {
390         PlaySound_hmod = hmod;
391         PlaySound_fdwSound = fdwSound;
392         PlaySound_Result = FALSE;
393         if (StrDup) {
394             HeapFree(GetProcessHeap(), 0, StrDup);
395             StrDup = NULL;
396         }
397         if (!((fdwSound & SND_MEMORY) || ((fdwSound & SND_RESOURCE) && 
398                                           !((DWORD)pszSound >> 16)) || !pszSound)) {
399             StrDup = HEAP_strdupA(GetProcessHeap(),0,pszSound);
400             PlaySound_pszSound = StrDup;
401         } else PlaySound_pszSound = pszSound;
402         PlaySound_Loop = fdwSound & SND_LOOP;
403         SetEvent(PlaySound_hPlayEvent);
404         ResetEvent(PlaySound_hMiddleEvent);
405         return TRUE;
406     }
407     return FALSE;
408 }
409
410 /**************************************************************************
411  *                              PlaySoundW              [WINMM.18]
412  */
413 BOOL32 WINAPI PlaySound32W(LPCWSTR pszSound, HMODULE32 hmod, DWORD fdwSound)
414 {
415     LPSTR       pszSoundA;
416     BOOL32      bSound;
417     
418     if (!((fdwSound & SND_MEMORY) || ((fdwSound & SND_RESOURCE) && 
419                                       !((DWORD)pszSound >> 16)) || !pszSound)) {
420         pszSoundA = HEAP_strdupWtoA(GetProcessHeap(),0,pszSound);
421         bSound = PlaySound32A(pszSoundA, hmod, fdwSound);
422         HeapFree(GetProcessHeap(),0,pszSoundA);
423     } else  
424         bSound = PlaySound32A((LPCSTR)pszSound, hmod, fdwSound);
425     
426     return bSound;
427 }
428
429 /**************************************************************************
430  *                              sndPlaySound            [MMSYSTEM.2]
431  */
432 BOOL16 WINAPI sndPlaySound(LPCSTR lpszSoundName, UINT16 uFlags)
433 {
434     PlaySound_SearchMode = 1;
435     return PlaySound32A(lpszSoundName, 0, uFlags);
436 }
437
438 /**************************************************************************
439  *                              mmsystemGetVersion      [WINMM.134]
440  */
441 UINT32 WINAPI mmsystemGetVersion32()
442 {
443     return mmsystemGetVersion16();
444 }
445
446 /**************************************************************************
447  *                              mmsystemGetVersion      [MMSYSTEM.5]
448  * return value borrowed from Win95 winmm.dll ;)
449  */
450 UINT16 WINAPI mmsystemGetVersion16()
451 {
452     TRACE(mmsys, "3.10 (Win95?)\n");
453     return 0x030a;
454 }
455
456 /**************************************************************************
457  *                              DriverProc      [MMSYSTEM.6]
458  */
459 LRESULT WINAPI DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, 
460                           DWORD dwParam1, DWORD dwParam2)
461 {
462     return DrvDefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
463 }
464
465 /**************************************************************************
466  *                              DriverCallback  [MMSYSTEM.31]
467  */
468 BOOL16 WINAPI DriverCallback(DWORD dwCallBack, UINT16 uFlags, HANDLE16 hDev, 
469                              WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
470 {
471     TRACE(mmsys, "(%08lX, %04X, %04X, %04X, %08lX, %08lX, %08lX); !\n",
472           dwCallBack, uFlags, hDev, wMsg, dwUser, dwParam1, dwParam2);
473     switch (uFlags & DCB_TYPEMASK) {
474     case DCB_NULL:
475         TRACE(mmsys, "CALLBACK_NULL !\n");
476         break;
477     case DCB_WINDOW:
478         TRACE(mmsys, "CALLBACK_WINDOW = %04lX handle = %04X!\n",
479               dwCallBack,hDev);
480         if (!IsWindow32(dwCallBack) || USER_HEAP_LIN_ADDR(hDev) == NULL)
481             return FALSE;
482         
483         PostMessage16((HWND16)dwCallBack, wMsg, hDev, dwParam1);
484         break;
485     case DCB_TASK:
486         TRACE(mmsys, "CALLBACK_TASK !\n");
487         return FALSE;
488     case DCB_FUNCTION:
489         TRACE(mmsys, "CALLBACK_FUNCTION !\n");
490         Callbacks->CallDriverCallback( (FARPROC16)dwCallBack,
491                                        hDev, wMsg, dwUser,
492                                        dwParam1, dwParam2 );
493         break;
494     case DCB_FUNC32:
495         TRACE(mmsys, "CALLBACK_FUNCTION !\n");
496         ((LPDRVCALLBACK32)dwCallBack)( hDev, wMsg, dwUser,
497                                        dwParam1, dwParam2 );
498         break;
499     default:
500         WARN(mmsys, "Unknown callback type\n");
501         break;
502     }
503     return TRUE;
504 }
505
506 /**************************************************************************
507  *      Mixer devices. New to Win95
508  */
509 /**************************************************************************
510  * find out the real mixer ID depending on hmix (depends on dwFlags)
511  * FIXME: also fix dwInstance passing to mixMessage 
512  */
513 static UINT32 _get_mixerID_from_handle(HMIXEROBJ32 hmix,DWORD dwFlags) {
514     /* FIXME: Check dwFlags for MIXER_OBJECTF_xxxx entries and modify hmix 
515      * accordingly. For now we always use mixerdevice 0. 
516      */
517     return 0;
518 }
519 /**************************************************************************
520  *                              mixerGetNumDevs         [WINMM.108]
521  */
522 UINT32 WINAPI mixerGetNumDevs32() 
523 {
524     return mixerGetNumDevs16();
525 }
526
527 /**************************************************************************
528  *                              mixerGetNumDevs 
529  */
530 UINT16 WINAPI mixerGetNumDevs16() 
531 {
532     UINT16      count;
533     
534     count = mixMessage(0,MXDM_GETNUMDEVS,0L,0L,0L);
535     TRACE(mmaux,"mixerGetNumDevs returns %d\n",count);
536     return count;
537 }
538
539 /**************************************************************************
540  *                              mixerGetDevCapsW                [WINMM.102]
541  */
542 UINT32 WINAPI mixerGetDevCaps32W(UINT32 devid,LPMIXERCAPS32W mixcaps,UINT32 size) 
543 {
544     MIXERCAPS16 mic16;
545     UINT32      ret = mixerGetDevCaps16(devid,&mic16,sizeof(mic16));
546     
547     mixcaps->wMid = mic16.wMid;
548     mixcaps->wPid = mic16.wPid;
549     mixcaps->vDriverVersion = mic16.vDriverVersion;
550     lstrcpyAtoW(mixcaps->szPname,mic16.szPname);
551     mixcaps->fdwSupport = mic16.fdwSupport;
552     mixcaps->cDestinations = mic16.cDestinations;
553     return ret;
554 }
555 /**************************************************************************
556  *                              mixerGetDevCaps         [WINMM.101]
557  */
558 UINT32 WINAPI mixerGetDevCaps32A(UINT32 devid,LPMIXERCAPS32A mixcaps,UINT32 size) 
559 {
560     MIXERCAPS16 mic16;
561     UINT32      ret = mixerGetDevCaps16(devid,&mic16,sizeof(mic16));
562     
563     mixcaps->wMid = mic16.wMid;
564     mixcaps->wPid = mic16.wPid;
565     mixcaps->vDriverVersion = mic16.vDriverVersion;
566     strcpy(mixcaps->szPname,mic16.szPname);
567     mixcaps->fdwSupport = mic16.fdwSupport;
568     mixcaps->cDestinations = mic16.cDestinations;
569     return ret;
570 }
571
572 /**************************************************************************
573  *                              mixerGetDevCaps 
574  */
575 UINT16 WINAPI mixerGetDevCaps16(UINT16 devid,LPMIXERCAPS16 mixcaps,UINT16 size) 
576 {
577     FIXME(mmsys,"should this be a fixme?\n");
578     return mixMessage(devid,MXDM_GETDEVCAPS,0L,(DWORD)mixcaps,(DWORD)size);
579 }
580
581 /**************************************************************************
582  *                              mixerOpen               [WINMM.110]
583  */
584 UINT32 WINAPI mixerOpen32(LPHMIXER32 lphmix,UINT32 uDeviceID,DWORD dwCallback,
585                           DWORD dwInstance,DWORD fdwOpen) 
586 {
587     HMIXER16    hmix16;
588     UINT32      ret;
589     
590     FIXME(mmsys,"(%p,%d,%08lx,%08lx,%08lx): semi stub?\n",
591           lphmix,uDeviceID,dwCallback,dwInstance,fdwOpen);
592     ret = mixerOpen16(&hmix16,uDeviceID,dwCallback,dwInstance,fdwOpen);
593     if (lphmix) *lphmix = hmix16;
594     return ret;
595 }
596
597 /**************************************************************************
598  *                              mixerOpen
599  */
600 UINT16 WINAPI mixerOpen16(LPHMIXER16 lphmix,UINT16 uDeviceID,DWORD dwCallback,
601                           DWORD dwInstance,DWORD fdwOpen) 
602 {
603     HMIXER16            hmix;
604     LPMIXEROPENDESC     lpmod;
605     BOOL32              mapperflag = (uDeviceID==0);
606     DWORD               dwRet;
607     
608     TRACE(mmsys,"(%p,%d,%08lx,%08lx,%08lx)\n",
609           lphmix,uDeviceID,dwCallback,dwInstance,fdwOpen);
610     hmix = USER_HEAP_ALLOC(sizeof(MIXEROPENDESC));
611     if (lphmix) *lphmix = hmix;
612     lpmod = (LPMIXEROPENDESC)USER_HEAP_LIN_ADDR(hmix);
613     lpmod->hmx = hmix;
614     lpmod->dwCallback = dwCallback;
615     lpmod->dwInstance = dwInstance;
616     if (uDeviceID >= MAXMIXERDRIVERS)
617         uDeviceID = 0;
618     while (uDeviceID < MAXMIXERDRIVERS) {
619         dwRet=mixMessage(uDeviceID,MXDM_OPEN,dwInstance,(DWORD)lpmod,fdwOpen);
620         if (dwRet == MMSYSERR_NOERROR) break;
621         if (!mapperflag) break;
622         uDeviceID++;
623     }
624     lpmod->uDeviceID = uDeviceID;
625     return dwRet;
626 }
627
628 /**************************************************************************
629  *                              mixerClose              [WINMM.98]
630  */
631 UINT32 WINAPI mixerClose32(HMIXER32 hmix) 
632 {
633     return mixerClose16(hmix);
634 }
635
636 /**************************************************************************
637  *                              mixerClose
638  */
639 UINT16 WINAPI mixerClose16(HMIXER16 hmix) 
640 {
641     LPMIXEROPENDESC     lpmod;
642     
643     FIXME(mmsys,"(%04x): semi-stub?\n",hmix);
644     lpmod = (LPMIXEROPENDESC)USER_HEAP_LIN_ADDR(hmix);
645     return mixMessage(lpmod->uDeviceID,MXDM_CLOSE,lpmod->dwInstance,0L,0L);
646 }
647
648 /**************************************************************************
649  *                              mixerGetID              [WINMM.103]
650  */
651 UINT32 WINAPI mixerGetID32(HMIXEROBJ32 hmix,LPUINT32 lpid,DWORD fdwID) 
652 {
653     UINT16      xid;    
654     UINT32      ret = mixerGetID16(hmix,&xid,fdwID);
655
656     if (*lpid) *lpid = xid;
657     return ret;
658 }
659
660 /**************************************************************************
661  *                              mixerGetID
662  */
663 UINT16 WINAPI mixerGetID16(HMIXEROBJ16 hmix,LPUINT16 lpid,DWORD fdwID) 
664 {
665     FIXME(mmsys,"(%04x): semi-stub\n",hmix);
666     return _get_mixerID_from_handle(hmix,fdwID);
667 }
668
669 /**************************************************************************
670  *                              mixerGetControlDetailsA [WINMM.99]
671  */
672 UINT32 WINAPI mixerGetControlDetails32A(HMIXEROBJ32 hmix,LPMIXERCONTROLDETAILS32 lpmcd,DWORD fdwDetails) 
673 {
674     FIXME(mmsys,"(%04x,%p,%08lx): stub!\n",hmix,lpmcd,fdwDetails);
675     return MMSYSERR_NOTENABLED;
676 }
677
678 /**************************************************************************
679  *                              mixerGetControlDetailsW [WINMM.100]
680  */
681 UINT32 WINAPI mixerGetControlDetails32W(HMIXEROBJ32 hmix,LPMIXERCONTROLDETAILS32 lpmcd,DWORD fdwDetails) 
682 {
683     FIXME(mmsys,"(%04x,%p,%08lx): stub!\n",     hmix,lpmcd,fdwDetails);
684     return MMSYSERR_NOTENABLED;
685 }
686
687 /**************************************************************************
688  *                              mixerGetControlDetails  [MMSYSTEM.808]
689  */
690 UINT16 WINAPI mixerGetControlDetails16(HMIXEROBJ16 hmix,LPMIXERCONTROLDETAILS16 lpmcd,DWORD fdwDetails) 
691 {
692     FIXME(mmsys,"(%04x,%p,%08lx): stub!\n",hmix,lpmcd,fdwDetails);
693     return MMSYSERR_NOTENABLED;
694 }
695
696 /**************************************************************************
697  *                              mixerGetLineControlsA   [WINMM.104]
698  */
699 UINT32 WINAPI mixerGetLineControls32A(HMIXEROBJ32 hmix,LPMIXERLINECONTROLS32A lpmlc,DWORD fdwControls) 
700 {
701     FIXME(mmsys,"(%04x,%p,%08lx): stub!\n",hmix,lpmlc,fdwControls);
702     return MMSYSERR_NOTENABLED;
703 }
704
705 /**************************************************************************
706  *                              mixerGetLineControlsW   [WINMM.105]
707  */
708 UINT32 WINAPI mixerGetLineControls32W(HMIXEROBJ32 hmix,LPMIXERLINECONTROLS32W lpmlc,DWORD fdwControls) 
709 {
710     FIXME(mmsys,"(%04x,%p,%08lx): stub!\n",hmix,lpmlc,fdwControls);
711     return MMSYSERR_NOTENABLED;
712 }
713
714 /**************************************************************************
715  *                              mixerGetLineControls    [MMSYSTEM.807]
716  */
717 UINT16 WINAPI mixerGetLineControls16(HMIXEROBJ16 hmix,LPMIXERLINECONTROLS16 lpmlc,DWORD fdwControls) 
718 {
719     FIXME(mmsys,"(%04x,%p,%08lx): stub!\n",hmix,lpmlc,fdwControls);
720     return MMSYSERR_NOTENABLED;
721 }
722
723 /**************************************************************************
724  *                              mixerGetLineInfoA       [WINMM.106]
725  */
726 UINT32 WINAPI mixerGetLineInfo32A(HMIXEROBJ32 hmix,LPMIXERLINE32A lpml,DWORD fdwInfo) 
727 {
728     MIXERLINE16         ml16;
729     UINT32              ret;
730     
731     ml16.dwDestination = lpml->dwDestination;
732     FIXME(mmsys,"(%04x,%p,%08lx): stub!\n",hmix,lpml,fdwInfo);
733     ret = mixerGetLineInfo16(hmix,&ml16,fdwInfo);
734     lpml->cbStruct = sizeof(*lpml);
735     lpml->dwSource = ml16.dwSource;
736     lpml->dwLineID = ml16.dwLineID;
737     lpml->fdwLine = ml16.fdwLine;
738     lpml->dwUser = ml16.dwUser;
739     lpml->dwComponentType = ml16.dwComponentType;
740     lpml->cChannels = ml16.cChannels;
741     lpml->cConnections = ml16.cConnections;
742     lpml->cControls = ml16.cControls;
743     strcpy(lpml->szShortName,ml16.szShortName);
744     strcpy(lpml->szName,ml16.szName);
745     lpml->Target.dwType = ml16.Target.dwType;
746     lpml->Target.dwDeviceID = ml16.Target.dwDeviceID;
747     lpml->Target.wMid = ml16.Target.wMid;
748     lpml->Target.wPid = ml16.Target.wPid;
749     lpml->Target.vDriverVersion = ml16.Target.vDriverVersion;
750     strcpy(lpml->Target.szPname,ml16.Target.szPname);
751     return ret;
752 }
753
754 /**************************************************************************
755  *                              mixerGetLineInfoW       [WINMM.107]
756  */
757 UINT32 WINAPI mixerGetLineInfo32W(HMIXEROBJ32 hmix,LPMIXERLINE32W lpml,DWORD fdwInfo) 
758 {
759     MIXERLINE16         ml16;
760     UINT32              ret;
761     
762     ml16.dwDestination = lpml->dwDestination;
763     FIXME(mmsys,"(%04x,%p,%08lx): stub!\n",hmix,lpml,fdwInfo);
764     ret = mixerGetLineInfo16(hmix,&ml16,fdwInfo);
765     lpml->cbStruct = sizeof(*lpml);
766     lpml->dwSource = ml16.dwSource;
767     lpml->dwLineID = ml16.dwLineID;
768     lpml->fdwLine = ml16.fdwLine;
769     lpml->dwUser = ml16.dwUser;
770     lpml->dwComponentType = ml16.dwComponentType;
771     lpml->cChannels = ml16.cChannels;
772     lpml->cConnections = ml16.cConnections;
773     lpml->cControls = ml16.cControls;
774     lstrcpyAtoW(lpml->szShortName,ml16.szShortName);
775     lstrcpyAtoW(lpml->szName,ml16.szName);
776     lpml->Target.dwType = ml16.Target.dwType;
777     lpml->Target.dwDeviceID = ml16.Target.dwDeviceID;
778     lpml->Target.wMid = ml16.Target.wMid;
779     lpml->Target.wPid = ml16.Target.wPid;
780     lpml->Target.vDriverVersion = ml16.Target.vDriverVersion;
781     /*lstrcpyAtoW(lpml->Target.szPname,ml16.Target.szPname);*/
782     return ret;
783 }
784
785 /**************************************************************************
786  *                              mixerGetLineInfo        [MMSYSTEM.805]
787  */
788 UINT16 WINAPI mixerGetLineInfo16(HMIXEROBJ16 hmix,LPMIXERLINE16 lpml,DWORD fdwInfo) 
789 {
790     UINT16 devid =  _get_mixerID_from_handle(hmix,fdwInfo);
791     
792     FIXME(mmsys,"(%04x,%p[line %08lx],%08lx) - semi-stub?\n",
793           hmix,lpml,lpml->dwDestination,fdwInfo);
794     return mixMessage(devid,MXDM_GETLINEINFO,0,(DWORD)lpml,fdwInfo);
795 }
796
797 /**************************************************************************
798  *                              mixerSetControlDetails  [WINMM.111]
799  */
800 UINT32 WINAPI mixerSetControlDetails32(HMIXEROBJ32 hmix,LPMIXERCONTROLDETAILS32 lpmcd,DWORD fdwDetails) 
801 {
802     FIXME(mmsys,"(%04x,%p,%08lx): stub!\n",hmix,lpmcd,fdwDetails);
803     return MMSYSERR_NOTENABLED;
804 }
805
806 /**************************************************************************
807  *                              mixerSetControlDetails  [MMSYSTEM.809]
808  */
809 UINT16 WINAPI mixerSetControlDetails16(HMIXEROBJ16 hmix,LPMIXERCONTROLDETAILS16 lpmcd,DWORD fdwDetails) 
810 {
811     FIXME(mmsys,"(%04x,%p,%08lx): stub!\n",hmix,lpmcd,fdwDetails);
812     return MMSYSERR_NOTENABLED;
813 }
814
815 /**************************************************************************
816  *                              mixerMessage            [WINMM.109]
817  */
818 UINT32 WINAPI mixerMessage32(HMIXER32 hmix,UINT32 uMsg,DWORD dwParam1,DWORD dwParam2) 
819 {
820     LPMIXEROPENDESC     lpmod;
821     UINT16              uDeviceID;
822     
823     lpmod = (LPMIXEROPENDESC)USER_HEAP_LIN_ADDR(hmix);
824     if (lpmod)
825         uDeviceID = lpmod->uDeviceID;
826     else
827         uDeviceID = 0;
828     FIXME(mmsys,"(%04lx,%d,%08lx,%08lx): semi-stub?\n",
829           (DWORD)hmix,uMsg,dwParam1,dwParam2);
830     return mixMessage(uDeviceID,uMsg,0L,dwParam1,dwParam2);
831 }
832
833 /**************************************************************************
834  *                              mixerMessage            [MMSYSTEM.804]
835  */
836 UINT16 WINAPI mixerMessage16(HMIXER16 hmix,UINT16 uMsg,DWORD dwParam1,DWORD dwParam2) 
837 {
838     LPMIXEROPENDESC     lpmod;
839     UINT16              uDeviceID;
840     
841     lpmod = (LPMIXEROPENDESC)USER_HEAP_LIN_ADDR(hmix);
842     if (lpmod)
843         uDeviceID = lpmod->uDeviceID;
844     else
845         uDeviceID = 0;
846     FIXME(mmsys,"(%04x,%d,%08lx,%08lx) - semi-stub?\n",
847           hmix,uMsg,dwParam1,dwParam2);
848     return mixMessage(uDeviceID,uMsg,0L,dwParam1,dwParam2);
849 }
850
851 /**************************************************************************
852  *                              auxGetNumDevs           [WINMM.22]
853  */
854 UINT32 WINAPI auxGetNumDevs32()
855 {
856     return auxGetNumDevs16();
857 }
858
859 /**************************************************************************
860  *                              auxGetNumDevs           [MMSYSTEM.350]
861  */
862 UINT16 WINAPI auxGetNumDevs16()
863 {
864     UINT16      count = 0;
865     TRACE(mmsys, "auxGetNumDevs !\n");
866     count += auxMessage(0, AUXDM_GETNUMDEVS, 0L, 0L, 0L);
867     TRACE(mmsys, "auxGetNumDevs return %u \n", count);
868     return count;
869 }
870
871 /**************************************************************************
872  *                              auxGetDevCaps           [WINMM.20]
873  */
874 UINT32 WINAPI auxGetDevCaps32W(UINT32 uDeviceID,LPAUXCAPS32W lpCaps,UINT32 uSize)
875 {
876     AUXCAPS16   ac16;
877     UINT32      ret = auxGetDevCaps16(uDeviceID,&ac16,sizeof(ac16));
878     
879     lpCaps->wMid = ac16.wMid;
880     lpCaps->wPid = ac16.wPid;
881     lpCaps->vDriverVersion = ac16.vDriverVersion;
882     lstrcpyAtoW(lpCaps->szPname,ac16.szPname);
883     lpCaps->wTechnology = ac16.wTechnology;
884     lpCaps->dwSupport = ac16.dwSupport;
885     return ret;
886 }
887
888 /**************************************************************************
889  *                              auxGetDevCaps           [WINMM.21]
890  */
891 UINT32 WINAPI auxGetDevCaps32A(UINT32 uDeviceID,LPAUXCAPS32A lpCaps,UINT32 uSize)
892 {
893     AUXCAPS16   ac16;
894     UINT32      ret = auxGetDevCaps16(uDeviceID,&ac16,sizeof(ac16));
895     
896     lpCaps->wMid = ac16.wMid;
897     lpCaps->wPid = ac16.wPid;
898     lpCaps->vDriverVersion = ac16.vDriverVersion;
899     strcpy(lpCaps->szPname,ac16.szPname);
900     lpCaps->wTechnology = ac16.wTechnology;
901     lpCaps->dwSupport = ac16.dwSupport;
902     return ret;
903 }
904
905 /**************************************************************************
906  *                              auxGetDevCaps           [MMSYSTEM.351]
907  */
908 UINT16 WINAPI auxGetDevCaps16(UINT16 uDeviceID,LPAUXCAPS16 lpCaps, UINT16 uSize)
909 {
910     TRACE(mmsys, "(%04X, %p, %d) !\n", 
911           uDeviceID, lpCaps, uSize);
912     return auxMessage(uDeviceID, AUXDM_GETDEVCAPS,
913                       0L, (DWORD)lpCaps, (DWORD)uSize);
914 }
915
916 /**************************************************************************
917  *                              auxGetVolume            [WINM.23]
918  */
919 UINT32 WINAPI auxGetVolume32(UINT32 uDeviceID, DWORD * lpdwVolume)
920 {
921     return auxGetVolume16(uDeviceID,lpdwVolume);
922 }
923
924 /**************************************************************************
925  *                              auxGetVolume            [MMSYSTEM.352]
926  */
927 UINT16 WINAPI auxGetVolume16(UINT16 uDeviceID, DWORD * lpdwVolume)
928 {
929     TRACE(mmsys, "(%04X, %p) !\n", uDeviceID, lpdwVolume);
930     return auxMessage(uDeviceID, AUXDM_GETVOLUME, 0L, (DWORD)lpdwVolume, 0L);
931 }
932
933 /**************************************************************************
934  *                              auxSetVolume            [WINMM.25]
935  */
936 UINT32 WINAPI auxSetVolume32(UINT32 uDeviceID, DWORD dwVolume)
937 {
938     return auxSetVolume16(uDeviceID,dwVolume);
939 }
940
941 /**************************************************************************
942  *                              auxSetVolume            [MMSYSTEM.353]
943  */
944 UINT16 WINAPI auxSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
945 {
946     TRACE(mmsys, "(%04X, %08lX) !\n", uDeviceID, dwVolume);
947     return auxMessage(uDeviceID, AUXDM_SETVOLUME, 0L, dwVolume, 0L);
948 }
949
950 /**************************************************************************
951  *                              auxOutMessage           [MMSYSTEM.354]
952  */
953 DWORD WINAPI auxOutMessage32(UINT32 uDeviceID,UINT32 uMessage,DWORD dw1,DWORD dw2)
954 {
955     switch (uMessage) {
956     case AUXDM_GETNUMDEVS:
957     case AUXDM_GETVOLUME:
958     case AUXDM_SETVOLUME:
959         /* no argument conversion needed */
960         break;
961     case AUXDM_GETDEVCAPS:
962         return auxGetDevCaps32A(uDeviceID,(LPAUXCAPS32A)dw1,dw2);
963     default:
964         ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
965             uDeviceID,uMessage,dw1,dw2);
966         break;
967     }
968     return auxMessage(uDeviceID,uMessage,0L,dw1,dw2);
969 }
970
971 /**************************************************************************
972  *                              auxOutMessage           [MMSYSTEM.354]
973  */
974 DWORD WINAPI auxOutMessage16(UINT16 uDeviceID, UINT16 uMessage, DWORD dw1, DWORD dw2)
975 {
976     TRACE(mmsys, "(%04X, %04X, %08lX, %08lX)\n", 
977           uDeviceID, uMessage, dw1, dw2);
978     switch (uMessage) {
979     case AUXDM_GETNUMDEVS:
980     case AUXDM_SETVOLUME:
981         /* no argument conversion needed */
982         break;
983     case AUXDM_GETVOLUME:
984         return auxGetVolume16(uDeviceID,(LPDWORD)PTR_SEG_TO_LIN(dw1));
985     case AUXDM_GETDEVCAPS:
986         return auxGetDevCaps16(uDeviceID,(LPAUXCAPS16)PTR_SEG_TO_LIN(dw1),dw2);
987     default:
988         ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
989             uDeviceID,uMessage,dw1,dw2);
990         break;
991     }
992     return auxMessage(uDeviceID, uMessage, 0L, dw1, dw2);
993 }
994
995 /**************************************************************************
996  *                              mciGetErrorStringW              [WINMM.46]
997  */
998 BOOL32 WINAPI mciGetErrorString32W(DWORD wError,LPWSTR lpstrBuffer,UINT32 uLength)
999 {
1000     LPSTR       bufstr = HeapAlloc(GetProcessHeap(),0,uLength);
1001     BOOL32      ret = mciGetErrorString32A(wError,bufstr,uLength);
1002     
1003     lstrcpyAtoW(lpstrBuffer,bufstr);
1004     HeapFree(GetProcessHeap(),0,bufstr);
1005     return ret;
1006 }
1007
1008 /**************************************************************************
1009  *                              mciGetErrorStringA              [WINMM.45]
1010  */
1011 BOOL32 WINAPI mciGetErrorString32A(DWORD wError,LPSTR lpstrBuffer,UINT32 uLength)
1012 {
1013     return mciGetErrorString16(wError,lpstrBuffer,uLength);
1014 }
1015
1016 /**************************************************************************
1017  *                              mciGetErrorString               [MMSYSTEM.706]
1018  */
1019 BOOL16 WINAPI mciGetErrorString16(DWORD wError,LPSTR lpstrBuffer,UINT16 uLength)
1020 {
1021     LPSTR       msgptr;
1022     TRACE(mmsys, "(%08lX, %p, %d);\n", 
1023           wError, lpstrBuffer, uLength);
1024     if ((lpstrBuffer == NULL) || (uLength < 1)) return(FALSE);
1025     lpstrBuffer[0] = '\0';
1026     switch (wError) {
1027     case MCIERR_INVALID_DEVICE_ID:
1028         msgptr = "Invalid MCI device ID. Use the ID returned when opening the MCI device.";
1029         break;
1030     case MCIERR_UNRECOGNIZED_KEYWORD:
1031         msgptr = "The driver cannot recognize the specified command parameter.";
1032         break;
1033     case MCIERR_UNRECOGNIZED_COMMAND:
1034         msgptr = "The driver cannot recognize the specified command.";
1035         break;
1036     case MCIERR_HARDWARE:
1037         msgptr = "There is a problem with your media device. Make sure it is working correctly or contact the device manufacturer.";
1038         break;
1039     case MCIERR_INVALID_DEVICE_NAME:
1040         msgptr = "The specified device is not open or is not recognized by MCI.";
1041         break;
1042     case MCIERR_OUT_OF_MEMORY:
1043         msgptr = "Not enough memory available for this task. \nQuit one or more applications to increase available memory, and then try again.";
1044         break;
1045     case MCIERR_DEVICE_OPEN:
1046         msgptr = "The device name is already being used as an alias by this application. Use a unique alias.";
1047         break;
1048     case MCIERR_CANNOT_LOAD_DRIVER:
1049         msgptr = "There is an undetectable problem in loading the specified device driver.";
1050         break;
1051     case MCIERR_MISSING_COMMAND_STRING:
1052         msgptr = "No command was specified.";
1053         break;
1054     case MCIERR_PARAM_OVERFLOW:
1055         msgptr = "The output string was to large to fit in the return buffer. Increase the size of the buffer.";
1056         break;
1057     case MCIERR_MISSING_STRING_ARGUMENT:
1058         msgptr = "The specified command requires a character-string parameter. Please provide one.";
1059         break;
1060     case MCIERR_BAD_INTEGER:
1061         msgptr = "The specified integer is invalid for this command.";
1062         break;
1063     case MCIERR_PARSER_INTERNAL:
1064         msgptr = "The device driver returned an invalid return type. Check with the device manufacturer about obtaining a new driver.";
1065         break;
1066     case MCIERR_DRIVER_INTERNAL:
1067         msgptr = "There is a problem with the device driver. Check with the device manufacturer about obtaining a new driver.";
1068         break;
1069     case MCIERR_MISSING_PARAMETER:
1070         msgptr = "The specified command requires a parameter. Please supply one.";
1071         break;
1072     case MCIERR_UNSUPPORTED_FUNCTION:
1073         msgptr = "The MCI device you are using does not support the specified command.";
1074         break;
1075     case MCIERR_FILE_NOT_FOUND:
1076         msgptr = "Cannot find the specified file. Make sure the path and filename are correct.";
1077         break;
1078     case MCIERR_DEVICE_NOT_READY:
1079         msgptr = "The device driver is not ready.";
1080         break;
1081     case MCIERR_INTERNAL:
1082         msgptr = "A problem occurred in initializing MCI. Try restarting Windows.";
1083         break;
1084     case MCIERR_DRIVER:
1085         msgptr = "There is a problem with the device driver. The driver has closed. Cannot access error.";
1086         break;
1087     case MCIERR_CANNOT_USE_ALL:
1088         msgptr = "Cannot use 'all' as the device name with the specified command.";
1089         break;
1090     case MCIERR_MULTIPLE:
1091         msgptr = "Errors occurred in more than one device. Specify each command and device separately to determine which devices caused the error";
1092         break;
1093     case MCIERR_EXTENSION_NOT_FOUND:
1094         msgptr = "Cannot determine the device type from the given filename extension.";
1095         break;
1096     case MCIERR_OUTOFRANGE:
1097         msgptr = "The specified parameter is out of range for the specified command.";
1098         break;
1099     case MCIERR_FLAGS_NOT_COMPATIBLE:
1100         msgptr = "The specified parameters cannot be used together.";
1101         break;
1102     case MCIERR_FILE_NOT_SAVED:
1103         msgptr = "Cannot save the specified file. Make sure you have enough disk space or are still connected to the network.";
1104         break;
1105     case MCIERR_DEVICE_TYPE_REQUIRED:
1106         msgptr = "Cannot find the specified device. Make sure it is installed or that the device name is spelled correctly.";
1107         break;
1108     case MCIERR_DEVICE_LOCKED:
1109         msgptr = "The specified device is now being closed. Wait a few seconds, and then try again.";
1110         break;
1111     case MCIERR_DUPLICATE_ALIAS:
1112         msgptr = "The specified alias is already being used in this application. Use a unique alias.";
1113         break;
1114     case MCIERR_BAD_CONSTANT:
1115         msgptr = "The specified parameter is invalid for this command.";
1116         break;
1117     case MCIERR_MUST_USE_SHAREABLE:
1118         msgptr = "The device driver is already in use. To share it, use the 'shareable' parameter with each 'open' command.";
1119         break;
1120     case MCIERR_MISSING_DEVICE_NAME:
1121         msgptr = "The specified command requires an alias, file, driver, or device name. Please supply one.";
1122         break;
1123     case MCIERR_BAD_TIME_FORMAT:
1124         msgptr = "The specified value for the time format is invalid. Refer to the MCI documentation for valid formats.";
1125         break;
1126     case MCIERR_NO_CLOSING_QUOTE:
1127         msgptr = "A closing double-quotation mark is missing from the parameter value. Please supply one.";
1128         break;
1129     case MCIERR_DUPLICATE_FLAGS:
1130         msgptr = "A parameter or value was specified twice. Only specify it once.";
1131         break;
1132     case MCIERR_INVALID_FILE:
1133         msgptr = "The specified file cannot be played on the specified MCI device. The file may be corrupt, or not in the correct format.";
1134         break;
1135     case MCIERR_NULL_PARAMETER_BLOCK:
1136         msgptr = "A null parameter block was passed to MCI.";
1137         break;
1138     case MCIERR_UNNAMED_RESOURCE:
1139         msgptr = "Cannot save an unnamed file. Supply a filename.";
1140         break;
1141     case MCIERR_NEW_REQUIRES_ALIAS:
1142         msgptr = "You must specify an alias when using the 'new' parameter.";
1143         break;
1144     case MCIERR_NOTIFY_ON_AUTO_OPEN:
1145         msgptr = "Cannot use the 'notify' flag with auto-opened devices.";
1146         break;
1147     case MCIERR_NO_ELEMENT_ALLOWED:
1148         msgptr = "Cannot use a filename with the specified device.";
1149         break;
1150     case MCIERR_NONAPPLICABLE_FUNCTION:
1151         msgptr = "Cannot carry out the commands in the order specified. Correct the command sequence, and then try again.";
1152         break;
1153     case MCIERR_ILLEGAL_FOR_AUTO_OPEN:
1154         msgptr = "Cannot carry out the specified command on an auto-opened device. Wait until the device is closed, and then try again.";
1155         break;
1156     case MCIERR_FILENAME_REQUIRED:
1157         msgptr = "The filename is invalid. Make sure the filename is not longer than 8 characters, followed by a period and an extension.";
1158         break;
1159     case MCIERR_EXTRA_CHARACTERS:
1160         msgptr = "Cannot specify extra characters after a string enclosed in quotation marks.";
1161         break;
1162     case MCIERR_DEVICE_NOT_INSTALLED:
1163         msgptr = "The specified device is not installed on the system. Use the Drivers option in Control Panel to install the device.";
1164         break;
1165     case MCIERR_GET_CD:
1166         msgptr = "Cannot access the specified file or MCI device. Try changing directories or restarting your computer.";
1167         break;
1168     case MCIERR_SET_CD:
1169         msgptr = "Cannot access the specified file or MCI device because the application cannot change directories.";
1170         break;
1171     case MCIERR_SET_DRIVE:
1172         msgptr = "Cannot access specified file or MCI device because the application cannot change drives.";
1173         break;
1174     case MCIERR_DEVICE_LENGTH:
1175         msgptr = "Specify a device or driver name that is less than 79 characters.";
1176         break;
1177     case MCIERR_DEVICE_ORD_LENGTH:
1178         msgptr = "Specify a device or driver name that is less than 69 characters.";
1179         break;
1180     case MCIERR_NO_INTEGER:
1181         msgptr = "The specified command requires an integer parameter. Please provide one.";
1182         break;
1183     case MCIERR_WAVE_OUTPUTSINUSE:
1184         msgptr = "All wave devices that can play files in the current format are in use. Wait until a wave device is free, and then try again.";
1185         break;
1186     case MCIERR_WAVE_SETOUTPUTINUSE:
1187         msgptr = "Cannot set the current wave device for play back because it is in use. Wait until the device is free, and then try again.";
1188         break;
1189     case MCIERR_WAVE_INPUTSINUSE:
1190         msgptr = "All wave devices that can record files in the current format are in use. Wait until a wave device is free, and then try again.";
1191         break;
1192     case MCIERR_WAVE_SETINPUTINUSE:
1193         msgptr = "Cannot set the current wave device for recording because it is in use. Wait until the device is free, and then try again.";
1194         break;
1195     case MCIERR_WAVE_OUTPUTUNSPECIFIED:
1196         msgptr = "Any compatible waveform playback device may be used.";
1197         break;
1198     case MCIERR_WAVE_INPUTUNSPECIFIED:
1199         msgptr = "Any compatible waveform recording device may be used.";
1200         break;
1201     case MCIERR_WAVE_OUTPUTSUNSUITABLE:
1202         msgptr = "No wave device that can play files in the current format is installed. Use the Drivers option to install the wave device.";
1203         break;
1204     case MCIERR_WAVE_SETOUTPUTUNSUITABLE:
1205         msgptr = "The device you are trying to play to cannot recognize the current file format.";
1206         break;
1207     case MCIERR_WAVE_INPUTSUNSUITABLE:
1208         msgptr = "No wave device that can record files in the current format is installed. Use the Drivers option to install the wave device.";
1209         break;
1210     case MCIERR_WAVE_SETINPUTUNSUITABLE:
1211         msgptr = "The device you are trying to record from cannot recognize the current file format.";
1212         break;
1213     case MCIERR_NO_WINDOW:
1214         msgptr = "There is no display window.";
1215         break;
1216     case MCIERR_CREATEWINDOW:
1217         msgptr = "Could not create or use window.";
1218         break;
1219     case MCIERR_FILE_READ:
1220         msgptr = "Cannot read the specified file. Make sure the file is still present, or check your disk or network connection.";
1221         break;
1222     case MCIERR_FILE_WRITE:
1223         msgptr = "Cannot write to the specified file. Make sure you have enough disk space or are still connected to the network.";
1224         break;
1225     case MCIERR_SEQ_DIV_INCOMPATIBLE:
1226         msgptr = "The time formats of the \"song pointer\" and SMPTE are mutually exclusive. You can't use them together.";
1227         break;
1228     case MCIERR_SEQ_NOMIDIPRESENT:
1229         msgptr = "The system has no installed MIDI devices. Use the Drivers option from the Control Panel to install a MIDI driver.";
1230         break;
1231     case MCIERR_SEQ_PORT_INUSE:
1232         msgptr = "The specified MIDI port is already in use. Wait until it is free; the try again.";
1233         break;
1234     case MCIERR_SEQ_PORT_MAPNODEVICE:
1235         msgptr = "The current MIDI Mapper setup refers to a MIDI device that is not installed on the system. Use the MIDI Mapper option from the Control Panel to edit the setup.";
1236         break;
1237     case MCIERR_SEQ_PORT_MISCERROR:
1238         msgptr = "An error occurred with the specified port.";
1239         break;
1240     case MCIERR_SEQ_PORT_NONEXISTENT:
1241         msgptr = "The specified MIDI device is not installed on the system. Use the Drivers option from the Control Panel to install a MIDI device.";
1242         break;
1243     case MCIERR_SEQ_PORTUNSPECIFIED:
1244         msgptr = "The system doesnot have a current MIDI port specified.";
1245         break;
1246     case MCIERR_SEQ_TIMER:
1247         msgptr = "All multimedia timers are being used by other applications. Quit one of these applications; then, try again.";
1248         break;
1249         
1250         /* 
1251            msg# 513 : vcr
1252            msg# 514 : videodisc
1253            msg# 515 : overlay
1254            msg# 516 : cdaudio
1255            msg# 517 : dat
1256            msg# 518 : scanner
1257            msg# 519 : animation
1258            msg# 520 : digitalvideo
1259            msg# 521 : other
1260            msg# 522 : waveaudio
1261            msg# 523 : sequencer
1262            msg# 524 : not ready
1263            msg# 525 : stopped
1264            msg# 526 : playing
1265            msg# 527 : recording
1266            msg# 528 : seeking
1267            msg# 529 : paused
1268            msg# 530 : open
1269            msg# 531 : false
1270            msg# 532 : true
1271            msg# 533 : milliseconds
1272            msg# 534 : hms
1273            msg# 535 : msf
1274            msg# 536 : frames
1275            msg# 537 : smpte 24
1276            msg# 538 : smpte 25
1277            msg# 539 : smpte 30
1278            msg# 540 : smpte 30 drop
1279            msg# 541 : bytes
1280            msg# 542 : samples
1281            msg# 543 : tmsf
1282         */
1283     default:
1284         msgptr = "Unknown MCI Error !\n";
1285         break;
1286     }
1287     lstrcpyn32A(lpstrBuffer, msgptr, uLength);
1288     TRACE(mmsys, "msg = %s;\n", msgptr);
1289     return TRUE;
1290 }
1291
1292
1293 /**************************************************************************
1294  *                              mciDriverNotify                 [MMSYSTEM.711]
1295  */
1296 BOOL16 WINAPI mciDriverNotify(HWND16 hWndCallBack, UINT16 wDevID, UINT16 wStatus)
1297 {
1298     TRACE(mmsys, "(%04X, %u, %04X)\n", hWndCallBack, wDevID, wStatus);
1299     if (!IsWindow32(hWndCallBack)) return FALSE;
1300     TRACE(mmsys, "before PostMessage\n");
1301     PostMessage16( hWndCallBack, MM_MCINOTIFY, wStatus, 
1302                    MAKELONG(wDevID, 0));
1303     return TRUE;
1304 }
1305
1306 /**************************************************************************
1307  *                      mciOpen16                               [internal]
1308  */
1309 static DWORD mciOpen16(DWORD dwParam, LPMCI_OPEN_PARMS16 lp16Parms)
1310 {
1311     char                str[128];
1312     LPMCI_OPEN_PARMS16  lpParms;
1313     UINT16              uDevTyp = 0;
1314     UINT16              wDevID = MMSYSTEM_FirstDevID();
1315     DWORD               dwret;
1316     
1317     lpParms = PTR_SEG_TO_LIN(lp16Parms);
1318     TRACE(mmsys, "(%08lX, %p (%p))\n", dwParam, lp16Parms, lpParms);
1319     if (lp16Parms == NULL) return MCIERR_INTERNAL;
1320     
1321     while (mciGetDrv(wDevID)->modp.wType != 0) {
1322         wDevID = MMSYSTEM_NextDevID(wDevID);
1323         if (!MMSYSTEM_DevIDValid(wDevID)) {
1324             TRACE(mmsys, "MAXMCIDRIVERS reached !\n");
1325             return MCIERR_INTERNAL;
1326         }
1327     }
1328     TRACE(mmsys, "wDevID=%04X \n", wDevID);
1329     memcpy(mciGetOpenDrv(wDevID), lpParms, sizeof(*lpParms));
1330     
1331     if (dwParam & MCI_OPEN_ELEMENT) {
1332         char    *s,*t;
1333         
1334         TRACE(mmsys,"lpstrElementName='%s'\n",
1335               (char*)PTR_SEG_TO_LIN(lpParms->lpstrElementName)
1336               );
1337         s = (char*)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
1338         t = strrchr(s,'.');
1339         if (t) {
1340             GetProfileString32A("mci extensions",t+1,"*",str,sizeof(str));
1341             CharUpper32A(str);
1342             TRACE(mmsys, "str = %s \n", str);
1343             if (strcmp(str, "CDAUDIO") == 0) {
1344                 uDevTyp = MCI_DEVTYPE_CD_AUDIO;
1345             } else if (strcmp(str, "WAVEAUDIO") == 0) {
1346                 uDevTyp = MCI_DEVTYPE_WAVEFORM_AUDIO;
1347             } else if (strcmp(str, "SEQUENCER") == 0)   {
1348                 uDevTyp = MCI_DEVTYPE_SEQUENCER;
1349             } else if (strcmp(str, "ANIMATION1") == 0) {
1350                 uDevTyp = MCI_DEVTYPE_ANIMATION;
1351             } else if (strcmp(str, "AVIVIDEO") == 0) {
1352                 uDevTyp = MCI_DEVTYPE_DIGITAL_VIDEO;
1353             } else if (strcmp(str,"*") == 0) {
1354                 TRACE(mmsys,"No [mci extensions] entry for %s found.\n",t);
1355                 return MCIERR_EXTENSION_NOT_FOUND;
1356 #if testing16
1357             } else  {
1358                 HDRVR16 hdrv = OpenDriver(str,"mci",NULL);
1359                 if (hdrv) {
1360                     HMODULE16   hmod;
1361                     
1362                     hmod = GetDriverModuleHandle(hdrv);
1363                     mciGetDrv(wDevID)->hDrv = hdrv;
1364                     mciGetDrv(wDevID)->driverProc = GetProcAddress16(hmod,SEGPTR_GET(SEGPTR_STRDUP("DRIVERPROC")));
1365                     uDevTyp = MCI_DEVTYPE_OTHER;
1366                 } else {
1367                     FIXME(mmsys, "[mci extensions] entry %s for %s not supported.\n",str,t);
1368                     return MCIERR_DEVICE_NOT_INSTALLED;
1369                 }
1370 #endif
1371             }
1372         } else
1373             return MCIERR_EXTENSION_NOT_FOUND;
1374     }
1375     
1376     if (dwParam & MCI_OPEN_ALIAS) {
1377         TRACE(mmsys, "Alias='%s' !\n",
1378               (char*)PTR_SEG_TO_LIN(lpParms->lpstrAlias));
1379         mciGetOpenDrv(wDevID)->lpstrAlias = strdup(PTR_SEG_TO_LIN(lpParms->lpstrAlias));
1380         /* mplayer does allocate alias to CDAUDIO */
1381     }
1382     if (dwParam & MCI_OPEN_TYPE) {
1383         if (dwParam & MCI_OPEN_TYPE_ID) {
1384             TRACE(mmsys, "Dev=%08lx!\n", (DWORD)PTR_SEG_TO_LIN(lpParms->lpstrDeviceType));
1385             uDevTyp = LOWORD((DWORD)lpParms->lpstrDeviceType);
1386             mciGetOpenDrv(wDevID)->lpstrDeviceType=strdup(PTR_SEG_TO_LIN(lpParms->lpstrDeviceType));
1387         } else {
1388             if (lpParms->lpstrDeviceType == NULL) return MCIERR_INTERNAL;
1389             TRACE(mmsys, "Dev='%s' !\n",
1390                   (char*)PTR_SEG_TO_LIN(lpParms->lpstrDeviceType));
1391             mciGetOpenDrv(wDevID)->lpstrDeviceType=strdup(PTR_SEG_TO_LIN(lpParms->lpstrDeviceType));
1392             strcpy(str, PTR_SEG_TO_LIN(lpParms->lpstrDeviceType));
1393             CharUpper32A(str);
1394             if (strcmp(str, "CDAUDIO") == 0) {
1395                 uDevTyp = MCI_DEVTYPE_CD_AUDIO;
1396             } else if (strcmp(str, "WAVEAUDIO") == 0) {
1397                 uDevTyp = MCI_DEVTYPE_WAVEFORM_AUDIO;
1398             } else if (strcmp(str, "SEQUENCER") == 0)   {
1399                 uDevTyp = MCI_DEVTYPE_SEQUENCER;
1400             } else if (strcmp(str, "ANIMATION1") == 0) {
1401                 uDevTyp = MCI_DEVTYPE_ANIMATION;
1402             } else if (strcmp(str, "AVIVIDEO") == 0) {
1403                 uDevTyp = MCI_DEVTYPE_DIGITAL_VIDEO;
1404             } else {
1405 #if testing16
1406                 HDRVR16 hdrv;
1407                 TRACE(mmsys,"trying to load driver...\n");
1408                 hdrv = OpenDriver(str,"mci",NULL);
1409                 if (hdrv) {
1410                     HMODULE16   hmod;
1411                     
1412                     hmod = GetDriverModuleHandle(hdrv);
1413                     mciGetDrv(wDevID)->hDrv = hdrv;
1414                     mciGetDrv(wDevID)->driverProc = GetProcAddress16(hmod,SEGPTR_GET(SEGPTR_STRDUP("DRIVERPROC")));
1415                     uDevTyp = MCI_DEVTYPE_OTHER;
1416                 } else
1417 #endif
1418                     return MCIERR_DEVICE_NOT_INSTALLED;
1419             }
1420         }
1421     }
1422     mciGetDrv(wDevID)->modp.wType = uDevTyp;
1423     mciGetDrv(wDevID)->modp.wDeviceID = 0;  /* FIXME? for multiple devices */
1424     lpParms->wDeviceID = wDevID;
1425     TRACE(mmsys, "mcidev=%d, uDevTyp=%04X wDeviceID=%04X !\n", 
1426           wDevID, uDevTyp, lpParms->wDeviceID);
1427     switch (uDevTyp) {
1428     case MCI_DEVTYPE_CD_AUDIO:
1429         dwret = CDAUDIO_DriverProc16(0, 0, MCI_OPEN_DRIVER, dwParam, (DWORD)lp16Parms);
1430         break;
1431     case MCI_DEVTYPE_WAVEFORM_AUDIO:
1432         dwret =  WAVE_DriverProc16(0, 0, MCI_OPEN_DRIVER, dwParam, (DWORD)lp16Parms);
1433         break;
1434     case MCI_DEVTYPE_SEQUENCER:
1435         dwret = MIDI_DriverProc16(0, 0, MCI_OPEN_DRIVER, dwParam, (DWORD)lp16Parms);
1436         break;
1437     case MCI_DEVTYPE_ANIMATION:
1438         dwret = ANIM_DriverProc16(0, 0, MCI_OPEN_DRIVER, dwParam, (DWORD)lp16Parms);
1439         break;
1440     case MCI_DEVTYPE_DIGITAL_VIDEO:
1441         TRACE(mmsys, "No DIGITAL_VIDEO yet !\n");
1442         return MCIERR_DEVICE_NOT_INSTALLED;
1443     default:
1444 #if testing16
1445         dwret = Callbacks->CallDriverProc(mciGetDrv(wDevID)->driverProc,0,mciGetDrv(wDevID)->hDrv,MCI_OPEN_DRIVER,dwParam,(DWORD)lp16Parms);
1446         WARN(mmsys, "Invalid Device Name '%08lx' !\n", (DWORD)lpParms->lpstrDeviceType);
1447 #endif
1448         return MCIERR_INVALID_DEVICE_NAME;
1449     }
1450     
1451     
1452     if (dwParam & MCI_NOTIFY)
1453         mciDriverNotify(lpParms->dwCallback, wDevID,
1454                         (dwret==0?MCI_NOTIFY_SUCCESSFUL:MCI_NOTIFY_FAILURE));
1455     
1456     /* only handled devices fall through */
1457     TRACE(mmsys, "wDevID = %04X wDeviceID = %d dwret = %ld\n",wDevID, lpParms->wDeviceID, dwret);
1458     return dwret;
1459 }
1460
1461 /**************************************************************************
1462  *                      mciGetDriverData                        [MMSYSTEM.708]
1463  */
1464 DWORD WINAPI mciGetDriverData16(HDRVR16 hdrv) 
1465 {
1466     FIXME(mmsys,"(%04x): stub!\n",hdrv);
1467     return 0x42;
1468 }
1469
1470 /**************************************************************************
1471  *                      mciSetDriverData                        [MMSYSTEM.707]
1472  */
1473 DWORD WINAPI mciSetDriverData16(HDRVR16 hdrv,DWORD data) 
1474 {
1475     FIXME(mmsys,"(%04x,%08lx): stub!\n",hdrv,data);
1476     return 0;
1477 }
1478
1479 /**************************************************************************
1480  *                      mciClose16                              [internal]
1481  */
1482 static DWORD mciClose16(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
1483 {
1484     DWORD       dwRet = MCIERR_INTERNAL;
1485     
1486     TRACE(mmsys, "(%04x, %08lX, %p)\n", wDevID, dwParam, lpParms);
1487
1488     if(wDevID == MCI_ALL_DEVICE_ID) {
1489         FIXME(mmsys, "unhandled MCI_ALL_DEVICE_ID\n");
1490         return MCIERR_CANNOT_USE_ALL;
1491     }
1492
1493     switch (mciGetDrv(wDevID)->modp.wType) {
1494     case MCI_DEVTYPE_CD_AUDIO:
1495         dwRet = CDAUDIO_DriverProc16(mciGetDrv(wDevID)->modp.wDeviceID,0,
1496                                    MCI_CLOSE, dwParam, (DWORD)lpParms);
1497         break;
1498     case MCI_DEVTYPE_WAVEFORM_AUDIO:
1499         dwRet = WAVE_DriverProc16(mciGetDrv(wDevID)->modp.wDeviceID, 0, 
1500                                 MCI_CLOSE, dwParam,
1501                                 (DWORD)lpParms);
1502         break;
1503     case MCI_DEVTYPE_SEQUENCER:
1504         dwRet = MIDI_DriverProc16(mciGetDrv(wDevID)->modp.wDeviceID, 0, 
1505                                 MCI_CLOSE, dwParam,
1506                                 (DWORD)lpParms);
1507         break;
1508         /*
1509           case MCI_DEVTYPE_ANIMATION:
1510           dwRet = ANIM_DriverProc16(mciGetDrv(wDevID)->modp.wDeviceID, 0, 
1511           MCI_CLOSE, dwParam,
1512           (DWORD)lpParms);
1513           break;
1514         */
1515     default:
1516         dwRet = Callbacks->CallDriverProc(mciGetDrv(wDevID)->driverProc,
1517                                           mciGetDrv(wDevID)->modp.wDeviceID,
1518                                           mciGetDrv(wDevID)->hDrv,MCI_CLOSE,dwParam,
1519                                           (DWORD)lpParms);
1520     }
1521     mciGetDrv(wDevID)->modp.wType = 0;
1522     
1523     if (dwParam&MCI_NOTIFY)
1524         mciDriverNotify(lpParms->dwCallback,wDevID,
1525                         (dwRet==0?MCI_NOTIFY_SUCCESSFUL:MCI_NOTIFY_FAILURE));
1526     
1527     TRACE(mmsys, "returns %ld\n",dwRet);
1528     return dwRet;
1529 }
1530
1531
1532 /**************************************************************************
1533  *                      mciSysinfo16                            [internal]
1534  */
1535 static DWORD mciSysInfo16(DWORD dwFlags, LPMCI_SYSINFO_PARMS16 lpParms)
1536 {
1537     LPSTR       lpstrReturn;
1538     DWORD       *lpdwRet;
1539     
1540     TRACE(mci, "(%08lX, %08lX)\n", dwFlags, (DWORD)lpParms);
1541     lpstrReturn = PTR_SEG_TO_LIN(lpParms->lpstrReturn);
1542     switch (dwFlags) {
1543     case MCI_SYSINFO_QUANTITY:
1544         TRACE(mci, "MCI_SYSINFO_QUANTITY \n");
1545         lpdwRet = (DWORD *)lpstrReturn;
1546         *(lpdwRet) = mciInstalledCount;
1547         return 0;
1548     case MCI_SYSINFO_INSTALLNAME:
1549         TRACE(mci, "MCI_SYSINFO_INSTALLNAME \n");
1550         if (lpParms->dwRetSize < mciInstalledListLen)
1551             lstrcpyn32A(lpstrReturn, lpmciInstallNames, lpParms->dwRetSize - 1);
1552         else
1553             strcpy(lpstrReturn, lpmciInstallNames);
1554         return 0;
1555     case MCI_SYSINFO_NAME:
1556         TRACE(mci, "MCI_SYSINFO_NAME\n");
1557         if (lpParms->dwNumber > mciInstalledCount)
1558             return MMSYSERR_INVALPARAM;
1559         {
1560             DWORD       count = lpParms->dwNumber;
1561             LPSTR       ptr = lpmciInstallNames;
1562
1563             while (--count > 0) 
1564                 ptr += strlen(ptr) + 1;
1565             if (lpParms->dwRetSize < strlen(ptr))
1566                 lstrcpyn32A(lpstrReturn, ptr, lpParms->dwRetSize - 1);
1567             else
1568                 strcpy(lpstrReturn, ptr);
1569         }
1570         TRACE(mci, "(%ld) => '%s'\n", lpParms->dwNumber, lpParms->lpstrReturn);
1571         return 0;
1572     case MCI_SYSINFO_OPEN:
1573         TRACE(mci, "MCI_SYSINFO_OPEN \n");
1574         return 0;
1575     }
1576     return MMSYSERR_INVALPARAM;
1577 }
1578
1579 /**************************************************************************
1580  *                      mciLoadCommandResource16  [MMSYSTEM.705]
1581  */
1582 UINT16 WINAPI mciLoadCommandResource16(HANDLE16 hinst,LPCSTR resname,UINT16 type)
1583 {
1584     char            buf[200];
1585     OFSTRUCT        ofs;
1586     HANDLE16        xhinst;
1587     HRSRC16         hrsrc;
1588     HGLOBAL16       hmem;
1589     LPSTR           segstr;
1590     SEGPTR          xmem;
1591     LPBYTE          lmem;
1592     static UINT16   mcidevtype = 0;
1593     
1594     FIXME(mmsys,"(%04x,%s,%d): stub!\n",hinst,resname,type);
1595     if (!lstrcmpi32A(resname,"core")) {
1596         FIXME(mmsys,"(...,\"core\",...), have to use internal tables... (not there yet)\n");
1597         return 0;
1598     }
1599     /* if file exists "resname.mci", then load resource "resname" from it
1600      * otherwise directly from driver
1601      */
1602     strcpy(buf,resname);
1603     strcat(buf,".mci");
1604     if (OpenFile32(buf,&ofs,OF_EXIST)!=HFILE_ERROR32) {
1605         xhinst = LoadLibrary16(buf);
1606         if (xhinst >32)
1607             hinst = xhinst;
1608     } /* else use passed hinst */
1609     segstr = SEGPTR_STRDUP(resname);
1610     hrsrc = FindResource16(hinst,SEGPTR_GET(segstr),type);
1611     SEGPTR_FREE(segstr);
1612     if (!hrsrc) {
1613         WARN(mmsys,"no special commandlist found in resource\n");
1614         return MCI_NO_COMMAND_TABLE;
1615     }
1616     hmem = LoadResource16(hinst,hrsrc);
1617     if (!hmem) {
1618         WARN(mmsys,"couldn't load resource??\n");
1619         return MCI_NO_COMMAND_TABLE;
1620     }
1621     xmem = WIN16_LockResource16(hmem);
1622     if (!xmem) {
1623         WARN(mmsys,"couldn't lock resource??\n");
1624         FreeResource16(hmem);
1625         return MCI_NO_COMMAND_TABLE;
1626     }
1627     lmem = PTR_SEG_TO_LIN(xmem);
1628     TRACE(mmsys,"first resource entry is %s\n",(char*)lmem);
1629     /* parse resource, register stuff, return unique id */
1630     return ++mcidevtype;
1631 }
1632
1633
1634 /**************************************************************************
1635  *                      mciSound                                [internal]
1636  *  not used anymore ??
1637  
1638  DWORD mciSound(UINT16 wDevID, DWORD dwParam, LPMCI_SOUND_PARMS lpParms)
1639  {
1640  if (lpParms == NULL) return MCIERR_INTERNAL;
1641  if (dwParam & MCI_SOUND_NAME)
1642  TRACE(mci, "file='%s' !\n", lpParms->lpstrSoundName);
1643  return MCIERR_INVALID_DEVICE_ID;
1644  }
1645  *
1646  */
1647
1648 static const char *_mciCommandToString(UINT16 wMsg)
1649 {
1650     static char buffer[100];
1651     
1652 #define CASE(s) case (s): return #s
1653     
1654     switch (wMsg) {
1655         CASE(MCI_OPEN);
1656         CASE(MCI_CLOSE);
1657         CASE(MCI_ESCAPE);
1658         CASE(MCI_PLAY);
1659         CASE(MCI_SEEK);
1660         CASE(MCI_STOP);
1661         CASE(MCI_PAUSE);
1662         CASE(MCI_INFO);
1663         CASE(MCI_GETDEVCAPS);
1664         CASE(MCI_SPIN);
1665         CASE(MCI_SET);
1666         CASE(MCI_STEP);
1667         CASE(MCI_RECORD);
1668         CASE(MCI_SYSINFO);
1669         CASE(MCI_BREAK);
1670         CASE(MCI_SAVE);
1671         CASE(MCI_STATUS);
1672         CASE(MCI_CUE);
1673         CASE(MCI_REALIZE);
1674         CASE(MCI_WINDOW);
1675         CASE(MCI_PUT);
1676         CASE(MCI_WHERE);
1677         CASE(MCI_FREEZE);
1678         CASE(MCI_UNFREEZE);
1679         CASE(MCI_LOAD);
1680         CASE(MCI_CUT);
1681         CASE(MCI_COPY);
1682         CASE(MCI_PASTE);
1683         CASE(MCI_UPDATE);
1684         CASE(MCI_RESUME);
1685         CASE(MCI_DELETE);
1686     default:
1687         sprintf(buffer, "%04X", wMsg);
1688         return buffer;
1689         
1690     }
1691 }
1692
1693 /**************************************************************************
1694  *                      mciOpen32                               [internal]
1695  */
1696
1697 static DWORD mciOpen32(DWORD dwParam, LPMCI_OPEN_PARMS32A lpParms)
1698 {
1699     char                str[128];
1700     UINT16              uDevTyp = 0;
1701     UINT16              wDevID = MMSYSTEM_FirstDevID();
1702     DWORD               dwret;
1703     
1704     TRACE(mmsys, "(%08lX, %p)\n", dwParam, lpParms);
1705     if (lpParms == NULL) return MCIERR_INTERNAL;
1706     
1707     if ((dwParam & ~(MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY)) != 0) {
1708         FIXME(mmsys, "unsupported yet dwFlags=%08lX\n", 
1709               (dwParam & ~(MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY)));
1710     }
1711
1712     while (mciGetDrv(wDevID)->modp.wType != 0) {
1713         wDevID = MMSYSTEM_NextDevID(wDevID);
1714         if (!MMSYSTEM_DevIDValid(wDevID)) {
1715             TRACE(mmsys, "MAXMCIDRIVERS reached !\n");
1716             return MCIERR_INTERNAL;
1717         }
1718     }
1719     TRACE(mmsys, "wDevID=%04X \n", wDevID);
1720     memcpy(mciGetOpenDrv(wDevID), lpParms, sizeof(*lpParms));
1721     
1722     if (dwParam & MCI_OPEN_ELEMENT) {
1723         char    *s,*t;
1724         
1725         TRACE(mmsys,"lpstrElementName='%s'\n", lpParms->lpstrElementName);
1726         s = lpParms->lpstrElementName;
1727         t = strrchr(s, '.');
1728         if (t) {
1729             GetProfileString32A("mci extensions", t+1, "*", str, sizeof(str));
1730             CharUpper32A(str);
1731             TRACE(mmsys, "str = %s \n", str);
1732             if (strcmp(str, "CDAUDIO") == 0) {
1733                 uDevTyp = MCI_DEVTYPE_CD_AUDIO;
1734             } else if (strcmp(str, "WAVEAUDIO") == 0) {
1735                 uDevTyp = MCI_DEVTYPE_WAVEFORM_AUDIO;
1736             } else if (strcmp(str, "SEQUENCER") == 0)   {
1737                 uDevTyp = MCI_DEVTYPE_SEQUENCER;
1738             } else if (strcmp(str, "ANIMATION1") == 0) {
1739                 uDevTyp = MCI_DEVTYPE_ANIMATION;
1740             } else if (strcmp(str, "AVIVIDEO") == 0) {
1741                 uDevTyp = MCI_DEVTYPE_DIGITAL_VIDEO;
1742             } else if (strcmp(str,"*") == 0) {
1743                 TRACE(mmsys,"No [mci extensions] entry for %s found.\n",t);
1744                 return MCIERR_EXTENSION_NOT_FOUND;
1745 #if testing32
1746                 /* FIXME has to written, seems to be experimental 16 bit code anyway */
1747             } else  {
1748                 HDRVR16 hdrv = OpenDriver(str, "mci", NULL);
1749                 if (hdrv) {
1750                     HMODULE16   hmod;
1751                     
1752                     hmod = GetDriverModuleHandle(hdrv);
1753                     mciGetDrv(wDevID)->hDrv = hdrv;
1754                     mciGetDrv(wDevID)->driverProc = GetProcAddress16(hmod,oouch SEGPTR_GET(SEGPTR_STRDUP("DRIVERPROC")));
1755                     uDevTyp = MCI_DEVTYPE_OTHER;
1756                 } else {
1757                     FIXME(mmsys, "[mci extensions] entry %s for %s not supported.\n",str,t);
1758                     return MCIERR_DEVICE_NOT_INSTALLED;
1759                 }
1760 #endif
1761             }
1762         } else
1763             return MCIERR_EXTENSION_NOT_FOUND;
1764     }
1765     
1766     if (dwParam & MCI_OPEN_ALIAS) {
1767         TRACE(mmsys, "Alias='%s' !\n", lpParms->lpstrAlias);
1768         /* FIXME is there any memory leak here ? */
1769         mciGetOpenDrv(wDevID)->lpstrAlias = strdup(lpParms->lpstrAlias);
1770         /* mplayer does allocate alias to CDAUDIO */
1771     }
1772     if (dwParam & MCI_OPEN_TYPE) {
1773         if (dwParam & MCI_OPEN_TYPE_ID) {
1774             TRACE(mmsys, "Dev=%08lx!\n", (DWORD)lpParms->lpstrDeviceType);
1775             uDevTyp = LOWORD((DWORD)lpParms->lpstrDeviceType);
1776             mciGetOpenDrv(wDevID)->lpstrDeviceType = lpParms->lpstrDeviceType;
1777         } else {
1778             if (lpParms->lpstrDeviceType == NULL) 
1779                 return MCIERR_INTERNAL;
1780             TRACE(mmsys, "Dev='%s' !\n", lpParms->lpstrDeviceType);
1781             /* FIXME is there any memory leak here ? */
1782             mciGetOpenDrv(wDevID)->lpstrDeviceType = strdup(lpParms->lpstrDeviceType);
1783             strcpy(str, lpParms->lpstrDeviceType);
1784             CharUpper32A(str);
1785             if (strcmp(str, "CDAUDIO") == 0) {
1786                 uDevTyp = MCI_DEVTYPE_CD_AUDIO;
1787             } else if (strcmp(str, "WAVEAUDIO") == 0) {
1788                 uDevTyp = MCI_DEVTYPE_WAVEFORM_AUDIO;
1789             } else if (strcmp(str, "SEQUENCER") == 0)   {
1790                 uDevTyp = MCI_DEVTYPE_SEQUENCER;
1791             } else if (strcmp(str, "ANIMATION1") == 0) {
1792                 uDevTyp = MCI_DEVTYPE_ANIMATION;
1793             } else if (strcmp(str, "AVIVIDEO") == 0) {
1794                 uDevTyp = MCI_DEVTYPE_DIGITAL_VIDEO;
1795             } else {
1796 #if testing32
1797                 /* FIXME has to written, seems to be experimental 16 bit code anyway */
1798                 HDRVR16 hdrv;
1799                 TRACE(mmsys,"trying to load driver...\n");
1800                 hdrv = OpenDriver(str,"mci",NULL);
1801                 if (hdrv) {
1802                     HMODULE16   hmod;
1803                     
1804                     hmod = GetDriverModuleHandle(hdrv);
1805                     mciGetDrv(wDevID)->hDrv = hdrv;
1806                     mciGetDrv(wDevID)->driverProc = GetProcAddress16(hmod,oouch SEGPTR_GET(SEGPTR_STRDUP("DRIVERPROC")));
1807                     uDevTyp = MCI_DEVTYPE_OTHER;
1808                 } else
1809 #endif
1810                     return MCIERR_DEVICE_NOT_INSTALLED;
1811             }
1812         }
1813     }
1814     mciGetDrv(wDevID)->modp.wType = uDevTyp;
1815     mciGetDrv(wDevID)->modp.wDeviceID = 0;  /* FIXME? for multiple devices */
1816     lpParms->wDeviceID = wDevID;
1817     TRACE(mmsys, "mcidev=%d, uDevTyp=%04X wDeviceID=%04X !\n", 
1818           wDevID, uDevTyp, lpParms->wDeviceID);
1819     switch (uDevTyp) {
1820     case MCI_DEVTYPE_CD_AUDIO:
1821         dwret = CDAUDIO_DriverProc32( 0, 0, MCI_OPEN_DRIVER,
1822                                     dwParam, (DWORD)lpParms);
1823         break;
1824     case MCI_DEVTYPE_WAVEFORM_AUDIO:
1825         dwret =  WAVE_DriverProc32( 0, 0, MCI_OPEN_DRIVER, 
1826                                   dwParam, (DWORD)lpParms);
1827         break;
1828     case MCI_DEVTYPE_SEQUENCER:
1829         dwret = MIDI_DriverProc32( 0, 0, MCI_OPEN_DRIVER, 
1830                                  dwParam, (DWORD)lpParms);
1831         break;
1832     case MCI_DEVTYPE_ANIMATION:
1833         dwret = ANIM_DriverProc32( 0, 0, MCI_OPEN_DRIVER, 
1834                                  dwParam, (DWORD)lpParms);
1835         break;
1836     case MCI_DEVTYPE_DIGITAL_VIDEO:
1837         TRACE(mmsys, "No DIGITAL_VIDEO yet !\n");
1838         return MCIERR_DEVICE_NOT_INSTALLED;
1839     default:
1840 #if testing32
1841         dwret = Callbacks->CallDriverProc(mciGetDrv(wDevID)->driverProc,0,mciGetDrv(wDevID)->hdrv,MCI_OPEN_DRIVER,dwParam,(DWORD)lpParms);
1842         WARN(mmsys, "Invalid Device Name '%08lx' !\n", (DWORD)lpParms->lpstrDeviceType);
1843 #endif
1844         return MCIERR_INVALID_DEVICE_NAME;
1845     }
1846     
1847     
1848     if (dwParam & MCI_NOTIFY)
1849         mciDriverNotify(lpParms->dwCallback,wDevID,
1850                         (dwret==0?MCI_NOTIFY_SUCCESSFUL:MCI_NOTIFY_FAILURE));
1851     
1852     /* only handled devices fall through */
1853     TRACE(mmsys, "wDevID = %04X wDeviceID = %d dwret = %ld\n",wDevID, lpParms->wDeviceID, dwret);
1854     return dwret;
1855 }
1856
1857 /**************************************************************************
1858  *                      mciClose32                              [internal]
1859  */
1860 static DWORD mciClose32(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
1861 {
1862     DWORD       dwRet = MCIERR_INTERNAL;
1863     
1864     TRACE(mmsys, "(%04x, %08lX, %p)\n", wDevID, dwParam, lpParms);
1865
1866     if (wDevID == MCI_ALL_DEVICE_ID) {
1867         FIXME(mmsys, "unhandled MCI_ALL_DEVICE_ID\n");
1868         return MCIERR_CANNOT_USE_ALL;
1869     }
1870
1871     switch (mciGetDrv(wDevID)->modp.wType) {
1872     case MCI_DEVTYPE_CD_AUDIO:
1873         dwRet = CDAUDIO_DriverProc32(mciGetDrv(wDevID)->modp.wDeviceID,0,
1874                                    MCI_CLOSE, dwParam, (DWORD)lpParms);
1875         break;
1876     case MCI_DEVTYPE_WAVEFORM_AUDIO:
1877         dwRet = WAVE_DriverProc32(mciGetDrv(wDevID)->modp.wDeviceID, 0, 
1878                                 MCI_CLOSE, dwParam,
1879                                 (DWORD)lpParms);
1880         break;
1881     case MCI_DEVTYPE_SEQUENCER:
1882         dwRet = MIDI_DriverProc32(mciGetDrv(wDevID)->modp.wDeviceID, 0, 
1883                                 MCI_CLOSE, dwParam,
1884                                 (DWORD)lpParms);
1885         break;
1886         /*
1887           case MCI_DEVTYPE_ANIMATION:
1888           dwRet = ANIM_DriverProc32(mciGetDrv(wDevID)->modp.wDeviceID, 0, 
1889           MCI_CLOSE, dwParam,
1890           (DWORD)lpParms);
1891           break;
1892         */
1893     default:
1894         dwRet = Callbacks->CallDriverProc(mciGetDrv(wDevID)->driverProc,
1895                                           mciGetDrv(wDevID)->modp.wDeviceID,
1896                                           mciGetDrv(wDevID)->hDrv,MCI_CLOSE,dwParam,
1897                                           (DWORD)lpParms);
1898     }
1899     mciGetDrv(wDevID)->modp.wType = 0;
1900     
1901     if (dwParam&MCI_NOTIFY)
1902         mciDriverNotify(lpParms->dwCallback,wDevID,
1903                         (dwRet==0?MCI_NOTIFY_SUCCESSFUL:MCI_NOTIFY_FAILURE));
1904     
1905     TRACE(mmsys, "returns %ld\n",dwRet);
1906     return dwRet;
1907 }
1908
1909 /**************************************************************************
1910  *                      mciSysinfo32                            [internal]
1911  */
1912 static DWORD mciSysInfo32(DWORD dwFlags, LPMCI_SYSINFO_PARMS32A lpParms)
1913 {
1914     TRACE(mci, "(%08lX, %08lX)\n", dwFlags, (DWORD)lpParms);
1915     switch (dwFlags) {
1916     case MCI_SYSINFO_QUANTITY:
1917         TRACE(mci, "MCI_SYSINFO_QUANTITY \n");
1918         *(DWORD*)lpParms->lpstrReturn = mciInstalledCount;
1919         return 0;
1920     case MCI_SYSINFO_INSTALLNAME:
1921         TRACE(mci, "MCI_SYSINFO_INSTALLNAME \n");
1922         if (lpParms->dwRetSize < mciInstalledListLen)
1923             lstrcpyn32A(lpParms->lpstrReturn, lpmciInstallNames, lpParms->dwRetSize - 1);
1924         else
1925             strcpy(lpParms->lpstrReturn, lpmciInstallNames);
1926         return 0;
1927     case MCI_SYSINFO_NAME:
1928         TRACE(mci, "MCI_SYSINFO_NAME\n");       fflush(stddeb);
1929         if (lpParms->dwNumber > mciInstalledCount)
1930             return MMSYSERR_INVALPARAM;
1931         {
1932             DWORD       count = lpParms->dwNumber;
1933             LPSTR       ptr = lpmciInstallNames;
1934
1935             while (--count > 0) 
1936                 ptr += strlen(ptr) + 1;
1937             if (lpParms->dwRetSize < strlen(ptr))
1938                 lstrcpyn32A(lpParms->lpstrReturn, ptr, lpParms->dwRetSize - 1);
1939             else
1940                 strcpy(lpParms->lpstrReturn, ptr);
1941         }
1942         TRACE(mci, "(%ld) => '%s'\n", lpParms->dwNumber, lpParms->lpstrReturn);
1943         return 0;
1944     case MCI_SYSINFO_OPEN:
1945         TRACE(mci, "MCI_SYSINFO_OPEN \n");
1946         return 0;
1947     }
1948     return MMSYSERR_INVALPARAM;
1949 }
1950
1951 struct SCA32 {
1952     UINT32      wDevID;
1953     UINT32      wMsg;
1954     DWORD       dwParam1;
1955     DWORD       dwParam2;
1956 };
1957
1958 DWORD WINAPI mciSendCommand32A(UINT32 wDevID, UINT32 wMsg, DWORD dwParam1, DWORD dwParam2);
1959
1960 static DWORD WINAPI mciSCAStarter32(LPVOID arg)
1961 {
1962     struct SCA32*       sca = (struct SCA32*)arg;
1963     DWORD               ret;
1964
1965     TRACE(mci, "In thread for async command (%08x,%s,%08lx,%08lx)\n",
1966           sca->wDevID, _mciCommandToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
1967     ret = mciSendCommand32A(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);
1968     free(sca);
1969     return ret;
1970 }
1971
1972 /**************************************************************************
1973  *                              mciSendCommandAsync32           [internal]
1974  */
1975 DWORD mciSendCommandAsync32(UINT32 wDevID, UINT32 wMsg, DWORD dwParam1, DWORD dwParam2)
1976 {
1977     struct SCA32*       sca = malloc(sizeof(struct SCA32));
1978
1979     if (sca == 0)       return MCIERR_OUT_OF_MEMORY;
1980
1981     sca->wDevID   = wDevID;
1982     sca->wMsg     = wMsg;
1983     sca->dwParam1 = dwParam1;
1984     sca->dwParam2 = dwParam2;
1985     
1986     if (CreateThread(NULL, 0, mciSCAStarter32, sca, 0, NULL) == 0) {
1987         WARN(mci, "Couldn't allocate thread for async command handling, sending synchonously\n");
1988         return mciSCAStarter32(&sca);
1989     }
1990     return 0;
1991 }
1992
1993 /**************************************************************************
1994  *                              mciSendCommand32A               [WINMM.49]
1995  */
1996 DWORD WINAPI mciSendCommand32A(UINT32 wDevID, UINT32 wMsg, DWORD dwParam1, DWORD dwParam2)
1997 {
1998     TRACE(mci,"(%08x,%s,%08lx,%08lx)\n",
1999           wDevID,_mciCommandToString(wMsg),dwParam1,dwParam2);
2000
2001     switch (wMsg) {
2002     case MCI_OPEN:
2003         return mciOpen32(dwParam1, (LPMCI_OPEN_PARMS32A)dwParam2);
2004     case MCI_CLOSE:
2005         return mciClose32(wDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
2006     case MCI_SYSINFO:
2007         return mciSysInfo32(dwParam1, (LPMCI_SYSINFO_PARMS32A)dwParam2);
2008     default:
2009         {
2010             DWORD               dwRet = MCIERR_INTERNAL;
2011             LONG                (*proc)(DWORD, HDRVR16, DWORD, DWORD, DWORD) = 0;
2012
2013             if (wDevID == MCI_ALL_DEVICE_ID) {
2014                 FIXME(mci, "unhandled MCI_ALL_DEVICE_ID\n");
2015                 return MCIERR_CANNOT_USE_ALL;
2016             }
2017             
2018             if (!MMSYSTEM_DevIDValid(wDevID))
2019                 return MMSYSERR_INVALPARAM;
2020
2021             switch (mciGetDrv(wDevID)->modp.wType) {
2022             case MCI_DEVTYPE_CD_AUDIO:          proc = CDAUDIO_DriverProc32;    break;
2023             case MCI_DEVTYPE_WAVEFORM_AUDIO:    proc = WAVE_DriverProc32;       break;
2024             case MCI_DEVTYPE_SEQUENCER:         proc = MIDI_DriverProc32;       break;
2025                 /*  case MCI_DEVTYPE_ANIMATION: proc = ANIM_DriverProc32;       break;*/
2026             }
2027             if (proc) {
2028                 dwRet = (proc)(mciGetDrv(wDevID)->modp.wDeviceID, mciGetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
2029             } else if (mciGetDrv(wDevID)->driverProc) {
2030                 FIXME(mmsys, "is that correct ?\n");
2031                 dwRet = Callbacks->CallDriverProc(mciGetDrv(wDevID)->driverProc,
2032                                                   mciGetDrv(wDevID)->modp.wDeviceID,
2033                                                   mciGetDrv(wDevID)->hDrv,wMsg, dwParam1, dwParam2);
2034             } else {
2035                 WARN(mmsys, "unknown device type=%04X !\n", mciGetDrv(wDevID)->modp.wType);
2036             }
2037             return dwRet;
2038         }
2039     }
2040     return 0x1; /* !ok */
2041 }
2042 /**************************************************************************
2043  *                              mciSendCommand                  [MMSYSTEM.701]
2044  */
2045 DWORD WINAPI mciSendCommand(UINT16 wDevID, UINT16 wMsg, DWORD dwParam1,
2046                             DWORD dwParam2)
2047 {
2048     TRACE(mmsys, "(%04X, %s, %08lX, %08lX)\n", 
2049           wDevID, _mciCommandToString(wMsg), dwParam1, dwParam2);
2050
2051     switch (wMsg) {
2052     case MCI_OPEN:
2053         return mciOpen16(dwParam1, (LPMCI_OPEN_PARMS16)dwParam2);
2054     case MCI_CLOSE:
2055         return mciClose16(wDevID, dwParam1,
2056                          (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
2057     case MCI_SYSINFO:
2058         return mciSysInfo16(dwParam1,
2059                            (LPMCI_SYSINFO_PARMS16)PTR_SEG_TO_LIN(dwParam2));
2060     default:
2061         {
2062             DWORD               dwRet = MCIERR_INTERNAL;
2063             LONG                (*proc)(DWORD, HDRVR16, WORD, DWORD, DWORD) = 0;
2064
2065             if (wDevID == MCI_ALL_DEVICE_ID) {
2066                 FIXME(mci, "unhandled MCI_ALL_DEVICE_ID\n");
2067                 return MCIERR_CANNOT_USE_ALL;
2068             }
2069     
2070             if (!MMSYSTEM_DevIDValid(wDevID))
2071                 return MMSYSERR_INVALPARAM;
2072     
2073             switch (mciGetDrv(wDevID)->modp.wType) {
2074             case MCI_DEVTYPE_CD_AUDIO:          proc = CDAUDIO_DriverProc16;    break;
2075             case MCI_DEVTYPE_WAVEFORM_AUDIO:    proc = WAVE_DriverProc16;       break;
2076             case MCI_DEVTYPE_SEQUENCER:         proc = MIDI_DriverProc16;       break;
2077                 /*  case MCI_DEVTYPE_ANIMATION: proc = ANIM_DriverProc16;       break;*/
2078             }
2079             if (proc) {
2080                 dwRet = (proc)(mciGetDrv(wDevID)->modp.wDeviceID, mciGetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
2081             } else if (mciGetDrv(wDevID)->driverProc) {
2082                 dwRet = Callbacks->CallDriverProc(mciGetDrv(wDevID)->driverProc,
2083                                                   mciGetDrv(wDevID)->modp.wDeviceID,
2084                                                   mciGetDrv(wDevID)->hDrv,wMsg, dwParam1, dwParam2);
2085             } else {
2086                 WARN(mmsys, "unknown device type=%04X !\n", mciGetDrv(wDevID)->modp.wType);
2087             }
2088             return dwRet;
2089         }
2090     }
2091     return MMSYSERR_INVALPARAM;
2092 }
2093
2094 /**************************************************************************
2095  *                              mciGetDeviceID          [MMSYSTEM.703]
2096  */
2097 UINT16 WINAPI mciGetDeviceID(LPCSTR lpstrName)
2098 {
2099     UINT16 wDevID;
2100     
2101     TRACE(mmsys, "(\"%s\")\n", lpstrName);
2102
2103     if (!lpstrName)
2104         return 0;
2105     
2106     if (!lstrcmpi32A(lpstrName, "ALL"))
2107         return MCI_ALL_DEVICE_ID;
2108     
2109     wDevID = MMSYSTEM_FirstDevID();
2110     while (MMSYSTEM_DevIDValid(wDevID) && mciGetDrv(wDevID)->modp.wType) {
2111         if (mciGetOpenDrv(wDevID)->lpstrDeviceType && strcmp(mciGetOpenDrv(wDevID)->lpstrDeviceType, lpstrName) == 0)
2112             return wDevID;
2113         
2114         if (mciGetOpenDrv(wDevID)->lpstrAlias && strcmp(mciGetOpenDrv(wDevID)->lpstrAlias, lpstrName) == 0)
2115             return wDevID;
2116         
2117         wDevID = MMSYSTEM_NextDevID(wDevID);
2118     }
2119     
2120     return 0;
2121 }
2122
2123 /**************************************************************************
2124  *                              mciSetYieldProc         [MMSYSTEM.714]
2125  */
2126 BOOL16 WINAPI mciSetYieldProc (UINT16 uDeviceID, 
2127                                YIELDPROC fpYieldProc, DWORD dwYieldData)
2128 {
2129     return FALSE;
2130 }
2131
2132 /**************************************************************************
2133  *                              mciGetDeviceIDFromElementID     [MMSYSTEM.715]
2134  */
2135 UINT16 WINAPI mciGetDeviceIDFromElementID(DWORD dwElementID, LPCSTR lpstrType)
2136 {
2137     return 0;
2138 }
2139
2140 /**************************************************************************
2141  *                              mciGetYieldProc         [MMSYSTEM.716]
2142  */
2143 YIELDPROC WINAPI mciGetYieldProc(UINT16 uDeviceID, DWORD * lpdwYieldData)
2144 {
2145     return NULL;
2146 }
2147
2148 /**************************************************************************
2149  *                              mciGetCreatorTask       [MMSYSTEM.717]
2150  */
2151 HTASK16 WINAPI mciGetCreatorTask(UINT16 uDeviceID)
2152 {
2153     return 0;
2154 }
2155
2156 /**************************************************************************
2157  *                              midiOutGetNumDevs       [WINMM.80]
2158  */
2159 UINT32 WINAPI midiOutGetNumDevs32(void)
2160 {
2161     return midiOutGetNumDevs16();
2162 }
2163 /**************************************************************************
2164  *                              midiOutGetNumDevs       [MMSYSTEM.201]
2165  */
2166 UINT16 WINAPI midiOutGetNumDevs16(void)
2167 {
2168     UINT16      count = modMessage(0, MODM_GETNUMDEVS, 0L, 0L, 0L);
2169     TRACE(mmsys, "returns %u\n", count);
2170     return count;
2171 }
2172
2173 /**************************************************************************
2174  *                              midiOutGetDevCapsW      [WINMM.76]
2175  */
2176 UINT32 WINAPI midiOutGetDevCaps32W(UINT32 uDeviceID,LPMIDIOUTCAPS32W lpCaps, UINT32 uSize)
2177 {
2178     MIDIOUTCAPS16       moc16;
2179     UINT32              ret;
2180     
2181     ret = midiOutGetDevCaps16(uDeviceID,&moc16,sizeof(moc16));
2182     lpCaps->wMid                = moc16.wMid;
2183     lpCaps->wPid                = moc16.wPid;
2184     lpCaps->vDriverVersion      = moc16.vDriverVersion;
2185     lstrcpyAtoW(lpCaps->szPname,moc16.szPname);
2186     lpCaps->wTechnology = moc16.wTechnology;
2187     lpCaps->wVoices             = moc16.wVoices;
2188     lpCaps->wNotes              = moc16.wNotes;
2189     lpCaps->wChannelMask        = moc16.wChannelMask;
2190     lpCaps->dwSupport   = moc16.dwSupport;
2191     return ret;
2192 }
2193 /**************************************************************************
2194  *                              midiOutGetDevCapsA      [WINMM.75]
2195  */
2196 UINT32 WINAPI midiOutGetDevCaps32A(UINT32 uDeviceID,LPMIDIOUTCAPS32A lpCaps, UINT32 uSize)
2197 {
2198     MIDIOUTCAPS16       moc16;
2199     UINT32              ret;
2200     
2201     ret = midiOutGetDevCaps16(uDeviceID,&moc16,sizeof(moc16));
2202     lpCaps->wMid                = moc16.wMid;
2203     lpCaps->wPid                = moc16.wPid;
2204     lpCaps->vDriverVersion      = moc16.vDriverVersion;
2205     strcpy(lpCaps->szPname,moc16.szPname);
2206     lpCaps->wTechnology = moc16.wTechnology;
2207     lpCaps->wVoices             = moc16.wVoices;
2208     lpCaps->wNotes              = moc16.wNotes;
2209     lpCaps->wChannelMask        = moc16.wChannelMask;
2210     lpCaps->dwSupport   = moc16.dwSupport;
2211     return ret;
2212 }
2213
2214 /**************************************************************************
2215  *                              midiOutGetDevCaps       [MMSYSTEM.202]
2216  */
2217 UINT16 WINAPI midiOutGetDevCaps16(UINT16 uDeviceID,LPMIDIOUTCAPS16 lpCaps, UINT16 uSize)
2218 {
2219     TRACE(mmsys, "midiOutGetDevCaps\n");
2220     return modMessage(uDeviceID,MODM_GETDEVCAPS,0,(DWORD)lpCaps,uSize);
2221 }
2222
2223 /**************************************************************************
2224  *                              midiOutGetErrorTextA    [WINMM.77]
2225  */
2226 UINT32 WINAPI midiOutGetErrorText32A(UINT32 uError, LPSTR lpText, UINT32 uSize)
2227 {
2228     TRACE(mmsys, "midiOutGetErrorText\n");
2229     return midiGetErrorText(uError, lpText, uSize);
2230 }
2231
2232 /**************************************************************************
2233  *                              midiOutGetErrorTextW    [WINMM.78]
2234  */
2235 UINT32 WINAPI midiOutGetErrorText32W(UINT32 uError, LPWSTR lpText, UINT32 uSize)
2236 {
2237     LPSTR       xstr = HeapAlloc(GetProcessHeap(),0,uSize);
2238     UINT32      ret;
2239     
2240     TRACE(mmsys, "midiOutGetErrorText\n");
2241     ret = midiGetErrorText(uError, xstr, uSize);
2242     lstrcpyAtoW(lpText,xstr);
2243     HeapFree(GetProcessHeap(),0,xstr);
2244     return ret;
2245 }
2246
2247 /**************************************************************************
2248  *                              midiOutGetErrorText     [MMSYSTEM.203]
2249  */
2250 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
2251 {
2252     TRACE(mmsys, "midiOutGetErrorText\n");
2253     return midiGetErrorText(uError, lpText, uSize);
2254 }
2255
2256 /**************************************************************************
2257  *                              midiGetErrorText        [internal]
2258  */
2259 UINT16 WINAPI midiGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize)
2260 {
2261     LPSTR       msgptr;
2262     if ((lpText == NULL) || (uSize < 1)) return(FALSE);
2263     lpText[0] = '\0';
2264     switch (uError) {
2265     case MIDIERR_UNPREPARED:
2266         msgptr = "The MIDI header was not prepared. Use the Prepare function to prepare the header, and then try again.";
2267         break;
2268     case MIDIERR_STILLPLAYING:
2269         msgptr = "Cannot perform this operation while media data is still playing. Reset the device, or wait until the data is finished playing.";
2270         break;
2271     case MIDIERR_NOMAP:
2272         msgptr = "A MIDI map was not found. There may be a problem with the driver, or the MIDIMAP.CFG file may be corrupt or missing.";
2273         break;
2274     case MIDIERR_NOTREADY:
2275         msgptr = "The port is transmitting data to the device. Wait until the data has been transmitted, and then try again.";
2276         break;
2277     case MIDIERR_NODEVICE:
2278         msgptr = "The current MIDI Mapper setup refers to a MIDI device that is not installed on the system. Use MIDI Mapper to edit the setup.";
2279         break;
2280     case MIDIERR_INVALIDSETUP:
2281         msgptr = "The current MIDI setup is damaged. Copy the original MIDIMAP.CFG file to the Windows SYSTEM directory, and then try again.";
2282         break;
2283         /*
2284           msg# 336 : Cannot use the song-pointer time format and the SMPTE time-format together.
2285           msg# 337 : The specified MIDI device is already in use. Wait until it is free, and then try again.
2286           msg# 338 : The specified MIDI device is not installed on the system. Use the Drivers option in Control Panel to install the driver.
2287           msg# 339 : The current MIDI Mapper setup refers to a MIDI device that is not installed on the system. Use MIDI Mapper to edit the setup.
2288           msg# 340 : An error occurred using the specified port.
2289           msg# 341 : All multimedia timers are being used by other applications. Quit one of these applications, and then try again.
2290           msg# 342 : There is no current MIDI port.
2291           msg# 343 : There are no MIDI devices installed on the system. Use the Drivers option in Control Panel to install the driver.
2292         */
2293     default:
2294         msgptr = "Unknown MIDI Error !\n";
2295         break;
2296     }
2297     lstrcpyn32A(lpText, msgptr, uSize);
2298     return TRUE;
2299 }
2300
2301 /**************************************************************************
2302  *                              midiOutOpen             [WINM.84]
2303  */
2304 UINT32 WINAPI midiOutOpen32(HMIDIOUT32 * lphMidiOut, UINT32 uDeviceID,
2305                             DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
2306 {
2307     HMIDIOUT16  hmo16;
2308     UINT32      ret;
2309     
2310     ret = midiOutOpen16(&hmo16,uDeviceID,dwCallback,dwInstance,
2311                         CALLBACK32CONV(dwFlags));
2312     if (lphMidiOut) *lphMidiOut = hmo16;
2313     return ret;
2314 }
2315
2316 /**************************************************************************
2317  *                              midiOutOpen             [MMSYSTEM.204]
2318  */
2319 UINT16 WINAPI midiOutOpen16(HMIDIOUT16 * lphMidiOut, UINT16 uDeviceID,
2320                             DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
2321 {
2322     HMIDI16                     hMidiOut;
2323     LPMIDIOPENDESC              lpDesc;
2324     DWORD                       dwRet = 0;
2325     BOOL32                      bMapperFlg = FALSE;
2326     
2327     if (lphMidiOut != NULL) *lphMidiOut = 0;
2328     TRACE(mmsys, "(%p, %d, %08lX, %08lX, %08lX);\n", 
2329           lphMidiOut, uDeviceID, dwCallback, dwInstance, dwFlags);
2330     if (uDeviceID == (UINT16)MIDI_MAPPER) {
2331         TRACE(mmsys, "MIDI_MAPPER mode requested !\n");
2332         bMapperFlg = TRUE;
2333         uDeviceID = 0;
2334     }
2335     hMidiOut = USER_HEAP_ALLOC(sizeof(MIDIOPENDESC));
2336     if (lphMidiOut != NULL) 
2337         *lphMidiOut = hMidiOut;
2338     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2339     if (lpDesc == NULL)
2340         return MMSYSERR_NOMEM;
2341     lpDesc->hMidi = hMidiOut;
2342     lpDesc->dwCallback = dwCallback;
2343     lpDesc->dwInstance = dwInstance;
2344     
2345     while (uDeviceID < MAXMIDIDRIVERS) {
2346         dwRet = modMessage(uDeviceID, MODM_OPEN, 
2347                            lpDesc->dwInstance, (DWORD)lpDesc, dwFlags);
2348         if (dwRet == MMSYSERR_NOERROR) break;
2349         if (!bMapperFlg) break;
2350         uDeviceID++;
2351         TRACE(mmsys, "MIDI_MAPPER mode ! try next driver...\n");
2352     }
2353     lpDesc->wDevID = uDeviceID;
2354     return dwRet;
2355 }
2356
2357 /**************************************************************************
2358  *                              midiOutClose            [WINMM.74]
2359  */
2360 UINT32 WINAPI midiOutClose32(HMIDIOUT32 hMidiOut)
2361 {
2362     return midiOutClose16(hMidiOut);
2363 }
2364
2365 /**************************************************************************
2366  *                              midiOutClose            [MMSYSTEM.205]
2367  */
2368 UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
2369 {
2370     LPMIDIOPENDESC      lpDesc;
2371     TRACE(mmsys, "(%04X)\n", hMidiOut);
2372     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2373     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2374     return modMessage(lpDesc->wDevID, MODM_CLOSE, lpDesc->dwInstance, 0L, 0L);
2375 }
2376
2377 /**************************************************************************
2378  *                              midiOutPrepareHeader    [WINMM.85]
2379  */
2380 UINT32 WINAPI midiOutPrepareHeader32(HMIDIOUT32 hMidiOut,
2381                                      MIDIHDR * lpMidiOutHdr, UINT32 uSize)
2382 {
2383     LPMIDIOPENDESC      lpDesc;
2384     TRACE(mmsys, "(%04X, %p, %d)\n", 
2385           hMidiOut, lpMidiOutHdr, uSize);
2386     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2387     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2388     lpMidiOutHdr->reserved = (DWORD)lpMidiOutHdr->lpData;
2389     return modMessage(lpDesc->wDevID, MODM_PREPARE, lpDesc->dwInstance, 
2390                       (DWORD)lpMidiOutHdr, (DWORD)uSize);
2391 }
2392
2393 /**************************************************************************
2394  *                              midiOutPrepareHeader    [MMSYSTEM.206]
2395  */
2396 UINT16 WINAPI midiOutPrepareHeader16(HMIDIOUT16 hMidiOut,
2397                                      MIDIHDR * lpMidiOutHdr, UINT16 uSize)
2398 {
2399     LPMIDIOPENDESC      lpDesc;
2400     TRACE(mmsys, "(%04X, %p, %d)\n", 
2401           hMidiOut, lpMidiOutHdr, uSize);
2402     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2403     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2404     lpMidiOutHdr->reserved = (DWORD)PTR_SEG_TO_LIN(lpMidiOutHdr->lpData);
2405     return modMessage(lpDesc->wDevID, MODM_PREPARE, lpDesc->dwInstance, 
2406                       (DWORD)lpMidiOutHdr, (DWORD)uSize);
2407 }
2408
2409 /**************************************************************************
2410  *                              midiOutUnprepareHeader  [WINMM.89]
2411  */
2412 UINT32 WINAPI midiOutUnprepareHeader32(HMIDIOUT32 hMidiOut,
2413                                        MIDIHDR * lpMidiOutHdr, UINT32 uSize)
2414 {
2415     return midiOutUnprepareHeader16(hMidiOut,lpMidiOutHdr,uSize);
2416 }
2417
2418 /**************************************************************************
2419  *                              midiOutUnprepareHeader  [MMSYSTEM.207]
2420  */
2421 UINT16 WINAPI midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut,
2422                                        MIDIHDR * lpMidiOutHdr, UINT16 uSize)
2423 {
2424     LPMIDIOPENDESC      lpDesc;
2425     TRACE(mmsys, "(%04X, %p, %d)\n", 
2426           hMidiOut, lpMidiOutHdr, uSize);
2427     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2428     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2429     return modMessage(lpDesc->wDevID, MODM_UNPREPARE, lpDesc->dwInstance, 
2430                       (DWORD)lpMidiOutHdr, (DWORD)uSize);
2431 }
2432
2433 /**************************************************************************
2434  *                              midiOutShortMsg         [WINMM.88]
2435  */
2436 UINT32 WINAPI midiOutShortMsg32(HMIDIOUT32 hMidiOut, DWORD dwMsg)
2437 {
2438     return midiOutShortMsg16(hMidiOut,dwMsg);
2439 }
2440
2441 /**************************************************************************
2442  *                              midiOutShortMsg         [MMSYSTEM.208]
2443  */
2444 UINT16 WINAPI midiOutShortMsg16(HMIDIOUT16 hMidiOut, DWORD dwMsg)
2445 {
2446     LPMIDIOPENDESC      lpDesc;
2447     TRACE(mmsys, "(%04X, %08lX)\n", hMidiOut, dwMsg);
2448     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2449     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2450     return modMessage(lpDesc->wDevID, MODM_DATA, lpDesc->dwInstance, dwMsg, 0L);
2451 }
2452
2453 /**************************************************************************
2454  *                              midiOutLongMsg          [WINMM.82]
2455  */
2456 UINT32 WINAPI midiOutLongMsg32(HMIDIOUT32 hMidiOut,
2457                                MIDIHDR * lpMidiOutHdr, UINT32 uSize)
2458 {
2459     return midiOutLongMsg16(hMidiOut,lpMidiOutHdr,uSize);
2460 }
2461
2462 /**************************************************************************
2463  *                              midiOutLongMsg          [MMSYSTEM.209]
2464  */
2465 UINT16 WINAPI midiOutLongMsg16(HMIDIOUT16 hMidiOut,
2466                                MIDIHDR * lpMidiOutHdr, UINT16 uSize)
2467 {
2468     LPMIDIOPENDESC      lpDesc;
2469     TRACE(mmsys, "(%04X, %p, %d)\n", 
2470           hMidiOut, lpMidiOutHdr, uSize);
2471     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2472     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2473     return modMessage(lpDesc->wDevID, MODM_LONGDATA, lpDesc->dwInstance, 
2474                       (DWORD)lpMidiOutHdr, (DWORD)uSize);
2475 }
2476
2477 /**************************************************************************
2478  *                              midiOutReset            [WINMM.86]
2479  */
2480 UINT32 WINAPI midiOutReset32(HMIDIOUT32 hMidiOut)
2481 {
2482     return midiOutReset16(hMidiOut);
2483 }
2484
2485 /**************************************************************************
2486  *                              midiOutReset            [MMSYSTEM.210]
2487  */
2488 UINT16 WINAPI midiOutReset16(HMIDIOUT16 hMidiOut)
2489 {
2490     LPMIDIOPENDESC      lpDesc;
2491     TRACE(mmsys, "(%04X)\n", hMidiOut);
2492     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2493     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2494     return modMessage(lpDesc->wDevID, MODM_RESET, lpDesc->dwInstance, 0L, 0L);
2495 }
2496
2497 /**************************************************************************
2498  *                              midiOutGetVolume        [WINM.81]
2499  */
2500 UINT32 WINAPI midiOutGetVolume32(UINT32 uDeviceID, DWORD * lpdwVolume)
2501 {
2502     return midiOutGetVolume16(uDeviceID,lpdwVolume);
2503 }
2504 /**************************************************************************
2505  *                              midiOutGetVolume        [MMSYSTEM.211]
2506  */
2507 UINT16 WINAPI midiOutGetVolume16(UINT16 uDeviceID, DWORD * lpdwVolume)
2508 {
2509     TRACE(mmsys, "(%04X, %p);\n", uDeviceID, lpdwVolume);
2510     return modMessage(uDeviceID, MODM_GETVOLUME, 0L, (DWORD)lpdwVolume, 0L);
2511 }
2512
2513 /**************************************************************************
2514  *                              midiOutSetVolume        [WINMM.87]
2515  */
2516 UINT32 WINAPI midiOutSetVolume32(UINT32 uDeviceID, DWORD dwVolume)
2517 {
2518     return midiOutSetVolume16(uDeviceID,dwVolume);
2519 }
2520
2521 /**************************************************************************
2522  *                              midiOutSetVolume        [MMSYSTEM.212]
2523  */
2524 UINT16 WINAPI midiOutSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
2525 {
2526     TRACE(mmsys, "(%04X, %08lX);\n", uDeviceID, dwVolume);
2527     return modMessage(uDeviceID, MODM_SETVOLUME, 0L, dwVolume, 0L);
2528 }
2529
2530 /**************************************************************************
2531  *                              midiOutCachePatches             [WINMM.73]
2532  */
2533 UINT32 WINAPI midiOutCachePatches32(HMIDIOUT32 hMidiOut, UINT32 uBank,
2534                                     WORD * lpwPatchArray, UINT32 uFlags)
2535 {
2536     return midiOutCachePatches16(hMidiOut,uBank,lpwPatchArray,uFlags);
2537 }
2538
2539 /**************************************************************************
2540  *                              midiOutCachePatches             [MMSYSTEM.213]
2541  */
2542 UINT16 WINAPI midiOutCachePatches16(HMIDIOUT16 hMidiOut, UINT16 uBank,
2543                                     WORD * lpwPatchArray, UINT16 uFlags)
2544 {
2545     /* not really necessary to support this */
2546     FIXME(mmsys, "not supported yet\n");
2547     return MMSYSERR_NOTSUPPORTED;
2548 }
2549
2550 /**************************************************************************
2551  *                              midiOutCacheDrumPatches [WINMM.72]
2552  */
2553 UINT32 WINAPI midiOutCacheDrumPatches32(HMIDIOUT32 hMidiOut, UINT32 uPatch,
2554                                         WORD * lpwKeyArray, UINT32 uFlags)
2555 {
2556     return midiOutCacheDrumPatches16(hMidiOut,uPatch,lpwKeyArray,uFlags);
2557 }
2558
2559 /**************************************************************************
2560  *                              midiOutCacheDrumPatches [MMSYSTEM.214]
2561  */
2562 UINT16 WINAPI midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut, UINT16 uPatch,
2563                                         WORD * lpwKeyArray, UINT16 uFlags)
2564 {
2565     FIXME(mmsys, "not supported yet\n");
2566     return MMSYSERR_NOTSUPPORTED;
2567 }
2568
2569 /**************************************************************************
2570  *                              midiOutGetID            [WINMM.79]
2571  */
2572 UINT32 WINAPI midiOutGetID32(HMIDIOUT32 hMidiOut, UINT32 * lpuDeviceID)
2573 {
2574     UINT16      xid;
2575     UINT32      ret;
2576     
2577     ret = midiOutGetID16(hMidiOut,&xid);
2578     *lpuDeviceID = xid;
2579     return ret;
2580 }
2581
2582 /**************************************************************************
2583  *                              midiOutGetID            [MMSYSTEM.215]
2584  */
2585 UINT16 WINAPI midiOutGetID16(HMIDIOUT16 hMidiOut, UINT16 * lpuDeviceID)
2586 {
2587     TRACE(mmsys, "midiOutGetID\n");
2588     return 0;
2589 }
2590
2591 /**************************************************************************
2592  *                              midiOutMessage          [WINMM.83]
2593  */
2594 DWORD WINAPI midiOutMessage32(HMIDIOUT32 hMidiOut, UINT32 uMessage, 
2595                               DWORD dwParam1, DWORD dwParam2)
2596 {
2597     LPMIDIOPENDESC      lpDesc;
2598     
2599     TRACE(mmsys, "(%04X, %04X, %08lX, %08lX)\n", 
2600           hMidiOut, uMessage, dwParam1, dwParam2);
2601     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2602     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2603     switch (uMessage) {
2604     case MODM_OPEN:
2605         FIXME(mmsys,"can't handle MODM_OPEN!\n");
2606         return 0;
2607     case MODM_GETDEVCAPS:
2608         return midiOutGetDevCaps32A(hMidiOut,(LPMIDIOUTCAPS32A)dwParam1,dwParam2);
2609     case MODM_GETNUMDEVS:
2610     case MODM_RESET:
2611     case MODM_CLOSE:
2612     case MODM_GETVOLUME:
2613     case MODM_SETVOLUME:
2614     case MODM_LONGDATA:
2615     case MODM_PREPARE:
2616     case MODM_UNPREPARE:
2617         /* no argument conversion needed */
2618         break;
2619     default:
2620         ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
2621             hMidiOut,uMessage,dwParam1,dwParam2);
2622         break;
2623     }
2624     return modMessage(lpDesc->wDevID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
2625 }
2626
2627 /**************************************************************************
2628  *                              midiOutMessage          [MMSYSTEM.216]
2629  */
2630 DWORD WINAPI midiOutMessage16(HMIDIOUT16 hMidiOut, UINT16 uMessage, 
2631                               DWORD dwParam1, DWORD dwParam2)
2632 {
2633     LPMIDIOPENDESC      lpDesc;
2634     
2635     TRACE(mmsys, "(%04X, %04X, %08lX, %08lX)\n", 
2636           hMidiOut, uMessage, dwParam1, dwParam2);
2637     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2638     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2639     switch (uMessage) {
2640     case MODM_OPEN:
2641         FIXME(mmsys,"can't handle MODM_OPEN!\n");
2642         return 0;
2643     case MODM_GETNUMDEVS:
2644     case MODM_RESET:
2645     case MODM_CLOSE:
2646     case MODM_SETVOLUME:
2647         /* no argument conversion needed */
2648         break;
2649     case MODM_GETVOLUME:
2650         return midiOutGetVolume16(hMidiOut,(LPDWORD)PTR_SEG_TO_LIN(dwParam1));
2651     case MODM_LONGDATA:
2652         return midiOutLongMsg16(hMidiOut,(LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
2653     case MODM_PREPARE:
2654         return midiOutPrepareHeader16(hMidiOut,(LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
2655     case MODM_UNPREPARE:
2656         return midiOutUnprepareHeader16(hMidiOut,(LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
2657     default:
2658         ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
2659             hMidiOut,uMessage,dwParam1,dwParam2);
2660         break;
2661     }
2662     return modMessage(lpDesc->wDevID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
2663 }
2664
2665 /**************************************************************************
2666  *                              midiInGetNumDevs        [WINMM.64]
2667  */
2668 UINT32 WINAPI midiInGetNumDevs32(void)
2669 {
2670     return midiInGetNumDevs16();
2671 }
2672
2673 /**************************************************************************
2674  *                              midiInGetNumDevs        [MMSYSTEM.301]
2675  */
2676 UINT16 WINAPI midiInGetNumDevs16(void)
2677 {
2678     UINT16      count = 0;
2679     TRACE(mmsys, "midiInGetNumDevs\n");
2680     count += midMessage(0, MIDM_GETNUMDEVS, 0L, 0L, 0L);
2681     TRACE(mmsys, "midiInGetNumDevs return %u \n", count);
2682     return count;
2683 }
2684
2685 /**************************************************************************
2686  *                              midiInGetDevCaps        [WINMM.60]
2687  */
2688 UINT32 WINAPI midiInGetDevCaps32W(UINT32 uDeviceID,
2689                                   LPMIDIINCAPS32W lpCaps, UINT32 uSize)
2690 {
2691     MIDIINCAPS16        mic16;
2692     UINT32              ret = midiInGetDevCaps16(uDeviceID,&mic16,uSize);
2693     
2694     lpCaps->wMid = mic16.wMid;
2695     lpCaps->wPid = mic16.wPid;
2696     lpCaps->vDriverVersion = mic16.vDriverVersion;
2697     lstrcpyAtoW(lpCaps->szPname,mic16.szPname);
2698     lpCaps->dwSupport = mic16.dwSupport;
2699     return ret;
2700 }
2701
2702 /**************************************************************************
2703  *                              midiInGetDevCaps        [WINMM.59]
2704  */
2705 UINT32 WINAPI midiInGetDevCaps32A(UINT32 uDeviceID,
2706                                   LPMIDIINCAPS32A lpCaps, UINT32 uSize)
2707 {
2708     MIDIINCAPS16        mic16;
2709     UINT32              ret = midiInGetDevCaps16(uDeviceID,&mic16,uSize);
2710     
2711     lpCaps->wMid = mic16.wMid;
2712     lpCaps->wPid = mic16.wPid;
2713     lpCaps->vDriverVersion = mic16.vDriverVersion;
2714     strcpy(lpCaps->szPname,mic16.szPname);
2715     lpCaps->dwSupport = mic16.dwSupport;
2716     return ret;
2717 }
2718
2719 /**************************************************************************
2720  *                              midiInGetDevCaps        [MMSYSTEM.302]
2721  */
2722 UINT16 WINAPI midiInGetDevCaps16(UINT16 uDeviceID,
2723                                  LPMIDIINCAPS16 lpCaps, UINT16 uSize)
2724 {
2725     TRACE(mmsys, "midiInGetDevCaps\n");
2726     return midMessage(uDeviceID,MIDM_GETDEVCAPS,0,(DWORD)lpCaps,uSize);;
2727 }
2728
2729 /**************************************************************************
2730  *                              midiInGetErrorText              [WINMM.62]
2731  */
2732 UINT32 WINAPI midiInGetErrorText32W(UINT32 uError, LPWSTR lpText, UINT32 uSize)
2733 {
2734     LPSTR       xstr = HeapAlloc(GetProcessHeap(),0,uSize);
2735     UINT32      ret = midiInGetErrorText16(uError,xstr,uSize);
2736     lstrcpyAtoW(lpText,xstr);
2737     HeapFree(GetProcessHeap(),0,xstr);
2738     return ret;
2739 }
2740 /**************************************************************************
2741  *                              midiInGetErrorText              [WINMM.61]
2742  */
2743 UINT32 WINAPI midiInGetErrorText32A(UINT32 uError, LPSTR lpText, UINT32 uSize)
2744 {
2745     return midiInGetErrorText16(uError,lpText,uSize);
2746 }
2747
2748 /**************************************************************************
2749  *                              midiInGetErrorText              [MMSYSTEM.303]
2750  */
2751 UINT16 WINAPI midiInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
2752 {
2753     TRACE(mmsys, "midiInGetErrorText\n");
2754     return (midiGetErrorText(uError, lpText, uSize));
2755 }
2756
2757 /**************************************************************************
2758  *                              midiInOpen              [WINMM.66]
2759  */
2760 UINT32 WINAPI midiInOpen32(HMIDIIN32 * lphMidiIn, UINT32 uDeviceID,
2761                            DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
2762 {
2763     HMIDIIN16   xhmid16;
2764     UINT32              ret = midiInOpen16(&xhmid16,uDeviceID,dwCallback,dwInstance,
2765                                            CALLBACK32CONV(dwFlags));
2766     if (lphMidiIn) 
2767         *lphMidiIn = xhmid16;
2768     return ret;
2769 }
2770
2771 /**************************************************************************
2772  *                              midiInOpen              [MMSYSTEM.304]
2773  */
2774 UINT16 WINAPI midiInOpen16(HMIDIIN16 * lphMidiIn, UINT16 uDeviceID,
2775                            DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
2776 {
2777     HMIDI16                     hMidiIn;
2778     LPMIDIOPENDESC              lpDesc;
2779     DWORD                       dwRet = 0;
2780     BOOL32                      bMapperFlg = FALSE;
2781     
2782     if (lphMidiIn != NULL) 
2783         *lphMidiIn = 0;
2784     TRACE(mmsys, "(%p, %d, %08lX, %08lX, %08lX);\n", 
2785           lphMidiIn, uDeviceID, dwCallback, dwInstance, dwFlags);
2786     if (uDeviceID == (UINT16)MIDI_MAPPER) {
2787         TRACE(mmsys, "MIDI_MAPPER mode requested !\n");
2788         bMapperFlg = TRUE;
2789         uDeviceID = 0;
2790     }
2791     hMidiIn = USER_HEAP_ALLOC(sizeof(MIDIOPENDESC));
2792     if (lphMidiIn != NULL) 
2793         *lphMidiIn = hMidiIn;
2794     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2795     if (lpDesc == NULL) 
2796         return MMSYSERR_NOMEM;
2797     lpDesc->hMidi = hMidiIn;
2798     lpDesc->dwCallback = dwCallback;
2799     lpDesc->dwInstance = dwInstance;
2800     
2801     while (uDeviceID < MAXMIDIDRIVERS) {
2802         dwRet = midMessage(uDeviceID, MIDM_OPEN, 
2803                            lpDesc->dwInstance, (DWORD)lpDesc, dwFlags);
2804         if (dwRet == MMSYSERR_NOERROR) 
2805             break;
2806         if (!bMapperFlg) 
2807             break;
2808         uDeviceID++;
2809         TRACE(mmsys, "MIDI_MAPPER mode ! try next driver...\n");
2810     }
2811     lpDesc->wDevID = uDeviceID;
2812     return dwRet;
2813 }
2814
2815 /**************************************************************************
2816  *                              midiInClose             [WINMM.58]
2817  */
2818 UINT32 WINAPI midiInClose32(HMIDIIN32 hMidiIn)
2819 {
2820     return midiInClose16(hMidiIn);
2821 }
2822
2823 /**************************************************************************
2824  *                              midiInClose             [MMSYSTEM.305]
2825  */
2826 UINT16 WINAPI midiInClose16(HMIDIIN16 hMidiIn)
2827 {
2828     LPMIDIOPENDESC      lpDesc;
2829     TRACE(mmsys, "(%04X)\n", hMidiIn);
2830     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2831     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2832     return midMessage(lpDesc->wDevID, MIDM_CLOSE, lpDesc->dwInstance, 0L, 0L);
2833 }
2834
2835 /**************************************************************************
2836  *                              midiInPrepareHeader     [WINMM.67]
2837  */
2838 UINT32 WINAPI midiInPrepareHeader32(HMIDIIN32 hMidiIn,
2839                                     MIDIHDR * lpMidiInHdr, UINT32 uSize)
2840 {
2841     LPMIDIOPENDESC      lpDesc;
2842     
2843     TRACE(mmsys, "(%04X, %p, %d)\n", 
2844           hMidiIn, lpMidiInHdr, uSize);
2845     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2846     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2847     lpMidiInHdr->reserved = (DWORD)lpMidiInHdr->lpData;
2848     return midMessage(lpDesc->wDevID, MIDM_PREPARE, lpDesc->dwInstance, 
2849                       (DWORD)lpMidiInHdr, (DWORD)uSize);
2850 }
2851
2852 /**************************************************************************
2853  *                              midiInPrepareHeader     [MMSYSTEM.306]
2854  */
2855 UINT16 WINAPI midiInPrepareHeader16(HMIDIIN16 hMidiIn,
2856                                     MIDIHDR * lpMidiInHdr, UINT16 uSize)
2857 {
2858     LPMIDIOPENDESC      lpDesc;
2859     
2860     TRACE(mmsys, "(%04X, %p, %d)\n", 
2861           hMidiIn, lpMidiInHdr, uSize);
2862     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2863     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2864     lpMidiInHdr->reserved = (DWORD)PTR_SEG_TO_LIN(lpMidiInHdr->lpData);
2865     return midMessage(lpDesc->wDevID, MIDM_PREPARE, lpDesc->dwInstance, 
2866                       (DWORD)lpMidiInHdr, (DWORD)uSize);
2867 }
2868
2869 /**************************************************************************
2870  *                              midiInUnprepareHeader   [WINMM.71]
2871  */
2872 UINT32 WINAPI midiInUnprepareHeader32(HMIDIIN32 hMidiIn,
2873                                       MIDIHDR * lpMidiInHdr, UINT32 uSize)
2874 {
2875     return midiInUnprepareHeader16(hMidiIn,lpMidiInHdr,uSize);
2876 }
2877
2878 /**************************************************************************
2879  *                              midiInUnprepareHeader   [MMSYSTEM.307]
2880  */
2881 UINT16 WINAPI midiInUnprepareHeader16(HMIDIIN16 hMidiIn,
2882                                       MIDIHDR * lpMidiInHdr, UINT16 uSize)
2883 {
2884     LPMIDIOPENDESC      lpDesc;
2885     TRACE(mmsys, "(%04X, %p, %d)\n", 
2886           hMidiIn, lpMidiInHdr, uSize);
2887     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2888     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2889     return midMessage(lpDesc->wDevID, MIDM_UNPREPARE, lpDesc->dwInstance, 
2890                       (DWORD)lpMidiInHdr, (DWORD)uSize);
2891 }
2892
2893 /**************************************************************************
2894  *                              midiInAddBuffer         [WINMM.57]
2895  */
2896 UINT32 WINAPI midiInAddBuffer32(HMIDIIN32 hMidiIn,
2897                                 MIDIHDR * lpMidiInHdr, UINT32 uSize)
2898 {
2899     return midiInAddBuffer16(hMidiIn,lpMidiInHdr,uSize);
2900 }
2901
2902 /**************************************************************************
2903  *                              midiInAddBuffer         [MMSYSTEM.308]
2904  */
2905 UINT16 WINAPI midiInAddBuffer16(HMIDIIN16 hMidiIn,
2906                                 MIDIHDR * lpMidiInHdr, UINT16 uSize)
2907 {
2908     TRACE(mmsys, "midiInAddBuffer\n");
2909     return 0;
2910 }
2911
2912 /**************************************************************************
2913  *                              midiInStart                     [WINMM.69]
2914  */
2915 UINT32 WINAPI midiInStart32(HMIDIIN32 hMidiIn)
2916 {
2917     return midiInStart16(hMidiIn);
2918 }
2919
2920 /**************************************************************************
2921  *                              midiInStart                     [MMSYSTEM.309]
2922  */
2923 UINT16 WINAPI midiInStart16(HMIDIIN16 hMidiIn)
2924 {
2925     LPMIDIOPENDESC      lpDesc;
2926     
2927     TRACE(mmsys, "(%04X)\n", hMidiIn);
2928     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2929     if (lpDesc == NULL) 
2930         return MMSYSERR_INVALHANDLE;
2931     return midMessage(lpDesc->wDevID, MIDM_START, lpDesc->dwInstance, 0L, 0L);
2932 }
2933
2934 /**************************************************************************
2935  *                              midiInStop                      [WINMM.70]
2936  */
2937 UINT32 WINAPI midiInStop32(HMIDIIN32 hMidiIn)
2938 {
2939     return midiInStop16(hMidiIn);
2940 }
2941
2942 /**************************************************************************
2943  *                              midiInStop                      [MMSYSTEM.310]
2944  */
2945 UINT16 WINAPI midiInStop16(HMIDIIN16 hMidiIn)
2946 {
2947     LPMIDIOPENDESC      lpDesc;
2948     
2949     TRACE(mmsys, "(%04X)\n", hMidiIn);
2950     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2951     if (lpDesc == NULL) 
2952         return MMSYSERR_INVALHANDLE;
2953     return midMessage(lpDesc->wDevID, MIDM_STOP, lpDesc->dwInstance, 0L, 0L);
2954 }
2955
2956 /**************************************************************************
2957  *                              midiInReset                     [WINMM.68]
2958  */
2959 UINT32 WINAPI midiInReset32(HMIDIIN32 hMidiIn)
2960 {
2961     return midiInReset16(hMidiIn);
2962 }
2963
2964 /**************************************************************************
2965  *                              midiInReset                     [MMSYSTEM.311]
2966  */
2967 UINT16 WINAPI midiInReset16(HMIDIIN16 hMidiIn)
2968 {
2969     LPMIDIOPENDESC      lpDesc;
2970     
2971     TRACE(mmsys, "(%04X)\n", hMidiIn);
2972     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2973     if (lpDesc == NULL) 
2974         return MMSYSERR_INVALHANDLE;
2975     return midMessage(lpDesc->wDevID, MIDM_RESET, lpDesc->dwInstance, 0L, 0L);
2976 }
2977
2978 /**************************************************************************
2979  *                              midiInGetID                     [WINMM.63]
2980  */
2981 UINT32 WINAPI midiInGetID32(HMIDIIN32 hMidiIn, UINT32* lpuDeviceID)
2982 {
2983     LPMIDIOPENDESC      lpDesc;
2984     
2985     TRACE(mmsys, "(%04X, %p)\n", hMidiIn, lpuDeviceID);
2986     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2987     if (lpDesc == NULL) 
2988         return MMSYSERR_INVALHANDLE;
2989     if (lpuDeviceID == NULL) 
2990         return MMSYSERR_INVALPARAM;
2991     *lpuDeviceID = lpDesc->wDevID;
2992     
2993     return MMSYSERR_NOERROR;
2994 }
2995
2996 /**************************************************************************
2997  *                              midiInGetID                     [MMSYSTEM.312]
2998  */
2999 UINT16 WINAPI midiInGetID16(HMIDIIN16 hMidiIn, UINT16* lpuDeviceID)
3000 {
3001     LPMIDIOPENDESC      lpDesc;
3002     
3003     TRACE(mmsys, "(%04X, %p)\n", hMidiIn, lpuDeviceID);
3004     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
3005     if (lpDesc == NULL) 
3006         return MMSYSERR_INVALHANDLE;
3007     if (lpuDeviceID == NULL) 
3008         return MMSYSERR_INVALPARAM;
3009     *lpuDeviceID = lpDesc->wDevID;
3010     
3011     return MMSYSERR_NOERROR;
3012 }
3013
3014 /**************************************************************************
3015  *                              midiInMessage           [WINMM.65]
3016  */
3017 DWORD WINAPI midiInMessage32(HMIDIIN32 hMidiIn, UINT32 uMessage, 
3018                              DWORD dwParam1, DWORD dwParam2)
3019 {
3020     LPMIDIOPENDESC      lpDesc;
3021     
3022     TRACE(mmsys, "(%04X, %04X, %08lX, %08lX)\n", 
3023           hMidiIn, uMessage, dwParam1, dwParam2);
3024     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
3025     if (lpDesc == NULL) 
3026         return MMSYSERR_INVALHANDLE;
3027     
3028     switch (uMessage) {
3029     case MIDM_OPEN:
3030         FIXME(mmsys,"can't handle MIDM_OPEN!\n");
3031         return 0;
3032     case MIDM_GETDEVCAPS:
3033         return midiInGetDevCaps32A(hMidiIn,(LPMIDIINCAPS32A)dwParam1,dwParam2);
3034     case MIDM_GETNUMDEVS:
3035     case MIDM_RESET:
3036     case MIDM_STOP:
3037     case MIDM_START:
3038     case MIDM_CLOSE:
3039         /* no argument conversion needed */
3040         break;
3041     case MIDM_PREPARE:
3042         return midiInPrepareHeader32(hMidiIn,(LPMIDIHDR)dwParam1,dwParam2);
3043     case MIDM_UNPREPARE:
3044         return midiInUnprepareHeader32(hMidiIn,(LPMIDIHDR)dwParam1,dwParam2);
3045     case MIDM_ADDBUFFER:
3046         return midiInAddBuffer32(hMidiIn,(LPMIDIHDR)dwParam1,dwParam2);
3047     default:
3048         ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
3049             hMidiIn,uMessage,dwParam1,dwParam2);
3050         break;
3051     }
3052     return midMessage(0, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
3053 }
3054
3055 /**************************************************************************
3056  *                              midiInMessage           [MMSYSTEM.313]
3057  */
3058 DWORD WINAPI midiInMessage16(HMIDIIN16 hMidiIn, UINT16 uMessage, 
3059                              DWORD dwParam1, DWORD dwParam2)
3060 {
3061     LPMIDIOPENDESC      lpDesc;
3062     TRACE(mmsys, "(%04X, %04X, %08lX, %08lX)\n", 
3063           hMidiIn, uMessage, dwParam1, dwParam2);
3064     lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
3065     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3066     switch (uMessage) {
3067     case MIDM_OPEN:
3068         WARN(mmsys,"can't handle MIDM_OPEN!\n");
3069         return 0;
3070     case MIDM_GETDEVCAPS:
3071         return midiInGetDevCaps16(hMidiIn,(LPMIDIINCAPS16)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3072     case MIDM_GETNUMDEVS:
3073     case MIDM_RESET:
3074     case MIDM_STOP:
3075     case MIDM_START:
3076     case MIDM_CLOSE:
3077         /* no argument conversion needed */
3078         break;
3079     case MIDM_PREPARE:
3080         return midiInPrepareHeader16(hMidiIn,(LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3081     case MIDM_UNPREPARE:
3082         return midiInUnprepareHeader16(hMidiIn,(LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3083     case MIDM_ADDBUFFER:
3084         return midiInAddBuffer16(hMidiIn,(LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3085     default:
3086         ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
3087             hMidiIn,uMessage,dwParam1,dwParam2);
3088         break;
3089     }
3090     return midMessage(0, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
3091 }
3092
3093 /**************************************************************************
3094  *                              midiStreamOpen          [MMSYSTEM.91]
3095  */
3096 MMRESULT32 WINAPI midiStreamOpen32(HMIDISTRM32 *phms,LPUINT32 devid,DWORD cMidi,DWORD dwCallback,DWORD dwInstance,DWORD fdwOpen) {
3097         FIXME(midi,"(%p,%p,%d,%p,%p,0x%08lx),stub!\n",phms,devid,cMidi,dwCallback,dwInstance,fdwOpen);
3098         return MMSYSERR_NOTSUPPORTED;
3099 }
3100
3101
3102 /**************************************************************************
3103  *                              waveOutGetNumDevs               [MMSYSTEM.401]
3104  */
3105 UINT32 WINAPI waveOutGetNumDevs32() {
3106     return waveOutGetNumDevs16();
3107 }
3108
3109 /**************************************************************************
3110  *                              waveOutGetNumDevs               [WINMM.167]
3111  */
3112 UINT16 WINAPI waveOutGetNumDevs16()
3113 {
3114     UINT16      count = 0;
3115     TRACE(mmsys, "waveOutGetNumDevs\n");
3116     count += wodMessage( MMSYSTEM_FirstDevID(), WODM_GETNUMDEVS, 0L, 0L, 0L);
3117     TRACE(mmsys, "waveOutGetNumDevs return %u \n", count);
3118     return count;
3119 }
3120
3121 /**************************************************************************
3122  *                              waveOutGetDevCaps               [MMSYSTEM.402]
3123  */
3124 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID, WAVEOUTCAPS16 * lpCaps,
3125                                   UINT16 uSize)
3126 {
3127     if (uDeviceID > waveOutGetNumDevs16() - 1) return MMSYSERR_BADDEVICEID;
3128     if (uDeviceID == (UINT16)WAVE_MAPPER) return MMSYSERR_BADDEVICEID; /* FIXME: do we have a wave mapper ? */
3129     TRACE(mmsys, "waveOutGetDevCaps\n");
3130     return wodMessage(uDeviceID, WODM_GETDEVCAPS, 0L, (DWORD)lpCaps, uSize);
3131 }
3132
3133 /**************************************************************************
3134  *                              waveOutGetDevCapsA              [WINMM.162]
3135  */
3136 UINT32 WINAPI waveOutGetDevCaps32A(UINT32 uDeviceID, LPWAVEOUTCAPS32A lpCaps,
3137                                    UINT32 uSize)
3138 {
3139     WAVEOUTCAPS16       woc16;
3140     UINT16 ret = waveOutGetDevCaps16(uDeviceID,&woc16,sizeof(woc16));
3141     
3142     lpCaps->wMid = woc16.wMid;
3143     lpCaps->wPid = woc16.wPid;
3144     lpCaps->vDriverVersion = woc16.vDriverVersion;
3145     strcpy(lpCaps->szPname,woc16.szPname);
3146     lpCaps->dwFormats = woc16.dwFormats;
3147     lpCaps->wChannels = woc16.wChannels;
3148     lpCaps->dwSupport = woc16.dwSupport;
3149     return ret;
3150 }
3151
3152 /**************************************************************************
3153  *                              waveOutGetDevCapsW              [WINMM.163]
3154  */
3155 UINT32 WINAPI waveOutGetDevCaps32W(UINT32 uDeviceID, LPWAVEOUTCAPS32W lpCaps,
3156                                    UINT32 uSize)
3157 {
3158     WAVEOUTCAPS16       woc16;
3159     UINT32 ret = waveOutGetDevCaps16(uDeviceID,&woc16,sizeof(woc16));
3160     
3161     lpCaps->wMid = woc16.wMid;
3162     lpCaps->wPid = woc16.wPid;
3163     lpCaps->vDriverVersion = woc16.vDriverVersion;
3164     lstrcpyAtoW(lpCaps->szPname,woc16.szPname);
3165     lpCaps->dwFormats = woc16.dwFormats;
3166     lpCaps->wChannels = woc16.wChannels;
3167     lpCaps->dwSupport = woc16.dwSupport;
3168     return ret;
3169 }
3170
3171 /**************************************************************************
3172  *                              waveOutGetErrorText     [MMSYSTEM.403]
3173  */
3174 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
3175 {
3176     TRACE(mmsys, "waveOutGetErrorText\n");
3177     return(waveGetErrorText(uError, lpText, uSize));
3178 }
3179
3180 /**************************************************************************
3181  *                              waveOutGetErrorTextA    [WINMM.164]
3182  */
3183 UINT32 WINAPI waveOutGetErrorText32A(UINT32 uError, LPSTR lpText, UINT32 uSize)
3184 {
3185     return(waveOutGetErrorText16(uError, lpText, uSize));
3186 }
3187
3188 /**************************************************************************
3189  *                              waveOutGetErrorTextW    [WINMM.165]
3190  */
3191 UINT32 WINAPI waveOutGetErrorText32W(UINT32 uError, LPWSTR lpText, UINT32 uSize)
3192 {
3193     LPSTR       xstr = HeapAlloc(GetProcessHeap(),0,uSize);
3194     UINT32      ret = waveOutGetErrorText32A(uError, xstr, uSize);
3195     
3196     lstrcpyAtoW(lpText,xstr);
3197     HeapFree(GetProcessHeap(),0,xstr);
3198     return ret;
3199 }
3200
3201
3202 /**************************************************************************
3203  *                              waveGetErrorText                [internal]
3204  */
3205 static UINT16 waveGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize)
3206 {
3207     LPSTR       msgptr;
3208     TRACE(mmsys, "(%04X, %p, %d);\n", 
3209           uError, lpText, uSize);
3210     if ((lpText == NULL) || (uSize < 1)) return(FALSE);
3211     lpText[0] = '\0';
3212     switch (uError) {
3213     case MMSYSERR_NOERROR:
3214         msgptr = "The specified command was carried out.";
3215         break;
3216     case MMSYSERR_ERROR:
3217         msgptr = "Undefined external error.";
3218         break;
3219     case MMSYSERR_BADDEVICEID:
3220         msgptr = "A device ID has been used that is out of range for your system.";
3221         break;
3222     case MMSYSERR_NOTENABLED:
3223         msgptr = "The driver was not enabled.";
3224         break;
3225     case MMSYSERR_ALLOCATED:
3226         msgptr = "The specified device is already in use. Wait until it is free, and then try again.";
3227         break;
3228     case MMSYSERR_INVALHANDLE:
3229         msgptr = "The specified device handle is invalid.";
3230         break;
3231     case MMSYSERR_NODRIVER:
3232         msgptr = "There is no driver installed on your system !\n";
3233         break;
3234     case MMSYSERR_NOMEM:
3235         msgptr = "Not enough memory available for this task. Quit one or more applications to increase available memory, and then try again.";
3236         break;
3237     case MMSYSERR_NOTSUPPORTED:
3238         msgptr = "This function is not supported. Use the Capabilities function to determine which functions and messages the driver supports.";
3239         break;
3240     case MMSYSERR_BADERRNUM:
3241         msgptr = "An error number was specified that is not defined in the system.";
3242         break;
3243     case MMSYSERR_INVALFLAG:
3244         msgptr = "An invalid flag was passed to a system function.";
3245         break;
3246     case MMSYSERR_INVALPARAM:
3247         msgptr = "An invalid parameter was passed to a system function.";
3248         break;
3249     case WAVERR_BADFORMAT:
3250         msgptr = "The specified format is not supported or cannot be translated. Use the Capabilities function to determine the supported formats";
3251         break;
3252     case WAVERR_STILLPLAYING:
3253         msgptr = "Cannot perform this operation while media data is still playing. Reset the device, or wait until the data is finished playing.";
3254         break;
3255     case WAVERR_UNPREPARED:
3256         msgptr = "The wave header was not prepared. Use the Prepare function to prepare the header, and then try again.";
3257         break;
3258     case WAVERR_SYNC:
3259         msgptr = "Cannot open the device without using the WAVE_ALLOWSYNC flag. Use the flag, and then try again.";
3260         break;
3261     default:
3262         msgptr = "Unknown MMSYSTEM Error !\n";
3263         break;
3264     }
3265     lstrcpyn32A(lpText, msgptr, uSize);
3266     return TRUE;
3267 }
3268
3269 /**************************************************************************
3270  *                      waveOutOpen                     [WINMM.173]
3271  * All the args/structs have the same layout as the win16 equivalents
3272  */
3273 UINT32 WINAPI waveOutOpen32(HWAVEOUT32 * lphWaveOut, UINT32 uDeviceID,
3274                             const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
3275                             DWORD dwInstance, DWORD dwFlags)
3276 {
3277     HWAVEOUT16  hwo16;
3278     UINT32      ret = waveOutOpen16(&hwo16,uDeviceID,lpFormat,dwCallback,dwInstance,
3279                                     CALLBACK32CONV(dwFlags));
3280
3281     if (lphWaveOut) *lphWaveOut=hwo16;
3282     return ret;
3283 }
3284 /**************************************************************************
3285  *                      waveOutOpen                     [MMSYSTEM.404]
3286  */
3287 UINT16 WINAPI waveOutOpen16(HWAVEOUT16 * lphWaveOut, UINT16 uDeviceID,
3288                             const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
3289                             DWORD dwInstance, DWORD dwFlags)
3290 {
3291     HWAVEOUT16  hWaveOut;
3292     LPWAVEOPENDESC      lpDesc;
3293     DWORD               dwRet = 0;
3294     BOOL32              bMapperFlg = FALSE;
3295     
3296     TRACE(mmsys, "(%p, %d, %p, %08lX, %08lX, %08lX);\n", 
3297           lphWaveOut, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags);
3298     if (dwFlags & WAVE_FORMAT_QUERY)
3299         TRACE(mmsys, "WAVE_FORMAT_QUERY requested !\n");
3300     if (uDeviceID == (UINT16)WAVE_MAPPER) {
3301         TRACE(mmsys, "WAVE_MAPPER mode requested !\n");
3302         bMapperFlg = TRUE;
3303         uDeviceID = 0;
3304     }
3305     if (lpFormat == NULL) return WAVERR_BADFORMAT;
3306     
3307     hWaveOut = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
3308     if (lphWaveOut != NULL) *lphWaveOut = hWaveOut;
3309     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3310     if (lpDesc == NULL) return MMSYSERR_NOMEM;
3311     lpDesc->hWave = hWaveOut;
3312     lpDesc->lpFormat = (LPWAVEFORMAT)lpFormat;  /* should the struct be copied iso pointer? */
3313     lpDesc->dwCallBack = dwCallback;
3314     lpDesc->dwInstance = dwInstance;
3315     if (uDeviceID >= MAXWAVEDRIVERS)
3316         uDeviceID = 0;
3317     while (uDeviceID < MAXWAVEDRIVERS) {
3318         dwRet = wodMessage(uDeviceID, WODM_OPEN, 
3319                            lpDesc->dwInstance, (DWORD)lpDesc, dwFlags);
3320         if (dwRet == MMSYSERR_NOERROR) break;
3321         if (!bMapperFlg) break;
3322         uDeviceID++;
3323         TRACE(mmsys, "WAVE_MAPPER mode ! try next driver...\n");
3324     }
3325     lpDesc->uDeviceID = uDeviceID;  /* save physical Device ID */
3326     if (dwFlags & WAVE_FORMAT_QUERY) {
3327         TRACE(mmsys, "End of WAVE_FORMAT_QUERY !\n");
3328         dwRet = waveOutClose32(hWaveOut);
3329     }
3330     return dwRet;
3331 }
3332
3333 /**************************************************************************
3334  *                              waveOutClose            [WINMM.161]
3335  */
3336 UINT32 WINAPI waveOutClose32(HWAVEOUT32 hWaveOut)
3337 {
3338     return waveOutClose16(hWaveOut);
3339 }
3340 /**************************************************************************
3341  *                              waveOutClose            [MMSYSTEM.405]
3342  */
3343 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
3344 {
3345     LPWAVEOPENDESC      lpDesc;
3346     
3347     TRACE(mmsys, "(%04X)\n", hWaveOut);
3348     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3349     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3350     return wodMessage( lpDesc->uDeviceID, WODM_CLOSE, lpDesc->dwInstance, 0L, 0L);
3351 }
3352
3353 /**************************************************************************
3354  *                              waveOutPrepareHeader    [WINMM.175]
3355  */
3356 UINT32 WINAPI waveOutPrepareHeader32(HWAVEOUT32 hWaveOut,
3357                                      WAVEHDR * lpWaveOutHdr, UINT32 uSize)
3358 {
3359     LPWAVEOPENDESC      lpDesc;
3360     
3361     TRACE(mmsys, "(%04X, %p, %u);\n", 
3362           hWaveOut, lpWaveOutHdr, uSize);
3363     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3364     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3365     return wodMessage( lpDesc->uDeviceID, WODM_PREPARE, lpDesc->dwInstance, 
3366                        (DWORD)lpWaveOutHdr,uSize);
3367 }
3368 /**************************************************************************
3369  *                              waveOutPrepareHeader    [MMSYSTEM.406]
3370  */
3371 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut,
3372                                      WAVEHDR * lpWaveOutHdr, UINT16 uSize)
3373 {
3374     LPWAVEOPENDESC      lpDesc;
3375     LPBYTE              saveddata = lpWaveOutHdr->lpData;
3376     UINT16              ret;
3377     
3378     TRACE(mmsys, "(%04X, %p, %u);\n", 
3379           hWaveOut, lpWaveOutHdr, uSize);
3380     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3381     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3382     lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3383     ret = wodMessage( lpDesc->uDeviceID, WODM_PREPARE, lpDesc->dwInstance, 
3384                       (DWORD)lpWaveOutHdr,uSize);
3385     lpWaveOutHdr->lpData = saveddata;
3386     return ret;
3387 }
3388
3389 /**************************************************************************
3390  *                              waveOutUnprepareHeader  [WINMM.181]
3391  */
3392 UINT32 WINAPI waveOutUnprepareHeader32(HWAVEOUT32 hWaveOut,
3393                                        WAVEHDR * lpWaveOutHdr, UINT32 uSize)
3394 {
3395     LPWAVEOPENDESC      lpDesc;
3396     
3397     TRACE(mmsys, "(%04X, %p, %u);\n", 
3398           hWaveOut, lpWaveOutHdr, uSize);
3399     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3400     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3401     return wodMessage(lpDesc->uDeviceID,WODM_UNPREPARE,lpDesc->dwInstance, 
3402                       (DWORD)lpWaveOutHdr, uSize);
3403 }
3404 /**************************************************************************
3405  *                              waveOutUnprepareHeader  [MMSYSTEM.407]
3406  */
3407 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut,
3408                                        WAVEHDR * lpWaveOutHdr, UINT16 uSize)
3409 {
3410     LPWAVEOPENDESC      lpDesc;
3411     LPBYTE              saveddata = lpWaveOutHdr->lpData;
3412     UINT16              ret;
3413     
3414     TRACE(mmsys, "(%04X, %p, %u);\n", 
3415           hWaveOut, lpWaveOutHdr, uSize);
3416     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3417     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3418     lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3419     ret = wodMessage(lpDesc->uDeviceID,WODM_UNPREPARE,lpDesc->dwInstance, 
3420                      (DWORD)lpWaveOutHdr, uSize);
3421     lpWaveOutHdr->lpData = saveddata;
3422     return ret;
3423 }
3424
3425 /**************************************************************************
3426  *                              waveOutWrite            [MMSYSTEM.408]
3427  */
3428 UINT32 WINAPI waveOutWrite32(HWAVEOUT32 hWaveOut, WAVEHDR * lpWaveOutHdr,
3429                              UINT32 uSize)
3430 {
3431     LPWAVEOPENDESC      lpDesc;
3432     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3433     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3434     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3435     lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3436     return wodMessage( lpDesc->uDeviceID, WODM_WRITE, lpDesc->dwInstance, (DWORD)lpWaveOutHdr, uSize);
3437 }
3438 /**************************************************************************
3439  *                              waveOutWrite            [MMSYSTEM.408]
3440  */
3441 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut, WAVEHDR * lpWaveOutHdr,
3442                              UINT16 uSize)
3443 {
3444     LPWAVEOPENDESC      lpDesc;
3445     UINT16              ret;
3446     
3447     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3448     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3449     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3450     lpWaveOutHdr->reserved=(DWORD)lpWaveOutHdr->lpData;/*save original ptr*/
3451     lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3452     ret = wodMessage( lpDesc->uDeviceID, WODM_WRITE, lpDesc->dwInstance, (DWORD)lpWaveOutHdr, uSize);
3453     lpWaveOutHdr->lpData = (LPBYTE)lpWaveOutHdr->reserved;
3454     return ret;
3455 }
3456
3457 /**************************************************************************
3458  *                              waveOutPause            [WINMM.174]
3459  */
3460 UINT32 WINAPI waveOutPause32(HWAVEOUT32 hWaveOut)
3461 {
3462     return waveOutPause16(hWaveOut);
3463 }
3464
3465 /**************************************************************************
3466  *                              waveOutPause            [MMSYSTEM.409]
3467  */
3468 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut)
3469 {
3470     LPWAVEOPENDESC      lpDesc;
3471     
3472     TRACE(mmsys, "(%04X)\n", hWaveOut);
3473     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3474     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3475     return wodMessage( lpDesc->uDeviceID, WODM_PAUSE, lpDesc->dwInstance, 0L, 0L);
3476 }
3477
3478 /**************************************************************************
3479  *                              waveOutRestart          [WINMM.177]
3480  */
3481 UINT32 WINAPI waveOutRestart32(HWAVEOUT32 hWaveOut)
3482 {
3483     return waveOutRestart16(hWaveOut);
3484 }
3485
3486 /**************************************************************************
3487  *                              waveOutRestart          [MMSYSTEM.410]
3488  */
3489 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut)
3490 {
3491     LPWAVEOPENDESC      lpDesc;
3492     
3493     TRACE(mmsys, "(%04X)\n", hWaveOut);
3494     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3495     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3496     return wodMessage( lpDesc->uDeviceID, WODM_RESTART, lpDesc->dwInstance, 0L, 0L);
3497 }
3498
3499 /**************************************************************************
3500  *                              waveOutReset            [WINMM.176]
3501  */
3502 UINT32 WINAPI waveOutReset32(HWAVEOUT32 hWaveOut)
3503 {
3504     return waveOutReset16(hWaveOut);
3505 }
3506
3507 /**************************************************************************
3508  *                              waveOutReset            [MMSYSTEM.411]
3509  */
3510 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut)
3511 {
3512     LPWAVEOPENDESC      lpDesc;
3513     TRACE(mmsys, "(%04X)\n", hWaveOut);
3514     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3515     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3516     return wodMessage( lpDesc->uDeviceID, WODM_RESET, lpDesc->dwInstance, 0L, 0L);
3517 }
3518
3519 /**************************************************************************
3520  *                              waveOutGetPosition      [WINMM.170]
3521  */
3522 UINT32 WINAPI waveOutGetPosition32(HWAVEOUT32 hWaveOut, LPMMTIME32 lpTime,
3523                                    UINT32 uSize)
3524 {
3525     MMTIME16    mmt16;
3526     UINT32 ret;
3527     
3528     mmt16.wType = lpTime->wType;
3529     ret = waveOutGetPosition16(hWaveOut,&mmt16,sizeof(mmt16));
3530     MMSYSTEM_MMTIME16to32(lpTime,&mmt16);
3531     return ret;
3532 }
3533 /**************************************************************************
3534  *                              waveOutGetPosition      [MMSYSTEM.412]
3535  */
3536 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut,LPMMTIME16 lpTime,
3537                                    UINT16 uSize)
3538 {
3539     LPWAVEOPENDESC      lpDesc;
3540     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpTime, uSize);
3541     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3542     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3543     return wodMessage( lpDesc->uDeviceID, WODM_GETPOS, lpDesc->dwInstance, 
3544                        (DWORD)lpTime, (DWORD)uSize);
3545 }
3546
3547 #define WAVEOUT_SHORTCUT_1(xx,XX,atype) \
3548         UINT32 WINAPI waveOut##xx##32(HWAVEOUT32 hWaveOut, atype x)     \
3549 {                                                                       \
3550         return waveOut##xx##16(hWaveOut,x);                             \
3551 }                                                                       \
3552 UINT16 WINAPI waveOut##xx##16(HWAVEOUT16 hWaveOut, atype x)             \
3553 {                                                                       \
3554         LPWAVEOPENDESC  lpDesc;                                         \
3555         TRACE(mmsys, "waveOut"#xx"(%04X, %08lx);\n", hWaveOut,(DWORD)x);\
3556         lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);         \
3557         if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;                \
3558         return wodMessage(lpDesc->uDeviceID, WODM_##XX, lpDesc->dwInstance,\
3559                           (DWORD)x, 0L);                                \
3560 }
3561
3562 WAVEOUT_SHORTCUT_1(GetPitch,GETPITCH,DWORD*)
3563 WAVEOUT_SHORTCUT_1(SetPitch,SETPITCH,DWORD)
3564 WAVEOUT_SHORTCUT_1(GetPlaybackRate,GETPLAYBACKRATE,DWORD*)
3565 WAVEOUT_SHORTCUT_1(SetPlaybackRate,SETPLAYBACKRATE,DWORD)
3566     
3567 #define WAVEOUT_SHORTCUT_2(xx,XX,atype) \
3568         UINT32 WINAPI waveOut##xx##32(UINT32 devid, atype x)            \
3569 {                                                                       \
3570         return waveOut##xx##16(devid,x);                                \
3571 }                                                                       \
3572 UINT16 WINAPI waveOut##xx##16(UINT16 devid, atype x)                    \
3573 {                                                                       \
3574         TRACE(mmsys, "waveOut"#xx"(%04X, %08lx);\n", devid,(DWORD)x);   \
3575         return wodMessage(devid, WODM_##XX, 0L, (DWORD)x, 0L);          \
3576 }
3577     
3578     
3579 WAVEOUT_SHORTCUT_2(GetVolume,GETVOLUME,DWORD*)
3580 WAVEOUT_SHORTCUT_2(SetVolume,SETVOLUME,DWORD)
3581     
3582     
3583 /**************************************************************************
3584  *                              waveOutBreakLoop        [MMSYSTEM.419]
3585  */
3586 UINT32 WINAPI waveOutBreakLoop32(HWAVEOUT32 hWaveOut)
3587 {
3588     return waveOutBreakLoop16(hWaveOut);
3589 }
3590 /**************************************************************************
3591  *                              waveOutBreakLoop        [MMSYSTEM.419]
3592  */
3593 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut)
3594 {
3595     TRACE(mmsys, "(%04X)\n", hWaveOut);
3596     return MMSYSERR_INVALHANDLE;
3597 }
3598
3599 /**************************************************************************
3600  *                              waveOutGetID            [MMSYSTEM.420]
3601  */
3602 UINT32 WINAPI waveOutGetID32(HWAVEOUT32 hWaveOut, UINT32 * lpuDeviceID)
3603 {
3604     LPWAVEOPENDESC      lpDesc;
3605     TRACE(mmsys, "(%04X, %p);\n", hWaveOut, lpuDeviceID);
3606     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3607     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3608     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
3609     *lpuDeviceID = lpDesc->uDeviceID;
3610     return 0;
3611 }
3612 /**************************************************************************
3613  *                              waveOutGetID            [MMSYSTEM.420]
3614  */
3615 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16 * lpuDeviceID)
3616 {
3617     LPWAVEOPENDESC      lpDesc;
3618     TRACE(mmsys, "(%04X, %p);\n", hWaveOut, lpuDeviceID);
3619     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3620     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3621     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
3622     *lpuDeviceID = lpDesc->uDeviceID;
3623     return 0;
3624 }
3625
3626 /**************************************************************************
3627  *                              waveOutMessage          [MMSYSTEM.421]
3628  */
3629 DWORD WINAPI waveOutMessage32(HWAVEOUT32 hWaveOut, UINT32 uMessage, 
3630                               DWORD dwParam1, DWORD dwParam2)
3631 {
3632     LPWAVEOPENDESC      lpDesc;
3633     
3634     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3635     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3636     switch (uMessage) {
3637     case WODM_GETNUMDEVS:
3638     case WODM_GETPOS:
3639     case WODM_GETVOLUME:
3640     case WODM_GETPITCH:
3641     case WODM_GETPLAYBACKRATE:
3642     case WODM_SETVOLUME:
3643     case WODM_SETPITCH:
3644     case WODM_SETPLAYBACKRATE:
3645     case WODM_RESET:
3646     case WODM_PAUSE:
3647     case WODM_PREPARE:
3648     case WODM_UNPREPARE:
3649     case WODM_STOP:
3650     case WODM_CLOSE:
3651         /* no argument conversion needed */
3652         break;
3653     case WODM_WRITE:
3654         return waveOutWrite32(hWaveOut,(LPWAVEHDR)dwParam1,dwParam2);
3655     case WODM_GETDEVCAPS:
3656         /* FIXME: UNICODE/ANSI? */
3657         return waveOutGetDevCaps32A(hWaveOut,(LPWAVEOUTCAPS32A)dwParam1,dwParam2);
3658     case WODM_OPEN:
3659         FIXME(mmsys,"can't handle WODM_OPEN, please report.\n");
3660         break;
3661     default:
3662         ERR(mmsys,"(0x%04x,0x%04x,%08lx,%08lx): unhandled message\n",
3663             hWaveOut,uMessage,dwParam1,dwParam2);
3664         break;
3665     }
3666     return wodMessage( lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
3667 }
3668
3669 /**************************************************************************
3670  *                              waveOutMessage          [MMSYSTEM.421]
3671  */
3672 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage, 
3673                               DWORD dwParam1, DWORD dwParam2)
3674 {
3675     LPWAVEOPENDESC      lpDesc;
3676     
3677     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3678     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3679     switch (uMessage) {
3680     case WODM_GETNUMDEVS:
3681     case WODM_SETVOLUME:
3682     case WODM_SETPITCH:
3683     case WODM_SETPLAYBACKRATE:
3684     case WODM_RESET:
3685     case WODM_PAUSE:
3686     case WODM_STOP:
3687     case WODM_CLOSE:
3688         /* no argument conversion needed */
3689         break;
3690     case WODM_GETPOS:
3691         return waveOutGetPosition16(hWaveOut,(LPMMTIME16)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3692     case WODM_GETVOLUME:
3693         return waveOutGetVolume16(hWaveOut,(LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3694     case WODM_GETPITCH:
3695         return waveOutGetPitch16(hWaveOut,(LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3696     case WODM_GETPLAYBACKRATE:
3697         return waveOutGetPlaybackRate16(hWaveOut,(LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3698     case WODM_GETDEVCAPS:
3699         return waveOutGetDevCaps16(hWaveOut,(LPWAVEOUTCAPS16)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3700     case WODM_PREPARE:
3701         return waveOutPrepareHeader16(hWaveOut,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3702     case WODM_UNPREPARE:
3703         return waveOutUnprepareHeader16(hWaveOut,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3704     case WODM_WRITE:
3705         return waveOutWrite16(hWaveOut,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3706     case WODM_OPEN:
3707         FIXME(mmsys,"can't handle WODM_OPEN, please report.\n");
3708         break;
3709     default:
3710         ERR(mmsys,"(0x%04x,0x%04x,%08lx,%08lx): unhandled message\n",
3711             hWaveOut,uMessage,dwParam1,dwParam2);
3712     }
3713     return wodMessage( lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
3714 }
3715
3716 /**************************************************************************
3717  *                              waveInGetNumDevs                [WINMM.151]
3718  */
3719 UINT32 WINAPI waveInGetNumDevs32()
3720 {
3721     return waveInGetNumDevs16();
3722 }
3723
3724 /**************************************************************************
3725  *                              waveInGetNumDevs                [MMSYSTEM.501]
3726  */
3727 UINT16 WINAPI waveInGetNumDevs16()
3728 {
3729     UINT16      count = 0;
3730     TRACE(mmsys, "waveInGetNumDevs\n");
3731     count += widMessage(0, WIDM_GETNUMDEVS, 0L, 0L, 0L);
3732     TRACE(mmsys, "waveInGetNumDevs return %u \n", count);
3733     return count;
3734 }
3735
3736 /**************************************************************************
3737  *                              waveInGetDevCapsA               [WINMM.147]
3738  */
3739 UINT32 WINAPI waveInGetDevCaps32W(UINT32 uDeviceID, LPWAVEINCAPS32W lpCaps, UINT32 uSize)
3740 {
3741     WAVEINCAPS16        wic16;
3742     UINT32      ret = waveInGetDevCaps16(uDeviceID,&wic16,uSize);
3743     
3744     lpCaps->wMid = wic16.wMid;
3745     lpCaps->wPid = wic16.wPid;
3746     lpCaps->vDriverVersion = wic16.vDriverVersion;
3747     lstrcpyAtoW(lpCaps->szPname,wic16.szPname);
3748     lpCaps->dwFormats = wic16.dwFormats;
3749     lpCaps->wChannels = wic16.wChannels;
3750     
3751     return ret;
3752 }
3753 /**************************************************************************
3754  *                              waveInGetDevCapsA               [WINMM.146]
3755  */
3756 UINT32 WINAPI waveInGetDevCaps32A(UINT32 uDeviceID, LPWAVEINCAPS32A lpCaps, UINT32 uSize)
3757 {
3758     WAVEINCAPS16        wic16;
3759     UINT32      ret = waveInGetDevCaps16(uDeviceID,&wic16,uSize);
3760     
3761     lpCaps->wMid = wic16.wMid;
3762     lpCaps->wPid = wic16.wPid;
3763     lpCaps->vDriverVersion = wic16.vDriverVersion;
3764     strcpy(lpCaps->szPname,wic16.szPname);
3765     lpCaps->dwFormats = wic16.dwFormats;
3766     lpCaps->wChannels = wic16.wChannels;
3767     return ret;
3768 }
3769 /**************************************************************************
3770  *                              waveInGetDevCaps                [MMSYSTEM.502]
3771  */
3772 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps, UINT16 uSize)
3773 {
3774     TRACE(mmsys, "waveInGetDevCaps\n");
3775     return widMessage(uDeviceID, WIDM_GETDEVCAPS, 0L, (DWORD)lpCaps, uSize);
3776 }
3777
3778 /**************************************************************************
3779  *                              waveInGetErrorTextA     [WINMM.148]
3780  */
3781 UINT32 WINAPI waveInGetErrorText32A(UINT32 uError, LPSTR lpText, UINT32 uSize)
3782 {
3783     TRACE(mmsys, "waveInGetErrorText\n");
3784     return(waveGetErrorText(uError, lpText, uSize));
3785 }
3786
3787 /**************************************************************************
3788  *                              waveInGetErrorTextW     [WINMM.149]
3789  */
3790 UINT32 WINAPI waveInGetErrorText32W(UINT32 uError, LPWSTR lpText, UINT32 uSize)
3791 {
3792     LPSTR txt = HeapAlloc(GetProcessHeap(),0,uSize);
3793     UINT32      ret = waveGetErrorText(uError, txt, uSize);
3794     
3795     lstrcpyAtoW(lpText,txt);
3796     HeapFree(GetProcessHeap(),0,txt);
3797     return ret;
3798 }
3799
3800 /**************************************************************************
3801  *                              waveInGetErrorText      [MMSYSTEM.503]
3802  */
3803 UINT16 WINAPI waveInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
3804 {
3805     TRACE(mmsys, "waveInGetErrorText\n");
3806     return(waveGetErrorText(uError, lpText, uSize));
3807 }
3808
3809
3810 /**************************************************************************
3811  *                              waveInOpen                      [WINMM.154]
3812  */
3813 UINT32 WINAPI waveInOpen32(HWAVEIN32 * lphWaveIn, UINT32 uDeviceID,
3814                            const LPWAVEFORMAT lpFormat, DWORD dwCallback,
3815                            DWORD dwInstance, DWORD dwFlags)
3816 {
3817     HWAVEIN16   hwin16;
3818     UINT32      ret = waveInOpen16(&hwin16,uDeviceID,lpFormat,dwCallback,dwInstance,
3819                                  CALLBACK32CONV(dwFlags));
3820     if (lphWaveIn) *lphWaveIn = hwin16;
3821     return ret;
3822 }
3823
3824 /**************************************************************************
3825  *                              waveInOpen                      [MMSYSTEM.504]
3826  */
3827 UINT16 WINAPI waveInOpen16(HWAVEIN16 * lphWaveIn, UINT16 uDeviceID,
3828                            const LPWAVEFORMAT lpFormat, DWORD dwCallback,
3829                            DWORD dwInstance, DWORD dwFlags)
3830 {
3831     HWAVEIN16 hWaveIn;
3832     LPWAVEOPENDESC      lpDesc;
3833     DWORD       dwRet = 0;
3834     BOOL32      bMapperFlg = FALSE;
3835     TRACE(mmsys, "(%p, %d, %p, %08lX, %08lX, %08lX);\n", 
3836           lphWaveIn, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags);
3837     if (dwFlags & WAVE_FORMAT_QUERY)
3838         TRACE(mmsys, "WAVE_FORMAT_QUERY requested !\n");
3839     if (uDeviceID == (UINT16)WAVE_MAPPER) {
3840         TRACE(mmsys, "WAVE_MAPPER mode requested !\n");
3841         bMapperFlg = TRUE;
3842         uDeviceID = 0;
3843     }
3844     if (lpFormat == NULL) return WAVERR_BADFORMAT;
3845     hWaveIn = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
3846     if (lphWaveIn != NULL) *lphWaveIn = hWaveIn;
3847     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3848     if (lpDesc == NULL) return MMSYSERR_NOMEM;
3849     lpDesc->hWave = hWaveIn;
3850     lpDesc->lpFormat = lpFormat;
3851     lpDesc->dwCallBack = dwCallback;
3852     lpDesc->dwInstance = dwInstance;
3853     while (uDeviceID < MAXWAVEDRIVERS) {
3854         dwRet = widMessage(uDeviceID, WIDM_OPEN, 
3855                            lpDesc->dwInstance, (DWORD)lpDesc, 0L);
3856         if (dwRet == MMSYSERR_NOERROR) break;
3857         if (!bMapperFlg) break;
3858         uDeviceID++;
3859         TRACE(mmsys, "WAVE_MAPPER mode ! try next driver...\n");
3860     }
3861     lpDesc->uDeviceID = uDeviceID;
3862     if (dwFlags & WAVE_FORMAT_QUERY) {
3863         TRACE(mmsys, "End of WAVE_FORMAT_QUERY !\n");
3864         dwRet = waveInClose16(hWaveIn);
3865     }
3866     return dwRet;
3867 }
3868
3869 /**************************************************************************
3870  *                              waveInClose                     [WINMM.145]
3871  */
3872 UINT32 WINAPI waveInClose32(HWAVEIN32 hWaveIn)
3873 {
3874     return waveInClose16(hWaveIn);
3875 }
3876 /**************************************************************************
3877  *                              waveInClose                     [MMSYSTEM.505]
3878  */
3879 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
3880 {
3881     LPWAVEOPENDESC      lpDesc;
3882     
3883     TRACE(mmsys, "(%04X)\n", hWaveIn);
3884     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3885     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3886     return widMessage(lpDesc->uDeviceID, WIDM_CLOSE, lpDesc->dwInstance, 0L, 0L);
3887 }
3888
3889 /**************************************************************************
3890  *                              waveInPrepareHeader             [WINMM.155]
3891  */
3892 UINT32 WINAPI waveInPrepareHeader32(HWAVEIN32 hWaveIn,
3893                                     WAVEHDR * lpWaveInHdr, UINT32 uSize)
3894 {
3895     LPWAVEOPENDESC      lpDesc;
3896     
3897     TRACE(mmsys, "(%04X, %p, %u);\n", 
3898           hWaveIn, lpWaveInHdr, uSize);
3899     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3900     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3901     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3902     lpWaveInHdr = lpWaveInHdr;
3903     lpWaveInHdr->lpNext = NULL;
3904     lpWaveInHdr->dwBytesRecorded = 0;
3905     TRACE(mmsys, "lpData=%p size=%lu \n", 
3906           lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3907     return widMessage(lpDesc->uDeviceID,WIDM_PREPARE,lpDesc->dwInstance, 
3908                       (DWORD)lpWaveInHdr, uSize);
3909 }
3910 /**************************************************************************
3911  *                              waveInPrepareHeader             [MMSYSTEM.506]
3912  */
3913 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn,
3914                                     WAVEHDR * lpWaveInHdr, UINT16 uSize)
3915 {
3916     LPWAVEOPENDESC      lpDesc;
3917     LPBYTE              saveddata = lpWaveInHdr->lpData;
3918     UINT16              ret;
3919     
3920     TRACE(mmsys, "(%04X, %p, %u);\n", 
3921           hWaveIn, lpWaveInHdr, uSize);
3922     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3923     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3924     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3925     lpWaveInHdr = lpWaveInHdr;
3926     lpWaveInHdr->lpNext = NULL;
3927     lpWaveInHdr->dwBytesRecorded = 0;
3928     
3929     TRACE(mmsys, "lpData=%p size=%lu \n", 
3930           lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3931     lpWaveInHdr->lpData = PTR_SEG_TO_LIN(lpWaveInHdr->lpData);
3932     ret = widMessage(lpDesc->uDeviceID,WIDM_PREPARE,lpDesc->dwInstance, 
3933                      (DWORD)lpWaveInHdr,uSize);
3934     lpWaveInHdr->lpData = saveddata;
3935     return ret;
3936 }
3937
3938
3939 /**************************************************************************
3940  *                              waveInUnprepareHeader   [WINMM.159]
3941  */
3942 UINT32 WINAPI waveInUnprepareHeader32(HWAVEIN32 hWaveIn,
3943                                       WAVEHDR * lpWaveInHdr, UINT32 uSize)
3944 {
3945     LPWAVEOPENDESC      lpDesc;
3946     
3947     TRACE(mmsys, "(%04X, %p, %u);\n", 
3948           hWaveIn, lpWaveInHdr, uSize);
3949     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3950     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3951     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3952     /*USER_HEAP_FREE(HIWORD((DWORD)lpWaveInHdr->lpData)); FIXME */
3953     lpWaveInHdr->lpData = NULL;
3954     lpWaveInHdr->lpNext = NULL;
3955     return widMessage(lpDesc->uDeviceID,WIDM_UNPREPARE,lpDesc->dwInstance, 
3956                       (DWORD)lpWaveInHdr, uSize);
3957 }
3958 /**************************************************************************
3959  *                              waveInUnprepareHeader   [MMSYSTEM.507]
3960  */
3961 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn,
3962                                       WAVEHDR * lpWaveInHdr, UINT16 uSize)
3963 {
3964     LPWAVEOPENDESC      lpDesc;
3965     
3966     TRACE(mmsys, "(%04X, %p, %u);\n", 
3967           hWaveIn, lpWaveInHdr, uSize);
3968     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3969     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3970     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3971     /*USER_HEAP_FREE(HIWORD((DWORD)lpWaveInHdr->lpData)); FIXME */
3972     lpWaveInHdr->lpData = NULL;
3973     lpWaveInHdr->lpNext = NULL;
3974     return widMessage(lpDesc->uDeviceID,WIDM_UNPREPARE,lpDesc->dwInstance, 
3975                       (DWORD)lpWaveInHdr, uSize);
3976 }
3977
3978 /**************************************************************************
3979  *                              waveInAddBuffer         [WINMM.144]
3980  */
3981 UINT32 WINAPI waveInAddBuffer32(HWAVEIN32 hWaveIn,
3982                                 WAVEHDR * lpWaveInHdr, UINT32 uSize)
3983 {
3984     LPWAVEOPENDESC      lpDesc;
3985     
3986     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
3987     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3988     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3989     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3990     lpWaveInHdr->lpNext = NULL;
3991     lpWaveInHdr->dwBytesRecorded = 0;
3992     TRACE(mmsys, "lpData=%p size=%lu \n", 
3993           lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3994     return widMessage(lpDesc->uDeviceID, WIDM_ADDBUFFER, lpDesc->dwInstance,
3995                       (DWORD)lpWaveInHdr, uSize);
3996     
3997 }
3998
3999 /**************************************************************************
4000  *                              waveInAddBuffer         [MMSYSTEM.508]
4001  */
4002 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn,
4003                                 WAVEHDR * lpWaveInHdr, UINT16 uSize)
4004 {
4005     LPWAVEOPENDESC      lpDesc;
4006     UINT16              ret;
4007     
4008     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
4009     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4010     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4011     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
4012     lpWaveInHdr->lpNext = NULL;
4013     lpWaveInHdr->dwBytesRecorded = 0;
4014     lpWaveInHdr->lpData = PTR_SEG_TO_LIN(lpWaveInHdr->lpData);
4015     TRACE(mmsys, "lpData=%p size=%lu \n", 
4016           lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
4017     ret = widMessage(lpDesc->uDeviceID, WIDM_ADDBUFFER, lpDesc->dwInstance,
4018                      (DWORD)lpWaveInHdr, uSize);
4019     /*lpWaveInHdr->lpData = saveddata;*/
4020     return ret;
4021 }
4022
4023 /**************************************************************************
4024  *                              waveInStart                     [WINMM.157]
4025  */
4026 UINT32 WINAPI waveInStart32(HWAVEIN32 hWaveIn)
4027 {
4028     return waveInStart16(hWaveIn);
4029 }
4030
4031 /**************************************************************************
4032  *                              waveInStart                     [MMSYSTEM.509]
4033  */
4034 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn)
4035 {
4036     LPWAVEOPENDESC      lpDesc;
4037     
4038     TRACE(mmsys, "(%04X)\n", hWaveIn);
4039     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4040     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4041     return widMessage(lpDesc->uDeviceID,WIDM_START,lpDesc->dwInstance,0,0);
4042 }
4043
4044 /**************************************************************************
4045  *                              waveInStop                      [WINMM.158]
4046  */
4047 UINT32 WINAPI waveInStop32(HWAVEIN32 hWaveIn)
4048 {
4049     return waveInStop16(hWaveIn);
4050 }
4051
4052 /**************************************************************************
4053  *                              waveInStop                      [MMSYSTEM.510]
4054  */
4055 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn)
4056 {
4057     LPWAVEOPENDESC      lpDesc;
4058     
4059     TRACE(mmsys, "(%04X)\n", hWaveIn);
4060     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4061     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4062     return widMessage(lpDesc->uDeviceID, WIDM_STOP, lpDesc->dwInstance, 0L, 0L);
4063 }
4064
4065 /**************************************************************************
4066  *                              waveInReset                     [WINMM.156]
4067  */
4068 UINT32 WINAPI waveInReset32(HWAVEIN32 hWaveIn)
4069 {
4070     return waveInReset16(hWaveIn);
4071 }
4072
4073 /**************************************************************************
4074  *                              waveInReset                     [MMSYSTEM.511]
4075  */
4076 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn)
4077 {
4078     LPWAVEOPENDESC      lpDesc;
4079     
4080     TRACE(mmsys, "(%04X)\n", hWaveIn);
4081     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4082     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4083     return widMessage(lpDesc->uDeviceID,WIDM_RESET,lpDesc->dwInstance,0,0);
4084 }
4085
4086 /**************************************************************************
4087  *                              waveInGetPosition       [WINMM.152]
4088  */
4089 UINT32 WINAPI waveInGetPosition32(HWAVEIN32 hWaveIn, LPMMTIME32 lpTime,
4090                                   UINT32 uSize)
4091 {
4092     MMTIME16    mmt16;
4093     UINT32      ret = waveInGetPosition16(hWaveIn,&mmt16,uSize);
4094     
4095     MMSYSTEM_MMTIME16to32(lpTime,&mmt16);
4096     return ret;
4097 }
4098
4099 /**************************************************************************
4100  *                              waveInGetPosition       [MMSYSTEM.512]
4101  */
4102 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn,LPMMTIME16 lpTime,
4103                                   UINT16 uSize)
4104 {
4105     LPWAVEOPENDESC      lpDesc;
4106     
4107     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpTime, uSize);
4108     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4109     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4110     return widMessage(lpDesc->uDeviceID, WIDM_GETPOS, lpDesc->dwInstance,
4111                       (DWORD)lpTime, (DWORD)uSize);
4112 }
4113
4114 /**************************************************************************
4115  *                              waveInGetID                     [WINMM.150]
4116  */
4117 UINT32 WINAPI waveInGetID32(HWAVEIN32 hWaveIn, UINT32 * lpuDeviceID)
4118 {
4119     LPWAVEOPENDESC      lpDesc;
4120     
4121     TRACE(mmsys, "waveInGetID\n");
4122     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
4123     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4124     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4125     *lpuDeviceID = lpDesc->uDeviceID;
4126     return 0;
4127 }
4128
4129
4130 /**************************************************************************
4131  *                              waveInGetID                     [MMSYSTEM.513]
4132  */
4133 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16 * lpuDeviceID)
4134 {
4135     LPWAVEOPENDESC      lpDesc;
4136     
4137     TRACE(mmsys, "waveInGetID\n");
4138     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
4139     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4140     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4141     *lpuDeviceID = lpDesc->uDeviceID;
4142     return 0;
4143 }
4144
4145 /**************************************************************************
4146  *                              waveInMessage           [WINMM.153]
4147  */
4148 DWORD WINAPI waveInMessage32(HWAVEIN32 hWaveIn, UINT32 uMessage,
4149                              DWORD dwParam1, DWORD dwParam2)
4150 {
4151     LPWAVEOPENDESC      lpDesc;
4152     
4153     FIXME(mmsys, "(%04X, %04X, %08lX, %08lX),FIXME!\n", 
4154           hWaveIn, uMessage, dwParam1, dwParam2);
4155     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4156     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4157     switch (uMessage) {
4158     case WIDM_OPEN:
4159         FIXME(mmsys, "cannot handle WIDM_OPEN, please report.\n");
4160         break;
4161     case WIDM_GETNUMDEVS:
4162     case WIDM_GETPOS:
4163     case WIDM_CLOSE:
4164     case WIDM_STOP :
4165     case WIDM_RESET:
4166     case WIDM_START:
4167     case WIDM_PREPARE:
4168     case WIDM_UNPREPARE:
4169     case WIDM_ADDBUFFER:
4170     case WIDM_PAUSE:
4171         /* no argument conversion needed */
4172         break;
4173     case WIDM_GETDEVCAPS:
4174         /*FIXME: ANSI/UNICODE */
4175         return waveInGetDevCaps32A(hWaveIn,(LPWAVEINCAPS32A)dwParam1,dwParam2);
4176     default:
4177         ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
4178             hWaveIn,uMessage,dwParam1,dwParam2);
4179         break;
4180     }
4181     return widMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
4182 }
4183
4184 /**************************************************************************
4185  *                              waveInMessage           [MMSYSTEM.514]
4186  */
4187 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
4188                              DWORD dwParam1, DWORD dwParam2)
4189 {
4190     LPWAVEOPENDESC      lpDesc;
4191     
4192     FIXME(mmsys, "(%04X, %04X, %08lX, %08lX),FIXME!\n", 
4193           hWaveIn, uMessage, dwParam1, dwParam2);
4194     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4195     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4196     switch (uMessage) {
4197     case WIDM_OPEN:
4198         FIXME(mmsys,"cannot handle WIDM_OPEN, please report.\n");
4199         break;
4200     case WIDM_GETNUMDEVS:
4201     case WIDM_CLOSE:
4202     case WIDM_STOP :
4203     case WIDM_RESET:
4204     case WIDM_START:
4205     case WIDM_PAUSE:
4206         /* no argument conversion needed */
4207         break;
4208     case WIDM_GETDEVCAPS:
4209         return waveInGetDevCaps16(hWaveIn,(LPWAVEINCAPS16)PTR_SEG_TO_LIN(dwParam1),dwParam2);
4210     case WIDM_GETPOS:
4211         return waveInGetPosition16(hWaveIn,(LPMMTIME16)PTR_SEG_TO_LIN(dwParam1),dwParam2);
4212     case WIDM_PREPARE:
4213         return waveInPrepareHeader16(hWaveIn,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
4214     case WIDM_UNPREPARE:
4215         return waveInUnprepareHeader16(hWaveIn,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
4216     case WIDM_ADDBUFFER:
4217         return waveInAddBuffer16(hWaveIn,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
4218     default:
4219         ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
4220             hWaveIn,uMessage,dwParam1,dwParam2);
4221         break;
4222     }
4223     return widMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
4224 }
4225
4226 /**************************************************************************
4227  *                              DrvOpen                 [MMSYSTEM.1100]
4228  */
4229 HDRVR16 WINAPI DrvOpen(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
4230 {
4231     TRACE(mmsys,"('%s','%s',%08lX);\n",lpDriverName,lpSectionName,lParam);
4232     return OpenDriver16(lpDriverName, lpSectionName, lParam);
4233 }
4234
4235
4236 /**************************************************************************
4237  *                              DrvClose                [MMSYSTEM.1101]
4238  */
4239 LRESULT WINAPI DrvClose(HDRVR16 hDrvr, LPARAM lParam1, LPARAM lParam2)
4240 {
4241     TRACE(mmsys, "(%04X, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
4242     return CloseDriver16(hDrvr, lParam1, lParam2);
4243 }
4244
4245
4246 /**************************************************************************
4247  *                              DrvSendMessage          [MMSYSTEM.1102]
4248  */
4249 LRESULT WINAPI DrvSendMessage(HDRVR16 hDriver, WORD msg, LPARAM lParam1,
4250                               LPARAM lParam2)
4251 {
4252     DWORD       dwDriverID = 0;
4253     FIXME(mmsys, "(%04X, %04X, %08lX, %08lX);\n",
4254           hDriver, msg, lParam1, lParam2);
4255     /* FIXME: wrong ... */
4256     return CDAUDIO_DriverProc16(dwDriverID, hDriver, msg, lParam1, lParam2);
4257 }
4258
4259 /**************************************************************************
4260  *                              DrvGetModuleHandle      [MMSYSTEM.1103]
4261  */
4262 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrvr)
4263 {
4264     return GetDriverModuleHandle16(hDrvr);
4265 }
4266
4267 /**************************************************************************
4268  *                              DrvDefDriverProc        [MMSYSTEM.1104]
4269  */
4270 LRESULT WINAPI DrvDefDriverProc(DWORD dwDriverID, HDRVR16 hDriv, WORD wMsg, 
4271                                 DWORD dwParam1, DWORD dwParam2)
4272 {
4273     return DefDriverProc16(dwDriverID, hDriv, wMsg, dwParam1, dwParam2);
4274 }
4275
4276 /**************************************************************************
4277  *                              DefDriverProc32  [WINMM.5]
4278  */
4279 LRESULT WINAPI DefDriverProc32(DWORD dwDriverIdentifier, HDRVR32 hdrvr,
4280                                UINT32 Msg, LPARAM lParam1, LPARAM lParam2)
4281 {
4282     switch (Msg) {
4283       case DRV_LOAD:
4284       case DRV_DISABLE:
4285       case DRV_INSTALL:
4286         return 0;
4287       case DRV_ENABLE:
4288       case DRV_FREE:
4289       case DRV_REMOVE:
4290         return 1;
4291       default:
4292         return 0;
4293     }
4294 }
4295
4296 /**************************************************************************
4297  *                              mmThreadCreate          [MMSYSTEM.1120]
4298  */
4299 LRESULT WINAPI mmThreadCreate16(LPVOID x1, LPWORD x2, DWORD x3, DWORD x4) {
4300     FIXME(mmsys,"(%p,%p,%08lx,%08lx): stub!\n",x1,x2,x3,x4);
4301     *x2 = 0xbabe;
4302     return 0;
4303 }
4304
4305 /**************************************************************************
4306  *                              mmThreadGetTask         [MMSYSTEM.1125]
4307  */
4308 LRESULT WINAPI mmThreadGetTask16(WORD hnd) {
4309     FIXME(mmsys,"(%04x): stub!\n",hnd);
4310     return GetCurrentTask();
4311 }
4312
4313 /**************************************************************************
4314  *                              mmThreadSignal          [MMSYSTEM.1121]
4315  */
4316 LRESULT WINAPI mmThreadSignal16(WORD hnd) {
4317     FIXME(mmsys,"(%04x): stub!\n",hnd);
4318     return 0;
4319 }
4320
4321 /**************************************************************************
4322  *                              mmTaskCreate            [MMSYSTEM.900]
4323  */
4324 HINSTANCE16 WINAPI mmTaskCreate16(LPWORD lphnd,HINSTANCE16 *hMmTask,DWORD x2)
4325 {
4326     DWORD showCmd = 0x40002;
4327     LPSTR cmdline;
4328     WORD sel1, sel2;
4329     LOADPARAMS *lp;
4330     HINSTANCE16 ret, handle;
4331     
4332     TRACE(mmsys,"(%p,%p,%08lx);\n",lphnd,hMmTask,x2);
4333     cmdline = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 0x0d);
4334     cmdline[0] = 0x0d;
4335     (DWORD)cmdline[1] = (DWORD)lphnd;
4336     (DWORD)cmdline[5] = x2;
4337     (DWORD)cmdline[9] = 0;
4338     
4339     sel1 = SELECTOR_AllocBlock(cmdline, 0x0d, SEGMENT_DATA, FALSE, FALSE);
4340     sel2 = SELECTOR_AllocBlock(&showCmd, sizeof(showCmd),
4341                                SEGMENT_DATA, FALSE, FALSE);
4342     
4343     lp = (LOADPARAMS *)HeapAlloc(GetProcessHeap(), 0, sizeof(LOADPARAMS));
4344     lp->hEnvironment = 0;
4345     lp->cmdLine = PTR_SEG_OFF_TO_SEGPTR(sel1, 0);
4346     lp->showCmd = PTR_SEG_OFF_TO_SEGPTR(sel2, 0);
4347     lp->reserved = 0;
4348     
4349     ret = LoadModule16("c:\\windows\\mmtask.tsk", lp);
4350     if (ret < 32) {
4351         if (ret)
4352             ret = 1;
4353         else
4354             ret = 2;
4355         handle = 0;
4356     }
4357     else {
4358         handle = ret;
4359         ret = 0;
4360     }
4361     if (hMmTask)
4362         *(HINSTANCE16 *)PTR_SEG_TO_LIN(hMmTask) = handle;
4363     
4364     UnMapLS(PTR_SEG_OFF_TO_SEGPTR(sel2, 0));
4365     UnMapLS(PTR_SEG_OFF_TO_SEGPTR(sel1, 0));
4366     
4367     HeapFree(GetProcessHeap(), 0, lp);
4368     HeapFree(GetProcessHeap(), 0, cmdline);
4369     
4370     return ret;
4371 }
4372
4373 /**************************************************************************
4374  *                              mmTaskSignal            [MMSYSTEM.903]
4375  */
4376 LRESULT WINAPI mmTaskSignal16(HTASK16 ht) 
4377 {
4378     TRACE(mmsys,"(%04x);\n",ht);
4379     return PostAppMessage16(ht,WM_USER,0,0);
4380 }
4381
4382 /**************************************************************************
4383  *                              mciDriverYield          [MMSYSTEM.710]
4384  */
4385 LRESULT WINAPI mciDriverYield16(HANDLE16 hnd) 
4386 {
4387     FIXME(mmsys,"(%04x): stub!\n",hnd);
4388     return 0;
4389 }
4390