Sync trunk.
[reactos.git] / dll / directx / qedit / regsvr.c
1 /*
2 * self-registerable dll functions for qedit.dll
3 *
4 * Copyright (C) 2008 Google (Lei Zhang)
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
21 #include "qedit_private.h"
22 #include "winreg.h"
23
24 #include "wine/debug.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(qedit);
27
28 struct regsvr_coclass
29 {
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 */
38 };
39
40 static HRESULT register_coclasses(struct regsvr_coclass const *list);
41 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
42
43 /***********************************************************************
44 * static string constants
45 */
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',
59 0 };
60 static char const tmodel_valuename[] = "ThreadingModel";
61
62 /***********************************************************************
63 * static helper functions
64 */
65 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
66 WCHAR const *value);
67 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
68 char const *value);
69 static LONG register_progid(WCHAR const *clsid,
70 char const *progid, char const *curver_progid,
71 char const *name, char const *extra);
72
73
74
75 /***********************************************************************
76 * register_coclasses
77 */
78 static HRESULT register_coclasses(struct regsvr_coclass const *list)
79 {
80 LONG res = ERROR_SUCCESS;
81 HKEY coclass_key;
82
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;
86
87 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
88 WCHAR buf[39];
89 HKEY clsid_key;
90
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;
95
96 if (list->name) {
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;
101 }
102
103 if (list->ips) {
104 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
105 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
106 }
107
108 if (list->ips32) {
109 HKEY ips32_key;
110
111 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
112 KEY_READ | KEY_WRITE, NULL,
113 &ips32_key, NULL);
114 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
115
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;
125 }
126
127 if (list->progid) {
128 res = register_key_defvalueA(clsid_key, progid_keyname,
129 list->progid);
130 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
131
132 res = register_progid(buf, list->progid, NULL,
133 list->name, list->progid_extra);
134 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
135 }
136
137 if (list->viprogid) {
138 res = register_key_defvalueA(clsid_key, viprogid_keyname,
139 list->viprogid);
140 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
141
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;
145 }
146
147 error_close_clsid_key:
148 RegCloseKey(clsid_key);
149 }
150
151 error_close_coclass_key:
152 RegCloseKey(coclass_key);
153 error_return:
154 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
155 }
156
157 /***********************************************************************
158 * unregister_coclasses
159 */
160 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
161 {
162 LONG res = ERROR_SUCCESS;
163 HKEY coclass_key;
164
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;
169
170 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
171 WCHAR buf[39];
172
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;
177
178 if (list->progid) {
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;
182 }
183
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;
188 }
189 }
190
191 error_close_coclass_key:
192 RegCloseKey(coclass_key);
193 error_return:
194 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
195 }
196
197 /***********************************************************************
198 * regsvr_key_defvalueW
199 */
200 static LONG register_key_defvalueW(
201 HKEY base,
202 WCHAR const *name,
203 WCHAR const *value)
204 {
205 LONG res;
206 HKEY key;
207
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));
213 RegCloseKey(key);
214 return res;
215 }
216
217 /***********************************************************************
218 * regsvr_key_defvalueA
219 */
220 static LONG register_key_defvalueA(
221 HKEY base,
222 WCHAR const *name,
223 char const *value)
224 {
225 LONG res;
226 HKEY key;
227
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);
233 RegCloseKey(key);
234 return res;
235 }
236
237 /***********************************************************************
238 * regsvr_progid
239 */
240 static LONG register_progid(
241 WCHAR const *clsid,
242 char const *progid,
243 char const *curver_progid,
244 char const *name,
245 char const *extra)
246 {
247 LONG res;
248 HKEY progid_key;
249
250 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
251 NULL, 0, KEY_READ | KEY_WRITE, NULL,
252 &progid_key, NULL);
253 if (res != ERROR_SUCCESS) return res;
254
255 if (name) {
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;
259 }
260
261 if (clsid) {
262 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
263 if (res != ERROR_SUCCESS) goto error_close_progid_key;
264 }
265
266 if (curver_progid) {
267 res = register_key_defvalueA(progid_key, curver_keyname,
268 curver_progid);
269 if (res != ERROR_SUCCESS) goto error_close_progid_key;
270 }
271
272 if (extra) {
273 HKEY extra_key;
274
275 res = RegCreateKeyExA(progid_key, extra, 0,
276 NULL, 0, KEY_READ | KEY_WRITE, NULL,
277 &extra_key, NULL);
278 if (res == ERROR_SUCCESS)
279 RegCloseKey(extra_key);
280 }
281
282 error_close_progid_key:
283 RegCloseKey(progid_key);
284 return res;
285 }
286
287 /***********************************************************************
288 * coclass list
289 */
290 static struct regsvr_coclass const coclass_list[] = {
291 { &CLSID_MediaDet,
292 "MediaDet",
293 NULL,
294 "qedit.dll",
295 "Both"
296 },
297 { &CLSID_SampleGrabber,
298 "Sample Grabber",
299 NULL,
300 "qedit.dll",
301 "Both"
302 },
303 { NULL } /* list terminator */
304 };
305
306 /***********************************************************************
307 * DllRegisterServer (QEDIT.@)
308 */
309 HRESULT WINAPI DllRegisterServer(void)
310 {
311 HRESULT hr;
312
313 TRACE("\n");
314
315 hr = register_coclasses(coclass_list);
316 return hr;
317 }
318
319 /***********************************************************************
320 * DllUnregisterServer (QEDIT.@)
321 */
322 HRESULT WINAPI DllUnregisterServer(void)
323 {
324 HRESULT hr;
325
326 TRACE("\n");
327
328 hr = unregister_coclasses(coclass_list);
329 return hr;
330 }