reactos/dll/win32/mmdrv/common.c

262 lines
6.3 KiB
C
Raw Normal View History

/*
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Multimedia
* FILE: dll/win32/mmdrv/common.c
* PURPOSE: Multimedia User Mode Driver (Common functions)
* PROGRAMMER: Andrew Greenwood
* UPDATE HISTORY:
* Jan 14, 2007: Created
*/
#include "mmdrv.h"
#define NDEBUG
#include <debug.h>
/*
Translates errors to MMRESULT codes.
*/
MMRESULT
ErrorToMmResult(UINT error_code)
{
switch ( error_code )
{
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;
};
/* If all else fails, it's just a plain old error */
return MMSYSERR_ERROR;
}
/*
Obtains a device count for a specific kind of device.
*/
DWORD
GetDeviceCount(DeviceType device_type)
{
UINT index = 0;
HANDLE handle;
/* Cycle through devices until an error occurs */
while ( OpenKernelDevice(device_type, index, GENERIC_READ, &handle) == MMSYSERR_NOERROR )
{
CloseHandle(handle);
index ++;
}
DPRINT("Found %d devices of type %d\n", index, device_type);
return index;
}
/*
Obtains device capabilities. This could either be done as individual
functions for wave, MIDI and aux, or like this. I chose this method as
it centralizes everything.
*/
DWORD
GetDeviceCapabilities(
DeviceType device_type,
Merge from amd64 branch: [SPIDER] 44002 Fix 64 bit build. (Samuel Serapión) [PAINT] 43858 Fix 64 bit warnings. (Samuel Serapión) [RAPPS] 43906 Fix 64 bit build. (Samuel Serapión) [SNDREC32] 44389 Fix 64 bit build. (Samuel Serapión) [TFTP] 41097 Fix pointer to DWORD cast. (Timo Kreuzer) [COMCTL32] 36172 Build as unicode. (Samuel Serapión) [USERMGR] 41098 Fix 2 POINTER<->DWORD casts. (Timo Kreuzer) [d3d9] 38149 Fix pointer<->ULONG cast. (Timo Kreuzer) 43839 Fix 64 bit Build. (Samuel Serapión) [DSOUND] 40753 Make DSDRIVERDESC.dnDevNode a DWORD_PTR and DSPROPERTY.InstanceId a ULONG_PTR. (Timo Kreuzer) [LSASRV] 44037 Fix 64 bit Build. (Samuel Serapión) [MMDRV] 40125 Fix 64bit build. (Samuel Serapión) [MSGINA] 40993 fix 64bit build (Timo Kreuzer) [NETSHELL] 41001 Don't cast the 1st parameter of InterlockedExchange to volatile void **, but to void ** (Timo Kreuzer) [OPENGL32] 36502 No need to assert an offset thats only used in i386 specific code. (Samuel Serapión) [POWRPROF] 41044 Don't cast NULL to DWORD. (Timo Kreuzer) 43860 Don't cast NULL to an integer type. (Samuel Serapión) [PSAPI] 38150 Fix a cast (Timo Kreuzer) [SHELL32] 38355 Use Get/SetWindowLongPtr (Samuel Serapión) 41047 Get rid of deprecated LargeInteger functions and use native int64 math instead. (Timo Kreuzer) 41048 DialogProc returns INT_PTR and not BOOL. Don't cast a pointer to LONG. Use INT_PTR instead of int for pointer math. (Timo Kreuzer) 41049 Change return type of OpenMRUListW and CreateMRUListW to HANDLE, add a comment that CREATEMRULISTW is already defined differently in explorer_new/undoc.h (Timo Kreuzer) 44601 Fix a prototype. Convert RtlLargeInteger to native int64. Fixes 64bit built. (Timo Kreuzer) [WDMAUD.DRV] 41101 Don't cast DWORD to PVOID, use UlongToPtr instead. (Timo Kreuzer) [WS2_32] 35777 fix ws2_32 spec file (Timo kreuzer) 44044 Fix ws2_32 64bit build (1 of 2) (Samuel Serapión) 44045 Fix ws2_32 64bit build (2 of 2) (Samuel Serapión) [WS2_32_NEW] 44389 Fix 64 bit built. (Samuel Serapión) svn path=/trunk/; revision=44602
2009-12-15 15:16:01 +00:00
UINT device_id,
DWORD_PTR capabilities,
DWORD capabilities_size)
{
MMRESULT result;
DWORD ioctl;
HANDLE handle;
DWORD bytes_returned;
BOOL device_io_result;
ASSERT(capabilities);
/* Choose the right IOCTL for the job */
if ( IsWaveDevice(device_type) )
ioctl = IOCTL_WAVE_GET_CAPABILITIES;
else if ( IsMidiDevice(device_type) )
ioctl = IOCTL_MIDI_GET_CAPABILITIES;
else if ( IsAuxDevice(device_type) )
return MMSYSERR_NOTSUPPORTED; /* TODO */
else
return MMSYSERR_NOTSUPPORTED;
result = OpenKernelDevice(device_type,
device_id,
GENERIC_READ,
&handle);
if ( result != MMSYSERR_NOERROR )
{
DPRINT("Failed to open kernel device\n");
return result;
}
device_io_result = DeviceIoControl(handle,
ioctl,
NULL,
0,
(LPVOID) capabilities,
capabilities_size,
&bytes_returned,
NULL);
/* Translate result */
if ( device_io_result )
result = MMSYSERR_NOERROR;
else
result = ErrorToMmResult(GetLastError());
/* Clean up and return */
CloseKernelDevice(handle);
return result;
}
/*
A wrapper around OpenKernelDevice that creates a session,
opens the kernel device, initializes session data and notifies
the client (application) that the device has been opened. Again,
this supports any device type and the only real difference is
the open descriptor.
*/
DWORD
OpenDevice(
DeviceType device_type,
Merge from amd64 branch: [SPIDER] 44002 Fix 64 bit build. (Samuel Serapión) [PAINT] 43858 Fix 64 bit warnings. (Samuel Serapión) [RAPPS] 43906 Fix 64 bit build. (Samuel Serapión) [SNDREC32] 44389 Fix 64 bit build. (Samuel Serapión) [TFTP] 41097 Fix pointer to DWORD cast. (Timo Kreuzer) [COMCTL32] 36172 Build as unicode. (Samuel Serapión) [USERMGR] 41098 Fix 2 POINTER<->DWORD casts. (Timo Kreuzer) [d3d9] 38149 Fix pointer<->ULONG cast. (Timo Kreuzer) 43839 Fix 64 bit Build. (Samuel Serapión) [DSOUND] 40753 Make DSDRIVERDESC.dnDevNode a DWORD_PTR and DSPROPERTY.InstanceId a ULONG_PTR. (Timo Kreuzer) [LSASRV] 44037 Fix 64 bit Build. (Samuel Serapión) [MMDRV] 40125 Fix 64bit build. (Samuel Serapión) [MSGINA] 40993 fix 64bit build (Timo Kreuzer) [NETSHELL] 41001 Don't cast the 1st parameter of InterlockedExchange to volatile void **, but to void ** (Timo Kreuzer) [OPENGL32] 36502 No need to assert an offset thats only used in i386 specific code. (Samuel Serapión) [POWRPROF] 41044 Don't cast NULL to DWORD. (Timo Kreuzer) 43860 Don't cast NULL to an integer type. (Samuel Serapión) [PSAPI] 38150 Fix a cast (Timo Kreuzer) [SHELL32] 38355 Use Get/SetWindowLongPtr (Samuel Serapión) 41047 Get rid of deprecated LargeInteger functions and use native int64 math instead. (Timo Kreuzer) 41048 DialogProc returns INT_PTR and not BOOL. Don't cast a pointer to LONG. Use INT_PTR instead of int for pointer math. (Timo Kreuzer) 41049 Change return type of OpenMRUListW and CreateMRUListW to HANDLE, add a comment that CREATEMRULISTW is already defined differently in explorer_new/undoc.h (Timo Kreuzer) 44601 Fix a prototype. Convert RtlLargeInteger to native int64. Fixes 64bit built. (Timo Kreuzer) [WDMAUD.DRV] 41101 Don't cast DWORD to PVOID, use UlongToPtr instead. (Timo Kreuzer) [WS2_32] 35777 fix ws2_32 spec file (Timo kreuzer) 44044 Fix ws2_32 64bit build (1 of 2) (Samuel Serapión) 44045 Fix ws2_32 64bit build (2 of 2) (Samuel Serapión) [WS2_32_NEW] 44389 Fix 64 bit built. (Samuel Serapión) svn path=/trunk/; revision=44602
2009-12-15 15:16:01 +00:00
UINT device_id,
PVOID open_descriptor,
DWORD flags,
Merge from amd64 branch: [SPIDER] 44002 Fix 64 bit build. (Samuel Serapión) [PAINT] 43858 Fix 64 bit warnings. (Samuel Serapión) [RAPPS] 43906 Fix 64 bit build. (Samuel Serapión) [SNDREC32] 44389 Fix 64 bit build. (Samuel Serapión) [TFTP] 41097 Fix pointer to DWORD cast. (Timo Kreuzer) [COMCTL32] 36172 Build as unicode. (Samuel Serapión) [USERMGR] 41098 Fix 2 POINTER<->DWORD casts. (Timo Kreuzer) [d3d9] 38149 Fix pointer<->ULONG cast. (Timo Kreuzer) 43839 Fix 64 bit Build. (Samuel Serapión) [DSOUND] 40753 Make DSDRIVERDESC.dnDevNode a DWORD_PTR and DSPROPERTY.InstanceId a ULONG_PTR. (Timo Kreuzer) [LSASRV] 44037 Fix 64 bit Build. (Samuel Serapión) [MMDRV] 40125 Fix 64bit build. (Samuel Serapión) [MSGINA] 40993 fix 64bit build (Timo Kreuzer) [NETSHELL] 41001 Don't cast the 1st parameter of InterlockedExchange to volatile void **, but to void ** (Timo Kreuzer) [OPENGL32] 36502 No need to assert an offset thats only used in i386 specific code. (Samuel Serapión) [POWRPROF] 41044 Don't cast NULL to DWORD. (Timo Kreuzer) 43860 Don't cast NULL to an integer type. (Samuel Serapión) [PSAPI] 38150 Fix a cast (Timo Kreuzer) [SHELL32] 38355 Use Get/SetWindowLongPtr (Samuel Serapión) 41047 Get rid of deprecated LargeInteger functions and use native int64 math instead. (Timo Kreuzer) 41048 DialogProc returns INT_PTR and not BOOL. Don't cast a pointer to LONG. Use INT_PTR instead of int for pointer math. (Timo Kreuzer) 41049 Change return type of OpenMRUListW and CreateMRUListW to HANDLE, add a comment that CREATEMRULISTW is already defined differently in explorer_new/undoc.h (Timo Kreuzer) 44601 Fix a prototype. Convert RtlLargeInteger to native int64. Fixes 64bit built. (Timo Kreuzer) [WDMAUD.DRV] 41101 Don't cast DWORD to PVOID, use UlongToPtr instead. (Timo Kreuzer) [WS2_32] 35777 fix ws2_32 spec file (Timo kreuzer) 44044 Fix ws2_32 64bit build (1 of 2) (Samuel Serapión) 44045 Fix ws2_32 64bit build (2 of 2) (Samuel Serapión) [WS2_32_NEW] 44389 Fix 64 bit built. (Samuel Serapión) svn path=/trunk/; revision=44602
2009-12-15 15:16:01 +00:00
DWORD_PTR private_handle)
{
SessionInfo* session_info;
MMRESULT result;
DWORD message;
/* This will automatically check for duplicate sessions */
result = CreateSession(device_type, device_id, &session_info);
if ( result != MMSYSERR_NOERROR )
{
DPRINT("Couldn't allocate session info\n");
return result;
}
result = OpenKernelDevice(device_type,
device_id,
GENERIC_READ,
&session_info->kernel_device_handle);
if ( result != MMSYSERR_NOERROR )
{
DPRINT("Failed to open kernel device\n");
DestroySession(session_info);
return result;
}
/* Set common session data */
session_info->flags = flags;
/* Set wave/MIDI specific data */
if ( IsWaveDevice(device_type) )
{
LPWAVEOPENDESC wave_open_desc = (LPWAVEOPENDESC) open_descriptor;
session_info->callback = wave_open_desc->dwCallback;
session_info->mme_wave_handle = wave_open_desc->hWave;
session_info->app_user_data = wave_open_desc->dwInstance;
}
else
{
DPRINT("Only wave devices are supported at present!\n");
DestroySession(session_info);
return MMSYSERR_NOTSUPPORTED;
}
/* Start the processing thread */
result = StartSessionThread(session_info);
if ( result != MMSYSERR_NOERROR )
{
DestroySession(session_info);
return result;
}
/* Store the session info */
*((SessionInfo**)private_handle) = session_info;
/* Send the right message */
message = (device_type == WaveOutDevice) ? WOM_OPEN :
(device_type == WaveInDevice) ? WIM_OPEN :
(device_type == MidiOutDevice) ? MOM_OPEN :
(device_type == MidiInDevice) ? MIM_OPEN : 0xFFFFFFFF;
NotifyClient(session_info, message, 0, 0);
return MMSYSERR_NOERROR;
}
/*
Attempts to close a device. This can fail if playback/recording has
not been stopped. We need to make sure it's safe to destroy the
session as well (mainly by killing the session thread.)
*/
DWORD
CloseDevice(
Merge from amd64 branch: [SPIDER] 44002 Fix 64 bit build. (Samuel Serapión) [PAINT] 43858 Fix 64 bit warnings. (Samuel Serapión) [RAPPS] 43906 Fix 64 bit build. (Samuel Serapión) [SNDREC32] 44389 Fix 64 bit build. (Samuel Serapión) [TFTP] 41097 Fix pointer to DWORD cast. (Timo Kreuzer) [COMCTL32] 36172 Build as unicode. (Samuel Serapión) [USERMGR] 41098 Fix 2 POINTER<->DWORD casts. (Timo Kreuzer) [d3d9] 38149 Fix pointer<->ULONG cast. (Timo Kreuzer) 43839 Fix 64 bit Build. (Samuel Serapión) [DSOUND] 40753 Make DSDRIVERDESC.dnDevNode a DWORD_PTR and DSPROPERTY.InstanceId a ULONG_PTR. (Timo Kreuzer) [LSASRV] 44037 Fix 64 bit Build. (Samuel Serapión) [MMDRV] 40125 Fix 64bit build. (Samuel Serapión) [MSGINA] 40993 fix 64bit build (Timo Kreuzer) [NETSHELL] 41001 Don't cast the 1st parameter of InterlockedExchange to volatile void **, but to void ** (Timo Kreuzer) [OPENGL32] 36502 No need to assert an offset thats only used in i386 specific code. (Samuel Serapión) [POWRPROF] 41044 Don't cast NULL to DWORD. (Timo Kreuzer) 43860 Don't cast NULL to an integer type. (Samuel Serapión) [PSAPI] 38150 Fix a cast (Timo Kreuzer) [SHELL32] 38355 Use Get/SetWindowLongPtr (Samuel Serapión) 41047 Get rid of deprecated LargeInteger functions and use native int64 math instead. (Timo Kreuzer) 41048 DialogProc returns INT_PTR and not BOOL. Don't cast a pointer to LONG. Use INT_PTR instead of int for pointer math. (Timo Kreuzer) 41049 Change return type of OpenMRUListW and CreateMRUListW to HANDLE, add a comment that CREATEMRULISTW is already defined differently in explorer_new/undoc.h (Timo Kreuzer) 44601 Fix a prototype. Convert RtlLargeInteger to native int64. Fixes 64bit built. (Timo Kreuzer) [WDMAUD.DRV] 41101 Don't cast DWORD to PVOID, use UlongToPtr instead. (Timo Kreuzer) [WS2_32] 35777 fix ws2_32 spec file (Timo kreuzer) 44044 Fix ws2_32 64bit build (1 of 2) (Samuel Serapión) 44045 Fix ws2_32 64bit build (2 of 2) (Samuel Serapión) [WS2_32_NEW] 44389 Fix 64 bit built. (Samuel Serapión) svn path=/trunk/; revision=44602
2009-12-15 15:16:01 +00:00
DWORD_PTR private_handle)
{
MMRESULT result;
SessionInfo* session_info = (SessionInfo*) private_handle;
/* TODO: Maybe this is best off inside the playback thread? */
ASSERT(session_info);
result = CallSessionThread(session_info, WODM_CLOSE, 0);
if ( result == MMSYSERR_NOERROR )
{
/* TODO: Wait for it to be safe to terminate */
CloseKernelDevice(session_info->kernel_device_handle);
DestroySession(session_info);
}
return result;
}