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 "mmdeviceapi.h"
25 #include "audioclient.h"
26 #include "audiopolicy.h"
31 DEFINE_GUID(GUID_NULL
,0,0,0,0,0,0,0,0,0,0,0);
33 /* Some of the QueryInterface tests are really just to check if I got the IIDs right :) */
35 /* IMMDeviceCollection appears to have no QueryInterface method and instead forwards to mme */
36 static void test_collection(IMMDeviceEnumerator
*mme
, IMMDeviceCollection
*col
)
38 IMMDeviceCollection
*col2
;
39 IMMDeviceEnumerator
*mme2
;
46 /* collection doesn't keep a ref on parent */
47 IMMDeviceEnumerator_AddRef(mme
);
48 ref
= IMMDeviceEnumerator_Release(mme
);
49 ok(ref
== 2, "Reference count on parent is %u\n", ref
);
51 ref
= IMMDeviceCollection_AddRef(col
);
52 IMMDeviceCollection_Release(col
);
53 ok(ref
== 2, "Invalid reference count %u on collection\n", ref
);
55 hr
= IMMDeviceCollection_QueryInterface(col
, &IID_IUnknown
, NULL
);
56 ok(hr
== E_POINTER
, "Null ppv returns %08x\n", hr
);
58 hr
= IMMDeviceCollection_QueryInterface(col
, &IID_IUnknown
, (void**)&unk
);
59 ok(hr
== S_OK
, "Cannot query for IID_IUnknown: 0x%08x\n", hr
);
62 ok((IUnknown
*)col
== unk
, "Pointers are not identical %p/%p/%p\n", col
, unk
, mme
);
63 IUnknown_Release(unk
);
66 hr
= IMMDeviceCollection_QueryInterface(col
, &IID_IMMDeviceCollection
, (void**)&col2
);
67 ok(hr
== S_OK
, "Cannot query for IID_IMMDeviceCollection: 0x%08x\n", hr
);
69 IMMDeviceCollection_Release(col2
);
71 hr
= IMMDeviceCollection_QueryInterface(col
, &IID_IMMDeviceEnumerator
, (void**)&mme2
);
72 ok(hr
== E_NOINTERFACE
, "Query for IID_IMMDeviceEnumerator returned: 0x%08x\n", hr
);
74 IMMDeviceEnumerator_Release(mme2
);
76 hr
= IMMDeviceCollection_GetCount(col
, NULL
);
77 ok(hr
== E_POINTER
, "GetCount returned 0x%08x\n", hr
);
79 hr
= IMMDeviceCollection_GetCount(col
, &numdev
);
80 ok(hr
== S_OK
, "GetCount returned 0x%08x\n", hr
);
82 dev
= (void*)(LONG_PTR
)0x12345678;
83 hr
= IMMDeviceCollection_Item(col
, numdev
, &dev
);
84 ok(hr
== E_INVALIDARG
, "Asking for too high device returned 0x%08x\n", hr
);
85 ok(dev
== NULL
, "Returned non-null device\n");
89 hr
= IMMDeviceCollection_Item(col
, 0, NULL
);
90 ok(hr
== E_POINTER
, "Query with null pointer returned 0x%08x\n", hr
);
92 hr
= IMMDeviceCollection_Item(col
, 0, &dev
);
93 ok(hr
== S_OK
, "Valid Item returned 0x%08x\n", hr
);
94 ok(dev
!= NULL
, "Device is null!\n");
99 if (IMMDevice_GetId(dev
, &id
) == S_OK
)
103 temp
[sizeof(temp
)-1] = 0;
104 WideCharToMultiByte(CP_ACP
, 0, id
, -1, temp
, sizeof(temp
)-1, NULL
, NULL
);
105 trace("Device found: %s\n", temp
);
107 hr
= IMMDeviceEnumerator_GetDevice(mme
, id
, &dev2
);
108 ok(hr
== S_OK
, "GetDevice failed: %08x\n", hr
);
110 IMMDevice_Release(dev2
);
116 IMMDevice_Release(dev
);
118 IMMDeviceCollection_Release(col
);
121 static HRESULT WINAPI
notif_QueryInterface(IMMNotificationClient
*iface
,
122 const GUID
*riid
, void **obj
)
124 ok(0, "Unexpected QueryInterface call\n");
128 static ULONG WINAPI
notif_AddRef(IMMNotificationClient
*iface
)
130 ok(0, "Unexpected AddRef call\n");
134 static ULONG WINAPI
notif_Release(IMMNotificationClient
*iface
)
136 ok(0, "Unexpected Release call\n");
140 static HRESULT WINAPI
notif_OnDeviceStateChanged(IMMNotificationClient
*iface
,
141 const WCHAR
*device_id
, DWORD new_state
)
143 ok(0, "Unexpected OnDeviceStateChanged call\n");
147 static HRESULT WINAPI
notif_OnDeviceAdded(IMMNotificationClient
*iface
,
148 const WCHAR
*device_id
)
150 ok(0, "Unexpected OnDeviceAdded call\n");
154 static HRESULT WINAPI
notif_OnDeviceRemoved(IMMNotificationClient
*iface
,
155 const WCHAR
*device_id
)
157 ok(0, "Unexpected OnDeviceRemoved call\n");
161 static HRESULT WINAPI
notif_OnDefaultDeviceChanged(IMMNotificationClient
*iface
,
162 EDataFlow flow
, ERole role
, const WCHAR
*device_id
)
164 ok(0, "Unexpected OnDefaultDeviceChanged call\n");
168 static HRESULT WINAPI
notif_OnPropertyValueChanged(IMMNotificationClient
*iface
,
169 const WCHAR
*device_id
, const PROPERTYKEY key
)
171 ok(0, "Unexpected OnPropertyValueChanged call\n");
175 static IMMNotificationClientVtbl notif_vtbl
= {
176 notif_QueryInterface
,
179 notif_OnDeviceStateChanged
,
181 notif_OnDeviceRemoved
,
182 notif_OnDefaultDeviceChanged
,
183 notif_OnPropertyValueChanged
186 static IMMNotificationClient notif
= { ¬if_vtbl
};
188 /* Only do parameter tests here, the actual MMDevice testing should be a separate test */
189 START_TEST(mmdevenum
)
191 static const WCHAR not_a_deviceW
[] = {'n','o','t','a','d','e','v','i','c','e',0};
194 IUnknown
*unk
= NULL
;
195 IMMDeviceEnumerator
*mme
, *mme2
;
197 IMMDeviceCollection
*col
;
200 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
201 hr
= CoCreateInstance(&CLSID_MMDeviceEnumerator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMMDeviceEnumerator
, (void**)&mme
);
204 skip("mmdevapi not available: 0x%08x\n", hr
);
208 /* Odd behavior.. bug? */
209 ref
= IMMDeviceEnumerator_AddRef(mme
);
210 ok(ref
== 3, "Invalid reference count after incrementing: %u\n", ref
);
211 IMMDeviceEnumerator_Release(mme
);
213 hr
= IMMDeviceEnumerator_QueryInterface(mme
, &IID_IUnknown
, (void**)&unk
);
214 ok(hr
== S_OK
, "returned 0x%08x\n", hr
);
215 if (hr
!= S_OK
) return;
217 ok( (LONG_PTR
)mme
== (LONG_PTR
)unk
, "Pointers are unequal %p/%p\n", unk
, mme
);
218 IUnknown_Release(unk
);
220 /* Proving that it is static.. */
221 hr
= CoCreateInstance(&CLSID_MMDeviceEnumerator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMMDeviceEnumerator
, (void**)&mme2
);
222 ok(hr
== S_OK
, "CoCreateInstance failed: 0x%08x\n", hr
);
223 IMMDeviceEnumerator_Release(mme2
);
224 ok(mme
== mme2
, "Pointers are not equal!\n");
226 hr
= IMMDeviceEnumerator_QueryInterface(mme
, &IID_IUnknown
, NULL
);
227 ok(hr
== E_POINTER
, "Null pointer on QueryInterface returned %08x\n", hr
);
229 hr
= IMMDeviceEnumerator_QueryInterface(mme
, &GUID_NULL
, (void**)&unk
);
230 ok(!unk
, "Unk not reset to null after invalid QI\n");
231 ok(hr
== E_NOINTERFACE
, "Invalid hr %08x returned on IID_NULL\n", hr
);
233 hr
= IMMDeviceEnumerator_GetDevice(mme
, not_a_deviceW
, NULL
);
234 ok(hr
== E_POINTER
, "GetDevice gave wrong error: %08x\n", hr
);
236 hr
= IMMDeviceEnumerator_GetDevice(mme
, NULL
, &dev
);
237 ok(hr
== E_POINTER
, "GetDevice gave wrong error: %08x\n", hr
);
239 hr
= IMMDeviceEnumerator_GetDevice(mme
, not_a_deviceW
, &dev
);
240 ok(hr
== E_INVALIDARG
, "GetDevice gave wrong error: %08x\n", hr
);
242 col
= (void*)(LONG_PTR
)0x12345678;
243 hr
= IMMDeviceEnumerator_EnumAudioEndpoints(mme
, 0xffff, DEVICE_STATEMASK_ALL
, &col
);
244 ok(hr
== E_INVALIDARG
, "Setting invalid data flow returned 0x%08x\n", hr
);
245 ok(col
== NULL
, "Collection pointer non-null on failure\n");
247 hr
= IMMDeviceEnumerator_EnumAudioEndpoints(mme
, eAll
, DEVICE_STATEMASK_ALL
+1, &col
);
248 ok(hr
== E_INVALIDARG
, "Setting invalid mask returned 0x%08x\n", hr
);
250 hr
= IMMDeviceEnumerator_EnumAudioEndpoints(mme
, eAll
, DEVICE_STATEMASK_ALL
, NULL
);
251 ok(hr
== E_POINTER
, "Invalid pointer returned: 0x%08x\n", hr
);
253 hr
= IMMDeviceEnumerator_EnumAudioEndpoints(mme
, eAll
, DEVICE_STATEMASK_ALL
, &col
);
254 ok(hr
== S_OK
, "Valid EnumAudioEndpoints returned 0x%08x\n", hr
);
257 ok(!!col
, "Returned null pointer\n");
259 test_collection(mme
, col
);
262 hr
= IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme
, NULL
);
263 ok(hr
== E_POINTER
, "RegisterEndpointNotificationCallback failed: %08x\n", hr
);
265 hr
= IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme
, ¬if
);
266 ok(hr
== S_OK
, "RegisterEndpointNotificationCallback failed: %08x\n", hr
);
268 hr
= IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme
, ¬if
);
269 ok(hr
== S_OK
, "RegisterEndpointNotificationCallback failed: %08x\n", hr
);
271 hr
= IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme
, NULL
);
272 ok(hr
== E_POINTER
, "UnregisterEndpointNotificationCallback failed: %08x\n", hr
);
274 hr
= IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme
, (IMMNotificationClient
*)0xdeadbeef);
275 ok(hr
== E_NOTFOUND
, "UnregisterEndpointNotificationCallback failed: %08x\n", hr
);
277 hr
= IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme
, ¬if
);
278 ok(hr
== S_OK
, "UnregisterEndpointNotificationCallback failed: %08x\n", hr
);
280 hr
= IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme
, ¬if
);
281 ok(hr
== S_OK
, "UnregisterEndpointNotificationCallback failed: %08x\n", hr
);
283 hr
= IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme
, ¬if
);
284 ok(hr
== E_NOTFOUND
, "UnregisterEndpointNotificationCallback failed: %08x\n", hr
);
286 IMMDeviceEnumerator_Release(mme
);