⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drvutil.c

📁 Windows NT声卡驱动VXD
💻 C
字号:
/****************************************************************************
 *
 *   drvutil.c
 *
 *   Multimedia kernel driver support component (esddrv)
 *
 *   Copyright (c) Microsoft Corporation 1992 - 1995. All rights reserved.
 *
 *   Support functions common to multiple multi-media drivers :
 *
 *   -- Open a device
 *   -- Translate a kernel IO return code to a multi-media return code
 *   -- Count the number of devices of a given type
 *   -- Set and Get data synchronously to a kernel device
 *
 *   History
 *      01-Feb-1992 - Robin Speed (RobinSp) wrote it
 *      04-Feb-1992 - Reviewed by SteveDav
 *
 ***************************************************************************/

#include "esddrv.h"
#include <ntddwave.h>
#include <ntddmidi.h>
#include <ntddaux.h>

/****************************************************************************
 * @doc INTERNAL
 *
 * @api MMRESULT | sndOpenDev | Open the kernel driver device corresponding
 *       to a logical wave device id
 *
 * @parm UINT | DeviceType | The type of device
 *
 * @parm DWORD | dwId | The device id
 *
 * @parm PHANDLE | phDev | Where to return the kernel device handle
 *
 * @parm ACCESS_MASK | Access | The desired access
 *
 * @comm For our sound devices the only relevant access are read and
 *    read/write.  Device should ALWAYS allow opens for read unless some
 *    resource or access-rights restriction occurs.
 ***************************************************************************/
MMRESULT sndOpenDev(UINT DeviceType, DWORD dwId,
                    PHANDLE phDev, DWORD Access)
{
    WCHAR cDev[SOUND_MAX_DEVICE_NAME];

    WinAssert(DeviceType == WaveOutDevice ||
              DeviceType == WaveInDevice  ||
              DeviceType == MidiOutDevice ||
              DeviceType == MidiInDevice  ||
              DeviceType == AuxDevice);

    *phDev = INVALID_HANDLE_VALUE;  // Always initialise the return value

    //
    // Check it's not out of range
    //

    if (dwId > SOUND_MAX_DEVICES) {
        return MMSYSERR_BADDEVICEID;
    }
    //
    // Create the device name and open it - remove '\Device'
    //

    wsprintf(cDev, L"\\\\.%ls%d",
             (DeviceType == WaveOutDevice ? DD_WAVE_OUT_DEVICE_NAME_U :
              DeviceType == WaveInDevice  ? DD_WAVE_IN_DEVICE_NAME_U  :
              DeviceType == MidiOutDevice ? DD_MIDI_OUT_DEVICE_NAME_U :
              DeviceType == MidiInDevice  ? DD_MIDI_IN_DEVICE_NAME_U  :
                                            DD_AUX_DEVICE_NAME_U) +
              strlen("\\Device"),
             dwId);

    *phDev = CreateFile(cDev,
                        Access,
                        FILE_SHARE_WRITE,
                        NULL,
                        OPEN_EXISTING,
                        Access != GENERIC_READ ? FILE_FLAG_OVERLAPPED : 0,
                        NULL);

    //
    // Check up on the driver for refusing to open
    // multiply for read
    //

    WinAssert(!(GetLastError() == ERROR_ACCESS_DENIED &&
                Access == GENERIC_READ));

    //
    // Return status to caller
    //

    return *phDev != INVALID_HANDLE_VALUE ? MMSYSERR_NOERROR : sndTranslateStatus();
}

/****************************************************************************
 * @doc INTERNAL
 *
 * @api void | sndTranslateStatus | This function translates an NT status
 *     code into a multi-media error code as far as possible.
 *
 * @parm NTSTATUS | Status | The NT base operating system return status.
 *
 *
 * @rdesc The multi-media error code.
 ***************************************************************************/
