include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / winealsa.drv / mmdevdrv.c
blobee80aa7c09da45e8bc38b545e0b775a0d042844c
1 /*
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
21 #define COBJMACROS
23 #include <stdarg.h>
24 #include <wchar.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnls.h"
29 #include "winreg.h"
30 #include "winternl.h"
31 #include "propsys.h"
32 #include "propkey.h"
33 #include "initguid.h"
34 #include "ole2.h"
35 #include "mmdeviceapi.h"
36 #include "devpkey.h"
37 #include "mmsystem.h"
38 #include "dsound.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"
48 #include "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)
59 switch (reason)
61 case DLL_PROCESS_ATTACH:
63 WCHAR buf[MAX_PATH];
64 WCHAR *filename;
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);
76 break;
78 case DLL_PROCESS_DETACH:
79 if (reserved) break;
80 break;
82 return TRUE;
85 static void set_device_guid(EDataFlow flow, HKEY drv_key, const WCHAR *key_name,
86 GUID *guid)
88 HKEY key;
89 BOOL opened = FALSE;
90 LONG lr;
92 if(!drv_key){
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);
97 return;
99 opened = TRUE;
102 lr = RegCreateKeyExW(drv_key, key_name, 0, NULL, 0, KEY_WRITE,
103 NULL, &key, NULL);
104 if(lr != ERROR_SUCCESS){
105 ERR("RegCreateKeyEx(%s) failed: %lu\n", wine_dbgstr_w(key_name), lr);
106 goto exit;
109 lr = RegSetValueExW(key, guidW, 0, REG_BINARY, (BYTE*)guid,
110 sizeof(GUID));
111 if(lr != ERROR_SUCCESS)
112 ERR("RegSetValueEx(%s\\guid) failed: %lu\n", wine_dbgstr_w(key_name), lr);
114 RegCloseKey(key);
115 exit:
116 if(opened)
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);
124 WCHAR key_name[256];
126 if(flow == eCapture)
127 key_name[0] = '1';
128 else
129 key_name[0] = '0';
130 key_name[1] = ',';
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);
139 RegCloseKey(key);
140 return;
142 ERR("Invalid type for device %s GUID: %lu; ignoring and overwriting\n",
143 wine_dbgstr_w(key_name), type);
145 RegCloseKey(dev_key);
149 CoCreateGuid(guid);
151 set_device_guid(flow, key, key_name, guid);
153 if(key)
154 RegCloseKey(key);
157 BOOL WINAPI get_device_name_from_guid(GUID *guid, char **name, EDataFlow *flow)
159 HKEY devices_key;
160 UINT i = 0;
161 WCHAR key_name[256];
162 DWORD key_name_size;
164 if(RegOpenKeyExW(HKEY_CURRENT_USER, drv_key_devicesW, 0, KEY_READ, &devices_key) != ERROR_SUCCESS){
165 ERR("No devices found in registry?\n");
166 return FALSE;
169 while(1){
170 HKEY key;
171 DWORD size, type;
172 GUID reg_guid;
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)
177 break;
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));
181 continue;
184 size = sizeof(reg_guid);
185 if(RegQueryValueExW(key, guidW, 0, &type,
186 (BYTE*)&reg_guid, &size) == ERROR_SUCCESS){
187 if(IsEqualGUID(&reg_guid, guid)){
188 INT size;
190 RegCloseKey(key);
191 RegCloseKey(devices_key);
193 TRACE("Found matching device key: %s\n", wine_dbgstr_w(key_name));
195 if(key_name[0] == '0')
196 *flow = eRender;
197 else if(key_name[0] == '1')
198 *flow = eCapture;
199 else{
200 ERR("Unknown device type: %c\n", key_name[0]);
201 return FALSE;
204 if(!(size = WideCharToMultiByte(CP_UNIXCP, 0, key_name + 2, -1, NULL, 0, NULL, NULL)))
205 return FALSE;
207 if(!(*name = malloc(size)))
208 return FALSE;
210 if(!WideCharToMultiByte(CP_UNIXCP, 0, key_name + 2, -1, *name, size, NULL, NULL)){
211 free(*name);
212 return FALSE;
215 return TRUE;
219 RegCloseKey(key);
222 RegCloseKey(devices_key);
224 WARN("No matching device in registry for GUID %s\n", debugstr_guid(guid));
226 return FALSE;