Logo Search packages:      
Sourcecode: wine-unstable version File versions  Download package

message16.c

/*
 * MMSYSTEM MCI and low level mapping functions
 *
 * Copyright 1999 Eric Pouech
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
#include "wine/winbase16.h"
#include "windef.h"
#include "winbase.h"
#include "wownt32.h"
#include "winemm16.h"
#include "digitalv.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(winmm);

/* =================================
 *       A U X    M A P P E R S
 * ================================= */

/* =================================
 *     M I X E R  M A P P E R S
 * ================================= */

/**************************************************************************
 *                      MMSYSTDRV_Mixer_Map16To32W          [internal]
 */
static  MMSYSTEM_MapType      MMSYSTDRV_Mixer_Map16To32W  (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
{
    return MMSYSTEM_MAP_MSGERROR;
}

/**************************************************************************
 *                      MMSYSTDRV_Mixer_UnMap16To32W  [internal]
 */
static  MMSYSTEM_MapType      MMSYSTDRV_Mixer_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
{
#if 0
    MIXERCAPSA    micA;
    UINT    ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));

    if (ret == MMSYSERR_NOERROR) {
      mixcaps->wMid           = micA.wMid;
      mixcaps->wPid           = micA.wPid;
      mixcaps->vDriverVersion = micA.vDriverVersion;
      strcpy(mixcaps->szPname, micA.szPname);
      mixcaps->fdwSupport     = micA.fdwSupport;
      mixcaps->cDestinations  = micA.cDestinations;
    }
    return ret;
#endif
    return MMSYSTEM_MAP_MSGERROR;
}

/**************************************************************************
 *                      MMSYSTDRV_Mixer_MapCB
 */
static  void                      MMSYSTDRV_Mixer_MapCB(DWORD uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2)
{
    FIXME("NIY\n");
}

/* =================================
 *   M I D I  I N    M A P P E R S
 * ================================= */

/**************************************************************************
 *                      MMSYSTDRV_MidiIn_Map16To32W         [internal]
 */
static  MMSYSTEM_MapType      MMSYSTDRV_MidiIn_Map16To32W  (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
{
    return MMSYSTEM_MAP_MSGERROR;
}

/**************************************************************************
 *                      MMSYSTDRV_MidiIn_UnMap16To32W [internal]
 */
static  MMSYSTEM_MapType      MMSYSTDRV_MidiIn_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
{
    return MMSYSTEM_MAP_MSGERROR;
}

/**************************************************************************
 *                      MMSYSTDRV_MidiIn_MapCB        [internal]
 */
static  void                  MMSYSTDRV_MidiIn_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2)
{
    switch (uMsg) {
    case MIM_OPEN:
    case MIM_CLOSE:
      /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */

    case MIM_DATA:
    case MIM_MOREDATA:
    case MIM_ERROR:
      /* dwParam1 & dwParam2 are data, nothing to do */
      break;
    case MIM_LONGDATA:
    case MIM_LONGERROR:
        {
          LPMIDIHDR           mh32 = (LPMIDIHDR)(*dwParam1);
          SEGPTR        segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
          LPMIDIHDR           mh16 = MapSL(segmh16);

          *dwParam1 = (DWORD)segmh16;
          mh16->dwFlags = mh32->dwFlags;
          mh16->dwBytesRecorded = mh32->dwBytesRecorded;
          if (mh16->reserved >= sizeof(MIDIHDR))
            mh16->dwOffset = mh32->dwOffset;
      }
      break;
    default:
      ERR("Unknown msg %u\n", uMsg);
    }
}

/* =================================
 *   M I D I  O U T  M A P P E R S
 * ================================= */

/**************************************************************************
 *                      MMSYSTDRV_MidiOut_Map16To32W  [internal]
 */
