user32/tests: Accept DISP_CHANGE_RESTART also for tests expected to fail.
[wine] / dlls / qcap / qcap_main.c
1 /*
2  * Qcap implementation, dllentry points
3  *
4  * Copyright (C) 2003 Dominik Strasser
5  * Copyright (C) 2005 Rolf Kalbermatter
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 #include "config.h"
22
23 #include <assert.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26
27 #define COBJMACROS
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winerror.h"
35 #include "objbase.h"
36 #include "uuids.h"
37 #include "strmif.h"
38
39 #include "dllsetup.h"
40 #include "qcap_main.h"
41
42 #include "wine/unicode.h"
43 #include "wine/debug.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
46
47 static LONG objects_ref = 0;
48 static LONG server_locks = 0;
49
50 static const WCHAR wAudioCaptFilter[] =
51 {'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',0};
52 static const WCHAR wAVICompressor[] =
53 {'A','V','I',' ','C','o','m','p','r','e','s','s','o','r',0};
54 static const WCHAR wVFWCaptFilter[] =
55 {'V','F','W',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',0};
56 static const WCHAR wVFWCaptFilterProp[] =
57 {'V','F','W',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',' ',
58  'P','r','o','p','e','r','t','y',' ','P','a','g','e',0};
59 static const WCHAR wAVIMux[] =
60 {'A','V','I',' ','m','u','x',0};
61 static const WCHAR wAVIMuxPropPage[] =
62 {'A','V','I',' ','m','u','x',' ','P','r','o','p','e','r','t','y',' ','P','a','g','e',0};
63 static const WCHAR wAVIMuxPropPage1[] =
64 {'A','V','I',' ','m','u','x',' ','P','r','o','p','e','r','t','y',' ','P','a','g','e','1',0};
65 static const WCHAR wFileWriter[] =
66 {'F','i','l','e',' ','W','r','i','t','e','r',0};
67 static const WCHAR wCaptGraphBuilder[] =
68 {'C','a','p','t','u','r','e',' ','G','r','a','p','h',' ','B','u','i','l','d','e','r',0};
69 static const WCHAR wCaptGraphBuilder2[] =
70 {'C','a','p','t','u','r','e',' ','G','r','a','p','h',' ','B','u','i','l','d','e','r','2',0};
71 static const WCHAR wInfPinTeeFilter[] =
72 {'I','n','f','i','n','i','t','e',' ','P','i','n',' ','T','e','e',' ','F','i',
73  'l','t','e','r',0};
74 static const WCHAR wSmartTeeFilter[] =
75 {'S','m','a','r','t',' ','T','e','e',' ','F','i','l','t','e','r',0};
76 static const WCHAR wAudioInMixerProp[] =
77 {'A','u','d','i','o','I','n','p','u','t','M','i','x','e','r',' ','P','r','o',
78  'p','e','r','t','y',' ','P','a','g','e',0};
79  
80 static CFactoryTemplate const g_cTemplates[] = {
81 /*
82     {
83         wAudioCaptureFilter, 
84         &CLSID_AudioCaptureFilter,
85         QCAP_createAudioCaptureFilter,
86         NULL
87     },{
88         wAVICompressor, 
89         &CLSID_AVICompressor, 
90         QCAP_createAVICompressor,
91         NULL
92     },*/{
93         wVFWCaptFilter,
94         &CLSID_VfwCapture,
95         QCAP_createVFWCaptureFilter,
96         NULL
97     },/*{
98         wVFWCaptFilterProp,
99         &CLSID_VFWCaptureFilterPropertyPage,
100         QCAP_createVFWCaptureFilterPropertyPage,
101         NULL
102     },{
103         wAVIMux,
104         &CLSID_AVImux,
105         QCAP_createAVImux,
106         NULL
107     },{
108         wAVIMuxPropPage,
109         &CLSID_AVImuxPropertyPage,
110         QCAP_createAVImuxPropertyPage,
111         NULL
112     },{
113         wAVIMuxPropPage1,
114         &CLSID_AVImuxPropertyPage1,
115         QCAP_createAVImuxPropertyPage1,
116         NULL
117     },{
118         wFileWriter,
119         &CLSID_FileWriter,
120         QCAP_createFileWriter,
121         NULL
122     },*/{
123         wCaptGraphBuilder,
124         &CLSID_CaptureGraphBuilder,
125         QCAP_createCaptureGraphBuilder2,
126         NULL
127     },{
128         wCaptGraphBuilder2,
129         &CLSID_CaptureGraphBuilder2,
130         QCAP_createCaptureGraphBuilder2,
131         NULL
132     }/*,{
133         wInfPinTeeFilter, 
134         &CLSID_InfinitePinTeeFilter, 
135         QCAP_createInfinitePinTeeFilter,
136         NULL
137     },{
138         wSmartTeeFilter,
139         &CLSID_SmartTeeFilter,
140         QCAP_createSmartTeeFilter,
141         NULL
142     },{
143         wAudioInMixerProp,
144         &CLSID_AudioInputMixerPropertyPage,
145         QCAP_createAudioInputMixerPropertyPage,
146         NULL
147     }*/
148 };
149
150 static int g_numTemplates = sizeof(g_cTemplates) / sizeof(g_cTemplates[0]);
151
152 /***********************************************************************
153  *    Dll EntryPoint (QCAP.@)
154  */
155 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
156 {
157     switch (fdwReason)
158     {
159         case DLL_PROCESS_ATTACH:
160             DisableThreadLibraryCalls(hInstDLL);
161             SetupInitializeServers(g_cTemplates, g_numTemplates, TRUE);
162             break;
163         case DLL_PROCESS_DETACH:
164             SetupInitializeServers(g_cTemplates, g_numTemplates, FALSE);
165             break;
166     }
167     return TRUE;
168 }
169
170 /***********************************************************************
171  *    DllRegisterServer (QCAP.@)
172  */
173 HRESULT WINAPI DllRegisterServer(void)
174 {
175     TRACE("()\n");
176
177     return SetupRegisterServers(g_cTemplates, g_numTemplates, TRUE);
178 }
179
180 /***********************************************************************
181  *    DllUnregisterServer (QCAP.@)
182  */
183 HRESULT WINAPI DllUnregisterServer(void)
184 {
185     TRACE("\n");
186
187     return SetupRegisterServers(g_cTemplates, g_numTemplates, FALSE);
188 }
189
190 /***********************************************************************
191  *    DllCanUnloadNow (QCAP.@)
192  */
193 HRESULT WINAPI DllCanUnloadNow(void)
194 {
195     TRACE("\n");
196
197     if (objects_ref == 0 && server_locks == 0)
198         return S_OK;
199     return S_FALSE;     
200 }
201
202 /******************************************************************************
203  * DLL ClassFactory
204  */
205 typedef struct {
206     IClassFactory ITF_IClassFactory;
207
208     LONG ref;
209     LPFNNewCOMObject pfnCreateInstance;
210 } IClassFactoryImpl;
211
212 static HRESULT WINAPI
213 DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
214 {
215     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
216
217     if (IsEqualGUID(riid, &IID_IUnknown) ||
218         IsEqualGUID(riid, &IID_IClassFactory))
219     {
220         IClassFactory_AddRef(iface);
221         *ppobj = This;
222         return S_OK;
223     }
224
225     WARN("(%p)->(%s,%p), not found\n", This, debugstr_guid(riid), ppobj);
226     return E_NOINTERFACE;
227 }
228
229 static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface)
230 {
231     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
232     return InterlockedIncrement(&This->ref);
233 }
234
235 static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface)
236 {
237     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
238
239     ULONG ref = InterlockedDecrement(&This->ref);
240
241     if (ref == 0)
242         HeapFree(GetProcessHeap(), 0, This);
243
244     return ref;
245 }
246
247 static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
248                                           REFIID riid, LPVOID *ppobj)
249 {
250     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
251     HRESULT hres = ERROR_SUCCESS;
252     LPUNKNOWN punk;
253
254     TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
255
256     if (!ppobj)
257         return E_POINTER;
258
259     /* Enforce the normal OLE rules regarding interfaces and delegation */
260     if (pOuter && !IsEqualGUID(riid, &IID_IUnknown))
261         return E_NOINTERFACE;
262
263     *ppobj = NULL;
264     punk = This->pfnCreateInstance(pOuter, &hres);
265     if (!punk)
266     {
267         /* No object created, update error if it isn't done already and return */
268         if (SUCCEEDED(hres))
269             hres = E_OUTOFMEMORY;
270     return hres;
271     }
272
273     if (SUCCEEDED(hres))
274     {
275         hres = IUnknown_QueryInterface(punk, riid, ppobj);
276     }
277     /* Releasing the object. If everything was successful, QueryInterface
278        should have incremented the refcount once more, otherwise this will
279        purge the object. */
280     IUnknown_Release(punk);
281     return hres;
282 }
283
284 static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
285 {
286     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
287     TRACE("(%p)->(%d)\n",This, dolock);
288
289     if (dolock)
290         InterlockedIncrement(&server_locks);
291     else
292         InterlockedDecrement(&server_locks);
293     return S_OK;
294 }
295
296 static const IClassFactoryVtbl DSCF_Vtbl =
297 {
298     DSCF_QueryInterface,
299     DSCF_AddRef,
300     DSCF_Release,
301     DSCF_CreateInstance,
302     DSCF_LockServer
303 };
304
305 /***********************************************************************
306  *    DllGetClassObject (QCAP.@)
307  */
308 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
309 {
310     const CFactoryTemplate *pList = g_cTemplates;
311     IClassFactoryImpl *factory;
312     int i;
313
314     TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
315
316     if (!ppv)
317         return E_POINTER;
318
319     *ppv = NULL;
320
321     if (!IsEqualGUID(&IID_IClassFactory, riid) &&
322         !IsEqualGUID(&IID_IUnknown, riid))
323         return E_NOINTERFACE;
324
325     for (i = 0; i < g_numTemplates; i++, pList++)
326     {
327         if (IsEqualGUID(pList->m_ClsID, rclsid))
328             break;
329     }
330
331     if (i == g_numTemplates)
332     {
333         FIXME("%s: no class found.\n", debugstr_guid(rclsid));
334         return CLASS_E_CLASSNOTAVAILABLE;
335     }
336
337     factory = HeapAlloc(GetProcessHeap(), 0, sizeof(IClassFactoryImpl));
338     if (!factory)
339         return E_OUTOFMEMORY;
340
341     factory->ITF_IClassFactory.lpVtbl = &DSCF_Vtbl;
342     factory->ref = 1;
343
344     factory->pfnCreateInstance = pList->m_lpfnNew;
345
346     *ppv = &(factory->ITF_IClassFactory);
347     return S_OK;
348 }
349
350 DWORD ObjectRefCount(BOOL increment)
351 {
352     if (increment)
353         return InterlockedIncrement(&objects_ref);
354     return InterlockedDecrement(&objects_ref);
355 }