2 * MSXML6 self-registerable dll functions
4 * Copyright (C) 2003 John K. Hohm
5 * Copyright (C) 2006 Robert Shearman
6 * Copyright (C) 2008 Alistair Leslie-Hughes
7 * Copyright (C) 2010 Nikolay Sivov for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(msxml6
);
47 * Near the bottom of this file are the exported DllRegisterServer and
48 * DllUnregisterServer, which make all this worthwhile.
53 CLSID
const *clsid
; /* NULL for end of list */
54 LPCSTR name
; /* can be NULL to omit */
55 LPCSTR ips
; /* can be NULL to omit */
56 LPCSTR ips32
; /* can be NULL to omit */
57 LPCSTR ips32_tmodel
; /* can be NULL to omit */
58 LPCSTR progid
; /* can be NULL to omit */
59 LPCSTR version
; /* can be NULL to omit */
62 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
63 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
67 LPCSTR name
; /* NULL for end of list */
68 LPCSTR description
; /* can be NULL to omit */
70 LPCSTR curver
; /* can be NULL to omit */
73 static HRESULT
register_progids(struct progid
const *list
);
74 static HRESULT
unregister_progids(struct progid
const *list
);
76 /***********************************************************************
77 * static string constants
79 static WCHAR
const interface_keyname
[10] = {
80 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
81 static WCHAR
const base_ifa_keyname
[14] = {
82 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
84 static WCHAR
const num_methods_keyname
[11] = {
85 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
86 static WCHAR
const ps_clsid_keyname
[15] = {
87 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
89 static WCHAR
const ps_clsid32_keyname
[17] = {
90 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
91 'i', 'd', '3', '2', 0 };
92 static WCHAR
const clsid_keyname
[6] = {
93 'C', 'L', 'S', 'I', 'D', 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 versionindependentprogid_keyname
[] = {
103 'V', 'e', 'r', 's', 'i', 'o', 'n',
104 'I', 'n', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 't',
105 'P', 'r', 'o', 'g', 'I', 'D', 0 };
106 static WCHAR
const version_keyname
[] = {
107 'V', 'e', 'r', 's', 'i', 'o', 'n', 0 };
108 static WCHAR
const curver_keyname
[] = {
109 'C', 'u', 'r', 'V', 'e', 'r', 0 };
110 static char const tmodel_valuename
[] = "ThreadingModel";
112 /***********************************************************************
113 * static helper functions
115 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
117 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
120 /***********************************************************************
123 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
125 LONG res
= ERROR_SUCCESS
;
128 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
129 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
130 if (res
!= ERROR_SUCCESS
) goto error_return
;
132 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
136 StringFromGUID2(list
->clsid
, buf
, 39);
137 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
138 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
139 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
142 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
143 (CONST BYTE
*)(list
->name
),
144 strlen(list
->name
) + 1);
145 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
149 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
150 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
156 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
157 KEY_READ
| KEY_WRITE
, NULL
,
159 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
161 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
162 (CONST BYTE
*)list
->ips32
,
163 lstrlenA(list
->ips32
) + 1);
164 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
165 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
166 (CONST BYTE
*)list
->ips32_tmodel
,
167 strlen(list
->ips32_tmodel
) + 1);
168 RegCloseKey(ips32_key
);
169 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
177 buffer
= HeapAlloc(GetProcessHeap(), 0, strlen(list
->progid
) + strlen(list
->version
) + 2);
179 res
= ERROR_OUTOFMEMORY
;
180 goto error_close_clsid_key
;
182 strcpy(buffer
, list
->progid
);
184 strcat(buffer
, list
->version
);
187 progid
= list
->progid
;
188 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
190 HeapFree(GetProcessHeap(), 0, buffer
);
191 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
194 res
= register_key_defvalueA(clsid_key
, versionindependentprogid_keyname
,
196 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
201 res
= register_key_defvalueA(clsid_key
, version_keyname
,
203 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
206 error_close_clsid_key
:
207 RegCloseKey(clsid_key
);
210 error_close_coclass_key
:
211 RegCloseKey(coclass_key
);
213 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
216 /***********************************************************************
217 * unregister_coclasses
219 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
221 LONG res
= ERROR_SUCCESS
;
224 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
225 KEY_READ
| KEY_WRITE
, &coclass_key
);
226 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
227 if (res
!= ERROR_SUCCESS
) goto error_return
;
229 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
232 StringFromGUID2(list
->clsid
, buf
, 39);
233 res
= RegDeleteTreeW(coclass_key
, buf
);
234 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
235 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
238 error_close_coclass_key
:
239 RegCloseKey(coclass_key
);
241 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
244 /***********************************************************************
247 static HRESULT
register_progids(struct progid
const *list
)
249 LONG res
= ERROR_SUCCESS
;
251 for (; res
== ERROR_SUCCESS
&& list
->name
; ++list
) {
255 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, list
->name
, 0,
256 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
258 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
260 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
261 (CONST BYTE
*)list
->description
,
262 strlen(list
->description
) + 1);
263 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
265 StringFromGUID2(list
->clsid
, buf
, 39);
267 res
= register_key_defvalueW(progid_key
, clsid_keyname
, buf
);
268 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
271 res
= register_key_defvalueA(progid_key
, curver_keyname
, list
->curver
);
272 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
275 error_close_clsid_key
:
276 RegCloseKey(progid_key
);
279 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
282 /***********************************************************************
285 static HRESULT
unregister_progids(struct progid
const *list
)
287 LONG res
= ERROR_SUCCESS
;
289 for (; res
== ERROR_SUCCESS
&& list
->name
; ++list
) {
290 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->name
);
291 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
294 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
297 /***********************************************************************
298 * regsvr_key_defvalueW
300 static LONG
register_key_defvalueW(
308 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
309 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
310 if (res
!= ERROR_SUCCESS
) return res
;
311 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
312 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
317 /***********************************************************************
318 * regsvr_key_defvalueA
320 static LONG
register_key_defvalueA(
328 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
329 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
330 if (res
!= ERROR_SUCCESS
) return res
;
331 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
332 lstrlenA(value
) + 1);
337 /***********************************************************************
340 static struct regsvr_coclass
const coclass_list
[] = {
341 { &CLSID_DOMDocument60
,
342 "XML DOM Document 6.0",
346 "Msxml2.DOMDocument",
349 { &CLSID_XMLSchemaCache60
,
350 "XML Schema Cache 6.0",
354 "Msxml2.XMLSchemaCache",
357 { &CLSID_MXXMLWriter60
,
358 "IMXWriter interface 6.0",
362 "Msxml2.MXXMLWriter",
365 { &CLSID_SAXAttributes60
,
370 "Msxml2.SAXAttributes",
373 { &CLSID_FreeThreadedDOMDocument60
,
374 "Free Threaded XML DOM Document 6.0",
378 "Microsoft.FreeThreadedDOMDocument6.0",
381 { NULL
} /* list terminator */
384 /***********************************************************************
387 static struct progid
const progid_list
[] = {
388 { "Msxml2.DOMDocument.6.0",
389 "XML DOM Document 6.0",
390 &CLSID_DOMDocument60
,
393 { "Msxml2.XMLSchemaCache.6.0",
394 "XML Schema Cache 6.0",
395 &CLSID_XMLSchemaCache60
,
398 { "Msxml2.MXXMLWriter.6.0",
400 &CLSID_MXXMLWriter60
,
403 { "Msxml2.SAXAttributes.6.0",
405 &CLSID_SAXAttributes60
,
408 { "MSXML.FreeThreadedDOMDocument60",
409 "Free threaded XML DOM Document 6.0",
410 &CLSID_FreeThreadedDOMDocument60
,
413 { NULL
} /* list terminator */
416 /***********************************************************************
417 * DllRegisterServer (MSXML4.@)
419 HRESULT WINAPI
DllRegisterServer(void)
425 hr
= register_coclasses(coclass_list
);
427 hr
= register_progids(progid_list
);
432 /***********************************************************************
433 * DllUnregisterServer (MSXML4.@)
435 HRESULT WINAPI
DllUnregisterServer(void)
441 hr
= unregister_coclasses(coclass_list
);
443 hr
= unregister_progids(progid_list
);