static MMSYSTEM_MapType MMSYSTDRV_MidiOut_Map16To32W  (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
{
    MMSYSTEM_MapType    ret = MMSYSTEM_MAP_MSGERROR;

    switch (wMsg) {
    case MODM_GETNUMDEVS:
    case MODM_DATA:
    case MODM_RESET:
    case MODM_SETVOLUME:
      ret = MMSYSTEM_MAP_OK;
      break;

    case MODM_OPEN:
    case MODM_CLOSE:
    case MODM_GETVOLUME:
      FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
      break;

    case MODM_GETDEVCAPS:
      {
            LPMIDIOUTCAPSW    moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSW));
          LPMIDIOUTCAPS16     moc16 = MapSL(*lpParam1);

          if (moc32) {
            *(LPMIDIOUTCAPS16*)moc32 = moc16;
            moc32 = (LPMIDIOUTCAPSW)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16));
            *lpParam1 = (DWORD)moc32;
            *lpParam2 = sizeof(MIDIOUTCAPSW);

            ret = MMSYSTEM_MAP_OKMEM;
          } else {
            ret = MMSYSTEM_MAP_NOMEM;
          }
      }
      break;
    case MODM_PREPARE:
      {
          LPMIDIHDR           mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR));
          LPMIDIHDR           mh16 = MapSL(*lpParam1);

          if (mh32) {
            *(LPMIDIHDR*)mh32 = (LPMIDIHDR)*lpParam1;
            mh32 = (LPMIDIHDR)((LPSTR)mh32 + sizeof(LPMIDIHDR));
            mh32->lpData = MapSL((SEGPTR)mh16->lpData);
            mh32->dwBufferLength = mh16->dwBufferLength;
            mh32->dwBytesRecorded = mh16->dwBytesRecorded;
            mh32->dwUser = mh16->dwUser;
            mh32->dwFlags = mh16->dwFlags;
            /* FIXME: nothing on mh32->lpNext */
            /* could link the mh32->lpNext at this level for memory house keeping */
            mh32->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? mh16->dwOffset : 0;
            mh16->lpNext = mh32; /* for reuse in unprepare and write */
            /* store size of passed MIDIHDR?? structure to know if dwOffset is available or not */
            mh16->reserved = *lpParam2;
            *lpParam1 = (DWORD)mh32;
            *lpParam2 = sizeof(MIDIHDR);

            ret = MMSYSTEM_MAP_OKMEM;
          } else {
            ret = MMSYSTEM_MAP_NOMEM;
          }
      }
      break;
    case MODM_UNPREPARE:
    case MODM_LONGDATA:
      {
          LPMIDIHDR           mh16 = MapSL(*lpParam1);
          LPMIDIHDR           mh32 = mh16->lpNext;

          *lpParam1 = (DWORD)mh32;
          *lpParam2 = sizeof(MIDIHDR);
          /* dwBufferLength can be reduced between prepare & write */
          if (wMsg == MODM_LONGDATA && mh32->dwBufferLength < mh16->dwBufferLength) {
            ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
                mh32->dwBufferLength, mh16->dwBufferLength);
          } else
                mh32->dwBufferLength = mh16->dwBufferLength;
          ret = MMSYSTEM_MAP_OKMEM;
      }
      break;

    case MODM_CACHEPATCHES:
    case MODM_CACHEDRUMPATCHES:
    default:
      FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
      break;
    }
    return ret;
}

/**************************************************************************
 *                      MMSYSTDRV_MidiOut_UnMap16To32W      [internal]
 */
static  MMSYSTEM_MapType      MMSYSTDRV_MidiOut_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
{
    MMSYSTEM_MapType    ret = MMSYSTEM_MAP_MSGERROR;

    switch (wMsg) {
    case MODM_GETNUMDEVS:
    case MODM_DATA:
    case MODM_RESET:
    case MODM_SETVOLUME:
      ret = MMSYSTEM_MAP_OK;
      break;

    case MODM_OPEN:
    case MODM_CLOSE:
    case MODM_GETVOLUME:
      FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
      break;

    case MODM_GETDEVCAPS:
      {
            LPMIDIOUTCAPSW          moc32 = (LPMIDIOUTCAPSW)(*lpParam1);
          LPMIDIOUTCAPS16           moc16 = *(LPMIDIOUTCAPS16*)((LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));

          moc16->wMid               = moc32->wMid;
          moc16->wPid               = moc32->wPid;
          moc16->vDriverVersion     = moc32->vDriverVersion;
            WideCharToMultiByte( CP_ACP, 0, moc32->szPname, -1, moc16->szPname,
                                 sizeof(moc16->szPname), NULL, NULL );
          moc16->wTechnology        = moc32->wTechnology;
          moc16->wVoices            = moc32->wVoices;
          moc16->wNotes       = moc32->wNotes;
          moc16->wChannelMask       = moc32->wChannelMask;
          moc16->dwSupport          = moc32->dwSupport;
          HeapFree(GetProcessHeap(), 0, (LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16));
          ret = MMSYSTEM_MAP_OK;
      }
      break;
    case MODM_PREPARE:
    case MODM_UNPREPARE:
    case MODM_LONGDATA:
      {
          LPMIDIHDR           mh32 = (LPMIDIHDR)(*lpParam1);
          LPMIDIHDR           mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)));

          assert(mh16->lpNext == mh32);
          mh16->dwBufferLength = mh32->dwBufferLength;
          mh16->dwBytesRecorded = mh32->dwBytesRecorded;
          mh16->dwUser = mh32->dwUser;
          mh16->dwFlags = mh32->dwFlags;
          if (mh16->reserved >= sizeof(MIDIHDR))
            mh16->dwOffset = mh32->dwOffset;

          if (wMsg == MODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
            HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR));
            mh16->lpNext = 0;
          }
          ret = MMSYSTEM_MAP_OK;
      }
      break;

    case MODM_CACHEPATCHES:
    case MODM_CACHEDRUMPATCHES:
    default:
      FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
      break;
    }
    return ret;
}

