Keep track of per-column information inside the listview.
[wine] / dlls / winmm / mmsystem.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  * MMSYTEM functions
5  *
6  * Copyright 1993      Martin Ayotte
7  *           1998-2002 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 /*
25  * Eric POUECH :
26  *      99/4    added mmTask and mmThread functions support
27  */
28
29 /* FIXME: I think there are some segmented vs. linear pointer weirdnesses
30  *        and long term pointers to 16 bit space in here
31  */
32
33 #include <string.h>
34
35 #include "mmsystem.h"
36 #include "winbase.h"
37
38 #include "wine/mmsystem16.h"
39 #include "wine/winuser16.h"
40 #include "winemm.h"
41 #include "heap.h"
42
43 #include "wine/debug.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
46
47 /**************************************************************************
48  *                      DllEntryPoint (MMSYSTEM.2046)
49  *
50  * MMSYSTEM DLL entry point
51  *
52  */
53 BOOL WINAPI MMSYSTEM_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
54                              WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
55 {
56     HANDLE                      hndl;
57     LPWINE_MM_IDATA             iData;
58
59     TRACE("0x%x 0x%lx\n", hinstDLL, fdwReason);
60
61     switch (fdwReason) {
62     case DLL_PROCESS_ATTACH:
63         /* need to load WinMM in order to:
64          * - initiate correctly shared variables (MULTIMEDIA_Init())
65          * - create correctly the per process WINE_MM_IDATA chunk
66          */
67         hndl = LoadLibraryA("WINMM.DLL");
68
69         if (!hndl) {
70             ERR("Could not load sibling WinMM.dll\n");
71             return FALSE;
72         }
73         iData = MULTIMEDIA_GetIData();
74         iData->hWinMM16Instance = hinstDLL;
75         iData->h16Module32 = hndl;
76         break;
77     case DLL_PROCESS_DETACH:
78         iData = MULTIMEDIA_GetIData();
79         FreeLibrary(iData->h16Module32);
80         break;
81     case DLL_THREAD_ATTACH:
82     case DLL_THREAD_DETACH:
83         break;
84     }
85     return TRUE;
86 }
87
88 /**************************************************************************
89  *                              MMSYSTEM_WEP                    [MMSYSTEM.1]
90  */
91 int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
92                         WORD cbHeapSize, LPSTR lpCmdLine)
93 {
94     FIXME("STUB: Unloading MMSystem DLL ... hInst=%04X \n", hInstance);
95     return TRUE;
96 }
97
98 /**************************************************************************
99  *                              PlaySound               [MMSYSTEM.3]
100  */
101 BOOL16 WINAPI PlaySound16(LPCSTR pszSound, HMODULE16 hmod, DWORD fdwSound)
102 {
103     BOOL16      retv;
104     DWORD       lc;
105
106     ReleaseThunkLock(&lc);
107     retv = PlaySoundA(pszSound, hmod, fdwSound);
108     RestoreThunkLock(lc);
109
110     return retv;
111 }
112
113 /**************************************************************************
114  *                              sndPlaySound            [MMSYSTEM.2]
115  */
116 BOOL16 WINAPI sndPlaySound16(LPCSTR lpszSoundName, UINT16 uFlags)
117 {
118     BOOL16      retv;
119     DWORD       lc;
120
121     ReleaseThunkLock(&lc);
122     retv = sndPlaySoundA(lpszSoundName, uFlags);
123     RestoreThunkLock(lc);
124
125     return retv;
126 }
127
128 /**************************************************************************
129  *                              mmsystemGetVersion      [MMSYSTEM.5]
130  *
131  */
132 UINT16 WINAPI mmsystemGetVersion16(void)
133 {
134     return mmsystemGetVersion();
135 }
136
137 /**************************************************************************
138  *                              DriverCallback                  [MMSYSTEM.31]
139  */
140 BOOL16 WINAPI DriverCallback16(DWORD dwCallBack, UINT16 uFlags, HDRVR16 hDev,
141                                WORD wMsg, DWORD dwUser, DWORD dwParam1,
142                                DWORD dwParam2)
143 {
144     return DriverCallback(dwCallBack, uFlags, HDRVR_32(hDev), wMsg, dwUser, dwParam1, dwParam2);
145 }
146
147 /**************************************************************************
148  *      Mixer devices. New to Win95
149  */
150
151 /**************************************************************************
152  *                              mixerGetNumDevs                 [MMSYSTEM.800]
153  */
154 UINT16 WINAPI mixerGetNumDevs16(void)
155 {
156     return MMDRV_GetNum(MMDRV_MIXER);
157 }
158
159 /**************************************************************************
160  *                              mixerGetDevCaps                 [MMSYSTEM.801]
161  */
162 UINT16 WINAPI mixerGetDevCaps16(UINT16 devid, LPMIXERCAPS16 mixcaps,
163                                 UINT16 size)
164 {
165     MIXERCAPSA  micA;
166     UINT        ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
167
168     if (ret == MMSYSERR_NOERROR) {
169         mixcaps->wMid           = micA.wMid;
170         mixcaps->wPid           = micA.wPid;
171         mixcaps->vDriverVersion = micA.vDriverVersion;
172         strcpy(mixcaps->szPname, micA.szPname);
173         mixcaps->fdwSupport     = micA.fdwSupport;
174         mixcaps->cDestinations  = micA.cDestinations;
175     }
176     return ret;
177 }
178
179 /**************************************************************************
180  *                              mixerOpen                       [MMSYSTEM.802]
181  */
182 UINT16 WINAPI mixerOpen16(LPHMIXER16 lphmix, UINT16 uDeviceID, DWORD dwCallback,
183                           DWORD dwInstance, DWORD fdwOpen)
184 {
185     HMIXER      hmix;
186     UINT        ret;
187
188     ret = MMSYSTEM_mixerOpen(&hmix, uDeviceID,
189                              dwCallback, dwInstance, fdwOpen, FALSE);
190     if (lphmix) *lphmix = HMIXER_16(hmix);
191     return ret;
192 }
193
194 /**************************************************************************
195  *                              mixerClose                      [MMSYSTEM.803]
196  */
197 UINT16 WINAPI mixerClose16(HMIXER16 hMix)
198 {
199     return mixerClose(HMIXER_32(hMix));
200 }
201
202 /**************************************************************************
203  *                              mixerGetID (MMSYSTEM.806)
204  */
205 UINT16 WINAPI mixerGetID16(HMIXEROBJ16 hmix, LPUINT16 lpid, DWORD fdwID)
206 {
207     UINT        xid;
208     UINT        ret = mixerGetID(HMIXEROBJ_32(hmix), &xid, fdwID);
209
210     if (lpid)
211         *lpid = xid;
212     return ret;
213 }
214
215 /**************************************************************************
216  *                              mixerGetControlDetails  [MMSYSTEM.808]
217  */
218 UINT16 WINAPI mixerGetControlDetails16(HMIXEROBJ16 hmix,
219                                        LPMIXERCONTROLDETAILS16 lpmcd,
220                                        DWORD fdwDetails)
221 {
222     DWORD       ret = MMSYSERR_NOTENABLED;
223     SEGPTR      sppaDetails;
224
225     TRACE("(%04x, %p, %08lx)\n", hmix, lpmcd, fdwDetails);
226
227     if (lpmcd == NULL || lpmcd->cbStruct != sizeof(*lpmcd))
228         return MMSYSERR_INVALPARAM;
229
230     sppaDetails = (SEGPTR)lpmcd->paDetails;
231     lpmcd->paDetails = MapSL(sppaDetails);
232     ret = mixerGetControlDetailsA(HMIXEROBJ_32(hmix),
233                                  (LPMIXERCONTROLDETAILS)lpmcd, fdwDetails);
234     lpmcd->paDetails = (LPVOID)sppaDetails;
235
236     return ret;
237 }
238
239 /**************************************************************************
240  *                              mixerGetLineControls            [MMSYSTEM.807]
241  */
242 UINT16 WINAPI mixerGetLineControls16(HMIXEROBJ16 hmix,
243                                      LPMIXERLINECONTROLS16 lpmlc16,
244                                      DWORD fdwControls)
245 {
246     MIXERLINECONTROLSA  mlcA;
247     DWORD               ret;
248     int                 i;
249     LPMIXERCONTROL16    lpmc16;
250
251     TRACE("(%04x, %p, %08lx)\n", hmix, lpmlc16, fdwControls);
252
253     if (lpmlc16 == NULL || lpmlc16->cbStruct != sizeof(*lpmlc16) ||
254         lpmlc16->cbmxctrl != sizeof(MIXERCONTROL16))
255         return MMSYSERR_INVALPARAM;
256
257     mlcA.cbStruct = sizeof(mlcA);
258     mlcA.dwLineID = lpmlc16->dwLineID;
259     mlcA.u.dwControlID = lpmlc16->u.dwControlID;
260     mlcA.u.dwControlType = lpmlc16->u.dwControlType;
261     mlcA.cControls = lpmlc16->cControls;
262     mlcA.cbmxctrl = sizeof(MIXERCONTROLA);
263     mlcA.pamxctrl = HeapAlloc(GetProcessHeap(), 0,
264                               mlcA.cControls * mlcA.cbmxctrl);
265
266     ret = mixerGetLineControlsA(HMIXEROBJ_32(hmix), &mlcA, fdwControls);
267
268     if (ret == MMSYSERR_NOERROR) {
269         lpmlc16->dwLineID = mlcA.dwLineID;
270         lpmlc16->u.dwControlID = mlcA.u.dwControlID;
271         lpmlc16->u.dwControlType = mlcA.u.dwControlType;
272         lpmlc16->cControls = mlcA.cControls;
273
274         lpmc16 = MapSL(lpmlc16->pamxctrl);
275
276         for (i = 0; i < mlcA.cControls; i++) {
277             lpmc16[i].cbStruct = sizeof(MIXERCONTROL16);
278             lpmc16[i].dwControlID = mlcA.pamxctrl[i].dwControlID;
279             lpmc16[i].dwControlType = mlcA.pamxctrl[i].dwControlType;
280             lpmc16[i].fdwControl = mlcA.pamxctrl[i].fdwControl;
281             lpmc16[i].cMultipleItems = mlcA.pamxctrl[i].cMultipleItems;
282             strcpy(lpmc16[i].szShortName, mlcA.pamxctrl[i].szShortName);
283             strcpy(lpmc16[i].szName, mlcA.pamxctrl[i].szName);
284             /* sizeof(lpmc16[i].Bounds) == sizeof(mlcA.pamxctrl[i].Bounds) */
285             memcpy(&lpmc16[i].Bounds, &mlcA.pamxctrl[i].Bounds,
286                    sizeof(mlcA.pamxctrl[i].Bounds));
287             /* sizeof(lpmc16[i].Metrics) == sizeof(mlcA.pamxctrl[i].Metrics) */
288             memcpy(&lpmc16[i].Metrics, &mlcA.pamxctrl[i].Metrics,
289                    sizeof(mlcA.pamxctrl[i].Metrics));
290         }
291     }
292
293     HeapFree(GetProcessHeap(), 0, mlcA.pamxctrl);
294
295     return ret;
296 }
297
298 /**************************************************************************
299  *                              mixerGetLineInfo        [MMSYSTEM.805]
300  */
301 UINT16 WINAPI mixerGetLineInfo16(HMIXEROBJ16 hmix, LPMIXERLINE16 lpmli16,
302                                  DWORD fdwInfo)
303 {
304     MIXERLINEA          mliA;
305     UINT                ret;
306
307     TRACE("(%04x, %p, %08lx)\n", hmix, lpmli16, fdwInfo);
308
309     if (lpmli16 == NULL || lpmli16->cbStruct != sizeof(*lpmli16))
310         return MMSYSERR_INVALPARAM;
311
312     mliA.cbStruct = sizeof(mliA);
313     switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) {
314     case MIXER_GETLINEINFOF_COMPONENTTYPE:
315         mliA.dwComponentType = lpmli16->dwComponentType;
316         break;
317     case MIXER_GETLINEINFOF_DESTINATION:
318         mliA.dwDestination = lpmli16->dwDestination;
319         break;
320     case MIXER_GETLINEINFOF_LINEID:
321         mliA.dwLineID = lpmli16->dwLineID;
322         break;
323     case MIXER_GETLINEINFOF_SOURCE:
324         mliA.dwDestination = lpmli16->dwDestination;
325         mliA.dwSource = lpmli16->dwSource;
326         break;
327     case MIXER_GETLINEINFOF_TARGETTYPE:
328         mliA.Target.dwType = lpmli16->Target.dwType;
329         mliA.Target.wMid = lpmli16->Target.wMid;
330         mliA.Target.wPid = lpmli16->Target.wPid;
331         mliA.Target.vDriverVersion = lpmli16->Target.vDriverVersion;
332         strcpy(mliA.Target.szPname, lpmli16->Target.szPname);
333         break;
334     default:
335         FIXME("Unsupported fdwControls=0x%08lx\n", fdwInfo);
336     }
337
338     ret = mixerGetLineInfoA(HMIXEROBJ_32(hmix), &mliA, fdwInfo);
339
340     lpmli16->dwDestination      = mliA.dwDestination;
341     lpmli16->dwSource           = mliA.dwSource;
342     lpmli16->dwLineID           = mliA.dwLineID;
343     lpmli16->fdwLine            = mliA.fdwLine;
344     lpmli16->dwUser             = mliA.dwUser;
345     lpmli16->dwComponentType    = mliA.dwComponentType;
346     lpmli16->cChannels          = mliA.cChannels;
347     lpmli16->cConnections       = mliA.cConnections;
348     lpmli16->cControls          = mliA.cControls;
349     strcpy(lpmli16->szShortName, mliA.szShortName);
350     strcpy(lpmli16->szName, mliA.szName);
351     lpmli16->Target.dwType      = mliA.Target.dwType;
352     lpmli16->Target.dwDeviceID  = mliA.Target.dwDeviceID;
353     lpmli16->Target.wMid        = mliA.Target.wMid;
354     lpmli16->Target.wPid        = mliA.Target.wPid;
355     lpmli16->Target.vDriverVersion = mliA.Target.vDriverVersion;
356     strcpy(lpmli16->Target.szPname, mliA.Target.szPname);
357
358     return ret;
359 }
360
361 /**************************************************************************
362  *                              mixerSetControlDetails  [MMSYSTEM.809]
363  */
364 UINT16 WINAPI mixerSetControlDetails16(HMIXEROBJ16 hmix,
365                                        LPMIXERCONTROLDETAILS16 lpmcd,
366                                        DWORD fdwDetails)
367 {
368     TRACE("(%04x, %p, %08lx)\n", hmix, lpmcd, fdwDetails);
369     return MMSYSERR_NOTENABLED;
370 }
371
372 /**************************************************************************
373  *                              mixerMessage            [MMSYSTEM.804]
374  */
375 DWORD WINAPI mixerMessage16(HMIXER16 hmix, UINT16 uMsg, DWORD dwParam1,
376                              DWORD dwParam2)
377 {
378     return mixerMessage(HMIXER_32(hmix), uMsg, dwParam1, dwParam2);
379 }
380
381 /**************************************************************************
382  *                              auxGetNumDevs           [MMSYSTEM.350]
383  */
384 UINT16 WINAPI auxGetNumDevs16(void)
385 {
386     return MMDRV_GetNum(MMDRV_AUX);
387 }
388
389 /**************************************************************************
390  *                              auxGetDevCaps           [MMSYSTEM.351]
391  */
392 UINT16 WINAPI auxGetDevCaps16(UINT16 uDeviceID, LPAUXCAPS16 lpCaps, UINT16 uSize)
393 {
394     LPWINE_MLD          wmld;
395
396     TRACE("(%04X, %p, %d) !\n", uDeviceID, lpCaps, uSize);
397
398     if ((wmld = MMDRV_Get(uDeviceID, MMDRV_AUX, TRUE)) == NULL)
399         return MMSYSERR_INVALHANDLE;
400     return MMDRV_Message(wmld, AUXDM_GETDEVCAPS, (DWORD)lpCaps, uSize, TRUE);
401 }
402
403 /**************************************************************************
404  *                              auxGetVolume            [MMSYSTEM.352]
405  */
406 UINT16 WINAPI auxGetVolume16(UINT16 uDeviceID, LPDWORD lpdwVolume)
407 {
408     LPWINE_MLD          wmld;
409
410     TRACE("(%04X, %p) !\n", uDeviceID, lpdwVolume);
411
412     if ((wmld = MMDRV_Get(uDeviceID, MMDRV_AUX, TRUE)) == NULL)
413         return MMSYSERR_INVALHANDLE;
414     return MMDRV_Message(wmld, AUXDM_GETVOLUME, (DWORD)lpdwVolume, 0L, TRUE);
415 }
416
417 /**************************************************************************
418  *                              auxSetVolume            [MMSYSTEM.353]
419  */
420 UINT16 WINAPI auxSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
421 {
422     LPWINE_MLD          wmld;
423
424     TRACE("(%04X, %lu) !\n", uDeviceID, dwVolume);
425
426     if ((wmld = MMDRV_Get(uDeviceID, MMDRV_AUX, TRUE)) == NULL)
427         return MMSYSERR_INVALHANDLE;
428     return MMDRV_Message(wmld, AUXDM_SETVOLUME, dwVolume, 0L, TRUE);
429 }
430
431 /**************************************************************************
432  *                              auxOutMessage           [MMSYSTEM.354]
433  */
434 DWORD WINAPI auxOutMessage16(UINT16 uDeviceID, UINT16 uMessage, DWORD dw1, DWORD dw2)
435 {
436     LPWINE_MLD          wmld;
437
438     TRACE("(%04X, %04X, %08lX, %08lX)\n", uDeviceID, uMessage, dw1, dw2);
439
440     switch (uMessage) {
441     case AUXDM_GETNUMDEVS:
442     case AUXDM_SETVOLUME:
443         /* no argument conversion needed */
444         break;
445     case AUXDM_GETVOLUME:
446         return auxGetVolume16(uDeviceID, MapSL(dw1));
447     case AUXDM_GETDEVCAPS:
448         return auxGetDevCaps16(uDeviceID, MapSL(dw1), dw2);
449     default:
450         TRACE("(%04x, %04x, %08lx, %08lx): unhandled message\n",
451               uDeviceID, uMessage, dw1, dw2);
452         break;
453     }
454     if ((wmld = MMDRV_Get(uDeviceID, MMDRV_AUX, TRUE)) == NULL)
455         return MMSYSERR_INVALHANDLE;
456
457     return MMDRV_Message(wmld, uMessage, dw1, dw2, TRUE);
458 }
459
460 /**************************************************************************
461  *                              mciGetErrorString               [MMSYSTEM.706]
462  */
463 BOOL16 WINAPI mciGetErrorString16(DWORD wError, LPSTR lpstrBuffer, UINT16 uLength)
464 {
465     return mciGetErrorStringA(wError, lpstrBuffer, uLength);
466 }
467
468 /**************************************************************************
469  *                              mciDriverNotify                 [MMSYSTEM.711]
470  */
471 BOOL16 WINAPI mciDriverNotify16(HWND16 hWndCallBack, UINT16 wDevID, UINT16 wStatus)
472 {
473     TRACE("(%04X, %04x, %04X)\n", hWndCallBack, wDevID, wStatus);
474
475     return PostMessageA(HWND_32(hWndCallBack), MM_MCINOTIFY, wStatus, wDevID);
476 }
477
478 /**************************************************************************
479  *                      mciGetDriverData                        [MMSYSTEM.708]
480  */
481 DWORD WINAPI mciGetDriverData16(UINT16 uDeviceID)
482 {
483     return mciGetDriverData(uDeviceID);
484 }
485
486 /**************************************************************************
487  *                      mciSetDriverData                        [MMSYSTEM.707]
488  */
489 BOOL16 WINAPI mciSetDriverData16(UINT16 uDeviceID, DWORD data)
490 {
491     return mciSetDriverData(uDeviceID, data);
492 }
493
494 /**************************************************************************
495  *                              mciSendCommand                  [MMSYSTEM.701]
496  */
497 DWORD WINAPI mciSendCommand16(UINT16 wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
498 {
499     DWORD               dwRet;
500
501     TRACE("(%04X, %s, %08lX, %08lX)\n",
502           wDevID, MCI_MessageToString(wMsg), dwParam1, dwParam2);
503
504     dwRet = MCI_SendCommand(wDevID, wMsg, dwParam1, dwParam2, FALSE);
505     dwRet = MCI_CleanUp(dwRet, wMsg, dwParam2, FALSE);
506     TRACE("=> %ld\n", dwRet);
507     return dwRet;
508 }
509
510 /**************************************************************************
511  *                              mciGetDeviceID                  [MMSYSTEM.703]
512  */
513 UINT16 WINAPI mciGetDeviceID16(LPCSTR lpstrName)
514 {
515     TRACE("(\"%s\")\n", lpstrName);
516
517     return MCI_GetDriverFromString(lpstrName);
518 }
519
520 /**************************************************************************
521  *                              mciSetYieldProc                 [MMSYSTEM.714]
522  */
523 BOOL16 WINAPI mciSetYieldProc16(UINT16 uDeviceID, YIELDPROC16 fpYieldProc, DWORD dwYieldData)
524 {
525     LPWINE_MCIDRIVER    wmd;
526
527     TRACE("(%u, %p, %08lx)\n", uDeviceID, fpYieldProc, dwYieldData);
528
529     if (!(wmd = MCI_GetDriver(uDeviceID))) {
530         WARN("Bad uDeviceID\n");
531         return FALSE;
532     }
533
534     wmd->lpfnYieldProc = (YIELDPROC)fpYieldProc;
535     wmd->dwYieldData   = dwYieldData;
536     wmd->bIs32         = FALSE;
537
538     return TRUE;
539 }
540
541 /**************************************************************************
542  *                              mciGetDeviceIDFromElementID     [MMSYSTEM.715]
543  */
544 UINT16 WINAPI mciGetDeviceIDFromElementID16(DWORD dwElementID, LPCSTR lpstrType)
545 {
546     FIXME("(%lu, %s) stub\n", dwElementID, lpstrType);
547     return 0;
548 }
549
550 /**************************************************************************
551  *                              mciGetYieldProc                 [MMSYSTEM.716]
552  */
553 YIELDPROC16 WINAPI mciGetYieldProc16(UINT16 uDeviceID, DWORD* lpdwYieldData)
554 {
555     LPWINE_MCIDRIVER    wmd;
556
557     TRACE("(%u, %p)\n", uDeviceID, lpdwYieldData);
558
559     if (!(wmd = MCI_GetDriver(uDeviceID))) {
560         WARN("Bad uDeviceID\n");
561         return NULL;
562     }
563     if (!wmd->lpfnYieldProc) {
564         WARN("No proc set\n");
565         return NULL;
566     }
567     if (wmd->bIs32) {
568         WARN("Proc is 32 bit\n");
569         return NULL;
570     }
571     return (YIELDPROC16)wmd->lpfnYieldProc;
572 }
573
574 /**************************************************************************
575  *                              mciGetCreatorTask               [MMSYSTEM.717]
576  */
577 HTASK16 WINAPI mciGetCreatorTask16(UINT16 uDeviceID)
578 {
579     LPWINE_MCIDRIVER wmd;
580     HTASK16 ret = 0;
581
582     if ((wmd = MCI_GetDriver(uDeviceID))) ret = wmd->hCreatorTask;
583
584     TRACE("(%u) => %04x\n", uDeviceID, ret);
585     return ret;
586 }
587
588 /**************************************************************************
589  *                              mciDriverYield                  [MMSYSTEM.710]
590  */
591 UINT16 WINAPI mciDriverYield16(UINT16 uDeviceID)
592 {
593     LPWINE_MCIDRIVER    wmd;
594     UINT16              ret = 0;
595
596     /*    TRACE("(%04x)\n", uDeviceID); */
597
598     if (!(wmd = MCI_GetDriver(uDeviceID)) || !wmd->lpfnYieldProc || wmd->bIs32) {
599         UserYield16();
600     } else {
601         ret = wmd->lpfnYieldProc(uDeviceID, wmd->dwYieldData);
602     }
603
604     return ret;
605 }
606
607 /**************************************************************************
608  *                              midiOutGetNumDevs       [MMSYSTEM.201]
609  */
610 UINT16 WINAPI midiOutGetNumDevs16(void)
611 {
612     return MMDRV_GetNum(MMDRV_MIDIOUT);
613 }
614
615 /**************************************************************************
616  *                              midiOutGetDevCaps       [MMSYSTEM.202]
617  */
618 UINT16 WINAPI midiOutGetDevCaps16(UINT16 uDeviceID, LPMIDIOUTCAPS16 lpCaps,
619                                   UINT16 uSize)
620 {
621     MIDIOUTCAPSA        capsA;
622     UINT                dwRet;
623
624     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
625
626     dwRet = midiOutGetDevCapsA(uDeviceID, &capsA, sizeof(capsA));
627     if (dwRet == MMSYSERR_NOERROR) {
628         lpCaps->wMid            = capsA.wMid;
629         lpCaps->wPid            = capsA.wPid;
630         lpCaps->vDriverVersion  = capsA.vDriverVersion;
631         strcpy(lpCaps->szPname, capsA.szPname);
632         lpCaps->wTechnology     = capsA.wTechnology;
633         lpCaps->wVoices         = capsA.wVoices;
634         lpCaps->wNotes          = capsA.wNotes;
635         lpCaps->wChannelMask    = capsA.wChannelMask;
636         lpCaps->dwSupport       = capsA.dwSupport;
637     }
638     return dwRet;
639  }
640
641 /**************************************************************************
642  *                              midiOutGetErrorText     [MMSYSTEM.203]
643  */
644 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
645 {
646     return midiOutGetErrorTextA(uError, lpText, uSize);
647 }
648
649 /**************************************************************************
650  *                              midiOutOpen             [MMSYSTEM.204]
651  */
652 UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
653                             DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
654 {
655     HMIDIOUT    hmo;
656     UINT        ret;
657
658     ret = MMSYSTEM_midiOutOpen(&hmo, uDeviceID, dwCallback, dwInstance,
659                                dwFlags, FALSE);
660
661     if (lphMidiOut != NULL) *lphMidiOut = HMIDIOUT_16(hmo);
662     return ret;
663 }
664
665 /**************************************************************************
666  *                              midiOutClose            [MMSYSTEM.205]
667  */
668 UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
669 {
670     return midiOutClose(HMIDIOUT_32(hMidiOut));
671 }
672
673 /**************************************************************************
674  *                              midiOutPrepareHeader    [MMSYSTEM.206]
675  */
676 UINT16 WINAPI midiOutPrepareHeader16(HMIDIOUT16 hMidiOut,         /* [in] */
677                                      SEGPTR lpsegMidiOutHdr,      /* [???] */
678                                      UINT16 uSize)                /* [in] */
679 {
680     LPWINE_MLD          wmld;
681
682     TRACE("(%04X, %08lx, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
683
684     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
685         return MMSYSERR_INVALHANDLE;
686
687     return MMDRV_Message(wmld, MODM_PREPARE, lpsegMidiOutHdr, uSize, FALSE);
688 }
689
690 /**************************************************************************
691  *                              midiOutUnprepareHeader  [MMSYSTEM.207]
692  */
693 UINT16 WINAPI midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut,         /* [in] */
694                                        SEGPTR lpsegMidiOutHdr,      /* [???] */
695                                        UINT16 uSize)                /* [in] */
696 {
697     LPWINE_MLD          wmld;
698     LPMIDIHDR16         lpMidiOutHdr = MapSL(lpsegMidiOutHdr);
699
700     TRACE("(%04X, %08lx, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
701
702     if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) {
703         return MMSYSERR_NOERROR;
704     }
705
706     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
707         return MMSYSERR_INVALHANDLE;
708
709     return MMDRV_Message(wmld, MODM_UNPREPARE, (DWORD)lpsegMidiOutHdr, uSize, FALSE);
710 }
711
712 /**************************************************************************
713  *                              midiOutShortMsg         [MMSYSTEM.208]
714  */
715 UINT16 WINAPI midiOutShortMsg16(HMIDIOUT16 hMidiOut, DWORD dwMsg)
716 {
717     return midiOutShortMsg(HMIDIOUT_32(hMidiOut), dwMsg);
718 }
719
720 /**************************************************************************
721  *                              midiOutLongMsg          [MMSYSTEM.209]
722  */
723 UINT16 WINAPI midiOutLongMsg16(HMIDIOUT16 hMidiOut,          /* [in] */
724                                LPMIDIHDR16 lpsegMidiOutHdr,  /* [???] NOTE: SEGPTR */
725                                UINT16 uSize)                 /* [in] */
726 {
727     LPWINE_MLD          wmld;
728
729     TRACE("(%04X, %p, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
730
731     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
732         return MMSYSERR_INVALHANDLE;
733
734     return MMDRV_Message(wmld, MODM_LONGDATA, (DWORD)lpsegMidiOutHdr, uSize, FALSE);
735 }
736
737 /**************************************************************************
738  *                              midiOutReset            [MMSYSTEM.210]
739  */
740 UINT16 WINAPI midiOutReset16(HMIDIOUT16 hMidiOut)
741 {
742     return midiOutReset(HMIDIOUT_32(hMidiOut));
743 }
744
745 /**************************************************************************
746  *                              midiOutGetVolume        [MMSYSTEM.211]
747  */
748 UINT16 WINAPI midiOutGetVolume16(UINT16 uDeviceID, DWORD* lpdwVolume)
749 {
750     return midiOutGetVolume(uDeviceID, lpdwVolume);
751 }
752
753 /**************************************************************************
754  *                              midiOutSetVolume        [MMSYSTEM.212]
755  */
756 UINT16 WINAPI midiOutSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
757 {
758     return midiOutSetVolume(uDeviceID, dwVolume);
759 }
760
761 /**************************************************************************
762  *                              midiOutCachePatches             [MMSYSTEM.213]
763  */
764 UINT16 WINAPI midiOutCachePatches16(HMIDIOUT16 hMidiOut, UINT16 uBank,
765                                     WORD* lpwPatchArray, UINT16 uFlags)
766 {
767     return midiOutCachePatches(HMIDIOUT_32(hMidiOut), uBank, lpwPatchArray,
768                                uFlags);
769 }
770
771 /**************************************************************************
772  *                              midiOutCacheDrumPatches [MMSYSTEM.214]
773  */
774 UINT16 WINAPI midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut, UINT16 uPatch,
775                                         WORD* lpwKeyArray, UINT16 uFlags)
776 {
777     return midiOutCacheDrumPatches(HMIDIOUT_32(hMidiOut), uPatch, lpwKeyArray, uFlags);
778 }
779
780 /**************************************************************************
781  *                              midiOutGetID            [MMSYSTEM.215]
782  */
783 UINT16 WINAPI midiOutGetID16(HMIDIOUT16 hMidiOut, UINT16* lpuDeviceID)
784 {
785     LPWINE_MLD          wmld;
786
787     TRACE("(%04X, %p)\n", hMidiOut, lpuDeviceID);
788
789     if (lpuDeviceID == NULL) return MMSYSERR_INVALPARAM;
790     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
791         return MMSYSERR_INVALHANDLE;
792
793     *lpuDeviceID = wmld->uDeviceID;
794     return MMSYSERR_NOERROR;
795 }
796
797 /**************************************************************************
798  *                              midiOutMessage          [MMSYSTEM.216]
799  */
800 DWORD WINAPI midiOutMessage16(HMIDIOUT16 hMidiOut, UINT16 uMessage,
801                               DWORD dwParam1, DWORD dwParam2)
802 {
803     LPWINE_MLD          wmld;
804
805     TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiOut, uMessage, dwParam1, dwParam2);
806
807     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
808         return MMSYSERR_INVALHANDLE;
809
810     switch (uMessage) {
811     case MODM_OPEN:
812     case MODM_CLOSE:
813         FIXME("can't handle OPEN or CLOSE message!\n");
814         return MMSYSERR_NOTSUPPORTED;
815
816     case MODM_GETVOLUME:
817         return midiOutGetVolume16(hMidiOut, MapSL(dwParam1));
818     case MODM_LONGDATA:
819         return midiOutLongMsg16(hMidiOut, MapSL(dwParam1), dwParam2);
820     case MODM_PREPARE:
821         /* lpMidiOutHdr is still a segmented pointer for this function */
822         return midiOutPrepareHeader16(hMidiOut, dwParam1, dwParam2);
823     case MODM_UNPREPARE:
824         return midiOutUnprepareHeader16(hMidiOut, dwParam1, dwParam2);
825     }
826     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, TRUE);
827 }
828
829 /**************************************************************************
830  *                              midiInGetNumDevs        [MMSYSTEM.301]
831  */
832 UINT16 WINAPI midiInGetNumDevs16(void)
833 {
834     return MMDRV_GetNum(MMDRV_MIDIIN);
835 }
836
837 /**************************************************************************
838  *                              midiInGetDevCaps        [MMSYSTEM.302]
839  */
840 UINT16 WINAPI midiInGetDevCaps16(UINT16 uDeviceID, LPMIDIINCAPS16 lpCaps,
841                                  UINT16 uSize)
842 {
843     MIDIINCAPSA         micA;
844     UINT                ret = midiInGetDevCapsA(uDeviceID, &micA, uSize);
845
846     if (ret == MMSYSERR_NOERROR) {
847         lpCaps->wMid = micA.wMid;
848         lpCaps->wPid = micA.wPid;
849         lpCaps->vDriverVersion = micA.vDriverVersion;
850         strcpy(lpCaps->szPname, micA.szPname);
851         lpCaps->dwSupport = micA.dwSupport;
852     }
853
854     return ret;
855 }
856
857 /**************************************************************************
858  *                              midiInGetErrorText              [MMSYSTEM.303]
859  */
860 UINT16 WINAPI midiInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
861 {
862     return midiInGetErrorTextA(uError, lpText, uSize);
863 }
864
865 /**************************************************************************
866  *                              midiInOpen              [MMSYSTEM.304]
867  */
868 UINT16 WINAPI midiInOpen16(HMIDIIN16* lphMidiIn, UINT16 uDeviceID,
869                            DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
870 {
871     HMIDIIN     xhmid;
872     UINT        ret;
873
874     ret = MMSYSTEM_midiInOpen(&xhmid, uDeviceID, dwCallback, dwInstance,
875                               dwFlags, FALSE);
876
877     if (lphMidiIn) *lphMidiIn = HMIDIIN_16(xhmid);
878     return ret;
879 }
880
881 /**************************************************************************
882  *                              midiInClose             [MMSYSTEM.305]
883  */
884 UINT16 WINAPI midiInClose16(HMIDIIN16 hMidiIn)
885 {
886     return midiInClose(HMIDIIN_32(hMidiIn));
887 }
888
889 /**************************************************************************
890  *                              midiInPrepareHeader     [MMSYSTEM.306]
891  */
892 UINT16 WINAPI midiInPrepareHeader16(HMIDIIN16 hMidiIn,         /* [in] */
893                                     SEGPTR lpsegMidiInHdr,     /* [???] */
894                                     UINT16 uSize)              /* [in] */
895 {
896     LPWINE_MLD          wmld;
897
898     TRACE("(%04X, %08lx, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
899
900     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
901         return MMSYSERR_INVALHANDLE;
902
903     return MMDRV_Message(wmld, MIDM_PREPARE, (DWORD)lpsegMidiInHdr, uSize, FALSE);
904 }
905
906 /**************************************************************************
907  *                              midiInUnprepareHeader   [MMSYSTEM.307]
908  */
909 UINT16 WINAPI midiInUnprepareHeader16(HMIDIIN16 hMidiIn,         /* [in] */
910                                       SEGPTR lpsegMidiInHdr,     /* [???] */
911                                       UINT16 uSize)              /* [in] */
912 {
913     LPWINE_MLD          wmld;
914     LPMIDIHDR16         lpMidiInHdr = MapSL(lpsegMidiInHdr);
915
916     TRACE("(%04X, %08lx, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
917
918     if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) {
919         return MMSYSERR_NOERROR;
920     }
921
922     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
923         return MMSYSERR_INVALHANDLE;
924
925     return MMDRV_Message(wmld, MIDM_UNPREPARE, (DWORD)lpsegMidiInHdr, uSize, FALSE);
926 }
927
928 /**************************************************************************
929  *                              midiInAddBuffer         [MMSYSTEM.308]
930  */
931 UINT16 WINAPI midiInAddBuffer16(HMIDIIN16 hMidiIn,         /* [in] */
932                                 MIDIHDR16* lpsegMidiInHdr, /* [???] NOTE: SEGPTR */
933                                 UINT16 uSize)              /* [in] */
934 {
935     LPWINE_MLD          wmld;
936
937     TRACE("(%04X, %p, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
938
939     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
940         return MMSYSERR_INVALHANDLE;
941
942     return MMDRV_Message(wmld, MIDM_ADDBUFFER, (DWORD)lpsegMidiInHdr, uSize, FALSE);
943 }
944
945 /**************************************************************************
946  *                              midiInStart                     [MMSYSTEM.309]
947  */
948 UINT16 WINAPI midiInStart16(HMIDIIN16 hMidiIn)
949 {
950     return midiInStart(HMIDIIN_32(hMidiIn));
951 }
952
953 /**************************************************************************
954  *                              midiInStop                      [MMSYSTEM.310]
955  */
956 UINT16 WINAPI midiInStop16(HMIDIIN16 hMidiIn)
957 {
958     return midiInStop(HMIDIIN_32(hMidiIn));
959 }
960
961 /**************************************************************************
962  *                              midiInReset                     [MMSYSTEM.311]
963  */
964 UINT16 WINAPI midiInReset16(HMIDIIN16 hMidiIn)
965 {
966     return midiInReset(HMIDIIN_32(hMidiIn));
967 }
968
969 /**************************************************************************
970  *                              midiInGetID                     [MMSYSTEM.312]
971  */
972 UINT16 WINAPI midiInGetID16(HMIDIIN16 hMidiIn, UINT16* lpuDeviceID)
973 {
974     LPWINE_MLD          wmld;
975
976     TRACE("(%04X, %p)\n", hMidiIn, lpuDeviceID);
977
978     if (lpuDeviceID == NULL) return MMSYSERR_INVALPARAM;
979
980     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, TRUE)) == NULL)
981         return MMSYSERR_INVALHANDLE;
982
983     *lpuDeviceID = wmld->uDeviceID;
984
985     return MMSYSERR_NOERROR;
986 }
987
988 /**************************************************************************
989  *                              midiInMessage           [MMSYSTEM.313]
990  */
991 DWORD WINAPI midiInMessage16(HMIDIIN16 hMidiIn, UINT16 uMessage,
992                              DWORD dwParam1, DWORD dwParam2)
993 {
994     LPWINE_MLD          wmld;
995
996     TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiIn, uMessage, dwParam1, dwParam2);
997
998     switch (uMessage) {
999     case MIDM_OPEN:
1000     case MIDM_CLOSE:
1001         FIXME("can't handle OPEN or CLOSE message!\n");
1002         return MMSYSERR_NOTSUPPORTED;
1003
1004     case MIDM_GETDEVCAPS:
1005         return midiInGetDevCaps16(hMidiIn, MapSL(dwParam1), dwParam2);
1006     case MIDM_PREPARE:
1007         return midiInPrepareHeader16(hMidiIn, dwParam1, dwParam2);
1008     case MIDM_UNPREPARE:
1009         return midiInUnprepareHeader16(hMidiIn, dwParam1, dwParam2);
1010     case MIDM_ADDBUFFER:
1011         return midiInAddBuffer16(hMidiIn, MapSL(dwParam1), dwParam2);
1012     }
1013
1014     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
1015         return MMSYSERR_INVALHANDLE;
1016
1017     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1018 }
1019
1020 /**************************************************************************
1021  *                              midiStreamClose                 [MMSYSTEM.252]
1022  */
1023 MMRESULT16 WINAPI midiStreamClose16(HMIDISTRM16 hMidiStrm)
1024 {
1025     return midiStreamClose(HMIDISTRM_32(hMidiStrm));
1026 }
1027
1028 /**************************************************************************
1029  *                              midiStreamOpen                  [MMSYSTEM.251]
1030  */
1031 MMRESULT16 WINAPI midiStreamOpen16(HMIDISTRM16* phMidiStrm, LPUINT16 devid,
1032                                    DWORD cMidi, DWORD dwCallback,
1033                                    DWORD dwInstance, DWORD fdwOpen)
1034 {
1035     HMIDISTRM   hMidiStrm32;
1036     MMRESULT    ret;
1037     UINT        devid32;
1038
1039     if (!phMidiStrm || !devid)
1040         return MMSYSERR_INVALPARAM;
1041     devid32 = *devid;
1042     ret = MMSYSTEM_MidiStream_Open(&hMidiStrm32, &devid32, cMidi, dwCallback,
1043                                    dwInstance, fdwOpen, FALSE);
1044     *phMidiStrm = HMIDISTRM_16(hMidiStrm32);
1045     *devid = devid32;
1046     return ret;
1047 }
1048
1049 /**************************************************************************
1050  *                              midiStreamOut                   [MMSYSTEM.254]
1051  */
1052 MMRESULT16 WINAPI midiStreamOut16(HMIDISTRM16 hMidiStrm, LPMIDIHDR16 lpMidiHdr, UINT16 cbMidiHdr)
1053 {
1054     return midiStreamOut(HMIDISTRM_32(hMidiStrm), (LPMIDIHDR)lpMidiHdr,
1055                          cbMidiHdr);
1056 }
1057
1058 /**************************************************************************
1059  *                              midiStreamPause                 [MMSYSTEM.255]
1060  */
1061 MMRESULT16 WINAPI midiStreamPause16(HMIDISTRM16 hMidiStrm)
1062 {
1063     return midiStreamPause(HMIDISTRM_32(hMidiStrm));
1064 }
1065
1066 /**************************************************************************
1067  *                              midiStreamPosition              [MMSYSTEM.253]
1068  */
1069 MMRESULT16 WINAPI midiStreamPosition16(HMIDISTRM16 hMidiStrm, LPMMTIME16 lpmmt16, UINT16 cbmmt)
1070 {
1071     MMTIME      mmt32;
1072     MMRESULT    ret;
1073
1074     if (!lpmmt16)
1075         return MMSYSERR_INVALPARAM;
1076     MMSYSTEM_MMTIME16to32(&mmt32, lpmmt16);
1077     ret = midiStreamPosition(HMIDISTRM_32(hMidiStrm), &mmt32, sizeof(MMTIME));
1078     MMSYSTEM_MMTIME32to16(lpmmt16, &mmt32);
1079     return ret;
1080 }
1081
1082 /**************************************************************************
1083  *                              midiStreamProperty              [MMSYSTEM.250]
1084  */
1085 MMRESULT16 WINAPI midiStreamProperty16(HMIDISTRM16 hMidiStrm, LPBYTE lpPropData, DWORD dwProperty)
1086 {
1087     return midiStreamProperty(HMIDISTRM_32(hMidiStrm), lpPropData, dwProperty);
1088 }
1089
1090 /**************************************************************************
1091  *                              midiStreamRestart               [MMSYSTEM.256]
1092  */
1093 MMRESULT16 WINAPI midiStreamRestart16(HMIDISTRM16 hMidiStrm)
1094 {
1095     return midiStreamRestart(HMIDISTRM_32(hMidiStrm));
1096 }
1097
1098 /**************************************************************************
1099  *                              midiStreamStop                  [MMSYSTEM.257]
1100  */
1101 MMRESULT16 WINAPI midiStreamStop16(HMIDISTRM16 hMidiStrm)
1102 {
1103     return midiStreamStop(HMIDISTRM_32(hMidiStrm));
1104 }
1105
1106 /**************************************************************************
1107  *                              waveOutGetNumDevs               [MMSYSTEM.401]
1108  */
1109 UINT16 WINAPI waveOutGetNumDevs16(void)
1110 {
1111     return MMDRV_GetNum(MMDRV_WAVEOUT);
1112 }
1113
1114 /**************************************************************************
1115  *                              waveOutGetDevCaps               [MMSYSTEM.402]
1116  */
1117 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID,
1118                                   LPWAVEOUTCAPS16 lpCaps, UINT16 uSize)
1119 {
1120     WAVEOUTCAPSA        wocA;
1121     UINT                ret;
1122
1123     TRACE("(%u %p %u)!\n", uDeviceID, lpCaps, uSize);
1124     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1125
1126     ret = waveOutGetDevCapsA(uDeviceID, &wocA, sizeof(wocA));
1127
1128     if (ret == MMSYSERR_NOERROR) {
1129         lpCaps->wMid = wocA.wMid;
1130         lpCaps->wPid = wocA.wPid;
1131         lpCaps->vDriverVersion = wocA.vDriverVersion;
1132         strcpy(lpCaps->szPname, wocA.szPname);
1133         lpCaps->dwFormats = wocA.dwFormats;
1134         lpCaps->wChannels = wocA.wChannels;
1135         lpCaps->dwSupport = wocA.dwSupport;
1136     }
1137     return ret;
1138 }
1139
1140 /**************************************************************************
1141  *                              waveOutGetErrorText     [MMSYSTEM.403]
1142  */
1143 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1144 {
1145     return waveOutGetErrorTextA(uError, lpText, uSize);
1146 }
1147
1148 /**************************************************************************
1149  *                      waveOutOpen                     [MMSYSTEM.404]
1150  */
1151 UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
1152                             const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
1153                             DWORD dwInstance, DWORD dwFlags)
1154 {
1155     HWAVEOUT            hWaveOut;
1156     UINT                ret;
1157
1158     /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1159      * call the 32 bit version
1160      * however, we need to promote correctly the wave mapper id
1161      * (0xFFFFFFFF and not 0x0000FFFF)
1162      */
1163     ret = MMSYSTEM_waveOpen(&hWaveOut, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1164                             MMDRV_WAVEOUT, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1165
1166     if (lphWaveOut != NULL) *lphWaveOut = HWAVEOUT_16(hWaveOut);
1167     return ret;
1168 }
1169
1170 /**************************************************************************
1171  *                              waveOutClose            [MMSYSTEM.405]
1172  */
1173 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
1174 {
1175     DWORD       level;
1176     UINT16      ret;
1177
1178     ReleaseThunkLock(&level);
1179     ret = waveOutClose(HWAVEOUT_32(hWaveOut));
1180     RestoreThunkLock(level);
1181     return ret;
1182 }
1183
1184 /**************************************************************************
1185  *                              waveOutPrepareHeader    [MMSYSTEM.406]
1186  */
1187 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut,      /* [in] */
1188                                      SEGPTR lpsegWaveOutHdr,   /* [???] */
1189                                      UINT16 uSize)             /* [in] */
1190 {
1191     LPWINE_MLD          wmld;
1192     LPWAVEHDR           lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1193
1194     TRACE("(%04X, %08lx, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1195
1196     if (lpWaveOutHdr == NULL) return MMSYSERR_INVALPARAM;
1197
1198     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1199         return MMSYSERR_INVALHANDLE;
1200
1201     return MMDRV_Message(wmld, WODM_PREPARE, (DWORD)lpsegWaveOutHdr, uSize, FALSE);
1202 }
1203
1204 /**************************************************************************
1205  *                              waveOutUnprepareHeader  [MMSYSTEM.407]
1206  */
1207 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut,       /* [in] */
1208                                        SEGPTR lpsegWaveOutHdr,    /* [???] */
1209                                        UINT16 uSize)              /* [in] */
1210 {
1211     LPWINE_MLD          wmld;
1212     LPWAVEHDR           lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1213
1214     TRACE("(%04X, %08lx, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1215
1216     if (!(lpWaveOutHdr->dwFlags & WHDR_PREPARED)) {
1217         return MMSYSERR_NOERROR;
1218     }
1219
1220     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1221         return MMSYSERR_INVALHANDLE;
1222
1223     return MMDRV_Message(wmld, WODM_UNPREPARE, (DWORD)lpsegWaveOutHdr, uSize, FALSE);
1224 }
1225
1226 /**************************************************************************
1227  *                              waveOutWrite            [MMSYSTEM.408]
1228  */
1229 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut,       /* [in] */
1230                              LPWAVEHDR lpsegWaveOutHdr, /* [???] NOTE: SEGPTR */
1231                              UINT16 uSize)              /* [in] */
1232 {
1233     LPWINE_MLD          wmld;
1234
1235     TRACE("(%04X, %p, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1236
1237     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1238         return MMSYSERR_INVALHANDLE;
1239
1240     return MMDRV_Message(wmld, WODM_WRITE, (DWORD)lpsegWaveOutHdr, uSize, FALSE);
1241 }
1242
1243 /**************************************************************************
1244  *                              waveOutBreakLoop        [MMSYSTEM.419]
1245  */
1246 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut16)
1247 {
1248     DWORD       level;
1249     UINT16      ret;
1250
1251     ReleaseThunkLock(&level);
1252     ret = waveOutBreakLoop(HWAVEOUT_32(hWaveOut16));
1253     RestoreThunkLock(level);
1254     return ret;
1255 }
1256
1257 /**************************************************************************
1258  *                              waveOutPause            [MMSYSTEM.409]
1259  */
1260 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut16)
1261 {
1262     DWORD       level;
1263     UINT16      ret;
1264
1265     ReleaseThunkLock(&level);
1266     ret = waveOutPause(HWAVEOUT_32(hWaveOut16));
1267     RestoreThunkLock(level);
1268     return ret;
1269 }
1270
1271 /**************************************************************************
1272  *                              waveOutReset            [MMSYSTEM.411]
1273  */
1274 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut16)
1275 {
1276     DWORD       level;
1277     UINT16      ret;
1278
1279     ReleaseThunkLock(&level);
1280     ret = waveOutReset(HWAVEOUT_32(hWaveOut16));
1281     RestoreThunkLock(level);
1282     return ret;
1283 }
1284
1285 /**************************************************************************
1286  *                              waveOutRestart  [MMSYSTEM.410]
1287  */
1288 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut16)
1289 {
1290     DWORD       level;
1291     UINT16      ret;
1292
1293     ReleaseThunkLock(&level);
1294     ret = waveOutRestart(HWAVEOUT_32(hWaveOut16));
1295     RestoreThunkLock(level);
1296     return ret;
1297 }
1298
1299 /**************************************************************************
1300  *                              waveOutGetPosition      [MMSYSTEM.412]
1301  */
1302 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
1303                                    UINT16 uSize)
1304 {
1305     UINT        ret;
1306     MMTIME      mmt;
1307
1308     mmt.wType = lpTime->wType;
1309     ret = waveOutGetPosition(HWAVEOUT_32(hWaveOut), &mmt, sizeof(mmt));
1310     MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1311     return ret;
1312 }
1313
1314 /**************************************************************************
1315  *                              waveOutGetPitch         [MMSYSTEM.413]
1316  */
1317 UINT16 WINAPI waveOutGetPitch16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1318 {
1319     return waveOutGetPitch(HWAVEOUT_32(hWaveOut16), lpdw);
1320 }
1321
1322 /**************************************************************************
1323  *                              waveOutSetPitch         [MMSYSTEM.414]
1324  */
1325 UINT16 WINAPI waveOutSetPitch16(HWAVEOUT16 hWaveOut16, DWORD dw)
1326 {
1327     return waveOutSetPitch(HWAVEOUT_32(hWaveOut16), dw);
1328 }
1329
1330 /**************************************************************************
1331  *                              waveOutGetPlaybackRate  [MMSYSTEM.417]
1332  */
1333 UINT16 WINAPI waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1334 {
1335     return waveOutGetPlaybackRate(HWAVEOUT_32(hWaveOut16), lpdw);
1336 }
1337
1338 /**************************************************************************
1339  *                              waveOutSetPlaybackRate  [MMSYSTEM.418]
1340  */
1341 UINT16 WINAPI waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16, DWORD dw)
1342 {
1343     return waveOutSetPlaybackRate(HWAVEOUT_32(hWaveOut16), dw);
1344 }
1345
1346 /**************************************************************************
1347  *                              waveOutGetVolume        [MMSYSTEM.415]
1348  */
1349 UINT16 WINAPI waveOutGetVolume16(UINT16 devid, LPDWORD lpdw)
1350 {
1351     return waveOutGetVolume(devid, lpdw);
1352 }
1353
1354 /**************************************************************************
1355  *                              waveOutSetVolume        [MMSYSTEM.416]
1356  */
1357 UINT16 WINAPI waveOutSetVolume16(UINT16 devid, DWORD dw)
1358 {
1359     return waveOutSetVolume(devid, dw);
1360 }
1361
1362 /**************************************************************************
1363  *                              waveOutGetID            [MMSYSTEM.420]
1364  */
1365 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16* lpuDeviceID)
1366 {
1367     LPWINE_MLD          wmld;
1368
1369     TRACE("(%04X, %p);\n", hWaveOut, lpuDeviceID);
1370
1371     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
1372
1373     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1374         return MMSYSERR_INVALHANDLE;
1375
1376     *lpuDeviceID = wmld->uDeviceID;
1377     return 0;
1378 }
1379
1380 /**************************************************************************
1381  *                              waveOutMessage          [MMSYSTEM.421]
1382  */
1383 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage,
1384                               DWORD dwParam1, DWORD dwParam2)
1385 {
1386     LPWINE_MLD          wmld;
1387
1388     TRACE("(%04x, %u, %ld, %ld)\n", hWaveOut, uMessage, dwParam1, dwParam2);
1389
1390     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL) {
1391         if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, TRUE)) != NULL) {
1392             return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
1393         }
1394         return MMSYSERR_INVALHANDLE;
1395     }
1396
1397     /* from M$ KB */
1398     if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1399         return MMSYSERR_INVALPARAM;
1400
1401     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1402 }
1403
1404 /**************************************************************************
1405  *                              waveInGetNumDevs                [MMSYSTEM.501]
1406  */
1407 UINT16 WINAPI waveInGetNumDevs16(void)
1408 {
1409     return MMDRV_GetNum(MMDRV_WAVEIN);
1410 }
1411
1412 /**************************************************************************
1413  *                              waveInGetDevCaps                [MMSYSTEM.502]
1414  */
1415 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps,
1416                                  UINT16 uSize)
1417 {
1418     WAVEINCAPSA wicA;
1419     UINT        ret = waveInGetDevCapsA(uDeviceID, &wicA, sizeof(wicA));
1420
1421     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1422
1423     if (ret == MMSYSERR_NOERROR) {
1424         lpCaps->wMid = wicA.wMid;
1425         lpCaps->wPid = wicA.wPid;
1426         lpCaps->vDriverVersion = wicA.vDriverVersion;
1427         strcpy(lpCaps->szPname, wicA.szPname);
1428         lpCaps->dwFormats = wicA.dwFormats;
1429         lpCaps->wChannels = wicA.wChannels;
1430     }
1431     return ret;
1432 }
1433
1434 /**************************************************************************
1435  *                              waveInGetErrorText      [MMSYSTEM.503]
1436  */
1437 UINT16 WINAPI waveInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1438 {
1439     return waveInGetErrorTextA(uError, lpText, uSize);
1440 }
1441
1442 /**************************************************************************
1443  *                              waveInOpen                      [MMSYSTEM.504]
1444  */
1445 UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
1446                            const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
1447                            DWORD dwInstance, DWORD dwFlags)
1448 {
1449     HWAVEIN             hWaveIn;
1450     UINT                ret;
1451
1452     /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1453      * call the 32 bit version
1454      * however, we need to promote correctly the wave mapper id
1455      * (0xFFFFFFFF and not 0x0000FFFF)
1456      */
1457     ret = MMSYSTEM_waveOpen(&hWaveIn, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1458                             MMDRV_WAVEIN, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1459
1460     if (lphWaveIn != NULL) *lphWaveIn = HWAVEIN_16(hWaveIn);
1461     return ret;
1462 }
1463
1464 /**************************************************************************
1465  *                              waveInClose                     [MMSYSTEM.505]
1466  */
1467 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
1468 {
1469     DWORD       level;
1470     UINT16      ret;
1471
1472     ReleaseThunkLock(&level);
1473     ret = waveInClose(HWAVEIN_32(hWaveIn));
1474     RestoreThunkLock(level);
1475     return ret;
1476 }
1477
1478 /**************************************************************************
1479  *                              waveInPrepareHeader             [MMSYSTEM.506]
1480  */
1481 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn,       /* [in] */
1482                                     SEGPTR lpsegWaveInHdr,   /* [???] */
1483                                     UINT16 uSize)            /* [in] */
1484 {
1485     LPWINE_MLD          wmld;
1486     LPWAVEHDR           lpWaveInHdr = MapSL(lpsegWaveInHdr);
1487     UINT16              ret;
1488
1489     TRACE("(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
1490
1491     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
1492     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1493         return MMSYSERR_INVALHANDLE;
1494
1495     lpWaveInHdr->dwBytesRecorded = 0;
1496
1497     ret = MMDRV_Message(wmld, WIDM_PREPARE, (DWORD)lpsegWaveInHdr, uSize, FALSE);
1498     return ret;
1499 }
1500
1501 /**************************************************************************
1502  *                              waveInUnprepareHeader   [MMSYSTEM.507]
1503  */
1504 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn,       /* [in] */
1505                                       SEGPTR lpsegWaveInHdr,   /* [???] */
1506                                       UINT16 uSize)            /* [in] */
1507 {
1508     LPWINE_MLD          wmld;
1509     LPWAVEHDR           lpWaveInHdr = MapSL(lpsegWaveInHdr);
1510
1511     TRACE("(%04X, %08lx, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1512
1513     if (lpWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1514
1515     if (!(lpWaveInHdr->dwFlags & WHDR_PREPARED)) {
1516         return MMSYSERR_NOERROR;
1517     }
1518
1519     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1520         return MMSYSERR_INVALHANDLE;
1521
1522     return MMDRV_Message(wmld, WIDM_UNPREPARE, (DWORD)lpsegWaveInHdr, uSize, FALSE);
1523 }
1524
1525 /**************************************************************************
1526  *                              waveInAddBuffer         [MMSYSTEM.508]
1527  */
1528 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn,       /* [in] */
1529                                 WAVEHDR* lpsegWaveInHdr, /* [???] NOTE: SEGPTR */
1530                                 UINT16 uSize)            /* [in] */
1531 {
1532     LPWINE_MLD          wmld;
1533
1534     TRACE("(%04X, %p, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1535
1536     if (lpsegWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1537     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1538         return MMSYSERR_INVALHANDLE;
1539
1540     return MMDRV_Message(wmld, WIDM_ADDBUFFER, (DWORD)lpsegWaveInHdr, uSize, FALSE);
1541 }
1542
1543 /**************************************************************************
1544  *                              waveInReset             [MMSYSTEM.511]
1545  */
1546 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn16)
1547 {
1548     DWORD       level;
1549     UINT16      ret;
1550
1551     ReleaseThunkLock(&level);
1552     ret = waveInReset(HWAVEIN_32(hWaveIn16));
1553     RestoreThunkLock(level);
1554     return ret;
1555 }
1556
1557 /**************************************************************************
1558  *                              waveInStart             [MMSYSTEM.509]
1559  */
1560 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn16)
1561 {
1562     DWORD       level;
1563     UINT16      ret;
1564
1565     ReleaseThunkLock(&level);
1566     ret = waveInStart(HWAVEIN_32(hWaveIn16));
1567     RestoreThunkLock(level);
1568     return ret;
1569 }
1570
1571 /**************************************************************************
1572  *                              waveInStop              [MMSYSTEM.510]
1573  */
1574 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn16)
1575 {
1576     DWORD       level;
1577     UINT16      ret;
1578
1579     ReleaseThunkLock(&level);
1580     ret = waveInStop(HWAVEIN_32(hWaveIn16));
1581     RestoreThunkLock(level);
1582     return ret;
1583 }
1584
1585 /**************************************************************************
1586  *                              waveInGetPosition       [MMSYSTEM.512]
1587  */
1588 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn, LPMMTIME16 lpTime,
1589                                   UINT16 uSize)
1590 {
1591     UINT        ret;
1592     MMTIME      mmt;
1593
1594     mmt.wType = lpTime->wType;
1595     ret = waveInGetPosition(HWAVEIN_32(hWaveIn), &mmt, sizeof(mmt));
1596     MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1597     return ret;
1598 }
1599
1600 /**************************************************************************
1601  *                              waveInGetID                     [MMSYSTEM.513]
1602  */
1603 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16* lpuDeviceID)
1604 {
1605     LPWINE_MLD          wmld;
1606
1607     TRACE("(%04X, %p);\n", hWaveIn, lpuDeviceID);
1608
1609     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
1610
1611     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1612         return MMSYSERR_INVALHANDLE;
1613
1614     *lpuDeviceID = wmld->uDeviceID;
1615     return MMSYSERR_NOERROR;
1616 }
1617
1618 /**************************************************************************
1619  *                              waveInMessage           [MMSYSTEM.514]
1620  */
1621 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
1622                              DWORD dwParam1, DWORD dwParam2)
1623 {
1624     LPWINE_MLD          wmld;
1625
1626     TRACE("(%04x, %u, %ld, %ld)\n", hWaveIn, uMessage, dwParam1, dwParam2);
1627
1628     /* from M$ KB */
1629     if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1630         return MMSYSERR_INVALPARAM;
1631
1632     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1633         return MMSYSERR_INVALHANDLE;
1634
1635     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, TRUE);
1636 }
1637
1638 /*#define USE_MM_TSK_WINE*/
1639
1640 /**************************************************************************
1641  *                              mmTaskCreate            [MMSYSTEM.900]
1642  *
1643  * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
1644  * called upon creation with dwPmt as parameter.
1645  */
1646 HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt)
1647 {
1648     HINSTANCE16         ret;
1649     HINSTANCE16         handle;
1650     char cmdline[16];
1651     DWORD showCmd = 0x40002;
1652     LOADPARAMS16 lp;
1653
1654     TRACE("(%08lx, %p, %08lx);\n", spProc, lphMmTask, dwPmt);
1655     /* This to work requires NE modules to be started with a binary command line
1656      * which is not currently the case. A patch exists but has never been committed.
1657      * A workaround would be to integrate code for mmtask.tsk into Wine, but
1658      * this requires tremendous work (starting with patching tools/build to
1659      * create NE executables (and not only DLLs) for builtins modules.
1660      * EP 99/04/25
1661      */
1662     FIXME("This is currently broken. It will fail\n");
1663
1664     cmdline[0] = 0x0d;
1665     *(LPDWORD)(cmdline + 1) = (DWORD)spProc;
1666     *(LPDWORD)(cmdline + 5) = dwPmt;
1667     *(LPDWORD)(cmdline + 9) = 0;
1668
1669     lp.hEnvironment = 0;
1670     lp.cmdLine = MapLS(cmdline);
1671     lp.showCmd = MapLS(&showCmd);
1672     lp.reserved = 0;
1673
1674 #ifndef USE_MM_TSK_WINE
1675     handle = LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp);
1676 #else
1677     handle = LoadModule16("mmtask.tsk", &lp);
1678 #endif
1679     if (handle < 32) {
1680         ret = (handle) ? 1 : 2;
1681         handle = 0;
1682     } else {
1683         ret = 0;
1684     }
1685     if (lphMmTask)
1686         *lphMmTask = handle;
1687
1688     UnMapLS( lp.cmdLine );
1689     UnMapLS( lp.showCmd );
1690     TRACE("=> 0x%04x/%d\n", handle, ret);
1691     return ret;
1692 }
1693
1694 #ifdef USE_MM_TSK_WINE
1695 /* C equivalent to mmtask.tsk binary content */
1696 void    mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
1697 {
1698     int len = cmdLine[0x80];
1699
1700     if (len / 2 == 6) {
1701         void    (*fpProc)(DWORD) = MapSL(*((DWORD*)(cmdLine + 1)));
1702         DWORD   dwPmt  = *((DWORD*)(cmdLine + 5));
1703
1704 #if 0
1705         InitTask16(); /* FIXME: pmts / from context ? */
1706         InitApp(di);
1707 #endif
1708         if (SetMessageQueue16(0x40)) {
1709             WaitEvent16(0);
1710             if (HIWORD(fpProc)) {
1711                 OldYield16();
1712 /* EPP          StackEnter16(); */
1713                 (fpProc)(dwPmt);
1714             }
1715         }
1716     }
1717     OldYield16();
1718     OldYield16();
1719     OldYield16();
1720     ExitProcess(0);
1721 }
1722 #endif
1723
1724 /**************************************************************************
1725  *                              mmTaskBlock             [MMSYSTEM.902]
1726  */
1727 void    WINAPI  mmTaskBlock16(HINSTANCE16 WINE_UNUSED hInst)
1728 {
1729     MSG         msg;
1730
1731     do {
1732         GetMessageA(&msg, 0, 0, 0);
1733         if (msg.hwnd) {
1734             TranslateMessage(&msg);
1735             DispatchMessageA(&msg);
1736         }
1737     } while (msg.message < 0x3A0);
1738 }
1739
1740 /**************************************************************************
1741  *                              mmTaskSignal            [MMSYSTEM.903]
1742  */
1743 LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
1744 {
1745     TRACE("(%04x);\n", ht);
1746     return PostAppMessage16(ht, WM_USER, 0, 0);
1747 }
1748
1749 /**************************************************************************
1750  *                              mmGetCurrentTask        [MMSYSTEM.904]
1751  */
1752 HTASK16 WINAPI mmGetCurrentTask16(void)
1753 {
1754     return GetCurrentTask();
1755 }
1756
1757 /**************************************************************************
1758  *                              mmTaskYield             [MMSYSTEM.905]
1759  */
1760 void    WINAPI  mmTaskYield16(void)
1761 {
1762     MSG         msg;
1763
1764     if (PeekMessageA(&msg, 0, 0, 0, 0)) {
1765         K32WOWYield16();
1766     }
1767 }
1768
1769 extern DWORD    WINAPI  GetProcessFlags(DWORD);
1770
1771 /**************************************************************************
1772  *                              mmThreadCreate          [MMSYSTEM.1120]
1773  *
1774  * undocumented
1775  * Creates a MM thread, calling fpThreadAddr(dwPmt).
1776  * dwFlags:
1777  *      bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
1778  *      bit.1 set means to open a VxD for this thread (unsupported)
1779  */
1780 LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE lpHndl, DWORD dwPmt, DWORD dwFlags)
1781 {
1782     HANDLE16            hndl;
1783     LRESULT             ret;
1784
1785     TRACE("(%p, %p, %08lx, %08lx)!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
1786
1787     hndl = GlobalAlloc16(sizeof(WINE_MMTHREAD), GMEM_SHARE|GMEM_ZEROINIT);
1788
1789     if (hndl == 0) {
1790         ret = 2;
1791     } else {
1792         WINE_MMTHREAD*  lpMMThd = MapSL( MAKESEGPTR(hndl, 0) );
1793
1794 #if 0
1795         /* force mmtask routines even if mmthread is required */
1796         /* this will work only if the patch about binary cmd line and NE tasks
1797          * is committed
1798          */
1799         dwFlags |= 1;
1800 #endif
1801
1802         lpMMThd->dwSignature    = WINE_MMTHREAD_CREATED;
1803         lpMMThd->dwCounter      = 0;
1804         lpMMThd->hThread        = 0;
1805         lpMMThd->dwThreadID     = 0;
1806         lpMMThd->fpThread       = fpThreadAddr;
1807         lpMMThd->dwThreadPmt    = dwPmt;
1808         lpMMThd->dwSignalCount  = 0;
1809         lpMMThd->hEvent         = 0;
1810         lpMMThd->hVxD           = 0;
1811         lpMMThd->dwStatus       = 0;
1812         lpMMThd->dwFlags        = dwFlags;
1813         lpMMThd->hTask          = 0;
1814
1815         if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
1816             lpMMThd->hEvent = CreateEventA(0, 0, 1, 0);
1817
1818             TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd);
1819             if (lpMMThd->dwFlags & 2) {
1820                 /* as long as we don't support MM VxD in wine, we don't need
1821                  * to care about this flag
1822                  */
1823                 /* FIXME("Don't know how to properly open VxD handles\n"); */
1824                 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
1825             }
1826
1827             lpMMThd->hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)WINE_mmThreadEntryPoint,
1828                                             (LPVOID)(DWORD)hndl, CREATE_SUSPENDED, &lpMMThd->dwThreadID);
1829             if (lpMMThd->hThread == 0) {
1830                 WARN("Couldn't create thread\n");
1831                 /* clean-up(VxDhandle...); devicedirectio... */
1832                 if (lpMMThd->hEvent != 0)
1833                     CloseHandle(lpMMThd->hEvent);
1834                 ret = 2;
1835             } else {
1836                 TRACE("Got a nice thread hndl=0x%04x id=0x%08lx\n", lpMMThd->hThread, lpMMThd->dwThreadID);
1837                 ret = 0;
1838             }
1839         } else {
1840             /* get WINE_mmThreadEntryPoint()
1841              * 2047 is its ordinal in mmsystem.spec
1842              */
1843             FARPROC16   fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR)2047);
1844
1845             TRACE("farproc seg=0x%08lx lin=%p\n", (DWORD)fp, MapSL((SEGPTR)fp));
1846
1847             ret = (fp == 0) ? 2 : mmTaskCreate16((DWORD)fp, 0, hndl);
1848         }
1849
1850         if (ret == 0) {
1851             if (lpMMThd->hThread && !ResumeThread(lpMMThd->hThread))
1852                 WARN("Couldn't resume thread\n");
1853
1854             while (lpMMThd->dwStatus != 0x10) { /* test also HIWORD of dwStatus */
1855                 UserYield16();
1856             }
1857         }
1858     }
1859
1860     if (ret != 0) {
1861         GlobalFree16(hndl);
1862         hndl = 0;
1863     }
1864
1865     if (lpHndl)
1866         *lpHndl = hndl;
1867
1868     TRACE("ok => %ld\n", ret);
1869     return ret;
1870 }
1871
1872 /**************************************************************************
1873  *                              mmThreadSignal          [MMSYSTEM.1121]
1874  */
1875 void WINAPI mmThreadSignal16(HANDLE16 hndl)
1876 {
1877     TRACE("(%04x)!\n", hndl);
1878
1879     if (hndl) {
1880         WINE_MMTHREAD*  lpMMThd = MapSL( MAKESEGPTR(hndl, 0) );
1881
1882         lpMMThd->dwCounter++;
1883         if (lpMMThd->hThread != 0) {
1884             InterlockedIncrement(&lpMMThd->dwSignalCount);
1885             SetEvent(lpMMThd->hEvent);
1886         } else {
1887             mmTaskSignal16(lpMMThd->hTask);
1888         }
1889         lpMMThd->dwCounter--;
1890     }
1891 }
1892
1893 static  void    MMSYSTEM_ThreadBlock(WINE_MMTHREAD* lpMMThd)
1894 {
1895     MSG         msg;
1896     DWORD       ret;
1897
1898     if (lpMMThd->dwThreadID != GetCurrentThreadId())
1899         ERR("Not called by thread itself\n");
1900
1901     for (;;) {
1902         ResetEvent(lpMMThd->hEvent);
1903         if (InterlockedDecrement(&lpMMThd->dwSignalCount) >= 0)
1904             break;
1905         InterlockedIncrement(&lpMMThd->dwSignalCount);
1906
1907         TRACE("S1\n");
1908
1909         ret = MsgWaitForMultipleObjects(1, &lpMMThd->hEvent, FALSE, INFINITE, QS_ALLINPUT);
1910         switch (ret) {
1911         case WAIT_OBJECT_0:     /* Event */
1912             TRACE("S2.1\n");
1913             break;
1914         case WAIT_OBJECT_0 + 1: /* Msg */
1915             TRACE("S2.2\n");
1916             if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
1917                 TranslateMessage(&msg);
1918                 DispatchMessageA(&msg);
1919             }
1920             break;
1921         default:
1922             WARN("S2.x unsupported ret val 0x%08lx\n", ret);
1923         }
1924         TRACE("S3\n");
1925     }
1926 }
1927
1928 /**************************************************************************
1929  *                              mmThreadBlock           [MMSYSTEM.1122]
1930  */
1931 void    WINAPI mmThreadBlock16(HANDLE16 hndl)
1932 {
1933     TRACE("(%04x)!\n", hndl);
1934
1935     if (hndl) {
1936         WINE_MMTHREAD*  lpMMThd = MapSL( MAKESEGPTR(hndl, 0) );
1937
1938         if (lpMMThd->hThread != 0) {
1939             DWORD       lc;
1940
1941             ReleaseThunkLock(&lc);
1942             MMSYSTEM_ThreadBlock(lpMMThd);
1943             RestoreThunkLock(lc);
1944         } else {
1945             mmTaskBlock16(lpMMThd->hTask);
1946         }
1947     }
1948     TRACE("done\n");
1949 }
1950
1951 /**************************************************************************
1952  *                              mmThreadIsCurrent       [MMSYSTEM.1123]
1953  */
1954 BOOL16  WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
1955 {
1956     BOOL16              ret = FALSE;
1957
1958     TRACE("(%04x)!\n", hndl);
1959
1960     if (hndl && mmThreadIsValid16(hndl)) {
1961         WINE_MMTHREAD*  lpMMThd = MapSL( MAKESEGPTR(hndl, 0) );
1962         ret = (GetCurrentThreadId() == lpMMThd->dwThreadID);
1963     }
1964     TRACE("=> %d\n", ret);
1965     return ret;
1966 }
1967
1968 /**************************************************************************
1969  *                              mmThreadIsValid         [MMSYSTEM.1124]
1970  */
1971 BOOL16  WINAPI  mmThreadIsValid16(HANDLE16 hndl)
1972 {
1973     BOOL16              ret = FALSE;
1974
1975     TRACE("(%04x)!\n", hndl);
1976
1977     if (hndl) {
1978         WINE_MMTHREAD*  lpMMThd = MapSL( MAKESEGPTR(hndl, 0) );
1979
1980         if (!IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) &&
1981             lpMMThd->dwSignature == WINE_MMTHREAD_CREATED &&
1982             IsTask16(lpMMThd->hTask)) {
1983             lpMMThd->dwCounter++;
1984             if (lpMMThd->hThread != 0) {
1985                 DWORD   dwThreadRet;
1986                 if (GetExitCodeThread(lpMMThd->hThread, &dwThreadRet) &&
1987                     dwThreadRet == STATUS_PENDING) {
1988                     ret = TRUE;
1989                 }
1990             } else {
1991                 ret = TRUE;
1992             }
1993             lpMMThd->dwCounter--;
1994         }
1995     }
1996     TRACE("=> %d\n", ret);
1997     return ret;
1998 }
1999
2000 /**************************************************************************
2001  *                              mmThreadGetTask         [MMSYSTEM.1125]
2002  */
2003 HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
2004 {
2005     HANDLE16    ret = 0;
2006
2007     TRACE("(%04x)\n", hndl);
2008
2009     if (mmThreadIsValid16(hndl)) {
2010         WINE_MMTHREAD*  lpMMThd = MapSL( MAKESEGPTR(hndl, 0) );
2011         ret = lpMMThd->hTask;
2012     }
2013     return ret;
2014 }
2015
2016 /* ### start build ### */
2017 extern LONG CALLBACK MMSYSTEM_CallTo16_long_l    (FARPROC16,LONG);
2018 /* ### stop build ### */
2019
2020 /**************************************************************************
2021  *                              __wine_mmThreadEntryPoint (MMSYSTEM.2047)
2022  */
2023 void WINAPI WINE_mmThreadEntryPoint(DWORD _pmt)
2024 {
2025     HANDLE16            hndl = (HANDLE16)_pmt;
2026     WINE_MMTHREAD*      lpMMThd = MapSL( MAKESEGPTR(hndl, 0) );
2027
2028     TRACE("(%04x %p)\n", hndl, lpMMThd);
2029
2030     lpMMThd->hTask = LOWORD(GetCurrentTask());
2031     TRACE("[10-%08x] setting hTask to 0x%08x\n", lpMMThd->hThread, lpMMThd->hTask);
2032     lpMMThd->dwStatus = 0x10;
2033     MMSYSTEM_ThreadBlock(lpMMThd);
2034     TRACE("[20-%08x]\n", lpMMThd->hThread);
2035     lpMMThd->dwStatus = 0x20;
2036     if (lpMMThd->fpThread) {
2037         MMSYSTEM_CallTo16_long_l(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
2038     }
2039     lpMMThd->dwStatus = 0x30;
2040     TRACE("[30-%08x]\n", lpMMThd->hThread);
2041     while (lpMMThd->dwCounter) {
2042         Sleep(1);
2043         /* K32WOWYield16();*/
2044     }
2045     TRACE("[XX-%08x]\n", lpMMThd->hThread);
2046     /* paranoia */
2047     lpMMThd->dwSignature = WINE_MMTHREAD_DELETED;
2048     /* close lpMMThread->hVxD directIO */
2049     if (lpMMThd->hEvent)
2050         CloseHandle(lpMMThd->hEvent);
2051     GlobalFree16(hndl);
2052     TRACE("done\n");
2053 }
2054
2055 typedef BOOL16 (WINAPI *MMCPLCALLBACK)(HWND, LPCSTR, LPCSTR, LPCSTR);
2056
2057 /**************************************************************************
2058  *                      mmShowMMCPLPropertySheet        [MMSYSTEM.1150]
2059  */
2060 BOOL16  WINAPI  mmShowMMCPLPropertySheet16(HWND hWnd, LPCSTR lpStrDevice,
2061                                            LPCSTR lpStrTab, LPCSTR lpStrTitle)
2062 {
2063     HANDLE      hndl;
2064     BOOL16      ret = FALSE;
2065
2066     TRACE("(%04x \"%s\" \"%s\" \"%s\")\n", hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2067
2068     hndl = LoadLibraryA("MMSYS.CPL");
2069     if (hndl != 0) {
2070         MMCPLCALLBACK   fp = (MMCPLCALLBACK)GetProcAddress(hndl, "ShowMMCPLPropertySheet");
2071         if (fp != NULL) {
2072             DWORD       lc;
2073             ReleaseThunkLock(&lc);
2074             ret = (fp)(hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2075             RestoreThunkLock(lc);
2076         }
2077         FreeLibrary(hndl);
2078     }
2079
2080     return ret;
2081 }
2082
2083 /**************************************************************************
2084  *                      StackEnter              [MMSYSTEM.32]
2085  */
2086 void WINAPI StackEnter16(void)
2087 {
2088 #ifdef __i386__
2089     /* mmsystem.dll from Win 95 does only this: so does Wine */
2090     __asm__("stc");
2091 #endif
2092 }
2093
2094 /**************************************************************************
2095  *                      StackLeave              [MMSYSTEM.33]
2096  */
2097 void WINAPI StackLeave16(void)
2098 {
2099 #ifdef __i386__
2100     /* mmsystem.dll from Win 95 does only this: so does Wine */
2101     __asm__("stc");
2102 #endif
2103 }
2104
2105 /**************************************************************************
2106  *                      WMMMidiRunOnce          [MMSYSTEM.8]
2107  */
2108 void WINAPI WMMMidiRunOnce16(void)
2109 {
2110         FIXME("(), stub!\n");
2111 }
2112
2113 /**************************************************************************
2114  *                      OutputDebugStr          [MMSYSTEM.30]
2115  */
2116 void WINAPI OutputDebugStr16(
2117     LPCSTR str) /* [in] The message to be logged and given to the debugger. */
2118 {
2119     OutputDebugStringA( str );
2120 }
2121
2122 /**************************************************************************
2123  *                              DrvOpen                 [MMSYSTEM.1100]
2124  */
2125 HDRVR16 WINAPI DrvOpen16(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
2126 {
2127     return OpenDriver16(lpDriverName, lpSectionName, lParam);
2128 }
2129
2130 /**************************************************************************
2131  *                              DrvClose                [MMSYSTEM.1101]
2132  */
2133 LRESULT WINAPI DrvClose16(HDRVR16 hDrv, LPARAM lParam1, LPARAM lParam2)
2134 {
2135     return CloseDriver16(hDrv, lParam1, lParam2);
2136 }
2137
2138 /**************************************************************************
2139  *                              DrvSendMessage          [MMSYSTEM.1102]
2140  */
2141 LRESULT WINAPI DrvSendMessage16(HDRVR16 hDrv, WORD msg, LPARAM lParam1,
2142                                 LPARAM lParam2)
2143 {
2144     return SendDriverMessage16(hDrv, msg, lParam1, lParam2);
2145 }
2146
2147 /**************************************************************************
2148  *                              DrvGetModuleHandle      [MMSYSTEM.1103]
2149  */
2150 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrv)
2151 {
2152     return GetDriverModuleHandle16(hDrv);
2153 }
2154
2155 /**************************************************************************
2156  *                              DrvDefDriverProc        [MMSYSTEM.1104]
2157  */
2158 LRESULT WINAPI DrvDefDriverProc16(DWORD dwDriverID, HDRVR16 hDrv, WORD wMsg,
2159                                   DWORD dwParam1, DWORD dwParam2)
2160 {
2161     return DefDriverProc16(dwDriverID, hDrv, wMsg, dwParam1, dwParam2);
2162 }
2163
2164 /**************************************************************************
2165  *                              DriverProc                      [MMSYSTEM.6]
2166  */
2167 LRESULT WINAPI DriverProc16(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
2168                             DWORD dwParam1, DWORD dwParam2)
2169 {
2170     TRACE("dwDevID=%08lx hDrv=%04x wMsg=%04x dwParam1=%08lx dwParam2=%08lx\n",
2171           dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2172
2173     return DrvDefDriverProc16(dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2174 }
2175
2176 /**************************************************************************
2177  *                              timeGetSystemTime       [MMSYSTEM.601]
2178  */
2179 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
2180 {
2181     TRACE("(%p, %u);\n", lpTime, wSize);
2182
2183     if (wSize >= sizeof(*lpTime)) {
2184         lpTime->wType = TIME_MS;
2185         lpTime->u.ms = TIME_MMTimeStart()->mmSysTimeMS;
2186
2187         TRACE("=> %lu\n", lpTime->u.ms);
2188     }
2189
2190     return 0;
2191 }
2192
2193 /**************************************************************************
2194  *                              timeSetEvent            [MMSYSTEM.602]
2195  */
2196 MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol, LPTIMECALLBACK16 lpFunc,
2197                                  DWORD dwUser, UINT16 wFlags)
2198 {
2199     if (wFlags & WINE_TIMER_IS32)
2200         WARN("Unknown windows flag... wine internally used.. ooch\n");
2201
2202     return timeSetEventInternal(wDelay, wResol, (FARPROC16)lpFunc,
2203                                 dwUser, wFlags & ~WINE_TIMER_IS32);
2204 }
2205
2206 /**************************************************************************
2207  *                              timeKillEvent           [MMSYSTEM.603]
2208  */
2209 MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
2210 {
2211     return timeKillEvent(wID);
2212 }
2213
2214 /**************************************************************************
2215  *                              timeGetDevCaps          [MMSYSTEM.604]
2216  */
2217 MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
2218 {
2219     TIMECAPS    caps;
2220     MMRESULT    ret;
2221
2222     TRACE("(%p, %u) !\n", lpCaps, wSize);
2223
2224     ret = timeGetDevCaps(&caps, sizeof(caps));
2225     lpCaps->wPeriodMin = caps.wPeriodMin;
2226     lpCaps->wPeriodMax = caps.wPeriodMax;
2227     return 0;
2228 }
2229
2230 /**************************************************************************
2231  *                              timeBeginPeriod [MMSYSTEM.605]
2232  */
2233 MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
2234 {
2235     TRACE("(%u) !\n", wPeriod);
2236
2237     return timeBeginPeriod(wPeriod);
2238 }
2239
2240 /**************************************************************************
2241  *                              timeEndPeriod           [MMSYSTEM.606]
2242  */
2243 MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
2244 {
2245     TRACE("(%u) !\n", wPeriod);
2246
2247     return timeEndPeriod(wPeriod);
2248 }
2249
2250 /**************************************************************************
2251  *                              mciSendString                   [MMSYSTEM.702]
2252  */
2253 DWORD WINAPI mciSendString16(LPCSTR lpstrCommand, LPSTR lpstrRet,
2254                              UINT16 uRetLen, HWND16 hwndCallback)
2255 {
2256     return mciSendStringA(lpstrCommand, lpstrRet, uRetLen, HWND_32(hwndCallback));
2257 }
2258
2259 /**************************************************************************
2260  *                      mciLoadCommandResource                  [MMSYSTEM.705]
2261  */
2262 UINT16 WINAPI mciLoadCommandResource16(HANDLE16 hInst, LPCSTR resname, UINT16 type)
2263 {
2264     LPCWSTR     ptr = HEAP_strdupAtoW(GetProcessHeap(), 0, resname);
2265     UINT        ret = mciLoadCommandResource(hInst, ptr, type);
2266     HeapFree(GetProcessHeap(), 0, (LPWSTR)ptr);
2267     return ret;
2268 }
2269
2270 /**************************************************************************
2271  *                      mciFreeCommandResource                  [MMSYSTEM.713]
2272  */
2273 BOOL16 WINAPI mciFreeCommandResource16(UINT16 uTable)
2274 {
2275     TRACE("(%04x)!\n", uTable);
2276
2277     return mciFreeCommandResource(uTable);
2278 }