2 * Copyright 2009 Maarten Lankhorst
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
19 #include "wine/test.h"
24 #include "endpointvolume.h"
25 #include "mmdeviceapi.h"
26 #include "audioclient.h"
27 #include "audiopolicy.h"
32 DEFINE_GUID(GUID_NULL
,0,0,0,0,0,0,0,0,0,0,0);
34 /* Some of the QueryInterface tests are really just to check if I got the IIDs right :) */
36 /* IMMDeviceCollection appears to have no QueryInterface method and instead forwards to mme */
37 static void test_collection(IMMDeviceEnumerator
*mme
, IMMDeviceCollection
*col
)
39 IMMDeviceCollection
*col2
;
40 IMMDeviceEnumerator
*mme2
;
47 /* collection doesn't keep a ref on parent */
48 IMMDeviceEnumerator_AddRef(mme
);
49 ref
= IMMDeviceEnumerator_Release(mme
);
50 ok(ref
== 2, "Reference count on parent is %u\n", ref
);
52 ref
= IMMDeviceCollection_AddRef(col
);
53 IMMDeviceCollection_Release(col
);
54 ok(ref
== 2, "Invalid reference count %u on collection\n", ref
);
56 hr
= IMMDeviceCollection_QueryInterface(col
, &IID_IUnknown
, NULL
);
57 ok(hr
== E_POINTER
, "Null ppv returns %08x\n", hr
);
59 hr
= IMMDeviceCollection_QueryInterface(col
, &IID_IUnknown
, (void**)&unk
);
60 ok(hr
== S_OK
, "Cannot query for IID_IUnknown: 0x%08x\n", hr
);
63 ok((IUnknown
*)col
== unk
, "Pointers are not identical %p/%p/%p\n", col
, unk
, mme
);
64 IUnknown_Release(unk
);
67 hr
= IMMDeviceCollection_QueryInterface(col
, &IID_IMMDeviceCollection
, (void**)&col2
);
68 ok(hr
== S_OK
, "Cannot query for IID_IMMDeviceCollection: 0x%08x\n", hr
);
70 IMMDeviceCollection_Release(col2
);
72 hr
= IMMDeviceCollection_QueryInterface(col
, &IID_IMMDeviceEnumerator
, (void**)&mme2
);
73 ok(hr
== E_NOINTERFACE
, "Query for IID_IMMDeviceEnumerator returned: 0x%08x\n", hr
);
75 IMMDeviceEnumerator_Release(mme2
);
77 hr
= IMMDeviceCollection_GetCount(col
, NULL
);
78 ok(hr
== E_POINTER
, "GetCount returned 0x%08x\n", hr
);
80 hr
= IMMDeviceCollection_GetCount(col
, &numdev
);
81 ok(hr
== S_OK
, "GetCount returned 0x%08x\n", hr
);
83 dev
= (void*)(LONG_PTR
)0x12345678;
84 hr
= IMMDeviceCollection_Item(col
, numdev
, &dev
);
85 ok(hr
== E_INVALIDARG
, "Asking for too high device returned 0x%08x\n", hr
);
86 ok(dev
== NULL
, "Returned non-null device\n");
90 hr
= IMMDeviceCollection_Item(col
, 0, NULL
);
91 ok(hr
== E_POINTER
, "Query with null pointer returned 0x%08x\n", hr
);
93 hr
= IMMDeviceCollection_Item(col
, 0, &dev
);
94 ok(hr
== S_OK
, "Valid Item returned 0x%08x\n", hr
);
95 ok(dev
!= NULL
, "Device is null!\n");
100 if (IMMDevice_GetId(dev
, &id
) == S_OK
)
104 temp
[sizeof(temp
)-1] = 0;
105 WideCharToMultiByte(CP_ACP
, 0, id
, -1, temp
, sizeof(temp
)-1, NULL
, NULL
);
106 trace("Device found: %s\n", temp
);
108 hr
= IMMDeviceEnumerator_GetDevice(mme
, id
, &dev2
);
109 ok(hr
== S_OK
, "GetDevice failed: %08x\n", hr
);
111 IMMDevice_Release(dev2
);
117 IMMDevice_Release(dev
);
119 IMMDeviceCollection_Release(col
);
122 static HRESULT WINAPI
notif_QueryInterface(IMMNotificationClient
*iface
,
123 const GUID
*riid
, void **obj
)
125 ok(0, "Unexpected QueryInterface call\n");
129 static ULONG WINAPI
notif_AddRef(IMMNotificationClient
*iface
)
131 ok(0, "Unexpected AddRef call\n");
135 static ULONG WINAPI
notif_Release(IMMNotificationClient
*iface
)
137 ok(0, "Unexpected Release call\n");
141 static HRESULT WINAPI
notif_OnDeviceStateChanged(IMMNotificationClient
*iface
,
142 const WCHAR
*device_id
, DWORD new_state
)
144 ok(0, "Unexpected OnDeviceStateChanged call\n");
148 static HRESULT WINAPI
notif_OnDeviceAdded(IMMNotificationClient
*iface
,
149 const WCHAR
*device_id
)
151 ok(0, "Unexpected OnDeviceAdded call\n");
155 static HRESULT WINAPI
notif_OnDeviceRemoved(IMMNotificationClient
*iface
,
156 const WCHAR
*device_id
)
158 ok(0, "Unexpected OnDeviceRemoved call\n");
162 static HRESULT WINAPI
notif_OnDefaultDeviceChanged(IMMNotificationClient
*iface
,
163 EDataFlow flow
, ERole role
, const WCHAR
*device_id
)
165 ok(0, "Unexpected OnDefaultDeviceChanged call\n");
169 static HRESULT WINAPI
notif_OnPropertyValueChanged(IMMNotificationClient
*iface
,
170 const WCHAR
*device_id
, const PROPERTYKEY key
)
172 ok(0, "Unexpected OnPropertyValueChanged call\n");
176 static IMMNotificationClientVtbl notif_vtbl
= {
177 notif_QueryInterface
,
180 notif_OnDeviceStateChanged
,
182 notif_OnDeviceRemoved
,
183 notif_OnDefaultDeviceChanged
,
184 notif_OnPropertyValueChanged
187 static IMMNotificationClient notif
= { ¬if_vtbl
};
189 /* Only do parameter tests here, the actual MMDevice testing should be a separate test */
190 START_TEST(mmdevenum
)
192 static const WCHAR not_a_deviceW
[] = {'n','o','t','a','d','e','v','i','c','e',0};
195 IUnknown
*unk
= NULL
;
196 IMMDeviceEnumerator
*mme
, *mme2
;
198 IMMDeviceCollection
*col
;
201 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
202 hr
= CoCreateInstance(&CLSID_MMDeviceEnumerator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMMDeviceEnumerator
, (void**)&mme
);
205 skip("mmdevapi not available: 0x%08x\n", hr
);
209 /* Odd behavior.. bug? */
210 ref
= IMMDeviceEnumerator_AddRef(mme
);
211 ok(ref
== 3, "Invalid reference count after incrementing: %u\n", ref
);
212 IMMDeviceEnumerator_Release(mme
);
214 hr
= IMMDeviceEnumerator_QueryInterface(mme
, &IID_IUnknown
, (void**)&unk
);
215 ok(hr
== S_OK
, "returned 0x%08x\n", hr
);
216 if (hr
!= S_OK
) return;
218 ok( (LONG_PTR
)mme
== (LONG_PTR
)unk
, "Pointers are unequal %p/%p\n", unk
, mme
);
219 IUnknown_Release(unk
);
221 /* Proving that it is static.. */
222 hr
= CoCreateInstance(&CLSID_MMDeviceEnumerator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMMDeviceEnumerator
, (void**)&mme2
);
223 ok(hr
== S_OK
, "CoCreateInstance failed: 0x%08x\n", hr
);
224 IMMDeviceEnumerator_Release(mme2
);
225 ok(mme
== mme2
, "Pointers are not equal!\n");
227 hr
= IMMDeviceEnumerator_QueryInterface(mme
, &IID_IUnknown
, NULL
);
228 ok(hr
== E_POINTER
, "Null pointer on QueryInterface returned %08x\n", hr
);
230 hr
= IMMDeviceEnumerator_QueryInterface(mme
, &GUID_NULL
, (void**)&unk
);
231 ok(!unk
, "Unk not reset to null after invalid QI\n");
232 ok(hr
== E_NOINTERFACE
, "Invalid hr %08x returned on IID_NULL\n", hr
);
234 hr
= IMMDeviceEnumerator_GetDevice(mme
, not_a_deviceW
, NULL
);
235 ok(hr
== E_POINTER
, "GetDevice gave wrong error: %08x\n", hr
);
237 hr
= IMMDeviceEnumerator_GetDevice(mme
, NULL
, &dev
);
238 ok(hr
== E_POINTER
, "GetDevice gave wrong error: %08x\n", hr
);
240 hr
= IMMDeviceEnumerator_GetDevice(mme
, not_a_deviceW
, &dev
);
241 ok(hr
== E_INVALIDARG
, "GetDevice gave wrong error: %08x\n", hr
);
243 col
= (void*)(LONG_PTR
)0x12345678;
244 hr
= IMMDeviceEnumerator_EnumAudioEndpoints(mme
, 0xffff, DEVICE_STATEMASK_ALL
, &col
);
245 ok(hr
== E_INVALIDARG
, "Setting invalid data flow returned 0x%08x\n", hr
);
246 ok(col
== NULL
, "Collection pointer non-null on failure\n");
248 hr
= IMMDeviceEnumerator_EnumAudioEndpoints(mme
, eAll
, DEVICE_STATEMASK_ALL
+1, &col
);
249 ok(hr
== E_INVALIDARG
, "Setting invalid mask returned 0x%08x\n", hr
);
251 hr
= IMMDeviceEnumerator_EnumAudioEndpoints(mme
, eAll
, DEVICE_STATEMASK_ALL
, NULL
);
252 ok(hr
== E_POINTER
, "Invalid pointer returned: 0x%08x\n", hr
);
254 hr
= IMMDeviceEnumerator_EnumAudioEndpoints(mme
, eAll
, DEVICE_STATEMASK_ALL
, &col
);
255 ok(hr
== S_OK
, "Valid EnumAudioEndpoints returned 0x%08x\n", hr
);
258 ok(!!col
, "Returned null pointer\n");
260 test_collection(mme
, col
);
263 hr
= IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme
, NULL
);
264 ok(hr
== E_POINTER
, "RegisterEndpointNotificationCallback failed: %08x\n", hr
);
266 hr
= IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme
, ¬if
);
267 ok(hr
== S_OK
, "RegisterEndpointNotificationCallback failed: %08x\n", hr
);
269 hr
= IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme
, ¬if
);
270 ok(hr
== S_OK
, "RegisterEndpointNotificationCallback failed: %08x\n", hr
);
272 hr
= IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme
, NULL
);
273 ok(hr
== E_POINTER
, "UnregisterEndpointNotificationCallback failed: %08x\n", hr
);
275 hr
= IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme
, (IMMNotificationClient
*)0xdeadbeef);
276 ok(hr
== E_NOTFOUND
, "UnregisterEndpointNotificationCallback failed: %08x\n", hr
);
278 hr
= IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme
, ¬if
);
279 ok(hr
== S_OK
, "UnregisterEndpointNotificationCallback failed: %08x\n", hr
);
281 hr
= IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme
, ¬if
);
282 ok(hr
== S_OK
, "UnregisterEndpointNotificationCallback failed: %08x\n", hr
);
284 hr
= IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme
, ¬if
);
285 ok(hr
== E_NOTFOUND
, "UnregisterEndpointNotificationCallback failed: %08x\n", hr
);
287 IMMDeviceEnumerator_Release(mme
);