mirror of
https://github.com/reactos/reactos.git
synced 2024-10-31 03:48:17 +00:00
203 lines
6.3 KiB
C
203 lines
6.3 KiB
C
/*
|
|
* PROJECT: ReactOS Sound System "MME Buddy" NT4 Library
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: lib/drivers/sound/mment4/detect.c
|
|
*
|
|
* PURPOSE: Assists in locating Windows NT4 compatible sound devices,
|
|
* which mostly use the same device naming convention and/or
|
|
* store their created device names within their service key
|
|
* within the registry.
|
|
*
|
|
* PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <mment4.h>
|
|
#include <mmebuddy_debug.h>
|
|
|
|
/*
|
|
This is the "nice" way to discover audio devices in NT4 - go into the
|
|
service registry key and enumerate the Parameters\Device*\Devices
|
|
values. The value names represent the device name, whereas the data
|
|
assigned to them identifies the type of device.
|
|
*/
|
|
MMRESULT
|
|
EnumerateNt4ServiceSoundDevices(
|
|
IN LPWSTR ServiceName,
|
|
IN MMDEVICE_TYPE DeviceType,
|
|
IN SOUND_DEVICE_DETECTED_PROC SoundDeviceDetectedProc)
|
|
{
|
|
HKEY Key;
|
|
DWORD KeyIndex = 0;
|
|
|
|
VALIDATE_MMSYS_PARAMETER( ServiceName );
|
|
|
|
/* Device type zero means "all" */
|
|
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType) ||
|
|
DeviceType == 0 );
|
|
|
|
while ( OpenSoundDeviceRegKey(ServiceName, KeyIndex, &Key) == MMSYSERR_NOERROR )
|
|
{
|
|
HKEY DevicesKey;
|
|
DWORD ValueType = REG_NONE, ValueIndex = 0;
|
|
DWORD MaxNameLength = 0, ValueNameLength = 0;
|
|
PWSTR DevicePath = NULL, ValueName = NULL;
|
|
DWORD ValueDataLength = sizeof(DWORD);
|
|
DWORD ValueData;
|
|
|
|
if ( RegOpenKeyEx(Key,
|
|
REG_DEVICES_KEY_NAME_U,
|
|
0,
|
|
KEY_READ,
|
|
&DevicesKey) == ERROR_SUCCESS )
|
|
{
|
|
/* Find out how much memory is needed for the key name */
|
|
if ( RegQueryInfoKey(DevicesKey,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&MaxNameLength,
|
|
NULL, NULL, NULL) != ERROR_SUCCESS )
|
|
{
|
|
SND_ERR(L"Failed to query registry key information\n");
|
|
RegCloseKey(DevicesKey);
|
|
RegCloseKey(Key);
|
|
|
|
return MMSYSERR_ERROR;
|
|
}
|
|
|
|
DevicePath = AllocateWideString(MaxNameLength +
|
|
strlen("\\\\.\\"));
|
|
|
|
/* Check that the memory allocation was successful */
|
|
if ( ! DevicePath )
|
|
{
|
|
/* There's no point in going further */
|
|
RegCloseKey(DevicesKey);
|
|
RegCloseKey(Key);
|
|
|
|
return MMSYSERR_NOMEM;
|
|
}
|
|
|
|
/* Insert the device path prefix */
|
|
wsprintf(DevicePath, L"\\\\.\\");
|
|
|
|
/* The offset of the string following this prefix */
|
|
ValueName = DevicePath + strlen("\\\\.\\");
|
|
|
|
/* Copy this so that it may be overwritten - include NULL */
|
|
ValueNameLength = MaxNameLength + sizeof(WCHAR);
|
|
|
|
SND_TRACE(L"Interested in devices beginning with %wS\n", DevicePath);
|
|
|
|
while ( RegEnumValue(DevicesKey,
|
|
ValueIndex,
|
|
ValueName,
|
|
&ValueNameLength,
|
|
NULL,
|
|
&ValueType,
|
|
(LPBYTE) &ValueData,
|
|
&ValueDataLength) == ERROR_SUCCESS )
|
|
{
|
|
/* Device types are stored as DWORDs */
|
|
if ( ( ValueType == REG_DWORD ) &&
|
|
( ValueDataLength == sizeof(DWORD) ) )
|
|
{
|
|
if ( ( DeviceType == 0 ) ||
|
|
( DeviceType == ValueData ) )
|
|
{
|
|
SND_TRACE(L"Found device: %wS\n", DevicePath);
|
|
SoundDeviceDetectedProc(ValueData, DevicePath);
|
|
}
|
|
}
|
|
|
|
/* Reset variables for the next iteration */
|
|
ValueNameLength = MaxNameLength + sizeof(WCHAR);
|
|
ZeroMemory(ValueName, (MaxNameLength+1)*sizeof(WCHAR));
|
|
/*ZeroWideString(ValueName);*/
|
|
ValueDataLength = sizeof(DWORD);
|
|
ValueData = 0;
|
|
ValueType = REG_NONE;
|
|
|
|
++ ValueIndex;
|
|
}
|
|
|
|
FreeMemory(DevicePath);
|
|
|
|
RegCloseKey(DevicesKey);
|
|
}
|
|
else
|
|
{
|
|
SND_WARN(L"Unable to open the Devices key!\n");
|
|
}
|
|
|
|
++ KeyIndex;
|
|
|
|
RegCloseKey(Key);
|
|
}
|
|
|
|
return MMSYSERR_NOERROR;
|
|
}
|
|
|
|
/*
|
|
Brute-force device detection, using a base device name (eg: \\.\WaveOut).
|
|
|
|
This will add the device number as a suffix to the end of the string and
|
|
attempt to open the device based on that name. On success, it will
|
|
increment the device number and repeat this process.
|
|
|
|
When it runs out of devices, it will give up.
|
|
*/
|
|
MMRESULT
|
|
DetectNt4SoundDevices(
|
|
IN MMDEVICE_TYPE DeviceType,
|
|
IN PWSTR BaseDeviceName,
|
|
IN SOUND_DEVICE_DETECTED_PROC SoundDeviceDetectedProc)
|
|
{
|
|
SIZE_T DeviceNameLength = 0;
|
|
PWSTR DeviceName = NULL;
|
|
ULONG Index = 0;
|
|
HANDLE DeviceHandle;
|
|
BOOLEAN DoSearch = TRUE;
|
|
|
|
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType) );
|
|
|
|
DeviceNameLength = wcslen(BaseDeviceName);
|
|
/* Consider the length of the number */
|
|
DeviceNameLength += GetDigitCount(Index);
|
|
|
|
DeviceName = AllocateWideString(DeviceNameLength);
|
|
|
|
if ( ! DeviceName )
|
|
{
|
|
return MMSYSERR_NOMEM;
|
|
}
|
|
|
|
while ( DoSearch )
|
|
{
|
|
/* Nothing like a nice clean device name */
|
|
ZeroWideString(DeviceName);
|
|
wsprintf(DeviceName, L"%ls%d", BaseDeviceName, Index);
|
|
|
|
if ( OpenKernelSoundDeviceByName(DeviceName,
|
|
TRUE,
|
|
&DeviceHandle) == MMSYSERR_NOERROR )
|
|
{
|
|
/* Notify the callback function */
|
|
SND_TRACE(L"Found device: %wS\n", DeviceName);
|
|
SoundDeviceDetectedProc(DeviceType, DeviceName);
|
|
|
|
CloseHandle(DeviceHandle);
|
|
|
|
++ Index;
|
|
}
|
|
else
|
|
{
|
|
DoSearch = FALSE;
|
|
}
|
|
}
|
|
|
|
FreeMemory(DeviceName);
|
|
|
|
return MMSYSERR_NOERROR;
|
|
}
|