usp10: Handle dangling joiners when processing Indic GlyphProps.
[wine.git] / dlls / mscoree / config.c
blob02c11b1adf5ffa1be5ab3cfb5f1b17c91f91f3a3
1 /*
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 #define COBJMACROS
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "ole2.h"
29 #include "msxml2.h"
30 #include "mscoree.h"
31 #include "corhdr.h"
32 #include "metahost.h"
33 #include "cordebug.h"
34 #include "wine/list.h"
35 #include "mscoree_private.h"
36 #include "shlwapi.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
42 enum parse_state
44 STATE_ROOT,
45 STATE_CONFIGURATION,
46 STATE_STARTUP,
47 STATE_UNKNOWN
50 typedef struct ConfigFileHandler
52 ISAXContentHandler ISAXContentHandler_iface;
53 ISAXErrorHandler ISAXErrorHandler_iface;
54 LONG ref;
55 enum parse_state states[16];
56 int statenum;
57 parsed_config_file *result;
58 } ConfigFileHandler;
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))
76 *ppvObject = iface;
78 else
80 WARN("Unsupported interface %s\n", debugstr_guid(riid));
81 return E_NOINTERFACE;
84 ISAXContentHandler_AddRef(iface);
86 return S_OK;
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);
100 if (ref == 0)
101 HeapFree(GetProcessHeap(), 0, This);
103 return ref;
106 static HRESULT WINAPI ConfigFileHandler_putDocumentLocator(ISAXContentHandler *iface,
107 ISAXLocator *pLocator)
109 return S_OK;
112 static HRESULT WINAPI ConfigFileHandler_startDocument(ISAXContentHandler *iface)
114 return S_OK;
117 static HRESULT WINAPI ConfigFileHandler_endDocument(ISAXContentHandler *iface)
119 return S_OK;
122 static HRESULT WINAPI ConfigFileHandler_startPrefixMapping(ISAXContentHandler *iface,
123 const WCHAR *pPrefix, int nPrefix, const WCHAR *pUri, int nUri)
125 return S_OK;
128 static HRESULT WINAPI ConfigFileHandler_endPrefixMapping(ISAXContentHandler *iface,
129 const WCHAR *pPrefix, int nPrefix)
131 return S_OK;
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};
138 LPCWSTR value;
139 int value_size;
140 HRESULT hr;
142 hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, legacy, lstrlenW(legacy), &value, &value_size);
143 if (SUCCEEDED(hr))
144 FIXME("useLegacyV2RuntimeActivationPolicy=%s not implemented\n", debugstr_wn(value, value_size));
145 hr = S_OK;
147 return hr;
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};
155 LPCWSTR value;
156 int value_size;
157 HRESULT hr;
158 supported_runtime *entry;
160 hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, version, lstrlenW(version), &value, &value_size);
161 if (SUCCEEDED(hr))
163 TRACE("%s\n", debugstr_wn(value, value_size));
164 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(supported_runtime));
165 if (entry)
167 entry->version = HeapAlloc(GetProcessHeap(), 0, (value_size + 1) * sizeof(WCHAR));
168 if (entry->version)
170 lstrcpyW(entry->version, value);
171 list_add_tail(&This->result->supported_runtimes, &entry->entry);
173 else
175 HeapFree(GetProcessHeap(), 0, entry);
176 hr = E_OUTOFMEMORY;
179 else
180 hr = E_OUTOFMEMORY;
182 else
183 WARN("Missing version attribute\n");
185 if (SUCCEEDED(hr))
187 hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, sku, lstrlenW(sku), &value, &value_size);
188 if (SUCCEEDED(hr))
189 FIXME("sku=%s not implemented\n", debugstr_wn(value, value_size));
190 hr = S_OK;
193 return hr;
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};
204 HRESULT hr = S_OK;
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");
212 return E_FAIL;
215 switch (This->states[This->statenum])
217 case STATE_ROOT:
218 if (nLocalName == sizeof(configuration)/sizeof(WCHAR)-1 &&
219 lstrcmpW(pLocalName, configuration) == 0)
221 This->states[++This->statenum] = STATE_CONFIGURATION;
222 break;
224 else
225 goto unknown;
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;
232 break;
234 else
235 goto unknown;
236 case 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;
242 break;
244 else
245 goto unknown;
246 default:
247 goto unknown;
250 return hr;
252 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;
258 return S_OK;
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)
272 This->statenum--;
274 else
276 ERR("element end does not match a start\n");
277 return E_FAIL;
280 return S_OK;
283 static HRESULT WINAPI ConfigFileHandler_characters(ISAXContentHandler *iface,
284 const WCHAR *pChars, int nChars)
286 TRACE("%s\n", debugstr_wn(pChars,nChars));
288 return S_OK;
291 static HRESULT WINAPI ConfigFileHandler_ignorableWhitespace(ISAXContentHandler *iface,
292 const WCHAR *pChars, int nChars)
294 return S_OK;
297 static HRESULT WINAPI ConfigFileHandler_processingInstruction(ISAXContentHandler *iface,
298 const WCHAR *pTarget, int nTarget, const WCHAR *pData, int nData)
300 return S_OK;
303 static HRESULT WINAPI ConfigFileHandler_skippedEntity(ISAXContentHandler *iface,
304 const WCHAR * pName, int nName)
306 TRACE("%s\n", debugstr_wn(pName,nName));
307 return S_OK;
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))
334 *ppvObject = iface;
336 else
338 WARN("Unsupported interface %s\n", debugstr_guid(riid));
339 return E_NOINTERFACE;
342 ISAXErrorHandler_AddRef(iface);
344 return S_OK;
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);
363 return S_OK;
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);
370 return S_OK;
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);
377 return S_OK;
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;
399 HRESULT hr;
401 handler = HeapAlloc(GetProcessHeap(), 0, sizeof(ConfigFileHandler));
402 if (!handler)
403 return E_OUTOFMEMORY;
405 handler->ISAXContentHandler_iface.lpVtbl = &ConfigFileHandlerVtbl;
406 handler->ISAXErrorHandler_iface.lpVtbl = &ConfigFileHandlerErrorVtbl;
407 handler->ref = 1;
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);
415 if (SUCCEEDED(hr))
417 hr = ISAXXMLReader_putContentHandler(reader, &handler->ISAXContentHandler_iface);
419 if (SUCCEEDED(hr))
420 hr = ISAXXMLReader_putErrorHandler(reader, &handler->ISAXErrorHandler_iface);
422 if (SUCCEEDED(hr))
423 hr = ISAXXMLReader_parse(reader, input);
425 ISAXXMLReader_Release(reader);
428 IUnknown_Release((IUnknown*)handler);
430 return S_OK;
433 HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
435 IStream *stream;
436 VARIANT var;
437 HRESULT hr;
438 HRESULT initresult;
440 init_config(result);
442 initresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
444 hr = SHCreateStreamOnFileW(filename, STGM_SHARE_DENY_WRITE | STGM_READ | STGM_FAILIFTHERE, &stream);
446 if (SUCCEEDED(hr))
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))
457 CoUninitialize();
459 return hr;
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);