2 * self-registerable dll functions for msctf
4 * Copyright (C) 2004 Stefan Leichter
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.
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.
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
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
40 * Near the bottom of this file are the exported DllRegisterServer and
41 * DllUnregisterServer, which make all this worthwhile.
44 /***********************************************************************
45 * interface for self-registering
47 struct regsvr_interface
49 IID const *iid; /* NULL for end of list */
50 LPCSTR name; /* can be NULL to omit */
51 IID const *base_iid; /* can be NULL to omit */
52 int num_methods; /* can be <0 to omit */
53 CLSID const *ps_clsid; /* can be NULL to omit */
54 CLSID const *ps_clsid32; /* can be NULL to omit */
57 static HRESULT register_interfaces(struct regsvr_interface const *list);
58 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
62 CLSID const *clsid; /* NULL for end of list */
63 LPCSTR name; /* can be NULL to omit */
64 LPCSTR ips; /* can be NULL to omit */
65 LPCSTR ips32; /* can be NULL to omit */
66 LPCSTR ips32_tmodel; /* can be NULL to omit */
67 LPCSTR progid; /* can be NULL to omit */
68 LPCSTR viprogid; /* can be NULL to omit */
69 LPCSTR progid_extra; /* can be NULL to omit */
72 static HRESULT register_coclasses(struct regsvr_coclass const *list);
73 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
75 /***********************************************************************
76 * static string constants
78 static WCHAR const interface_keyname[10] = {
79 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
80 static WCHAR const base_ifa_keyname[14] = {
81 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
83 static WCHAR const num_methods_keyname[11] = {
84 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
85 static WCHAR const ps_clsid_keyname[15] = {
86 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
88 static WCHAR const ps_clsid32_keyname[17] = {
89 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
90 'i', 'd', '3', '2', 0 };
91 static WCHAR const clsid_keyname[6] = {
92 'C', 'L', 'S', 'I', 'D', 0 };
93 static WCHAR const curver_keyname[7] = {
94 'C', 'u', 'r', 'V', 'e', 'r', 0 };
95 static WCHAR const ips_keyname[13] = {
96 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
98 static WCHAR const ips32_keyname[15] = {
99 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
101 static WCHAR const progid_keyname[7] = {
102 'P', 'r', 'o', 'g', 'I', 'D', 0 };
103 static WCHAR const viprogid_keyname[25] = {
104 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
105 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
107 static char const tmodel_valuename[] = "ThreadingModel";
109 /***********************************************************************
110 * static helper functions
112 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
113 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
115 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
117 static LONG register_progid(WCHAR const *clsid,
118 char const *progid, char const *curver_progid,
119 char const *name, char const *extra);
121 /***********************************************************************
122 * register_interfaces
124 static HRESULT register_interfaces(struct regsvr_interface const *list)
126 LONG res = ERROR_SUCCESS;
129 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
130 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
131 if (res != ERROR_SUCCESS) goto error_return;
133 for (; res == ERROR_SUCCESS && list->iid; ++list) {
137 StringFromGUID2(list->iid, buf, 39);
138 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
139 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
140 if (res != ERROR_SUCCESS) goto error_close_interface_key;
143 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
144 (CONST BYTE*)(list->name),
145 strlen(list->name) + 1);
146 if (res != ERROR_SUCCESS) goto error_close_iid_key;
149 if (list->base_iid) {
150 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
151 if (res != ERROR_SUCCESS) goto error_close_iid_key;
154 if (0 <= list->num_methods) {
155 static WCHAR const fmt[3] = { '%', 'd', 0 };
158 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
159 KEY_READ | KEY_WRITE, NULL, &key, NULL);
160 if (res != ERROR_SUCCESS) goto error_close_iid_key;
162 wsprintfW(buf, fmt, list->num_methods);
163 res = RegSetValueExW(key, NULL, 0, REG_SZ,
165 (lstrlenW(buf) + 1) * sizeof(WCHAR));
168 if (res != ERROR_SUCCESS) goto error_close_iid_key;
171 if (list->ps_clsid) {
172 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
173 if (res != ERROR_SUCCESS) goto error_close_iid_key;
176 if (list->ps_clsid32) {
177 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
178 if (res != ERROR_SUCCESS) goto error_close_iid_key;
182 RegCloseKey(iid_key);
185 error_close_interface_key:
186 RegCloseKey(interface_key);
188 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
191 /***********************************************************************
192 * unregister_interfaces
194 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
196 LONG res = ERROR_SUCCESS;
199 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
200 KEY_READ | KEY_WRITE, &interface_key);
201 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
202 if (res != ERROR_SUCCESS) goto error_return;
204 for (; res == ERROR_SUCCESS && list->iid; ++list) {
207 StringFromGUID2(list->iid, buf, 39);
208 res = RegDeleteTreeW(interface_key, buf);
209 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
212 RegCloseKey(interface_key);
214 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
217 /***********************************************************************
220 static HRESULT register_coclasses(struct regsvr_coclass const *list)
222 LONG res = ERROR_SUCCESS;
225 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
226 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
227 if (res != ERROR_SUCCESS) goto error_return;
229 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
233 StringFromGUID2(list->clsid, buf, 39);
234 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
235 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
236 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
239 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
240 (CONST BYTE*)(list->name),
241 strlen(list->name) + 1);
242 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
246 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
247 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
253 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
254 KEY_READ | KEY_WRITE, NULL,
256 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
258 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
259 (CONST BYTE*)list->ips32,
260 lstrlenA(list->ips32) + 1);
261 if (res == ERROR_SUCCESS && list->ips32_tmodel)
262 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
263 (CONST BYTE*)list->ips32_tmodel,
264 strlen(list->ips32_tmodel) + 1);
265 RegCloseKey(ips32_key);
266 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
270 res = register_key_defvalueA(clsid_key, progid_keyname,
272 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
274 res = register_progid(buf, list->progid, NULL,
275 list->name, list->progid_extra);
276 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
279 if (list->viprogid) {
280 res = register_key_defvalueA(clsid_key, viprogid_keyname,
282 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
284 res = register_progid(buf, list->viprogid, list->progid,
285 list->name, list->progid_extra);
286 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
289 error_close_clsid_key:
290 RegCloseKey(clsid_key);
293 error_close_coclass_key:
294 RegCloseKey(coclass_key);
296 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
299 /***********************************************************************
300 * unregister_coclasses
302 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
304 LONG res = ERROR_SUCCESS;
307 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
308 KEY_READ | KEY_WRITE, &coclass_key);
309 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
310 if (res != ERROR_SUCCESS) goto error_return;
312 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
315 StringFromGUID2(list->clsid, buf, 39);
316 res = RegDeleteTreeW(coclass_key, buf);
317 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
318 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
321 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
322 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
323 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
326 if (list->viprogid) {
327 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
328 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
329 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
333 error_close_coclass_key:
334 RegCloseKey(coclass_key);
336 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
339 /***********************************************************************
342 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
346 StringFromGUID2(guid, buf, 39);
347 return register_key_defvalueW(base, name, buf);
350 /***********************************************************************
351 * regsvr_key_defvalueW
353 static LONG register_key_defvalueW(
361 res = RegCreateKeyExW(base, name, 0, NULL, 0,
362 KEY_READ | KEY_WRITE, NULL, &key, NULL);
363 if (res != ERROR_SUCCESS) return res;
364 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
365 (lstrlenW(value) + 1) * sizeof(WCHAR));
370 /***********************************************************************
371 * regsvr_key_defvalueA
373 static LONG register_key_defvalueA(
381 res = RegCreateKeyExW(base, name, 0, NULL, 0,
382 KEY_READ | KEY_WRITE, NULL, &key, NULL);
383 if (res != ERROR_SUCCESS) return res;
384 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
385 lstrlenA(value) + 1);
390 /***********************************************************************
393 static LONG register_progid(
396 char const *curver_progid,
403 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
404 NULL, 0, KEY_READ | KEY_WRITE, NULL,
406 if (res != ERROR_SUCCESS) return res;
409 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
410 (CONST BYTE*)name, strlen(name) + 1);
411 if (res != ERROR_SUCCESS) goto error_close_progid_key;
415 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
416 if (res != ERROR_SUCCESS) goto error_close_progid_key;
420 res = register_key_defvalueA(progid_key, curver_keyname,
422 if (res != ERROR_SUCCESS) goto error_close_progid_key;
428 res = RegCreateKeyExA(progid_key, extra, 0,
429 NULL, 0, KEY_READ | KEY_WRITE, NULL,
431 if (res == ERROR_SUCCESS)
432 RegCloseKey(extra_key);
435 error_close_progid_key:
436 RegCloseKey(progid_key);
440 /***********************************************************************
443 static struct regsvr_coclass const coclass_list[] = {
452 &CLSID_TF_InputProcessorProfiles,
453 "TF_InputProcessorProfiles",
459 &CLSID_TF_CategoryMgr,
466 &CLSID_TF_LangBarMgr,
473 &CLSID_TF_DisplayAttributeMgr,
474 "TF_DisplayAttributeMgr",
479 { NULL } /* list terminator */
482 /***********************************************************************
486 static struct regsvr_interface const interface_list[] = {
487 { NULL } /* list terminator */
490 /***********************************************************************
491 * DllRegisterServer (MSCTF.@)
493 HRESULT WINAPI DllRegisterServer(void)
499 hr = register_coclasses(coclass_list);
501 hr = register_interfaces(interface_list);
505 /***********************************************************************
506 * DllUnregisterServer (MSCTF.@)
508 HRESULT WINAPI DllUnregisterServer(void)
514 hr = unregister_coclasses(coclass_list);
516 hr = unregister_interfaces(interface_list);