mshtml: Use create_nselem in exec_hyperlink.
[wine] / dlls / winmm / mmsystem.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  * MMSYSTEM functions
5  *
6  * Copyright 1993      Martin Ayotte
7  *           1998-2003 Eric Pouech
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 /*
25  * Eric POUECH :
26  *      99/4    added mmTask and mmThread functions support
27  */
28
29 #include <stdarg.h>
30 #include <string.h>
31
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
34 #include "windef.h"
35 #include "winbase.h"
36 #include "mmsystem.h"
37 #include "winternl.h"
38 #include "wownt32.h"
39 #include "winnls.h"
40
41 #include "wine/list.h"
42 #include "wine/winuser16.h"
43 #include "winemm.h"
44 #include "winemm16.h"
45
46 #include "wine/debug.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
49
50 static WINE_MMTHREAD*   WINMM_GetmmThread(HANDLE16);
51 static LPWINE_DRIVER    DRIVER_OpenDriver16(LPCWSTR, LPCWSTR, LPARAM);
52 static LRESULT          DRIVER_CloseDriver16(HDRVR16, LPARAM, LPARAM);
53 static LRESULT          DRIVER_SendMessage16(HDRVR16, UINT, LPARAM, LPARAM);
54
55 static CRITICAL_SECTION mmdrv_cs;
56 static CRITICAL_SECTION_DEBUG mmdrv_critsect_debug =
57 {
58     0, 0, &mmdrv_cs,
59     { &mmdrv_critsect_debug.ProcessLocksList, &mmdrv_critsect_debug.ProcessLocksList },
60       0, 0, { (DWORD_PTR)(__FILE__ ": mmsystem_mmdrv_cs") }
61 };
62 static CRITICAL_SECTION mmdrv_cs = { &mmdrv_critsect_debug, -1, 0, 0, 0, 0 };
63
64 /* ###################################################
65  * #                  LIBRARY                        #
66  * ###################################################
67  */
68
69 /**************************************************************************
70  *                      DllEntryPoint (MMSYSTEM.4)
71  *
72  * MMSYSTEM DLL entry point
73  *
74  */
75 BOOL WINAPI MMSYSTEM_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
76                              WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
77 {
78     TRACE("%p 0x%x\n", hinstDLL, fdwReason);
79
80     switch (fdwReason) {
81     case DLL_PROCESS_ATTACH:
82         /* need to load WinMM in order to:
83          * - initiate correctly shared variables (WINMM_Init())
84          */
85         if (!GetModuleHandleA("WINMM.DLL"))
86         {
87             ERR("Could not load sibling WinMM.dll\n");
88             return FALSE;
89         }
90         /* hook in our 16 bit function pointers */
91         pFnGetMMThread16    = WINMM_GetmmThread;
92         pFnOpenDriver16     = DRIVER_OpenDriver16;
93         pFnCloseDriver16    = DRIVER_CloseDriver16;
94         pFnSendMessage16    = DRIVER_SendMessage16;
95         pFnReleaseThunkLock = ReleaseThunkLock;
96         pFnRestoreThunkLock = RestoreThunkLock;
97         MMDRV_Init16();
98         break;
99     case DLL_PROCESS_DETACH:
100         pFnGetMMThread16    = NULL;
101         pFnOpenDriver16     = NULL;
102         pFnCloseDriver16    = NULL;
103         pFnSendMessage16    = NULL;
104         pFnReleaseThunkLock = NULL;
105         pFnRestoreThunkLock = NULL;
106         /* FIXME: add equivalent for MMDRV_Init16() */
107         break;
108     case DLL_THREAD_ATTACH:
109     case DLL_THREAD_DETACH:
110         break;
111     }
112     return TRUE;
113 }
114
115 /**************************************************************************
116  *                              WEP                     [MMSYSTEM.1]
117  */
118 int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
119                         WORD cbHeapSize, LPSTR lpCmdLine)
120 {
121     TRACE("STUB: Unloading MMSystem DLL ... hInst=%04X\n", hInstance);
122     return TRUE;
123 }
124
125 /* ###################################################
126  * #                  PlaySound                      #
127  * ###################################################
128  */
129
130 /**************************************************************************
131  *                              PlaySound               [MMSYSTEM.3]
132  */
133 BOOL16 WINAPI PlaySound16(LPCSTR pszSound, HMODULE16 hmod, DWORD fdwSound)
134 {
135     BOOL16      retv;
136     DWORD       lc;
137
138     if ((fdwSound & SND_RESOURCE) == SND_RESOURCE)
139     {
140         HGLOBAL16 handle;
141         HRSRC16 res;
142
143         if (!(res = FindResource16( hmod, pszSound, "WAVE" ))) return FALSE;
144         if (!(handle = LoadResource16( hmod, res ))) return FALSE;
145         pszSound = LockResource16(handle);
146         fdwSound = (fdwSound & ~SND_RESOURCE) | SND_MEMORY;
147         /* FIXME: FreeResource16 */
148     }
149
150     ReleaseThunkLock(&lc);
151     retv = PlaySoundA(pszSound, 0, fdwSound);
152     RestoreThunkLock(lc);
153
154     return retv;
155 }
156
157 /**************************************************************************
158  *                              sndPlaySound            [MMSYSTEM.2]
159  */
160 BOOL16 WINAPI sndPlaySound16(LPCSTR lpszSoundName, UINT16 uFlags)
161 {
162     BOOL16      retv;
163     DWORD       lc;
164
165     ReleaseThunkLock(&lc);
166     retv = sndPlaySoundA(lpszSoundName, uFlags);
167     RestoreThunkLock(lc);
168
169     return retv;
170 }
171
172 /* ###################################################
173  * #                    MISC                         #
174  * ###################################################
175  */
176
177 /**************************************************************************
178  *                              mmsystemGetVersion      [MMSYSTEM.5]
179  *
180  */
181 UINT16 WINAPI mmsystemGetVersion16(void)
182 {
183     return mmsystemGetVersion();
184 }
185
186 /**************************************************************************
187  *                              DriverCallback                  [MMSYSTEM.31]
188  */
189 BOOL16 WINAPI DriverCallback16(DWORD dwCallBack, UINT16 uFlags, HDRVR16 hDev,
190                                WORD wMsg, DWORD dwUser, DWORD dwParam1,
191                                DWORD dwParam2)
192 {
193     return DriverCallback(dwCallBack, uFlags, HDRVR_32(hDev), wMsg, dwUser, dwParam1, dwParam2);
194 }
195
196 /**************************************************************************
197  *                      OutputDebugStr          [MMSYSTEM.30]
198  */
199 void WINAPI OutputDebugStr16(LPCSTR str)
200 {
201     OutputDebugStringA( str );
202 }
203
204
205 /* ###################################################
206  * #                    MIXER                        #
207  * ###################################################
208  */
209
210 /**************************************************************************
211  *      Mixer devices. New to Win95
212  */
213
214 /**************************************************************************
215  *                              mixerGetNumDevs                 [MMSYSTEM.800]
216  */
217 UINT16 WINAPI mixerGetNumDevs16(void)
218 {
219     return mixerGetNumDevs();
220 }
221
222 /**************************************************************************
223  *                              mixerGetDevCaps                 [MMSYSTEM.801]
224  */
225 UINT16 WINAPI mixerGetDevCaps16(UINT16 uDeviceID, LPMIXERCAPS16 lpCaps,
226                                 UINT16 uSize)
227 {
228     MIXERCAPSA  micA;
229     UINT        ret;
230
231     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
232
233     ret = mixerGetDevCapsA(uDeviceID, &micA, sizeof(micA));
234     if (ret == MMSYSERR_NOERROR) {
235         MIXERCAPS16 mic16;
236         mic16.wMid           = micA.wMid;
237         mic16.wPid           = micA.wPid;
238         mic16.vDriverVersion = micA.vDriverVersion;
239         strcpy(mic16.szPname, micA.szPname);
240         mic16.fdwSupport     = micA.fdwSupport;
241         mic16.cDestinations  = micA.cDestinations;
242         memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
243     }
244     return ret;
245 }
246
247 /**************************************************************************
248  *                              mixerOpen                       [MMSYSTEM.802]
249  */
250 UINT16 WINAPI mixerOpen16(LPHMIXER16 lphmix, UINT16 uDeviceID, DWORD dwCallback,
251                           DWORD dwInstance, DWORD fdwOpen)
252 {
253     HMIXER      hmix;
254     UINT        ret;
255
256     ret = MIXER_Open(&hmix, uDeviceID, dwCallback, dwInstance, fdwOpen, FALSE);
257     if (lphmix) *lphmix = HMIXER_16(hmix);
258     return ret;
259 }
260
261 /**************************************************************************
262  *                              mixerClose                      [MMSYSTEM.803]
263  */
264 UINT16 WINAPI mixerClose16(HMIXER16 hMix)
265 {
266     return mixerClose(HMIXER_32(hMix));
267 }
268
269 /**************************************************************************
270  *                              mixerGetID (MMSYSTEM.806)
271  */
272 UINT16 WINAPI mixerGetID16(HMIXEROBJ16 hmix, LPUINT16 lpid, DWORD fdwID)
273 {
274     UINT        xid;
275     UINT        ret = mixerGetID(HMIXEROBJ_32(hmix), &xid, fdwID);
276
277     if (lpid)
278         *lpid = xid;
279     return ret;
280 }
281
282 /**************************************************************************
283  *                              mixerGetControlDetails  [MMSYSTEM.808]
284  */
285 UINT16 WINAPI mixerGetControlDetails16(HMIXEROBJ16 hmix,
286                                        LPMIXERCONTROLDETAILS16 lpmcd,
287                                        DWORD fdwDetails)
288 {
289     DWORD       ret = MMSYSERR_NOTENABLED;
290     SEGPTR      sppaDetails;
291
292     TRACE("(%04x, %p, %08x)\n", hmix, lpmcd, fdwDetails);
293
294     if (lpmcd == NULL || lpmcd->cbStruct != sizeof(*lpmcd))
295         return MMSYSERR_INVALPARAM;
296
297     sppaDetails = (SEGPTR)lpmcd->paDetails;
298     lpmcd->paDetails = MapSL(sppaDetails);
299     ret = mixerGetControlDetailsA(HMIXEROBJ_32(hmix),
300                                  (LPMIXERCONTROLDETAILS)lpmcd, fdwDetails);
301     lpmcd->paDetails = (LPVOID)sppaDetails;
302
303     return ret;
304 }
305
306 /**************************************************************************
307  *                              mixerGetLineControls            [MMSYSTEM.807]
308  */
309 UINT16 WINAPI mixerGetLineControls16(HMIXEROBJ16 hmix,
310                                      LPMIXERLINECONTROLS16 lpmlc16,
311                                      DWORD fdwControls)
312 {
313     MIXERLINECONTROLSA  mlcA;
314     DWORD               ret;
315     unsigned int        i;
316     LPMIXERCONTROL16    lpmc16;
317
318     TRACE("(%04x, %p, %08x)\n", hmix, lpmlc16, fdwControls);
319
320     if (lpmlc16 == NULL || lpmlc16->cbStruct != sizeof(*lpmlc16) ||
321         lpmlc16->cbmxctrl != sizeof(MIXERCONTROL16))
322         return MMSYSERR_INVALPARAM;
323
324     mlcA.cbStruct = sizeof(mlcA);
325     mlcA.dwLineID = lpmlc16->dwLineID;
326     mlcA.u.dwControlID = lpmlc16->u.dwControlID;
327     mlcA.u.dwControlType = lpmlc16->u.dwControlType;
328     mlcA.cControls = lpmlc16->cControls;
329     mlcA.cbmxctrl = sizeof(MIXERCONTROLA);
330     mlcA.pamxctrl = HeapAlloc(GetProcessHeap(), 0,
331                               mlcA.cControls * mlcA.cbmxctrl);
332
333     ret = mixerGetLineControlsA(HMIXEROBJ_32(hmix), &mlcA, fdwControls);
334
335     if (ret == MMSYSERR_NOERROR) {
336         lpmlc16->dwLineID = mlcA.dwLineID;
337         lpmlc16->u.dwControlID = mlcA.u.dwControlID;
338         lpmlc16->u.dwControlType = mlcA.u.dwControlType;
339         lpmlc16->cControls = mlcA.cControls;
340
341         lpmc16 = MapSL(lpmlc16->pamxctrl);
342
343         for (i = 0; i < mlcA.cControls; i++) {
344             lpmc16[i].cbStruct = sizeof(MIXERCONTROL16);
345             lpmc16[i].dwControlID = mlcA.pamxctrl[i].dwControlID;
346             lpmc16[i].dwControlType = mlcA.pamxctrl[i].dwControlType;
347             lpmc16[i].fdwControl = mlcA.pamxctrl[i].fdwControl;
348             lpmc16[i].cMultipleItems = mlcA.pamxctrl[i].cMultipleItems;
349             strcpy(lpmc16[i].szShortName, mlcA.pamxctrl[i].szShortName);
350             strcpy(lpmc16[i].szName, mlcA.pamxctrl[i].szName);
351             /* sizeof(lpmc16[i].Bounds) == sizeof(mlcA.pamxctrl[i].Bounds) */
352             memcpy(&lpmc16[i].Bounds, &mlcA.pamxctrl[i].Bounds,
353                    sizeof(mlcA.pamxctrl[i].Bounds));
354             /* sizeof(lpmc16[i].Metrics) == sizeof(mlcA.pamxctrl[i].Metrics) */
355             memcpy(&lpmc16[i].Metrics, &mlcA.pamxctrl[i].Metrics,
356                    sizeof(mlcA.pamxctrl[i].Metrics));
357         }
358     }
359
360     HeapFree(GetProcessHeap(), 0, mlcA.pamxctrl);
361
362     return ret;
363 }
364
365 /**************************************************************************
366  *                              mixerGetLineInfo        [MMSYSTEM.805]
367  */
368 UINT16 WINAPI mixerGetLineInfo16(HMIXEROBJ16 hmix, LPMIXERLINE16 lpmli16,
369                                  DWORD fdwInfo)
370 {
371     MIXERLINEA          mliA;
372     UINT                ret;
373
374     TRACE("(%04x, %p, %08x)\n", hmix, lpmli16, fdwInfo);
375
376     if (lpmli16 == NULL || lpmli16->cbStruct != sizeof(*lpmli16))
377         return MMSYSERR_INVALPARAM;
378
379     mliA.cbStruct = sizeof(mliA);
380     switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) {
381     case MIXER_GETLINEINFOF_COMPONENTTYPE:
382         mliA.dwComponentType = lpmli16->dwComponentType;
383         break;
384     case MIXER_GETLINEINFOF_DESTINATION:
385         mliA.dwDestination = lpmli16->dwDestination;
386         break;
387     case MIXER_GETLINEINFOF_LINEID:
388         mliA.dwLineID = lpmli16->dwLineID;
389         break;
390     case MIXER_GETLINEINFOF_SOURCE:
391         mliA.dwDestination = lpmli16->dwDestination;
392         mliA.dwSource = lpmli16->dwSource;
393         break;
394     case MIXER_GETLINEINFOF_TARGETTYPE:
395         mliA.Target.dwType = lpmli16->Target.dwType;
396         mliA.Target.wMid = lpmli16->Target.wMid;
397         mliA.Target.wPid = lpmli16->Target.wPid;
398         mliA.Target.vDriverVersion = lpmli16->Target.vDriverVersion;
399         strcpy(mliA.Target.szPname, lpmli16->Target.szPname);
400         break;
401     default:
402         FIXME("Unsupported fdwControls=0x%08x\n", fdwInfo);
403     }
404
405     ret = mixerGetLineInfoA(HMIXEROBJ_32(hmix), &mliA, fdwInfo);
406
407     lpmli16->dwDestination      = mliA.dwDestination;
408     lpmli16->dwSource           = mliA.dwSource;
409     lpmli16->dwLineID           = mliA.dwLineID;
410     lpmli16->fdwLine            = mliA.fdwLine;
411     lpmli16->dwUser             = mliA.dwUser;
412     lpmli16->dwComponentType    = mliA.dwComponentType;
413     lpmli16->cChannels          = mliA.cChannels;
414     lpmli16->cConnections       = mliA.cConnections;
415     lpmli16->cControls          = mliA.cControls;
416     strcpy(lpmli16->szShortName, mliA.szShortName);
417     strcpy(lpmli16->szName, mliA.szName);
418     lpmli16->Target.dwType      = mliA.Target.dwType;
419     lpmli16->Target.dwDeviceID  = mliA.Target.dwDeviceID;
420     lpmli16->Target.wMid        = mliA.Target.wMid;
421     lpmli16->Target.wPid        = mliA.Target.wPid;
422     lpmli16->Target.vDriverVersion = mliA.Target.vDriverVersion;
423     strcpy(lpmli16->Target.szPname, mliA.Target.szPname);
424
425     return ret;
426 }
427
428 /**************************************************************************
429  *                              mixerSetControlDetails  [MMSYSTEM.809]
430  */
431 UINT16 WINAPI mixerSetControlDetails16(HMIXEROBJ16 hmix,
432                                        LPMIXERCONTROLDETAILS16 lpmcd,
433                                        DWORD fdwDetails)
434 {
435     TRACE("(%04x, %p, %08x)\n", hmix, lpmcd, fdwDetails);
436     return MMSYSERR_NOTENABLED;
437 }
438
439 /**************************************************************************
440  *                              mixerMessage            [MMSYSTEM.804]
441  */
442 DWORD WINAPI mixerMessage16(HMIXER16 hmix, UINT16 uMsg, DWORD dwParam1,
443                              DWORD dwParam2)
444 {
445     return mixerMessage(HMIXER_32(hmix), uMsg, dwParam1, dwParam2);
446 }
447
448 /**************************************************************************
449  *                              auxGetNumDevs           [MMSYSTEM.350]
450  */
451 UINT16 WINAPI auxGetNumDevs16(void)
452 {
453     return auxGetNumDevs();
454 }
455
456 /* ###################################################
457  * #                     AUX                         #
458  * ###################################################
459  */
460
461 /**************************************************************************
462  *                              auxGetDevCaps           [MMSYSTEM.351]
463  */
464 UINT16 WINAPI auxGetDevCaps16(UINT16 uDeviceID, LPAUXCAPS16 lpCaps, UINT16 uSize)
465 {
466     AUXCAPSA  acA;
467     UINT      ret;
468
469     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
470
471     ret = auxGetDevCapsA(uDeviceID, &acA, sizeof(acA));
472     if (ret == MMSYSERR_NOERROR) {
473         AUXCAPS16 ac16;
474         ac16.wMid           = acA.wMid; 
475         ac16.wPid           = acA.wPid; 
476         ac16.vDriverVersion = acA.vDriverVersion; 
477         strcpy(ac16.szPname, acA.szPname); 
478         ac16.wTechnology    = acA.wTechnology; 
479         ac16.dwSupport      = acA.dwSupport; 
480         memcpy(lpCaps, &ac16, min(uSize, sizeof(ac16)));
481     }
482     return ret;
483 }
484
485 /**************************************************************************
486  *                              auxGetVolume            [MMSYSTEM.352]
487  */
488 UINT16 WINAPI auxGetVolume16(UINT16 uDeviceID, LPDWORD lpdwVolume)
489 {
490     return auxGetVolume(uDeviceID, lpdwVolume);
491 }
492
493 /**************************************************************************
494  *                              auxSetVolume            [MMSYSTEM.353]
495  */
496 UINT16 WINAPI auxSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
497 {
498     return auxSetVolume(uDeviceID, dwVolume);
499 }
500
501 /**************************************************************************
502  *                              auxOutMessage           [MMSYSTEM.354]
503  */
504 DWORD WINAPI auxOutMessage16(UINT16 uDeviceID, UINT16 uMessage, DWORD dw1, DWORD dw2)
505 {
506     TRACE("(%04X, %04X, %08X, %08X)\n", uDeviceID, uMessage, dw1, dw2);
507
508     switch (uMessage) {
509     case AUXDM_GETNUMDEVS:
510     case AUXDM_SETVOLUME:
511         /* no argument conversion needed */
512         break;
513     case AUXDM_GETVOLUME:
514         return auxGetVolume16(uDeviceID, MapSL(dw1));
515     case AUXDM_GETDEVCAPS:
516         return auxGetDevCaps16(uDeviceID, MapSL(dw1), dw2);
517     default:
518         TRACE("(%04x, %04x, %08x, %08x): unhandled message\n",
519               uDeviceID, uMessage, dw1, dw2);
520         break;
521     }
522     return auxOutMessage(uDeviceID, uMessage, dw1, dw2);
523 }
524
525 /* ###################################################
526  * #                     MIDI                        #
527  * ###################################################
528  */
529
530 /**************************************************************************
531  *                              midiOutGetNumDevs       [MMSYSTEM.201]
532  */
533 UINT16 WINAPI midiOutGetNumDevs16(void)
534 {
535     return midiOutGetNumDevs();
536 }
537
538 /**************************************************************************
539  *                              midiOutGetDevCaps       [MMSYSTEM.202]
540  */
541 UINT16 WINAPI midiOutGetDevCaps16(UINT16 uDeviceID, LPMIDIOUTCAPS16 lpCaps,
542                                   UINT16 uSize)
543 {
544     MIDIOUTCAPSA        mocA;
545     UINT                ret;
546
547     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
548
549     ret = midiOutGetDevCapsA(uDeviceID, &mocA, sizeof(mocA));
550     if (ret == MMSYSERR_NOERROR) {
551         MIDIOUTCAPS16 moc16;
552         moc16.wMid            = mocA.wMid;
553         moc16.wPid            = mocA.wPid;
554         moc16.vDriverVersion  = mocA.vDriverVersion;
555         strcpy(moc16.szPname, mocA.szPname);
556         moc16.wTechnology     = mocA.wTechnology;
557         moc16.wVoices         = mocA.wVoices;
558         moc16.wNotes          = mocA.wNotes;
559         moc16.wChannelMask    = mocA.wChannelMask;
560         moc16.dwSupport       = mocA.dwSupport;
561         memcpy(lpCaps, &moc16, min(uSize, sizeof(moc16)));
562     }
563     return ret;
564  }
565
566 /**************************************************************************
567  *                              midiOutGetErrorText     [MMSYSTEM.203]
568  *                              midiInGetErrorText      [MMSYSTEM.303]
569  */
570 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
571 {
572     return midiOutGetErrorTextA(uError, lpText, uSize);
573 }
574
575 /**************************************************************************
576  *                              midiOutOpen             [MMSYSTEM.204]
577  */
578 UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
579                             DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
580 {
581     HMIDIOUT    hmo;
582     UINT        ret;
583
584     ret = MIDI_OutOpen(&hmo, uDeviceID, dwCallback, dwInstance, dwFlags, FALSE);
585
586     if (lphMidiOut != NULL) *lphMidiOut = HMIDIOUT_16(hmo);
587     return ret;
588 }
589
590 /**************************************************************************
591  *                              midiOutClose            [MMSYSTEM.205]
592  */
593 UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
594 {
595     return midiOutClose(HMIDIOUT_32(hMidiOut));
596 }
597
598 /**************************************************************************
599  *                              midiOutPrepareHeader    [MMSYSTEM.206]
600  */
601 UINT16 WINAPI midiOutPrepareHeader16(HMIDIOUT16 hMidiOut,         /* [in] */
602                                      SEGPTR lpsegMidiOutHdr,      /* [???] */
603                                      UINT16 uSize)                /* [in] */
604 {
605     LPWINE_MLD          wmld;
606
607     TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
608
609     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
610         return MMSYSERR_INVALHANDLE;
611
612     return MMDRV_Message(wmld, MODM_PREPARE, lpsegMidiOutHdr, uSize, FALSE);
613 }
614
615 /**************************************************************************
616  *                              midiOutUnprepareHeader  [MMSYSTEM.207]
617  */
618 UINT16 WINAPI midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut,         /* [in] */
619                                        SEGPTR lpsegMidiOutHdr,      /* [???] */
620                                        UINT16 uSize)                /* [in] */
621 {
622     LPWINE_MLD          wmld;
623     LPMIDIHDR16         lpMidiOutHdr = MapSL(lpsegMidiOutHdr);
624
625     TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
626
627     if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) {
628         return MMSYSERR_NOERROR;
629     }
630
631     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
632         return MMSYSERR_INVALHANDLE;
633
634     return MMDRV_Message(wmld, MODM_UNPREPARE, lpsegMidiOutHdr, uSize, FALSE);
635 }
636
637 /**************************************************************************
638  *                              midiOutShortMsg         [MMSYSTEM.208]
639  */
640 UINT16 WINAPI midiOutShortMsg16(HMIDIOUT16 hMidiOut, DWORD dwMsg)
641 {
642     return midiOutShortMsg(HMIDIOUT_32(hMidiOut), dwMsg);
643 }
644
645 /**************************************************************************
646  *                              midiOutLongMsg          [MMSYSTEM.209]
647  */
648 UINT16 WINAPI midiOutLongMsg16(HMIDIOUT16 hMidiOut,          /* [in] */
649                                LPMIDIHDR16 lpsegMidiOutHdr,  /* [???] NOTE: SEGPTR */
650                                UINT16 uSize)                 /* [in] */
651 {
652     LPWINE_MLD          wmld;
653
654     TRACE("(%04X, %p, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
655
656     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
657         return MMSYSERR_INVALHANDLE;
658
659     return MMDRV_Message(wmld, MODM_LONGDATA, (DWORD_PTR)lpsegMidiOutHdr, uSize, FALSE);
660 }
661
662 /**************************************************************************
663  *                              midiOutReset            [MMSYSTEM.210]
664  */
665 UINT16 WINAPI midiOutReset16(HMIDIOUT16 hMidiOut)
666 {
667     return midiOutReset(HMIDIOUT_32(hMidiOut));
668 }
669
670 /**************************************************************************
671  *                              midiOutGetVolume        [MMSYSTEM.211]
672  */
673 UINT16 WINAPI midiOutGetVolume16(UINT16 uDeviceID, DWORD* lpdwVolume)
674 {
675     return midiOutGetVolume(HMIDIOUT_32(uDeviceID), lpdwVolume);
676 }
677
678 /**************************************************************************
679  *                              midiOutSetVolume        [MMSYSTEM.212]
680  */
681 UINT16 WINAPI midiOutSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
682 {
683     return midiOutSetVolume(HMIDIOUT_32(uDeviceID), dwVolume);
684 }
685
686 /**************************************************************************
687  *                              midiOutCachePatches             [MMSYSTEM.213]
688  */
689 UINT16 WINAPI midiOutCachePatches16(HMIDIOUT16 hMidiOut, UINT16 uBank,
690                                     WORD* lpwPatchArray, UINT16 uFlags)
691 {
692     return midiOutCachePatches(HMIDIOUT_32(hMidiOut), uBank, lpwPatchArray,
693                                uFlags);
694 }
695
696 /**************************************************************************
697  *                              midiOutCacheDrumPatches [MMSYSTEM.214]
698  */
699 UINT16 WINAPI midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut, UINT16 uPatch,
700                                         WORD* lpwKeyArray, UINT16 uFlags)
701 {
702     return midiOutCacheDrumPatches(HMIDIOUT_32(hMidiOut), uPatch, lpwKeyArray, uFlags);
703 }
704
705 /**************************************************************************
706  *                              midiOutGetID            [MMSYSTEM.215]
707  */
708 UINT16 WINAPI midiOutGetID16(HMIDIOUT16 hMidiOut, UINT16* lpuDeviceID)
709 {
710     UINT        devid;
711     UINT16      ret;
712
713     ret = midiOutGetID(HMIDIOUT_32(hMidiOut), &devid);
714     if (ret != MMSYSERR_NOERROR) return ret;
715     *lpuDeviceID = devid;
716     return ret;
717 }
718
719 /**************************************************************************
720  *                              midiOutMessage          [MMSYSTEM.216]
721  */
722 DWORD WINAPI midiOutMessage16(HMIDIOUT16 hMidiOut, UINT16 uMessage,
723                               DWORD dwParam1, DWORD dwParam2)
724 {
725     LPWINE_MLD          wmld;
726
727     TRACE("(%04X, %04X, %08X, %08X)\n", hMidiOut, uMessage, dwParam1, dwParam2);
728
729     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
730         return MMSYSERR_INVALHANDLE;
731
732     switch (uMessage) {
733     case MODM_OPEN:
734     case MODM_CLOSE:
735         FIXME("can't handle OPEN or CLOSE message!\n");
736         return MMSYSERR_NOTSUPPORTED;
737
738     case MODM_GETVOLUME:
739         return midiOutGetVolume16(hMidiOut, MapSL(dwParam1));
740     case MODM_LONGDATA:
741         return midiOutLongMsg16(hMidiOut, MapSL(dwParam1), dwParam2);
742     case MODM_PREPARE:
743         /* lpMidiOutHdr is still a segmented pointer for this function */
744         return midiOutPrepareHeader16(hMidiOut, dwParam1, dwParam2);
745     case MODM_UNPREPARE:
746         return midiOutUnprepareHeader16(hMidiOut, dwParam1, dwParam2);
747     }
748     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, TRUE);
749 }
750
751 /**************************************************************************
752  *                              midiInGetNumDevs        [MMSYSTEM.301]
753  */
754 UINT16 WINAPI midiInGetNumDevs16(void)
755 {
756     return midiInGetNumDevs();
757 }
758
759 /**************************************************************************
760  *                              midiInGetDevCaps        [MMSYSTEM.302]
761  */
762 UINT16 WINAPI midiInGetDevCaps16(UINT16 uDeviceID, LPMIDIINCAPS16 lpCaps,
763                                  UINT16 uSize)
764 {
765     MIDIINCAPSA         micA;
766     UINT                ret;
767
768     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
769
770     ret = midiInGetDevCapsA(uDeviceID, &micA, uSize);
771     if (ret == MMSYSERR_NOERROR) {
772         MIDIINCAPS16 mic16;
773         mic16.wMid           = micA.wMid;
774         mic16.wPid           = micA.wPid;
775         mic16.vDriverVersion = micA.vDriverVersion;
776         strcpy(mic16.szPname, micA.szPname);
777         mic16.dwSupport      = micA.dwSupport;
778         memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
779     }
780     return ret;
781 }
782
783 /**************************************************************************
784  *                              midiInOpen              [MMSYSTEM.304]
785  */
786 UINT16 WINAPI midiInOpen16(HMIDIIN16* lphMidiIn, UINT16 uDeviceID,
787                            DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
788 {
789     HMIDIIN     xhmid;
790     UINT        ret;
791
792     ret = MIDI_InOpen(&xhmid, uDeviceID, dwCallback, dwInstance, dwFlags, FALSE);
793
794     if (lphMidiIn) *lphMidiIn = HMIDIIN_16(xhmid);
795     return ret;
796 }
797
798 /**************************************************************************
799  *                              midiInClose             [MMSYSTEM.305]
800  */
801 UINT16 WINAPI midiInClose16(HMIDIIN16 hMidiIn)
802 {
803     return midiInClose(HMIDIIN_32(hMidiIn));
804 }
805
806 /**************************************************************************
807  *                              midiInPrepareHeader     [MMSYSTEM.306]
808  */
809 UINT16 WINAPI midiInPrepareHeader16(HMIDIIN16 hMidiIn,         /* [in] */
810                                     SEGPTR lpsegMidiInHdr,     /* [???] */
811                                     UINT16 uSize)              /* [in] */
812 {
813     LPWINE_MLD          wmld;
814
815     TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
816
817     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
818         return MMSYSERR_INVALHANDLE;
819
820     return MMDRV_Message(wmld, MIDM_PREPARE, lpsegMidiInHdr, uSize, FALSE);
821 }
822
823 /**************************************************************************
824  *                              midiInUnprepareHeader   [MMSYSTEM.307]
825  */
826 UINT16 WINAPI midiInUnprepareHeader16(HMIDIIN16 hMidiIn,         /* [in] */
827                                       SEGPTR lpsegMidiInHdr,     /* [???] */
828                                       UINT16 uSize)              /* [in] */
829 {
830     LPWINE_MLD          wmld;
831     LPMIDIHDR16         lpMidiInHdr = MapSL(lpsegMidiInHdr);
832
833     TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
834
835     if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) {
836         return MMSYSERR_NOERROR;
837     }
838
839     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
840         return MMSYSERR_INVALHANDLE;
841
842     return MMDRV_Message(wmld, MIDM_UNPREPARE, lpsegMidiInHdr, uSize, FALSE);
843 }
844
845 /**************************************************************************
846  *                              midiInAddBuffer         [MMSYSTEM.308]
847  */
848 UINT16 WINAPI midiInAddBuffer16(HMIDIIN16 hMidiIn,         /* [in] */
849                                 MIDIHDR16* lpsegMidiInHdr, /* [???] NOTE: SEGPTR */
850                                 UINT16 uSize)              /* [in] */
851 {
852     LPWINE_MLD          wmld;
853
854     TRACE("(%04X, %p, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
855
856     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
857         return MMSYSERR_INVALHANDLE;
858
859     return MMDRV_Message(wmld, MIDM_ADDBUFFER, (DWORD_PTR)lpsegMidiInHdr, uSize, FALSE);
860 }
861
862 /**************************************************************************
863  *                              midiInStart                     [MMSYSTEM.309]
864  */
865 UINT16 WINAPI midiInStart16(HMIDIIN16 hMidiIn)
866 {
867     return midiInStart(HMIDIIN_32(hMidiIn));
868 }
869
870 /**************************************************************************
871  *                              midiInStop                      [MMSYSTEM.310]
872  */
873 UINT16 WINAPI midiInStop16(HMIDIIN16 hMidiIn)
874 {
875     return midiInStop(HMIDIIN_32(hMidiIn));
876 }
877
878 /**************************************************************************
879  *                              midiInReset                     [MMSYSTEM.311]
880  */
881 UINT16 WINAPI midiInReset16(HMIDIIN16 hMidiIn)
882 {
883     return midiInReset(HMIDIIN_32(hMidiIn));
884 }
885
886 /**************************************************************************
887  *                              midiInGetID                     [MMSYSTEM.312]
888  */
889 UINT16 WINAPI midiInGetID16(HMIDIIN16 hMidiIn, UINT16* lpuDeviceID)
890 {
891     UINT        devid;
892     UINT16      ret;
893
894     ret = midiInGetID(HMIDIIN_32(hMidiIn), &devid);
895     if (ret != MMSYSERR_NOERROR) return ret;
896     *lpuDeviceID = devid;
897     return ret;
898 }
899
900 /**************************************************************************
901  *                              midiInMessage           [MMSYSTEM.313]
902  */
903 DWORD WINAPI midiInMessage16(HMIDIIN16 hMidiIn, UINT16 uMessage,
904                              DWORD dwParam1, DWORD dwParam2)
905 {
906     LPWINE_MLD          wmld;
907
908     TRACE("(%04X, %04X, %08X, %08X)\n", hMidiIn, uMessage, dwParam1, dwParam2);
909
910     switch (uMessage) {
911     case MIDM_OPEN:
912     case MIDM_CLOSE:
913         FIXME("can't handle OPEN or CLOSE message!\n");
914         return MMSYSERR_NOTSUPPORTED;
915
916     case MIDM_GETDEVCAPS:
917         return midiInGetDevCaps16(hMidiIn, MapSL(dwParam1), dwParam2);
918     case MIDM_PREPARE:
919         return midiInPrepareHeader16(hMidiIn, dwParam1, dwParam2);
920     case MIDM_UNPREPARE:
921         return midiInUnprepareHeader16(hMidiIn, dwParam1, dwParam2);
922     case MIDM_ADDBUFFER:
923         return midiInAddBuffer16(hMidiIn, MapSL(dwParam1), dwParam2);
924     }
925
926     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
927         return MMSYSERR_INVALHANDLE;
928
929     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
930 }
931
932 /**************************************************************************
933  *                              midiStreamClose                 [MMSYSTEM.252]
934  */
935 MMRESULT16 WINAPI midiStreamClose16(HMIDISTRM16 hMidiStrm)
936 {
937     return midiStreamClose(HMIDISTRM_32(hMidiStrm));
938 }
939
940 /**************************************************************************
941  *                              midiStreamOpen                  [MMSYSTEM.251]
942  */
943 MMRESULT16 WINAPI midiStreamOpen16(HMIDISTRM16* phMidiStrm, LPUINT16 devid,
944                                    DWORD cMidi, DWORD dwCallback,
945                                    DWORD dwInstance, DWORD fdwOpen)
946 {
947     HMIDISTRM   hMidiStrm32;
948     MMRESULT    ret;
949     UINT        devid32;
950
951     if (!phMidiStrm || !devid)
952         return MMSYSERR_INVALPARAM;
953     devid32 = *devid;
954     ret = MIDI_StreamOpen(&hMidiStrm32, &devid32, cMidi, dwCallback,
955                           dwInstance, fdwOpen, FALSE);
956     *phMidiStrm = HMIDISTRM_16(hMidiStrm32);
957     *devid = devid32;
958     return ret;
959 }
960
961 /**************************************************************************
962  *                              midiStreamOut                   [MMSYSTEM.254]
963  */
964 MMRESULT16 WINAPI midiStreamOut16(HMIDISTRM16 hMidiStrm, LPMIDIHDR16 lpMidiHdr, UINT16 cbMidiHdr)
965 {
966     return midiStreamOut(HMIDISTRM_32(hMidiStrm), (LPMIDIHDR)lpMidiHdr,
967                          cbMidiHdr);
968 }
969
970 /**************************************************************************
971  *                              midiStreamPause                 [MMSYSTEM.255]
972  */
973 MMRESULT16 WINAPI midiStreamPause16(HMIDISTRM16 hMidiStrm)
974 {
975     return midiStreamPause(HMIDISTRM_32(hMidiStrm));
976 }
977
978 /**************************************************************************
979  *                              midiStreamPosition              [MMSYSTEM.253]
980  */
981 MMRESULT16 WINAPI midiStreamPosition16(HMIDISTRM16 hMidiStrm, LPMMTIME16 lpmmt16, UINT16 cbmmt)
982 {
983     MMTIME      mmt32;
984     MMRESULT    ret;
985
986     if (!lpmmt16)
987         return MMSYSERR_INVALPARAM;
988     MMSYSTEM_MMTIME16to32(&mmt32, lpmmt16);
989     ret = midiStreamPosition(HMIDISTRM_32(hMidiStrm), &mmt32, sizeof(MMTIME));
990     MMSYSTEM_MMTIME32to16(lpmmt16, &mmt32);
991     return ret;
992 }
993
994 /**************************************************************************
995  *                              midiStreamProperty              [MMSYSTEM.250]
996  */
997 MMRESULT16 WINAPI midiStreamProperty16(HMIDISTRM16 hMidiStrm, LPBYTE lpPropData, DWORD dwProperty)
998 {
999     return midiStreamProperty(HMIDISTRM_32(hMidiStrm), lpPropData, dwProperty);
1000 }
1001
1002 /**************************************************************************
1003  *                              midiStreamRestart               [MMSYSTEM.256]
1004  */
1005 MMRESULT16 WINAPI midiStreamRestart16(HMIDISTRM16 hMidiStrm)
1006 {
1007     return midiStreamRestart(HMIDISTRM_32(hMidiStrm));
1008 }
1009
1010 /**************************************************************************
1011  *                              midiStreamStop                  [MMSYSTEM.257]
1012  */
1013 MMRESULT16 WINAPI midiStreamStop16(HMIDISTRM16 hMidiStrm)
1014 {
1015     return midiStreamStop(HMIDISTRM_32(hMidiStrm));
1016 }
1017
1018 /* ###################################################
1019  * #                     WAVE                        #
1020  * ###################################################
1021  */
1022
1023 /**************************************************************************
1024  *                              waveOutGetNumDevs               [MMSYSTEM.401]
1025  */
1026 UINT16 WINAPI waveOutGetNumDevs16(void)
1027 {
1028     return waveOutGetNumDevs();
1029 }
1030
1031 /**************************************************************************
1032  *                              waveOutGetDevCaps               [MMSYSTEM.402]
1033  */
1034 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID,
1035                                   LPWAVEOUTCAPS16 lpCaps, UINT16 uSize)
1036 {
1037     WAVEOUTCAPSA        wocA;
1038     UINT                ret;
1039     TRACE("(%u %p %u)!\n", uDeviceID, lpCaps, uSize);
1040
1041     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1042
1043     ret = waveOutGetDevCapsA(uDeviceID, &wocA, sizeof(wocA));
1044     if (ret == MMSYSERR_NOERROR) {
1045         WAVEOUTCAPS16 woc16;
1046         woc16.wMid           = wocA.wMid;
1047         woc16.wPid           = wocA.wPid;
1048         woc16.vDriverVersion = wocA.vDriverVersion;
1049         strcpy(woc16.szPname, wocA.szPname);
1050         woc16.dwFormats      = wocA.dwFormats;
1051         woc16.wChannels      = wocA.wChannels;
1052         woc16.dwSupport      = wocA.dwSupport;
1053         memcpy(lpCaps, &woc16, min(uSize, sizeof(woc16)));
1054     }
1055     return ret;
1056 }
1057
1058 /**************************************************************************
1059  *                              waveOutGetErrorText     [MMSYSTEM.403]
1060  *                              waveInGetErrorText      [MMSYSTEM.503]
1061  */
1062 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1063 {
1064     return waveOutGetErrorTextA(uError, lpText, uSize);
1065 }
1066
1067 /**************************************************************************
1068  *                      waveOutOpen                     [MMSYSTEM.404]
1069  */
1070 UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
1071                             LPCWAVEFORMATEX lpFormat, DWORD dwCallback,
1072                             DWORD dwInstance, DWORD dwFlags)
1073 {
1074     HANDLE              hWaveOut;
1075     UINT                ret;
1076
1077     /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1078      * call the 32 bit version
1079      * however, we need to promote correctly the wave mapper id
1080      * (0xFFFFFFFF and not 0x0000FFFF)
1081      */
1082     ret = WAVE_Open(&hWaveOut, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1083                     MMDRV_WAVEOUT, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1084
1085     if (lphWaveOut != NULL) *lphWaveOut = HWAVEOUT_16(hWaveOut);
1086     return ret;
1087 }
1088
1089 /**************************************************************************
1090  *                              waveOutClose            [MMSYSTEM.405]
1091  */
1092 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
1093 {
1094     DWORD       level;
1095     UINT16      ret;
1096
1097     ReleaseThunkLock(&level);
1098     ret = waveOutClose(HWAVEOUT_32(hWaveOut));
1099     RestoreThunkLock(level);
1100     return ret;
1101 }
1102
1103 /**************************************************************************
1104  *                              waveOutPrepareHeader    [MMSYSTEM.406]
1105  */
1106 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut,      /* [in] */
1107                                      SEGPTR lpsegWaveOutHdr,   /* [???] */
1108                                      UINT16 uSize)             /* [in] */
1109 {
1110     LPWINE_MLD          wmld;
1111     LPWAVEHDR           lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1112     UINT16              result;
1113
1114     TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1115
1116     if (lpWaveOutHdr == NULL) return MMSYSERR_INVALPARAM;
1117
1118     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1119         return MMSYSERR_INVALHANDLE;
1120
1121     if ((result = MMDRV_Message(wmld, WODM_PREPARE, lpsegWaveOutHdr,
1122                                 uSize, FALSE)) != MMSYSERR_NOTSUPPORTED)
1123         return result;
1124
1125     if (lpWaveOutHdr->dwFlags & WHDR_INQUEUE)
1126         return WAVERR_STILLPLAYING;
1127
1128     lpWaveOutHdr->dwFlags |= WHDR_PREPARED;
1129     lpWaveOutHdr->dwFlags &= ~WHDR_DONE;
1130
1131     return MMSYSERR_NOERROR;
1132 }
1133
1134 /**************************************************************************
1135  *                              waveOutUnprepareHeader  [MMSYSTEM.407]
1136  */
1137 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut,       /* [in] */
1138                                        SEGPTR lpsegWaveOutHdr,    /* [???] */
1139                                        UINT16 uSize)              /* [in] */
1140 {
1141     LPWINE_MLD          wmld;
1142     LPWAVEHDR           lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1143
1144     TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1145
1146     if (!(lpWaveOutHdr->dwFlags & WHDR_PREPARED)) {
1147         return MMSYSERR_NOERROR;
1148     }
1149
1150     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1151         return MMSYSERR_INVALHANDLE;
1152
1153     return MMDRV_Message(wmld, WODM_UNPREPARE, lpsegWaveOutHdr, uSize, FALSE);
1154 }
1155
1156 /**************************************************************************
1157  *                              waveOutWrite            [MMSYSTEM.408]
1158  */
1159 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut,       /* [in] */
1160                              LPWAVEHDR lpsegWaveOutHdr, /* [???] NOTE: SEGPTR */
1161                              UINT16 uSize)              /* [in] */
1162 {
1163     LPWINE_MLD          wmld;
1164
1165     TRACE("(%04X, %p, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1166
1167     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1168         return MMSYSERR_INVALHANDLE;
1169
1170     return MMDRV_Message(wmld, WODM_WRITE, (DWORD_PTR)lpsegWaveOutHdr, uSize, FALSE);
1171 }
1172
1173 /**************************************************************************
1174  *                              waveOutBreakLoop        [MMSYSTEM.419]
1175  */
1176 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut16)
1177 {
1178     DWORD       level;
1179     UINT16      ret;
1180
1181     ReleaseThunkLock(&level);
1182     ret = waveOutBreakLoop(HWAVEOUT_32(hWaveOut16));
1183     RestoreThunkLock(level);
1184     return ret;
1185 }
1186
1187 /**************************************************************************
1188  *                              waveOutPause            [MMSYSTEM.409]
1189  */
1190 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut16)
1191 {
1192     DWORD       level;
1193     UINT16      ret;
1194
1195     ReleaseThunkLock(&level);
1196     ret = waveOutPause(HWAVEOUT_32(hWaveOut16));
1197     RestoreThunkLock(level);
1198     return ret;
1199 }
1200
1201 /**************************************************************************
1202  *                              waveOutReset            [MMSYSTEM.411]
1203  */
1204 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut16)
1205 {
1206     DWORD       level;
1207     UINT16      ret;
1208
1209     ReleaseThunkLock(&level);
1210     ret = waveOutReset(HWAVEOUT_32(hWaveOut16));
1211     RestoreThunkLock(level);
1212     return ret;
1213 }
1214
1215 /**************************************************************************
1216  *                              waveOutRestart  [MMSYSTEM.410]
1217  */
1218 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut16)
1219 {
1220     DWORD       level;
1221     UINT16      ret;
1222
1223     ReleaseThunkLock(&level);
1224     ret = waveOutRestart(HWAVEOUT_32(hWaveOut16));
1225     RestoreThunkLock(level);
1226     return ret;
1227 }
1228
1229 /**************************************************************************
1230  *                              waveOutGetPosition      [MMSYSTEM.412]
1231  */
1232 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
1233                                    UINT16 uSize)
1234 {
1235     UINT        ret;
1236     MMTIME      mmt;
1237
1238     mmt.wType = lpTime->wType;
1239     ret = waveOutGetPosition(HWAVEOUT_32(hWaveOut), &mmt, sizeof(mmt));
1240     MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1241     return ret;
1242 }
1243
1244 /**************************************************************************
1245  *                              waveOutGetPitch         [MMSYSTEM.413]
1246  */
1247 UINT16 WINAPI waveOutGetPitch16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1248 {
1249     return waveOutGetPitch(HWAVEOUT_32(hWaveOut16), lpdw);
1250 }
1251
1252 /**************************************************************************
1253  *                              waveOutSetPitch         [MMSYSTEM.414]
1254  */
1255 UINT16 WINAPI waveOutSetPitch16(HWAVEOUT16 hWaveOut16, DWORD dw)
1256 {
1257     return waveOutSetPitch(HWAVEOUT_32(hWaveOut16), dw);
1258 }
1259
1260 /**************************************************************************
1261  *                              waveOutGetPlaybackRate  [MMSYSTEM.417]
1262  */
1263 UINT16 WINAPI waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1264 {
1265     return waveOutGetPlaybackRate(HWAVEOUT_32(hWaveOut16), lpdw);
1266 }
1267
1268 /**************************************************************************
1269  *                              waveOutSetPlaybackRate  [MMSYSTEM.418]
1270  */
1271 UINT16 WINAPI waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16, DWORD dw)
1272 {
1273     return waveOutSetPlaybackRate(HWAVEOUT_32(hWaveOut16), dw);
1274 }
1275
1276 /**************************************************************************
1277  *                              waveOutGetVolume        [MMSYSTEM.415]
1278  */
1279 UINT16 WINAPI waveOutGetVolume16(UINT16 devid, LPDWORD lpdw)
1280 {
1281     return waveOutGetVolume(HWAVEOUT_32(devid), lpdw);
1282 }
1283
1284 /**************************************************************************
1285  *                              waveOutSetVolume        [MMSYSTEM.416]
1286  */
1287 UINT16 WINAPI waveOutSetVolume16(UINT16 devid, DWORD dw)
1288 {
1289     return waveOutSetVolume(HWAVEOUT_32(devid), dw);
1290 }
1291
1292 /**************************************************************************
1293  *                              waveOutGetID            [MMSYSTEM.420]
1294  */
1295 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16* lpuDeviceID)
1296 {
1297     UINT        devid;
1298     UINT16      ret;
1299
1300     ret = waveOutGetID(HWAVEOUT_32(hWaveOut), &devid);
1301     if (ret != MMSYSERR_NOERROR) return ret;
1302     *lpuDeviceID = devid;
1303     return ret;
1304 }
1305
1306 /**************************************************************************
1307  *                              waveOutMessage          [MMSYSTEM.421]
1308  */
1309 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage,
1310                               DWORD dwParam1, DWORD dwParam2)
1311 {
1312     LPWINE_MLD          wmld;
1313
1314     TRACE("(%04x, %u, %d, %d)\n", hWaveOut, uMessage, dwParam1, dwParam2);
1315
1316     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL) {
1317         if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, TRUE)) != NULL) {
1318             if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1319                 dwParam1 = (DWORD)MapSL(dwParam1);
1320             return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
1321         }
1322         return MMSYSERR_INVALHANDLE;
1323     }
1324
1325     /* from M$ KB */
1326     if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1327         return MMSYSERR_INVALPARAM;
1328
1329     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1330 }
1331
1332 /**************************************************************************
1333  *                              waveInGetNumDevs                [MMSYSTEM.501]
1334  */
1335 UINT16 WINAPI waveInGetNumDevs16(void)
1336 {
1337     return waveInGetNumDevs();
1338 }
1339
1340 /**************************************************************************
1341  *                              waveInGetDevCaps                [MMSYSTEM.502]
1342  */
1343 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps,
1344                                  UINT16 uSize)
1345 {
1346     WAVEINCAPSA wicA;
1347     UINT        ret;
1348
1349     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1350
1351     ret = waveInGetDevCapsA(uDeviceID, &wicA, sizeof(wicA));
1352     if (ret == MMSYSERR_NOERROR) {
1353         WAVEINCAPS16 wic16;
1354         wic16.wMid           = wicA.wMid;
1355         wic16.wPid           = wicA.wPid;
1356         wic16.vDriverVersion = wicA.vDriverVersion;
1357         strcpy(wic16.szPname, wicA.szPname);
1358         wic16.dwFormats      = wicA.dwFormats;
1359         wic16.wChannels      = wicA.wChannels;
1360         memcpy(lpCaps, &wic16, min(uSize, sizeof(wic16)));
1361     }
1362     return ret;
1363 }
1364
1365 /**************************************************************************
1366  *                              waveInOpen                      [MMSYSTEM.504]
1367  */
1368 UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
1369                            LPCWAVEFORMATEX lpFormat, DWORD dwCallback,
1370                            DWORD dwInstance, DWORD dwFlags)
1371 {
1372     HANDLE              hWaveIn;
1373     UINT                ret;
1374
1375     /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1376      * call the 32 bit version
1377      * however, we need to promote correctly the wave mapper id
1378      * (0xFFFFFFFF and not 0x0000FFFF)
1379      */
1380     ret = WAVE_Open(&hWaveIn, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1381                     MMDRV_WAVEIN, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1382
1383     if (lphWaveIn != NULL) *lphWaveIn = HWAVEIN_16(hWaveIn);
1384     return ret;
1385 }
1386
1387 /**************************************************************************
1388  *                              waveInClose                     [MMSYSTEM.505]
1389  */
1390 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
1391 {
1392     DWORD       level;
1393     UINT16      ret;
1394
1395     ReleaseThunkLock(&level);
1396     ret = waveInClose(HWAVEIN_32(hWaveIn));
1397     RestoreThunkLock(level);
1398     return ret;
1399 }
1400
1401 /**************************************************************************
1402  *                              waveInPrepareHeader             [MMSYSTEM.506]
1403  */
1404 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn,       /* [in] */
1405                                     SEGPTR lpsegWaveInHdr,   /* [???] */
1406                                     UINT16 uSize)            /* [in] */
1407 {
1408     LPWINE_MLD          wmld;
1409     LPWAVEHDR           lpWaveInHdr = MapSL(lpsegWaveInHdr);
1410     UINT16              ret;
1411
1412     TRACE("(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
1413
1414     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
1415     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1416         return MMSYSERR_INVALHANDLE;
1417
1418     lpWaveInHdr->dwBytesRecorded = 0;
1419
1420     ret = MMDRV_Message(wmld, WIDM_PREPARE, lpsegWaveInHdr, uSize, FALSE);
1421     return ret;
1422 }
1423
1424 /**************************************************************************
1425  *                              waveInUnprepareHeader   [MMSYSTEM.507]
1426  */
1427 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn,       /* [in] */
1428                                       SEGPTR lpsegWaveInHdr,   /* [???] */
1429                                       UINT16 uSize)            /* [in] */
1430 {
1431     LPWINE_MLD          wmld;
1432     LPWAVEHDR           lpWaveInHdr = MapSL(lpsegWaveInHdr);
1433
1434     TRACE("(%04X, %08x, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1435
1436     if (lpWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1437
1438     if (!(lpWaveInHdr->dwFlags & WHDR_PREPARED)) {
1439         return MMSYSERR_NOERROR;
1440     }
1441
1442     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1443         return MMSYSERR_INVALHANDLE;
1444
1445     return MMDRV_Message(wmld, WIDM_UNPREPARE, lpsegWaveInHdr, uSize, FALSE);
1446 }
1447
1448 /**************************************************************************
1449  *                              waveInAddBuffer         [MMSYSTEM.508]
1450  */
1451 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn,       /* [in] */
1452                                 WAVEHDR* lpsegWaveInHdr, /* [???] NOTE: SEGPTR */
1453                                 UINT16 uSize)            /* [in] */
1454 {
1455     LPWINE_MLD          wmld;
1456
1457     TRACE("(%04X, %p, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1458
1459     if (lpsegWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1460     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1461         return MMSYSERR_INVALHANDLE;
1462
1463     return MMDRV_Message(wmld, WIDM_ADDBUFFER, (DWORD_PTR)lpsegWaveInHdr, uSize, FALSE);
1464 }
1465
1466 /**************************************************************************
1467  *                              waveInReset             [MMSYSTEM.511]
1468  */
1469 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn16)
1470 {
1471     DWORD       level;
1472     UINT16      ret;
1473
1474     ReleaseThunkLock(&level);
1475     ret = waveInReset(HWAVEIN_32(hWaveIn16));
1476     RestoreThunkLock(level);
1477     return ret;
1478 }
1479
1480 /**************************************************************************
1481  *                              waveInStart             [MMSYSTEM.509]
1482  */
1483 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn16)
1484 {
1485     DWORD       level;
1486     UINT16      ret;
1487
1488     ReleaseThunkLock(&level);
1489     ret = waveInStart(HWAVEIN_32(hWaveIn16));
1490     RestoreThunkLock(level);
1491     return ret;
1492 }
1493
1494 /**************************************************************************
1495  *                              waveInStop              [MMSYSTEM.510]
1496  */
1497 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn16)
1498 {
1499     DWORD       level;
1500     UINT16      ret;
1501
1502     ReleaseThunkLock(&level);
1503     ret = waveInStop(HWAVEIN_32(hWaveIn16));
1504     RestoreThunkLock(level);
1505     return ret;
1506 }
1507
1508 /**************************************************************************
1509  *                              waveInGetPosition       [MMSYSTEM.512]
1510  */
1511 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn, LPMMTIME16 lpTime,
1512                                   UINT16 uSize)
1513 {
1514     UINT        ret;
1515     MMTIME      mmt;
1516
1517     mmt.wType = lpTime->wType;
1518     ret = waveInGetPosition(HWAVEIN_32(hWaveIn), &mmt, sizeof(mmt));
1519     MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1520     return ret;
1521 }
1522
1523 /**************************************************************************
1524  *                              waveInGetID                     [MMSYSTEM.513]
1525  */
1526 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16* lpuDeviceID)
1527 {
1528     UINT        devid;
1529     UINT16      ret;
1530
1531     ret = waveInGetID(HWAVEIN_32(hWaveIn), &devid);
1532     if (ret != MMSYSERR_NOERROR) return ret;
1533     *lpuDeviceID = devid;
1534     return ret;
1535 }
1536
1537 /**************************************************************************
1538  *                              waveInMessage           [MMSYSTEM.514]
1539  */
1540 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
1541                              DWORD dwParam1, DWORD dwParam2)
1542 {
1543     LPWINE_MLD          wmld;
1544
1545     TRACE("(%04x, %u, %d, %d)\n", hWaveIn, uMessage, dwParam1, dwParam2);
1546
1547     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL) {
1548         if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, TRUE)) != NULL) {
1549             if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1550                 dwParam1 = (DWORD)MapSL(dwParam1);
1551             return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
1552         }
1553         return MMSYSERR_INVALHANDLE;
1554     }
1555
1556     /* from M$ KB */
1557     if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1558         return MMSYSERR_INVALPARAM;
1559
1560     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1561 }
1562
1563 /* ###################################################
1564  * #                     TASK                        #
1565  * ###################################################
1566  */
1567
1568 /*#define USE_MM_TSK_WINE*/
1569
1570 /**************************************************************************
1571  *                              mmTaskCreate            [MMSYSTEM.900]
1572  *
1573  * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
1574  * called upon creation with dwPmt as parameter.
1575  */
1576 HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt)
1577 {
1578     HINSTANCE16         ret;
1579     HINSTANCE16         handle;
1580     char cmdline[16];
1581     DWORD showCmd = 0x40002;
1582     LOADPARAMS16 lp;
1583
1584     TRACE("(%08x, %p, %08x);\n", spProc, lphMmTask, dwPmt);
1585     /* This to work requires NE modules to be started with a binary command line
1586      * which is not currently the case. A patch exists but has never been committed.
1587      * A workaround would be to integrate code for mmtask.tsk into Wine, but
1588      * this requires tremendous work (starting with patching tools/build to
1589      * create NE executables (and not only DLLs) for builtins modules.
1590      * EP 99/04/25
1591      */
1592     FIXME("This is currently broken. It will fail\n");
1593
1594     cmdline[0] = 0x0d;
1595     *(LPDWORD)(cmdline + 1) = (DWORD)spProc;
1596     *(LPDWORD)(cmdline + 5) = dwPmt;
1597     *(LPDWORD)(cmdline + 9) = 0;
1598
1599     lp.hEnvironment = 0;
1600     lp.cmdLine = MapLS(cmdline);
1601     lp.showCmd = MapLS(&showCmd);
1602     lp.reserved = 0;
1603
1604 #ifndef USE_MM_TSK_WINE
1605     handle = LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp);
1606 #else
1607     handle = LoadModule16("mmtask.tsk", &lp);
1608 #endif
1609     if (handle < 32) {
1610         ret = (handle) ? 1 : 2;
1611         handle = 0;
1612     } else {
1613         ret = 0;
1614     }
1615     if (lphMmTask)
1616         *lphMmTask = handle;
1617
1618     UnMapLS( lp.cmdLine );
1619     UnMapLS( lp.showCmd );
1620     TRACE("=> 0x%04x/%d\n", handle, ret);
1621     return ret;
1622 }
1623
1624 #ifdef USE_MM_TSK_WINE
1625 /* C equivalent to mmtask.tsk binary content */
1626 void    mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
1627 {
1628     int len = cmdLine[0x80];
1629
1630     if (len / 2 == 6) {
1631         void    (*fpProc)(DWORD) = MapSL(*((DWORD*)(cmdLine + 1)));
1632         DWORD   dwPmt  = *((DWORD*)(cmdLine + 5));
1633
1634 #if 0
1635         InitTask16(); /* FIXME: pmts / from context ? */
1636         InitApp(di);
1637 #endif
1638         if (SetMessageQueue16(0x40)) {
1639             WaitEvent16(0);
1640             if (HIWORD(fpProc)) {
1641                 OldYield16();
1642 /* EPP          StackEnter16(); */
1643                 (fpProc)(dwPmt);
1644             }
1645         }
1646     }
1647     OldYield16();
1648     OldYield16();
1649     OldYield16();
1650     ExitProcess(0);
1651 }
1652 #endif
1653
1654 /**************************************************************************
1655  *                              mmTaskBlock             [MMSYSTEM.902]
1656  */
1657 void WINAPI mmTaskBlock16(HINSTANCE16 hInst)
1658 {
1659     MSG         msg;
1660
1661     do {
1662         GetMessageA(&msg, 0, 0, 0);
1663         if (msg.hwnd) {
1664             TranslateMessage(&msg);
1665             DispatchMessageA(&msg);
1666         }
1667     } while (msg.message < 0x3A0);
1668 }
1669
1670 /**************************************************************************
1671  *                              mmTaskSignal            [MMSYSTEM.903]
1672  */
1673 LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
1674 {
1675     TRACE("(%04x);\n", ht);
1676     return PostThreadMessageW( HTASK_32(ht), WM_USER, 0, 0 );
1677 }
1678
1679 /**************************************************************************
1680  *                              mmGetCurrentTask        [MMSYSTEM.904]
1681  */
1682 HTASK16 WINAPI mmGetCurrentTask16(void)
1683 {
1684     return GetCurrentTask();
1685 }
1686
1687 /**************************************************************************
1688  *                              mmTaskYield             [MMSYSTEM.905]
1689  */
1690 void    WINAPI  mmTaskYield16(void)
1691 {
1692     MSG         msg;
1693
1694     if (PeekMessageA(&msg, 0, 0, 0, 0)) {
1695         WOWYield16();
1696     }
1697 }
1698
1699 extern DWORD    WINAPI  GetProcessFlags(DWORD);
1700
1701 /******************************************************************
1702  *              WINMM_GetmmThread
1703  *
1704  *
1705  */
1706 static  WINE_MMTHREAD*  WINMM_GetmmThread(HANDLE16 h)
1707 {
1708     return MapSL(MAKESEGPTR(h, 0));
1709 }
1710
1711 DWORD WINAPI WINE_mmThreadEntryPoint(LPVOID);
1712
1713 /**************************************************************************
1714  *                              mmThreadCreate          [MMSYSTEM.1120]
1715  *
1716  * undocumented
1717  * Creates a MM thread, calling fpThreadAddr(dwPmt).
1718  * dwFlags:
1719  *      bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
1720  *      bit.1 set means to open a VxD for this thread (unsupported)
1721  */
1722 LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE16 lpHndl, DWORD dwPmt, DWORD dwFlags)
1723 {
1724     HANDLE16            hndl;
1725     LRESULT             ret;
1726
1727     TRACE("(%p, %p, %08x, %08x)!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
1728
1729     hndl = GlobalAlloc16(sizeof(WINE_MMTHREAD), GMEM_SHARE|GMEM_ZEROINIT);
1730
1731     if (hndl == 0) {
1732         ret = 2;
1733     } else {
1734         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1735
1736 #if 0
1737         /* force mmtask routines even if mmthread is required */
1738         /* this will work only if the patch about binary cmd line and NE tasks
1739          * is committed
1740          */
1741         dwFlags |= 1;
1742 #endif
1743
1744         lpMMThd->dwSignature    = WINE_MMTHREAD_CREATED;
1745         lpMMThd->dwCounter      = 0;
1746         lpMMThd->hThread        = 0;
1747         lpMMThd->dwThreadID     = 0;
1748         lpMMThd->fpThread       = (DWORD)fpThreadAddr;
1749         lpMMThd->dwThreadPmt    = dwPmt;
1750         lpMMThd->dwSignalCount  = 0;
1751         lpMMThd->hEvent         = 0;
1752         lpMMThd->hVxD           = 0;
1753         lpMMThd->dwStatus       = 0;
1754         lpMMThd->dwFlags        = dwFlags;
1755         lpMMThd->hTask          = 0;
1756
1757         if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
1758             lpMMThd->hEvent = CreateEventW(NULL, FALSE, TRUE, NULL);
1759
1760             TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd);
1761             if (lpMMThd->dwFlags & 2) {
1762                 /* as long as we don't support MM VxD in wine, we don't need
1763                  * to care about this flag
1764                  */
1765                 /* FIXME("Don't know how to properly open VxD handles\n"); */
1766                 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
1767             }
1768
1769             lpMMThd->hThread = CreateThread(0, 0, WINE_mmThreadEntryPoint,
1770                                             (LPVOID)(DWORD_PTR)hndl, CREATE_SUSPENDED, &lpMMThd->dwThreadID);
1771             if (lpMMThd->hThread == 0) {
1772                 WARN("Couldn't create thread\n");
1773                 /* clean-up(VxDhandle...); devicedirectio... */
1774                 if (lpMMThd->hEvent != 0)
1775                     CloseHandle(lpMMThd->hEvent);
1776                 ret = 2;
1777             } else {
1778                 SetThreadPriority(lpMMThd->hThread, THREAD_PRIORITY_TIME_CRITICAL);
1779                 TRACE("Got a nice thread hndl=%p id=0x%08x\n", lpMMThd->hThread, lpMMThd->dwThreadID);
1780                 ret = 0;
1781             }
1782         } else {
1783             /* get WINE_mmThreadEntryPoint()
1784              * 2047 is its ordinal in mmsystem.spec
1785              */
1786             FARPROC16   fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR)2047);
1787
1788             TRACE("farproc seg=0x%p lin=%p\n", fp, MapSL((SEGPTR)fp));
1789
1790             ret = (fp == 0) ? 2 : mmTaskCreate16((DWORD)fp, 0, hndl);
1791         }
1792
1793         if (ret == 0) {
1794             if (lpMMThd->hThread && !ResumeThread(lpMMThd->hThread))
1795                 WARN("Couldn't resume thread\n");
1796
1797             while (lpMMThd->dwStatus != 0x10) { /* test also HIWORD of dwStatus */
1798                 UserYield16();
1799             }
1800         }
1801     }
1802
1803     if (ret != 0) {
1804         GlobalFree16(hndl);
1805         hndl = 0;
1806     }
1807
1808     if (lpHndl)
1809         *lpHndl = hndl;
1810
1811     TRACE("ok => %ld\n", ret);
1812     return ret;
1813 }
1814
1815 /**************************************************************************
1816  *                              mmThreadSignal          [MMSYSTEM.1121]
1817  */
1818 void WINAPI mmThreadSignal16(HANDLE16 hndl)
1819 {
1820     TRACE("(%04x)!\n", hndl);
1821
1822     if (hndl) {
1823         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1824
1825         lpMMThd->dwCounter++;
1826         if (lpMMThd->hThread != 0) {
1827             InterlockedIncrement(&lpMMThd->dwSignalCount);
1828             SetEvent(lpMMThd->hEvent);
1829         } else {
1830             mmTaskSignal16(lpMMThd->hTask);
1831         }
1832         lpMMThd->dwCounter--;
1833     }
1834 }
1835
1836 static  void    MMSYSTEM_ThreadBlock(WINE_MMTHREAD* lpMMThd)
1837 {
1838     MSG         msg;
1839     DWORD       ret;
1840
1841     if (lpMMThd->dwThreadID != GetCurrentThreadId())
1842         ERR("Not called by thread itself\n");
1843
1844     for (;;) {
1845         ResetEvent(lpMMThd->hEvent);
1846         if (InterlockedDecrement(&lpMMThd->dwSignalCount) >= 0)
1847             break;
1848         InterlockedIncrement(&lpMMThd->dwSignalCount);
1849
1850         TRACE("S1\n");
1851
1852         ret = MsgWaitForMultipleObjects(1, &lpMMThd->hEvent, FALSE, INFINITE, QS_ALLINPUT);
1853         switch (ret) {
1854         case WAIT_OBJECT_0:     /* Event */
1855             TRACE("S2.1\n");
1856             break;
1857         case WAIT_OBJECT_0 + 1: /* Msg */
1858             TRACE("S2.2\n");
1859             if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
1860                 TranslateMessage(&msg);
1861                 DispatchMessageA(&msg);
1862             }
1863             break;
1864         default:
1865             WARN("S2.x unsupported ret val 0x%08x\n", ret);
1866         }
1867         TRACE("S3\n");
1868     }
1869 }
1870
1871 /**************************************************************************
1872  *                              mmThreadBlock           [MMSYSTEM.1122]
1873  */
1874 void    WINAPI mmThreadBlock16(HANDLE16 hndl)
1875 {
1876     TRACE("(%04x)!\n", hndl);
1877
1878     if (hndl) {
1879         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1880
1881         if (lpMMThd->hThread != 0) {
1882             DWORD       lc;
1883
1884             ReleaseThunkLock(&lc);
1885             MMSYSTEM_ThreadBlock(lpMMThd);
1886             RestoreThunkLock(lc);
1887         } else {
1888             mmTaskBlock16(lpMMThd->hTask);
1889         }
1890     }
1891     TRACE("done\n");
1892 }
1893
1894 /**************************************************************************
1895  *                              mmThreadIsCurrent       [MMSYSTEM.1123]
1896  */
1897 BOOL16  WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
1898 {
1899     BOOL16              ret = FALSE;
1900
1901     TRACE("(%04x)!\n", hndl);
1902
1903     if (hndl && mmThreadIsValid16(hndl)) {
1904         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1905         ret = (GetCurrentThreadId() == lpMMThd->dwThreadID);
1906     }
1907     TRACE("=> %d\n", ret);
1908     return ret;
1909 }
1910
1911 /**************************************************************************
1912  *                              mmThreadIsValid         [MMSYSTEM.1124]
1913  */
1914 BOOL16  WINAPI  mmThreadIsValid16(HANDLE16 hndl)
1915 {
1916     BOOL16              ret = FALSE;
1917
1918     TRACE("(%04x)!\n", hndl);
1919
1920     if (hndl) {
1921         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1922
1923         if (!IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) &&
1924             lpMMThd->dwSignature == WINE_MMTHREAD_CREATED &&
1925             IsTask16(lpMMThd->hTask)) {
1926             lpMMThd->dwCounter++;
1927             if (lpMMThd->hThread != 0) {
1928                 DWORD   dwThreadRet;
1929                 if (GetExitCodeThread(lpMMThd->hThread, &dwThreadRet) &&
1930                     dwThreadRet == STATUS_PENDING) {
1931                     ret = TRUE;
1932                 }
1933             } else {
1934                 ret = TRUE;
1935             }
1936             lpMMThd->dwCounter--;
1937         }
1938     }
1939     TRACE("=> %d\n", ret);
1940     return ret;
1941 }
1942
1943 /**************************************************************************
1944  *                              mmThreadGetTask         [MMSYSTEM.1125]
1945  */
1946 HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
1947 {
1948     HANDLE16    ret = 0;
1949
1950     TRACE("(%04x)\n", hndl);
1951
1952     if (mmThreadIsValid16(hndl)) {
1953         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1954         ret = lpMMThd->hTask;
1955     }
1956     return ret;
1957 }
1958
1959 /**************************************************************************
1960  *                              __wine_mmThreadEntryPoint (MMSYSTEM.2047)
1961  */
1962 DWORD WINAPI WINE_mmThreadEntryPoint(LPVOID p)
1963 {
1964     HANDLE16            hndl = (HANDLE16)(DWORD_PTR)p;
1965     WINE_MMTHREAD*      lpMMThd = WINMM_GetmmThread(hndl);
1966
1967     TRACE("(%04x %p)\n", hndl, lpMMThd);
1968
1969     lpMMThd->hTask = LOWORD(GetCurrentTask());
1970     TRACE("[10-%p] setting hTask to 0x%08x\n", lpMMThd->hThread, lpMMThd->hTask);
1971     lpMMThd->dwStatus = 0x10;
1972     MMSYSTEM_ThreadBlock(lpMMThd);
1973     TRACE("[20-%p]\n", lpMMThd->hThread);
1974     lpMMThd->dwStatus = 0x20;
1975     if (lpMMThd->fpThread) {
1976         WOWCallback16(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
1977     }
1978     lpMMThd->dwStatus = 0x30;
1979     TRACE("[30-%p]\n", lpMMThd->hThread);
1980     while (lpMMThd->dwCounter) {
1981         Sleep(1);
1982         /* WOWYield16();*/
1983     }
1984     TRACE("[XX-%p]\n", lpMMThd->hThread);
1985     /* paranoia */
1986     lpMMThd->dwSignature = WINE_MMTHREAD_DELETED;
1987     /* close lpMMThread->hVxD directIO */
1988     if (lpMMThd->hEvent)
1989         CloseHandle(lpMMThd->hEvent);
1990     GlobalFree16(hndl);
1991     TRACE("done\n");
1992
1993     return 0;
1994 }
1995
1996 typedef BOOL16 (WINAPI *MMCPLCALLBACK)(HWND, LPCSTR, LPCSTR, LPCSTR);
1997
1998 /**************************************************************************
1999  *                      mmShowMMCPLPropertySheet        [MMSYSTEM.1150]
2000  */
2001 BOOL16  WINAPI  mmShowMMCPLPropertySheet16(HWND hWnd, LPCSTR lpStrDevice,
2002                                            LPCSTR lpStrTab, LPCSTR lpStrTitle)
2003 {
2004     HANDLE      hndl;
2005     BOOL16      ret = FALSE;
2006
2007     TRACE("(%p \"%s\" \"%s\" \"%s\")\n", hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2008
2009     hndl = LoadLibraryA("MMSYS.CPL");
2010     if (hndl != 0) {
2011         MMCPLCALLBACK   fp = (MMCPLCALLBACK)GetProcAddress(hndl, "ShowMMCPLPropertySheet");
2012         if (fp != NULL) {
2013             DWORD       lc;
2014             ReleaseThunkLock(&lc);
2015             ret = (fp)(hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2016             RestoreThunkLock(lc);
2017         }
2018         FreeLibrary(hndl);
2019     }
2020
2021     return ret;
2022 }
2023
2024 /**************************************************************************
2025  *                      StackEnter              [MMSYSTEM.32]
2026  */
2027 void WINAPI StackEnter16(void)
2028 {
2029 #ifdef __i386__
2030     /* mmsystem.dll from Win 95 does only this: so does Wine */
2031     __asm__("stc");
2032 #endif
2033 }
2034
2035 /**************************************************************************
2036  *                      StackLeave              [MMSYSTEM.33]
2037  */
2038 void WINAPI StackLeave16(void)
2039 {
2040 #ifdef __i386__
2041     /* mmsystem.dll from Win 95 does only this: so does Wine */
2042     __asm__("stc");
2043 #endif
2044 }
2045
2046 /**************************************************************************
2047  *                      WMMMidiRunOnce          [MMSYSTEM.8]
2048  */
2049 void WINAPI WMMMidiRunOnce16(void)
2050 {
2051     FIXME("(), stub!\n");
2052 }
2053
2054 /* ###################################################
2055  * #                    DRIVER                       #
2056  * ###################################################
2057  */
2058
2059 /**************************************************************************
2060  *                              DRIVER_MapMsg32To16             [internal]
2061  *
2062  * Map a 32 bit driver message to a 16 bit driver message.
2063  */
2064 static WINMM_MapType DRIVER_MapMsg32To16(WORD wMsg, LPARAM *lParam1, LPARAM *lParam2)
2065 {
2066     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
2067
2068     switch (wMsg) {
2069     case DRV_LOAD:
2070     case DRV_ENABLE:
2071     case DRV_DISABLE:
2072     case DRV_FREE:
2073     case DRV_QUERYCONFIGURE:
2074     case DRV_REMOVE:
2075     case DRV_EXITSESSION:
2076     case DRV_EXITAPPLICATION:
2077     case DRV_POWER:
2078     case DRV_CLOSE:     /* should be 0/0 */
2079     case DRV_OPEN:      /* pass through */
2080         /* lParam1 and lParam2 are not used */
2081         ret = WINMM_MAP_OK;
2082         break;
2083     case DRV_CONFIGURE:
2084     case DRV_INSTALL:
2085         /* lParam1 is a handle to a window (conf) or to a driver (inst) or not used,
2086          * lParam2 is a pointer to DRVCONFIGINFO
2087          */
2088         if (*lParam2) {
2089             LPDRVCONFIGINFO16 dci16 = HeapAlloc( GetProcessHeap(), 0, sizeof(*dci16) );
2090             LPDRVCONFIGINFO     dci32 = (LPDRVCONFIGINFO)(*lParam2);
2091
2092             if (dci16) {
2093                 LPSTR str1 = NULL,str2;
2094                 INT len;
2095                 dci16->dwDCISize = sizeof(DRVCONFIGINFO16);
2096
2097                 if (dci32->lpszDCISectionName) {
2098                     len = WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCISectionName, -1, NULL, 0, NULL, NULL );
2099                     str1 = HeapAlloc( GetProcessHeap(), 0, len );
2100                     if (str1) {
2101                         WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCISectionName, -1, str1, len, NULL, NULL );
2102                         dci16->lpszDCISectionName = MapLS( str1 );
2103                     } else {
2104                         HeapFree( GetProcessHeap(), 0, dci16);
2105                         return WINMM_MAP_NOMEM;
2106                     }
2107                 } else {
2108                     dci16->lpszDCISectionName = 0L;
2109                 }
2110                 if (dci32->lpszDCIAliasName) {
2111                     len = WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, NULL, 0, NULL, NULL );
2112                     str2 = HeapAlloc( GetProcessHeap(), 0, len );
2113                     if (str2) {
2114                         WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, str2, len, NULL, NULL );
2115                         dci16->lpszDCIAliasName = MapLS( str2 );
2116                     } else {
2117                         HeapFree( GetProcessHeap(), 0, str1);
2118                         HeapFree( GetProcessHeap(), 0, dci16);
2119                         return WINMM_MAP_NOMEM;
2120                     }
2121                 } else {
2122                     dci16->lpszDCISectionName = 0L;
2123                 }
2124             } else {
2125                 return WINMM_MAP_NOMEM;
2126             }
2127             *lParam2 = MapLS( dci16 );
2128             ret = WINMM_MAP_OKMEM;
2129         } else {
2130             ret = WINMM_MAP_OK;
2131         }
2132         break;
2133     default:
2134         if (!((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100))) {
2135            FIXME("Unknown message 0x%04x\n", wMsg);
2136         }
2137         ret = WINMM_MAP_OK;
2138     }
2139     return ret;
2140 }
2141
2142 /**************************************************************************
2143  *                              DRIVER_UnMapMsg32To16           [internal]
2144  *
2145  * UnMap a 32 bit driver message to a 16 bit driver message.
2146  */
2147 static WINMM_MapType DRIVER_UnMapMsg32To16(WORD wMsg, DWORD lParam1, DWORD lParam2)
2148 {
2149     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
2150
2151     switch (wMsg) {
2152     case DRV_LOAD:
2153     case DRV_ENABLE:
2154     case DRV_DISABLE:
2155     case DRV_FREE:
2156     case DRV_QUERYCONFIGURE:
2157     case DRV_REMOVE:
2158     case DRV_EXITSESSION:
2159     case DRV_EXITAPPLICATION:
2160     case DRV_POWER:
2161     case DRV_OPEN:
2162     case DRV_CLOSE:
2163         /* lParam1 and lParam2 are not used */
2164         break;
2165     case DRV_CONFIGURE:
2166     case DRV_INSTALL:
2167         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
2168         if (lParam2) {
2169             LPDRVCONFIGINFO16   dci16 = MapSL(lParam2);
2170             HeapFree( GetProcessHeap(), 0, MapSL(dci16->lpszDCISectionName) );
2171             HeapFree( GetProcessHeap(), 0, MapSL(dci16->lpszDCIAliasName) );
2172             UnMapLS( lParam2 );
2173             UnMapLS( dci16->lpszDCISectionName );
2174             UnMapLS( dci16->lpszDCIAliasName );
2175             HeapFree( GetProcessHeap(), 0, dci16 );
2176         }
2177         ret = WINMM_MAP_OK;
2178         break;
2179     default:
2180         if (!((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100))) {
2181             FIXME("Unknown message 0x%04x\n", wMsg);
2182         }
2183         ret = WINMM_MAP_OK;
2184     }
2185     return ret;
2186 }
2187
2188 /**************************************************************************
2189  *                              DRIVER_TryOpenDriver16          [internal]
2190  *
2191  * Tries to load a 16 bit driver whose DLL's (module) name is lpFileName.
2192  */
2193 static  LPWINE_DRIVER   DRIVER_OpenDriver16(LPCWSTR fn, LPCWSTR sn, LPARAM lParam2)
2194 {
2195     LPWINE_DRIVER       lpDrv = NULL;
2196     LPCSTR              cause = NULL;
2197     LPSTR               fnA = NULL, snA = NULL;
2198     unsigned            len;
2199
2200     TRACE("(%s, %s, %08lX);\n", debugstr_w(fn), debugstr_w(sn), lParam2);
2201
2202     lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER));
2203     if (lpDrv == NULL) {cause = "OOM"; goto exit;}
2204
2205     if (fn)
2206     {
2207         len = WideCharToMultiByte( CP_ACP, 0, fn, -1, NULL, 0, NULL, NULL );
2208         fnA = HeapAlloc(GetProcessHeap(), 0, len);
2209         if (fnA == NULL) {cause = "OOM"; goto exit;}
2210         WideCharToMultiByte( CP_ACP, 0, fn, -1, fnA, len, NULL, NULL );
2211     }
2212
2213     if (sn)
2214     {
2215         len = WideCharToMultiByte( CP_ACP, 0, sn, -1, NULL, 0, NULL, NULL );
2216         snA = HeapAlloc(GetProcessHeap(), 0, len);
2217         if (snA == NULL) {cause = "OOM"; goto exit;}
2218         WideCharToMultiByte( CP_ACP, 0, sn, -1, snA, len, NULL, NULL );
2219     }
2220
2221     /* FIXME: shall we do some black magic here on sn ?
2222      *  drivers32 => drivers
2223      *  mci32 => mci
2224      * ...
2225      */
2226     lpDrv->d.d16.hDriver16 = OpenDriver16(fnA, snA, lParam2);
2227     if (lpDrv->d.d16.hDriver16 == 0) {cause = "Not a 16 bit driver"; goto exit;}
2228     lpDrv->dwFlags = WINE_GDF_16BIT;
2229
2230 exit:
2231     HeapFree(GetProcessHeap(), 0, fnA);
2232     HeapFree(GetProcessHeap(), 0, snA);
2233
2234     if (cause)
2235     {
2236         TRACE("Unable to load 16 bit module %s[%s]: %s\n",
2237             debugstr_w(fn), debugstr_w(sn), cause);
2238         HeapFree(GetProcessHeap(), 0, lpDrv);
2239         return NULL;
2240     }
2241
2242     TRACE("=> %p\n", lpDrv);
2243     return lpDrv;
2244 }
2245
2246 /******************************************************************
2247  *              DRIVER_SendMessage16
2248  *
2249  *
2250  */
2251 static LRESULT  DRIVER_SendMessage16(HDRVR16 hDrv16, UINT msg, 
2252                                      LPARAM lParam1, LPARAM lParam2)
2253 {
2254     LRESULT             ret = 0;
2255     WINMM_MapType       map;
2256
2257     TRACE("Before sdm16 call hDrv=%04x wMsg=%04x p1=%08lx p2=%08lx\n",
2258           hDrv16, msg, lParam1, lParam2);
2259
2260     switch (map = DRIVER_MapMsg32To16(msg, &lParam1, &lParam2)) {
2261     case WINMM_MAP_OKMEM:
2262     case WINMM_MAP_OK:
2263         ret = SendDriverMessage16(hDrv16, msg, lParam1, lParam2);
2264         if (map == WINMM_MAP_OKMEM)
2265             DRIVER_UnMapMsg32To16(msg, lParam1, lParam2);
2266     default:
2267         break;
2268     }
2269     return ret;
2270 }
2271
2272 /******************************************************************
2273  *              DRIVER_CloseDriver16
2274  *
2275  *
2276  */
2277 static LRESULT DRIVER_CloseDriver16(HDRVR16 hDrv16, LPARAM lParam1, LPARAM lParam2)
2278 {
2279     return CloseDriver16(hDrv16, lParam1, lParam2);
2280 }
2281
2282 /**************************************************************************
2283  *                              DrvOpen                 [MMSYSTEM.1100]
2284  */
2285 HDRVR16 WINAPI DrvOpen16(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
2286 {
2287     return OpenDriver16(lpDriverName, lpSectionName, lParam);
2288 }
2289
2290 /**************************************************************************
2291  *                              DrvClose                [MMSYSTEM.1101]
2292  */
2293 LRESULT WINAPI DrvClose16(HDRVR16 hDrv, LPARAM lParam1, LPARAM lParam2)
2294 {
2295     return CloseDriver16(hDrv, lParam1, lParam2);
2296 }
2297
2298 /**************************************************************************
2299  *                              DrvSendMessage          [MMSYSTEM.1102]
2300  */
2301 LRESULT WINAPI DrvSendMessage16(HDRVR16 hDrv, WORD msg, LPARAM lParam1,
2302                                 LPARAM lParam2)
2303 {
2304     return SendDriverMessage16(hDrv, msg, lParam1, lParam2);
2305 }
2306
2307 /**************************************************************************
2308  *                              DrvGetModuleHandle      [MMSYSTEM.1103]
2309  */
2310 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrv)
2311 {
2312     return GetDriverModuleHandle16(hDrv);
2313 }
2314
2315 /**************************************************************************
2316  *                              DrvDefDriverProc        [MMSYSTEM.1104]
2317  */
2318 LRESULT WINAPI DrvDefDriverProc16(DWORD dwDriverID, HDRVR16 hDrv, WORD wMsg,
2319                                   DWORD dwParam1, DWORD dwParam2)
2320 {
2321     return DefDriverProc16(dwDriverID, hDrv, wMsg, dwParam1, dwParam2);
2322 }
2323
2324 /**************************************************************************
2325  *                              DriverProc                      [MMSYSTEM.6]
2326  */
2327 LRESULT WINAPI DriverProc16(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
2328                             DWORD dwParam1, DWORD dwParam2)
2329 {
2330     TRACE("dwDevID=%08x hDrv=%04x wMsg=%04x dwParam1=%08x dwParam2=%08x\n",
2331           dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2332
2333     return DrvDefDriverProc16(dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2334 }
2335
2336 /* ###################################################
2337  * #                     TIME                        #
2338  * ###################################################
2339  */
2340
2341 /******************************************************************
2342  *              MMSYSTEM_MMTIME32to16
2343  *
2344  *
2345  */
2346 void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16, const MMTIME* mmt32)
2347 {
2348     mmt16->wType = mmt32->wType;
2349     /* layout of rest is the same for 32/16,
2350      * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
2351      */
2352     memcpy(&(mmt16->u), &(mmt32->u), sizeof(mmt16->u));
2353 }
2354
2355 /******************************************************************
2356  *              MMSYSTEM_MMTIME16to32
2357  *
2358  *
2359  */
2360 void MMSYSTEM_MMTIME16to32(LPMMTIME mmt32, const MMTIME16* mmt16)
2361 {
2362     mmt32->wType = mmt16->wType;
2363     /* layout of rest is the same for 32/16,
2364      * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
2365      */
2366     memcpy(&(mmt32->u), &(mmt16->u), sizeof(mmt16->u));
2367 }
2368
2369 /**************************************************************************
2370  *                              timeGetSystemTime       [MMSYSTEM.601]
2371  */
2372 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
2373 {
2374     if (wSize >= sizeof(*lpTime)) {
2375         lpTime->wType = TIME_MS;
2376         lpTime->u.ms = GetTickCount();
2377
2378         TRACE("=> %u\n", lpTime->u.ms);
2379     }
2380
2381     return 0;
2382 }
2383
2384 struct timer_entry {
2385     struct list         entry;
2386     UINT                id;
2387     LPTIMECALLBACK16    func16;
2388     DWORD               user;
2389 };
2390
2391 static struct list timer_list = LIST_INIT(timer_list);
2392
2393 static void CALLBACK timeCB3216(UINT id, UINT uMsg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2)
2394 {
2395     struct timer_entry* te = (void*)user;
2396     WORD                args[8];
2397     DWORD               ret;
2398
2399     args[7] = LOWORD(id);
2400     args[6] = LOWORD(uMsg);
2401     args[5] = HIWORD(te->user);
2402     args[4] = LOWORD(te->user);
2403     args[3] = HIWORD(dw1);
2404     args[2] = LOWORD(dw2);
2405     args[1] = HIWORD(dw2);
2406     args[0] = LOWORD(dw2);
2407     WOWCallback16Ex((DWORD)te->func16, WCB16_PASCAL, sizeof(args), args, &ret);
2408 }
2409
2410 /**************************************************************************
2411  *                              timeSetEvent            [MMSYSTEM.602]
2412  */
2413 MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol, LPTIMECALLBACK16 lpFunc,
2414                                  DWORD dwUser, UINT16 wFlags)
2415 {
2416     MMRESULT16          id;
2417     struct timer_entry* te;
2418
2419     switch (wFlags & (TIME_CALLBACK_EVENT_SET|TIME_CALLBACK_EVENT_PULSE))
2420     {
2421     case TIME_CALLBACK_EVENT_SET:
2422     case TIME_CALLBACK_EVENT_PULSE:
2423         id = timeSetEvent(wDelay, wResol, (LPTIMECALLBACK)lpFunc, dwUser, wFlags);
2424         break;
2425     case TIME_CALLBACK_FUNCTION:
2426         te = HeapAlloc(GetProcessHeap(), 0, sizeof(*te));
2427         if (!te) return 0;
2428         te->func16 = lpFunc;
2429         te->user = dwUser;
2430         id = te->id = timeSetEvent(wDelay, wResol, timeCB3216, (DWORD_PTR)te, wFlags);
2431         if (id)
2432         {
2433             EnterCriticalSection(&mmdrv_cs);
2434             list_add_tail(&timer_list, &te->entry);
2435             LeaveCriticalSection(&mmdrv_cs);
2436         }
2437         else HeapFree(GetProcessHeap(), 0, te);
2438         break;
2439     default:
2440         id = 0;
2441         break;
2442     }
2443     return id;
2444 }
2445
2446 /**************************************************************************
2447  *                              timeKillEvent           [MMSYSTEM.603]
2448  */
2449 MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
2450 {
2451     MMRESULT16  ret = timeKillEvent(wID);
2452     struct timer_entry* te;
2453
2454     if (ret == TIMERR_NOERROR)
2455     {
2456         EnterCriticalSection(&mmdrv_cs);
2457         LIST_FOR_EACH_ENTRY(te, &timer_list, struct timer_entry, entry)
2458         {
2459             if (wID == te->id)
2460             {
2461                 list_remove(&te->entry);
2462                 HeapFree(GetProcessHeap(), 0, te);
2463                 break;
2464             }
2465         }
2466         LeaveCriticalSection(&mmdrv_cs);
2467     }
2468     return ret;
2469 }
2470
2471 /**************************************************************************
2472  *                              timeGetDevCaps          [MMSYSTEM.604]
2473  */
2474 MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
2475 {
2476     TIMECAPS    caps;
2477     MMRESULT    ret;
2478     TRACE("(%p, %u) !\n", lpCaps, wSize);
2479
2480     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
2481
2482     ret = timeGetDevCaps(&caps, sizeof(caps));
2483     if (ret == MMSYSERR_NOERROR) {
2484         TIMECAPS16 tc16;
2485         tc16.wPeriodMin = caps.wPeriodMin;
2486         tc16.wPeriodMax = caps.wPeriodMax;
2487         memcpy(lpCaps, &tc16, min(wSize, sizeof(tc16)));
2488     }
2489     return ret;
2490 }
2491
2492 /**************************************************************************
2493  *                              timeBeginPeriod [MMSYSTEM.605]
2494  */
2495 MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
2496 {
2497     TRACE("(%u) !\n", wPeriod);
2498
2499     return timeBeginPeriod(wPeriod);
2500 }
2501
2502 /**************************************************************************
2503  *                              timeEndPeriod           [MMSYSTEM.606]
2504  */
2505 MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
2506 {
2507     TRACE("(%u) !\n", wPeriod);
2508
2509     return timeEndPeriod(wPeriod);
2510 }
2511
2512 /**************************************************************************
2513  *                      mciLoadCommandResource                  [MMSYSTEM.705]
2514  */
2515 UINT16 WINAPI mciLoadCommandResource16(HINSTANCE16 hInst, LPCSTR resname, UINT16 type)
2516 {
2517     HRSRC16     res;
2518     HGLOBAL16   handle;
2519     const BYTE* ptr16;
2520     BYTE*       ptr32;
2521     unsigned    pos = 0, size = 1024, len;
2522     const char* str;
2523     DWORD       flg;
2524     WORD        eid;
2525     UINT16      ret = MCIERR_OUT_OF_MEMORY;
2526
2527     if (!(res = FindResource16( hInst, resname, (LPSTR)RT_RCDATA))) return MCI_NO_COMMAND_TABLE;
2528     if (!(handle = LoadResource16( hInst, res ))) return MCI_NO_COMMAND_TABLE;
2529     ptr16 = LockResource16(handle);
2530     /* converting the 16 bit resource table into a 32W one */
2531     if ((ptr32 = HeapAlloc(GetProcessHeap(), 0, size)))
2532     {
2533         do {
2534             str = (LPCSTR)ptr16;
2535             ptr16 += strlen(str) + 1;
2536             flg = *(const DWORD*)ptr16;
2537             eid = *(const WORD*)(ptr16 + sizeof(DWORD));
2538             ptr16 += sizeof(DWORD) + sizeof(WORD);
2539             len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0) * sizeof(WCHAR);
2540             if (pos + len + sizeof(DWORD) + sizeof(WORD) > size)
2541             {
2542                 while (pos + len * sizeof(WCHAR) + sizeof(DWORD) + sizeof(WORD) > size) size += 1024;
2543                 ptr32 = HeapReAlloc(GetProcessHeap(), 0, ptr32, size);
2544                 if (!ptr32) goto the_end;
2545             }
2546             MultiByteToWideChar(CP_ACP, 0, str, -1, (LPWSTR)(ptr32 + pos), len / sizeof(WCHAR));
2547             *(DWORD*)(ptr32 + pos + len) = flg;
2548             *(WORD*)(ptr32 + pos + len + sizeof(DWORD)) = eid;
2549             pos += len + sizeof(DWORD) + sizeof(WORD);
2550         } while (eid != MCI_END_COMMAND_LIST);
2551     }
2552 the_end:
2553     FreeResource16( handle );
2554     if (ptr32) ret = MCI_SetCommandTable(ptr32, type);
2555     return ret;
2556 }
2557
2558 /**************************************************************************
2559  *                      mciFreeCommandResource                  [MMSYSTEM.713]
2560  */
2561 BOOL16 WINAPI mciFreeCommandResource16(UINT16 uTable)
2562 {
2563     TRACE("(%04x)!\n", uTable);
2564
2565     return MCI_DeleteCommandTable(uTable, TRUE);
2566 }
2567
2568 /* ###################################################
2569  * #                     JOYSTICK                    #
2570  * ###################################################
2571  */
2572
2573 /**************************************************************************
2574  *                              joyGetNumDevs           [MMSYSTEM.101]
2575  */
2576 UINT16 WINAPI joyGetNumDevs16(void)
2577 {
2578     return joyGetNumDevs();
2579 }
2580
2581 /**************************************************************************
2582  *                              joyGetDevCaps           [MMSYSTEM.102]
2583  */
2584 MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize)
2585 {
2586     JOYCAPSA    jca;
2587     MMRESULT    ret;
2588
2589     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
2590
2591     ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
2592
2593     if (ret != JOYERR_NOERROR) return ret;
2594     lpCaps->wMid = jca.wMid;
2595     lpCaps->wPid = jca.wPid;
2596     strcpy(lpCaps->szPname, jca.szPname);
2597     lpCaps->wXmin = jca.wXmin;
2598     lpCaps->wXmax = jca.wXmax;
2599     lpCaps->wYmin = jca.wYmin;
2600     lpCaps->wYmax = jca.wYmax;
2601     lpCaps->wZmin = jca.wZmin;
2602     lpCaps->wZmax = jca.wZmax;
2603     lpCaps->wNumButtons = jca.wNumButtons;
2604     lpCaps->wPeriodMin = jca.wPeriodMin;
2605     lpCaps->wPeriodMax = jca.wPeriodMax;
2606
2607     if (wSize >= sizeof(JOYCAPS16)) { /* Win95 extensions ? */
2608         lpCaps->wRmin = jca.wRmin;
2609         lpCaps->wRmax = jca.wRmax;
2610         lpCaps->wUmin = jca.wUmin;
2611         lpCaps->wUmax = jca.wUmax;
2612         lpCaps->wVmin = jca.wVmin;
2613         lpCaps->wVmax = jca.wVmax;
2614         lpCaps->wCaps = jca.wCaps;
2615         lpCaps->wMaxAxes = jca.wMaxAxes;
2616         lpCaps->wNumAxes = jca.wNumAxes;
2617         lpCaps->wMaxButtons = jca.wMaxButtons;
2618         strcpy(lpCaps->szRegKey, jca.szRegKey);
2619         strcpy(lpCaps->szOEMVxD, jca.szOEMVxD);
2620     }
2621
2622     return ret;
2623 }
2624
2625 /**************************************************************************
2626  *                              joyGetPosEx           [MMSYSTEM.110]
2627  */
2628 MMRESULT16 WINAPI joyGetPosEx16(UINT16 wID, LPJOYINFOEX lpInfo)
2629 {
2630     return joyGetPosEx(wID, lpInfo);
2631 }
2632
2633 /**************************************************************************
2634  *                              joyGetPos               [MMSYSTEM.103]
2635  */
2636 MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
2637 {
2638     JOYINFO     ji;
2639     MMRESULT    ret;
2640
2641     TRACE("(%d, %p);\n", wID, lpInfo);
2642
2643     if ((ret = joyGetPos(wID, &ji)) == JOYERR_NOERROR) {
2644         lpInfo->wXpos = ji.wXpos;
2645         lpInfo->wYpos = ji.wYpos;
2646         lpInfo->wZpos = ji.wZpos;
2647         lpInfo->wButtons = ji.wButtons;
2648     }
2649     return ret;
2650 }
2651
2652 /**************************************************************************
2653  *                              joyGetThreshold         [MMSYSTEM.104]
2654  */
2655 MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
2656 {
2657     UINT        t;
2658     MMRESULT    ret;
2659
2660     ret = joyGetThreshold(wID, &t);
2661     if (ret == JOYERR_NOERROR)
2662         *lpThreshold = t;
2663     return ret;
2664 }
2665
2666 /**************************************************************************
2667  *                              joyReleaseCapture       [MMSYSTEM.105]
2668  */
2669 MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
2670 {
2671     return joyReleaseCapture(wID);
2672 }
2673
2674 /**************************************************************************
2675  *                              joySetCapture           [MMSYSTEM.106]
2676  */
2677 MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd, UINT16 wID, UINT16 wPeriod, BOOL16 bChanged)
2678 {
2679     return joySetCapture(HWND_32(hWnd), wID, wPeriod, bChanged);
2680 }
2681
2682 /**************************************************************************
2683  *                              joySetThreshold         [MMSYSTEM.107]
2684  */
2685 MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
2686 {
2687     return joySetThreshold(wID,wThreshold);
2688 }
2689
2690 /**************************************************************************
2691  *                              joySetCalibration       [MMSYSTEM.109]
2692  */
2693 MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
2694 {
2695     FIXME("(%04X): stub.\n", wID);
2696     return JOYERR_NOCANDO;
2697 }