Annotation of ntddk/src/mmedia/mmdrv/drvutil.c, revision 1.1

1.1     ! root        1: /****************************************************************************
        !             2:  *
        !             3:  *   drvutil.c
        !             4:  *
        !             5:  *   Multimedia kernel driver support component (mmdrv)
        !             6:  *
        !             7:  *   Copyright (c) Microsoft Corporation 1992. All rights reserved.
        !             8:  *
        !             9:  *   Support functions common to multiple multi-media drivers :
        !            10:  *
        !            11:  *   -- Open a device
        !            12:  *   -- Translate a kernel IO return code to a multi-media return code
        !            13:  *   -- Count the number of devices of a given type
        !            14:  *   -- Set and Get data synchronously to a kernel device
        !            15:  *
        !            16:  *   History
        !            17:  *      01-Feb-1992 - Robin Speed (RobinSp) wrote it
        !            18:  *      04-Feb-1992 - Reviewed by SteveDav
        !            19:  *
        !            20:  ***************************************************************************/
        !            21: 
        !            22: #include "mmdrv.h"
        !            23: #include <ntddwave.h>
        !            24: #include <ntddmidi.h>
        !            25: #include <ntddaux.h>
        !            26: 
        !            27: /****************************************************************************
        !            28:  * @doc INTERNAL
        !            29:  *
        !            30:  * @api MMRESULT | sndOpenDev | Open the kernel driver device corresponding
        !            31:  *       to a logical wave device id
        !            32:  *
        !            33:  * @parm UINT | DeviceType | The type of device
        !            34:  *
        !            35:  * @parm DWORD | dwId | The device id
        !            36:  *
        !            37:  * @parm PHANDLE | phDev | Where to return the kernel device handle
        !            38:  *
        !            39:  * @parm ACCESS_MASK | Access | The desired access
        !            40:  *
        !            41:  * @comm For our sound devices the only relevant access are read and
        !            42:  *    read/write.  Device should ALWAYS allow opens for read unless some
        !            43:  *    resource or access-rights restriction occurs.
        !            44:  ***************************************************************************/
        !            45: MMRESULT sndOpenDev(UINT DeviceType, DWORD dwId,
        !            46:                     PHANDLE phDev, DWORD Access)
        !            47: {
        !            48:     WCHAR cDev[SOUND_MAX_DEVICE_NAME];
        !            49: 
        !            50:     WinAssert(DeviceType == WaveOutDevice ||
        !            51:               DeviceType == WaveInDevice  ||
        !            52:               DeviceType == MidiOutDevice ||
        !            53:               DeviceType == MidiInDevice  ||
        !            54:               DeviceType == AuxDevice);
        !            55: 
        !            56:     //
        !            57:     // Check it's not out of range
        !            58:     //
        !            59: 
        !            60:     if (dwId > SOUND_MAX_DEVICES) {
        !            61:         return MMSYSERR_BADDEVICEID;
        !            62:     }
        !            63:     //
        !            64:     // Create the device name and open it - remove '\Device'
        !            65:     //
        !            66: 
        !            67:     wsprintf(cDev, L"\\\\.%ls%d",
        !            68:              (DeviceType == WaveOutDevice ? DD_WAVE_OUT_DEVICE_NAME_U :
        !            69:               DeviceType == WaveInDevice  ? DD_WAVE_IN_DEVICE_NAME_U  :
        !            70:               DeviceType == MidiOutDevice ? DD_MIDI_OUT_DEVICE_NAME_U :
        !            71:               DeviceType == MidiInDevice  ? DD_MIDI_IN_DEVICE_NAME_U  :
        !            72:                                             DD_AUX_DEVICE_NAME_U) +
        !            73:               strlen("\\Device"),
        !            74:              dwId);
        !            75: 
        !            76:     *phDev = INVALID_HANDLE_VALUE;
        !            77: 
        !            78:     *phDev = CreateFile(cDev,
        !            79:                         Access,
        !            80:                         FILE_SHARE_WRITE,
        !            81:                         NULL,
        !            82:                         OPEN_EXISTING,
        !            83:                         Access != GENERIC_READ ? FILE_FLAG_OVERLAPPED : 0,
        !            84:                         NULL);
        !            85: 
        !            86:     //
        !            87:     // Check up on the driver for refusing to open
        !            88:     // multiply for read
        !            89:     //
        !            90: 
        !            91:     WinAssert(!(GetLastError() == ERROR_ACCESS_DENIED &&
        !            92:                 Access == GENERIC_READ));
        !            93: 
        !            94:     //
        !            95:     // Return status to caller
        !            96:     //
        !            97: 
        !            98:     return *phDev != INVALID_HANDLE_VALUE ? MMSYSERR_NOERROR : sndTranslateStatus();
        !            99: }
        !           100: 
        !           101: /****************************************************************************
        !           102:  * @doc INTERNAL
        !           103:  *
        !           104:  * @api void | sndTranslateStatus | This function translates an NT status
        !           105:  *     code into a multi-media error code as far as possible.
        !           106:  *
        !           107:  * @parm NTSTATUS | Status | The NT base operating system return status.
        !           108:  *
        !           109:  *
        !           110:  * @rdesc The multi-media error code.
        !           111:  ***************************************************************************/
        !           112: DWORD sndTranslateStatus(void)
        !           113: {
        !           114: #if DBG
        !           115:     UINT n;
        !           116:     switch (n=GetLastError()) {
        !           117: #else
        !           118:     switch (GetLastError()) {
        !           119: #endif
        !           120:     case NO_ERROR:
        !           121:     case ERROR_IO_PENDING:
        !           122:         return MMSYSERR_NOERROR;
        !           123: 
        !           124:     case ERROR_BUSY:
        !           125:         return MMSYSERR_ALLOCATED;
        !           126: 
        !           127:     case ERROR_NOT_SUPPORTED:
        !           128:     case ERROR_INVALID_FUNCTION:
        !           129:         return MMSYSERR_NOTSUPPORTED;
        !           130: 
        !           131:     case ERROR_NOT_ENOUGH_MEMORY:
        !           132:         return MMSYSERR_NOMEM;
        !           133: 
        !           134:     case ERROR_ACCESS_DENIED:
        !           135:         return MMSYSERR_BADDEVICEID;
        !           136: 
        !           137:     case ERROR_INSUFFICIENT_BUFFER:
        !           138:         return MMSYSERR_INVALPARAM;
        !           139: 
        !           140:     default:
        !           141:         dprintf2(("sndTranslateStatus:  LastError = %d", n));
        !           142:         return MMSYSERR_ERROR;
        !           143:     }
        !           144: }
        !           145: 
        !           146: /****************************************************************************
        !           147:  * @doc INTERNAL
        !           148:  *
        !           149:  * @api DWORD | sndGetNumDevs | This function returns the number of (kernel)
        !           150:  *
        !           151:  * @parm UINT | DeviceType | The Device type
        !           152:  *
        !           153:  * @rdesc The number of devices.
        !           154:  ***************************************************************************/
        !           155: 
        !           156: DWORD sndGetNumDevs(UINT DeviceType)
        !           157: {
        !           158:     //
        !           159:     // Look for devices until we don't find one
        !           160:     //
        !           161:     int i;
        !           162:     HANDLE h;
        !           163: 
        !           164:     for (i=0;
        !           165:          sndOpenDev(DeviceType, i, &h, GENERIC_READ) == MMSYSERR_NOERROR;
        !           166:          i++) {
        !           167: 
        !           168:         //
        !           169:         // BUGBUG try something to make sure !
        !           170:         //
        !           171: 
        !           172:         CloseHandle(h);
        !           173:     }
        !           174:     //
        !           175:     // We incremented i each time we found a good device
        !           176:     //
        !           177: 
        !           178:     return i;
        !           179: }
        !           180: 
        !           181: /****************************************************************************
        !           182:  * @doc INTERNAL
        !           183:  *
        !           184:  * @api DWORD | sndSetData | This function sets the volume given a device id
        !           185:  *                           and could be used for other soft value setting
        !           186:  *                           when only read access is required to the device
        !           187:  *
        !           188:  * @parm UINT | DeviceType | The Device type
        !           189:  *
        !           190:  * @parm UINT | DeviceId | The device id
        !           191:  *
        !           192:  * @parm UINT | Length | Length of data to set
        !           193:  *
        !           194:  * @parm PBYTE | Data | Data to set
        !           195:  *
        !           196:  * @parm ULONG | Ioctl | The Ioctl to use
        !           197:  *
        !           198:  * @rdesc MM... return code.
        !           199:  ***************************************************************************/
        !           200: 
        !           201:  MMRESULT sndSetData(UINT DeviceType, UINT DeviceId, UINT Length, PBYTE Data,
        !           202:                      ULONG Ioctl)
        !           203:  {
        !           204: 
        !           205:     HANDLE hDev;
        !           206:     MMRESULT mRet;
        !           207:     DWORD BytesReturned;
        !           208: 
        !           209:     //
        !           210:     // Open the wave output device
        !           211:     //
        !           212: 
        !           213:     mRet = sndOpenDev(DeviceType, DeviceId, &hDev, GENERIC_READ);
        !           214:     if (mRet != MMSYSERR_NOERROR) {
        !           215:          return mRet;
        !           216:     }
        !           217: 
        !           218:     //
        !           219:     // Set our data.
        !           220:     //
        !           221:     // Setting the overlapped parameter (last) to null means we
        !           222:     // wait until the operation completes.
        !           223:     //
        !           224: 
        !           225:     mRet = DeviceIoControl(hDev, Ioctl, Data, Length, NULL, 0,
        !           226:                            &BytesReturned, NULL) ?
        !           227:            MMSYSERR_NOERROR : sndTranslateStatus();
        !           228: 
        !           229: 
        !           230:     //
        !           231:     // Close our file and return
        !           232:     //
        !           233: 
        !           234:     CloseHandle(hDev);
        !           235: 
        !           236:     return mRet;
        !           237:  }
        !           238: 
        !           239: /****************************************************************************
        !           240:  * @doc INTERNAL
        !           241:  *
        !           242:  * @api DWORD | sndGetData | This function gets data from a given device
        !           243:  *                           specified by device id when read-only access is
        !           244:  *                           sufficient
        !           245:  *
        !           246:  * @parm UINT | DeviceType | The Device type
        !           247:  *
        !           248:  * @parm UINT | DeviceId | The device id
        !           249:  *
        !           250:  * @parm UINT | Length | Length of data to set
        !           251:  *
        !           252:  * @parm PBYTE | Data | Data to set
        !           253:  *
        !           254:  * @parm ULONG | Ioctl | The Ioctl to use
        !           255:  *
        !           256:  * @rdesc MM... return code.
        !           257:  ***************************************************************************/
        !           258: 
        !           259:  MMRESULT sndGetData(UINT DeviceType, UINT DeviceId, UINT Length, PBYTE Data,
        !           260:                      ULONG Ioctl)
        !           261:  {
        !           262: 
        !           263:     HANDLE hDev;
        !           264:     MMRESULT mRet;
        !           265:     DWORD BytesReturned;
        !           266: 
        !           267:     //
        !           268:     // Open the wave output device
        !           269:     //
        !           270: 
        !           271:     mRet = sndOpenDev(DeviceType, DeviceId, &hDev, GENERIC_READ);
        !           272:     if (mRet != MMSYSERR_NOERROR) {
        !           273:          return mRet;
        !           274:     }
        !           275: 
        !           276:     //
        !           277:     // Set our data.
        !           278:     //
        !           279:     // Setting the overlapped parameter (last) to null means we
        !           280:     // wait until the operation completes.
        !           281:     //
        !           282: 
        !           283:     mRet = DeviceIoControl(hDev, Ioctl, NULL, 0, (LPVOID)Data, Length,
        !           284:                            &BytesReturned, NULL) ?
        !           285:            MMSYSERR_NOERROR : sndTranslateStatus();
        !           286: 
        !           287: 
        !           288:     //
        !           289:     // Close our file and return
        !           290:     //
        !           291: 
        !           292:     CloseHandle(hDev);
        !           293: 
        !           294:     return mRet;
        !           295:  }
        !           296: 
        !           297: 
        !           298: /****************************************************************************
        !           299:  * @doc INTERNAL
        !           300:  *
        !           301:  * @api MMRESULT | sndGetHandleData | Get data from a device using its handle
        !           302:  *
        !           303:  * @parm PWAVEALLOC | pClient | Client handle.
        !           304:  *
        !           305:  * @parm DWORD | dwSize | Size of the data
        !           306:  *
        !           307:  * @parm PVOID | pData | Where to put the data.
        !           308:  *
        !           309:  * @parm ULONG | Function | The Ioctl to use
        !           310:  *
        !           311:  * @rdesc MMSYS... return value.
        !           312:  ***************************************************************************/
        !           313: 
        !           314: MMRESULT sndGetHandleData(HANDLE     hDev,
        !           315:                           DWORD      dwSize,
        !           316:                           PVOID      pData,
        !           317:                           ULONG      Ioctl,
        !           318:                           HANDLE     hEvent)
        !           319: {
        !           320:     OVERLAPPED Overlap;
        !           321:     DWORD BytesReturned;
        !           322: 
        !           323:     WinAssert(hDev != NULL);
        !           324: 
        !           325:     memset(&Overlap, 0, sizeof(Overlap));
        !           326: 
        !           327:     Overlap.hEvent = hEvent;
        !           328: 
        !           329:     //
        !           330:     // Issue the IO control.  We must wait with our own event because
        !           331:     // setting the overlapped object to null will complete if other
        !           332:     // IOs complete.
        !           333:     //
        !           334: 
        !           335:     if (!DeviceIoControl(hDev,
        !           336:                          Ioctl,
        !           337:                          NULL,
        !           338:                          0,
        !           339:                          pData,
        !           340:                          dwSize,
        !           341:                          &BytesReturned,
        !           342:                          &Overlap)) {
        !           343:          DWORD cbTransfer;
        !           344: 
        !           345:          //
        !           346:          // Wait for completion if necessary
        !           347:          //
        !           348: 
        !           349:          if (GetLastError() == ERROR_IO_PENDING) {
        !           350:              if (!GetOverlappedResult(hDev, &Overlap, &cbTransfer,
        !           351:                                       TRUE)) {
        !           352:                   return sndTranslateStatus();
        !           353:              }
        !           354:          } else {
        !           355:              return sndTranslateStatus();
        !           356:          }
        !           357:     }
        !           358: 
        !           359:     //
        !           360:     // We'd better peek aleratbly to flush out any IO
        !           361:     // completions so that things like RESET only
        !           362:     // return when all buffers have been completed
        !           363:     //
        !           364:     // This relies on the fact that SleepEx will return
        !           365:     // WAIT_IO_COMPLETION in preference to OK
        !           366:     //
        !           367: 
        !           368:     while (SetEvent(hEvent) &&
        !           369:            WaitForSingleObjectEx(hEvent, 0, TRUE) == WAIT_IO_COMPLETION) {}
        !           370: 
        !           371: 
        !           372:     return MMSYSERR_NOERROR;
        !           373: }
        !           374: 
        !           375: /****************************************************************************
        !           376:  * @doc INTERNAL
        !           377:  *
        !           378:  * @api MMRESULT | sndSetHandleData | Pass data to a device using its handle
        !           379:  *
        !           380:  * @parm PWAVEALLOC | pClient | Client handle.
        !           381:  *
        !           382:  * @parm DWORD | dwSize | Size of the data
        !           383:  *
        !           384:  * @parm PVOID | pData | Data to send.
        !           385:  *
        !           386:  * @parm ULONG | Function | The Ioctl to use
        !           387:  *
        !           388:  * @rdesc MMSYS... return value.
        !           389:  ***************************************************************************/
        !           390: MMRESULT sndSetHandleData(HANDLE     hDev,
        !           391:                           DWORD      dwSize,
        !           392:                           PVOID      pData,
        !           393:                           ULONG      Ioctl,
        !           394:                           HANDLE     hEvent)
        !           395: {
        !           396:     OVERLAPPED Overlap;
        !           397:     DWORD BytesReturned;
        !           398: 
        !           399:     WinAssert(hDev != NULL);
        !           400: 
        !           401:     memset((PVOID)&Overlap, 0, sizeof(Overlap));
        !           402: 
        !           403:     Overlap.hEvent = hEvent;
        !           404: 
        !           405:     //
        !           406:     // Issue the IO control.  We must wait with our own event because
        !           407:     // setting the overlapped object to null will complete if other
        !           408:     // IOs complete.
        !           409:     //
        !           410: 
        !           411:     if (!DeviceIoControl(hDev,
        !           412:                          Ioctl,
        !           413:                          pData,
        !           414:                          dwSize,
        !           415:                          NULL,
        !           416:                          0,
        !           417:                          &BytesReturned,
        !           418:                          &Overlap)) {
        !           419:          DWORD cbTransfer;
        !           420: 
        !           421:          //
        !           422:          // Wait for completion if necessary
        !           423:          //
        !           424: 
        !           425:          if (GetLastError() == ERROR_IO_PENDING) {
        !           426:              if (!GetOverlappedResult(hDev, &Overlap, &cbTransfer,
        !           427:                                       TRUE)) {
        !           428:                   return sndTranslateStatus();
        !           429:              }
        !           430:          } else {
        !           431:              return sndTranslateStatus();
        !           432:          }
        !           433:     }
        !           434: 
        !           435:     //
        !           436:     // We'd better peek aleratbly to flush out any IO
        !           437:     // completions so that things like RESET only
        !           438:     // return when all buffers have been completed
        !           439:     //
        !           440:     // This relies on the fact that SleepEx will return
        !           441:     // WAIT_IO_COMPLETION in preference to OK
        !           442:     //
        !           443: 
        !           444:     while (SleepEx(0, TRUE) == WAIT_IO_COMPLETION) {}
        !           445: 
        !           446:     return MMSYSERR_NOERROR;
        !           447: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.