/******************************************************************
 *                                  MMSYSTDRV_MidiOut_MapCB
 */
static  void MMSYSTDRV_MidiOut_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2)
{
    switch (uMsg) {
    case MOM_OPEN:
    case MOM_CLOSE:
      /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
      break;
    case MOM_DONE:
        {
          /* initial map is: 16 => 32 */
          LPMIDIHDR           mh32 = (LPMIDIHDR)(*dwParam1);
          SEGPTR        segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR));
          LPMIDIHDR           mh16 = MapSL(segmh16);

          *dwParam1 = (DWORD)segmh16;
          mh16->dwFlags = mh32->dwFlags;
          if (mh16->reserved >= sizeof(MIDIHDR))
            mh16->dwOffset = mh32->dwOffset;
      }
      break;
    case MOM_POSITIONCB:
        FIXME("NIY\n");
        /* FIXME: would require to recreate a 16bit MIDIHDR here */
        *dwParam1 = *dwParam2 = 0;
        break;
    default:
      ERR("Unknown msg %u\n", uMsg);
    }
}

/* =================================
 *   W A V E  I N    M A P P E R S
 * ================================= */

/**************************************************************************
 *                      MMSYSTDRV_WaveIn_Map16To32W         [internal]
 */
static  MMSYSTEM_MapType      MMSYSTDRV_WaveIn_Map16To32W  (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
{
    MMSYSTEM_MapType    ret = MMSYSTEM_MAP_MSGERROR;

    switch (wMsg) {
    case WIDM_GETNUMDEVS:
    case WIDM_RESET:
    case WIDM_START:
    case WIDM_STOP:
      ret = MMSYSTEM_MAP_OK;
      break;
    case WIDM_OPEN:
    case WIDM_CLOSE:
      FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
      break;
    case WIDM_GETDEVCAPS:
      {
            LPWAVEINCAPSW     wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSW));
          LPWAVEINCAPS16      wic16 = MapSL(*lpParam1);

          if (wic32) {
            *(LPWAVEINCAPS16*)wic32 = wic16;
            wic32 = (LPWAVEINCAPSW)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16));
            *lpParam1 = (DWORD)wic32;
            *lpParam2 = sizeof(WAVEINCAPSW);

            ret = MMSYSTEM_MAP_OKMEM;
          } else {
            ret = MMSYSTEM_MAP_NOMEM;
          }
      }
      break;
    case WIDM_GETPOS:
      {
            LPMMTIME          mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
          LPMMTIME16          mmt16 = MapSL(*lpParam1);

          if (mmt32) {
            *(LPMMTIME16*)mmt32 = mmt16;
            mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));

            mmt32->wType = mmt16->wType;
            *lpParam1 = (DWORD)mmt32;
            *lpParam2 = sizeof(MMTIME);

            ret = MMSYSTEM_MAP_OKMEM;
          } else {
            ret = MMSYSTEM_MAP_NOMEM;
          }
      }
      break;
    case WIDM_PREPARE:
      {
          LPWAVEHDR           wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
          LPWAVEHDR           wh16 = MapSL(*lpParam1);

          if (wh32) {
            *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
            wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
            wh32->lpData = MapSL((SEGPTR)wh16->lpData);
            wh32->dwBufferLength = wh16->dwBufferLength;
            wh32->dwBytesRecorded = wh16->dwBytesRecorded;
            wh32->dwUser = wh16->dwUser;
            wh32->dwFlags = wh16->dwFlags;
            wh32->dwLoops = wh16->dwLoops;
            /* FIXME: nothing on wh32->lpNext */
            /* could link the wh32->lpNext at this level for memory house keeping */
            wh16->lpNext = wh32; /* for reuse in unprepare and write */
            *lpParam1 = (DWORD)wh32;
            *lpParam2 = sizeof(WAVEHDR);

            ret = MMSYSTEM_MAP_OKMEM;
          } else {
            ret = MMSYSTEM_MAP_NOMEM;
          }
      }
      break;
    case WIDM_ADDBUFFER:
    case WIDM_UNPREPARE:
      {
          LPWAVEHDR           wh16 = MapSL(*lpParam1);
          LPWAVEHDR           wh32 = wh16->lpNext;

          *lpParam1 = (DWORD)wh32;
          *lpParam2 = sizeof(WAVEHDR);
          /* dwBufferLength can be reduced between prepare & write */
          if (wMsg == WIDM_ADDBUFFER && wh32->dwBufferLength < wh16->dwBufferLength) {
            ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
                wh32->dwBufferLength, wh16->dwBufferLength);
          } else
                wh32->dwBufferLength = wh16->dwBufferLength;
          ret = MMSYSTEM_MAP_OKMEM;
      }
      break;
    case WIDM_MAPPER_STATUS:
      /* just a single DWORD */
      *lpParam2 = (DWORD)MapSL(*lpParam2);
      ret = MMSYSTEM_MAP_OK;
      break;
    default:
      FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
      break;
    }
    return ret;
}

