Revert "winex11.drv: Optimise getting the bits of a DIB after calling SetDIBits."
[wine] / dlls / qcap / dllsetup.c
1 /*
2  * DirectX DLL registration and unregistration
3  *
4  * Copyright (C) 2005 Rolf Kalbermatter
5 *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include "config.h"
21
22 #include <stdarg.h>
23 #include <assert.h>
24
25 #define COBJMACROS
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winerror.h"
33 #include "winreg.h"
34 #include "objbase.h"
35 #include "uuids.h"
36
37 #include "dllsetup.h"
38
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
43
44 /*
45  * defines and constants
46  */
47 #define MAX_KEY_LEN  260
48
49 static WCHAR const clsid_keyname[6] =
50 {'C','L','S','I','D',0 };
51 static WCHAR const ips32_keyname[15] =
52 {'I','n','P','r','o','c','S','e','r','v','e','r','3','2',0};
53 static WCHAR const tmodel_keyname[15] =
54 {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
55 static WCHAR const tmodel_both[] =
56 {'B','o','t','h',0};
57
58 /*
59  * SetupRegisterClass()
60  */
61 static HRESULT SetupRegisterClass(HKEY clsid, LPCWSTR szCLSID,
62                                   LPCWSTR szDescription,
63                                   LPCWSTR szFileName,
64                                   LPCWSTR szServerType,
65                                   LPCWSTR szThreadingModel)
66 {
67     HKEY hkey, hsubkey = NULL;
68     LONG ret = RegCreateKeyW(clsid, szCLSID, &hkey);
69     if (ERROR_SUCCESS != ret)
70         return HRESULT_FROM_WIN32(ret);
71
72     /* set description string */
73     ret = RegSetValueW(hkey, NULL, REG_SZ, szDescription,
74                        sizeof(WCHAR) * (lstrlenW(szDescription) + 1));
75     if (ERROR_SUCCESS != ret)
76         goto err_out;
77
78     /* create CLSID\\{"CLSID"}\\"ServerType" key, using key to CLSID\\{"CLSID"}
79        passed back by last call to RegCreateKeyW(). */
80     ret = RegCreateKeyW(hkey,  szServerType, &hsubkey);
81     if (ERROR_SUCCESS != ret)
82         goto err_out;
83
84     /* set server path */
85     ret = RegSetValueW(hsubkey, NULL, REG_SZ, szFileName,
86                        sizeof(WCHAR) * (lstrlenW(szFileName) + 1));
87     if (ERROR_SUCCESS != ret)
88         goto err_out;
89
90     /* set threading model */
91     ret = RegSetValueExW(hsubkey, tmodel_keyname, 0L, REG_SZ,
92                          (const BYTE*)szThreadingModel, 
93                          sizeof(WCHAR) * (lstrlenW(szThreadingModel) + 1));
94 err_out:
95     if (hsubkey)
96         RegCloseKey(hsubkey);
97     RegCloseKey(hkey);
98     return HRESULT_FROM_WIN32(ret);
99 }
100
101 /*
102  * SetupRegisterFilter through IFilterMapper2
103  */
104 static HRESULT SetupRegisterFilter2(const AMOVIESETUP_FILTER * const pSetup,
105                                     IFilterMapper2 * pIFM2, BOOL bRegister)
106 {
107     HRESULT hr;
108
109     if (NULL == pSetup)
110         return S_FALSE;
111
112     /* unregister filter */
113     hr = IFilterMapper2_UnregisterFilter(pIFM2, 0, 0, pSetup->clsID);
114
115     if (bRegister)
116     {
117         REGFILTER2 rf2;
118         rf2.dwVersion = 1;
119         rf2.dwMerit = pSetup->dwMerit;
120         rf2.u.s.cPins = pSetup->nPins;
121         rf2.u.s.rgPins = pSetup->lpPin;
122     
123         /* register filter */
124         hr = IFilterMapper2_RegisterFilter(pIFM2, pSetup->clsID,
125                                            pSetup->strName, 0, 0, NULL, &rf2);
126     }
127     else
128     {
129         /* filter not found is ignored here,
130            but there is no #define for 0x80070002  */
131         if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
132             hr = NOERROR;
133     }
134     return hr;
135 }
136
137 /*
138  * SetupRegisterFilter through IFilterMapper
139  */
140 static HRESULT SetupRegisterFilter(const AMOVIESETUP_FILTER * const pSetup,
141                                    IFilterMapper * pIFM, BOOL bRegister)
142 {
143     HRESULT hr;
144
145     if (NULL == pSetup)
146         return S_FALSE;
147
148     /* unregister filter */
149     hr = IFilterMapper_UnregisterFilter(pIFM, *pSetup->clsID);
150
151     if (bRegister)
152     {
153         /* register filter */
154         hr = IFilterMapper_RegisterFilter(pIFM, *pSetup->clsID,
155                                           pSetup->strName, pSetup->dwMerit);
156         if (SUCCEEDED(hr))
157         {
158             const AMOVIESETUP_PIN *lpPin = pSetup->lpPin;
159             const AMOVIESETUP_MEDIATYPE *lpType;
160             UINT i, j;
161
162             for (i = 0; i < pSetup->nPins; i++, lpPin++)
163             {
164                 hr = IFilterMapper_RegisterPin(pIFM, *(pSetup->clsID),
165                                                lpPin->strName,
166                                                lpPin->bRendered,
167                                                lpPin->bOutput,
168                                                lpPin->bZero,
169                                                lpPin->bMany,
170                                                *(lpPin->clsConnectsToFilter),
171                                                lpPin->strConnectsToPin);
172
173                 if (SUCCEEDED(hr))
174                 {
175                     lpType = lpPin->lpMediaType;
176
177                     /* and each pin's media types */
178                     for (j = 0; j < lpPin->nMediaTypes; j++, lpType++)
179                     {
180                         hr = IFilterMapper_RegisterPinType(pIFM, *(pSetup->clsID),
181                                                            lpPin->strName,
182                                                            *(lpType->clsMajorType),
183                                                            *(lpType->clsMinorType));
184                         if (FAILED(hr)) break;
185                     }
186                     if (FAILED(hr)) break;
187                 }
188                 if (FAILED(hr)) break;
189             }
190         }
191     }
192     else
193     {
194         /* filter not registered is ignored here, there is no definition for 0x80070002  */
195         if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
196            hr = NOERROR;
197     }
198     return hr;
199 }
200
201 /*
202  * RegisterAllClasses()
203  */
204 static HRESULT SetupRegisterAllClasses(const CFactoryTemplate * pList, int num,
205                                        LPCWSTR szFileName, BOOL bRegister)
206 {
207     HRESULT hr = NOERROR;
208     HKEY hkey;
209     OLECHAR szCLSID[CHARS_IN_GUID];
210     LONG i, ret = RegCreateKeyW(HKEY_CLASSES_ROOT, clsid_keyname, &hkey);
211     if (ERROR_SUCCESS != ret)
212         return HRESULT_FROM_WIN32(ret);
213
214     for (i = 0; i < num; i++, pList++)
215     {
216         /* (un)register CLSID and InprocServer32 */
217         hr = StringFromGUID2(pList->m_ClsID, szCLSID, CHARS_IN_GUID);
218         if (SUCCEEDED(hr))
219         {
220             if (bRegister )
221                 hr = SetupRegisterClass(hkey, szCLSID,
222                                         pList->m_Name, szFileName,
223                                         ips32_keyname, tmodel_both);
224             else
225                 hr = RegDeleteTreeW(hkey, szCLSID);
226         }
227     }
228     RegCloseKey(hkey);
229     return hr;
230 }
231
232
233 /****************************************************************************
234  * SetupRegisterServers
235  *
236  * This function is table driven using the static members of the
237  * CFactoryTemplate class defined in the Dll.
238  *
239  * It registers the Dll as the InprocServer32 for all the classes in
240  * CFactoryTemplate
241  *
242  ****************************************************************************/
243 HRESULT SetupRegisterServers(const CFactoryTemplate * pList, int num,
244                              BOOL bRegister)
245 {
246     static const WCHAR szFileName[] = {'q','c','a','p','.','d','l','l',0};
247     HRESULT hr = NOERROR;
248     IFilterMapper2 *pIFM2 = NULL;
249     IFilterMapper *pIFM = NULL;
250
251     /* first register all server classes, just to make sure */
252     if (bRegister)
253         hr = SetupRegisterAllClasses(pList, num, szFileName, TRUE );
254
255     /* next, register/unregister all filters */
256     if (SUCCEEDED(hr))
257     {
258         hr = CoInitialize(NULL);
259
260         TRACE("Getting IFilterMapper2\r\n");
261         hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
262                               &IID_IFilterMapper2, (void **)&pIFM2);
263         if (FAILED(hr))
264         {
265             TRACE("- trying IFilterMapper instead\r\n");
266
267             hr = CoCreateInstance(&CLSID_FilterMapper, NULL, CLSCTX_INPROC_SERVER,
268                                   &IID_IFilterMapper, (void **)&pIFM);
269         }
270
271         if (SUCCEEDED(hr))
272         {
273             int i;
274             
275             /* scan through array of CFactoryTemplates registering all filters */
276             for (i = 0; i < num; i++, pList++)
277             {
278                 if (NULL != pList->m_pAMovieSetup_Filter)
279                 {
280                     if (pIFM2)
281                         hr = SetupRegisterFilter2(pList->m_pAMovieSetup_Filter,
282                                                   pIFM2, bRegister);
283                     else
284                         hr = SetupRegisterFilter(pList->m_pAMovieSetup_Filter,
285                                                  pIFM, bRegister);
286                 }
287
288                 /* check final error for this pass and break loop if we failed */
289                 if (FAILED(hr))
290                     break;
291             }
292
293             /* release interface */
294             if (pIFM2)
295                 IFilterMapper2_Release(pIFM2);
296             else
297                 IFilterMapper_Release(pIFM);
298         }
299
300         /* and clear up */
301         CoFreeUnusedLibraries();
302         CoUninitialize();
303     }
304
305     /* if unregistering, unregister all OLE servers */
306     if (SUCCEEDED(hr) && !bRegister)
307         hr = SetupRegisterAllClasses(pList, num, szFileName, FALSE);
308     return hr;
309 }
310
311 /****************************************************************************
312  * SetupInitializeServers
313  *
314  * This function is table driven using the static members of the
315  * CFactoryTemplate class defined in the Dll.
316  *
317  * It calls the initialize function for any class in CFactoryTemplate with
318  * one defined.
319  *
320  ****************************************************************************/
321 void SetupInitializeServers(const CFactoryTemplate * pList, int num,
322                             BOOL bLoading)
323 {
324     int i;
325
326     for (i = 0; i < num; i++, pList++)
327     {
328         if (pList->m_lpfnInit)
329             pList->m_lpfnInit(bLoading, pList->m_ClsID);
330     }
331 }