Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

400 lines
11 KiB

/************************************************************************/
/*
** Copyright (c) 1985-1999 Microsoft Corporation
**
** Title: drvproc.c - Multimedia Systems Media Control Interface
** waveform audio driver for RIFF wave files.
**
** Version: 1.00
**
** Date: 18-Apr-1990
**
** Author: ROBWI
*/
/************************************************************************/
/*
** Change log:
**
** DATE REV DESCRIPTION
** ----------- ----- ------------------------------------------
** 10-Jan-1992 MikeTri Ported to NT
** @@@ need to change slash slash comments to slash star
*/
/************************************************************************/
// #define DEBUGLEVELVAR mciwaveDebugLevel
#define UNICODE
#define NOGDICAPMASKS
#define NOVIRTUALKEYCODES
#define NOWINSTYLES
#define NOSYSMETRICS
#define NOMENUS
#define NOICONS
#define NOKEYSTATES
#define NOSYSCOMMANDS
#define NORASTEROPS
#define NOSHOWWINDOW
#define OEMRESOURCE
#define NOATOM
#define NOCLIPBOARD
#define NOCOLOR
#define NOCTLMGR
#define NODRAWTEXT
#define NOGDI
#define NOKERNEL
#define NONLS
#define NOMB
#define NOMEMMGR
#define NOMETAFILE
#define NOMINMAX
#define NOOPENFILE
#define NOSCROLL
#define NOTEXTMETRIC
#define NOWH
#define NOWINOFFSETS
#define NOCOMM
#define NOKANJI
#define NOHELP
#define NOPROFILER
#define NODEFERWINDOWPOS
#define MMNOMMIO
#define MMNOJOY
#define MMNOTIMER
#define MMNOAUX
#define MMNOMIDI
#include <windows.h>
#include "mciwave.h"
#include <mmddk.h>
/************************************************************************/
/*
** This constant is used for a return value when opening the MCI
** driver for configuration. Setting the high-order word of the
** dwDriverID identifies configuration opens.
*/
#define CONFIG_ID 10000L
#define MAXINISTRING 32
/************************************************************************/
/*
** wTableEntry Contains the wave command table identifier.
*/
#ifndef MCI_NO_COMMAND_TABLE
#define MCI_NO_COMMAND_TABLE -1
#endif
PRIVATE UINT wTableEntry = MCI_NO_COMMAND_TABLE;
/************************************************************************/
/*
@doc INTERNAL MCIWAVE
@func UINT | GetAudioSeconds |
This converts the given string to a UINT which represents the
number of seconds of audio buffers that should be available. The
number is bounded by the minimum and maximum number of seconds as
defined by MinAudioSeconds and MaxAudioSeconds.
@parm LPCSTR | lszNumber |
Points to the string containing the string representation of the
number to convert.
@rdesc Returns the int representation of the number passed. If the number
is out of range, the default number of audio seconds is returned.
*/
PUBLIC UINT PASCAL FAR GetAudioSeconds(
LPCWSTR lszNumber)
{
UINT wSeconds;
for (wSeconds = 0;
(wSeconds < MaxAudioSeconds) && (*lszNumber >= TEXT('0')) && (*lszNumber <= TEXT('9'));
lszNumber++)
wSeconds = wSeconds * 10 + (*lszNumber - '0');
if ((wSeconds > MaxAudioSeconds) || (wSeconds < MinAudioSeconds))
wSeconds = AudioSecondsDefault;
return wSeconds;
}
/************************************************************************/
/*
@doc INTERNAL MCIWAVE
@api BOOL | mwLoadDriver |
This function is called in response to a <m>DRV_LOAD<d> message, and
performs driver initialization. It determines the total number of
input and output devices for use in trying to open any device.
The function then tries to register the extended wave command table.
@rdesc Returns TRUE on success, else FALSE.
*/
PRIVATE BOOL PASCAL NEAR mwLoadDriver(
VOID)
{
WCHAR aszResource[MAXINISTRING];
dprintf3(("mwLoadDriver called"));
cWaveOutMax = waveOutGetNumDevs();
cWaveInMax = waveInGetNumDevs();
#if DBG
if (cWaveOutMax + cWaveInMax) {
dprintf4(("Number of Wave Out devices = %d, Wave In devices = %d", cWaveOutMax, cWaveInMax));
} else {
dprintf1(("NO wave input or output devices detected"));
}
#endif
if (LoadString( hModuleInstance,
IDS_COMMANDS,
aszResource,
sizeof(aszResource) / sizeof(WCHAR) ))
{
wTableEntry = mciLoadCommandResource(hModuleInstance, aszResource, 0);
if (wTableEntry != MCI_NO_COMMAND_TABLE) {
dprintf4(("Loaded MCIWAVE command table, table number %d", wTableEntry));
return TRUE;
}
#if DBG
else
dprintf1(("mwLoadDriver: mciLoadCommandResource failed"));
}
else
{
dprintf1(("mwLoadDriver: LoadString of command table identifier failed"));
#endif
}
dprintf1(("mwLoadDriver returning FALSE"));
return FALSE;
}
/************************************************************************/
/*
@doc INTERNAL MCIWAVE
@api BOOL | mwFreeDriver |
Perform driver cleanup in response to DRV_FREE message. This is only
called at driver unload time if a previous DRV_LOAD message succeeded.
@rdesc Returns TRUE always.
*/
PRIVATE BOOL PASCAL NEAR mwFreeDriver(
VOID)
{
if (wTableEntry != MCI_NO_COMMAND_TABLE) {
mciFreeCommandResource(wTableEntry);
wTableEntry = MCI_NO_COMMAND_TABLE;
}
return TRUE;
}
/************************************************************************/
/*
@doc INTERNAL MCIWAVE
@api LRESULT | DriverProc |
The entry point for an installable driver.
@parm DWORD | dDriverId |
For most messages, <p>dDriverId<d> is the DWORD value that the driver
returns in response to a <m>DRV_OPEN<d> message. Each time that the
driver is opened, through the DrvOpen API, the driver receives a
<m>DRV_OPEN<d> message and can return an arbitrary, non-zero, value.
The installable driver interface saves this value and returns a unique
driver handle to the application. Whenever the application sends a
message to the driver using the driver handle, the interface routes the
message to this entry point and passes the corresponding
<p>dDriverId<d>.
This mechanism allows the driver to use the same or different
identifiers for multiple opens but ensures that driver handles are
unique at the application interface layer.
The following messages are not related to a particular open instance
of the driver. For these messages, the <p>dDriverId<d> will always
be ZERO: <m>DRV_LOAD<d>, <m>DRV_FREE<d>, <m>DRV_ENABLE<d>,
<m>DRV_DISABLE<d>, <m>DRV_OPEN<d>.
@parm HANDLE | hDriver |
This is the handle returned to the application by the driver interface.
@parm UINT | wMessage |
The requested action to be performed. Message values below
<m>DRV_RESERVED<d> are used for globally defined messages. Message
values from <m>DRV_RESERVED<d> to <m>DRV_USER<d> are used for defined
driver portocols. Messages above <m>DRV_USER<d> are used for driver
specific messages.
@flag DRV_LOAD |
Load the driver.
@flag DRV_FREE |
Free the driver.
@flag DRV_OPEN |
Open the driver. If <p>dParam2<d> is NULL, the driver is being
opened for configuration, else the parameter points to an open
parameters block. The command line in the open parameters optionally
contains a replacement for the default audio seconds parameter. If so,
the current default is replaced with this new number.
The rest of the open parameters block is filled in with the driver's
extended command table and device type. The device ID is then
returned.
@flag DRV_CLOSE |
Close the driver. Returns TRUE.
@flag DRV_QUERYCONFIGURE |
Query as to whether the driver can be configured. Returns TRUE.
@flag DRV_CONFIGURE |
After verifying <p>dParam1<d> and <p>dParam2<d>, configure the
driver. Opens the driver configuration dialog.
@flag DRV_ENABLE |
Enable the driver. Use DefDriverProc.
@flag DRV_DISABLE |
Disable the driver. Use DefDriverProc.
@parm LPARAM | lParam1 |
Data for this message. Defined separately for each message.
@parm LPARAM | lParam2 |
Data for this message. Defined separately for each message.
@rdesc Defined separately for each message.
*/
#if 0
PUBLIC LRESULT PASCAL DefDriverProc(
DWORD dDriverID,
HANDLE hDriver,
UINT wMessage,
LONG lParam1,
LONG lParam2);
#endif
PUBLIC LRESULT PASCAL DriverProc(
DWORD dDriverID,
HANDLE hDriver,
UINT wMessage,
DWORD_PTR lParam1,
DWORD_PTR lParam2)
{
LPMCI_OPEN_DRIVER_PARMS lpOpen;
switch (wMessage) {
case DRV_LOAD:
return (LRESULT)(LONG)mwLoadDriver();
case DRV_FREE:
return (LRESULT)(LONG)mwFreeDriver();
case DRV_OPEN:
if (!(LONG)lParam2)
return (LRESULT)CONFIG_ID;
lpOpen = (LPMCI_OPEN_DRIVER_PARMS)lParam2;
if (lpOpen->lpstrParams != NULL)
wAudioSeconds = GetAudioSeconds(lpOpen->lpstrParams);
else
wAudioSeconds = AudioSecondsDefault;
lpOpen->wCustomCommandTable = wTableEntry;
lpOpen->wType = MCI_DEVTYPE_WAVEFORM_AUDIO;
return (LRESULT)(LONG)lpOpen->wDeviceID;
case DRV_CLOSE:
case DRV_QUERYCONFIGURE:
return (LRESULT)1;
case DRV_INSTALL:
case DRV_REMOVE:
return (LRESULT)DRVCNF_OK;
case DRV_CONFIGURE:
if ((LONG)lParam2 && (LONG)lParam1 && (((LPDRVCONFIGINFO)lParam2)->dwDCISize == sizeof(DRVCONFIGINFO)))
return (LRESULT)(LONG)Config((HWND)lParam1, (LPDRVCONFIGINFO)lParam2, hModuleInstance);
return (LRESULT)DRVCNF_CANCEL;
default:
if (!HIWORD(dDriverID) && wMessage >= DRV_MCI_FIRST && wMessage <= DRV_MCI_LAST)
return mciDriverEntry((WORD)dDriverID, wMessage, (DWORD)lParam1, (LPMCI_GENERIC_PARMS)lParam2);
else
return DefDriverProc(dDriverID, hDriver, wMessage, lParam1, lParam2);
}
}
/**************************************************************************
@doc EXTERNAL
@api BOOL | DllInstanceInit | This procedure is called whenever a
process attaches or detaches from the DLL.
@parm PVOID | hModule | Handle of the DLL.
@parm ULONG | Reason | What the reason for the call is.
@parm PCONTEXT | pContext | Some random other information.
@rdesc The return value is TRUE if the initialisation completed ok,
FALSE if not.
**************************************************************************/
BOOL DllInstanceInit(PVOID hModule, ULONG Reason, PCONTEXT pContext)
{
UNREFERENCED_PARAMETER(pContext);
if (Reason == DLL_PROCESS_ATTACH) {
#if DBG
WCHAR strname[50];
#endif
DisableThreadLibraryCalls(hModule);
mciwaveInitDebugLevel ();
InitCrit();
hModuleInstance = hModule;
#if DBG
GetModuleFileName(NULL, strname, sizeof(strname) / sizeof(WCHAR) );
dprintf2(("Process attaching, exe=%ls (Pid %x Tid %x)", strname, GetCurrentProcessId(), GetCurrentThreadId()));
dprintf2((" starting debug level=%d", mciwaveDebugLevel));
#endif
} else if (Reason == DLL_PROCESS_DETACH) {
dprintf2(("Process ending (Pid %x Tid %x)", GetCurrentProcessId(), GetCurrentThreadId()));
DeleteCrit(); // Something nasty happens if we don't do this
} else {
dprintf2(("DllInstanceInit - reason %d", Reason));
}
return TRUE;
}
/************************************************************************/