* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "mmdevapi.h"
+#include "config.h"
+
+#include <stdarg.h>
+
+#define NONAMELESSUNION
+#define COBJMACROS
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "wine/debug.h"
+#include "wine/list.h"
+#include "wine/unicode.h"
+
+#include "initguid.h"
+#include "ole2.h"
+#include "mmdeviceapi.h"
+#include "dshow.h"
+#include "dsound.h"
+#include "audioclient.h"
+#include "endpointvolume.h"
+#include "audiopolicy.h"
-#include <wine/list.h>
+#include "mmdevapi.h"
+#include "devpkey.h"
-#include <ole2.h>
-#include <initguid.h>
-#define _WINDOWS_H
-#include <dshow.h>
-#include <devpkey.h>
+WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
static const WCHAR software_mmdevapi[] =
{ 'S','o','f','t','w','a','r','e','\\',
LONG ret;
HKEY key;
StringFromGUID2(guid, buffer, 39);
- if ((ret = RegOpenKeyExW(flow == eRender ? key_render : key_capture, buffer, 0, KEY_READ|KEY_WRITE, &key)) != ERROR_SUCCESS)
+ if ((ret = RegOpenKeyExW(flow == eRender ? key_render : key_capture, buffer, 0, KEY_READ|KEY_WRITE|KEY_WOW64_64KEY, &key)) != ERROR_SUCCESS)
{
WARN("Opening key %s failed with %u\n", debugstr_w(buffer), ret);
return E_FAIL;
}
- ret = RegOpenKeyExW(key, reg_properties, 0, KEY_READ|KEY_WRITE, propkey);
+ ret = RegOpenKeyExW(key, reg_properties, 0, KEY_READ|KEY_WRITE|KEY_WOW64_64KEY, propkey);
RegCloseKey(key);
if (ret != ERROR_SUCCESS)
{
return hr;
}
+static HRESULT set_driver_prop_value(GUID *id, const EDataFlow flow, const PROPERTYKEY *prop)
+{
+ HRESULT hr;
+ PROPVARIANT pv;
+
+ if (!drvs.pGetPropValue)
+ return E_NOTIMPL;
+
+ hr = drvs.pGetPropValue(id, prop, &pv);
+
+ if (SUCCEEDED(hr))
+ {
+ MMDevice_SetPropValue(id, flow, prop, &pv);
+ PropVariantClear(&pv);
+ }
+
+ return hr;
+}
+
/* Creates or updates the state of a device
* If GUID is null, a random guid will be assigned
* and the device will be created
{0x233164c8, 0x1b2c, 0x4c7d, {0xbc, 0x68, 0xb6, 0x71, 0x68, 0x7a, 0x25, 0x67}}, 1
};
+ static const PROPERTYKEY devicepath_key = {
+ {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
+ };
+
for (i = 0; i < MMDevice_count; ++i)
{
MMDevice *device = MMDevice_head[i];
else
root = key_capture;
- if (RegCreateKeyExW(root, guidstr, 0, NULL, 0, KEY_WRITE|KEY_READ, NULL, &key, NULL) == ERROR_SUCCESS)
+ if (RegCreateKeyExW(root, guidstr, 0, NULL, 0, KEY_WRITE|KEY_READ|KEY_WOW64_64KEY, NULL, &key, NULL) == ERROR_SUCCESS)
{
HKEY keyprop;
RegSetValueExW(key, reg_devicestate, 0, REG_DWORD, (const BYTE*)&state, sizeof(DWORD));
- if (!RegCreateKeyExW(key, reg_properties, 0, NULL, 0, KEY_WRITE|KEY_READ, NULL, &keyprop, NULL))
+ if (!RegCreateKeyExW(key, reg_properties, 0, NULL, 0, KEY_WRITE|KEY_READ|KEY_WOW64_64KEY, NULL, &keyprop, NULL))
{
PROPVARIANT pv;
pv.vt = VT_LPWSTR;
pv.u.pwszVal = name;
MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pv);
+ MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_DeviceInterface_FriendlyName, &pv);
MMDevice_SetPropValue(id, flow, (const PROPERTYKEY*)&DEVPKEY_Device_DeviceDesc, &pv);
pv.u.pwszVal = guidstr;
MMDevice_SetPropValue(id, flow, &deviceinterface_key, &pv);
+ set_driver_prop_value(id, flow, &devicepath_key);
+
+ if (FAILED(set_driver_prop_value(id, flow, &PKEY_AudioEndpoint_FormFactor)))
+ {
+ pv.vt = VT_UI4;
+ pv.u.ulVal = (flow == eCapture) ? Microphone : Speakers;
+
+ MMDevice_SetPropValue(id, flow, &PKEY_AudioEndpoint_FormFactor, &pv);
+ }
+
+ if (flow != eCapture)
+ {
+ PROPVARIANT pv2;
+
+ PropVariantInit(&pv2);
+
+ /* make read-write by not overwriting if already set */
+ if (FAILED(MMDevice_GetPropValue(id, flow, &PKEY_AudioEndpoint_PhysicalSpeakers, &pv2)) || pv2.vt != VT_UI4)
+ set_driver_prop_value(id, flow, &PKEY_AudioEndpoint_PhysicalSpeakers);
+
+ PropVariantClear(&pv2);
+ }
+
RegCloseKey(keyprop);
}
RegCloseKey(key);
LONG ret;
DWORD curflow;
- ret = RegCreateKeyExW(HKEY_LOCAL_MACHINE, software_mmdevapi, 0, NULL, 0, KEY_WRITE|KEY_READ, NULL, &root, NULL);
+ ret = RegCreateKeyExW(HKEY_LOCAL_MACHINE, software_mmdevapi, 0, NULL, 0, KEY_WRITE|KEY_READ|KEY_WOW64_64KEY, NULL, &root, NULL);
if (ret == ERROR_SUCCESS)
- ret = RegCreateKeyExW(root, reg_capture, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &key_capture, NULL);
+ ret = RegCreateKeyExW(root, reg_capture, 0, NULL, 0, KEY_READ|KEY_WRITE|KEY_WOW64_64KEY, NULL, &key_capture, NULL);
if (ret == ERROR_SUCCESS)
- ret = RegCreateKeyExW(root, reg_render, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &key_render, NULL);
+ ret = RegCreateKeyExW(root, reg_render, 0, NULL, 0, KEY_READ|KEY_WRITE|KEY_WOW64_64KEY, NULL, &key_render, NULL);
RegCloseKey(root);
cur = key_capture;
curflow = eCapture;
&PKEY_AudioEngine_DeviceFormat, &pv);
MMDevice_SetPropValue(&dev->devguid, dev->flow,
&PKEY_AudioEngine_OEMFormat, &pv);
+ CoTaskMemFree(fmt);
return S_OK;
}
*ppv = NULL;
if (IsEqualIID(riid, &IID_IUnknown)
|| IsEqualIID(riid, &IID_IMMDevice))
- *ppv = This;
+ *ppv = &This->IMMDevice_iface;
else if (IsEqualIID(riid, &IID_IMMEndpoint))
*ppv = &This->IMMEndpoint_iface;
if (*ppv)
HRESULT hr = E_NOINTERFACE;
MMDevice *This = impl_from_IMMDevice(iface);
- TRACE("(%p)->(%p,%x,%p,%p)\n", iface, riid, clsctx, params, ppv);
+ TRACE("(%p)->(%s, %x, %p, %p)\n", iface, debugstr_guid(riid), clsctx, params, ppv);
if (!ppv)
return E_POINTER;
if (IsEqualIID(riid, &IID_IAudioClient)){
hr = drvs.pGetAudioEndpoint(&This->devguid, iface, (IAudioClient**)ppv);
- }else if (IsEqualIID(riid, &IID_IAudioEndpointVolume))
- hr = AudioEndpointVolume_Create(This, (IAudioEndpointVolume**)ppv);
+ }else if (IsEqualIID(riid, &IID_IAudioEndpointVolume) ||
+ IsEqualIID(riid, &IID_IAudioEndpointVolumeEx))
+ hr = AudioEndpointVolume_Create(This, (IAudioEndpointVolumeEx**)ppv);
else if (IsEqualIID(riid, &IID_IAudioSessionManager)
|| IsEqualIID(riid, &IID_IAudioSessionManager2))
{
if (SUCCEEDED(hr))
{
IPersistPropertyBag *ppb;
- hr = IUnknown_QueryInterface((IUnknown*)*ppv, &IID_IPersistPropertyBag, (void*)&ppb);
+ hr = IUnknown_QueryInterface((IUnknown*)*ppv, &IID_IPersistPropertyBag, (void **)&ppb);
if (SUCCEEDED(hr))
{
/* ::Load cannot assume the interface stays alive after the function returns,
IDirectSound_Release((IDirectSound*)*ppv);
}
}
- else if (IsEqualIID(riid, &IID_IDirectSoundCapture)
- || IsEqualIID(riid, &IID_IDirectSoundCapture8))
+ else if (IsEqualIID(riid, &IID_IDirectSoundCapture))
{
if (This->flow == eCapture)
hr = CoCreateInstance(&CLSID_DirectSoundCapture8, NULL, clsctx, riid, ppv);
return E_POINTER;
if (IsEqualIID(riid, &IID_IUnknown)
|| IsEqualIID(riid, &IID_IMMDeviceCollection))
- *ppv = This;
+ *ppv = &This->IMMDeviceCollection_iface;
else
*ppv = NULL;
if (!*ppv)
load_driver_devices(eRender);
load_driver_devices(eCapture);
}
- return IUnknown_QueryInterface((IUnknown*)This, riid, ppv);
+ return IMMDeviceEnumerator_QueryInterface(&This->IMMDeviceEnumerator_iface, riid, ppv);
}
void MMDevEnum_Free(void)
return E_POINTER;
if (IsEqualIID(riid, &IID_IUnknown)
|| IsEqualIID(riid, &IID_IMMDeviceEnumerator))
- *ppv = This;
+ *ppv = &This->IMMDeviceEnumerator_iface;
else
*ppv = NULL;
if (!*ppv)
for (i = 0; i < MMDevice_count; ++i)
{
+ HRESULT hr;
WCHAR *str;
dev = &MMDevice_head[i]->IMMDevice_iface;
- IMMDevice_GetId(dev, &str);
+ hr = IMMDevice_GetId(dev, &str);
+ if (FAILED(hr))
+ {
+ WARN("GetId failed: %08x\n", hr);
+ continue;
+ }
if (str && !lstrcmpW(str, name))
{
notify_clients(flow, eMultimedia, id);
}
-static int notify_if_changed(EDataFlow flow, ERole role, HKEY key,
- const WCHAR *val_name, WCHAR *old_val, IMMDevice *def_dev)
+static BOOL notify_if_changed(EDataFlow flow, ERole role, HKEY key,
+ const WCHAR *val_name, WCHAR *old_val, IMMDevice *def_dev)
{
WCHAR new_val[64], *id;
DWORD size;
hr = IMMDevice_GetId(def_dev, &id);
if(FAILED(hr)){
ERR("GetId failed: %08x\n", hr);
- return 0;
+ return FALSE;
}
}else
id = NULL;
old_val[0] = 0;
CoTaskMemFree(id);
- return 1;
+ return TRUE;
}
/* system default -> system default, noop */
- return 0;
+ return FALSE;
}
if(!lstrcmpW(old_val, new_val)){
/* set by user -> same value */
- return 0;
+ return FALSE;
}
if(new_val[0] != 0){
/* set by user -> different value */
notify_clients(flow, role, new_val);
memcpy(old_val, new_val, sizeof(new_val));
- return 1;
+ return TRUE;
}
/* set by user -> system default */
hr = IMMDevice_GetId(def_dev, &id);
if(FAILED(hr)){
ERR("GetId failed: %08x\n", hr);
- return 0;
+ return FALSE;
}
}else
id = NULL;
old_val[0] = 0;
CoTaskMemFree(id);
- return 1;
+ return TRUE;
}
static DWORD WINAPI notif_thread_proc(void *user)
static HRESULT WINAPI MMDevEnum_UnregisterEndpointNotificationCallback(IMMDeviceEnumerator *iface, IMMNotificationClient *client)
{
MMDevEnumImpl *This = impl_from_IMMDeviceEnumerator(iface);
- struct NotificationClientWrapper *wrapper, *wrapper2;
+ struct NotificationClientWrapper *wrapper;
TRACE("(%p)->(%p)\n", This, client);
EnterCriticalSection(&g_notif_lock);
- LIST_FOR_EACH_ENTRY_SAFE(wrapper, wrapper2, &g_notif_clients,
- struct NotificationClientWrapper, entry){
+ LIST_FOR_EACH_ENTRY(wrapper, &g_notif_clients, struct NotificationClientWrapper, entry){
if(wrapper->client == client){
list_remove(&wrapper->entry);
HeapFree(GetProcessHeap(), 0, wrapper);
return E_POINTER;
if (IsEqualIID(riid, &IID_IUnknown)
|| IsEqualIID(riid, &IID_IPropertyStore))
- *ppv = This;
+ *ppv = &This->IPropertyStore_iface;
else
*ppv = NULL;
if (!*ppv)
*nprops = 0;
do {
DWORD len = sizeof(buffer)/sizeof(*buffer);
- if (RegEnumKeyExW(propkey, i, buffer, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
+ if (RegEnumValueW(propkey, i, buffer, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
break;
i++;
- } while (0);
+ } while (1);
RegCloseKey(propkey);
TRACE("Returning %i\n", i);
*nprops = i;
if (FAILED(hr))
return hr;
- if (RegEnumKeyExW(propkey, prop, buffer, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS
- || len <= 40)
+ if (RegEnumValueW(propkey, prop, buffer, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS
+ || len <= 39)
{
WARN("GetAt %u failed\n", prop);
return E_INVALIDARG;
}
RegCloseKey(propkey);
- buffer[39] = 0;
+ buffer[38] = 0;
CLSIDFromString(buffer, &key->fmtid);
- key->pid = atoiW(&buffer[40]);
+ key->pid = atoiW(&buffer[39]);
return S_OK;
}
static HRESULT WINAPI MMDevPropStore_Commit(IPropertyStore *iface)
{
- FIXME("stub\n");
- return E_NOTIMPL;
+ MMDevPropStore *This = impl_from_IPropertyStore(iface);
+ TRACE("(%p)\n", iface);
+
+ if (This->access != STGM_WRITE
+ && This->access != STGM_READWRITE)
+ return STG_E_ACCESSDENIED;
+
+ /* Does nothing - for mmdevapi, the propstore values are written on SetValue,
+ * not on Commit. */
+
+ return S_OK;
}
static const IPropertyStoreVtbl MMDevPropVtbl =