2 * self-registerable dll functions for d3dxof.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
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(d3dxof
);
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
);
123 /***********************************************************************
124 * register_interfaces
126 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
128 LONG res
= ERROR_SUCCESS
;
131 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
132 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
133 if (res
!= ERROR_SUCCESS
) goto error_return
;
135 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
139 StringFromGUID2(list
->iid
, buf
, 39);
140 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
141 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
142 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
145 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
146 (CONST BYTE
*)(list
->name
),
147 strlen(list
->name
) + 1);
148 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
151 if (list
->base_iid
) {
152 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
153 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
156 if (0 <= list
->num_methods
) {
157 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
160 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
161 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
162 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
164 sprintfW(buf
, fmt
, list
->num_methods
);
165 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
167 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
170 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
173 if (list
->ps_clsid
) {
174 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
175 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
178 if (list
->ps_clsid32
) {
179 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
180 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
184 RegCloseKey(iid_key
);
187 error_close_interface_key
:
188 RegCloseKey(interface_key
);
190 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
193 /***********************************************************************
194 * unregister_interfaces
196 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
198 LONG res
= ERROR_SUCCESS
;
201 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
202 KEY_READ
| KEY_WRITE
, &interface_key
);
203 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
204 if (res
!= ERROR_SUCCESS
) goto error_return
;
206 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
209 StringFromGUID2(list
->iid
, buf
, 39);
210 res
= RegDeleteTreeW(interface_key
, buf
);
211 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
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
= RegDeleteTreeW(coclass_key
, buf
);
319 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
320 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
323 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
324 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
325 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
328 if (list
->viprogid
) {
329 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
330 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
331 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
335 error_close_coclass_key
:
336 RegCloseKey(coclass_key
);
338 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
341 /***********************************************************************
344 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
348 StringFromGUID2(guid
, buf
, 39);
349 return register_key_defvalueW(base
, name
, buf
);
352 /***********************************************************************
353 * regsvr_key_defvalueW
355 static LONG
register_key_defvalueW(
363 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
364 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
365 if (res
!= ERROR_SUCCESS
) return res
;
366 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
367 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
372 /***********************************************************************
373 * regsvr_key_defvalueA
375 static LONG
register_key_defvalueA(
383 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
384 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
385 if (res
!= ERROR_SUCCESS
) return res
;
386 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
387 lstrlenA(value
) + 1);
392 /***********************************************************************
395 static LONG
register_progid(
398 char const *curver_progid
,
405 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
406 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
408 if (res
!= ERROR_SUCCESS
) return res
;
411 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
412 (CONST BYTE
*)name
, strlen(name
) + 1);
413 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
417 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
418 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
422 res
= register_key_defvalueA(progid_key
, curver_keyname
,
424 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
430 res
= RegCreateKeyExA(progid_key
, extra
, 0,
431 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
433 if (res
== ERROR_SUCCESS
)
434 RegCloseKey(extra_key
);
437 error_close_progid_key
:
438 RegCloseKey(progid_key
);
442 /***********************************************************************
445 static struct regsvr_coclass
const coclass_list
[] = {
446 { &CLSID_CDirectXFile
,
452 { NULL
} /* list terminator */
455 /***********************************************************************
459 static struct regsvr_interface
const interface_list
[] = {
460 { NULL
} /* list terminator */
463 /***********************************************************************
464 * DllRegisterServer (D3DXOF.@)
466 HRESULT WINAPI
DllRegisterServer(void)
472 hr
= register_coclasses(coclass_list
);
474 hr
= register_interfaces(interface_list
);
478 /***********************************************************************
479 * DllUnregisterServer (D3DXOF.@)
481 HRESULT WINAPI
DllUnregisterServer(void)
487 hr
= unregister_coclasses(coclass_list
);
489 hr
= unregister_interfaces(interface_list
);