2 * MSXML4 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
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
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msxml4
);
46 * Near the bottom of this file are the exported DllRegisterServer and
47 * DllUnregisterServer, which make all this worthwhile.
52 CLSID
const *clsid
; /* NULL for end of list */
53 LPCSTR name
; /* can be NULL to omit */
54 LPCSTR ips
; /* can be NULL to omit */
55 LPCSTR ips32
; /* can be NULL to omit */
56 LPCSTR ips32_tmodel
; /* can be NULL to omit */
57 LPCSTR progid
; /* can be NULL to omit */
58 LPCSTR version
; /* can be NULL to omit */
61 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
62 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
66 LPCSTR name
; /* NULL for end of list */
67 LPCSTR description
; /* can be NULL to omit */
69 LPCSTR curver
; /* can be NULL to omit */
72 static HRESULT
register_progids(struct progid
const *list
);
73 static HRESULT
unregister_progids(struct progid
const *list
);
75 /***********************************************************************
76 * static string constants
78 static WCHAR
const interface_keyname
[10] = {
79 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
80 static WCHAR
const base_ifa_keyname
[14] = {
81 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
83 static WCHAR
const num_methods_keyname
[11] = {
84 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
85 static WCHAR
const ps_clsid_keyname
[15] = {
86 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
88 static WCHAR
const ps_clsid32_keyname
[17] = {
89 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
90 'i', 'd', '3', '2', 0 };
91 static WCHAR
const clsid_keyname
[6] = {
92 'C', 'L', 'S', 'I', 'D', 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 versionindependentprogid_keyname
[] = {
102 'V', 'e', 'r', 's', 'i', 'o', 'n',
103 'I', 'n', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 't',
104 'P', 'r', 'o', 'g', 'I', 'D', 0 };
105 static WCHAR
const version_keyname
[] = {
106 'V', 'e', 'r', 's', 'i', 'o', 'n', 0 };
107 static WCHAR
const curver_keyname
[] = {
108 'C', 'u', 'r', 'V', 'e', 'r', 0 };
109 static char const tmodel_valuename
[] = "ThreadingModel";
111 /***********************************************************************
112 * static helper functions
114 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
116 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
119 /***********************************************************************
122 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
124 LONG res
= ERROR_SUCCESS
;
127 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
128 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
129 if (res
!= ERROR_SUCCESS
) goto error_return
;
131 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
135 StringFromGUID2(list
->clsid
, buf
, 39);
136 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
137 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
138 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
141 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
142 (CONST BYTE
*)(list
->name
),
143 strlen(list
->name
) + 1);
144 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
148 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
149 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
155 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
156 KEY_READ
| KEY_WRITE
, NULL
,
158 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
160 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
161 (CONST BYTE
*)list
->ips32
,
162 lstrlenA(list
->ips32
) + 1);
163 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
164 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
165 (CONST BYTE
*)list
->ips32_tmodel
,
166 strlen(list
->ips32_tmodel
) + 1);
167 RegCloseKey(ips32_key
);
168 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
176 buffer
= HeapAlloc(GetProcessHeap(), 0, strlen(list
->progid
) + strlen(list
->version
) + 2);
178 res
= ERROR_OUTOFMEMORY
;
179 goto error_close_clsid_key
;
181 strcpy(buffer
, list
->progid
);
183 strcat(buffer
, list
->version
);
186 progid
= list
->progid
;
187 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
189 HeapFree(GetProcessHeap(), 0, buffer
);
190 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
193 res
= register_key_defvalueA(clsid_key
, versionindependentprogid_keyname
,
195 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
200 res
= register_key_defvalueA(clsid_key
, version_keyname
,
202 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
205 error_close_clsid_key
:
206 RegCloseKey(clsid_key
);
209 error_close_coclass_key
:
210 RegCloseKey(coclass_key
);
212 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
215 /***********************************************************************
216 * unregister_coclasses
218 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
220 LONG res
= ERROR_SUCCESS
;
223 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
224 KEY_READ
| KEY_WRITE
, &coclass_key
);
225 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
226 if (res
!= ERROR_SUCCESS
) goto error_return
;
228 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
231 StringFromGUID2(list
->clsid
, buf
, 39);
232 res
= RegDeleteTreeW(coclass_key
, buf
);
233 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
234 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
237 error_close_coclass_key
:
238 RegCloseKey(coclass_key
);
240 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
243 /***********************************************************************
246 static HRESULT
register_progids(struct progid
const *list
)
248 LONG res
= ERROR_SUCCESS
;
250 for (; res
== ERROR_SUCCESS
&& list
->name
; ++list
) {
254 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, list
->name
, 0,
255 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
257 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
259 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
260 (CONST BYTE
*)list
->description
,
261 strlen(list
->description
) + 1);
262 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
264 StringFromGUID2(list
->clsid
, buf
, 39);
266 res
= register_key_defvalueW(progid_key
, clsid_keyname
, buf
);
267 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
270 res
= register_key_defvalueA(progid_key
, curver_keyname
, list
->curver
);
271 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
274 error_close_clsid_key
:
275 RegCloseKey(progid_key
);
278 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
281 /***********************************************************************
284 static HRESULT
unregister_progids(struct progid
const *list
)
286 LONG res
= ERROR_SUCCESS
;
288 for (; res
== ERROR_SUCCESS
&& list
->name
; ++list
) {
289 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->name
);
290 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
293 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
296 /***********************************************************************
297 * regsvr_key_defvalueW
299 static LONG
register_key_defvalueW(
307 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
308 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
309 if (res
!= ERROR_SUCCESS
) return res
;
310 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
311 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
316 /***********************************************************************
317 * regsvr_key_defvalueA
319 static LONG
register_key_defvalueA(
327 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
328 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
329 if (res
!= ERROR_SUCCESS
) return res
;
330 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
331 lstrlenA(value
) + 1);
336 /***********************************************************************
339 static struct regsvr_coclass
const coclass_list
[] = {
340 { &CLSID_DOMDocument40
,
341 "XML DOM Document 4.0",
345 "Msxml2.DOMDocument",
348 { &CLSID_SAXXMLReader40
,
349 "SAX XML Reader 4.0",
353 "Msxml2.SAXXMLReader",
356 { NULL
} /* list terminator */
359 /***********************************************************************
362 static struct progid
const progid_list
[] = {
363 { "Msxml2.DOMDocument.4.0",
364 "XML DOM Document 4.0",
365 &CLSID_DOMDocument40
,
368 { "Msxml2.SAXXMLReader.4.0",
369 "SAX XML Reader 4.0",
370 &CLSID_SAXXMLReader40
,
373 { NULL
} /* list terminator */
376 /***********************************************************************
377 * DllRegisterServer (MSXML4.@)
379 HRESULT WINAPI
DllRegisterServer(void)
385 hr
= register_coclasses(coclass_list
);
387 hr
= register_progids(progid_list
);
392 /***********************************************************************
393 * DllUnregisterServer (MSXML4.@)
395 HRESULT WINAPI
DllUnregisterServer(void)
401 hr
= unregister_coclasses(coclass_list
);
403 hr
= unregister_progids(progid_list
);