/**************************************************************************
 *                      MMSYSTDRV_WaveIn_UnMap16To32W [internal]
 */
static  MMSYSTEM_MapType      MMSYSTDRV_WaveIn_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
{
    MMSYSTEM_MapType    ret = MMSYSTEM_MAP_MSGERROR;

    switch (wMsg) {
    case WIDM_GETNUMDEVS:
    case WIDM_RESET:
    case WIDM_START:
    case WIDM_STOP:
    case WIDM_MAPPER_STATUS:
      ret = MMSYSTEM_MAP_OK;
      break;
    case WIDM_OPEN:
    case WIDM_CLOSE:
      FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
      break;
    case WIDM_GETDEVCAPS:
      {
            LPWAVEINCAPSW           wic32 = (LPWAVEINCAPSW)(*lpParam1);
          LPWAVEINCAPS16            wic16 = *(LPWAVEINCAPS16*)((LPSTR)wic32 - sizeof(LPWAVEINCAPS16));

          wic16->wMid = wic32->wMid;
          wic16->wPid = wic32->wPid;
          wic16->vDriverVersion = wic32->vDriverVersion;
            WideCharToMultiByte( CP_ACP, 0, wic32->szPname, -1, wic16->szPname,
                                 sizeof(wic16->szPname), NULL, NULL );
          wic16->dwFormats = wic32->dwFormats;
          wic16->wChannels = wic32->wChannels;
          HeapFree(GetProcessHeap(), 0, (LPSTR)wic32 - sizeof(LPWAVEINCAPS16));
          ret = MMSYSTEM_MAP_OK;
      }
      break;
    case WIDM_GETPOS:
      {
            LPMMTIME          mmt32 = (LPMMTIME)(*lpParam1);
          LPMMTIME16          mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));

          MMSYSTEM_MMTIME32to16(mmt16, mmt32);
          HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
          ret = MMSYSTEM_MAP_OK;
      }
      break;
    case WIDM_ADDBUFFER:
    case WIDM_PREPARE:
    case WIDM_UNPREPARE:
      {
          LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
          LPWAVEHDR           wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));

          assert(wh16->lpNext == wh32);
          wh16->dwBufferLength = wh32->dwBufferLength;
          wh16->dwBytesRecorded = wh32->dwBytesRecorded;
          wh16->dwUser = wh32->dwUser;
          wh16->dwFlags = wh32->dwFlags;
          wh16->dwLoops = wh32->dwLoops;

          if (wMsg == WIDM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
            HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
            wh16->lpNext = 0;
          }
          ret = MMSYSTEM_MAP_OK;
      }
      break;
    default:
      FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
      break;
    }
    return ret;
}

/**************************************************************************
 *                      MMSYSTDRV_WaveIn_MapCB        [internal]
 */
static  void    MMSYSTDRV_WaveIn_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2)
{
    switch (uMsg) {
    case WIM_OPEN:
    case WIM_CLOSE:
      /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
      break;
    case WIM_DATA:
        {
          /* initial map is: 16 => 32 */
          LPWAVEHDR           wh32 = (LPWAVEHDR)(*dwParam1);
          SEGPTR        segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
          LPWAVEHDR           wh16 = MapSL(segwh16);

          *dwParam1 = (DWORD)segwh16;
          wh16->dwFlags = wh32->dwFlags;
          wh16->dwBytesRecorded = wh32->dwBytesRecorded;
      }
      break;
    default:
      ERR("Unknown msg %u\n", uMsg);
    }
}

