2 * self-registerable dll functions for qedit.dll
4 * Copyright (C) 2008 Google (Lei Zhang)
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
21 #include "qedit_private.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(qedit);
30 CLSID const *clsid; /* NULL for end of list */
31 LPCSTR name; /* can be NULL to omit */
32 LPCSTR ips; /* can be NULL to omit */
33 LPCSTR ips32; /* can be NULL to omit */
34 LPCSTR ips32_tmodel; /* can be NULL to omit */
35 LPCSTR progid; /* can be NULL to omit */
36 LPCSTR viprogid; /* can be NULL to omit */
37 LPCSTR progid_extra; /* can be NULL to omit */
40 static HRESULT register_coclasses(struct regsvr_coclass const *list);
41 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
43 /***********************************************************************
44 * static string constants
46 static WCHAR const clsid_keyname[6] = {
47 'C', 'L', 'S', 'I', 'D', 0 };
48 static WCHAR const curver_keyname[7] = {
49 'C', 'u', 'r', 'V', 'e', 'r', 0 };
50 static WCHAR const ips_keyname[13] = {
51 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', 0 };
52 static WCHAR const ips32_keyname[15] = {
53 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', '3', '2', 0 };
54 static WCHAR const progid_keyname[7] = {
55 'P', 'r', 'o', 'g', 'I', 'D', 0 };
56 static WCHAR const viprogid_keyname[25] = {
57 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
58 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
60 static char const tmodel_valuename[] = "ThreadingModel";
62 /***********************************************************************
63 * static helper functions
65 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
67 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
69 static LONG register_progid(WCHAR const *clsid,
70 char const *progid, char const *curver_progid,
71 char const *name, char const *extra);
75 /***********************************************************************
78 static HRESULT register_coclasses(struct regsvr_coclass const *list)
80 LONG res = ERROR_SUCCESS;
83 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
84 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
85 if (res != ERROR_SUCCESS) goto error_return;
87 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
91 StringFromGUID2(list->clsid, buf, 39);
92 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
93 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
94 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
97 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
98 (CONST BYTE*)(list->name),
99 strlen(list->name) + 1);
100 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
104 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
105 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
111 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
112 KEY_READ | KEY_WRITE, NULL,
114 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
116 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
117 (CONST BYTE*)list->ips32,
118 lstrlenA(list->ips32) + 1);
119 if (res == ERROR_SUCCESS && list->ips32_tmodel)
120 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
121 (CONST BYTE*)list->ips32_tmodel,
122 strlen(list->ips32_tmodel) + 1);
123 RegCloseKey(ips32_key);
124 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
128 res = register_key_defvalueA(clsid_key, progid_keyname,
130 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
132 res = register_progid(buf, list->progid, NULL,
133 list->name, list->progid_extra);
134 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
137 if (list->viprogid) {
138 res = register_key_defvalueA(clsid_key, viprogid_keyname,
140 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
142 res = register_progid(buf, list->viprogid, list->progid,
143 list->name, list->progid_extra);
144 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
147 error_close_clsid_key:
148 RegCloseKey(clsid_key);
151 error_close_coclass_key:
152 RegCloseKey(coclass_key);
154 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
157 /***********************************************************************
158 * unregister_coclasses
160 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
162 LONG res = ERROR_SUCCESS;
165 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
166 KEY_READ | KEY_WRITE, &coclass_key);
167 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
168 if (res != ERROR_SUCCESS) goto error_return;
170 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
173 StringFromGUID2(list->clsid, buf, 39);
174 res = RegDeleteTreeW(coclass_key, buf);
175 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
176 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
179 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
180 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
181 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
184 if (list->viprogid) {
185 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
186 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
187 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
191 error_close_coclass_key:
192 RegCloseKey(coclass_key);
194 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
197 /***********************************************************************
198 * regsvr_key_defvalueW
200 static LONG register_key_defvalueW(
208 res = RegCreateKeyExW(base, name, 0, NULL, 0,
209 KEY_READ | KEY_WRITE, NULL, &key, NULL);
210 if (res != ERROR_SUCCESS) return res;
211 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
212 (lstrlenW(value) + 1) * sizeof(WCHAR));
217 /***********************************************************************
218 * regsvr_key_defvalueA
220 static LONG register_key_defvalueA(
228 res = RegCreateKeyExW(base, name, 0, NULL, 0,
229 KEY_READ | KEY_WRITE, NULL, &key, NULL);
230 if (res != ERROR_SUCCESS) return res;
231 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
232 lstrlenA(value) + 1);
237 /***********************************************************************
240 static LONG register_progid(
243 char const *curver_progid,
250 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
251 NULL, 0, KEY_READ | KEY_WRITE, NULL,
253 if (res != ERROR_SUCCESS) return res;
256 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
257 (CONST BYTE*)name, strlen(name) + 1);
258 if (res != ERROR_SUCCESS) goto error_close_progid_key;
262 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
263 if (res != ERROR_SUCCESS) goto error_close_progid_key;
267 res = register_key_defvalueA(progid_key, curver_keyname,
269 if (res != ERROR_SUCCESS) goto error_close_progid_key;
275 res = RegCreateKeyExA(progid_key, extra, 0,
276 NULL, 0, KEY_READ | KEY_WRITE, NULL,
278 if (res == ERROR_SUCCESS)
279 RegCloseKey(extra_key);
282 error_close_progid_key:
283 RegCloseKey(progid_key);
287 /***********************************************************************
290 static struct regsvr_coclass const coclass_list[] = {
297 { NULL } /* list terminator */
300 /***********************************************************************
301 * DllRegisterServer (QEDIT.@)
303 HRESULT WINAPI DllRegisterServer(void)
309 hr = register_coclasses(coclass_list);
313 /***********************************************************************
314 * DllUnregisterServer (QEDIT.@)
316 HRESULT WINAPI DllUnregisterServer(void)
322 hr = unregister_coclasses(coclass_list);