2 * Copyright 2010 Maarten Lankhorst for CodeWeavers
3 * Copyright 2011 Andrew Eikum for CodeWeavers
4 * Copyright 2022 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
35 #include "mmdeviceapi.h"
40 #include "endpointvolume.h"
41 #include "audioclient.h"
42 #include "audiopolicy.h"
44 #include "wine/debug.h"
45 #include "wine/list.h"
46 #include "wine/unixlib.h"
50 #include "../mmdevapi/mmdevdrv.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(alsa
);
54 static WCHAR drv_key_devicesW
[256];
55 static const WCHAR guidW
[] = {'g','u','i','d',0};
57 BOOL WINAPI
DllMain(HINSTANCE dll
, DWORD reason
, void *reserved
)
61 case DLL_PROCESS_ATTACH
:
66 if(__wine_init_unix_call()) return FALSE
;
68 GetModuleFileNameW(dll
, buf
, ARRAY_SIZE(buf
));
70 filename
= wcsrchr(buf
, '\\');
71 filename
= filename
? filename
+ 1 : buf
;
73 swprintf(drv_key_devicesW
, ARRAY_SIZE(drv_key_devicesW
),
74 L
"Software\\Wine\\Drivers\\%s\\devices", filename
);
78 case DLL_PROCESS_DETACH
:
85 static void set_device_guid(EDataFlow flow
, HKEY drv_key
, const WCHAR
*key_name
,
93 lr
= RegCreateKeyExW(HKEY_CURRENT_USER
, drv_key_devicesW
, 0, NULL
, 0, KEY_WRITE
,
94 NULL
, &drv_key
, NULL
);
95 if(lr
!= ERROR_SUCCESS
){
96 ERR("RegCreateKeyEx(drv_key) failed: %lu\n", lr
);
102 lr
= RegCreateKeyExW(drv_key
, key_name
, 0, NULL
, 0, KEY_WRITE
,
104 if(lr
!= ERROR_SUCCESS
){
105 ERR("RegCreateKeyEx(%s) failed: %lu\n", wine_dbgstr_w(key_name
), lr
);
109 lr
= RegSetValueExW(key
, guidW
, 0, REG_BINARY
, (BYTE
*)guid
,
111 if(lr
!= ERROR_SUCCESS
)
112 ERR("RegSetValueEx(%s\\guid) failed: %lu\n", wine_dbgstr_w(key_name
), lr
);
117 RegCloseKey(drv_key
);
120 void WINAPI
get_device_guid(EDataFlow flow
, const char *device
, GUID
*guid
)
122 HKEY key
= NULL
, dev_key
;
123 DWORD type
, size
= sizeof(*guid
);
131 MultiByteToWideChar(CP_UNIXCP
, 0, device
, -1, key_name
+ 2, ARRAY_SIZE(key_name
) - 2);
133 if(RegOpenKeyExW(HKEY_CURRENT_USER
, drv_key_devicesW
, 0, KEY_WRITE
|KEY_READ
, &key
) == ERROR_SUCCESS
){
134 if(RegOpenKeyExW(key
, key_name
, 0, KEY_READ
, &dev_key
) == ERROR_SUCCESS
){
135 if(RegQueryValueExW(dev_key
, guidW
, 0, &type
,
136 (BYTE
*)guid
, &size
) == ERROR_SUCCESS
){
137 if(type
== REG_BINARY
){
138 RegCloseKey(dev_key
);
142 ERR("Invalid type for device %s GUID: %lu; ignoring and overwriting\n",
143 wine_dbgstr_w(key_name
), type
);
145 RegCloseKey(dev_key
);
151 set_device_guid(flow
, key
, key_name
, guid
);
157 BOOL WINAPI
get_device_name_from_guid(GUID
*guid
, char **name
, EDataFlow
*flow
)
164 if(RegOpenKeyExW(HKEY_CURRENT_USER
, drv_key_devicesW
, 0, KEY_READ
, &devices_key
) != ERROR_SUCCESS
){
165 ERR("No devices found in registry?\n");
174 key_name_size
= ARRAY_SIZE(key_name
);
175 if(RegEnumKeyExW(devices_key
, i
++, key_name
, &key_name_size
, NULL
,
176 NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
179 if(RegOpenKeyExW(devices_key
, key_name
, 0, KEY_READ
, &key
) != ERROR_SUCCESS
){
180 WARN("Couldn't open key: %s\n", wine_dbgstr_w(key_name
));
184 size
= sizeof(reg_guid
);
185 if(RegQueryValueExW(key
, guidW
, 0, &type
,
186 (BYTE
*)®_guid
, &size
) == ERROR_SUCCESS
){
187 if(IsEqualGUID(®_guid
, guid
)){
191 RegCloseKey(devices_key
);
193 TRACE("Found matching device key: %s\n", wine_dbgstr_w(key_name
));
195 if(key_name
[0] == '0')
197 else if(key_name
[0] == '1')
200 ERR("Unknown device type: %c\n", key_name
[0]);
204 if(!(size
= WideCharToMultiByte(CP_UNIXCP
, 0, key_name
+ 2, -1, NULL
, 0, NULL
, NULL
)))
207 if(!(*name
= malloc(size
)))
210 if(!WideCharToMultiByte(CP_UNIXCP
, 0, key_name
+ 2, -1, *name
, size
, NULL
, NULL
)){
222 RegCloseKey(devices_key
);
224 WARN("No matching device in registry for GUID %s\n", debugstr_guid(guid
));