2 * Configuration file parsing
4 * Copyright 2010 Vincent Povirk
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
34 #include "wine/list.h"
35 #include "mscoree_private.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL( mscoree
);
44 STATE_ASSEMBLY_BINDING
,
53 typedef struct ConfigFileHandler
55 ISAXContentHandler ISAXContentHandler_iface
;
56 ISAXErrorHandler ISAXErrorHandler_iface
;
58 enum parse_state states
[16];
60 parsed_config_file
*result
;
63 static inline ConfigFileHandler
*impl_from_ISAXContentHandler(ISAXContentHandler
*iface
)
65 return CONTAINING_RECORD(iface
, ConfigFileHandler
, ISAXContentHandler_iface
);
68 static inline ConfigFileHandler
*impl_from_ISAXErrorHandler(ISAXErrorHandler
*iface
)
70 return CONTAINING_RECORD(iface
, ConfigFileHandler
, ISAXErrorHandler_iface
);
73 static HRESULT WINAPI
ConfigFileHandler_QueryInterface(ISAXContentHandler
*iface
,
74 REFIID riid
, void **ppvObject
)
76 if (IsEqualGUID(riid
, &IID_ISAXContentHandler
) ||
77 IsEqualGUID(riid
, &IID_IUnknown
))
83 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
87 ISAXContentHandler_AddRef(iface
);
92 static ULONG WINAPI
ConfigFileHandler_AddRef(ISAXContentHandler
*iface
)
94 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
95 return InterlockedIncrement(&This
->ref
);
98 static ULONG WINAPI
ConfigFileHandler_Release(ISAXContentHandler
*iface
)
100 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
101 ULONG ref
= InterlockedDecrement(&This
->ref
);
104 HeapFree(GetProcessHeap(), 0, This
);
109 static HRESULT WINAPI
ConfigFileHandler_putDocumentLocator(ISAXContentHandler
*iface
,
110 ISAXLocator
*pLocator
)
115 static HRESULT WINAPI
ConfigFileHandler_startDocument(ISAXContentHandler
*iface
)
120 static HRESULT WINAPI
ConfigFileHandler_endDocument(ISAXContentHandler
*iface
)
125 static HRESULT WINAPI
ConfigFileHandler_startPrefixMapping(ISAXContentHandler
*iface
,
126 const WCHAR
*pPrefix
, int nPrefix
, const WCHAR
*pUri
, int nUri
)
131 static HRESULT WINAPI
ConfigFileHandler_endPrefixMapping(ISAXContentHandler
*iface
,
132 const WCHAR
*pPrefix
, int nPrefix
)
137 static HRESULT
parse_startup(ConfigFileHandler
*This
, ISAXAttributes
*pAttr
)
139 static const WCHAR legacy
[] = {'u','s','e','L','e','g','a','c','y','V','2','R','u','n','t','i','m','e','A','c','t','i','v','a','t','i','o','n','P','o','l','i','c','y',0};
140 static const WCHAR empty
[] = {0};
145 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, legacy
, lstrlenW(legacy
), &value
, &value_size
);
147 FIXME("useLegacyV2RuntimeActivationPolicy=%s not implemented\n", debugstr_wn(value
, value_size
));
153 static HRESULT
parse_probing(ConfigFileHandler
*This
, ISAXAttributes
*pAttr
)
155 static const WCHAR privatePath
[] = {'p','r','i','v','a','t','e','P','a','t','h',0};
156 static const WCHAR empty
[] = {0};
161 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, privatePath
, lstrlenW(privatePath
), &value
, &value_size
);
163 FIXME("privatePath=%s not implemented\n", debugstr_wn(value
, value_size
));
170 static HRESULT
parse_supported_runtime(ConfigFileHandler
*This
, ISAXAttributes
*pAttr
)
172 static const WCHAR version
[] = {'v','e','r','s','i','o','n',0};
173 static const WCHAR sku
[] = {'s','k','u',0};
174 static const WCHAR empty
[] = {0};
178 supported_runtime
*entry
;
180 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, version
, lstrlenW(version
), &value
, &value_size
);
183 TRACE("%s\n", debugstr_wn(value
, value_size
));
184 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(supported_runtime
));
187 entry
->version
= HeapAlloc(GetProcessHeap(), 0, (value_size
+ 1) * sizeof(WCHAR
));
190 lstrcpyW(entry
->version
, value
);
191 list_add_tail(&This
->result
->supported_runtimes
, &entry
->entry
);
195 HeapFree(GetProcessHeap(), 0, entry
);
203 WARN("Missing version attribute\n");
207 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, sku
, lstrlenW(sku
), &value
, &value_size
);
209 FIXME("sku=%s not implemented\n", debugstr_wn(value
, value_size
));
216 static HRESULT WINAPI
ConfigFileHandler_startElement(ISAXContentHandler
*iface
,
217 const WCHAR
*pNamespaceUri
, int nNamespaceUri
, const WCHAR
*pLocalName
,
218 int nLocalName
, const WCHAR
*pQName
, int nQName
, ISAXAttributes
*pAttr
)
220 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
221 static const WCHAR configuration
[] = {'c','o','n','f','i','g','u','r','a','t','i','o','n',0};
222 static const WCHAR assemblyBinding
[] = {'a','s','s','e','m','b','l','y','B','i','n','d','i','n','g',0};
223 static const WCHAR probing
[] = {'p','r','o','b','i','n','g',0};
224 static const WCHAR runtime
[] = {'r','u','n','t','i','m','e',0};
225 static const WCHAR startup
[] = {'s','t','a','r','t','u','p',0};
226 static const WCHAR supportedRuntime
[] = {'s','u','p','p','o','r','t','e','d','R','u','n','t','i','m','e',0};
230 TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri
,nNamespaceUri
),
231 debugstr_wn(pLocalName
,nLocalName
), debugstr_wn(pQName
,nQName
));
233 if (This
->statenum
== sizeof(This
->states
) / sizeof(This
->states
[0]) - 1)
235 ERR("file has too much nesting\n");
239 switch (This
->states
[This
->statenum
])
242 if (nLocalName
== sizeof(configuration
)/sizeof(WCHAR
)-1 &&
243 lstrcmpW(pLocalName
, configuration
) == 0)
245 This
->states
[++This
->statenum
] = STATE_CONFIGURATION
;
250 case STATE_CONFIGURATION
:
251 if (nLocalName
== sizeof(startup
)/sizeof(WCHAR
)-1 &&
252 lstrcmpW(pLocalName
, startup
) == 0)
254 hr
= parse_startup(This
, pAttr
);
255 This
->states
[++This
->statenum
] = STATE_STARTUP
;
258 else if (nLocalName
== sizeof(runtime
)/sizeof(WCHAR
)-1 &&
259 lstrcmpW(pLocalName
, runtime
) == 0)
261 This
->states
[++This
->statenum
] = STATE_RUNTIME
;
267 if (nLocalName
== sizeof(assemblyBinding
)/sizeof(WCHAR
)-1 &&
268 lstrcmpW(pLocalName
, assemblyBinding
) == 0)
270 This
->states
[++This
->statenum
] = STATE_ASSEMBLY_BINDING
;
275 case STATE_ASSEMBLY_BINDING
:
276 if (nLocalName
== sizeof(probing
)/sizeof(WCHAR
)-1 &&
277 lstrcmpW(pLocalName
, probing
) == 0)
279 hr
= parse_probing(This
, pAttr
);
280 This
->states
[++This
->statenum
] = STATE_PROBING
;
286 if (nLocalName
== sizeof(supportedRuntime
)/sizeof(WCHAR
)-1 &&
287 lstrcmpW(pLocalName
, supportedRuntime
) == 0)
289 hr
= parse_supported_runtime(This
, pAttr
);
290 This
->states
[++This
->statenum
] = STATE_UNKNOWN
;
302 FIXME("Unknown element %s in state %u\n", debugstr_wn(pLocalName
,nLocalName
),
303 This
->states
[This
->statenum
]);
305 This
->states
[++This
->statenum
] = STATE_UNKNOWN
;
310 static HRESULT WINAPI
ConfigFileHandler_endElement(ISAXContentHandler
*iface
,
311 const WCHAR
*pNamespaceUri
, int nNamespaceUri
, const WCHAR
*pLocalName
,
312 int nLocalName
, const WCHAR
*pQName
, int nQName
)
314 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
316 TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri
,nNamespaceUri
),
317 debugstr_wn(pLocalName
,nLocalName
), debugstr_wn(pQName
,nQName
));
319 if (This
->statenum
> 0)
325 ERR("element end does not match a start\n");
332 static HRESULT WINAPI
ConfigFileHandler_characters(ISAXContentHandler
*iface
,
333 const WCHAR
*pChars
, int nChars
)
335 TRACE("%s\n", debugstr_wn(pChars
,nChars
));
340 static HRESULT WINAPI
ConfigFileHandler_ignorableWhitespace(ISAXContentHandler
*iface
,
341 const WCHAR
*pChars
, int nChars
)
346 static HRESULT WINAPI
ConfigFileHandler_processingInstruction(ISAXContentHandler
*iface
,
347 const WCHAR
*pTarget
, int nTarget
, const WCHAR
*pData
, int nData
)
352 static HRESULT WINAPI
ConfigFileHandler_skippedEntity(ISAXContentHandler
*iface
,
353 const WCHAR
* pName
, int nName
)
355 TRACE("%s\n", debugstr_wn(pName
,nName
));
359 static const struct ISAXContentHandlerVtbl ConfigFileHandlerVtbl
=
361 ConfigFileHandler_QueryInterface
,
362 ConfigFileHandler_AddRef
,
363 ConfigFileHandler_Release
,
364 ConfigFileHandler_putDocumentLocator
,
365 ConfigFileHandler_startDocument
,
366 ConfigFileHandler_endDocument
,
367 ConfigFileHandler_startPrefixMapping
,
368 ConfigFileHandler_endPrefixMapping
,
369 ConfigFileHandler_startElement
,
370 ConfigFileHandler_endElement
,
371 ConfigFileHandler_characters
,
372 ConfigFileHandler_ignorableWhitespace
,
373 ConfigFileHandler_processingInstruction
,
374 ConfigFileHandler_skippedEntity
377 static HRESULT WINAPI
ConfigFileHandler_Error_QueryInterface(ISAXErrorHandler
*iface
,
378 REFIID riid
, void **ppvObject
)
380 if (IsEqualGUID(riid
, &IID_ISAXErrorHandler
) ||
381 IsEqualGUID(riid
, &IID_IUnknown
))
387 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
388 return E_NOINTERFACE
;
391 ISAXErrorHandler_AddRef(iface
);
396 static ULONG WINAPI
ConfigFileHandler_Error_AddRef(ISAXErrorHandler
*iface
)
398 ConfigFileHandler
*This
= impl_from_ISAXErrorHandler(iface
);
399 return IUnknown_AddRef((IUnknown
*)This
);
402 static ULONG WINAPI
ConfigFileHandler_Error_Release(ISAXErrorHandler
*iface
)
404 ConfigFileHandler
*This
= impl_from_ISAXErrorHandler(iface
);
405 return IUnknown_Release((IUnknown
*)This
);
408 static HRESULT WINAPI
ConfigFileHandler_error(ISAXErrorHandler
*iface
,
409 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
411 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
415 static HRESULT WINAPI
ConfigFileHandler_fatalError(ISAXErrorHandler
*iface
,
416 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
418 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
422 static HRESULT WINAPI
ConfigFileHandler_ignorableWarning(ISAXErrorHandler
*iface
,
423 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
425 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
429 static const struct ISAXErrorHandlerVtbl ConfigFileHandlerErrorVtbl
=
431 ConfigFileHandler_Error_QueryInterface
,
432 ConfigFileHandler_Error_AddRef
,
433 ConfigFileHandler_Error_Release
,
434 ConfigFileHandler_error
,
435 ConfigFileHandler_fatalError
,
436 ConfigFileHandler_ignorableWarning
439 static void init_config(parsed_config_file
*config
)
441 list_init(&config
->supported_runtimes
);
444 static HRESULT
parse_config(VARIANT input
, parsed_config_file
*result
)
446 ISAXXMLReader
*reader
;
447 ConfigFileHandler
*handler
;
450 handler
= HeapAlloc(GetProcessHeap(), 0, sizeof(ConfigFileHandler
));
452 return E_OUTOFMEMORY
;
454 handler
->ISAXContentHandler_iface
.lpVtbl
= &ConfigFileHandlerVtbl
;
455 handler
->ISAXErrorHandler_iface
.lpVtbl
= &ConfigFileHandlerErrorVtbl
;
457 handler
->states
[0] = STATE_ROOT
;
458 handler
->statenum
= 0;
459 handler
->result
= result
;
461 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
462 &IID_ISAXXMLReader
, (LPVOID
*)&reader
);
466 hr
= ISAXXMLReader_putContentHandler(reader
, &handler
->ISAXContentHandler_iface
);
469 hr
= ISAXXMLReader_putErrorHandler(reader
, &handler
->ISAXErrorHandler_iface
);
472 hr
= ISAXXMLReader_parse(reader
, input
);
474 ISAXXMLReader_Release(reader
);
477 ISAXContentHandler_Release(&handler
->ISAXContentHandler_iface
);
482 HRESULT
parse_config_file(LPCWSTR filename
, parsed_config_file
*result
)
491 initresult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
493 hr
= SHCreateStreamOnFileW(filename
, STGM_SHARE_DENY_WRITE
| STGM_READ
| STGM_FAILIFTHERE
, &stream
);
497 V_VT(&var
) = VT_UNKNOWN
;
498 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
500 hr
= parse_config(var
, result
);
502 IStream_Release(stream
);
505 if (SUCCEEDED(initresult
))
511 void free_parsed_config_file(parsed_config_file
*file
)
513 supported_runtime
*cursor
, *cursor2
;
515 LIST_FOR_EACH_ENTRY_SAFE(cursor
, cursor2
, &file
->supported_runtimes
, supported_runtime
, entry
)
517 HeapFree(GetProcessHeap(), 0, cursor
->version
);
518 list_remove(&cursor
->entry
);
519 HeapFree(GetProcessHeap(), 0, cursor
);