include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / winecoreaudio.drv / mmdevdrv.c
blob65e965c555645fbc357a97da99a7294f0b322704
1 /*
2 * Copyright 2011 Andrew Eikum for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 #define COBJMACROS
20 #include <stdarg.h>
21 #include <wchar.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winternl.h"
26 #include "winnls.h"
27 #include "winreg.h"
28 #include "wine/debug.h"
29 #include "wine/list.h"
30 #include "wine/unixlib.h"
32 #include "ole2.h"
33 #include "mmdeviceapi.h"
34 #include "devpkey.h"
35 #include "dshow.h"
36 #include "dsound.h"
38 #include "initguid.h"
39 #include "endpointvolume.h"
40 #include "audioclient.h"
41 #include "audiopolicy.h"
42 #include "unixlib.h"
44 #include "../mmdevapi/mmdevdrv.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(coreaudio);
48 static WCHAR drv_key_devicesW[256];
50 BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
52 switch (reason)
54 case DLL_PROCESS_ATTACH:
56 WCHAR buf[MAX_PATH];
57 WCHAR *filename;
59 DisableThreadLibraryCalls(dll);
60 if (__wine_init_unix_call())
61 return FALSE;
63 GetModuleFileNameW(dll, buf, ARRAY_SIZE(buf));
65 filename = wcsrchr(buf, '\\');
66 filename = filename ? filename + 1 : buf;
68 swprintf(drv_key_devicesW, ARRAY_SIZE(drv_key_devicesW),
69 L"Software\\Wine\\Drivers\\%s\\devices", filename);
71 break;
73 case DLL_PROCESS_DETACH:
74 if (reserved) break;
75 break;
77 return TRUE;
80 static void set_device_guid(EDataFlow flow, HKEY drv_key, const WCHAR *key_name,
81 GUID *guid)
83 HKEY key;
84 BOOL opened = FALSE;
85 LONG lr;
87 if(!drv_key){
88 lr = RegCreateKeyExW(HKEY_CURRENT_USER, drv_key_devicesW, 0, NULL, 0, KEY_WRITE,
89 NULL, &drv_key, NULL);
90 if(lr != ERROR_SUCCESS){
91 ERR("RegCreateKeyEx(drv_key) failed: %lu\n", lr);
92 return;
94 opened = TRUE;
97 lr = RegCreateKeyExW(drv_key, key_name, 0, NULL, 0, KEY_WRITE,
98 NULL, &key, NULL);
99 if(lr != ERROR_SUCCESS){
100 ERR("RegCreateKeyEx(%s) failed: %lu\n", wine_dbgstr_w(key_name), lr);
101 goto exit;
104 lr = RegSetValueExW(key, L"guid", 0, REG_BINARY, (BYTE*)guid,
105 sizeof(GUID));
106 if(lr != ERROR_SUCCESS)
107 ERR("RegSetValueEx(%s\\guid) failed: %lu\n", wine_dbgstr_w(key_name), lr);
109 RegCloseKey(key);
110 exit:
111 if(opened)
112 RegCloseKey(drv_key);
115 void WINAPI get_device_guid(EDataFlow flow, const char *dev, GUID *guid)
117 HKEY key = NULL, dev_key;
118 DWORD type, size = sizeof(*guid);
119 WCHAR key_name[256];
121 if(flow == eCapture)
122 key_name[0] = '1';
123 else
124 key_name[0] = '0';
125 key_name[1] = ',';
127 MultiByteToWideChar(CP_UTF8, 0, dev, -1, key_name + 2, ARRAY_SIZE(key_name) - 2);
129 if(RegOpenKeyExW(HKEY_CURRENT_USER, drv_key_devicesW, 0, KEY_WRITE|KEY_READ, &key) == ERROR_SUCCESS){
130 if(RegOpenKeyExW(key, key_name, 0, KEY_READ, &dev_key) == ERROR_SUCCESS){
131 if(RegQueryValueExW(dev_key, L"guid", 0, &type,
132 (BYTE*)guid, &size) == ERROR_SUCCESS){
133 if(type == REG_BINARY){
134 RegCloseKey(dev_key);
135 RegCloseKey(key);
136 return;
138 ERR("Invalid type for device %s GUID: %lu; ignoring and overwriting\n",
139 wine_dbgstr_w(key_name), type);
141 RegCloseKey(dev_key);
145 CoCreateGuid(guid);
147 set_device_guid(flow, key, key_name, guid);
149 if(key)
150 RegCloseKey(key);
153 BOOL WINAPI get_device_name_from_guid(const GUID *guid, char **name, EDataFlow *flow)
155 HKEY devices_key;
156 UINT i = 0;
157 WCHAR key_name[256];
158 DWORD key_name_size;
160 if(RegOpenKeyExW(HKEY_CURRENT_USER, drv_key_devicesW, 0, KEY_READ, &devices_key) != ERROR_SUCCESS){
161 ERR("No devices in registry?\n");
162 return FALSE;
165 while(1){
166 HKEY key;
167 DWORD size, type;
168 GUID reg_guid;
170 key_name_size = ARRAY_SIZE(key_name);
171 if(RegEnumKeyExW(devices_key, i++, key_name, &key_name_size, NULL,
172 NULL, NULL, NULL) != ERROR_SUCCESS)
173 break;
175 if(RegOpenKeyExW(devices_key, key_name, 0, KEY_READ, &key) != ERROR_SUCCESS){
176 WARN("Couldn't open key: %s\n", wine_dbgstr_w(key_name));
177 continue;
180 size = sizeof(reg_guid);
181 if(RegQueryValueExW(key, L"guid", 0, &type,
182 (BYTE*)&reg_guid, &size) == ERROR_SUCCESS){
183 if(IsEqualGUID(&reg_guid, guid)){
184 RegCloseKey(key);
185 RegCloseKey(devices_key);
187 TRACE("Found matching device key: %s\n", wine_dbgstr_w(key_name));
189 if(key_name[0] == '0')
190 *flow = eRender;
191 else if(key_name[0] == '1')
192 *flow = eCapture;
193 else{
194 ERR("Unknown device type: %c\n", key_name[0]);
195 return FALSE;
198 if(!(size = WideCharToMultiByte(CP_UTF8, 0, key_name + 2, -1, NULL, 0, NULL, NULL)))
199 return FALSE;
201 if(!(*name = malloc(size)))
202 return FALSE;
204 if(!WideCharToMultiByte(CP_UTF8, 0, key_name + 2, -1, *name, size, NULL, NULL)){
205 free(*name);
206 return FALSE;
209 return TRUE;
213 RegCloseKey(key);
216 RegCloseKey(devices_key);
218 WARN("No matching device in registry for GUID %s\n", debugstr_guid(guid));
220 return FALSE;