/* =================================
 *   W A V E  O U T  M A P P E R S
 * ================================= */

/**************************************************************************
 *                      MMSYSTDRV_WaveOut_Map16To32W  [internal]
 */
static  MMSYSTEM_MapType      MMSYSTDRV_WaveOut_Map16To32W  (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2)
{
    MMSYSTEM_MapType    ret = MMSYSTEM_MAP_MSGERROR;

    switch (wMsg) {
    /* nothing to do */
    case WODM_BREAKLOOP:
    case WODM_CLOSE:
    case WODM_GETNUMDEVS:
    case WODM_PAUSE:
    case WODM_RESET:
    case WODM_RESTART:
    case WODM_SETPITCH:
    case WODM_SETPLAYBACKRATE:
    case WODM_SETVOLUME:
      ret = MMSYSTEM_MAP_OK;
      break;

    case WODM_GETPITCH:
    case WODM_GETPLAYBACKRATE:
    case WODM_GETVOLUME:
    case WODM_OPEN:
      FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n");
      break;

    case WODM_GETDEVCAPS:
      {
            LPWAVEOUTCAPSW          woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSW));
          LPWAVEOUTCAPS16           woc16 = MapSL(*lpParam1);

          if (woc32) {
            *(LPWAVEOUTCAPS16*)woc32 = woc16;
            woc32 = (LPWAVEOUTCAPSW)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16));
            *lpParam1 = (DWORD)woc32;
            *lpParam2 = sizeof(WAVEOUTCAPSW);

            ret = MMSYSTEM_MAP_OKMEM;
          } else {
            ret = MMSYSTEM_MAP_NOMEM;
          }
      }
      break;
    case WODM_GETPOS:
      {
            LPMMTIME          mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME));
          LPMMTIME16          mmt16 = MapSL(*lpParam1);

          if (mmt32) {
            *(LPMMTIME16*)mmt32 = mmt16;
            mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16));

            mmt32->wType = mmt16->wType;
            *lpParam1 = (DWORD)mmt32;
            *lpParam2 = sizeof(MMTIME);

            ret = MMSYSTEM_MAP_OKMEM;
          } else {
            ret = MMSYSTEM_MAP_NOMEM;
          }
      }
      break;
    case WODM_PREPARE:
      {
          LPWAVEHDR           wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR));
          LPWAVEHDR           wh16 = MapSL(*lpParam1);

          if (wh32) {
            *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1;
            wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR));
            wh32->lpData = MapSL((SEGPTR)wh16->lpData);
            wh32->dwBufferLength = wh16->dwBufferLength;
            wh32->dwBytesRecorded = wh16->dwBytesRecorded;
            wh32->dwUser = wh16->dwUser;
            wh32->dwFlags = wh16->dwFlags;
            wh32->dwLoops = wh16->dwLoops;
            /* FIXME: nothing on wh32->lpNext */
            /* could link the wh32->lpNext at this level for memory house keeping */
            wh16->lpNext = wh32; /* for reuse in unprepare and write */
            *lpParam1 = (DWORD)wh32;
            *lpParam2 = sizeof(WAVEHDR);

            ret = MMSYSTEM_MAP_OKMEM;
          } else {
            ret = MMSYSTEM_MAP_NOMEM;
          }
      }
      break;
    case WODM_UNPREPARE:
    case WODM_WRITE:
      {
          LPWAVEHDR           wh16 = MapSL(*lpParam1);
          LPWAVEHDR           wh32 = wh16->lpNext;

          *lpParam1 = (DWORD)wh32;
          *lpParam2 = sizeof(WAVEHDR);
          /* dwBufferLength can be reduced between prepare & write */
          if (wMsg == WODM_WRITE && wh32->dwBufferLength < wh16->dwBufferLength) {
            ERR("Size of buffer has been increased from %d to %d, keeping initial value\n",
                wh32->dwBufferLength, wh16->dwBufferLength);
          } else
                wh32->dwBufferLength = wh16->dwBufferLength;
          ret = MMSYSTEM_MAP_OKMEM;
      }
      break;
    case WODM_MAPPER_STATUS:
      *lpParam2 = (DWORD)MapSL(*lpParam2);
      ret = MMSYSTEM_MAP_OK;
      break;
    default:
      FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
      break;
    }
    return ret;
}

