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
31 #include "wine/list.h"
32 #include "mscoree_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL( mscoree
);
47 typedef struct ConfigFileHandler
49 ISAXContentHandler ISAXContentHandler_iface
;
50 ISAXErrorHandler ISAXErrorHandler_iface
;
52 enum parse_state states
[16];
54 parsed_config_file
*result
;
57 static inline ConfigFileHandler
*impl_from_ISAXContentHandler(ISAXContentHandler
*iface
)
59 return CONTAINING_RECORD(iface
, ConfigFileHandler
, ISAXContentHandler_iface
);
62 static inline ConfigFileHandler
*impl_from_ISAXErrorHandler(ISAXErrorHandler
*iface
)
64 return CONTAINING_RECORD(iface
, ConfigFileHandler
, ISAXErrorHandler_iface
);
67 static HRESULT WINAPI
ConfigFileHandler_QueryInterface(ISAXContentHandler
*iface
,
68 REFIID riid
, void **ppvObject
)
70 if (IsEqualGUID(riid
, &IID_ISAXContentHandler
) ||
71 IsEqualGUID(riid
, &IID_IUnknown
))
77 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
81 ISAXContentHandler_AddRef(iface
);
86 static ULONG WINAPI
ConfigFileHandler_AddRef(ISAXContentHandler
*iface
)
88 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
89 return InterlockedIncrement(&This
->ref
);
92 static ULONG WINAPI
ConfigFileHandler_Release(ISAXContentHandler
*iface
)
94 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
95 ULONG ref
= InterlockedDecrement(&This
->ref
);
98 HeapFree(GetProcessHeap(), 0, This
);
103 static HRESULT WINAPI
ConfigFileHandler_putDocumentLocator(ISAXContentHandler
*iface
,
104 ISAXLocator
*pLocator
)
109 static HRESULT WINAPI
ConfigFileHandler_startDocument(ISAXContentHandler
*iface
)
114 static HRESULT WINAPI
ConfigFileHandler_endDocument(ISAXContentHandler
*iface
)
119 static HRESULT WINAPI
ConfigFileHandler_startPrefixMapping(ISAXContentHandler
*iface
,
120 const WCHAR
*pPrefix
, int nPrefix
, const WCHAR
*pUri
, int nUri
)
125 static HRESULT WINAPI
ConfigFileHandler_endPrefixMapping(ISAXContentHandler
*iface
,
126 const WCHAR
*pPrefix
, int nPrefix
)
131 static HRESULT
parse_startup(ConfigFileHandler
*This
, ISAXAttributes
*pAttr
)
133 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};
134 static const WCHAR empty
[] = {0};
139 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, legacy
, lstrlenW(legacy
), &value
, &value_size
);
141 FIXME("useLegacyV2RuntimeActivationPolicy=%s not implemented\n", debugstr_wn(value
, value_size
));
147 static HRESULT
parse_supported_runtime(ConfigFileHandler
*This
, ISAXAttributes
*pAttr
)
149 static const WCHAR version
[] = {'v','e','r','s','i','o','n',0};
150 static const WCHAR sku
[] = {'s','k','u',0};
151 static const WCHAR empty
[] = {0};
155 supported_runtime
*entry
;
157 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, version
, lstrlenW(version
), &value
, &value_size
);
160 TRACE("%s\n", debugstr_wn(value
, value_size
));
161 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(supported_runtime
));
164 entry
->version
= HeapAlloc(GetProcessHeap(), 0, (value_size
+ 1) * sizeof(WCHAR
));
167 lstrcpyW(entry
->version
, value
);
168 list_add_tail(&This
->result
->supported_runtimes
, &entry
->entry
);
172 HeapFree(GetProcessHeap(), 0, entry
);
180 WARN("Missing version attribute\n");
184 hr
= ISAXAttributes_getValueFromName(pAttr
, empty
, 0, sku
, lstrlenW(sku
), &value
, &value_size
);
186 FIXME("sku=%s not implemented\n", debugstr_wn(value
, value_size
));
193 static HRESULT WINAPI
ConfigFileHandler_startElement(ISAXContentHandler
*iface
,
194 const WCHAR
*pNamespaceUri
, int nNamespaceUri
, const WCHAR
*pLocalName
,
195 int nLocalName
, const WCHAR
*pQName
, int nQName
, ISAXAttributes
*pAttr
)
197 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
198 static const WCHAR configuration
[] = {'c','o','n','f','i','g','u','r','a','t','i','o','n',0};
199 static const WCHAR startup
[] = {'s','t','a','r','t','u','p',0};
200 static const WCHAR supportedRuntime
[] = {'s','u','p','p','o','r','t','e','d','R','u','n','t','i','m','e',0};
203 TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri
,nNamespaceUri
),
204 debugstr_wn(pLocalName
,nLocalName
), debugstr_wn(pQName
,nQName
));
206 if (This
->statenum
== sizeof(This
->states
) / sizeof(This
->states
[0]) - 1)
208 ERR("file has too much nesting\n");
212 switch (This
->states
[This
->statenum
])
215 if (nLocalName
== sizeof(configuration
)/sizeof(WCHAR
)-1 &&
216 lstrcmpW(pLocalName
, configuration
) == 0)
218 This
->states
[++This
->statenum
] = STATE_CONFIGURATION
;
223 case STATE_CONFIGURATION
:
224 if (nLocalName
== sizeof(startup
)/sizeof(WCHAR
)-1 &&
225 lstrcmpW(pLocalName
, startup
) == 0)
227 hr
= parse_startup(This
, pAttr
);
228 This
->states
[++This
->statenum
] = STATE_STARTUP
;
234 if (nLocalName
== sizeof(supportedRuntime
)/sizeof(WCHAR
)-1 &&
235 lstrcmpW(pLocalName
, supportedRuntime
) == 0)
237 hr
= parse_supported_runtime(This
, pAttr
);
238 This
->states
[++This
->statenum
] = STATE_UNKNOWN
;
250 FIXME("Unknown element %s in state %u\n", debugstr_wn(pLocalName
,nLocalName
),
251 This
->states
[This
->statenum
]);
253 This
->states
[++This
->statenum
] = STATE_UNKNOWN
;
258 static HRESULT WINAPI
ConfigFileHandler_endElement(ISAXContentHandler
*iface
,
259 const WCHAR
*pNamespaceUri
, int nNamespaceUri
, const WCHAR
*pLocalName
,
260 int nLocalName
, const WCHAR
*pQName
, int nQName
)
262 ConfigFileHandler
*This
= impl_from_ISAXContentHandler(iface
);
264 TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri
,nNamespaceUri
),
265 debugstr_wn(pLocalName
,nLocalName
), debugstr_wn(pQName
,nQName
));
267 if (This
->statenum
> 0)
273 ERR("element end does not match a start\n");
280 static HRESULT WINAPI
ConfigFileHandler_characters(ISAXContentHandler
*iface
,
281 const WCHAR
*pChars
, int nChars
)
283 TRACE("%s\n", debugstr_wn(pChars
,nChars
));
288 static HRESULT WINAPI
ConfigFileHandler_ignorableWhitespace(ISAXContentHandler
*iface
,
289 const WCHAR
*pChars
, int nChars
)
294 static HRESULT WINAPI
ConfigFileHandler_processingInstruction(ISAXContentHandler
*iface
,
295 const WCHAR
*pTarget
, int nTarget
, const WCHAR
*pData
, int nData
)
300 static HRESULT WINAPI
ConfigFileHandler_skippedEntity(ISAXContentHandler
*iface
,
301 const WCHAR
* pName
, int nName
)
303 TRACE("%s\n", debugstr_wn(pName
,nName
));
307 static const struct ISAXContentHandlerVtbl ConfigFileHandlerVtbl
=
309 ConfigFileHandler_QueryInterface
,
310 ConfigFileHandler_AddRef
,
311 ConfigFileHandler_Release
,
312 ConfigFileHandler_putDocumentLocator
,
313 ConfigFileHandler_startDocument
,
314 ConfigFileHandler_endDocument
,
315 ConfigFileHandler_startPrefixMapping
,
316 ConfigFileHandler_endPrefixMapping
,
317 ConfigFileHandler_startElement
,
318 ConfigFileHandler_endElement
,
319 ConfigFileHandler_characters
,
320 ConfigFileHandler_ignorableWhitespace
,
321 ConfigFileHandler_processingInstruction
,
322 ConfigFileHandler_skippedEntity
325 static HRESULT WINAPI
ConfigFileHandler_Error_QueryInterface(ISAXErrorHandler
*iface
,
326 REFIID riid
, void **ppvObject
)
328 if (IsEqualGUID(riid
, &IID_ISAXErrorHandler
) ||
329 IsEqualGUID(riid
, &IID_IUnknown
))
335 WARN("Unsupported interface %s\n", debugstr_guid(riid
));
336 return E_NOINTERFACE
;
339 ISAXErrorHandler_AddRef(iface
);
344 static ULONG WINAPI
ConfigFileHandler_Error_AddRef(ISAXErrorHandler
*iface
)
346 ConfigFileHandler
*This
= impl_from_ISAXErrorHandler(iface
);
347 return IUnknown_AddRef((IUnknown
*)This
);
350 static ULONG WINAPI
ConfigFileHandler_Error_Release(ISAXErrorHandler
*iface
)
352 ConfigFileHandler
*This
= impl_from_ISAXErrorHandler(iface
);
353 return IUnknown_Release((IUnknown
*)This
);
356 static HRESULT WINAPI
ConfigFileHandler_error(ISAXErrorHandler
*iface
,
357 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
359 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
363 static HRESULT WINAPI
ConfigFileHandler_fatalError(ISAXErrorHandler
*iface
,
364 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
366 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
370 static HRESULT WINAPI
ConfigFileHandler_ignorableWarning(ISAXErrorHandler
*iface
,
371 ISAXLocator
* pLocator
, const WCHAR
* pErrorMessage
, HRESULT hrErrorCode
)
373 WARN("%s,%x\n", debugstr_w(pErrorMessage
), hrErrorCode
);
377 static const struct ISAXErrorHandlerVtbl ConfigFileHandlerErrorVtbl
=
379 ConfigFileHandler_Error_QueryInterface
,
380 ConfigFileHandler_Error_AddRef
,
381 ConfigFileHandler_Error_Release
,
382 ConfigFileHandler_error
,
383 ConfigFileHandler_fatalError
,
384 ConfigFileHandler_ignorableWarning
387 static void init_config(parsed_config_file
*config
)
389 list_init(&config
->supported_runtimes
);
392 static HRESULT
parse_config(VARIANT input
, parsed_config_file
*result
)
394 ISAXXMLReader
*reader
;
395 ConfigFileHandler
*handler
;
398 handler
= HeapAlloc(GetProcessHeap(), 0, sizeof(ConfigFileHandler
));
400 return E_OUTOFMEMORY
;
402 handler
->ISAXContentHandler_iface
.lpVtbl
= &ConfigFileHandlerVtbl
;
403 handler
->ISAXErrorHandler_iface
.lpVtbl
= &ConfigFileHandlerErrorVtbl
;
405 handler
->states
[0] = STATE_ROOT
;
406 handler
->statenum
= 0;
407 handler
->result
= result
;
409 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
410 &IID_ISAXXMLReader
, (LPVOID
*)&reader
);
414 hr
= ISAXXMLReader_putContentHandler(reader
, &handler
->ISAXContentHandler_iface
);
417 hr
= ISAXXMLReader_putErrorHandler(reader
, &handler
->ISAXErrorHandler_iface
);
420 hr
= ISAXXMLReader_parse(reader
, input
);
422 ISAXXMLReader_Release(reader
);
425 IUnknown_Release((IUnknown
*)handler
);
430 extern HRESULT
parse_config_file(LPCWSTR filename
, parsed_config_file
*result
)
439 initresult
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
441 hr
= SHCreateStreamOnFileW(filename
, STGM_SHARE_DENY_WRITE
| STGM_READ
| STGM_FAILIFTHERE
, &stream
);
445 V_VT(&var
) = VT_UNKNOWN
|VT_DISPATCH
;
446 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
448 hr
= parse_config(var
, result
);
450 IStream_Release(stream
);
453 if (SUCCEEDED(initresult
))
459 void free_parsed_config_file(parsed_config_file
*file
)
461 supported_runtime
*cursor
, *cursor2
;
463 LIST_FOR_EACH_ENTRY_SAFE(cursor
, cursor2
, &file
->supported_runtimes
, supported_runtime
, entry
)
465 HeapFree(GetProcessHeap(), 0, cursor
->version
);
466 list_remove(&cursor
->entry
);
467 HeapFree(GetProcessHeap(), 0, cursor
);