comctl32/tests: Use CRT allocation functions.
[wine.git] / dlls / wineoss.drv / mmdevdrv.c
blob7b7d426d1df4dce5b5a97cf012fdf6db338f4fa9
1 /*
2 * Copyright 2011 Andrew Eikum for CodeWeavers
3 * 2022 Huw Davies
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
21 #include <stdarg.h>
22 #include <wchar.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winternl.h"
27 #include "winnls.h"
28 #include "winreg.h"
30 #include "ole2.h"
31 #include "mmdeviceapi.h"
32 #include "devpkey.h"
33 #include "dshow.h"
34 #include "dsound.h"
36 #include "initguid.h"
37 #include "endpointvolume.h"
38 #include "audiopolicy.h"
39 #include "audioclient.h"
41 #include "wine/debug.h"
42 #include "wine/list.h"
43 #include "wine/unixlib.h"
45 #include "unixlib.h"
47 #include "../mmdevapi/mmdevdrv.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(oss);
51 typedef struct _OSSDevice {
52 struct list entry;
53 EDataFlow flow;
54 GUID guid;
55 char devnode[0];
56 } OSSDevice;
58 static struct list g_devices = LIST_INIT(g_devices);
60 static WCHAR drv_key_devicesW[256];
61 static const WCHAR guidW[] = {'g','u','i','d',0};
63 BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
65 switch (reason)
67 case DLL_PROCESS_ATTACH:
69 WCHAR buf[MAX_PATH];
70 WCHAR *filename;
72 if(__wine_init_unix_call()) return FALSE;
74 GetModuleFileNameW(dll, buf, ARRAY_SIZE(buf));
76 filename = wcsrchr(buf, '\\');
77 filename = filename ? filename + 1 : buf;
79 swprintf(drv_key_devicesW, ARRAY_SIZE(drv_key_devicesW),
80 L"Software\\Wine\\Drivers\\%s\\devices", filename);
82 break;
84 case DLL_PROCESS_DETACH:
85 if (!reserved)
87 OSSDevice *iter, *iter2;
89 LIST_FOR_EACH_ENTRY_SAFE(iter, iter2, &g_devices, OSSDevice, entry){
90 HeapFree(GetProcessHeap(), 0, iter);
93 break;
95 return TRUE;
98 static void device_add(OSSDevice *oss_dev)
100 OSSDevice *dev_item;
101 LIST_FOR_EACH_ENTRY(dev_item, &g_devices, OSSDevice, entry)
102 if(IsEqualGUID(&oss_dev->guid, &dev_item->guid)){ /* already in list */
103 HeapFree(GetProcessHeap(), 0, oss_dev);
104 return;
107 list_add_tail(&g_devices, &oss_dev->entry);
110 static void set_device_guid(EDataFlow flow, HKEY drv_key, const WCHAR *key_name,
111 GUID *guid)
113 HKEY key;
114 BOOL opened = FALSE;
115 LONG lr;
117 if(!drv_key){
118 lr = RegCreateKeyExW(HKEY_CURRENT_USER, drv_key_devicesW, 0, NULL, 0, KEY_WRITE,
119 NULL, &drv_key, NULL);
120 if(lr != ERROR_SUCCESS){
121 ERR("RegCreateKeyEx(drv_key) failed: %lu\n", lr);
122 return;
124 opened = TRUE;
127 lr = RegCreateKeyExW(drv_key, key_name, 0, NULL, 0, KEY_WRITE,
128 NULL, &key, NULL);
129 if(lr != ERROR_SUCCESS){
130 ERR("RegCreateKeyEx(%s) failed: %lu\n", wine_dbgstr_w(key_name), lr);
131 goto exit;
134 lr = RegSetValueExW(key, guidW, 0, REG_BINARY, (BYTE*)guid,
135 sizeof(GUID));
136 if(lr != ERROR_SUCCESS)
137 ERR("RegSetValueEx(%s\\guid) failed: %lu\n", wine_dbgstr_w(key_name), lr);
139 RegCloseKey(key);
140 exit:
141 if(opened)
142 RegCloseKey(drv_key);
145 void WINAPI get_device_guid(EDataFlow flow, const char *device, GUID *guid)
147 OSSDevice *oss_dev;
148 HKEY key = NULL, dev_key;
149 DWORD type, size = sizeof(*guid);
150 WCHAR key_name[256];
151 const unsigned int dev_size = strlen(device) + 1;
153 if(flow == eCapture)
154 key_name[0] = '1';
155 else
156 key_name[0] = '0';
157 key_name[1] = ',';
158 MultiByteToWideChar(CP_UNIXCP, 0, device, -1, key_name + 2, ARRAY_SIZE(key_name) - 2);
160 if(RegOpenKeyExW(HKEY_CURRENT_USER, drv_key_devicesW, 0, KEY_WRITE|KEY_READ, &key) == ERROR_SUCCESS){
161 if(RegOpenKeyExW(key, key_name, 0, KEY_READ, &dev_key) == ERROR_SUCCESS){
162 if(RegQueryValueExW(dev_key, guidW, 0, &type,
163 (BYTE*)guid, &size) == ERROR_SUCCESS){
164 if(type == REG_BINARY){
165 RegCloseKey(dev_key);
166 RegCloseKey(key);
167 goto exit;
169 ERR("Invalid type for device %s GUID: %lu; ignoring and overwriting\n",
170 wine_dbgstr_w(key_name), type);
172 RegCloseKey(dev_key);
176 CoCreateGuid(guid);
178 set_device_guid(flow, key, key_name, guid);
179 exit:
180 if(key)
181 RegCloseKey(key);
183 oss_dev = HeapAlloc(GetProcessHeap(), 0, offsetof(OSSDevice, devnode[dev_size]));
184 if(oss_dev){
185 oss_dev->flow = flow;
186 oss_dev->guid = *guid;
187 memcpy(oss_dev->devnode, device, dev_size);
188 device_add(oss_dev);
192 BOOL WINAPI get_device_name_from_guid(GUID *guid, char **name, EDataFlow *flow)
194 OSSDevice *dev_item;
195 LIST_FOR_EACH_ENTRY(dev_item, &g_devices, OSSDevice, entry){
196 if(!IsEqualGUID(guid, &dev_item->guid))
197 continue;
199 if(!(*name = strdup(dev_item->devnode)))
200 return FALSE;
202 *flow = dev_item->flow;
204 return TRUE;
207 return FALSE;