msvcirt: Add implementation of streambuf::unbuffered.
[wine.git] / dlls / mscoree / config.c
blob5da1102437d17fc34f2cc48f3502fa13aea673d1
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_ASSEMBLY_BINDING,
45 STATE_ROOT,
46 STATE_CONFIGURATION,
47 STATE_PROBING,
48 STATE_RUNTIME,
49 STATE_STARTUP,
50 STATE_UNKNOWN
53 typedef struct ConfigFileHandler
55 ISAXContentHandler ISAXContentHandler_iface;
56 ISAXErrorHandler ISAXErrorHandler_iface;
57 LONG ref;
58 enum parse_state states[16];
59 int statenum;
60 parsed_config_file *result;
61 } ConfigFileHandler;
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))
79 *ppvObject = iface;
81 else
83 WARN("Unsupported interface %s\n", debugstr_guid(riid));
84 return E_NOINTERFACE;
87 ISAXContentHandler_AddRef(iface);
89 return S_OK;
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);
103 if (ref == 0)
104 HeapFree(GetProcessHeap(), 0, This);
106 return ref;
109 static HRESULT WINAPI ConfigFileHandler_putDocumentLocator(ISAXContentHandler *iface,
110 ISAXLocator *pLocator)
112 return S_OK;
115 static HRESULT WINAPI ConfigFileHandler_startDocument(ISAXContentHandler *iface)
117 return S_OK;
120 static HRESULT WINAPI ConfigFileHandler_endDocument(ISAXContentHandler *iface)
122 return S_OK;
125 static HRESULT WINAPI ConfigFileHandler_startPrefixMapping(ISAXContentHandler *iface,
126 const WCHAR *pPrefix, int nPrefix, const WCHAR *pUri, int nUri)
128 return S_OK;
131 static HRESULT WINAPI ConfigFileHandler_endPrefixMapping(ISAXContentHandler *iface,
132 const WCHAR *pPrefix, int nPrefix)
134 return S_OK;
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};
141 LPCWSTR value;
142 int value_size;
143 HRESULT hr;
145 hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, legacy, lstrlenW(legacy), &value, &value_size);
146 if (SUCCEEDED(hr))
147 FIXME("useLegacyV2RuntimeActivationPolicy=%s not implemented\n", debugstr_wn(value, value_size));
148 hr = S_OK;
150 return hr;
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};
157 LPCWSTR value;
158 int value_size;
159 HRESULT hr;
161 hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, privatePath, lstrlenW(privatePath), &value, &value_size);
162 if (SUCCEEDED(hr))
163 FIXME("privatePath=%s not implemented\n", debugstr_wn(value, value_size));
164 hr = S_OK;
166 return hr;
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};
175 LPCWSTR value;
176 int value_size;
177 HRESULT hr;
178 supported_runtime *entry;
180 hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, version, lstrlenW(version), &value, &value_size);
181 if (SUCCEEDED(hr))
183 TRACE("%s\n", debugstr_wn(value, value_size));
184 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(supported_runtime));
185 if (entry)
187 entry->version = HeapAlloc(GetProcessHeap(), 0, (value_size + 1) * sizeof(WCHAR));
188 if (entry->version)
190 lstrcpyW(entry->version, value);
191 list_add_tail(&This->result->supported_runtimes, &entry->entry);
193 else
195 HeapFree(GetProcessHeap(), 0, entry);
196 hr = E_OUTOFMEMORY;
199 else
200 hr = E_OUTOFMEMORY;
202 else
203 WARN("Missing version attribute\n");
205 if (SUCCEEDED(hr))
207 hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, sku, lstrlenW(sku), &value, &value_size);
208 if (SUCCEEDED(hr))
209 FIXME("sku=%s not implemented\n", debugstr_wn(value, value_size));
210 hr = S_OK;
213 return hr;
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};
228 HRESULT hr = S_OK;
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");
236 return E_FAIL;
239 switch (This->states[This->statenum])
241 case STATE_ROOT:
242 if (nLocalName == sizeof(configuration)/sizeof(WCHAR)-1 &&
243 lstrcmpW(pLocalName, configuration) == 0)
245 This->states[++This->statenum] = STATE_CONFIGURATION;
246 break;
248 else
249 goto unknown;
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;
256 break;
258 else if (nLocalName == sizeof(runtime)/sizeof(WCHAR)-1 &&
259 lstrcmpW(pLocalName, runtime) == 0)
261 This->states[++This->statenum] = STATE_RUNTIME;
262 break;
264 else
265 goto unknown;
266 case STATE_RUNTIME:
267 if (nLocalName == sizeof(assemblyBinding)/sizeof(WCHAR)-1 &&
268 lstrcmpW(pLocalName, assemblyBinding) == 0)
270 This->states[++This->statenum] = STATE_ASSEMBLY_BINDING;
271 break;
273 else
274 goto unknown;
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;
281 break;
283 else
284 goto unknown;
285 case STATE_STARTUP:
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;
291 break;
293 else
294 goto unknown;
295 default:
296 goto unknown;
299 return hr;
301 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;
307 return S_OK;
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)
321 This->statenum--;
323 else
325 ERR("element end does not match a start\n");
326 return E_FAIL;
329 return S_OK;
332 static HRESULT WINAPI ConfigFileHandler_characters(ISAXContentHandler *iface,
333 const WCHAR *pChars, int nChars)
335 TRACE("%s\n", debugstr_wn(pChars,nChars));
337 return S_OK;
340 static HRESULT WINAPI ConfigFileHandler_ignorableWhitespace(ISAXContentHandler *iface,
341 const WCHAR *pChars, int nChars)
343 return S_OK;
346 static HRESULT WINAPI ConfigFileHandler_processingInstruction(ISAXContentHandler *iface,
347 const WCHAR *pTarget, int nTarget, const WCHAR *pData, int nData)
349 return S_OK;
352 static HRESULT WINAPI ConfigFileHandler_skippedEntity(ISAXContentHandler *iface,
353 const WCHAR * pName, int nName)
355 TRACE("%s\n", debugstr_wn(pName,nName));
356 return S_OK;
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))
383 *ppvObject = iface;
385 else
387 WARN("Unsupported interface %s\n", debugstr_guid(riid));
388 return E_NOINTERFACE;
391 ISAXErrorHandler_AddRef(iface);
393 return S_OK;
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);
412 return S_OK;
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);
419 return S_OK;
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);
426 return S_OK;
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;
448 HRESULT hr;
450 handler = HeapAlloc(GetProcessHeap(), 0, sizeof(ConfigFileHandler));
451 if (!handler)
452 return E_OUTOFMEMORY;
454 handler->ISAXContentHandler_iface.lpVtbl = &ConfigFileHandlerVtbl;
455 handler->ISAXErrorHandler_iface.lpVtbl = &ConfigFileHandlerErrorVtbl;
456 handler->ref = 1;
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);
464 if (SUCCEEDED(hr))
466 hr = ISAXXMLReader_putContentHandler(reader, &handler->ISAXContentHandler_iface);
468 if (SUCCEEDED(hr))
469 hr = ISAXXMLReader_putErrorHandler(reader, &handler->ISAXErrorHandler_iface);
471 if (SUCCEEDED(hr))
472 hr = ISAXXMLReader_parse(reader, input);
474 ISAXXMLReader_Release(reader);
477 ISAXContentHandler_Release(&handler->ISAXContentHandler_iface);
479 return S_OK;
482 HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
484 IStream *stream;
485 VARIANT var;
486 HRESULT hr;
487 HRESULT initresult;
489 init_config(result);
491 initresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
493 hr = SHCreateStreamOnFileW(filename, STGM_SHARE_DENY_WRITE | STGM_READ | STGM_FAILIFTHERE, &stream);
495 if (SUCCEEDED(hr))
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))
506 CoUninitialize();
508 return hr;
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);