/**************************************************************************
 *                      MMSYSTDRV_WaveOut_UnMap16To32W      [internal]
 */
static  MMSYSTEM_MapType      MMSYSTDRV_WaveOut_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret)
{
    MMSYSTEM_MapType    ret = MMSYSTEM_MAP_MSGERROR;

    switch (wMsg) {
    /* nothing to do */
    case WODM_BREAKLOOP:
    case WODM_CLOSE:
    case WODM_GETNUMDEVS:
    case WODM_PAUSE:
    case WODM_RESET:
    case WODM_RESTART:
    case WODM_SETPITCH:
    case WODM_SETPLAYBACKRATE:
    case WODM_SETVOLUME:
    case WODM_MAPPER_STATUS:
      ret = MMSYSTEM_MAP_OK;
      break;

    case WODM_GETPITCH:
    case WODM_GETPLAYBACKRATE:
    case WODM_GETVOLUME:
    case WODM_OPEN:
      FIXME("Shouldn't be used: those 16 bit functions use the 32 bit interface\n");
      break;

    case WODM_GETDEVCAPS:
      {
            LPWAVEOUTCAPSW          woc32 = (LPWAVEOUTCAPSW)(*lpParam1);
          LPWAVEOUTCAPS16           woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));

          woc16->wMid = woc32->wMid;
          woc16->wPid = woc32->wPid;
          woc16->vDriverVersion = woc32->vDriverVersion;
            WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname,
                                 sizeof(woc16->szPname), NULL, NULL );
          woc16->dwFormats = woc32->dwFormats;
          woc16->wChannels = woc32->wChannels;
          woc16->dwSupport = woc32->dwSupport;
          HeapFree(GetProcessHeap(), 0, (LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16));
          ret = MMSYSTEM_MAP_OK;
      }
      break;
    case WODM_GETPOS:
      {
            LPMMTIME          mmt32 = (LPMMTIME)(*lpParam1);
          LPMMTIME16          mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16));

          MMSYSTEM_MMTIME32to16(mmt16, mmt32);
          HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16));
          ret = MMSYSTEM_MAP_OK;
      }
      break;
    case WODM_PREPARE:
    case WODM_UNPREPARE:
    case WODM_WRITE:
      {
          LPWAVEHDR           wh32 = (LPWAVEHDR)(*lpParam1);
          LPWAVEHDR           wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)));

          assert(wh16->lpNext == wh32);
          wh16->dwBufferLength = wh32->dwBufferLength;
          wh16->dwBytesRecorded = wh32->dwBytesRecorded;
          wh16->dwUser = wh32->dwUser;
          wh16->dwFlags = wh32->dwFlags;
          wh16->dwLoops = wh32->dwLoops;

          if (wMsg == WODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) {
            HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR));
            wh16->lpNext = 0;
          }
          ret = MMSYSTEM_MAP_OK;
      }
      break;
    default:
      FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2);
      break;
    }
    return ret;
}

/**************************************************************************
 *                      MMDRV_WaveOut_Callback        [internal]
 */
static  void      MMSYSTDRV_WaveOut_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2)
{
    switch (uMsg) {
    case WOM_OPEN:
    case WOM_CLOSE:
      /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
      break;
    case WOM_DONE:
        {
          /* initial map is: 16 => 32 */
          LPWAVEHDR           wh32 = (LPWAVEHDR)(*dwParam1);
          SEGPTR        segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR));
          LPWAVEHDR           wh16 = MapSL(segwh16);

          *dwParam1 = (DWORD)segwh16;
          wh16->dwFlags = wh32->dwFlags;
      }
      break;
    default:
      ERR("Unknown msg %u\n", uMsg);
    }
}

/* ###################################################
 * #                DRIVER THUNKING                  #
 * ###################################################
 */
typedef     MMSYSTEM_MapType        (*MMSYSTDRV_MAPMSG)(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2);
typedef     MMSYSTEM_MapType        (*MMSYSTDRV_UNMAPMSG)(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT ret);
typedef void                    (*MMSYSTDRV_MAPCB)(DWORD wMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2);

#include <pshpack1.h>
#define MMSYSTDRV_MAX_THUNKS      32

