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
21 #include "mscoree_private.h"
36 typedef struct ConfigFileHandler
38 ISAXContentHandler ISAXContentHandler_iface
;
39 ISAXErrorHandler ISAXErrorHandler_iface
;
41 enum parse_state states
[16];
43 parsed_config_file
*result
;
46 static inline ConfigFileHandler
*impl_from_ISAXContentHandler(ISAXContentHandler
*iface
)
48 return CONTAINING_RECORD(iface
, ConfigFileHandler
, ISAXContentHandler_iface
);
51 static inline ConfigFileHandler
*impl_from_ISAXErrorHandler(ISAXErrorHandler
*iface
)
53 return CONTAINING_RECORD(iface
, ConfigFileHandler
, ISAXErrorHandler_iface
);
56 static HRESULT WINAPI
ConfigFileHandler_QueryInterface(ISAXContentHandler
*iface
,
57 REFIID riid
, void **ppvObject
)
59 if (IsEqualGUID(riid
, &IID_ISAXContentHandler
) ||
60 IsEqualGUID(riid
, &IID_IUnknown
))
66 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
70 ISAXContentHandler_AddRef(iface
);
75 static ULONG WINAPI
ConfigFileHandler_AddRef(ISAXContentHandler
*iface
)
77 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
78 return InterlockedIncrement(&This
->ref
);
81 static ULONG WINAPI
ConfigFileHandler_Release(ISAXContentHandler
*iface
)
83 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
84 ULONG ref
= InterlockedDecrement(&This
->ref
);
87 HeapFree(GetProcessHeap(), 0, This
);
92 static HRESULT WINAPI
ConfigFileHandler_putDocumentLocator(ISAXContentHandler
*iface
,
93 ISAXLocator
*pLocator
)
98 static HRESULT WINAPI
ConfigFileHandler_startDocument(ISAXContentHandler
*iface
)
103 static HRESULT WINAPI
ConfigFileHandler_endDocument(ISAXContentHandler
*iface
)
108 static HRESULT WINAPI
ConfigFileHandler_startPrefixMapping(ISAXContentHandler
*iface
,
109 const WCHAR
*pPrefix
, int nPrefix
, const WCHAR
*pUri
, int nUri
)
114 static HRESULT WINAPI
ConfigFileHandler_endPrefixMapping(ISAXContentHandler
*iface
,
115 const WCHAR
*pPrefix
, int nPrefix
)
120 static HRESULT
parse_startup(ConfigFileHandler
*This
, ISAXAttributes
*pAttr
)
122 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};
123 static const WCHAR empty
[] = {0};
128 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, legacy
, lstrlenW(legacy
), &value
, &value_size
);
130 FIXME("useLegacyV2RuntimeActivationPolicy=%s not implemented\n", debugstr_wn(value
, value_size
));
136 static HRESULT
parse_supported_runtime(ConfigFileHandler
*This
, ISAXAttributes
*pAttr
)
138 static const WCHAR version
[] = {'v','e','r','s','i','o','n',0};
139 static const WCHAR sku
[] = {'s','k','u',0};
140 static const WCHAR empty
[] = {0};
144 supported_runtime
*entry
;
146 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, version
, lstrlenW(version
), &value
, &value_size
);
149 TRACE("%s\n", debugstr_wn(value
, value_size
));
150 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(supported_runtime
));
153 entry
->version
= HeapAlloc(GetProcessHeap(), 0, (value_size
+ 1) * sizeof(WCHAR
));
156 lstrcpyW(entry
->version
, value
);
157 list_add_tail(&This
->result
->supported_runtimes
, &entry
->entry
);
161 HeapFree(GetProcessHeap(), 0, entry
);
169 WARN("Missing version attribute\n");
173 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, sku
, lstrlenW(sku
), &value
, &value_size
);
175 FIXME("sku=%s not implemented\n", debugstr_wn(value
, value_size
));
182 static HRESULT WINAPI
ConfigFileHandler_startElement(ISAXContentHandler
*iface
,
183 const WCHAR
*pNamespaceUri
, int nNamespaceUri
, const WCHAR
*pLocalName
,
184 int nLocalName
, const WCHAR
*pQName
, int nQName
, ISAXAttributes
*pAttr
)
186 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
187 static const WCHAR configuration
[] = {'c','o','n','f','i','g','u','r','a','t','i','o','n',0};
188 static const WCHAR startup
[] = {'s','t','a','r','t','u','p',0};
189 static const WCHAR supportedRuntime
[] = {'s','u','p','p','o','r','t','e','d','R','u','n','t','i','m','e',0};
192 TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri
,nNamespaceUri
),
193 debugstr_wn(pLocalName
,nLocalName
), debugstr_wn(pQName
,nQName
));
195 if (This
->statenum
== sizeof(This
->states
) / sizeof(This
->states
[0]) - 1)
197 ERR("file has too much nesting\n");
201 switch (This
->states
[This
->statenum
])
204 if (nLocalName
== sizeof(configuration
)/sizeof(WCHAR
)-1 &&
205 lstrcmpW(pLocalName
, configuration
) == 0)
207 This
->states
[++This
->statenum
] = STATE_CONFIGURATION
;
212 case STATE_CONFIGURATION
:
213 if (nLocalName
== sizeof(startup
)/sizeof(WCHAR
)-1 &&
214 lstrcmpW(pLocalName
, startup
) == 0)
216 hr
= parse_startup(This
, pAttr
);
217 This
->states
[++This
->statenum
] = STATE_STARTUP
;
223 if (nLocalName
== sizeof(supportedRuntime
)/sizeof(WCHAR
)-1 &&
224 lstrcmpW(pLocalName
, supportedRuntime
) == 0)
226 hr
= parse_supported_runtime(This
, pAttr
);
227 This
->states
[++This
->statenum
] = STATE_UNKNOWN
;
239 FIXME("Unknown element %s in state %u\n", debugstr_wn(pLocalName
,nLocalName
),
240 This
->states
[This
->statenum
]);
242 This
->states
[++This
->statenum
] = STATE_UNKNOWN
;
247 static HRESULT WINAPI
ConfigFileHandler_endElement(ISAXContentHandler
*iface
,
248 const WCHAR
*pNamespaceUri
, int nNamespaceUri
, const WCHAR
*pLocalName
,
249 int nLocalName
, const WCHAR
*pQName
, int nQName
)
251 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
253 TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri
,nNamespaceUri
),
254 debugstr_wn(pLocalName
,nLocalName
), debugstr_wn(pQName
,nQName
));
256 if (This
->statenum
> 0)
262 ERR("element end does not match a start\n");
269 static HRESULT WINAPI
ConfigFileHandler_characters(ISAXContentHandler
*iface
,
270 const WCHAR
*pChars
, int nChars
)
272 TRACE("%s\n", debugstr_wn(pChars
,nChars
));
277 static HRESULT WINAPI
ConfigFileHandler_ignorableWhitespace(ISAXContentHandler
*iface
,
278 const WCHAR
*pChars
, int nChars
)
283 static HRESULT WINAPI
ConfigFileHandler_processingInstruction(ISAXContentHandler
*iface
,
284 const WCHAR
*pTarget
, int nTarget
, const WCHAR
*pData
, int nData
)
289 static HRESULT WINAPI
ConfigFileHandler_skippedEntity(ISAXContentHandler
*iface
,
290 const WCHAR
* pName
, int nName
)
292 TRACE("%s\n", debugstr_wn(pName
,nName
));
296 static const struct ISAXContentHandlerVtbl ConfigFileHandlerVtbl
=
298 ConfigFileHandler_QueryInterface
,
299 ConfigFileHandler_AddRef
,
300 ConfigFileHandler_Release
,
301 ConfigFileHandler_putDocumentLocator
,
302 ConfigFileHandler_startDocument
,
303 ConfigFileHandler_endDocument
,
304 ConfigFileHandler_startPrefixMapping
,
305 ConfigFileHandler_endPrefixMapping
,
306 ConfigFileHandler_startElement
,
307 ConfigFileHandler_endElement
,
308 ConfigFileHandler_characters
,
309 ConfigFileHandler_ignorableWhitespace
,
310 ConfigFileHandler_processingInstruction
,
311 ConfigFileHandler_skippedEntity
314 static HRESULT WINAPI
ConfigFileHandler_Error_QueryInterface(ISAXErrorHandler
*iface
,
315 REFIID riid
, void **ppvObject
)
317 if (IsEqualGUID(riid
, &IID_ISAXErrorHandler
) ||
318 IsEqualGUID(riid
, &IID_IUnknown
))
324 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
325 return E_NOINTERFACE
;
328 ISAXErrorHandler_AddRef(iface
);
333 static ULONG WINAPI
ConfigFileHandler_Error_AddRef(ISAXErrorHandler
*iface
)
335 ConfigFileHandler
*This
= impl_from_ISAXErrorHandler(iface
);
336 return IUnknown_AddRef((IUnknown
*)This
);
339 static ULONG WINAPI
ConfigFileHandler_Error_Release(ISAXErrorHandler
*iface
)
341 ConfigFileHandler
*This
= impl_from_ISAXErrorHandler(iface
);
342 return IUnknown_Release((IUnknown
*)This
);
345 static HRESULT WINAPI
ConfigFileHandler_error(ISAXErrorHandler
*iface
,
346 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
348 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
352 static HRESULT WINAPI
ConfigFileHandler_fatalError(ISAXErrorHandler
*iface
,
353 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
355 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
359 static HRESULT WINAPI
ConfigFileHandler_ignorableWarning(ISAXErrorHandler
*iface
,
360 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
362 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
366 static const struct ISAXErrorHandlerVtbl ConfigFileHandlerErrorVtbl
=
368 ConfigFileHandler_Error_QueryInterface
,
369 ConfigFileHandler_Error_AddRef
,
370 ConfigFileHandler_Error_Release
,
371 ConfigFileHandler_error
,
372 ConfigFileHandler_fatalError
,
373 ConfigFileHandler_ignorableWarning
376 static void init_config(parsed_config_file
*config
)
378 list_init(&config
->supported_runtimes
);
381 static HRESULT
parse_config(VARIANT input
, parsed_config_file
*result
)
383 ISAXXMLReader
*reader
;
384 ConfigFileHandler
*handler
;
387 handler
= HeapAlloc(GetProcessHeap(), 0, sizeof(ConfigFileHandler
));
389 return E_OUTOFMEMORY
;
391 handler
->ISAXContentHandler_iface
.lpVtbl
= &ConfigFileHandlerVtbl
;
392 handler
->ISAXErrorHandler_iface
.lpVtbl
= &ConfigFileHandlerErrorVtbl
;
394 handler
->states
[0] = STATE_ROOT
;
395 handler
->statenum
= 0;
396 handler
->result
= result
;
398 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
399 &IID_ISAXXMLReader
, (LPVOID
*)&reader
);
403 hr
= ISAXXMLReader_putContentHandler(reader
, &handler
->ISAXContentHandler_iface
);
406 hr
= ISAXXMLReader_putErrorHandler(reader
, &handler
->ISAXErrorHandler_iface
);
409 hr
= ISAXXMLReader_parse(reader
, input
);
411 ISAXXMLReader_Release(reader
);
414 ISAXContentHandler_Release(&handler
->ISAXContentHandler_iface
);
419 HRESULT
parse_config_file(LPCWSTR filename
, parsed_config_file
*result
)
428 initresult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
430 hr
= SHCreateStreamOnFileW(filename
, STGM_SHARE_DENY_WRITE
| STGM_READ
| STGM_FAILIFTHERE
, &stream
);
434 V_VT(&var
) = VT_UNKNOWN
;
435 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
437 hr
= parse_config(var
, result
);
439 IStream_Release(stream
);
442 if (SUCCEEDED(initresult
))
448 void free_parsed_config_file(parsed_config_file
*file
)
450 supported_runtime
*cursor
, *cursor2
;
452 LIST_FOR_EACH_ENTRY_SAFE(cursor
, cursor2
, &file
->supported_runtimes
, supported_runtime
, entry
)
454 HeapFree(GetProcessHeap(), 0, cursor
->version
);
455 list_remove(&cursor
->entry
);
456 HeapFree(GetProcessHeap(), 0, cursor
);