ReactOS 0.4.15-dev-7918-g2a2556c
mmdevenum.c
Go to the documentation of this file.
1/*
2 * Copyright 2009 Maarten Lankhorst
3 *
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.
8 *
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.
13 *
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
17 */
18
19#include "wine/test.h"
20
21#define COBJMACROS
22
23#include "initguid.h"
24#ifndef __REACTOS__
25#include "endpointvolume.h"
26#endif
27#include "mmdeviceapi.h"
28#include "audioclient.h"
29#include "audiopolicy.h"
30#include "dshow.h"
31#include "dsound.h"
32#include "devpkey.h"
33
34DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
35
36/* Some of the QueryInterface tests are really just to check if I got the IIDs right :) */
37
38/* IMMDeviceCollection appears to have no QueryInterface method and instead forwards to mme */
40{
43 IUnknown *unk;
44 HRESULT hr;
45 ULONG ref;
46 UINT numdev;
48
49 /* collection doesn't keep a ref on parent */
50 IMMDeviceEnumerator_AddRef(mme);
51 ref = IMMDeviceEnumerator_Release(mme);
52 ok(ref == 2, "Reference count on parent is %u\n", ref);
53
54 ref = IMMDeviceCollection_AddRef(col);
55 IMMDeviceCollection_Release(col);
56 ok(ref == 2, "Invalid reference count %u on collection\n", ref);
57
58 hr = IMMDeviceCollection_QueryInterface(col, &IID_IUnknown, NULL);
59 ok(hr == E_POINTER, "Null ppv returns %08x\n", hr);
60
61 hr = IMMDeviceCollection_QueryInterface(col, &IID_IUnknown, (void**)&unk);
62 ok(hr == S_OK, "Cannot query for IID_IUnknown: 0x%08x\n", hr);
63 if (hr == S_OK)
64 {
65 ok((IUnknown*)col == unk, "Pointers are not identical %p/%p/%p\n", col, unk, mme);
66 IUnknown_Release(unk);
67 }
68
69 hr = IMMDeviceCollection_QueryInterface(col, &IID_IMMDeviceCollection, (void**)&col2);
70 ok(hr == S_OK, "Cannot query for IID_IMMDeviceCollection: 0x%08x\n", hr);
71 if (hr == S_OK)
72 IMMDeviceCollection_Release(col2);
73
74 hr = IMMDeviceCollection_QueryInterface(col, &IID_IMMDeviceEnumerator, (void**)&mme2);
75 ok(hr == E_NOINTERFACE, "Query for IID_IMMDeviceEnumerator returned: 0x%08x\n", hr);
76 if (hr == S_OK)
77 IMMDeviceEnumerator_Release(mme2);
78
79 hr = IMMDeviceCollection_GetCount(col, NULL);
80 ok(hr == E_POINTER, "GetCount returned 0x%08x\n", hr);
81
82 hr = IMMDeviceCollection_GetCount(col, &numdev);
83 ok(hr == S_OK, "GetCount returned 0x%08x\n", hr);
84
85 dev = (void*)(LONG_PTR)0x12345678;
86 hr = IMMDeviceCollection_Item(col, numdev, &dev);
87 ok(hr == E_INVALIDARG, "Asking for too high device returned 0x%08x\n", hr);
88 ok(dev == NULL, "Returned non-null device\n");
89
90 if (numdev)
91 {
92 hr = IMMDeviceCollection_Item(col, 0, NULL);
93 ok(hr == E_POINTER, "Query with null pointer returned 0x%08x\n", hr);
94
95 hr = IMMDeviceCollection_Item(col, 0, &dev);
96 ok(hr == S_OK, "Valid Item returned 0x%08x\n", hr);
97 ok(dev != NULL, "Device is null!\n");
98 if (dev != NULL)
99 {
100 char temp[128];
101 WCHAR *id = NULL;
102 if (IMMDevice_GetId(dev, &id) == S_OK)
103 {
104 IMMDevice *dev2;
105
106 temp[sizeof(temp)-1] = 0;
107 WideCharToMultiByte(CP_ACP, 0, id, -1, temp, sizeof(temp)-1, NULL, NULL);
108 trace("Device found: %s\n", temp);
109
110 hr = IMMDeviceEnumerator_GetDevice(mme, id, &dev2);
111 ok(hr == S_OK, "GetDevice failed: %08x\n", hr);
112
113 IMMDevice_Release(dev2);
114
115 CoTaskMemFree(id);
116 }
117 }
118 if (dev)
119 IMMDevice_Release(dev);
120 }
121 IMMDeviceCollection_Release(col);
122}
123
125 const GUID *riid, void **obj)
126{
127 ok(0, "Unexpected QueryInterface call\n");
128 return E_NOTIMPL;
129}
130
132{
133 ok(0, "Unexpected AddRef call\n");
134 return 2;
135}
136
138{
139 ok(0, "Unexpected Release call\n");
140 return 1;
141}
142
144 const WCHAR *device_id, DWORD new_state)
145{
146 ok(0, "Unexpected OnDeviceStateChanged call\n");
147 return E_NOTIMPL;
148}
149
151 const WCHAR *device_id)
152{
153 ok(0, "Unexpected OnDeviceAdded call\n");
154 return E_NOTIMPL;
155}
156
158 const WCHAR *device_id)
159{
160 ok(0, "Unexpected OnDeviceRemoved call\n");
161 return E_NOTIMPL;
162}
163
165 EDataFlow flow, ERole role, const WCHAR *device_id)
166{
167 ok(0, "Unexpected OnDefaultDeviceChanged call\n");
168 return E_NOTIMPL;
169}
170
172 const WCHAR *device_id, const PROPERTYKEY key)
173{
174 ok(0, "Unexpected OnPropertyValueChanged call\n");
175 return E_NOTIMPL;
176}
177
178static IMMNotificationClientVtbl notif_vtbl = {
187};
188
190
191/* Only do parameter tests here, the actual MMDevice testing should be a separate test */
192START_TEST(mmdevenum)
193{
194 static const WCHAR not_a_deviceW[] = {'n','o','t','a','d','e','v','i','c','e',0};
195
196 HRESULT hr;
197 IUnknown *unk = NULL;
198 IMMDeviceEnumerator *mme, *mme2;
199 ULONG ref;
201 IMMDevice *dev;
202
204 hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
205 if (FAILED(hr))
206 {
207 skip("mmdevapi not available: 0x%08x\n", hr);
208 return;
209 }
210
211 /* Odd behavior.. bug? */
212 ref = IMMDeviceEnumerator_AddRef(mme);
213 ok(ref == 3, "Invalid reference count after incrementing: %u\n", ref);
214 IMMDeviceEnumerator_Release(mme);
215
216 hr = IMMDeviceEnumerator_QueryInterface(mme, &IID_IUnknown, (void**)&unk);
217 ok(hr == S_OK, "returned 0x%08x\n", hr);
218 if (hr != S_OK) return;
219
220 ok( (LONG_PTR)mme == (LONG_PTR)unk, "Pointers are unequal %p/%p\n", unk, mme);
221 IUnknown_Release(unk);
222
223 /* Proving that it is static.. */
224 hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme2);
225 ok(hr == S_OK, "CoCreateInstance failed: 0x%08x\n", hr);
226 IMMDeviceEnumerator_Release(mme2);
227 ok(mme == mme2, "Pointers are not equal!\n");
228
229 hr = IMMDeviceEnumerator_QueryInterface(mme, &IID_IUnknown, NULL);
230 ok(hr == E_POINTER, "Null pointer on QueryInterface returned %08x\n", hr);
231
232 hr = IMMDeviceEnumerator_QueryInterface(mme, &GUID_NULL, (void**)&unk);
233 ok(!unk, "Unk not reset to null after invalid QI\n");
234 ok(hr == E_NOINTERFACE, "Invalid hr %08x returned on IID_NULL\n", hr);
235
236 hr = IMMDeviceEnumerator_GetDevice(mme, not_a_deviceW, NULL);
237 ok(hr == E_POINTER, "GetDevice gave wrong error: %08x\n", hr);
238
239 hr = IMMDeviceEnumerator_GetDevice(mme, NULL, &dev);
240 ok(hr == E_POINTER, "GetDevice gave wrong error: %08x\n", hr);
241
242 hr = IMMDeviceEnumerator_GetDevice(mme, not_a_deviceW, &dev);
243 ok(hr == E_INVALIDARG, "GetDevice gave wrong error: %08x\n", hr);
244
245 col = (void*)(LONG_PTR)0x12345678;
246 hr = IMMDeviceEnumerator_EnumAudioEndpoints(mme, 0xffff, DEVICE_STATEMASK_ALL, &col);
247 ok(hr == E_INVALIDARG, "Setting invalid data flow returned 0x%08x\n", hr);
248 ok(col == NULL, "Collection pointer non-null on failure\n");
249
250 hr = IMMDeviceEnumerator_EnumAudioEndpoints(mme, eAll, DEVICE_STATEMASK_ALL+1, &col);
251 ok(hr == E_INVALIDARG, "Setting invalid mask returned 0x%08x\n", hr);
252
253 hr = IMMDeviceEnumerator_EnumAudioEndpoints(mme, eAll, DEVICE_STATEMASK_ALL, NULL);
254 ok(hr == E_POINTER, "Invalid pointer returned: 0x%08x\n", hr);
255
256 hr = IMMDeviceEnumerator_EnumAudioEndpoints(mme, eAll, DEVICE_STATEMASK_ALL, &col);
257 ok(hr == S_OK, "Valid EnumAudioEndpoints returned 0x%08x\n", hr);
258 if (hr == S_OK)
259 {
260 ok(!!col, "Returned null pointer\n");
261 if (col)
262 test_collection(mme, col);
263 }
264
265 hr = IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme, NULL);
266 ok(hr == E_POINTER, "RegisterEndpointNotificationCallback failed: %08x\n", hr);
267
268 hr = IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme, &notif);
269 ok(hr == S_OK, "RegisterEndpointNotificationCallback failed: %08x\n", hr);
270
271 hr = IMMDeviceEnumerator_RegisterEndpointNotificationCallback(mme, &notif);
272 ok(hr == S_OK, "RegisterEndpointNotificationCallback failed: %08x\n", hr);
273
274 hr = IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme, NULL);
275 ok(hr == E_POINTER, "UnregisterEndpointNotificationCallback failed: %08x\n", hr);
276
277 hr = IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme, (IMMNotificationClient*)0xdeadbeef);
278 ok(hr == E_NOTFOUND, "UnregisterEndpointNotificationCallback failed: %08x\n", hr);
279
280 hr = IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme, &notif);
281 ok(hr == S_OK, "UnregisterEndpointNotificationCallback failed: %08x\n", hr);
282
283 hr = IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme, &notif);
284 ok(hr == S_OK, "UnregisterEndpointNotificationCallback failed: %08x\n", hr);
285
286 hr = IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(mme, &notif);
287 ok(hr == E_NOTFOUND, "UnregisterEndpointNotificationCallback failed: %08x\n", hr);
288
289 IMMDeviceEnumerator_Release(mme);
290}
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
const GUID IID_IUnknown
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define NULL
Definition: types.h:112
#define CP_ACP
Definition: compat.h:109
#define WideCharToMultiByte
Definition: compat.h:111
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
Definition: compobj.c:2002
unsigned long DWORD
Definition: ntddk_ex.h:95
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
#define GUID_NULL
Definition: ks.h:106
static HRESULT WINAPI notif_OnDeviceAdded(IMMNotificationClient *iface, const WCHAR *device_id)
Definition: mmdevenum.c:150
static void test_collection(IMMDeviceEnumerator *mme, IMMDeviceCollection *col)
Definition: mmdevenum.c:39
static HRESULT WINAPI notif_OnPropertyValueChanged(IMMNotificationClient *iface, const WCHAR *device_id, const PROPERTYKEY key)
Definition: mmdevenum.c:171
static IMMNotificationClientVtbl notif_vtbl
Definition: mmdevenum.c:178
static HRESULT WINAPI notif_OnDeviceStateChanged(IMMNotificationClient *iface, const WCHAR *device_id, DWORD new_state)
Definition: mmdevenum.c:143
static HRESULT WINAPI notif_QueryInterface(IMMNotificationClient *iface, const GUID *riid, void **obj)
Definition: mmdevenum.c:124
static HRESULT WINAPI notif_OnDeviceRemoved(IMMNotificationClient *iface, const WCHAR *device_id)
Definition: mmdevenum.c:157
static ULONG WINAPI notif_AddRef(IMMNotificationClient *iface)
Definition: mmdevenum.c:131
static IMMNotificationClient notif
Definition: mmdevenum.c:189
static HRESULT WINAPI notif_OnDefaultDeviceChanged(IMMNotificationClient *iface, EDataFlow flow, ERole role, const WCHAR *device_id)
Definition: mmdevenum.c:164
static ULONG WINAPI notif_Release(IMMNotificationClient *iface)
Definition: mmdevenum.c:137
enum _ERole ERole
@ eAll
Definition: mmdeviceapi.idl:65
enum _EDataFlow EDataFlow
static IMMDeviceEnumerator * mme
Definition: render.c:63
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
unsigned int UINT
Definition: ndis.h:50
@ COINIT_MULTITHREADED
Definition: objbase.h:279
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
Definition: guiddef.h:68
static calc_node_t temp
Definition: rpn_ieee.c:38
HRESULT hr
Definition: shlfolder.c:183
Definition: copy.c:22
Definition: send.c:48
uint32_t ULONG
Definition: typedefs.h:59
#define WINAPI
Definition: msvc.h:6
#define E_NOINTERFACE
Definition: winerror.h:2364
#define E_POINTER
Definition: winerror.h:2365
__wchar_t WCHAR
Definition: xmlstorage.h:180