static struct mmsystdrv_thunk
{
    BYTE                        popl_eax;       /* popl  %eax (return address) */
    BYTE                        pushl_func;     /* pushl $pfn16 (16bit callback function) */
    struct mmsystdrv_thunk*     this;
    BYTE                        pushl_eax;      /* pushl %eax */
    BYTE                        jmp;            /* ljmp MMDRV_Callback1632 */
    DWORD                       callback;
    DWORD                       pfn16;
    void*                       hMmdrv;         /* Handle to 32bit mmdrv object */
    enum MMSYSTEM_DriverType    kind;
} *MMSYSTDRV_Thunks;

#include <poppack.h>

static struct MMSYSTDRV_Type
{
    MMSYSTDRV_MAPMSG    mapmsg16to32W;
    MMSYSTDRV_UNMAPMSG  unmapmsg16to32W;
    MMSYSTDRV_MAPCB     mapcb;
} MMSYSTEM_DriversType[MMSYSTDRV_MAX] =
{
    {MMSYSTDRV_Mixer_Map16To32W,   MMSYSTDRV_Mixer_UnMap16To32W,   MMSYSTDRV_Mixer_MapCB},
    {MMSYSTDRV_MidiIn_Map16To32W,  MMSYSTDRV_MidiIn_UnMap16To32W,  MMSYSTDRV_MidiIn_MapCB},
    {MMSYSTDRV_MidiOut_Map16To32W, MMSYSTDRV_MidiOut_UnMap16To32W, MMSYSTDRV_MidiOut_MapCB},
    {MMSYSTDRV_WaveIn_Map16To32W,  MMSYSTDRV_WaveIn_UnMap16To32W,  MMSYSTDRV_WaveIn_MapCB},
    {MMSYSTDRV_WaveOut_Map16To32W, MMSYSTDRV_WaveOut_UnMap16To32W, MMSYSTDRV_WaveOut_MapCB},
};

/******************************************************************
 *          MMSYSTDRV_Callback3216
 *
 */
static LRESULT CALLBACK MMSYSTDRV_Callback3216(struct mmsystdrv_thunk* thunk, DWORD uFlags, HDRVR hDev,
                                               DWORD wMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1,
                                               DWORD_PTR dwParam2)
{
    assert(thunk->kind < MMSYSTDRV_MAX);
    assert(MMSYSTEM_DriversType[thunk->kind].mapcb);

    MMSYSTEM_DriversType[thunk->kind].mapcb(wMsg, &dwUser, &dwParam1, &dwParam2);

    if ((uFlags & DCB_TYPEMASK) == DCB_FUNCTION)
    {
        WORD args[8];
      /* 16 bit func, call it */
      TRACE("Function (16 bit) !\n");

        args[7] = HDRVR_16(hDev);
        args[6] = wMsg;
        args[5] = HIWORD(dwUser);
        args[4] = LOWORD(dwUser);
        args[3] = HIWORD(dwParam1);
        args[2] = LOWORD(dwParam1);
        args[1] = HIWORD(dwParam2);
        args[0] = LOWORD(dwParam2);
        return WOWCallback16Ex(thunk->pfn16, WCB16_PASCAL, sizeof(args), args, NULL);
    }
    return DriverCallback(thunk->pfn16, uFlags, hDev, wMsg, dwUser, dwParam1, dwParam2);
}

/******************************************************************
 *          MMSYSTDRV_AddThunk
 *
 */
struct mmsystdrv_thunk*       MMSYSTDRV_AddThunk(DWORD pfn16, enum MMSYSTEM_DriverType kind)
{
    struct mmsystdrv_thunk* thunk;

    EnterCriticalSection(&mmdrv_cs);
    if (!MMSYSTDRV_Thunks)
    {
        MMSYSTDRV_Thunks = VirtualAlloc(NULL, MMSYSTDRV_MAX_THUNKS * sizeof(*MMSYSTDRV_Thunks),
                                        MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (!MMSYSTDRV_Thunks)
        {
            LeaveCriticalSection(&mmdrv_cs);
            return NULL;
        }
        for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++)
        {
            thunk->popl_eax     = 0x58;   /* popl  %eax */
            thunk->pushl_func   = 0x68;   /* pushl $pfn16 */
            thunk->this         = thunk;
            thunk->pushl_eax    = 0x50;   /* pushl %eax */
            thunk->jmp          = 0xe9;   /* jmp MMDRV_Callback3216 */
            thunk->callback     = (char *)MMSYSTDRV_Callback3216 - (char *)(&thunk->callback + 1);
            thunk->pfn16        = 0;
            thunk->hMmdrv       = NULL;
            thunk->kind         = MMSYSTDRV_MAX;
        }
    }
    for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++)
    {
        if (thunk->pfn16 == 0 && thunk->hMmdrv == NULL)
        {
            thunk->pfn16 = pfn16;
            thunk->hMmdrv = NULL;
            thunk->kind = kind;
            LeaveCriticalSection(&mmdrv_cs);
            return thunk;
        }
    }
    LeaveCriticalSection(&mmdrv_cs);
    FIXME("Out of mmdrv-thunks. Bump MMDRV_MAX_THUNKS\n");
    return NULL;
}

