Fixed some more missing WINAPIs (hopefully correct).
[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 "debug.h"
34 #include "xmalloc.h"
35 #include "callback.h"
36 #include "module.h"
37 #include "selectors.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");
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 /**************************************************************************
3095  *                              waveOutGetNumDevs               [MMSYSTEM.401]
3096  */
3097 UINT32 WINAPI waveOutGetNumDevs32() {
3098     return waveOutGetNumDevs16();
3099 }
3100
3101 /**************************************************************************
3102  *                              waveOutGetNumDevs               [WINMM.167]
3103  */
3104 UINT16 WINAPI waveOutGetNumDevs16()
3105 {
3106     UINT16      count = 0;
3107     TRACE(mmsys, "waveOutGetNumDevs\n");
3108     count += wodMessage( MMSYSTEM_FirstDevID(), WODM_GETNUMDEVS, 0L, 0L, 0L);
3109     TRACE(mmsys, "waveOutGetNumDevs return %u \n", count);
3110     return count;
3111 }
3112
3113 /**************************************************************************
3114  *                              waveOutGetDevCaps               [MMSYSTEM.402]
3115  */
3116 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID, WAVEOUTCAPS16 * lpCaps,
3117                                   UINT16 uSize)
3118 {
3119     if (uDeviceID > waveOutGetNumDevs16() - 1) return MMSYSERR_BADDEVICEID;
3120     if (uDeviceID == (UINT16)WAVE_MAPPER) return MMSYSERR_BADDEVICEID; /* FIXME: do we have a wave mapper ? */
3121     TRACE(mmsys, "waveOutGetDevCaps\n");
3122     return wodMessage(uDeviceID, WODM_GETDEVCAPS, 0L, (DWORD)lpCaps, uSize);
3123 }
3124
3125 /**************************************************************************
3126  *                              waveOutGetDevCapsA              [WINMM.162]
3127  */
3128 UINT32 WINAPI waveOutGetDevCaps32A(UINT32 uDeviceID, LPWAVEOUTCAPS32A lpCaps,
3129                                    UINT32 uSize)
3130 {
3131     WAVEOUTCAPS16       woc16;
3132     UINT16 ret = waveOutGetDevCaps16(uDeviceID,&woc16,sizeof(woc16));
3133     
3134     lpCaps->wMid = woc16.wMid;
3135     lpCaps->wPid = woc16.wPid;
3136     lpCaps->vDriverVersion = woc16.vDriverVersion;
3137     strcpy(lpCaps->szPname,woc16.szPname);
3138     lpCaps->dwFormats = woc16.dwFormats;
3139     lpCaps->wChannels = woc16.wChannels;
3140     lpCaps->dwSupport = woc16.dwSupport;
3141     return ret;
3142 }
3143
3144 /**************************************************************************
3145  *                              waveOutGetDevCapsW              [WINMM.163]
3146  */
3147 UINT32 WINAPI waveOutGetDevCaps32W(UINT32 uDeviceID, LPWAVEOUTCAPS32W lpCaps,
3148                                    UINT32 uSize)
3149 {
3150     WAVEOUTCAPS16       woc16;
3151     UINT32 ret = waveOutGetDevCaps16(uDeviceID,&woc16,sizeof(woc16));
3152     
3153     lpCaps->wMid = woc16.wMid;
3154     lpCaps->wPid = woc16.wPid;
3155     lpCaps->vDriverVersion = woc16.vDriverVersion;
3156     lstrcpyAtoW(lpCaps->szPname,woc16.szPname);
3157     lpCaps->dwFormats = woc16.dwFormats;
3158     lpCaps->wChannels = woc16.wChannels;
3159     lpCaps->dwSupport = woc16.dwSupport;
3160     return ret;
3161 }
3162
3163 /**************************************************************************
3164  *                              waveOutGetErrorText     [MMSYSTEM.403]
3165  */
3166 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
3167 {
3168     TRACE(mmsys, "waveOutGetErrorText\n");
3169     return(waveGetErrorText(uError, lpText, uSize));
3170 }
3171
3172 /**************************************************************************
3173  *                              waveOutGetErrorTextA    [WINMM.164]
3174  */
3175 UINT32 WINAPI waveOutGetErrorText32A(UINT32 uError, LPSTR lpText, UINT32 uSize)
3176 {
3177     return(waveOutGetErrorText16(uError, lpText, uSize));
3178 }
3179
3180 /**************************************************************************
3181  *                              waveOutGetErrorTextW    [WINMM.165]
3182  */
3183 UINT32 WINAPI waveOutGetErrorText32W(UINT32 uError, LPWSTR lpText, UINT32 uSize)
3184 {
3185     LPSTR       xstr = HeapAlloc(GetProcessHeap(),0,uSize);
3186     UINT32      ret = waveOutGetErrorText32A(uError, xstr, uSize);
3187     
3188     lstrcpyAtoW(lpText,xstr);
3189     HeapFree(GetProcessHeap(),0,xstr);
3190     return ret;
3191 }
3192
3193
3194 /**************************************************************************
3195  *                              waveGetErrorText                [internal]
3196  */
3197 static UINT16 waveGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize)
3198 {
3199     LPSTR       msgptr;
3200     TRACE(mmsys, "(%04X, %p, %d);\n", 
3201           uError, lpText, uSize);
3202     if ((lpText == NULL) || (uSize < 1)) return(FALSE);
3203     lpText[0] = '\0';
3204     switch (uError) {
3205     case MMSYSERR_NOERROR:
3206         msgptr = "The specified command was carried out.";
3207         break;
3208     case MMSYSERR_ERROR:
3209         msgptr = "Undefined external error.";
3210         break;
3211     case MMSYSERR_BADDEVICEID:
3212         msgptr = "A device ID has been used that is out of range for your system.";
3213         break;
3214     case MMSYSERR_NOTENABLED:
3215         msgptr = "The driver was not enabled.";
3216         break;
3217     case MMSYSERR_ALLOCATED:
3218         msgptr = "The specified device is already in use. Wait until it is free, and then try again.";
3219         break;
3220     case MMSYSERR_INVALHANDLE:
3221         msgptr = "The specified device handle is invalid.";
3222         break;
3223     case MMSYSERR_NODRIVER:
3224         msgptr = "There is no driver installed on your system !\n";
3225         break;
3226     case MMSYSERR_NOMEM:
3227         msgptr = "Not enough memory available for this task. Quit one or more applications to increase available memory, and then try again.";
3228         break;
3229     case MMSYSERR_NOTSUPPORTED:
3230         msgptr = "This function is not supported. Use the Capabilities function to determine which functions and messages the driver supports.";
3231         break;
3232     case MMSYSERR_BADERRNUM:
3233         msgptr = "An error number was specified that is not defined in the system.";
3234         break;
3235     case MMSYSERR_INVALFLAG:
3236         msgptr = "An invalid flag was passed to a system function.";
3237         break;
3238     case MMSYSERR_INVALPARAM:
3239         msgptr = "An invalid parameter was passed to a system function.";
3240         break;
3241     case WAVERR_BADFORMAT:
3242         msgptr = "The specified format is not supported or cannot be translated. Use the Capabilities function to determine the supported formats";
3243         break;
3244     case WAVERR_STILLPLAYING:
3245         msgptr = "Cannot perform this operation while media data is still playing. Reset the device, or wait until the data is finished playing.";
3246         break;
3247     case WAVERR_UNPREPARED:
3248         msgptr = "The wave header was not prepared. Use the Prepare function to prepare the header, and then try again.";
3249         break;
3250     case WAVERR_SYNC:
3251         msgptr = "Cannot open the device without using the WAVE_ALLOWSYNC flag. Use the flag, and then try again.";
3252         break;
3253     default:
3254         msgptr = "Unknown MMSYSTEM Error !\n";
3255         break;
3256     }
3257     lstrcpyn32A(lpText, msgptr, uSize);
3258     return TRUE;
3259 }
3260
3261 /**************************************************************************
3262  *                      waveOutOpen                     [WINMM.173]
3263  * All the args/structs have the same layout as the win16 equivalents
3264  */
3265 UINT32 WINAPI waveOutOpen32(HWAVEOUT32 * lphWaveOut, UINT32 uDeviceID,
3266                             const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
3267                             DWORD dwInstance, DWORD dwFlags)
3268 {
3269     HWAVEOUT16  hwo16;
3270     UINT32      ret = waveOutOpen16(&hwo16,uDeviceID,lpFormat,dwCallback,dwInstance,
3271                                     CALLBACK32CONV(dwFlags));
3272
3273     if (lphWaveOut) *lphWaveOut=hwo16;
3274     return ret;
3275 }
3276 /**************************************************************************
3277  *                      waveOutOpen                     [MMSYSTEM.404]
3278  */
3279 UINT16 WINAPI waveOutOpen16(HWAVEOUT16 * lphWaveOut, UINT16 uDeviceID,
3280                             const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
3281                             DWORD dwInstance, DWORD dwFlags)
3282 {
3283     HWAVEOUT16  hWaveOut;
3284     LPWAVEOPENDESC      lpDesc;
3285     DWORD               dwRet = 0;
3286     BOOL32              bMapperFlg = FALSE;
3287     
3288     TRACE(mmsys, "(%p, %d, %p, %08lX, %08lX, %08lX);\n", 
3289           lphWaveOut, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags);
3290     if (dwFlags & WAVE_FORMAT_QUERY)
3291         TRACE(mmsys, "WAVE_FORMAT_QUERY requested !\n");
3292     if (uDeviceID == (UINT16)WAVE_MAPPER) {
3293         TRACE(mmsys, "WAVE_MAPPER mode requested !\n");
3294         bMapperFlg = TRUE;
3295         uDeviceID = 0;
3296     }
3297     if (lpFormat == NULL) return WAVERR_BADFORMAT;
3298     
3299     hWaveOut = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
3300     if (lphWaveOut != NULL) *lphWaveOut = hWaveOut;
3301     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3302     if (lpDesc == NULL) return MMSYSERR_NOMEM;
3303     lpDesc->hWave = hWaveOut;
3304     lpDesc->lpFormat = (LPWAVEFORMAT)lpFormat;  /* should the struct be copied iso pointer? */
3305     lpDesc->dwCallBack = dwCallback;
3306     lpDesc->dwInstance = dwInstance;
3307     if (uDeviceID >= MAXWAVEDRIVERS)
3308         uDeviceID = 0;
3309     while (uDeviceID < MAXWAVEDRIVERS) {
3310         dwRet = wodMessage(uDeviceID, WODM_OPEN, 
3311                            lpDesc->dwInstance, (DWORD)lpDesc, dwFlags);
3312         if (dwRet == MMSYSERR_NOERROR) break;
3313         if (!bMapperFlg) break;
3314         uDeviceID++;
3315         TRACE(mmsys, "WAVE_MAPPER mode ! try next driver...\n");
3316     }
3317     lpDesc->uDeviceID = uDeviceID;  /* save physical Device ID */
3318     if (dwFlags & WAVE_FORMAT_QUERY) {
3319         TRACE(mmsys, "End of WAVE_FORMAT_QUERY !\n");
3320         dwRet = waveOutClose32(hWaveOut);
3321     }
3322     return dwRet;
3323 }
3324
3325 /**************************************************************************
3326  *                              waveOutClose            [WINMM.161]
3327  */
3328 UINT32 WINAPI waveOutClose32(HWAVEOUT32 hWaveOut)
3329 {
3330     return waveOutClose16(hWaveOut);
3331 }
3332 /**************************************************************************
3333  *                              waveOutClose            [MMSYSTEM.405]
3334  */
3335 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
3336 {
3337     LPWAVEOPENDESC      lpDesc;
3338     
3339     TRACE(mmsys, "(%04X)\n", hWaveOut);
3340     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3341     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3342     return wodMessage( lpDesc->uDeviceID, WODM_CLOSE, lpDesc->dwInstance, 0L, 0L);
3343 }
3344
3345 /**************************************************************************
3346  *                              waveOutPrepareHeader    [WINMM.175]
3347  */
3348 UINT32 WINAPI waveOutPrepareHeader32(HWAVEOUT32 hWaveOut,
3349                                      WAVEHDR * lpWaveOutHdr, UINT32 uSize)
3350 {
3351     LPWAVEOPENDESC      lpDesc;
3352     
3353     TRACE(mmsys, "(%04X, %p, %u);\n", 
3354           hWaveOut, lpWaveOutHdr, uSize);
3355     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3356     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3357     return wodMessage( lpDesc->uDeviceID, WODM_PREPARE, lpDesc->dwInstance, 
3358                        (DWORD)lpWaveOutHdr,uSize);
3359 }
3360 /**************************************************************************
3361  *                              waveOutPrepareHeader    [MMSYSTEM.406]
3362  */
3363 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut,
3364                                      WAVEHDR * lpWaveOutHdr, UINT16 uSize)
3365 {
3366     LPWAVEOPENDESC      lpDesc;
3367     LPBYTE              saveddata = lpWaveOutHdr->lpData;
3368     UINT16              ret;
3369     
3370     TRACE(mmsys, "(%04X, %p, %u);\n", 
3371           hWaveOut, lpWaveOutHdr, uSize);
3372     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3373     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3374     lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3375     ret = wodMessage( lpDesc->uDeviceID, WODM_PREPARE, lpDesc->dwInstance, 
3376                       (DWORD)lpWaveOutHdr,uSize);
3377     lpWaveOutHdr->lpData = saveddata;
3378     return ret;
3379 }
3380
3381 /**************************************************************************
3382  *                              waveOutUnprepareHeader  [WINMM.181]
3383  */
3384 UINT32 WINAPI waveOutUnprepareHeader32(HWAVEOUT32 hWaveOut,
3385                                        WAVEHDR * lpWaveOutHdr, UINT32 uSize)
3386 {
3387     LPWAVEOPENDESC      lpDesc;
3388     
3389     TRACE(mmsys, "(%04X, %p, %u);\n", 
3390           hWaveOut, lpWaveOutHdr, uSize);
3391     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3392     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3393     return wodMessage(lpDesc->uDeviceID,WODM_UNPREPARE,lpDesc->dwInstance, 
3394                       (DWORD)lpWaveOutHdr, uSize);
3395 }
3396 /**************************************************************************
3397  *                              waveOutUnprepareHeader  [MMSYSTEM.407]
3398  */
3399 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut,
3400                                        WAVEHDR * lpWaveOutHdr, UINT16 uSize)
3401 {
3402     LPWAVEOPENDESC      lpDesc;
3403     LPBYTE              saveddata = lpWaveOutHdr->lpData;
3404     UINT16              ret;
3405     
3406     TRACE(mmsys, "(%04X, %p, %u);\n", 
3407           hWaveOut, lpWaveOutHdr, uSize);
3408     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3409     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3410     lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3411     ret = wodMessage(lpDesc->uDeviceID,WODM_UNPREPARE,lpDesc->dwInstance, 
3412                      (DWORD)lpWaveOutHdr, uSize);
3413     lpWaveOutHdr->lpData = saveddata;
3414     return ret;
3415 }
3416
3417 /**************************************************************************
3418  *                              waveOutWrite            [MMSYSTEM.408]
3419  */
3420 UINT32 WINAPI waveOutWrite32(HWAVEOUT32 hWaveOut, WAVEHDR * lpWaveOutHdr,
3421                              UINT32 uSize)
3422 {
3423     LPWAVEOPENDESC      lpDesc;
3424     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3425     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3426     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3427     lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3428     return wodMessage( lpDesc->uDeviceID, WODM_WRITE, lpDesc->dwInstance, (DWORD)lpWaveOutHdr, uSize);
3429 }
3430 /**************************************************************************
3431  *                              waveOutWrite            [MMSYSTEM.408]
3432  */
3433 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut, WAVEHDR * lpWaveOutHdr,
3434                              UINT16 uSize)
3435 {
3436     LPWAVEOPENDESC      lpDesc;
3437     UINT16              ret;
3438     
3439     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3440     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3441     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3442     lpWaveOutHdr->reserved=(DWORD)lpWaveOutHdr->lpData;/*save original ptr*/
3443     lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3444     ret = wodMessage( lpDesc->uDeviceID, WODM_WRITE, lpDesc->dwInstance, (DWORD)lpWaveOutHdr, uSize);
3445     lpWaveOutHdr->lpData = (LPBYTE)lpWaveOutHdr->reserved;
3446     return ret;
3447 }
3448
3449 /**************************************************************************
3450  *                              waveOutPause            [WINMM.174]
3451  */
3452 UINT32 WINAPI waveOutPause32(HWAVEOUT32 hWaveOut)
3453 {
3454     return waveOutPause16(hWaveOut);
3455 }
3456
3457 /**************************************************************************
3458  *                              waveOutPause            [MMSYSTEM.409]
3459  */
3460 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut)
3461 {
3462     LPWAVEOPENDESC      lpDesc;
3463     
3464     TRACE(mmsys, "(%04X)\n", hWaveOut);
3465     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3466     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3467     return wodMessage( lpDesc->uDeviceID, WODM_PAUSE, lpDesc->dwInstance, 0L, 0L);
3468 }
3469
3470 /**************************************************************************
3471  *                              waveOutRestart          [WINMM.177]
3472  */
3473 UINT32 WINAPI waveOutRestart32(HWAVEOUT32 hWaveOut)
3474 {
3475     return waveOutRestart16(hWaveOut);
3476 }
3477
3478 /**************************************************************************
3479  *                              waveOutRestart          [MMSYSTEM.410]
3480  */
3481 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut)
3482 {
3483     LPWAVEOPENDESC      lpDesc;
3484     
3485     TRACE(mmsys, "(%04X)\n", hWaveOut);
3486     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3487     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3488     return wodMessage( lpDesc->uDeviceID, WODM_RESTART, lpDesc->dwInstance, 0L, 0L);
3489 }
3490
3491 /**************************************************************************
3492  *                              waveOutReset            [WINMM.176]
3493  */
3494 UINT32 WINAPI waveOutReset32(HWAVEOUT32 hWaveOut)
3495 {
3496     return waveOutReset16(hWaveOut);
3497 }
3498
3499 /**************************************************************************
3500  *                              waveOutReset            [MMSYSTEM.411]
3501  */
3502 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut)
3503 {
3504     LPWAVEOPENDESC      lpDesc;
3505     TRACE(mmsys, "(%04X)\n", hWaveOut);
3506     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3507     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3508     return wodMessage( lpDesc->uDeviceID, WODM_RESET, lpDesc->dwInstance, 0L, 0L);
3509 }
3510
3511 /**************************************************************************
3512  *                              waveOutGetPosition      [WINMM.170]
3513  */
3514 UINT32 WINAPI waveOutGetPosition32(HWAVEOUT32 hWaveOut, LPMMTIME32 lpTime,
3515                                    UINT32 uSize)
3516 {
3517     MMTIME16    mmt16;
3518     UINT32 ret;
3519     
3520     mmt16.wType = lpTime->wType;
3521     ret = waveOutGetPosition16(hWaveOut,&mmt16,sizeof(mmt16));
3522     MMSYSTEM_MMTIME16to32(lpTime,&mmt16);
3523     return ret;
3524 }
3525 /**************************************************************************
3526  *                              waveOutGetPosition      [MMSYSTEM.412]
3527  */
3528 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut,LPMMTIME16 lpTime,
3529                                    UINT16 uSize)
3530 {
3531     LPWAVEOPENDESC      lpDesc;
3532     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpTime, uSize);
3533     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3534     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3535     return wodMessage( lpDesc->uDeviceID, WODM_GETPOS, lpDesc->dwInstance, 
3536                        (DWORD)lpTime, (DWORD)uSize);
3537 }
3538
3539 #define WAVEOUT_SHORTCUT_1(xx,XX,atype) \
3540         UINT32 WINAPI waveOut##xx##32(HWAVEOUT32 hWaveOut, atype x)     \
3541 {                                                                       \
3542         return waveOut##xx##16(hWaveOut,x);                             \
3543 }                                                                       \
3544 UINT16 WINAPI waveOut##xx##16(HWAVEOUT16 hWaveOut, atype x)             \
3545 {                                                                       \
3546         LPWAVEOPENDESC  lpDesc;                                         \
3547         TRACE(mmsys, "waveOut"#xx"(%04X, %08lx);\n", hWaveOut,(DWORD)x);\
3548         lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);         \
3549         if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;                \
3550         return wodMessage(lpDesc->uDeviceID, WODM_##XX, lpDesc->dwInstance,\
3551                           (DWORD)x, 0L);                                \
3552 }
3553
3554 WAVEOUT_SHORTCUT_1(GetPitch,GETPITCH,DWORD*)
3555 WAVEOUT_SHORTCUT_1(SetPitch,SETPITCH,DWORD)
3556 WAVEOUT_SHORTCUT_1(GetPlaybackRate,GETPLAYBACKRATE,DWORD*)
3557 WAVEOUT_SHORTCUT_1(SetPlaybackRate,SETPLAYBACKRATE,DWORD)
3558     
3559 #define WAVEOUT_SHORTCUT_2(xx,XX,atype) \
3560         UINT32 WINAPI waveOut##xx##32(UINT32 devid, atype x)            \
3561 {                                                                       \
3562         return waveOut##xx##16(devid,x);                                \
3563 }                                                                       \
3564 UINT16 WINAPI waveOut##xx##16(UINT16 devid, atype x)                    \
3565 {                                                                       \
3566         TRACE(mmsys, "waveOut"#xx"(%04X, %08lx);\n", devid,(DWORD)x);   \
3567         return wodMessage(devid, WODM_##XX, 0L, (DWORD)x, 0L);          \
3568 }
3569     
3570     
3571 WAVEOUT_SHORTCUT_2(GetVolume,GETVOLUME,DWORD*)
3572 WAVEOUT_SHORTCUT_2(SetVolume,SETVOLUME,DWORD)
3573     
3574     
3575 /**************************************************************************
3576  *                              waveOutBreakLoop        [MMSYSTEM.419]
3577  */
3578 UINT32 WINAPI waveOutBreakLoop32(HWAVEOUT32 hWaveOut)
3579 {
3580     return waveOutBreakLoop16(hWaveOut);
3581 }
3582 /**************************************************************************
3583  *                              waveOutBreakLoop        [MMSYSTEM.419]
3584  */
3585 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut)
3586 {
3587     TRACE(mmsys, "(%04X)\n", hWaveOut);
3588     return MMSYSERR_INVALHANDLE;
3589 }
3590
3591 /**************************************************************************
3592  *                              waveOutGetID            [MMSYSTEM.420]
3593  */
3594 UINT32 WINAPI waveOutGetID32(HWAVEOUT32 hWaveOut, UINT32 * lpuDeviceID)
3595 {
3596     LPWAVEOPENDESC      lpDesc;
3597     TRACE(mmsys, "(%04X, %p);\n", hWaveOut, lpuDeviceID);
3598     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3599     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3600     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
3601     *lpuDeviceID = lpDesc->uDeviceID;
3602     return 0;
3603 }
3604 /**************************************************************************
3605  *                              waveOutGetID            [MMSYSTEM.420]
3606  */
3607 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16 * lpuDeviceID)
3608 {
3609     LPWAVEOPENDESC      lpDesc;
3610     TRACE(mmsys, "(%04X, %p);\n", hWaveOut, lpuDeviceID);
3611     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3612     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3613     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
3614     *lpuDeviceID = lpDesc->uDeviceID;
3615     return 0;
3616 }
3617
3618 /**************************************************************************
3619  *                              waveOutMessage          [MMSYSTEM.421]
3620  */
3621 DWORD WINAPI waveOutMessage32(HWAVEOUT32 hWaveOut, UINT32 uMessage, 
3622                               DWORD dwParam1, DWORD dwParam2)
3623 {
3624     LPWAVEOPENDESC      lpDesc;
3625     
3626     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3627     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3628     switch (uMessage) {
3629     case WODM_GETNUMDEVS:
3630     case WODM_GETPOS:
3631     case WODM_GETVOLUME:
3632     case WODM_GETPITCH:
3633     case WODM_GETPLAYBACKRATE:
3634     case WODM_SETVOLUME:
3635     case WODM_SETPITCH:
3636     case WODM_SETPLAYBACKRATE:
3637     case WODM_RESET:
3638     case WODM_PAUSE:
3639     case WODM_PREPARE:
3640     case WODM_UNPREPARE:
3641     case WODM_STOP:
3642     case WODM_CLOSE:
3643         /* no argument conversion needed */
3644         break;
3645     case WODM_WRITE:
3646         return waveOutWrite32(hWaveOut,(LPWAVEHDR)dwParam1,dwParam2);
3647     case WODM_GETDEVCAPS:
3648         /* FIXME: UNICODE/ANSI? */
3649         return waveOutGetDevCaps32A(hWaveOut,(LPWAVEOUTCAPS32A)dwParam1,dwParam2);
3650     case WODM_OPEN:
3651         FIXME(mmsys,"can't handle WODM_OPEN, please report.\n");
3652         break;
3653     default:
3654         ERR(mmsys,"(0x%04x,0x%04x,%08lx,%08lx): unhandled message\n",
3655             hWaveOut,uMessage,dwParam1,dwParam2);
3656         break;
3657     }
3658     return wodMessage( lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
3659 }
3660
3661 /**************************************************************************
3662  *                              waveOutMessage          [MMSYSTEM.421]
3663  */
3664 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage, 
3665                               DWORD dwParam1, DWORD dwParam2)
3666 {
3667     LPWAVEOPENDESC      lpDesc;
3668     
3669     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3670     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3671     switch (uMessage) {
3672     case WODM_GETNUMDEVS:
3673     case WODM_SETVOLUME:
3674     case WODM_SETPITCH:
3675     case WODM_SETPLAYBACKRATE:
3676     case WODM_RESET:
3677     case WODM_PAUSE:
3678     case WODM_STOP:
3679     case WODM_CLOSE:
3680         /* no argument conversion needed */
3681         break;
3682     case WODM_GETPOS:
3683         return waveOutGetPosition16(hWaveOut,(LPMMTIME16)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3684     case WODM_GETVOLUME:
3685         return waveOutGetVolume16(hWaveOut,(LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3686     case WODM_GETPITCH:
3687         return waveOutGetPitch16(hWaveOut,(LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3688     case WODM_GETPLAYBACKRATE:
3689         return waveOutGetPlaybackRate16(hWaveOut,(LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3690     case WODM_GETDEVCAPS:
3691         return waveOutGetDevCaps16(hWaveOut,(LPWAVEOUTCAPS16)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3692     case WODM_PREPARE:
3693         return waveOutPrepareHeader16(hWaveOut,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3694     case WODM_UNPREPARE:
3695         return waveOutUnprepareHeader16(hWaveOut,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3696     case WODM_WRITE:
3697         return waveOutWrite16(hWaveOut,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
3698     case WODM_OPEN:
3699         FIXME(mmsys,"can't handle WODM_OPEN, please report.\n");
3700         break;
3701     default:
3702         ERR(mmsys,"(0x%04x,0x%04x,%08lx,%08lx): unhandled message\n",
3703             hWaveOut,uMessage,dwParam1,dwParam2);
3704     }
3705     return wodMessage( lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
3706 }
3707
3708 /**************************************************************************
3709  *                              waveInGetNumDevs                [WINMM.151]
3710  */
3711 UINT32 WINAPI waveInGetNumDevs32()
3712 {
3713     return waveInGetNumDevs16();
3714 }
3715
3716 /**************************************************************************
3717  *                              waveInGetNumDevs                [MMSYSTEM.501]
3718  */
3719 UINT16 WINAPI waveInGetNumDevs16()
3720 {
3721     UINT16      count = 0;
3722     TRACE(mmsys, "waveInGetNumDevs\n");
3723     count += widMessage(0, WIDM_GETNUMDEVS, 0L, 0L, 0L);
3724     TRACE(mmsys, "waveInGetNumDevs return %u \n", count);
3725     return count;
3726 }
3727
3728 /**************************************************************************
3729  *                              waveInGetDevCapsA               [WINMM.147]
3730  */
3731 UINT32 WINAPI waveInGetDevCaps32W(UINT32 uDeviceID, LPWAVEINCAPS32W lpCaps, UINT32 uSize)
3732 {
3733     WAVEINCAPS16        wic16;
3734     UINT32      ret = waveInGetDevCaps16(uDeviceID,&wic16,uSize);
3735     
3736     lpCaps->wMid = wic16.wMid;
3737     lpCaps->wPid = wic16.wPid;
3738     lpCaps->vDriverVersion = wic16.vDriverVersion;
3739     lstrcpyAtoW(lpCaps->szPname,wic16.szPname);
3740     lpCaps->dwFormats = wic16.dwFormats;
3741     lpCaps->wChannels = wic16.wChannels;
3742     
3743     return ret;
3744 }
3745 /**************************************************************************
3746  *                              waveInGetDevCapsA               [WINMM.146]
3747  */
3748 UINT32 WINAPI waveInGetDevCaps32A(UINT32 uDeviceID, LPWAVEINCAPS32A lpCaps, UINT32 uSize)
3749 {
3750     WAVEINCAPS16        wic16;
3751     UINT32      ret = waveInGetDevCaps16(uDeviceID,&wic16,uSize);
3752     
3753     lpCaps->wMid = wic16.wMid;
3754     lpCaps->wPid = wic16.wPid;
3755     lpCaps->vDriverVersion = wic16.vDriverVersion;
3756     strcpy(lpCaps->szPname,wic16.szPname);
3757     lpCaps->dwFormats = wic16.dwFormats;
3758     lpCaps->wChannels = wic16.wChannels;
3759     return ret;
3760 }
3761 /**************************************************************************
3762  *                              waveInGetDevCaps                [MMSYSTEM.502]
3763  */
3764 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps, UINT16 uSize)
3765 {
3766     TRACE(mmsys, "waveInGetDevCaps\n");
3767     return widMessage(uDeviceID, WIDM_GETDEVCAPS, 0L, (DWORD)lpCaps, uSize);
3768 }
3769
3770 /**************************************************************************
3771  *                              waveInGetErrorTextA     [WINMM.148]
3772  */
3773 UINT32 WINAPI waveInGetErrorText32A(UINT32 uError, LPSTR lpText, UINT32 uSize)
3774 {
3775     TRACE(mmsys, "waveInGetErrorText\n");
3776     return(waveGetErrorText(uError, lpText, uSize));
3777 }
3778
3779 /**************************************************************************
3780  *                              waveInGetErrorTextW     [WINMM.149]
3781  */
3782 UINT32 WINAPI waveInGetErrorText32W(UINT32 uError, LPWSTR lpText, UINT32 uSize)
3783 {
3784     LPSTR txt = HeapAlloc(GetProcessHeap(),0,uSize);
3785     UINT32      ret = waveGetErrorText(uError, txt, uSize);
3786     
3787     lstrcpyAtoW(lpText,txt);
3788     HeapFree(GetProcessHeap(),0,txt);
3789     return ret;
3790 }
3791
3792 /**************************************************************************
3793  *                              waveInGetErrorText      [MMSYSTEM.503]
3794  */
3795 UINT16 WINAPI waveInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
3796 {
3797     TRACE(mmsys, "waveInGetErrorText\n");
3798     return(waveGetErrorText(uError, lpText, uSize));
3799 }
3800
3801
3802 /**************************************************************************
3803  *                              waveInOpen                      [WINMM.154]
3804  */
3805 UINT32 WINAPI waveInOpen32(HWAVEIN32 * lphWaveIn, UINT32 uDeviceID,
3806                            const LPWAVEFORMAT lpFormat, DWORD dwCallback,
3807                            DWORD dwInstance, DWORD dwFlags)
3808 {
3809     HWAVEIN16   hwin16;
3810     UINT32      ret = waveInOpen16(&hwin16,uDeviceID,lpFormat,dwCallback,dwInstance,
3811                                  CALLBACK32CONV(dwFlags));
3812     if (lphWaveIn) *lphWaveIn = hwin16;
3813     return ret;
3814 }
3815
3816 /**************************************************************************
3817  *                              waveInOpen                      [MMSYSTEM.504]
3818  */
3819 UINT16 WINAPI waveInOpen16(HWAVEIN16 * lphWaveIn, UINT16 uDeviceID,
3820                            const LPWAVEFORMAT lpFormat, DWORD dwCallback,
3821                            DWORD dwInstance, DWORD dwFlags)
3822 {
3823     HWAVEIN16 hWaveIn;
3824     LPWAVEOPENDESC      lpDesc;
3825     DWORD       dwRet = 0;
3826     BOOL32      bMapperFlg = FALSE;
3827     TRACE(mmsys, "(%p, %d, %p, %08lX, %08lX, %08lX);\n", 
3828           lphWaveIn, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags);
3829     if (dwFlags & WAVE_FORMAT_QUERY)
3830         TRACE(mmsys, "WAVE_FORMAT_QUERY requested !\n");
3831     if (uDeviceID == (UINT16)WAVE_MAPPER) {
3832         TRACE(mmsys, "WAVE_MAPPER mode requested !\n");
3833         bMapperFlg = TRUE;
3834         uDeviceID = 0;
3835     }
3836     if (lpFormat == NULL) return WAVERR_BADFORMAT;
3837     hWaveIn = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
3838     if (lphWaveIn != NULL) *lphWaveIn = hWaveIn;
3839     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3840     if (lpDesc == NULL) return MMSYSERR_NOMEM;
3841     lpDesc->hWave = hWaveIn;
3842     lpDesc->lpFormat = lpFormat;
3843     lpDesc->dwCallBack = dwCallback;
3844     lpDesc->dwInstance = dwInstance;
3845     while (uDeviceID < MAXWAVEDRIVERS) {
3846         dwRet = widMessage(uDeviceID, WIDM_OPEN, 
3847                            lpDesc->dwInstance, (DWORD)lpDesc, 0L);
3848         if (dwRet == MMSYSERR_NOERROR) break;
3849         if (!bMapperFlg) break;
3850         uDeviceID++;
3851         TRACE(mmsys, "WAVE_MAPPER mode ! try next driver...\n");
3852     }
3853     lpDesc->uDeviceID = uDeviceID;
3854     if (dwFlags & WAVE_FORMAT_QUERY) {
3855         TRACE(mmsys, "End of WAVE_FORMAT_QUERY !\n");
3856         dwRet = waveInClose16(hWaveIn);
3857     }
3858     return dwRet;
3859 }
3860
3861 /**************************************************************************
3862  *                              waveInClose                     [WINMM.145]
3863  */
3864 UINT32 WINAPI waveInClose32(HWAVEIN32 hWaveIn)
3865 {
3866     return waveInClose16(hWaveIn);
3867 }
3868 /**************************************************************************
3869  *                              waveInClose                     [MMSYSTEM.505]
3870  */
3871 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
3872 {
3873     LPWAVEOPENDESC      lpDesc;
3874     
3875     TRACE(mmsys, "(%04X)\n", hWaveIn);
3876     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3877     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3878     return widMessage(lpDesc->uDeviceID, WIDM_CLOSE, lpDesc->dwInstance, 0L, 0L);
3879 }
3880
3881 /**************************************************************************
3882  *                              waveInPrepareHeader             [WINMM.155]
3883  */
3884 UINT32 WINAPI waveInPrepareHeader32(HWAVEIN32 hWaveIn,
3885                                     WAVEHDR * lpWaveInHdr, UINT32 uSize)
3886 {
3887     LPWAVEOPENDESC      lpDesc;
3888     
3889     TRACE(mmsys, "(%04X, %p, %u);\n", 
3890           hWaveIn, lpWaveInHdr, uSize);
3891     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3892     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3893     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3894     lpWaveInHdr = lpWaveInHdr;
3895     lpWaveInHdr->lpNext = NULL;
3896     lpWaveInHdr->dwBytesRecorded = 0;
3897     TRACE(mmsys, "lpData=%p size=%lu \n", 
3898           lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3899     return widMessage(lpDesc->uDeviceID,WIDM_PREPARE,lpDesc->dwInstance, 
3900                       (DWORD)lpWaveInHdr, uSize);
3901 }
3902 /**************************************************************************
3903  *                              waveInPrepareHeader             [MMSYSTEM.506]
3904  */
3905 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn,
3906                                     WAVEHDR * lpWaveInHdr, UINT16 uSize)
3907 {
3908     LPWAVEOPENDESC      lpDesc;
3909     LPBYTE              saveddata = lpWaveInHdr->lpData;
3910     UINT16              ret;
3911     
3912     TRACE(mmsys, "(%04X, %p, %u);\n", 
3913           hWaveIn, lpWaveInHdr, uSize);
3914     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3915     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3916     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3917     lpWaveInHdr = lpWaveInHdr;
3918     lpWaveInHdr->lpNext = NULL;
3919     lpWaveInHdr->dwBytesRecorded = 0;
3920     
3921     TRACE(mmsys, "lpData=%p size=%lu \n", 
3922           lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3923     lpWaveInHdr->lpData = PTR_SEG_TO_LIN(lpWaveInHdr->lpData);
3924     ret = widMessage(lpDesc->uDeviceID,WIDM_PREPARE,lpDesc->dwInstance, 
3925                      (DWORD)lpWaveInHdr,uSize);
3926     lpWaveInHdr->lpData = saveddata;
3927     return ret;
3928 }
3929
3930
3931 /**************************************************************************
3932  *                              waveInUnprepareHeader   [WINMM.159]
3933  */
3934 UINT32 WINAPI waveInUnprepareHeader32(HWAVEIN32 hWaveIn,
3935                                       WAVEHDR * lpWaveInHdr, UINT32 uSize)
3936 {
3937     LPWAVEOPENDESC      lpDesc;
3938     
3939     TRACE(mmsys, "(%04X, %p, %u);\n", 
3940           hWaveIn, lpWaveInHdr, uSize);
3941     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3942     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3943     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3944     /*USER_HEAP_FREE(HIWORD((DWORD)lpWaveInHdr->lpData)); FIXME */
3945     lpWaveInHdr->lpData = NULL;
3946     lpWaveInHdr->lpNext = NULL;
3947     return widMessage(lpDesc->uDeviceID,WIDM_UNPREPARE,lpDesc->dwInstance, 
3948                       (DWORD)lpWaveInHdr, uSize);
3949 }
3950 /**************************************************************************
3951  *                              waveInUnprepareHeader   [MMSYSTEM.507]
3952  */
3953 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn,
3954                                       WAVEHDR * lpWaveInHdr, UINT16 uSize)
3955 {
3956     LPWAVEOPENDESC      lpDesc;
3957     
3958     TRACE(mmsys, "(%04X, %p, %u);\n", 
3959           hWaveIn, lpWaveInHdr, uSize);
3960     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3961     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3962     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3963     /*USER_HEAP_FREE(HIWORD((DWORD)lpWaveInHdr->lpData)); FIXME */
3964     lpWaveInHdr->lpData = NULL;
3965     lpWaveInHdr->lpNext = NULL;
3966     return widMessage(lpDesc->uDeviceID,WIDM_UNPREPARE,lpDesc->dwInstance, 
3967                       (DWORD)lpWaveInHdr, uSize);
3968 }
3969
3970 /**************************************************************************
3971  *                              waveInAddBuffer         [WINMM.144]
3972  */
3973 UINT32 WINAPI waveInAddBuffer32(HWAVEIN32 hWaveIn,
3974                                 WAVEHDR * lpWaveInHdr, UINT32 uSize)
3975 {
3976     LPWAVEOPENDESC      lpDesc;
3977     
3978     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
3979     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3980     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3981     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3982     lpWaveInHdr->lpNext = NULL;
3983     lpWaveInHdr->dwBytesRecorded = 0;
3984     TRACE(mmsys, "lpData=%p size=%lu \n", 
3985           lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3986     return widMessage(lpDesc->uDeviceID, WIDM_ADDBUFFER, lpDesc->dwInstance,
3987                       (DWORD)lpWaveInHdr, uSize);
3988     
3989 }
3990
3991 /**************************************************************************
3992  *                              waveInAddBuffer         [MMSYSTEM.508]
3993  */
3994 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn,
3995                                 WAVEHDR * lpWaveInHdr, UINT16 uSize)
3996 {
3997     LPWAVEOPENDESC      lpDesc;
3998     UINT16              ret;
3999     
4000     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
4001     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4002     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4003     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
4004     lpWaveInHdr->lpNext = NULL;
4005     lpWaveInHdr->dwBytesRecorded = 0;
4006     lpWaveInHdr->lpData = PTR_SEG_TO_LIN(lpWaveInHdr->lpData);
4007     TRACE(mmsys, "lpData=%p size=%lu \n", 
4008           lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
4009     ret = widMessage(lpDesc->uDeviceID, WIDM_ADDBUFFER, lpDesc->dwInstance,
4010                      (DWORD)lpWaveInHdr, uSize);
4011     /*lpWaveInHdr->lpData = saveddata;*/
4012     return ret;
4013 }
4014
4015 /**************************************************************************
4016  *                              waveInStart                     [WINMM.157]
4017  */
4018 UINT32 WINAPI waveInStart32(HWAVEIN32 hWaveIn)
4019 {
4020     return waveInStart16(hWaveIn);
4021 }
4022
4023 /**************************************************************************
4024  *                              waveInStart                     [MMSYSTEM.509]
4025  */
4026 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn)
4027 {
4028     LPWAVEOPENDESC      lpDesc;
4029     
4030     TRACE(mmsys, "(%04X)\n", hWaveIn);
4031     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4032     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4033     return widMessage(lpDesc->uDeviceID,WIDM_START,lpDesc->dwInstance,0,0);
4034 }
4035
4036 /**************************************************************************
4037  *                              waveInStop                      [WINMM.158]
4038  */
4039 UINT32 WINAPI waveInStop32(HWAVEIN32 hWaveIn)
4040 {
4041     return waveInStop16(hWaveIn);
4042 }
4043
4044 /**************************************************************************
4045  *                              waveInStop                      [MMSYSTEM.510]
4046  */
4047 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn)
4048 {
4049     LPWAVEOPENDESC      lpDesc;
4050     
4051     TRACE(mmsys, "(%04X)\n", hWaveIn);
4052     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4053     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4054     return widMessage(lpDesc->uDeviceID, WIDM_STOP, lpDesc->dwInstance, 0L, 0L);
4055 }
4056
4057 /**************************************************************************
4058  *                              waveInReset                     [WINMM.156]
4059  */
4060 UINT32 WINAPI waveInReset32(HWAVEIN32 hWaveIn)
4061 {
4062     return waveInReset16(hWaveIn);
4063 }
4064
4065 /**************************************************************************
4066  *                              waveInReset                     [MMSYSTEM.511]
4067  */
4068 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn)
4069 {
4070     LPWAVEOPENDESC      lpDesc;
4071     
4072     TRACE(mmsys, "(%04X)\n", hWaveIn);
4073     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4074     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4075     return widMessage(lpDesc->uDeviceID,WIDM_RESET,lpDesc->dwInstance,0,0);
4076 }
4077
4078 /**************************************************************************
4079  *                              waveInGetPosition       [WINMM.152]
4080  */
4081 UINT32 WINAPI waveInGetPosition32(HWAVEIN32 hWaveIn, LPMMTIME32 lpTime,
4082                                   UINT32 uSize)
4083 {
4084     MMTIME16    mmt16;
4085     UINT32      ret = waveInGetPosition16(hWaveIn,&mmt16,uSize);
4086     
4087     MMSYSTEM_MMTIME16to32(lpTime,&mmt16);
4088     return ret;
4089 }
4090
4091 /**************************************************************************
4092  *                              waveInGetPosition       [MMSYSTEM.512]
4093  */
4094 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn,LPMMTIME16 lpTime,
4095                                   UINT16 uSize)
4096 {
4097     LPWAVEOPENDESC      lpDesc;
4098     
4099     TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpTime, uSize);
4100     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4101     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4102     return widMessage(lpDesc->uDeviceID, WIDM_GETPOS, lpDesc->dwInstance,
4103                       (DWORD)lpTime, (DWORD)uSize);
4104 }
4105
4106 /**************************************************************************
4107  *                              waveInGetID                     [WINMM.150]
4108  */
4109 UINT32 WINAPI waveInGetID32(HWAVEIN32 hWaveIn, UINT32 * lpuDeviceID)
4110 {
4111     LPWAVEOPENDESC      lpDesc;
4112     
4113     TRACE(mmsys, "waveInGetID\n");
4114     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
4115     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4116     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4117     *lpuDeviceID = lpDesc->uDeviceID;
4118     return 0;
4119 }
4120
4121
4122 /**************************************************************************
4123  *                              waveInGetID                     [MMSYSTEM.513]
4124  */
4125 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16 * lpuDeviceID)
4126 {
4127     LPWAVEOPENDESC      lpDesc;
4128     
4129     TRACE(mmsys, "waveInGetID\n");
4130     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
4131     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4132     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4133     *lpuDeviceID = lpDesc->uDeviceID;
4134     return 0;
4135 }
4136
4137 /**************************************************************************
4138  *                              waveInMessage           [WINMM.153]
4139  */
4140 DWORD WINAPI waveInMessage32(HWAVEIN32 hWaveIn, UINT32 uMessage,
4141                              DWORD dwParam1, DWORD dwParam2)
4142 {
4143     LPWAVEOPENDESC      lpDesc;
4144     
4145     FIXME(mmsys, "(%04X, %04X, %08lX, %08lX),FIXME!\n", 
4146           hWaveIn, uMessage, dwParam1, dwParam2);
4147     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4148     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4149     switch (uMessage) {
4150     case WIDM_OPEN:
4151         FIXME(mmsys, "cannot handle WIDM_OPEN, please report.\n");
4152         break;
4153     case WIDM_GETNUMDEVS:
4154     case WIDM_GETPOS:
4155     case WIDM_CLOSE:
4156     case WIDM_STOP :
4157     case WIDM_RESET:
4158     case WIDM_START:
4159     case WIDM_PREPARE:
4160     case WIDM_UNPREPARE:
4161     case WIDM_ADDBUFFER:
4162     case WIDM_PAUSE:
4163         /* no argument conversion needed */
4164         break;
4165     case WIDM_GETDEVCAPS:
4166         /*FIXME: ANSI/UNICODE */
4167         return waveInGetDevCaps32A(hWaveIn,(LPWAVEINCAPS32A)dwParam1,dwParam2);
4168     default:
4169         ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
4170             hWaveIn,uMessage,dwParam1,dwParam2);
4171         break;
4172     }
4173     return widMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
4174 }
4175
4176 /**************************************************************************
4177  *                              waveInMessage           [MMSYSTEM.514]
4178  */
4179 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
4180                              DWORD dwParam1, DWORD dwParam2)
4181 {
4182     LPWAVEOPENDESC      lpDesc;
4183     
4184     FIXME(mmsys, "(%04X, %04X, %08lX, %08lX),FIXME!\n", 
4185           hWaveIn, uMessage, dwParam1, dwParam2);
4186     lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4187     if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4188     switch (uMessage) {
4189     case WIDM_OPEN:
4190         FIXME(mmsys,"cannot handle WIDM_OPEN, please report.\n");
4191         break;
4192     case WIDM_GETNUMDEVS:
4193     case WIDM_CLOSE:
4194     case WIDM_STOP :
4195     case WIDM_RESET:
4196     case WIDM_START:
4197     case WIDM_PAUSE:
4198         /* no argument conversion needed */
4199         break;
4200     case WIDM_GETDEVCAPS:
4201         return waveInGetDevCaps16(hWaveIn,(LPWAVEINCAPS16)PTR_SEG_TO_LIN(dwParam1),dwParam2);
4202     case WIDM_GETPOS:
4203         return waveInGetPosition16(hWaveIn,(LPMMTIME16)PTR_SEG_TO_LIN(dwParam1),dwParam2);
4204     case WIDM_PREPARE:
4205         return waveInPrepareHeader16(hWaveIn,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
4206     case WIDM_UNPREPARE:
4207         return waveInUnprepareHeader16(hWaveIn,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
4208     case WIDM_ADDBUFFER:
4209         return waveInAddBuffer16(hWaveIn,(LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1),dwParam2);
4210     default:
4211         ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
4212             hWaveIn,uMessage,dwParam1,dwParam2);
4213         break;
4214     }
4215     return widMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
4216 }
4217
4218 /**************************************************************************
4219  *                              DrvOpen                 [MMSYSTEM.1100]
4220  */
4221 HDRVR16 WINAPI DrvOpen(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
4222 {
4223     TRACE(mmsys,"('%s','%s',%08lX);\n",lpDriverName,lpSectionName,lParam);
4224     return OpenDriver16(lpDriverName, lpSectionName, lParam);
4225 }
4226
4227
4228 /**************************************************************************
4229  *                              DrvClose                [MMSYSTEM.1101]
4230  */
4231 LRESULT WINAPI DrvClose(HDRVR16 hDrvr, LPARAM lParam1, LPARAM lParam2)
4232 {
4233     TRACE(mmsys, "(%04X, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
4234     return CloseDriver16(hDrvr, lParam1, lParam2);
4235 }
4236
4237
4238 /**************************************************************************
4239  *                              DrvSendMessage          [MMSYSTEM.1102]
4240  */
4241 LRESULT WINAPI DrvSendMessage(HDRVR16 hDriver, WORD msg, LPARAM lParam1,
4242                               LPARAM lParam2)
4243 {
4244     DWORD       dwDriverID = 0;
4245     FIXME(mmsys, "(%04X, %04X, %08lX, %08lX);\n",
4246           hDriver, msg, lParam1, lParam2);
4247     /* FIXME: wrong ... */
4248     return CDAUDIO_DriverProc16(dwDriverID, hDriver, msg, lParam1, lParam2);
4249 }
4250
4251 /**************************************************************************
4252  *                              DrvGetModuleHandle      [MMSYSTEM.1103]
4253  */
4254 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrvr)
4255 {
4256     return GetDriverModuleHandle16(hDrvr);
4257 }
4258
4259 /**************************************************************************
4260  *                              DrvDefDriverProc        [MMSYSTEM.1104]
4261  */
4262 LRESULT WINAPI DrvDefDriverProc(DWORD dwDriverID, HDRVR16 hDriv, WORD wMsg, 
4263                                 DWORD dwParam1, DWORD dwParam2)
4264 {
4265     return DefDriverProc(dwDriverID, hDriv, wMsg, dwParam1, dwParam2);
4266 }
4267
4268 /**************************************************************************
4269  *                              mmThreadCreate          [MMSYSTEM.1120]
4270  */
4271 LRESULT WINAPI mmThreadCreate16(LPVOID x1, LPWORD x2, DWORD x3, DWORD x4) {
4272     FIXME(mmsys,"(%p,%p,%08lx,%08lx): stub!\n",x1,x2,x3,x4);
4273     *x2 = 0xbabe;
4274     return 0;
4275 }
4276
4277 /**************************************************************************
4278  *                              mmThreadGetTask         [MMSYSTEM.1125]
4279  */
4280 LRESULT WINAPI mmThreadGetTask16(WORD hnd) {
4281     FIXME(mmsys,"(%04x): stub!\n",hnd);
4282     return GetCurrentTask();
4283 }
4284
4285 /**************************************************************************
4286  *                              mmThreadSignal          [MMSYSTEM.1121]
4287  */
4288 LRESULT WINAPI mmThreadSignal16(WORD hnd) {
4289     FIXME(mmsys,"(%04x): stub!\n",hnd);
4290     return 0;
4291 }
4292
4293 /**************************************************************************
4294  *                              mmTaskCreate            [MMSYSTEM.900]
4295  */
4296 HINSTANCE16 WINAPI mmTaskCreate16(LPWORD lphnd,HINSTANCE16 *hMmTask,DWORD x2)
4297 {
4298     DWORD showCmd = 0x40002;
4299     LPSTR cmdline;
4300     WORD sel1, sel2;
4301     LOADPARAMS *lp;
4302     HINSTANCE16 ret, handle;
4303     
4304     TRACE(mmsys,"(%p,%p,%08lx);\n",lphnd,hMmTask,x2);
4305     cmdline = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 0x0d);
4306     cmdline[0] = 0x0d;
4307     (DWORD)cmdline[1] = (DWORD)lphnd;
4308     (DWORD)cmdline[5] = x2;
4309     (DWORD)cmdline[9] = 0;
4310     
4311     sel1 = SELECTOR_AllocBlock(cmdline, 0x0d, SEGMENT_DATA, FALSE, FALSE);
4312     sel2 = SELECTOR_AllocBlock(&showCmd, sizeof(showCmd),
4313                                SEGMENT_DATA, FALSE, FALSE);
4314     
4315     lp = (LOADPARAMS *)HeapAlloc(GetProcessHeap(), 0, sizeof(LOADPARAMS));
4316     lp->hEnvironment = 0;
4317     lp->cmdLine = PTR_SEG_OFF_TO_SEGPTR(sel1, 0);
4318     lp->showCmd = PTR_SEG_OFF_TO_SEGPTR(sel2, 0);
4319     lp->reserved = 0;
4320     
4321     ret = LoadModule16("c:\\windows\\mmtask.tsk", lp);
4322     if (ret < 32) {
4323         if (ret)
4324             ret = 1;
4325         else
4326             ret = 2;
4327         handle = 0;
4328     }
4329     else {
4330         handle = ret;
4331         ret = 0;
4332     }
4333     if (hMmTask)
4334         *(HINSTANCE16 *)PTR_SEG_TO_LIN(hMmTask) = handle;
4335     
4336     UnMapLS(PTR_SEG_OFF_TO_SEGPTR(sel2, 0));
4337     UnMapLS(PTR_SEG_OFF_TO_SEGPTR(sel1, 0));
4338     
4339     HeapFree(GetProcessHeap(), 0, lp);
4340     HeapFree(GetProcessHeap(), 0, cmdline);
4341     
4342     return ret;
4343 }
4344
4345 /**************************************************************************
4346  *                              mmTaskSignal            [MMSYSTEM.903]
4347  */
4348 LRESULT WINAPI mmTaskSignal16(HTASK16 ht) 
4349 {
4350     TRACE(mmsys,"(%04x);\n",ht);
4351     return PostAppMessage16(ht,WM_USER,0,0);
4352 }
4353
4354 /**************************************************************************
4355  *                              mciDriverYield          [MMSYSTEM.710]
4356  */
4357 LRESULT WINAPI mciDriverYield16(HANDLE16 hnd) 
4358 {
4359     FIXME(mmsys,"(%04x): stub!\n",hnd);
4360     return 0;
4361 }
4362