2 * self-registerable dll functions for amstream.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define COM_NO_WINDOWS_H
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(amstream);
42 * Near the bottom of this file are the exported DllRegisterServer and
43 * DllUnregisterServer, which make all this worthwhile.
46 /***********************************************************************
47 * interface for self-registering
49 struct regsvr_interface
51 IID const *iid; /* NULL for end of list */
52 LPCSTR name; /* can be NULL to omit */
53 IID const *base_iid; /* can be NULL to omit */
54 int num_methods; /* can be <0 to omit */
55 CLSID const *ps_clsid; /* can be NULL to omit */
56 CLSID const *ps_clsid32; /* can be NULL to omit */
59 static HRESULT register_interfaces(struct regsvr_interface const *list);
60 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
64 CLSID const *clsid; /* NULL for end of list */
65 LPCSTR name; /* can be NULL to omit */
66 LPCSTR ips; /* can be NULL to omit */
67 LPCSTR ips32; /* can be NULL to omit */
68 LPCSTR ips32_tmodel; /* can be NULL to omit */
69 LPCSTR progid; /* can be NULL to omit */
70 LPCSTR viprogid; /* can be NULL to omit */
71 LPCSTR progid_extra; /* can be NULL to omit */
74 static HRESULT register_coclasses(struct regsvr_coclass const *list);
75 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
77 /***********************************************************************
78 * static string constants
80 static WCHAR const interface_keyname[10] = {
81 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
82 static WCHAR const base_ifa_keyname[14] = {
83 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
85 static WCHAR const num_methods_keyname[11] = {
86 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
87 static WCHAR const ps_clsid_keyname[15] = {
88 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
90 static WCHAR const ps_clsid32_keyname[17] = {
91 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
92 'i', 'd', '3', '2', 0 };
93 static WCHAR const clsid_keyname[6] = {
94 'C', 'L', 'S', 'I', 'D', 0 };
95 static WCHAR const curver_keyname[7] = {
96 'C', 'u', 'r', 'V', 'e', 'r', 0 };
97 static WCHAR const ips_keyname[13] = {
98 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
100 static WCHAR const ips32_keyname[15] = {
101 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
103 static WCHAR const progid_keyname[7] = {
104 'P', 'r', 'o', 'g', 'I', 'D', 0 };
105 static WCHAR const viprogid_keyname[25] = {
106 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
107 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
109 static char const tmodel_valuename[] = "ThreadingModel";
111 /***********************************************************************
112 * static helper functions
114 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
115 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
117 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
119 static LONG register_progid(WCHAR const *clsid,
120 char const *progid, char const *curver_progid,
121 char const *name, char const *extra);
122 static LONG recursive_delete_key(HKEY key);
123 static LONG recursive_delete_keyA(HKEY base, char const *name);
124 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
126 /***********************************************************************
127 * register_interfaces
129 static HRESULT register_interfaces(struct regsvr_interface const *list)
131 LONG res = ERROR_SUCCESS;
134 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
135 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
136 if (res != ERROR_SUCCESS) goto error_return;
138 for (; res == ERROR_SUCCESS && list->iid; ++list) {
142 StringFromGUID2(list->iid, buf, 39);
143 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
144 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
145 if (res != ERROR_SUCCESS) goto error_close_interface_key;
148 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
149 (CONST BYTE*)(list->name),
150 strlen(list->name) + 1);
151 if (res != ERROR_SUCCESS) goto error_close_iid_key;
154 if (list->base_iid) {
155 register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
156 if (res != ERROR_SUCCESS) goto error_close_iid_key;
159 if (0 <= list->num_methods) {
160 static WCHAR const fmt[3] = { '%', 'd', 0 };
163 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
164 KEY_READ | KEY_WRITE, NULL, &key, NULL);
165 if (res != ERROR_SUCCESS) goto error_close_iid_key;
167 wsprintfW(buf, fmt, list->num_methods);
168 res = RegSetValueExW(key, NULL, 0, REG_SZ,
170 (lstrlenW(buf) + 1) * sizeof(WCHAR));
173 if (res != ERROR_SUCCESS) goto error_close_iid_key;
176 if (list->ps_clsid) {
177 register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
178 if (res != ERROR_SUCCESS) goto error_close_iid_key;
181 if (list->ps_clsid32) {
182 register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
183 if (res != ERROR_SUCCESS) goto error_close_iid_key;
187 RegCloseKey(iid_key);
190 error_close_interface_key:
191 RegCloseKey(interface_key);
193 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
196 /***********************************************************************
197 * unregister_interfaces
199 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
201 LONG res = ERROR_SUCCESS;
204 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
205 KEY_READ | KEY_WRITE, &interface_key);
206 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
207 if (res != ERROR_SUCCESS) goto error_return;
209 for (; res == ERROR_SUCCESS && list->iid; ++list) {
212 StringFromGUID2(list->iid, buf, 39);
213 res = recursive_delete_keyW(interface_key, buf);
216 RegCloseKey(interface_key);
218 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
221 /***********************************************************************
224 static HRESULT register_coclasses(struct regsvr_coclass const *list)
226 LONG res = ERROR_SUCCESS;
229 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
230 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
231 if (res != ERROR_SUCCESS) goto error_return;
233 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
237 StringFromGUID2(list->clsid, buf, 39);
238 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
239 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
240 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
243 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
244 (CONST BYTE*)(list->name),
245 strlen(list->name) + 1);
246 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
250 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
251 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
257 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
258 KEY_READ | KEY_WRITE, NULL,
260 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
262 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
263 (CONST BYTE*)list->ips32,
264 lstrlenA(list->ips32) + 1);
265 if (res == ERROR_SUCCESS && list->ips32_tmodel)
266 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
267 (CONST BYTE*)list->ips32_tmodel,
268 strlen(list->ips32_tmodel) + 1);
269 RegCloseKey(ips32_key);
270 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
274 res = register_key_defvalueA(clsid_key, progid_keyname,
276 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
278 res = register_progid(buf, list->progid, NULL,
279 list->name, list->progid_extra);
280 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
283 if (list->viprogid) {
284 res = register_key_defvalueA(clsid_key, viprogid_keyname,
286 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
288 res = register_progid(buf, list->viprogid, list->progid,
289 list->name, list->progid_extra);
290 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
293 error_close_clsid_key:
294 RegCloseKey(clsid_key);
297 error_close_coclass_key:
298 RegCloseKey(coclass_key);
300 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
303 /***********************************************************************
304 * unregister_coclasses
306 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
308 LONG res = ERROR_SUCCESS;
311 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
312 KEY_READ | KEY_WRITE, &coclass_key);
313 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
314 if (res != ERROR_SUCCESS) goto error_return;
316 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
319 StringFromGUID2(list->clsid, buf, 39);
320 res = recursive_delete_keyW(coclass_key, buf);
321 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
324 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
325 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
328 if (list->viprogid) {
329 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid);
330 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
334 error_close_coclass_key:
335 RegCloseKey(coclass_key);
337 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
340 /***********************************************************************
343 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
347 StringFromGUID2(guid, buf, 39);
348 return register_key_defvalueW(base, name, buf);
351 /***********************************************************************
352 * regsvr_key_defvalueW
354 static LONG register_key_defvalueW(
362 res = RegCreateKeyExW(base, name, 0, NULL, 0,
363 KEY_READ | KEY_WRITE, NULL, &key, NULL);
364 if (res != ERROR_SUCCESS) return res;
365 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
366 (lstrlenW(value) + 1) * sizeof(WCHAR));
371 /***********************************************************************
372 * regsvr_key_defvalueA
374 static LONG register_key_defvalueA(
382 res = RegCreateKeyExW(base, name, 0, NULL, 0,
383 KEY_READ | KEY_WRITE, NULL, &key, NULL);
384 if (res != ERROR_SUCCESS) return res;
385 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
386 lstrlenA(value) + 1);
391 /***********************************************************************
394 static LONG register_progid(
397 char const *curver_progid,
404 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
405 NULL, 0, KEY_READ | KEY_WRITE, NULL,
407 if (res != ERROR_SUCCESS) return res;
410 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
411 (CONST BYTE*)name, strlen(name) + 1);
412 if (res != ERROR_SUCCESS) goto error_close_progid_key;
416 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
417 if (res != ERROR_SUCCESS) goto error_close_progid_key;
421 res = register_key_defvalueA(progid_key, curver_keyname,
423 if (res != ERROR_SUCCESS) goto error_close_progid_key;
429 res = RegCreateKeyExA(progid_key, extra, 0,
430 NULL, 0, KEY_READ | KEY_WRITE, NULL,
432 if (res == ERROR_SUCCESS)
433 RegCloseKey(extra_key);
436 error_close_progid_key:
437 RegCloseKey(progid_key);
441 /***********************************************************************
442 * recursive_delete_key
444 static LONG recursive_delete_key(HKEY key)
447 WCHAR subkey_name[MAX_PATH];
452 cName = sizeof(subkey_name) / sizeof(WCHAR);
453 res = RegEnumKeyExW(key, 0, subkey_name, &cName,
454 NULL, NULL, NULL, NULL);
455 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
456 res = ERROR_SUCCESS; /* presumably we're done enumerating */
459 res = RegOpenKeyExW(key, subkey_name, 0,
460 KEY_READ | KEY_WRITE, &subkey);
461 if (res == ERROR_FILE_NOT_FOUND) continue;
462 if (res != ERROR_SUCCESS) break;
464 res = recursive_delete_key(subkey);
466 if (res != ERROR_SUCCESS) break;
469 if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
473 /***********************************************************************
474 * recursive_delete_keyA
476 static LONG recursive_delete_keyA(HKEY base, char const *name)
481 res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
482 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
483 if (res != ERROR_SUCCESS) return res;
484 res = recursive_delete_key(key);
489 /***********************************************************************
490 * recursive_delete_keyW
492 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
497 res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
498 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
499 if (res != ERROR_SUCCESS) return res;
500 res = recursive_delete_key(key);
505 /***********************************************************************
508 static struct regsvr_coclass const coclass_list[] = {
509 { &CLSID_AMMultiMediaStream,
510 "ActiveMovie MultiMedia Stream",
515 { NULL } /* list terminator */
518 /***********************************************************************
522 static struct regsvr_interface const interface_list[] = {
523 { NULL } /* list terminator */
526 /***********************************************************************
527 * DllRegisterServer (AMSTREAM.@)
529 HRESULT WINAPI DllRegisterServer(void)
535 hr = register_coclasses(coclass_list);
537 hr = register_interfaces(interface_list);
541 /***********************************************************************
542 * DllUnregisterServer (AMSTREAM.@)
544 HRESULT WINAPI DllUnregisterServer(void)
550 hr = unregister_coclasses(coclass_list);
552 hr = unregister_interfaces(interface_list);