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"
35 WINE_DEFAULT_DEBUG_CHANNEL(dinput
);
38 * Near the bottom of this file are the exported DllRegisterServer and
39 * DllUnregisterServer, which make all this worthwhile.
42 /***********************************************************************
43 * interface for self-registering
45 struct regsvr_interface
47 IID
const *iid
; /* NULL for end of list */
48 LPCSTR name
; /* can be NULL to omit */
49 IID
const *base_iid
; /* can be NULL to omit */
50 int num_methods
; /* can be <0 to omit */
51 CLSID
const *ps_clsid
; /* can be NULL to omit */
52 CLSID
const *ps_clsid32
; /* can be NULL to omit */
55 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
56 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
60 CLSID
const *clsid
; /* NULL for end of list */
61 LPCSTR name
; /* can be NULL to omit */
62 LPCSTR ips
; /* can be NULL to omit */
63 LPCSTR ips32
; /* can be NULL to omit */
64 LPCSTR ips32_tmodel
; /* can be NULL to omit */
65 LPCSTR progid
; /* can be NULL to omit */
66 LPCSTR viprogid
; /* can be NULL to omit */
67 LPCSTR progid_extra
; /* can be NULL to omit */
70 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
71 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
73 /***********************************************************************
74 * static string constants
76 static WCHAR
const interface_keyname
[10] = {
77 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
78 static WCHAR
const base_ifa_keyname
[14] = {
79 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
81 static WCHAR
const num_methods_keyname
[11] = {
82 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
83 static WCHAR
const ps_clsid_keyname
[15] = {
84 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
86 static WCHAR
const ps_clsid32_keyname
[17] = {
87 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
88 'i', 'd', '3', '2', 0 };
89 static WCHAR
const clsid_keyname
[6] = {
90 'C', 'L', 'S', 'I', 'D', 0 };
91 static WCHAR
const curver_keyname
[7] = {
92 'C', 'u', 'r', 'V', 'e', 'r', 0 };
93 static WCHAR
const ips_keyname
[13] = {
94 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
96 static WCHAR
const ips32_keyname
[15] = {
97 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
99 static WCHAR
const progid_keyname
[7] = {
100 'P', 'r', 'o', 'g', 'I', 'D', 0 };
101 static WCHAR
const viprogid_keyname
[25] = {
102 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
103 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
105 static char const tmodel_valuename
[] = "ThreadingModel";
107 /***********************************************************************
108 * static helper functions
110 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
111 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
113 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
115 static LONG
register_progid(WCHAR
const *clsid
,
116 char const *progid
, char const *curver_progid
,
117 char const *name
, char const *extra
);
119 /***********************************************************************
120 * register_interfaces
122 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
124 LONG res
= ERROR_SUCCESS
;
127 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
128 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
129 if (res
!= ERROR_SUCCESS
) goto error_return
;
131 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
135 StringFromGUID2(list
->iid
, buf
, 39);
136 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
137 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
138 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
141 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
142 (CONST BYTE
*)(list
->name
),
143 strlen(list
->name
) + 1);
144 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
147 if (list
->base_iid
) {
148 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
149 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
152 if (0 <= list
->num_methods
) {
153 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
156 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
157 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
158 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
160 wsprintfW(buf
, fmt
, list
->num_methods
);
161 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
163 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
166 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
169 if (list
->ps_clsid
) {
170 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
171 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
174 if (list
->ps_clsid32
) {
175 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
176 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
180 RegCloseKey(iid_key
);
183 error_close_interface_key
:
184 RegCloseKey(interface_key
);
186 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
189 /***********************************************************************
190 * unregister_interfaces
192 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
194 LONG res
= ERROR_SUCCESS
;
197 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
198 KEY_READ
| KEY_WRITE
, &interface_key
);
199 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
200 if (res
!= ERROR_SUCCESS
) goto error_return
;
202 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
205 StringFromGUID2(list
->iid
, buf
, 39);
206 res
= RegDeleteTreeW(interface_key
, buf
);
207 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
210 RegCloseKey(interface_key
);
212 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
215 /***********************************************************************
218 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
220 LONG res
= ERROR_SUCCESS
;
223 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
224 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
225 if (res
!= ERROR_SUCCESS
) goto error_return
;
227 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
231 StringFromGUID2(list
->clsid
, buf
, 39);
232 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
233 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
234 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
237 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
238 (CONST BYTE
*)(list
->name
),
239 strlen(list
->name
) + 1);
240 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
244 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
245 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
251 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
252 KEY_READ
| KEY_WRITE
, NULL
,
254 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
256 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
257 (CONST BYTE
*)list
->ips32
,
258 lstrlenA(list
->ips32
) + 1);
259 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
260 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
261 (CONST BYTE
*)list
->ips32_tmodel
,
262 strlen(list
->ips32_tmodel
) + 1);
263 RegCloseKey(ips32_key
);
264 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
268 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
270 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
272 res
= register_progid(buf
, list
->progid
, NULL
,
273 list
->name
, list
->progid_extra
);
274 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
277 if (list
->viprogid
) {
278 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
280 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
282 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
283 list
->name
, list
->progid_extra
);
284 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
287 error_close_clsid_key
:
288 RegCloseKey(clsid_key
);
291 error_close_coclass_key
:
292 RegCloseKey(coclass_key
);
294 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
297 /***********************************************************************
298 * unregister_coclasses
300 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
302 LONG res
= ERROR_SUCCESS
;
305 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
306 KEY_READ
| KEY_WRITE
, &coclass_key
);
307 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
308 if (res
!= ERROR_SUCCESS
) goto error_return
;
310 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
313 StringFromGUID2(list
->clsid
, buf
, 39);
314 res
= RegDeleteTreeW(coclass_key
, buf
);
315 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
316 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
319 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
320 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
321 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
324 if (list
->viprogid
) {
325 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
326 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
327 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
331 error_close_coclass_key
:
332 RegCloseKey(coclass_key
);
334 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
337 /***********************************************************************
340 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
344 StringFromGUID2(guid
, buf
, 39);
345 return register_key_defvalueW(base
, name
, buf
);
348 /***********************************************************************
349 * regsvr_key_defvalueW
351 static LONG
register_key_defvalueW(
359 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
360 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
361 if (res
!= ERROR_SUCCESS
) return res
;
362 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
363 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
368 /***********************************************************************
369 * regsvr_key_defvalueA
371 static LONG
register_key_defvalueA(
379 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
380 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
381 if (res
!= ERROR_SUCCESS
) return res
;
382 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
383 lstrlenA(value
) + 1);
388 /***********************************************************************
391 static LONG
register_progid(
394 char const *curver_progid
,
401 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
402 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
404 if (res
!= ERROR_SUCCESS
) return res
;
407 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
408 (CONST BYTE
*)name
, strlen(name
) + 1);
409 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
413 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
414 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
418 res
= register_key_defvalueA(progid_key
, curver_keyname
,
420 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
426 res
= RegCreateKeyExA(progid_key
, extra
, 0,
427 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
429 if (res
== ERROR_SUCCESS
)
430 RegCloseKey(extra_key
);
433 error_close_progid_key
:
434 RegCloseKey(progid_key
);
438 /***********************************************************************
441 static struct regsvr_coclass
const coclass_list
[] = {
444 "DirectInput Object",
450 &CLSID_DirectInputDevice
,
451 "DirectInputDevice Object",
456 { NULL
} /* list terminator */
459 /***********************************************************************
463 static struct regsvr_interface
const interface_list
[] = {
464 { NULL
} /* list terminator */
467 /***********************************************************************
468 * DllRegisterServer (DINPUT.@)
470 HRESULT WINAPI
DllRegisterServer(void)
476 hr
= register_coclasses(coclass_list
);
478 hr
= register_interfaces(interface_list
);
482 /***********************************************************************
483 * DllUnregisterServer (DINPUT.@)
485 HRESULT WINAPI
DllUnregisterServer(void)
491 hr
= unregister_coclasses(coclass_list
);
493 hr
= unregister_interfaces(interface_list
);