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