2 * self-registerable dll functions for mlang.dll
4 * Copyright (C) 2003 John K. Hohm
5 * Copyright (C) 2004 Steven Edwards for ReactOS
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.
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.
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
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(mlang
);
42 /* This one should probably be defined in mlang.idl but MSDN claims it is no longer supported */
43 DEFINE_GUID(CLSID_CMLangString
, 0xc04d65cf, 0xb70d, 0x11d0, 0xb1,0x88, 0x00,0xaa,0x00,0x38,0xc9,0x69);
46 * Near the bottom of this file are the exported DllRegisterServer and
47 * DllUnregisterServer, which make all this worthwhile.
50 /***********************************************************************
51 * interface for self-registering
53 struct regsvr_interface
55 IID
const *iid
; /* NULL for end of list */
56 LPCSTR name
; /* can be NULL to omit */
57 IID
const *base_iid
; /* can be NULL to omit */
58 int num_methods
; /* can be <0 to omit */
59 CLSID
const *ps_clsid
; /* can be NULL to omit */
60 CLSID
const *ps_clsid32
; /* can be NULL to omit */
63 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
64 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
68 CLSID
const *clsid
; /* NULL for end of list */
69 LPCSTR name
; /* can be NULL to omit */
70 LPCSTR ips
; /* can be NULL to omit */
71 LPCSTR ips32
; /* can be NULL to omit */
72 LPCSTR ips32_tmodel
; /* can be NULL to omit */
73 LPCSTR progid
; /* can be NULL to omit */
74 LPCSTR viprogid
; /* can be NULL to omit */
75 LPCSTR progid_extra
; /* can be NULL to omit */
78 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
79 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
81 /***********************************************************************
82 * static string constants
84 static WCHAR
const interface_keyname
[10] = {
85 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
86 static WCHAR
const base_ifa_keyname
[14] = {
87 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
89 static WCHAR
const num_methods_keyname
[11] = {
90 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
91 static WCHAR
const ps_clsid_keyname
[15] = {
92 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
94 static WCHAR
const ps_clsid32_keyname
[17] = {
95 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
96 'i', 'd', '3', '2', 0 };
97 static WCHAR
const clsid_keyname
[6] = {
98 'C', 'L', 'S', 'I', 'D', 0 };
99 static WCHAR
const curver_keyname
[7] = {
100 'C', 'u', 'r', 'V', 'e', 'r', 0 };
101 static WCHAR
const ips_keyname
[13] = {
102 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
104 static WCHAR
const ips32_keyname
[15] = {
105 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
107 static WCHAR
const progid_keyname
[7] = {
108 'P', 'r', 'o', 'g', 'I', 'D', 0 };
109 static WCHAR
const viprogid_keyname
[25] = {
110 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
111 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
113 static char const tmodel_valuename
[] = "ThreadingModel";
115 /***********************************************************************
116 * static helper functions
118 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
119 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
121 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
123 static LONG
register_progid(WCHAR
const *clsid
,
124 char const *progid
, char const *curver_progid
,
125 char const *name
, char const *extra
);
127 /***********************************************************************
128 * register_interfaces
130 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
132 LONG res
= ERROR_SUCCESS
;
135 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
136 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
137 if (res
!= ERROR_SUCCESS
) goto error_return
;
139 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
143 StringFromGUID2(list
->iid
, buf
, 39);
144 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
145 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
146 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
149 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
150 (CONST BYTE
*)(list
->name
),
151 strlen(list
->name
) + 1);
152 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
155 if (list
->base_iid
) {
156 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
157 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
160 if (0 <= list
->num_methods
) {
161 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
164 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
165 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
166 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
168 sprintfW(buf
, fmt
, list
->num_methods
);
169 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
171 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
174 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
177 if (list
->ps_clsid
) {
178 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
179 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
182 if (list
->ps_clsid32
) {
183 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
184 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
188 RegCloseKey(iid_key
);
191 error_close_interface_key
:
192 RegCloseKey(interface_key
);
194 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
197 /***********************************************************************
198 * unregister_interfaces
200 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
202 LONG res
= ERROR_SUCCESS
;
205 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
206 KEY_READ
| KEY_WRITE
, &interface_key
);
207 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
208 if (res
!= ERROR_SUCCESS
) goto error_return
;
210 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
213 StringFromGUID2(list
->iid
, buf
, 39);
214 res
= RegDeleteTreeW(interface_key
, buf
);
215 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
218 RegCloseKey(interface_key
);
220 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
223 /***********************************************************************
226 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
228 LONG res
= ERROR_SUCCESS
;
231 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
232 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
233 if (res
!= ERROR_SUCCESS
) goto error_return
;
235 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
239 StringFromGUID2(list
->clsid
, buf
, 39);
240 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
241 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
242 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
245 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
246 (CONST BYTE
*)(list
->name
),
247 strlen(list
->name
) + 1);
248 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
252 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
253 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
259 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
260 KEY_READ
| KEY_WRITE
, NULL
,
262 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
264 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
265 (CONST BYTE
*)list
->ips32
,
266 lstrlenA(list
->ips32
) + 1);
267 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
268 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
269 (CONST BYTE
*)list
->ips32_tmodel
,
270 strlen(list
->ips32_tmodel
) + 1);
271 RegCloseKey(ips32_key
);
272 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
276 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
278 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
280 res
= register_progid(buf
, list
->progid
, NULL
,
281 list
->name
, list
->progid_extra
);
282 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
285 if (list
->viprogid
) {
286 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
288 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
290 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
291 list
->name
, list
->progid_extra
);
292 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
295 error_close_clsid_key
:
296 RegCloseKey(clsid_key
);
299 error_close_coclass_key
:
300 RegCloseKey(coclass_key
);
302 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
305 /***********************************************************************
306 * unregister_coclasses
308 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
310 LONG res
= ERROR_SUCCESS
;
313 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
314 KEY_READ
| KEY_WRITE
, &coclass_key
);
315 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
316 if (res
!= ERROR_SUCCESS
) goto error_return
;
318 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
321 StringFromGUID2(list
->clsid
, buf
, 39);
322 res
= RegDeleteTreeW(coclass_key
, buf
);
323 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
324 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
327 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
328 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
329 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
332 if (list
->viprogid
) {
333 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
334 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
335 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
339 error_close_coclass_key
:
340 RegCloseKey(coclass_key
);
342 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
345 /***********************************************************************
348 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
352 StringFromGUID2(guid
, buf
, 39);
353 return register_key_defvalueW(base
, name
, buf
);
356 /***********************************************************************
357 * regsvr_key_defvalueW
359 static LONG
register_key_defvalueW(
367 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
368 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
369 if (res
!= ERROR_SUCCESS
) return res
;
370 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
371 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
376 /***********************************************************************
377 * regsvr_key_defvalueA
379 static LONG
register_key_defvalueA(
387 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
388 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
389 if (res
!= ERROR_SUCCESS
) return res
;
390 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
391 lstrlenA(value
) + 1);
396 /***********************************************************************
399 static LONG
register_progid(
402 char const *curver_progid
,
409 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
410 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
412 if (res
!= ERROR_SUCCESS
) return res
;
415 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
416 (CONST BYTE
*)name
, strlen(name
) + 1);
417 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
421 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
422 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
426 res
= register_key_defvalueA(progid_key
, curver_keyname
,
428 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
434 res
= RegCreateKeyExA(progid_key
, extra
, 0,
435 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
437 if (res
== ERROR_SUCCESS
)
438 RegCloseKey(extra_key
);
441 error_close_progid_key
:
442 RegCloseKey(progid_key
);
446 /***********************************************************************
449 static struct regsvr_coclass
const coclass_list
[] = {
451 &CLSID_CMultiLanguage
,
452 "Multi Language Support",
459 "Multi Language String",
465 &CLSID_CMLangConvertCharset
,
466 "Multi Language ConvertCharset",
471 { NULL
} /* list terminator */
474 /***********************************************************************
478 static struct regsvr_interface
const interface_list
[] = {
479 { NULL
} /* list terminator */
482 /***********************************************************************
483 * DllRegisterServer (MLANG.@)
485 HRESULT WINAPI
DllRegisterServer(void)
491 hr
= register_coclasses(coclass_list
);
493 hr
= register_interfaces(interface_list
);
497 /***********************************************************************
498 * DllUnregisterServer (MLANG.@)
500 HRESULT WINAPI
DllUnregisterServer(void)
506 hr
= unregister_coclasses(coclass_list
);
508 hr
= unregister_interfaces(interface_list
);