2 * Copyright 2011 Andrew Eikum for CodeWeavers
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
31 #include "mmdeviceapi.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"
47 #include "../mmdevapi/mmdevdrv.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(oss
);
51 typedef struct _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
)
67 case DLL_PROCESS_ATTACH
:
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
);
84 case DLL_PROCESS_DETACH
:
87 OSSDevice
*iter
, *iter2
;
89 LIST_FOR_EACH_ENTRY_SAFE(iter
, iter2
, &g_devices
, OSSDevice
, entry
){
90 HeapFree(GetProcessHeap(), 0, iter
);
98 static void device_add(OSSDevice
*oss_dev
)
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
);
107 list_add_tail(&g_devices
, &oss_dev
->entry
);
110 static void set_device_guid(EDataFlow flow
, HKEY drv_key
, const WCHAR
*key_name
,
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
);
127 lr
= RegCreateKeyExW(drv_key
, key_name
, 0, NULL
, 0, KEY_WRITE
,
129 if(lr
!= ERROR_SUCCESS
){
130 ERR("RegCreateKeyEx(%s) failed: %lu\n", wine_dbgstr_w(key_name
), lr
);
134 lr
= RegSetValueExW(key
, guidW
, 0, REG_BINARY
, (BYTE
*)guid
,
136 if(lr
!= ERROR_SUCCESS
)
137 ERR("RegSetValueEx(%s\\guid) failed: %lu\n", wine_dbgstr_w(key_name
), lr
);
142 RegCloseKey(drv_key
);
145 void WINAPI
get_device_guid(EDataFlow flow
, const char *device
, GUID
*guid
)
148 HKEY key
= NULL
, dev_key
;
149 DWORD type
, size
= sizeof(*guid
);
151 const unsigned int dev_size
= strlen(device
) + 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
);
169 ERR("Invalid type for device %s GUID: %lu; ignoring and overwriting\n",
170 wine_dbgstr_w(key_name
), type
);
172 RegCloseKey(dev_key
);
178 set_device_guid(flow
, key
, key_name
, guid
);
183 oss_dev
= HeapAlloc(GetProcessHeap(), 0, offsetof(OSSDevice
, devnode
[dev_size
]));
185 oss_dev
->flow
= flow
;
186 oss_dev
->guid
= *guid
;
187 memcpy(oss_dev
->devnode
, device
, dev_size
);
192 BOOL WINAPI
get_device_name_from_guid(GUID
*guid
, char **name
, EDataFlow
*flow
)
195 LIST_FOR_EACH_ENTRY(dev_item
, &g_devices
, OSSDevice
, entry
){
196 if(!IsEqualGUID(guid
, &dev_item
->guid
))
199 if(!(*name
= strdup(dev_item
->devnode
)))
202 *flow
= dev_item
->flow
;