DWORD sndTranslateStatus(void)
{
#if DBG
    UINT n;
    switch (n=GetLastError()) {
#else
    switch (GetLastError()) {
#endif
    case NO_ERROR:
    case ERROR_IO_PENDING:
        return MMSYSERR_NOERROR;

    case ERROR_BUSY:
        return MMSYSERR_ALLOCATED;

    case ERROR_NOT_SUPPORTED:
    case ERROR_INVALID_FUNCTION:
        return MMSYSERR_NOTSUPPORTED;

    case ERROR_NOT_ENOUGH_MEMORY:
        return MMSYSERR_NOMEM;

    case ERROR_ACCESS_DENIED:
        return MMSYSERR_BADDEVICEID;

    case ERROR_INSUFFICIENT_BUFFER:
        return MMSYSERR_INVALPARAM;

    default:
        dprintf2(("sndTranslateStatus:  LastError = %d", n));
        return MMSYSERR_ERROR;
    }
}

/****************************************************************************
 * @doc INTERNAL
 *
 * @api DWORD | sndGetNumDevs | This function returns the number of (kernel)
 *
 * @parm UINT | DeviceType | The Device type
 *
 * @rdesc The number of devices.
 ***************************************************************************/

DWORD sndGetNumDevs(UINT DeviceType)
{
    //
    // Look for devices until we don't find one
    //
    int i;
    HANDLE h;

    for (i=0;
         sndOpenDev(DeviceType, i, &h, GENERIC_READ) == MMSYSERR_NOERROR;
         i++) {

        //
        // BUGBUG try something to make sure !
        //

        CloseHandle(h);
    }
    //
    // We incremented i each time we found a good device
    //

    return i;
}

/****************************************************************************
 * @doc INTERNAL
 *
 * @api DWORD | sndSetData | This function sets the volume given a device id
 *                           and could be used for other soft value setting
 *                           when only read access is required to the device
 *
 * @parm UINT | DeviceType | The Device type
 *
 * @parm UINT | DeviceId | The device id
 *
 * @parm UINT | Length | Length of data to set
 *
 * @parm PBYTE | Data | Data to set
 *
 * @parm ULONG | Ioctl | The Ioctl to use
 *
 * @rdesc MM... return code.
 ***************************************************************************/

MMRESULT sndSetData(UINT DeviceType, UINT DeviceId, UINT Length, PBYTE Data,
                     ULONG Ioctl)
{
//
//    HANDLE hDev;
//    MMRESULT mRet;
//    DWORD BytesReturned;
//
//    //
//    // Open the wave output device
//    //
//
//    mRet = sndOpenDev(DeviceType, DeviceId, &hDev, GENERIC_READ);
//    if (mRet != MMSYSERR_NOERROR) {
//         return mRet;
//    }
//
//    //
//    // Set our data.
//    //
//    // Setting the overlapped parameter (last) to null means we
//    // wait until the operation completes.
//    //
//
////    mRet = DeviceIoControl(hDev, Ioctl, Data, Length, NULL, 0,
////                           &BytesReturned, NULL) ?
////           MMSYSERR_NOERROR : sndTranslateStatus();
//	mRet = MMSYSERROR_NOERROR;
//
//
//    //
//    // Close our file and return
//    //
//
//    CloseHandle(hDev);
//
//    return mRet;
	return MMSYSERR_NOERROR;
}

/****************************************************************************
 * @doc INTERNAL
 *
 * @api DWORD | sndGetData | This function gets data from a given device
 *                           specified by device id when read-only access is
 *                           sufficient
 *
 * @parm UINT | DeviceType | The Device type
 *
 * @parm UINT | DeviceId | The device id
 *
 * @parm UINT | Length | Length of data to set
 *
 * @parm PBYTE | Data | Data to set
 *
 * @parm ULONG | Ioctl | The Ioctl to use
 *
 * @rdesc MM... return code.
 ***************************************************************************/

MMRESULT sndGetData(UINT DeviceType, UINT DeviceId, UINT Length, PBYTE Data,
                     ULONG Ioctl)
{
//
//    HANDLE hDev;
//    MMRESULT mRet;
//    DWORD BytesReturned;
//
//    //
//    // Open the wave output device
//    //
//
//    mRet = sndOpenDev(DeviceType, DeviceId, &hDev, GENERIC_READ);
//    if (mRet != MMSYSERR_NOERROR) {
//         return mRet;
//    }
//
//    //
//    // Set our data.
//    //
//    // Setting the overlapped parameter (last) to null means we
//    // wait until the operation completes.
//    //
//
//    mRet = DeviceIoControl(hDev, Ioctl, NULL, 0, (LPVOID)Data, Length,
//                           &BytesReturned, NULL) ?
//           MMSYSERR_NOERROR : sndTranslateStatus();
//
//
//    //
//    // Close our file and return
//    //
//
//    CloseHandle(hDev);
//
//    return mRet;
	return MMSYSERR_NOERROR;
}


/****************************************************************************
 * @doc INTERNAL
 *
 * @api MMRESULT | sndGetHandleData | Get data from a device using its handle
 *
 * @parm PWAVEALLOC | pClient | Client handle.
 *
 * @parm DWORD | dwSize | Size of the data
 *
 * @parm PVOID | pData | Where to put the data.
 *
 * @parm ULONG | Function | The Ioctl to use
 *
 * @rdesc MMSYS... return value.
 ***************************************************************************/

MMRESULT sndGetHandleData(HANDLE     hDev,
                          DWORD      dwSize,
                          PVOID      pData,
                          ULONG      Ioctl,
                          HANDLE     hEvent)
{
//    OVERLAPPED Overlap;
//    DWORD BytesReturned;
//
//    WinAssert(hDev != NULL);
//
//    memset(&Overlap, 0, sizeof(Overlap));
//
//    Overlap.hEvent = hEvent;
//
//    //
//    // Issue the IO control.  We must wait with our own event because
//    // setting the overlapped object to null will complete if other
//    // IOs complete.
//    //
//
//    if (!DeviceIoControl(hDev,
//                         Ioctl,
//                         NULL,
//                         0,
//                         pData,
//                         dwSize,
//                         &BytesReturned,
//                         &Overlap)) {
//         DWORD cbTransfer;
//
//         //
//         // Wait for completion if necessary
//         //
//
//         if (GetLastError() == ERROR_IO_PENDING) {
//             if (!GetOverlappedResult(hDev, &Overlap, &cbTransfer,
//                                      TRUE)) {
//                  return sndTranslateStatus();
//             }
//         } else {
//             return sndTranslateStatus();
//         }
//    }
//
//    //
//    // We'd better peek aleratbly to flush out any IO
//    // completions so that things like RESET only
//    // return when all buffers have been completed
//    //
//    // This relies on the fact that SleepEx will return
//    // WAIT_IO_COMPLETION in preference to OK
//    //
//
//    while (SetEvent(hEvent) &&
//           WaitForSingleObjectEx(hEvent, 0, TRUE) == WAIT_IO_COMPLETION) {}


    return MMSYSERR_NOERROR;
}

/****************************************************************************
 * @doc INTERNAL
 *
 * @api MMRESULT | sndSetHandleData | Pass data to a device using its handle
 *
 * @parm PWAVEALLOC | pClient | Client handle.
 *
 * @parm DWORD | dwSize | Size of the data
 *
 * @parm PVOID | pData | Data to send.
 *
 * @parm ULONG | Function | The Ioctl to use
 *
 * @rdesc MMSYS... return value.
 ***************************************************************************/
MMRESULT sndSetHandleData(HANDLE     hDev,
                          DWORD      dwSize,
                          PVOID      pData,
                          ULONG      Ioctl,
                          HANDLE     hEvent)
{
//    OVERLAPPED Overlap;
//    DWORD BytesReturned;
//
//    WinAssert(hDev != NULL);
//
//    memset((PVOID)&Overlap, 0, sizeof(Overlap));
//
//    Overlap.hEvent = hEvent;
//
//    //
//    // Issue the IO control.  We must wait with our own event because
//    // setting the overlapped object to null will complete if other
//    // IOs complete.
//    //
//
//    if (!DeviceIoControl(hDev,
//                         Ioctl,
//                         pData,
//                         dwSize,
//                         NULL,
//                         0,
//                         &BytesReturned,
//                         &Overlap)) {
//         DWORD cbTransfer;
//
//         //
//         // Wait for completion if necessary
//         //
//
//         if (GetLastError() == ERROR_IO_PENDING) {
//             if (!GetOverlappedResult(hDev, &Overlap, &cbTransfer,
//                                      TRUE)) {
//                  return sndTranslateStatus();
//             }
//         } else {
//             return sndTranslateStatus();
//         }
//    }
//
//    //
//    // We'd better peek alertably to flush out any IO
//    // completions so that things like RESET only
//    // return when all buffers have been completed
//    //
//    // This relies on the fact that SleepEx will return
//    // WAIT_IO_COMPLETION in preference to OK
//    //
//
//    while (SleepEx(0, TRUE) == WAIT_IO_COMPLETION) {}

    return MMSYSERR_NOERROR;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -