po: Updated Korean translation.
[wine.git] / dlls / mscoree / config.c
blob40c83787a6eb9aa26d008390e57772223121cc62
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 "metahost.h"
31 #include "wine/list.h"
32 #include "mscoree_private.h"
33 #include "shlwapi.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
39 enum parse_state
41 STATE_ROOT,
42 STATE_CONFIGURATION,
43 STATE_STARTUP,
44 STATE_UNKNOWN
47 typedef struct ConfigFileHandler
49 ISAXContentHandler ISAXContentHandler_iface;
50 ISAXErrorHandler ISAXErrorHandler_iface;
51 LONG ref;
52 enum parse_state states[16];
53 int statenum;
54 parsed_config_file *result;
55 } ConfigFileHandler;
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))
73 *ppvObject = iface;
75 else
77 WARN("Unsupported interface %s\n", debugstr_guid(riid));
78 return E_NOINTERFACE;
81 ISAXContentHandler_AddRef(iface);
83 return S_OK;
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);
97 if (ref == 0)
98 HeapFree(GetProcessHeap(), 0, This);
100 return ref;
103 static HRESULT WINAPI ConfigFileHandler_putDocumentLocator(ISAXContentHandler *iface,
104 ISAXLocator *pLocator)
106 return S_OK;
109 static HRESULT WINAPI ConfigFileHandler_startDocument(ISAXContentHandler *iface)
111 return S_OK;
114 static HRESULT WINAPI ConfigFileHandler_endDocument(ISAXContentHandler *iface)
116 return S_OK;
119 static HRESULT WINAPI ConfigFileHandler_startPrefixMapping(ISAXContentHandler *iface,
120 const WCHAR *pPrefix, int nPrefix, const WCHAR *pUri, int nUri)
122 return S_OK;
125 static HRESULT WINAPI ConfigFileHandler_endPrefixMapping(ISAXContentHandler *iface,
126 const WCHAR *pPrefix, int nPrefix)
128 return S_OK;
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};
135 LPCWSTR value;
136 int value_size;
137 HRESULT hr;
139 hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, legacy, lstrlenW(legacy), &value, &value_size);
140 if (SUCCEEDED(hr))
141 FIXME("useLegacyV2RuntimeActivationPolicy=%s not implemented\n", debugstr_wn(value, value_size));
142 hr = S_OK;
144 return hr;
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};
152 LPCWSTR value;
153 int value_size;
154 HRESULT hr;
155 supported_runtime *entry;
157 hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, version, lstrlenW(version), &value, &value_size);
158 if (SUCCEEDED(hr))
160 TRACE("%s\n", debugstr_wn(value, value_size));
161 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(supported_runtime));
162 if (entry)
164 entry->version = HeapAlloc(GetProcessHeap(), 0, (value_size + 1) * sizeof(WCHAR));
165 if (entry->version)
167 lstrcpyW(entry->version, value);
168 list_add_tail(&This->result->supported_runtimes, &entry->entry);
170 else
172 HeapFree(GetProcessHeap(), 0, entry);
173 hr = E_OUTOFMEMORY;
176 else
177 hr = E_OUTOFMEMORY;
179 else
180 WARN("Missing version attribute\n");
182 if (SUCCEEDED(hr))
184 hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, sku, lstrlenW(sku), &value, &value_size);
185 if (SUCCEEDED(hr))
186 FIXME("sku=%s not implemented\n", debugstr_wn(value, value_size));
187 hr = S_OK;
190 return hr;
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};
201 HRESULT hr = S_OK;
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");
209 return E_FAIL;
212 switch (This->states[This->statenum])
214 case STATE_ROOT:
215 if (nLocalName == sizeof(configuration)/sizeof(WCHAR)-1 &&
216 lstrcmpW(pLocalName, configuration) == 0)
218 This->states[++This->statenum] = STATE_CONFIGURATION;
219 break;
221 else
222 goto unknown;
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;
229 break;
231 else
232 goto unknown;
233 case 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;
239 break;
241 else
242 goto unknown;
243 default:
244 goto unknown;
247 return hr;
249 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;
255 return S_OK;
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)
269 This->statenum--;
271 else
273 ERR("element end does not match a start\n");
274 return E_FAIL;
277 return S_OK;
280 static HRESULT WINAPI ConfigFileHandler_characters(ISAXContentHandler *iface,
281 const WCHAR *pChars, int nChars)
283 TRACE("%s\n", debugstr_wn(pChars,nChars));
285 return S_OK;
288 static HRESULT WINAPI ConfigFileHandler_ignorableWhitespace(ISAXContentHandler *iface,
289 const WCHAR *pChars, int nChars)
291 return S_OK;
294 static HRESULT WINAPI ConfigFileHandler_processingInstruction(ISAXContentHandler *iface,
295 const WCHAR *pTarget, int nTarget, const WCHAR *pData, int nData)
297 return S_OK;
300 static HRESULT WINAPI ConfigFileHandler_skippedEntity(ISAXContentHandler *iface,
301 const WCHAR * pName, int nName)
303 TRACE("%s\n", debugstr_wn(pName,nName));
304 return S_OK;
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))
331 *ppvObject = iface;
333 else
335 WARN("Unsupported interface %s\n", debugstr_guid(riid));
336 return E_NOINTERFACE;
339 ISAXErrorHandler_AddRef(iface);
341 return S_OK;
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);
360 return S_OK;
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);
367 return S_OK;
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);
374 return S_OK;
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;
396 HRESULT hr;
398 handler = HeapAlloc(GetProcessHeap(), 0, sizeof(ConfigFileHandler));
399 if (!handler)
400 return E_OUTOFMEMORY;
402 handler->ISAXContentHandler_iface.lpVtbl = &ConfigFileHandlerVtbl;
403 handler->ISAXErrorHandler_iface.lpVtbl = &ConfigFileHandlerErrorVtbl;
404 handler->ref = 1;
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);
412 if (SUCCEEDED(hr))
414 hr = ISAXXMLReader_putContentHandler(reader, &handler->ISAXContentHandler_iface);
416 if (SUCCEEDED(hr))
417 hr = ISAXXMLReader_putErrorHandler(reader, &handler->ISAXErrorHandler_iface);
419 if (SUCCEEDED(hr))
420 hr = ISAXXMLReader_parse(reader, input);
422 ISAXXMLReader_Release(reader);
425 IUnknown_Release((IUnknown*)handler);
427 return S_OK;
430 HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
432 IStream *stream;
433 VARIANT var;
434 HRESULT hr;
435 HRESULT initresult;
437 init_config(result);
439 initresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
441 hr = SHCreateStreamOnFileW(filename, STGM_SHARE_DENY_WRITE | STGM_READ | STGM_FAILIFTHERE, &stream);
443 if (SUCCEEDED(hr))
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))
454 CoUninitialize();
456 return hr;
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);