2 * self-registerable dll functions for dinput.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 "wine/debug.h"
34 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
39 * Near the bottom of this file are the exported DllRegisterServer and
40 * DllUnregisterServer, which make all this worthwhile.
43 /***********************************************************************
44 * interface for self-registering
46 struct regsvr_interface
48 IID const *iid; /* NULL for end of list */
49 LPCSTR name; /* can be NULL to omit */
50 IID const *base_iid; /* can be NULL to omit */
51 int num_methods; /* can be <0 to omit */
52 CLSID const *ps_clsid; /* can be NULL to omit */
53 CLSID const *ps_clsid32; /* can be NULL to omit */
56 static HRESULT register_interfaces(struct regsvr_interface const *list);
57 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
61 CLSID const *clsid; /* NULL for end of list */
62 LPCSTR name; /* can be NULL to omit */
63 LPCSTR ips; /* can be NULL to omit */
64 LPCSTR ips32; /* can be NULL to omit */
65 LPCSTR ips32_tmodel; /* can be NULL to omit */
66 LPCSTR progid; /* can be NULL to omit */
67 LPCSTR viprogid; /* can be NULL to omit */
68 LPCSTR progid_extra; /* can be NULL to omit */
71 static HRESULT register_coclasses(struct regsvr_coclass const *list);
72 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
74 /***********************************************************************
75 * static string constants
77 static WCHAR const interface_keyname[10] = {
78 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
79 static WCHAR const base_ifa_keyname[14] = {
80 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
82 static WCHAR const num_methods_keyname[11] = {
83 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
84 static WCHAR const ps_clsid_keyname[15] = {
85 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
87 static WCHAR const ps_clsid32_keyname[17] = {
88 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
89 'i', 'd', '3', '2', 0 };
90 static WCHAR const clsid_keyname[6] = {
91 'C', 'L', 'S', 'I', 'D', 0 };
92 static WCHAR const curver_keyname[7] = {
93 'C', 'u', 'r', 'V', 'e', 'r', 0 };
94 static WCHAR const ips_keyname[13] = {
95 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
97 static WCHAR const ips32_keyname[15] = {
98 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
100 static WCHAR const progid_keyname[7] = {
101 'P', 'r', 'o', 'g', 'I', 'D', 0 };
102 static WCHAR const viprogid_keyname[25] = {
103 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
104 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
106 static char const tmodel_valuename[] = "ThreadingModel";
108 /***********************************************************************
109 * static helper functions
111 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
112 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
114 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
116 static LONG register_progid(WCHAR const *clsid,
117 char const *progid, char const *curver_progid,
118 char const *name, char const *extra);
120 /***********************************************************************
121 * register_interfaces
123 static HRESULT register_interfaces(struct regsvr_interface const *list)
125 LONG res = ERROR_SUCCESS;
128 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
129 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
130 if (res != ERROR_SUCCESS) goto error_return;
132 for (; res == ERROR_SUCCESS && list->iid; ++list) {
136 StringFromGUID2(list->iid, buf, 39);
137 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
138 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
139 if (res != ERROR_SUCCESS) goto error_close_interface_key;
142 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
143 (CONST BYTE*)(list->name),
144 strlen(list->name) + 1);
145 if (res != ERROR_SUCCESS) goto error_close_iid_key;
148 if (list->base_iid) {
149 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
150 if (res != ERROR_SUCCESS) goto error_close_iid_key;
153 if (0 <= list->num_methods) {
154 static WCHAR const fmt[3] = { '%', 'd', 0 };
157 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
158 KEY_READ | KEY_WRITE, NULL, &key, NULL);
159 if (res != ERROR_SUCCESS) goto error_close_iid_key;
161 sprintfW(buf, fmt, list->num_methods);
162 res = RegSetValueExW(key, NULL, 0, REG_SZ,
164 (lstrlenW(buf) + 1) * sizeof(WCHAR));
167 if (res != ERROR_SUCCESS) goto error_close_iid_key;
170 if (list->ps_clsid) {
171 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
172 if (res != ERROR_SUCCESS) goto error_close_iid_key;
175 if (list->ps_clsid32) {
176 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
177 if (res != ERROR_SUCCESS) goto error_close_iid_key;
181 RegCloseKey(iid_key);
184 error_close_interface_key:
185 RegCloseKey(interface_key);
187 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
190 /***********************************************************************
191 * unregister_interfaces
193 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
195 LONG res = ERROR_SUCCESS;
198 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
199 KEY_READ | KEY_WRITE, &interface_key);
200 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
201 if (res != ERROR_SUCCESS) goto error_return;
203 for (; res == ERROR_SUCCESS && list->iid; ++list) {
206 StringFromGUID2(list->iid, buf, 39);
207 res = RegDeleteTreeW(interface_key, buf);
208 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
211 RegCloseKey(interface_key);
213 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
216 /***********************************************************************
219 static HRESULT register_coclasses(struct regsvr_coclass const *list)
221 LONG res = ERROR_SUCCESS;
224 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
225 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
226 if (res != ERROR_SUCCESS) goto error_return;
228 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
232 StringFromGUID2(list->clsid, buf, 39);
233 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
234 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
235 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
238 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
239 (CONST BYTE*)(list->name),
240 strlen(list->name) + 1);
241 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
245 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
246 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
252 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
253 KEY_READ | KEY_WRITE, NULL,
255 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
257 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
258 (CONST BYTE*)list->ips32,
259 lstrlenA(list->ips32) + 1);
260 if (res == ERROR_SUCCESS && list->ips32_tmodel)
261 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
262 (CONST BYTE*)list->ips32_tmodel,
263 strlen(list->ips32_tmodel) + 1);
264 RegCloseKey(ips32_key);
265 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
269 res = register_key_defvalueA(clsid_key, progid_keyname,
271 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
273 res = register_progid(buf, list->progid, NULL,
274 list->name, list->progid_extra);
275 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
278 if (list->viprogid) {
279 res = register_key_defvalueA(clsid_key, viprogid_keyname,
281 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
283 res = register_progid(buf, list->viprogid, list->progid,
284 list->name, list->progid_extra);
285 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
288 error_close_clsid_key:
289 RegCloseKey(clsid_key);
292 error_close_coclass_key:
293 RegCloseKey(coclass_key);
295 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
298 /***********************************************************************
299 * unregister_coclasses
301 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
303 LONG res = ERROR_SUCCESS;
306 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
307 KEY_READ | KEY_WRITE, &coclass_key);
308 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
309 if (res != ERROR_SUCCESS) goto error_return;
311 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
314 StringFromGUID2(list->clsid, buf, 39);
315 res = RegDeleteTreeW(coclass_key, buf);
316 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
317 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
320 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
321 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
322 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
325 if (list->viprogid) {
326 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
327 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
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 /***********************************************************************
442 static struct regsvr_coclass const coclass_list[] = {
445 "DirectInput Object",
451 &CLSID_DirectInputDevice,
452 "DirectInputDevice Object",
457 { NULL } /* list terminator */
460 /***********************************************************************
464 static struct regsvr_interface const interface_list[] = {
465 { NULL } /* list terminator */
468 /***********************************************************************
469 * DllRegisterServer (DINPUT.@)
471 HRESULT WINAPI DllRegisterServer(void)
477 hr = register_coclasses(coclass_list);
479 hr = register_interfaces(interface_list);
483 /***********************************************************************
484 * DllUnregisterServer (DINPUT.@)
486 HRESULT WINAPI DllUnregisterServer(void)
492 hr = unregister_coclasses(coclass_list);
494 hr = unregister_interfaces(interface_list);