1 /* 2 * PROJECT: ReactOS Sound System "MME Buddy" NT4 Library 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: lib/drivers/sound/mment4/detect.c 5 * 6 * PURPOSE: Assists in locating Windows NT4 compatible sound devices, 7 * which mostly use the same device naming convention and/or 8 * store their created device names within their service key 9 * within the registry. 10 * 11 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) 12 */ 13 14 #include "precomp.h" 15 16 #include <mment4.h> 17 #include <mmebuddy_debug.h> 18 19 /* 20 This is the "nice" way to discover audio devices in NT4 - go into the 21 service registry key and enumerate the Parameters\Device*\Devices 22 values. The value names represent the device name, whereas the data 23 assigned to them identifies the type of device. 24 */ 25 MMRESULT 26 EnumerateNt4ServiceSoundDevices( 27 IN LPWSTR ServiceName, 28 IN MMDEVICE_TYPE DeviceType, 29 IN SOUND_DEVICE_DETECTED_PROC SoundDeviceDetectedProc) 30 { 31 HKEY Key; 32 DWORD KeyIndex = 0; 33 34 VALIDATE_MMSYS_PARAMETER( ServiceName ); 35 36 /* Device type zero means "all" */ 37 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType) || 38 DeviceType == 0 ); 39 40 while ( OpenSoundDeviceRegKey(ServiceName, KeyIndex, &Key) == MMSYSERR_NOERROR ) 41 { 42 HKEY DevicesKey; 43 DWORD ValueType = REG_NONE, ValueIndex = 0; 44 DWORD MaxNameLength = 0, ValueNameLength = 0; 45 PWSTR DevicePath = NULL, ValueName = NULL; 46 DWORD ValueDataLength = sizeof(DWORD); 47 DWORD ValueData; 48 49 if ( RegOpenKeyEx(Key, 50 REG_DEVICES_KEY_NAME_U, 51 0, 52 KEY_READ, 53 &DevicesKey) == ERROR_SUCCESS ) 54 { 55 /* Find out how much memory is needed for the key name */ 56 if ( RegQueryInfoKey(DevicesKey, 57 NULL, NULL, NULL, NULL, NULL, NULL, NULL, 58 &MaxNameLength, 59 NULL, NULL, NULL) != ERROR_SUCCESS ) 60 { 61 SND_ERR(L"Failed to query registry key information\n"); 62 RegCloseKey(DevicesKey); 63 RegCloseKey(Key); 64 65 return MMSYSERR_ERROR; 66 } 67 68 DevicePath = AllocateWideString(MaxNameLength + 69 strlen("\\\\.\\")); 70 71 /* Check that the memory allocation was successful */ 72 if ( ! DevicePath ) 73 { 74 /* There's no point in going further */ 75 RegCloseKey(DevicesKey); 76 RegCloseKey(Key); 77 78 return MMSYSERR_NOMEM; 79 } 80 81 /* Insert the device path prefix */ 82 wsprintf(DevicePath, L"\\\\.\\"); 83 84 /* The offset of the string following this prefix */ 85 ValueName = DevicePath + strlen("\\\\.\\"); 86 87 /* Copy this so that it may be overwritten - include NULL */ 88 ValueNameLength = MaxNameLength + sizeof(WCHAR); 89 90 SND_TRACE(L"Interested in devices beginning with %wS\n", DevicePath); 91 92 while ( RegEnumValue(DevicesKey, 93 ValueIndex, 94 ValueName, 95 &ValueNameLength, 96 NULL, 97 &ValueType, 98 (LPBYTE) &ValueData, 99 &ValueDataLength) == ERROR_SUCCESS ) 100 { 101 /* Device types are stored as DWORDs */ 102 if ( ( ValueType == REG_DWORD ) && 103 ( ValueDataLength == sizeof(DWORD) ) ) 104 { 105 if ( ( DeviceType == 0 ) || 106 ( DeviceType == ValueData ) ) 107 { 108 SND_TRACE(L"Found device: %wS\n", DevicePath); 109 SoundDeviceDetectedProc(ValueData, DevicePath); 110 } 111 } 112 113 /* Reset variables for the next iteration */ 114 ValueNameLength = MaxNameLength + sizeof(WCHAR); 115 ZeroMemory(ValueName, (MaxNameLength+1)*sizeof(WCHAR)); 116 /*ZeroWideString(ValueName);*/ 117 ValueDataLength = sizeof(DWORD); 118 ValueData = 0; 119 ValueType = REG_NONE; 120 121 ++ ValueIndex; 122 } 123 124 FreeMemory(DevicePath); 125 126 RegCloseKey(DevicesKey); 127 } 128 else 129 { 130 SND_WARN(L"Unable to open the Devices key!\n"); 131 } 132 133 ++ KeyIndex; 134 135 RegCloseKey(Key); 136 } 137 138 return MMSYSERR_NOERROR; 139 } 140 141 /* 142 Brute-force device detection, using a base device name (eg: \\.\WaveOut). 143 144 This will add the device number as a suffix to the end of the string and 145 attempt to open the device based on that name. On success, it will 146 increment the device number and repeat this process. 147 148 When it runs out of devices, it will give up. 149 */ 150 MMRESULT 151 DetectNt4SoundDevices( 152 IN MMDEVICE_TYPE DeviceType, 153 IN PWSTR BaseDeviceName, 154 IN SOUND_DEVICE_DETECTED_PROC SoundDeviceDetectedProc) 155 { 156 SIZE_T DeviceNameLength = 0; 157 PWSTR DeviceName = NULL; 158 ULONG Index = 0; 159 HANDLE DeviceHandle; 160 BOOLEAN DoSearch = TRUE; 161 162 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType) ); 163 164 DeviceNameLength = wcslen(BaseDeviceName); 165 /* Consider the length of the number */ 166 DeviceNameLength += GetDigitCount(Index); 167 168 DeviceName = AllocateWideString(DeviceNameLength); 169 170 if ( ! DeviceName ) 171 { 172 return MMSYSERR_NOMEM; 173 } 174 175 while ( DoSearch ) 176 { 177 /* Nothing like a nice clean device name */ 178 ZeroWideString(DeviceName); 179 wsprintf(DeviceName, L"%ls%d", BaseDeviceName, Index); 180 181 if ( OpenKernelSoundDeviceByName(DeviceName, 182 TRUE, 183 &DeviceHandle) == MMSYSERR_NOERROR ) 184 { 185 /* Notify the callback function */ 186 SND_TRACE(L"Found device: %wS\n", DeviceName); 187 SoundDeviceDetectedProc(DeviceType, DeviceName); 188 189 CloseHandle(DeviceHandle); 190 191 ++ Index; 192 } 193 else 194 { 195 DoSearch = FALSE; 196 } 197 } 198 199 FreeMemory(DeviceName); 200 201 return MMSYSERR_NOERROR; 202 } 203