Release 1.4.1.
[wine] / dlls / quartz / main.c
1 /*              DirectShow Base Functions (QUARTZ.DLL)
2  *
3  * Copyright 2002 Lionel Ulmer
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include "config.h"
21 #include "wine/debug.h"
22
23 #include "quartz_private.h"
24 #include "wine/unicode.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
27
28 extern HRESULT WINAPI QUARTZ_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC_HIDDEN;
29 extern HRESULT WINAPI QUARTZ_DllCanUnloadNow(void) DECLSPEC_HIDDEN;
30 extern BOOL WINAPI QUARTZ_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN;
31
32 static DWORD dll_ref = 0;
33
34 /* For the moment, do nothing here. */
35 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
36 {
37     if (fdwReason == DLL_PROCESS_DETACH)
38         video_unregister_windowclass();
39     return QUARTZ_DllMain( hInstDLL, fdwReason, lpv );
40 }
41
42 /******************************************************************************
43  * DirectShow ClassFactory
44  */
45 typedef struct {
46     IClassFactory ITF_IClassFactory;
47
48     LONG ref;
49     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
50 } IClassFactoryImpl;
51
52 struct object_creation_info
53 {
54     const CLSID *clsid;
55     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
56 };
57
58 static const struct object_creation_info object_creation[] =
59 {
60     { &CLSID_SeekingPassThru, SeekingPassThru_create },
61     { &CLSID_FilterGraph, FilterGraph_create },
62     { &CLSID_FilterGraphNoThread, FilterGraphNoThread_create },
63     { &CLSID_FilterMapper, FilterMapper_create },
64     { &CLSID_FilterMapper2, FilterMapper2_create },
65     { &CLSID_AsyncReader, AsyncReader_create },
66     { &CLSID_MemoryAllocator, StdMemAllocator_create },
67     { &CLSID_AviSplitter, AVISplitter_create },
68     { &CLSID_MPEG1Splitter, MPEGSplitter_create },
69     { &CLSID_VideoRenderer, VideoRenderer_create },
70     { &CLSID_NullRenderer, NullRenderer_create },
71     { &CLSID_VideoRendererDefault, VideoRendererDefault_create },
72     { &CLSID_DSoundRender, DSoundRender_create },
73     { &CLSID_AudioRender, DSoundRender_create },
74     { &CLSID_AVIDec, AVIDec_create },
75     { &CLSID_SystemClock, QUARTZ_CreateSystemClock },
76     { &CLSID_ACMWrapper, ACMWrapper_create },
77     { &CLSID_WAVEParser, WAVEParser_create }
78 };
79
80 static HRESULT WINAPI
81 DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
82 {
83     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
84
85     if (IsEqualGUID(riid, &IID_IUnknown)
86         || IsEqualGUID(riid, &IID_IClassFactory))
87     {
88         IClassFactory_AddRef(iface);
89         *ppobj = This;
90         return S_OK;
91     }
92
93     *ppobj = NULL;
94     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
95     return E_NOINTERFACE;
96 }
97
98 static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface)
99 {
100     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
101     return InterlockedIncrement(&This->ref);
102 }
103
104 static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface)
105 {
106     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
107
108     ULONG ref = InterlockedDecrement(&This->ref);
109
110     if (ref == 0)
111         CoTaskMemFree(This);
112
113     return ref;
114 }
115
116
117 static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
118                                           REFIID riid, LPVOID *ppobj)
119 {
120     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
121     HRESULT hres;
122     LPUNKNOWN punk;
123     
124     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
125
126     *ppobj = NULL;
127     hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
128     if (SUCCEEDED(hres)) {
129         hres = IUnknown_QueryInterface(punk, riid, ppobj);
130         IUnknown_Release(punk);
131     }
132     return hres;
133 }
134
135 static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
136 {
137     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
138     FIXME("(%p)->(%d),stub!\n",This,dolock);
139     return S_OK;
140 }
141
142 static const IClassFactoryVtbl DSCF_Vtbl =
143 {
144     DSCF_QueryInterface,
145     DSCF_AddRef,
146     DSCF_Release,
147     DSCF_CreateInstance,
148     DSCF_LockServer
149 };
150
151 /*******************************************************************************
152  * DllGetClassObject [QUARTZ.@]
153  * Retrieves class object from a DLL object
154  *
155  * NOTES
156  *    Docs say returns STDAPI
157  *
158  * PARAMS
159  *    rclsid [I] CLSID for the class object
160  *    riid   [I] Reference to identifier of interface for class object
161  *    ppv    [O] Address of variable to receive interface pointer for riid
162  *
163  * RETURNS
164  *    Success: S_OK
165  *    Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
166  *             E_UNEXPECTED
167  */
168 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
169 {
170     unsigned int i;
171
172     TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
173
174     if (IsEqualGUID( &IID_IClassFactory, riid ) || IsEqualGUID( &IID_IUnknown, riid))
175     {
176         for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
177         {
178             if (IsEqualGUID(object_creation[i].clsid, rclsid))
179             {
180                 IClassFactoryImpl *factory = CoTaskMemAlloc(sizeof(*factory));
181                 if (factory == NULL) return E_OUTOFMEMORY;
182
183                 factory->ITF_IClassFactory.lpVtbl = &DSCF_Vtbl;
184                 factory->ref = 1;
185
186                 factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
187
188                 *ppv = &factory->ITF_IClassFactory;
189                 return S_OK;
190             }
191         }
192     }
193     return QUARTZ_DllGetClassObject( rclsid, riid, ppv );
194 }
195
196 /***********************************************************************
197  *              DllCanUnloadNow (QUARTZ.@)
198  */
199 HRESULT WINAPI DllCanUnloadNow(void)
200 {
201     if (dll_ref) return S_FALSE;
202     return QUARTZ_DllCanUnloadNow();
203 }
204
205
206 #define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
207     { { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } } , #name },
208
209 static const struct {
210         const GUID      riid;
211         const char      *name;
212 } InterfaceDesc[] =
213 {
214 #include "uuids.h"
215     { { 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} }, NULL }
216 };
217
218 /***********************************************************************
219  *              proxies
220  */
221 HRESULT CALLBACK ICaptureGraphBuilder_FindInterface_Proxy( ICaptureGraphBuilder *This,
222                                                            const GUID *pCategory,
223                                                            IBaseFilter *pf,
224                                                            REFIID riid,
225                                                            void **ppint )
226 {
227     return ICaptureGraphBuilder_RemoteFindInterface_Proxy( This, pCategory, pf,
228                                                            riid, (IUnknown **)ppint );
229 }
230
231 HRESULT __RPC_STUB ICaptureGraphBuilder_FindInterface_Stub( ICaptureGraphBuilder *This,
232                                                             const GUID *pCategory,
233                                                             IBaseFilter *pf,
234                                                             REFIID riid,
235                                                             IUnknown **ppint )
236 {
237     return ICaptureGraphBuilder_FindInterface( This, pCategory, pf, riid, (void **)ppint );
238 }
239
240 HRESULT CALLBACK ICaptureGraphBuilder2_FindInterface_Proxy( ICaptureGraphBuilder2 *This,
241                                                             const GUID *pCategory,
242                                                             const GUID *pType,
243                                                             IBaseFilter *pf,
244                                                             REFIID riid,
245                                                             void **ppint )
246 {
247     return ICaptureGraphBuilder2_RemoteFindInterface_Proxy( This, pCategory, pType,
248                                                             pf, riid, (IUnknown **)ppint );
249 }
250
251 HRESULT __RPC_STUB ICaptureGraphBuilder2_FindInterface_Stub( ICaptureGraphBuilder2 *This,
252                                                              const GUID *pCategory,
253                                                              const GUID *pType,
254                                                              IBaseFilter *pf,
255                                                              REFIID riid,
256                                                              IUnknown **ppint )
257 {
258     return ICaptureGraphBuilder2_FindInterface( This, pCategory, pType, pf, riid, (void **)ppint );
259 }
260
261 /***********************************************************************
262  *              qzdebugstr_guid (internal)
263  *
264  * Gives a text version of DirectShow GUIDs
265  */
266 const char * qzdebugstr_guid( const GUID * id )
267 {
268     int i;
269     char * name = NULL;
270
271     for (i=0;InterfaceDesc[i].name && !name;i++) {
272         if (IsEqualGUID(&InterfaceDesc[i].riid, id)) return InterfaceDesc[i].name;
273     }
274     return debugstr_guid(id);
275 }
276
277 LONG WINAPI AmpFactorToDB(LONG ampfactor)
278 {
279     FIXME("(%d) Stub!\n", ampfactor);
280     return 0;
281 }
282
283 LONG WINAPI DBToAmpFactor(LONG db)
284 {
285     FIXME("(%d) Stub!\n", db);
286     /* Avoid divide by zero (probably during range computation) in Windows Media Player 6.4 */
287     if (db < -1000)
288         return 0;
289     return 100;
290 }
291
292 /***********************************************************************
293  *              AMGetErrorTextA (QUARTZ.@)
294  */
295 DWORD WINAPI AMGetErrorTextA(HRESULT hr, LPSTR buffer, DWORD maxlen)
296 {
297     DWORD res;
298     WCHAR errorW[MAX_ERROR_TEXT_LEN];
299
300     TRACE("(%x,%p,%d)\n", hr, buffer, maxlen);
301     if (!buffer)
302         return 0;
303
304     res = AMGetErrorTextW(hr, errorW, sizeof(errorW)/sizeof(*errorW));
305     return WideCharToMultiByte(CP_ACP, 0, errorW, res, buffer, maxlen, 0, 0);
306 }
307
308 /***********************************************************************
309  *              AMGetErrorTextW (QUARTZ.@)
310  */
311 DWORD WINAPI AMGetErrorTextW(HRESULT hr, LPWSTR buffer, DWORD maxlen)
312 {
313     unsigned int len;
314     static const WCHAR format[] = {'E','r','r','o','r',':',' ','0','x','%','l','x',0};
315     WCHAR error[MAX_ERROR_TEXT_LEN];
316
317     FIXME("(%x,%p,%d) stub\n", hr, buffer, maxlen);
318
319     if (!buffer) return 0;
320     wsprintfW(error, format, hr);
321     if ((len = strlenW(error)) >= maxlen) return 0;
322     lstrcpyW(buffer, error);
323     return len;
324 }