mmdevapi: Implement MMDeviceCollection methods.
[wine] / dlls / mmdevapi / main.c
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 "config.h"
20
21 #include <stdarg.h>
22
23 #define CINTERFACE
24 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "wine/debug.h"
29
30 #include "initguid.h"
31 #include "ole2.h"
32 #include "mmdeviceapi.h"
33 #include "dshow.h"
34 #include "dsound.h"
35 #include "audioclient.h"
36 #include "endpointvolume.h"
37 #include "audiopolicy.h"
38 #include "devpkey.h"
39
40 #include "mmdevapi.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
43
44 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
45 {
46     TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
47
48     switch (fdwReason)
49     {
50         case DLL_PROCESS_ATTACH:
51             DisableThreadLibraryCalls(hinstDLL);
52             break;
53         case DLL_PROCESS_DETACH:
54             MMDevEnum_Free();
55             break;
56     }
57
58     return TRUE;
59 }
60
61 HRESULT WINAPI DllCanUnloadNow(void)
62 {
63     return S_FALSE;
64 }
65
66 typedef HRESULT (*FnCreateInstance)(REFIID riid, LPVOID *ppobj);
67
68 typedef struct {
69     const IClassFactoryVtbl *lpVtbl;
70     REFCLSID rclsid;
71     FnCreateInstance pfnCreateInstance;
72 } IClassFactoryImpl;
73
74 static HRESULT WINAPI
75 MMCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppobj)
76 {
77     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
78     TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
79     if (ppobj == NULL)
80         return E_POINTER;
81     if (IsEqualIID(riid, &IID_IUnknown) ||
82         IsEqualIID(riid, &IID_IClassFactory))
83     {
84         *ppobj = iface;
85         IUnknown_AddRef(iface);
86         return S_OK;
87     }
88     *ppobj = NULL;
89     return E_NOINTERFACE;
90 }
91
92 static ULONG WINAPI MMCF_AddRef(LPCLASSFACTORY iface)
93 {
94     return 2;
95 }
96
97 static ULONG WINAPI MMCF_Release(LPCLASSFACTORY iface)
98 {
99     /* static class, won't be freed */
100     return 1;
101 }
102
103 static HRESULT WINAPI MMCF_CreateInstance(
104     LPCLASSFACTORY iface,
105     LPUNKNOWN pOuter,
106     REFIID riid,
107     LPVOID *ppobj)
108 {
109     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
110     TRACE("(%p, %p, %s, %p)\n", This, pOuter, debugstr_guid(riid), ppobj);
111
112     if (pOuter)
113         return CLASS_E_NOAGGREGATION;
114
115     if (ppobj == NULL) {
116         WARN("invalid parameter\n");
117         return E_POINTER;
118     }
119     *ppobj = NULL;
120     return This->pfnCreateInstance(riid, ppobj);
121 }
122
123 static HRESULT WINAPI MMCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
124 {
125     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
126     FIXME("(%p, %d) stub!\n", This, dolock);
127     return S_OK;
128 }
129
130 static const IClassFactoryVtbl MMCF_Vtbl = {
131     MMCF_QueryInterface,
132     MMCF_AddRef,
133     MMCF_Release,
134     MMCF_CreateInstance,
135     MMCF_LockServer
136 };
137
138 static IClassFactoryImpl MMDEVAPI_CF[] = {
139     { &MMCF_Vtbl, &CLSID_MMDeviceEnumerator, (FnCreateInstance)MMDevEnum_Create }
140 };
141
142 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
143 {
144     int i = 0;
145     TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
146
147     if (ppv == NULL) {
148         WARN("invalid parameter\n");
149         return E_INVALIDARG;
150     }
151
152     *ppv = NULL;
153
154     if (!IsEqualIID(riid, &IID_IClassFactory) &&
155         !IsEqualIID(riid, &IID_IUnknown)) {
156         WARN("no interface for %s\n", debugstr_guid(riid));
157         return E_NOINTERFACE;
158     }
159
160     for (i = 0; i < sizeof(MMDEVAPI_CF)/sizeof(MMDEVAPI_CF[0]); ++i)
161     {
162         if (IsEqualGUID(rclsid, MMDEVAPI_CF[i].rclsid)) {
163             IUnknown_AddRef((IClassFactory*) &MMDEVAPI_CF[i]);
164             *ppv = &MMDEVAPI_CF[i];
165             return S_OK;
166         }
167         i++;
168     }
169
170     WARN("(%s, %s, %p): no class found.\n", debugstr_guid(rclsid),
171          debugstr_guid(riid), ppv);
172     return CLASS_E_CLASSNOTAVAILABLE;
173 }