/******************************************************************
 *          MMSYSTDRV_FindHandle
 *
 * Must be called with lock set
 */
static void*    MMSYSTDRV_FindHandle(void* h)
{
    struct mmsystdrv_thunk* thunk;

    for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++)
    {
        if (thunk->hMmdrv == h)
        {
            if (thunk->kind >= MMSYSTDRV_MAX) FIXME("Kind isn't properly initialized %x\n", thunk->kind);
            return thunk;
        }
    }
    return NULL;
}

/******************************************************************
 *          MMSYSTDRV_SetHandle
 *
 */
void    MMSYSTDRV_SetHandle(struct mmsystdrv_thunk* thunk, void* h)
{
    if (MMSYSTDRV_FindHandle(h)) FIXME("Already has a thunk for this handle %p!!!\n", h);
    thunk->hMmdrv = h;
}

/******************************************************************
 *          MMSYSTDRV_DeleteThunk
 */
void    MMSYSTDRV_DeleteThunk(struct mmsystdrv_thunk* thunk)
{
    thunk->pfn16 = 0;
    thunk->hMmdrv = NULL;
    thunk->kind = MMSYSTDRV_MAX;
}

/******************************************************************
 *          MMSYSTDRV_CloseHandle
 */
void    MMSYSTDRV_CloseHandle(void* h)
{
    struct mmsystdrv_thunk* thunk;

    EnterCriticalSection(&mmdrv_cs);
    if ((thunk = MMSYSTDRV_FindHandle(h)))
    {
        MMSYSTDRV_DeleteThunk(thunk);
    }
    LeaveCriticalSection(&mmdrv_cs);
}

/******************************************************************
 *          MMSYSTDRV_Message
 */
DWORD   MMSYSTDRV_Message(void* h, UINT msg, DWORD_PTR param1, DWORD_PTR param2)
{
    struct mmsystdrv_thunk*     thunk = MMSYSTDRV_FindHandle(h);
    struct MMSYSTDRV_Type*      drvtype;
    MMSYSTEM_MapType            map;
    DWORD                       ret;

    if (!thunk) return MMSYSERR_INVALHANDLE;
    drvtype = &MMSYSTEM_DriversType[thunk->kind];

    map = drvtype->mapmsg16to32W(msg, &param1, &param2);
    switch (map) {
    case MMSYSTEM_MAP_NOMEM:
        ret = MMSYSERR_NOMEM;
        break;
    case MMSYSTEM_MAP_MSGERROR:
        FIXME("NIY: no conversion yet 16->32 kind=%u msg=%u\n", thunk->kind, msg);
        ret = MMSYSERR_ERROR;
        break;
    case MMSYSTEM_MAP_OK:
    case MMSYSTEM_MAP_OKMEM:
        TRACE("Calling message(msg=%u p1=0x%08lx p2=0x%08lx)\n",
              msg, param1, param2);
        switch (thunk->kind)
        {
        case MMSYSTDRV_MIXER:   ret = mixerMessage  (h, msg, param1, param2); break;
        case MMSYSTDRV_MIDIIN:  ret = midiInMessage (h, msg, param1, param2); break;
        case MMSYSTDRV_MIDIOUT: ret = midiOutMessage(h, msg, param1, param2); break;
        case MMSYSTDRV_WAVEIN:  ret = waveInMessage (h, msg, param1, param2); break;
        case MMSYSTDRV_WAVEOUT: ret = waveOutMessage(h, msg, param1, param2); break;
        default: ret = MMSYSERR_INVALHANDLE; break; /* should never be reached */
        }
        if (map == MMSYSTEM_MAP_OKMEM)
            drvtype->unmapmsg16to32W(msg, &param1, &param2, ret);
        break;
    default:
        FIXME("NIY\n");
        ret = MMSYSERR_NOTSUPPORTED;
        break;
    }
    return ret;
}

Generated by  Doxygen 1.6.0   Back to index