2 * self-registerable dll functions for avifile.dll and avifil32.dll
4 * Copyright (C) 2003 John K. Hohm
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
33 #include "avifile_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
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);
120 static LONG recursive_delete_key(HKEY key);
121 static LONG recursive_delete_keyA(HKEY base, char const *name);
122 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
124 /***********************************************************************
125 * register_interfaces
127 static HRESULT register_interfaces(struct regsvr_interface const *list)
129 LONG res = ERROR_SUCCESS;
132 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
133 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
134 if (res != ERROR_SUCCESS) goto error_return;
136 for (; res == ERROR_SUCCESS && list->iid; ++list) {
140 StringFromGUID2(list->iid, buf, 39);
141 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
142 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
143 if (res != ERROR_SUCCESS) goto error_close_interface_key;
146 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
147 (CONST BYTE*)(list->name),
148 strlen(list->name) + 1);
149 if (res != ERROR_SUCCESS) goto error_close_iid_key;
152 if (list->base_iid) {
153 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
154 if (res != ERROR_SUCCESS) goto error_close_iid_key;
157 if (0 <= list->num_methods) {
158 static WCHAR const fmt[3] = { '%', 'd', 0 };
161 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
162 KEY_READ | KEY_WRITE, NULL, &key, NULL);
163 if (res != ERROR_SUCCESS) goto error_close_iid_key;
165 wsprintfW(buf, fmt, list->num_methods);
166 res = RegSetValueExW(key, NULL, 0, REG_SZ,
168 (lstrlenW(buf) + 1) * sizeof(WCHAR));
171 if (res != ERROR_SUCCESS) goto error_close_iid_key;
174 if (list->ps_clsid) {
175 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
176 if (res != ERROR_SUCCESS) goto error_close_iid_key;
179 if (list->ps_clsid32) {
180 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
181 if (res != ERROR_SUCCESS) goto error_close_iid_key;
185 RegCloseKey(iid_key);
188 error_close_interface_key:
189 RegCloseKey(interface_key);
191 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
194 /***********************************************************************
195 * unregister_interfaces
197 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
199 LONG res = ERROR_SUCCESS;
202 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
203 KEY_READ | KEY_WRITE, &interface_key);
204 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
205 if (res != ERROR_SUCCESS) goto error_return;
207 for (; res == ERROR_SUCCESS && list->iid; ++list) {
210 StringFromGUID2(list->iid, buf, 39);
211 res = recursive_delete_keyW(interface_key, buf);
214 RegCloseKey(interface_key);
216 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
219 /***********************************************************************
222 static HRESULT register_coclasses(struct regsvr_coclass const *list)
224 LONG res = ERROR_SUCCESS;
227 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
228 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
229 if (res != ERROR_SUCCESS) goto error_return;
231 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
235 StringFromGUID2(list->clsid, buf, 39);
236 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
237 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
238 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
241 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
242 (CONST BYTE*)(list->name),
243 strlen(list->name) + 1);
244 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
248 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
249 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
255 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
256 KEY_READ | KEY_WRITE, NULL,
258 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
260 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
261 (CONST BYTE*)list->ips32,
262 lstrlenA(list->ips32) + 1);
263 if (res == ERROR_SUCCESS && list->ips32_tmodel)
264 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
265 (CONST BYTE*)list->ips32_tmodel,
266 strlen(list->ips32_tmodel) + 1);
267 RegCloseKey(ips32_key);
268 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
272 res = register_key_defvalueA(clsid_key, progid_keyname,
274 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
276 res = register_progid(buf, list->progid, NULL,
277 list->name, list->progid_extra);
278 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
281 if (list->viprogid) {
282 res = register_key_defvalueA(clsid_key, viprogid_keyname,
284 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
286 res = register_progid(buf, list->viprogid, list->progid,
287 list->name, list->progid_extra);
288 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
291 error_close_clsid_key:
292 RegCloseKey(clsid_key);
295 error_close_coclass_key:
296 RegCloseKey(coclass_key);
298 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
301 /***********************************************************************
302 * unregister_coclasses
304 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
306 LONG res = ERROR_SUCCESS;
309 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
310 KEY_READ | KEY_WRITE, &coclass_key);
311 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
312 if (res != ERROR_SUCCESS) goto error_return;
314 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
317 StringFromGUID2(list->clsid, buf, 39);
318 res = recursive_delete_keyW(coclass_key, buf);
319 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
322 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
323 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
326 if (list->viprogid) {
327 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid);
328 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
332 error_close_coclass_key:
333 RegCloseKey(coclass_key);
335 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
338 /***********************************************************************
341 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
345 StringFromGUID2(guid, buf, 39);
346 return register_key_defvalueW(base, name, buf);
349 /***********************************************************************
350 * regsvr_key_defvalueW
352 static LONG register_key_defvalueW(
360 res = RegCreateKeyExW(base, name, 0, NULL, 0,
361 KEY_READ | KEY_WRITE, NULL, &key, NULL);
362 if (res != ERROR_SUCCESS) return res;
363 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
364 (lstrlenW(value) + 1) * sizeof(WCHAR));
369 /***********************************************************************
370 * regsvr_key_defvalueA
372 static LONG register_key_defvalueA(
380 res = RegCreateKeyExW(base, name, 0, NULL, 0,
381 KEY_READ | KEY_WRITE, NULL, &key, NULL);
382 if (res != ERROR_SUCCESS) return res;
383 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
384 lstrlenA(value) + 1);
389 /***********************************************************************
392 static LONG register_progid(
395 char const *curver_progid,
402 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
403 NULL, 0, KEY_READ | KEY_WRITE, NULL,
405 if (res != ERROR_SUCCESS) return res;
408 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
409 (CONST BYTE*)name, strlen(name) + 1);
410 if (res != ERROR_SUCCESS) goto error_close_progid_key;
414 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
415 if (res != ERROR_SUCCESS) goto error_close_progid_key;
419 res = register_key_defvalueA(progid_key, curver_keyname,
421 if (res != ERROR_SUCCESS) goto error_close_progid_key;
427 res = RegCreateKeyExA(progid_key, extra, 0,
428 NULL, 0, KEY_READ | KEY_WRITE, NULL,
430 if (res == ERROR_SUCCESS)
431 RegCloseKey(extra_key);
434 error_close_progid_key:
435 RegCloseKey(progid_key);
439 /***********************************************************************
440 * recursive_delete_key
442 static LONG recursive_delete_key(HKEY key)
445 WCHAR subkey_name[MAX_PATH];
450 cName = sizeof(subkey_name) / sizeof(WCHAR);
451 res = RegEnumKeyExW(key, 0, subkey_name, &cName,
452 NULL, NULL, NULL, NULL);
453 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
454 res = ERROR_SUCCESS; /* presumably we're done enumerating */
457 res = RegOpenKeyExW(key, subkey_name, 0,
458 KEY_READ | KEY_WRITE, &subkey);
459 if (res == ERROR_FILE_NOT_FOUND) continue;
460 if (res != ERROR_SUCCESS) break;
462 res = recursive_delete_key(subkey);
464 if (res != ERROR_SUCCESS) break;
467 if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
471 /***********************************************************************
472 * recursive_delete_keyA
474 static LONG recursive_delete_keyA(HKEY base, char const *name)
479 res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
480 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
481 if (res != ERROR_SUCCESS) return res;
482 res = recursive_delete_key(key);
487 /***********************************************************************
488 * recursive_delete_keyW
490 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
495 res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
496 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
497 if (res != ERROR_SUCCESS) return res;
498 res = recursive_delete_key(key);
503 /***********************************************************************
506 static GUID const CLSID_AVIProxy = {
507 0x0002000D, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
509 static struct regsvr_coclass const coclass_list[] = {
511 "Microsoft AVI Files",
517 "AVI Compressed Stream",
523 "Microsoft Wave File",
529 "IAVIStream & IAVIFile Proxy",
535 "ACM Compressed Audio Stream",
540 { NULL } /* list terminator */
543 /***********************************************************************
547 static struct regsvr_interface const interface_list[] = {
548 { NULL } /* list terminator */
551 /***********************************************************************
552 * DllRegisterServer (AVIFILE.@)
554 HRESULT WINAPI DllRegisterServer(void)
560 hr = register_coclasses(coclass_list);
562 hr = register_interfaces(interface_list);
566 /***********************************************************************
567 * DllUnregisterServer (AVIFILE.@)
569 HRESULT WINAPI DllUnregisterServer(void)
575 hr = unregister_coclasses(coclass_list);
577 hr = unregister_interfaces(interface_list);