jscript: Inherit Array valueOf from Object.
[wine] / dlls / windowscodecs / regsvr.c
1 /*
2  * Copyright 2009 Vincent Povirk for CodeWeavers
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 #define NONAMELESSUNION
20 #define NONAMELESSSTRUCT
21 #define COBJMACROS
22 #include <stdarg.h>
23 #include <string.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "winerror.h"
31
32 #include "objbase.h"
33 #include "ocidl.h"
34 #include "wincodec.h"
35
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
39
40 /***********************************************************************
41  *              interface for self-registering
42  */
43 struct regsvr_coclass
44 {
45     CLSID const *clsid;         /* NULL for end of list */
46     LPCSTR name;                /* can be NULL to omit */
47     LPCSTR ips;                 /* can be NULL to omit */
48     LPCSTR ips32;               /* can be NULL to omit */
49     LPCSTR ips32_tmodel;        /* can be NULL to omit */
50     LPCSTR progid;              /* can be NULL to omit */
51     LPCSTR viprogid;            /* can be NULL to omit */
52     LPCSTR progid_extra;        /* can be NULL to omit */
53 };
54
55 static HRESULT register_coclasses(struct regsvr_coclass const *list);
56 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
57
58 /***********************************************************************
59  *              static string constants
60  */
61 static WCHAR const clsid_keyname[6] = {
62     'C', 'L', 'S', 'I', 'D', 0 };
63 static WCHAR const curver_keyname[7] = {
64     'C', 'u', 'r', 'V', 'e', 'r', 0 };
65 static WCHAR const ips_keyname[13] = {
66     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
67     0 };
68 static WCHAR const ips32_keyname[15] = {
69     'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
70     '3', '2', 0 };
71 static WCHAR const progid_keyname[7] = {
72     'P', 'r', 'o', 'g', 'I', 'D', 0 };
73 static WCHAR const viprogid_keyname[25] = {
74     'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
75     'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
76     0 };
77 static char const tmodel_valuename[] = "ThreadingModel";
78
79 /***********************************************************************
80  *              static helper functions
81  */
82 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
83                                    WCHAR const *value);
84 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
85                                    char const *value);
86 static LONG register_progid(WCHAR const *clsid,
87                             char const *progid, char const *curver_progid,
88                             char const *name, char const *extra);
89
90 /***********************************************************************
91  *              register_coclasses
92  */
93 static HRESULT register_coclasses(struct regsvr_coclass const *list)
94 {
95     LONG res = ERROR_SUCCESS;
96     HKEY coclass_key;
97
98     res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
99                           KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
100     if (res != ERROR_SUCCESS) goto error_return;
101
102     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
103         WCHAR buf[39];
104         HKEY clsid_key;
105
106         StringFromGUID2(list->clsid, buf, 39);
107         res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
108                               KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
109         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
110
111         if (list->name) {
112             res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
113                                  (CONST BYTE*)(list->name),
114                                  strlen(list->name) + 1);
115             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
116         }
117
118         if (list->ips) {
119             res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
120             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
121         }
122
123         if (list->ips32) {
124             HKEY ips32_key;
125
126             res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
127                                   KEY_READ | KEY_WRITE, NULL,
128                                   &ips32_key, NULL);
129             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
130
131             res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
132                                  (CONST BYTE*)list->ips32,
133                                  lstrlenA(list->ips32) + 1);
134             if (res == ERROR_SUCCESS && list->ips32_tmodel)
135                 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
136                                      (CONST BYTE*)list->ips32_tmodel,
137                                      strlen(list->ips32_tmodel) + 1);
138             RegCloseKey(ips32_key);
139             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
140         }
141
142         if (list->progid) {
143             res = register_key_defvalueA(clsid_key, progid_keyname,
144                                          list->progid);
145             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
146
147             res = register_progid(buf, list->progid, NULL,
148                                   list->name, list->progid_extra);
149             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
150         }
151
152         if (list->viprogid) {
153             res = register_key_defvalueA(clsid_key, viprogid_keyname,
154                                          list->viprogid);
155             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
156
157             res = register_progid(buf, list->viprogid, list->progid,
158                                   list->name, list->progid_extra);
159             if (res != ERROR_SUCCESS) goto error_close_clsid_key;
160         }
161
162     error_close_clsid_key:
163         RegCloseKey(clsid_key);
164     }
165
166 error_close_coclass_key:
167     RegCloseKey(coclass_key);
168 error_return:
169     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
170 }
171
172 /***********************************************************************
173  *              unregister_coclasses
174  */
175 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
176 {
177     LONG res = ERROR_SUCCESS;
178     HKEY coclass_key;
179
180     res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
181                         KEY_READ | KEY_WRITE, &coclass_key);
182     if (res == ERROR_FILE_NOT_FOUND) return S_OK;
183     if (res != ERROR_SUCCESS) goto error_return;
184
185     for (; res == ERROR_SUCCESS && list->clsid; ++list) {
186         WCHAR buf[39];
187
188         StringFromGUID2(list->clsid, buf, 39);
189         res = RegDeleteTreeW(coclass_key, buf);
190         if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
191         if (res != ERROR_SUCCESS) goto error_close_coclass_key;
192
193         if (list->progid) {
194             res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
195             if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
196             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
197         }
198
199         if (list->viprogid) {
200             res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
201             if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
202             if (res != ERROR_SUCCESS) goto error_close_coclass_key;
203         }
204     }
205
206 error_close_coclass_key:
207     RegCloseKey(coclass_key);
208 error_return:
209     return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
210 }
211
212 /***********************************************************************
213  *              register_key_defvalueW
214  */
215 static LONG register_key_defvalueW(
216     HKEY base,
217     WCHAR const *name,
218     WCHAR const *value)
219 {
220     LONG res;
221     HKEY key;
222
223     res = RegCreateKeyExW(base, name, 0, NULL, 0,
224                           KEY_READ | KEY_WRITE, NULL, &key, NULL);
225     if (res != ERROR_SUCCESS) return res;
226     res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
227                          (lstrlenW(value) + 1) * sizeof(WCHAR));
228     RegCloseKey(key);
229     return res;
230 }
231
232 /***********************************************************************
233  *              register_key_defvalueA
234  */
235 static LONG register_key_defvalueA(
236     HKEY base,
237     WCHAR const *name,
238     char const *value)
239 {
240     LONG res;
241     HKEY key;
242
243     res = RegCreateKeyExW(base, name, 0, NULL, 0,
244                           KEY_READ | KEY_WRITE, NULL, &key, NULL);
245     if (res != ERROR_SUCCESS) return res;
246     res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
247                          lstrlenA(value) + 1);
248     RegCloseKey(key);
249     return res;
250 }
251
252 /***********************************************************************
253  *              register_progid
254  */
255 static LONG register_progid(
256     WCHAR const *clsid,
257     char const *progid,
258     char const *curver_progid,
259     char const *name,
260     char const *extra)
261 {
262     LONG res;
263     HKEY progid_key;
264
265     res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
266                           NULL, 0, KEY_READ | KEY_WRITE, NULL,
267                           &progid_key, NULL);
268     if (res != ERROR_SUCCESS) return res;
269
270     if (name) {
271         res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
272                              (CONST BYTE*)name, strlen(name) + 1);
273         if (res != ERROR_SUCCESS) goto error_close_progid_key;
274     }
275
276     if (clsid) {
277         res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
278         if (res != ERROR_SUCCESS) goto error_close_progid_key;
279     }
280
281     if (curver_progid) {
282         res = register_key_defvalueA(progid_key, curver_keyname,
283                                      curver_progid);
284         if (res != ERROR_SUCCESS) goto error_close_progid_key;
285     }
286
287     if (extra) {
288         HKEY extra_key;
289
290         res = RegCreateKeyExA(progid_key, extra, 0,
291                               NULL, 0, KEY_READ | KEY_WRITE, NULL,
292                               &extra_key, NULL);
293         if (res == ERROR_SUCCESS)
294             RegCloseKey(extra_key);
295     }
296
297 error_close_progid_key:
298     RegCloseKey(progid_key);
299     return res;
300 }
301
302 /***********************************************************************
303  *              coclass list
304  */
305 static struct regsvr_coclass const coclass_list[] = {
306     {   &CLSID_WICImagingFactory,
307         "WIC Imaging Factory",
308         NULL,
309         "windowscodecs.dll",
310         "Apartment"
311     },
312     {   &CLSID_WICBmpDecoder,
313         "WIC BMP Decoder",
314         NULL,
315         "windowscodecs.dll",
316         "Apartment"
317     },
318     { NULL }                    /* list terminator */
319 };
320
321 HRESULT WINAPI DllRegisterServer(void)
322 {
323     HRESULT hr;
324
325     TRACE("\n");
326
327     hr = register_coclasses(coclass_list);
328     return hr;
329 }
330
331 HRESULT WINAPI DllUnregisterServer(void)
332 {
333     HRESULT hr;
334
335     TRACE("\n");
336
337     hr = unregister_coclasses(coclass_list);
338     return hr;
339 }