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
);
50 typedef struct ConfigFileHandler
52 ISAXContentHandler ISAXContentHandler_iface
;
53 ISAXErrorHandler ISAXErrorHandler_iface
;
55 enum parse_state states
[16];
57 parsed_config_file
*result
;
60 static inline ConfigFileHandler
*impl_from_ISAXContentHandler(ISAXContentHandler
*iface
)
62 return CONTAINING_RECORD(iface
, ConfigFileHandler
, ISAXContentHandler_iface
);
65 static inline ConfigFileHandler
*impl_from_ISAXErrorHandler(ISAXErrorHandler
*iface
)
67 return CONTAINING_RECORD(iface
, ConfigFileHandler
, ISAXErrorHandler_iface
);
70 static HRESULT WINAPI
ConfigFileHandler_QueryInterface(ISAXContentHandler
*iface
,
71 REFIID riid
, void **ppvObject
)
73 if (IsEqualGUID(riid
, &IID_ISAXContentHandler
) ||
74 IsEqualGUID(riid
, &IID_IUnknown
))
80 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
84 ISAXContentHandler_AddRef(iface
);
89 static ULONG WINAPI
ConfigFileHandler_AddRef(ISAXContentHandler
*iface
)
91 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
92 return InterlockedIncrement(&This
->ref
);
95 static ULONG WINAPI
ConfigFileHandler_Release(ISAXContentHandler
*iface
)
97 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
98 ULONG ref
= InterlockedDecrement(&This
->ref
);
101 HeapFree(GetProcessHeap(), 0, This
);
106 static HRESULT WINAPI
ConfigFileHandler_putDocumentLocator(ISAXContentHandler
*iface
,
107 ISAXLocator
*pLocator
)
112 static HRESULT WINAPI
ConfigFileHandler_startDocument(ISAXContentHandler
*iface
)
117 static HRESULT WINAPI
ConfigFileHandler_endDocument(ISAXContentHandler
*iface
)
122 static HRESULT WINAPI
ConfigFileHandler_startPrefixMapping(ISAXContentHandler
*iface
,
123 const WCHAR
*pPrefix
, int nPrefix
, const WCHAR
*pUri
, int nUri
)
128 static HRESULT WINAPI
ConfigFileHandler_endPrefixMapping(ISAXContentHandler
*iface
,
129 const WCHAR
*pPrefix
, int nPrefix
)
134 static HRESULT
parse_startup(ConfigFileHandler
*This
, ISAXAttributes
*pAttr
)
136 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};
137 static const WCHAR empty
[] = {0};
142 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, legacy
, lstrlenW(legacy
), &value
, &value_size
);
144 FIXME("useLegacyV2RuntimeActivationPolicy=%s not implemented\n", debugstr_wn(value
, value_size
));
150 static HRESULT
parse_supported_runtime(ConfigFileHandler
*This
, ISAXAttributes
*pAttr
)
152 static const WCHAR version
[] = {'v','e','r','s','i','o','n',0};
153 static const WCHAR sku
[] = {'s','k','u',0};
154 static const WCHAR empty
[] = {0};
158 supported_runtime
*entry
;
160 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, version
, lstrlenW(version
), &value
, &value_size
);
163 TRACE("%s\n", debugstr_wn(value
, value_size
));
164 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(supported_runtime
));
167 entry
->version
= HeapAlloc(GetProcessHeap(), 0, (value_size
+ 1) * sizeof(WCHAR
));
170 lstrcpyW(entry
->version
, value
);
171 list_add_tail(&This
->result
->supported_runtimes
, &entry
->entry
);
175 HeapFree(GetProcessHeap(), 0, entry
);
183 WARN("Missing version attribute\n");
187 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, sku
, lstrlenW(sku
), &value
, &value_size
);
189 FIXME("sku=%s not implemented\n", debugstr_wn(value
, value_size
));
196 static HRESULT WINAPI
ConfigFileHandler_startElement(ISAXContentHandler
*iface
,
197 const WCHAR
*pNamespaceUri
, int nNamespaceUri
, const WCHAR
*pLocalName
,
198 int nLocalName
, const WCHAR
*pQName
, int nQName
, ISAXAttributes
*pAttr
)
200 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
201 static const WCHAR configuration
[] = {'c','o','n','f','i','g','u','r','a','t','i','o','n',0};
202 static const WCHAR startup
[] = {'s','t','a','r','t','u','p',0};
203 static const WCHAR supportedRuntime
[] = {'s','u','p','p','o','r','t','e','d','R','u','n','t','i','m','e',0};
206 TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri
,nNamespaceUri
),
207 debugstr_wn(pLocalName
,nLocalName
), debugstr_wn(pQName
,nQName
));
209 if (This
->statenum
== sizeof(This
->states
) / sizeof(This
->states
[0]) - 1)
211 ERR("file has too much nesting\n");
215 switch (This
->states
[This
->statenum
])
218 if (nLocalName
== sizeof(configuration
)/sizeof(WCHAR
)-1 &&
219 lstrcmpW(pLocalName
, configuration
) == 0)
221 This
->states
[++This
->statenum
] = STATE_CONFIGURATION
;
226 case STATE_CONFIGURATION
:
227 if (nLocalName
== sizeof(startup
)/sizeof(WCHAR
)-1 &&
228 lstrcmpW(pLocalName
, startup
) == 0)
230 hr
= parse_startup(This
, pAttr
);
231 This
->states
[++This
->statenum
] = STATE_STARTUP
;
237 if (nLocalName
== sizeof(supportedRuntime
)/sizeof(WCHAR
)-1 &&
238 lstrcmpW(pLocalName
, supportedRuntime
) == 0)
240 hr
= parse_supported_runtime(This
, pAttr
);
241 This
->states
[++This
->statenum
] = STATE_UNKNOWN
;
253 FIXME("Unknown element %s in state %u\n", debugstr_wn(pLocalName
,nLocalName
),
254 This
->states
[This
->statenum
]);
256 This
->states
[++This
->statenum
] = STATE_UNKNOWN
;
261 static HRESULT WINAPI
ConfigFileHandler_endElement(ISAXContentHandler
*iface
,
262 const WCHAR
*pNamespaceUri
, int nNamespaceUri
, const WCHAR
*pLocalName
,
263 int nLocalName
, const WCHAR
*pQName
, int nQName
)
265 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
267 TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri
,nNamespaceUri
),
268 debugstr_wn(pLocalName
,nLocalName
), debugstr_wn(pQName
,nQName
));
270 if (This
->statenum
> 0)
276 ERR("element end does not match a start\n");
283 static HRESULT WINAPI
ConfigFileHandler_characters(ISAXContentHandler
*iface
,
284 const WCHAR
*pChars
, int nChars
)
286 TRACE("%s\n", debugstr_wn(pChars
,nChars
));
291 static HRESULT WINAPI
ConfigFileHandler_ignorableWhitespace(ISAXContentHandler
*iface
,
292 const WCHAR
*pChars
, int nChars
)
297 static HRESULT WINAPI
ConfigFileHandler_processingInstruction(ISAXContentHandler
*iface
,
298 const WCHAR
*pTarget
, int nTarget
, const WCHAR
*pData
, int nData
)
303 static HRESULT WINAPI
ConfigFileHandler_skippedEntity(ISAXContentHandler
*iface
,
304 const WCHAR
* pName
, int nName
)
306 TRACE("%s\n", debugstr_wn(pName
,nName
));
310 static const struct ISAXContentHandlerVtbl ConfigFileHandlerVtbl
=
312 ConfigFileHandler_QueryInterface
,
313 ConfigFileHandler_AddRef
,
314 ConfigFileHandler_Release
,
315 ConfigFileHandler_putDocumentLocator
,
316 ConfigFileHandler_startDocument
,
317 ConfigFileHandler_endDocument
,
318 ConfigFileHandler_startPrefixMapping
,
319 ConfigFileHandler_endPrefixMapping
,
320 ConfigFileHandler_startElement
,
321 ConfigFileHandler_endElement
,
322 ConfigFileHandler_characters
,
323 ConfigFileHandler_ignorableWhitespace
,
324 ConfigFileHandler_processingInstruction
,
325 ConfigFileHandler_skippedEntity
328 static HRESULT WINAPI
ConfigFileHandler_Error_QueryInterface(ISAXErrorHandler
*iface
,
329 REFIID riid
, void **ppvObject
)
331 if (IsEqualGUID(riid
, &IID_ISAXErrorHandler
) ||
332 IsEqualGUID(riid
, &IID_IUnknown
))
338 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
339 return E_NOINTERFACE
;
342 ISAXErrorHandler_AddRef(iface
);
347 static ULONG WINAPI
ConfigFileHandler_Error_AddRef(ISAXErrorHandler
*iface
)
349 ConfigFileHandler
*This
= impl_from_ISAXErrorHandler(iface
);
350 return IUnknown_AddRef((IUnknown
*)This
);
353 static ULONG WINAPI
ConfigFileHandler_Error_Release(ISAXErrorHandler
*iface
)
355 ConfigFileHandler
*This
= impl_from_ISAXErrorHandler(iface
);
356 return IUnknown_Release((IUnknown
*)This
);
359 static HRESULT WINAPI
ConfigFileHandler_error(ISAXErrorHandler
*iface
,
360 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
362 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
366 static HRESULT WINAPI
ConfigFileHandler_fatalError(ISAXErrorHandler
*iface
,
367 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
369 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
373 static HRESULT WINAPI
ConfigFileHandler_ignorableWarning(ISAXErrorHandler
*iface
,
374 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
376 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
380 static const struct ISAXErrorHandlerVtbl ConfigFileHandlerErrorVtbl
=
382 ConfigFileHandler_Error_QueryInterface
,
383 ConfigFileHandler_Error_AddRef
,
384 ConfigFileHandler_Error_Release
,
385 ConfigFileHandler_error
,
386 ConfigFileHandler_fatalError
,
387 ConfigFileHandler_ignorableWarning
390 static void init_config(parsed_config_file
*config
)
392 list_init(&config
->supported_runtimes
);
395 static HRESULT
parse_config(VARIANT input
, parsed_config_file
*result
)
397 ISAXXMLReader
*reader
;
398 ConfigFileHandler
*handler
;
401 handler
= HeapAlloc(GetProcessHeap(), 0, sizeof(ConfigFileHandler
));
403 return E_OUTOFMEMORY
;
405 handler
->ISAXContentHandler_iface
.lpVtbl
= &ConfigFileHandlerVtbl
;
406 handler
->ISAXErrorHandler_iface
.lpVtbl
= &ConfigFileHandlerErrorVtbl
;
408 handler
->states
[0] = STATE_ROOT
;
409 handler
->statenum
= 0;
410 handler
->result
= result
;
412 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
413 &IID_ISAXXMLReader
, (LPVOID
*)&reader
);
417 hr
= ISAXXMLReader_putContentHandler(reader
, &handler
->ISAXContentHandler_iface
);
420 hr
= ISAXXMLReader_putErrorHandler(reader
, &handler
->ISAXErrorHandler_iface
);
423 hr
= ISAXXMLReader_parse(reader
, input
);
425 ISAXXMLReader_Release(reader
);
428 IUnknown_Release((IUnknown
*)handler
);
433 HRESULT
parse_config_file(LPCWSTR filename
, parsed_config_file
*result
)
442 initresult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
444 hr
= SHCreateStreamOnFileW(filename
, STGM_SHARE_DENY_WRITE
| STGM_READ
| STGM_FAILIFTHERE
, &stream
);
448 V_VT(&var
) = VT_UNKNOWN
|VT_DISPATCH
;
449 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
451 hr
= parse_config(var
, result
);
453 IStream_Release(stream
);
456 if (SUCCEEDED(initresult
))
462 void free_parsed_config_file(parsed_config_file
*file
)
464 supported_runtime
*cursor
, *cursor2
;
466 LIST_FOR_EACH_ENTRY_SAFE(cursor
, cursor2
, &file
->supported_runtimes
, supported_runtime
, entry
)
468 HeapFree(GetProcessHeap(), 0, cursor
->version
);
469 list_remove(&cursor
->entry
);
470 HeapFree(GetProcessHeap(), 0, cursor
);