ReactOS 0.4.15-dev-7842-g558ab78
schema.c
Go to the documentation of this file.
1/*
2 * Schema cache implementation
3 *
4 * Copyright 2007 Huw Davies
5 * Copyright 2010 Adam Martinson for CodeWeavers
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#define COBJMACROS
23
24#include "config.h"
25
26#include <assert.h>
27#include <stdarg.h>
28#ifdef HAVE_LIBXML2
29# include <libxml/xmlerror.h>
30# include <libxml/tree.h>
31# include <libxml/xmlschemas.h>
33# include <libxml/hash.h>
34# include <libxml/parser.h>
36# include <libxml/xmlIO.h>
37# include <libxml/xmlversion.h>
38# include <libxml/xpath.h>
39#endif
40
41#include "windef.h"
42#include "winbase.h"
43#include "winuser.h"
44#include "ole2.h"
45#include "msxml6.h"
46
47#include "wine/debug.h"
48
49#include "msxml_private.h"
50
51#ifdef HAVE_LIBXML2
52
54
55#if LIBXML_VERSION >= 20908
56#define XMLHASH_CONST const
57#else
58#define XMLHASH_CONST
59#endif
60
61/* We use a chained hashtable, which can hold any number of schemas
62 * TODO: grow/shrink hashtable depending on load factor
63 * TODO: implement read-only where appropriate
64 */
65
66/* This is just the number of buckets, should be prime */
67#define DEFAULT_HASHTABLE_SIZE 17
68
69xmlDocPtr XDR_to_XSD_doc(xmlDocPtr xdr_doc, xmlChar const* nsURI);
70
71static const xmlChar XSD_schema[] = "schema";
72static const xmlChar XSD_nsURI[] = "http://www.w3.org/2001/XMLSchema";
73static const xmlChar XDR_schema[] = "Schema";
74static const xmlChar XDR_nsURI[] = "urn:schemas-microsoft-com:xml-data";
75static const xmlChar DT_nsURI[] = "urn:schemas-microsoft-com:datatypes";
76
77static xmlChar * datatypes_src;
78static int datatypes_len;
79static HGLOBAL datatypes_handle;
80static HRSRC datatypes_rsrc;
81static xmlSchemaPtr datatypes_schema;
82
83static const WCHAR emptyW[] = {0};
84
85/* Supported types:
86 * msxml3 - XDR only
87 * msxml4 - XDR & XSD
88 * msxml5 - XDR & XSD
89 * mxsml6 - XSD only
90 *
91 * CacheType_NS is a special type used for read-only collection build with
92 * IXMLDOMDocument2::namespaces()
93 */
94typedef enum {
95 CacheEntryType_Invalid,
96 CacheEntryType_XDR,
97 CacheEntryType_XSD,
98 CacheEntryType_NS
99} CacheEntryType;
100
101typedef struct
102{
103 DispatchEx dispex;
104 IXMLDOMSchemaCollection2 IXMLDOMSchemaCollection2_iface;
105 LONG ref;
106
109 xmlChar **uris;
110 int allocated;
111 int count;
112
113 VARIANT_BOOL validateOnLoad;
114 int read_only;
115} schema_cache;
116
117typedef struct
118{
119 CacheEntryType type;
120 xmlSchemaPtr schema;
121 xmlDocPtr doc;
122 LONG ref;
124
125static const tid_t schema_cache_se_tids[] = {
129};
130
131/* datatypes lookup stuff
132 * generated with help from gperf */
133#define DT_MIN_STR_LEN 2
134#define DT_MAX_STR_LEN 11
135#define DT_MIN_HASH_VALUE 2
136#define DT_MAX_HASH_VALUE 115
137
138static const xmlChar DT_bin_base64[] = "bin.base64";
139static const xmlChar DT_bin_hex[] = "bin.hex";
140static const xmlChar DT_boolean[] = "boolean";
141static const xmlChar DT_char[] = "char";
142static const xmlChar DT_date[] = "date";
143static const xmlChar DT_date_tz[] = "date.tz";
144static const xmlChar DT_dateTime[] = "dateTime";
145static const xmlChar DT_dateTime_tz[] = "dateTime.tz";
146static const xmlChar DT_entity[] = "entity";
147static const xmlChar DT_entities[] = "entities";
148static const xmlChar DT_enumeration[] = "enumeration";
149static const xmlChar DT_fixed_14_4[] = "fixed.14.4";
150static const xmlChar DT_float[] = "float";
151static const xmlChar DT_i1[] = "i1";
152static const xmlChar DT_i2[] = "i2";
153static const xmlChar DT_i4[] = "i4";
154static const xmlChar DT_i8[] = "i8";
155static const xmlChar DT_id[] = "id";
156static const xmlChar DT_idref[] = "idref";
157static const xmlChar DT_idrefs[] = "idrefs";
158static const xmlChar DT_int[] = "int";
159static const xmlChar DT_nmtoken[] = "nmtoken";
160static const xmlChar DT_nmtokens[] = "nmtokens";
161static const xmlChar DT_notation[] = "notation";
162static const xmlChar DT_number[] = "number";
163static const xmlChar DT_r4[] = "r4";
164static const xmlChar DT_r8[] = "r8";
165static const xmlChar DT_string[] = "string";
166static const xmlChar DT_time[] = "time";
167static const xmlChar DT_time_tz[] = "time.tz";
168static const xmlChar DT_ui1[] = "ui1";
169static const xmlChar DT_ui2[] = "ui2";
170static const xmlChar DT_ui4[] = "ui4";
171static const xmlChar DT_ui8[] = "ui8";
172static const xmlChar DT_uri[] = "uri";
173static const xmlChar DT_uuid[] = "uuid";
174
175static const OLECHAR wDT_bin_base64[] = {'b','i','n','.','b','a','s','e','6','4',0};
176static const OLECHAR wDT_bin_hex[] = {'b','i','n','.','h','e','x',0};
177static const OLECHAR wDT_boolean[] = {'b','o','o','l','e','a','n',0};
178static const OLECHAR wDT_char[] = {'c','h','a','r',0};
179static const OLECHAR wDT_date[] = {'d','a','t','e',0};
180static const OLECHAR wDT_date_tz[] = {'d','a','t','e','.','t','z',0};
181static const OLECHAR wDT_dateTime[] = {'d','a','t','e','T','i','m','e',0};
182static const OLECHAR wDT_dateTime_tz[] = {'d','a','t','e','T','i','m','e','.','t','z',0};
183static const OLECHAR wDT_entity[] = {'e','n','t','i','t','y',0};
184static const OLECHAR wDT_entities[] = {'e','n','t','i','t','i','e','s',0};
185static const OLECHAR wDT_enumeration[] = {'e','n','u','m','e','r','a','t','i','o','n',0};
186static const OLECHAR wDT_fixed_14_4[] = {'f','i','x','e','d','.','1','4','.','4',0};
187static const OLECHAR wDT_float[] = {'f','l','o','a','t',0};
188static const OLECHAR wDT_i1[] = {'i','1',0};
189static const OLECHAR wDT_i2[] = {'i','2',0};
190static const OLECHAR wDT_i4[] = {'i','4',0};
191static const OLECHAR wDT_i8[] = {'i','8',0};
192static const OLECHAR wDT_id[] = {'i','d',0};
193static const OLECHAR wDT_idref[] = {'i','d','r','e','f',0};
194static const OLECHAR wDT_idrefs[] = {'i','d','r','e','f','s',0};
195static const OLECHAR wDT_int[] = {'i','n','t',0};
196static const OLECHAR wDT_nmtoken[] = {'n','m','t','o','k','e','n',0};
197static const OLECHAR wDT_nmtokens[] = {'n','m','t','o','k','e','n','s',0};
198static const OLECHAR wDT_notation[] = {'n','o','t','a','t','i','o','n',0};
199static const OLECHAR wDT_number[] = {'n','u','m','b','e','r',0};
200static const OLECHAR wDT_r4[] = {'r','4',0};
201static const OLECHAR wDT_r8[] = {'r','8',0};
202static const OLECHAR wDT_string[] = {'s','t','r','i','n','g',0};
203static const OLECHAR wDT_time[] = {'t','i','m','e',0};
204static const OLECHAR wDT_time_tz[] = {'t','i','m','e','.','t','z',0};
205static const OLECHAR wDT_ui1[] = {'u','i','1',0};
206static const OLECHAR wDT_ui2[] = {'u','i','2',0};
207static const OLECHAR wDT_ui4[] = {'u','i','4',0};
208static const OLECHAR wDT_ui8[] = {'u','i','8',0};
209static const OLECHAR wDT_uri[] = {'u','r','i',0};
210static const OLECHAR wDT_uuid[] = {'u','u','i','d',0};
211
212static const BYTE hash_assoc_values[] =
213{
214 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
215 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
216 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
217 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
218 116, 116, 116, 116, 116, 116, 10, 116, 116, 55,
219 45, 116, 5, 116, 0, 116, 0, 116, 116, 116,
220 116, 116, 116, 116, 116, 5, 0, 0, 20, 0,
221 0, 10, 0, 0, 116, 0, 0, 0, 15, 5,
222 116, 116, 10, 0, 0, 0, 116, 116, 0, 0,
223 10, 116, 116, 116, 116, 116, 116, 5, 0, 0,
224 20, 0, 0, 10, 0, 0, 116, 0, 0, 0,
225 15, 5, 116, 116, 10, 0, 0, 0, 116, 116,
226 0, 0, 10, 116, 116, 116, 116, 116, 116, 116,
227 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
228 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
229 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
230 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
231 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
232 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
233 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
234 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
235 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
236 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
237 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
238 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
239 116, 116, 116, 116, 116, 116
240};
241
242static void LIBXML2_LOG_CALLBACK parser_error(void* ctx, char const* msg, ...)
243{
244 va_list ap;
245 va_start(ap, msg);
246 LIBXML2_CALLBACK_ERR(Schema_parse, msg, ap);
247 va_end(ap);
248}
249
250static void LIBXML2_LOG_CALLBACK parser_warning(void* ctx, char const* msg, ...)
251{
252 va_list ap;
253 va_start(ap, msg);
254 LIBXML2_CALLBACK_WARN(Schema_parse, msg, ap);
255 va_end(ap);
256}
257
258#ifdef HAVE_XMLSCHEMASSETPARSERSTRUCTUREDERRORS
259static void parser_serror(void* ctx, xmlErrorPtr err)
260{
261 LIBXML2_CALLBACK_SERROR(Schema_parse, err);
262}
263#endif
264
265static inline xmlSchemaPtr Schema_parse(xmlSchemaParserCtxtPtr spctx)
266{
267 TRACE("(%p)\n", spctx);
268
269 xmlSchemaSetParserErrors(spctx, parser_error, parser_warning, NULL);
270#ifdef HAVE_XMLSCHEMASSETPARSERSTRUCTUREDERRORS
271 xmlSchemaSetParserStructuredErrors(spctx, parser_serror, NULL);
272#endif
273
274 return xmlSchemaParse(spctx);
275}
276
277static void LIBXML2_LOG_CALLBACK validate_error(void* ctx, char const* msg, ...)
278{
279 va_list ap;
280 va_start(ap, msg);
281 LIBXML2_CALLBACK_ERR(Schema_validate_tree, msg, ap);
282 va_end(ap);
283}
284
285static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, ...)
286{
287 va_list ap;
288 va_start(ap, msg);
289 LIBXML2_CALLBACK_WARN(Schema_validate_tree, msg, ap);
290 va_end(ap);
291}
292
293#ifdef HAVE_XMLSCHEMASSETVALIDSTRUCTUREDERRORS
294static void validate_serror(void* ctx, xmlErrorPtr err)
295{
296 LIBXML2_CALLBACK_SERROR(Schema_validate_tree, err);
297}
298#endif
299
300static HRESULT schema_cache_get_item(IUnknown *iface, LONG index, VARIANT *item)
301{
302 V_VT(item) = VT_BSTR;
303 return IXMLDOMSchemaCollection2_get_namespaceURI((IXMLDOMSchemaCollection2*)iface, index, &V_BSTR(item));
304}
305
306static const struct enumvariant_funcs schemacache_enumvariant = {
307 schema_cache_get_item,
308 NULL
309};
310
311static inline HRESULT Schema_validate_tree(xmlSchemaPtr schema, xmlNodePtr tree)
312{
313 xmlSchemaValidCtxtPtr svctx;
314 int err;
315
316 TRACE("(%p, %p)\n", schema, tree);
317 /* TODO: if validateOnLoad property is false,
318 * we probably need to validate the schema here. */
319 svctx = xmlSchemaNewValidCtxt(schema);
320 xmlSchemaSetValidErrors(svctx, validate_error, validate_warning, NULL);
321#ifdef HAVE_XMLSCHEMASSETVALIDSTRUCTUREDERRORS
322 xmlSchemaSetValidStructuredErrors(svctx, validate_serror, NULL);
323#endif
324
325 if (tree->type == XML_DOCUMENT_NODE)
326 err = xmlSchemaValidateDoc(svctx, (xmlDocPtr)tree);
327 else
328 err = xmlSchemaValidateOneElement(svctx, tree);
329
330 xmlSchemaFreeValidCtxt(svctx);
331 return err? S_FALSE : S_OK;
332}
333
334static DWORD dt_hash(xmlChar const* str, int len /* calculated if -1 */)
335{
336 DWORD hval = (len == -1)? xmlStrlen(str) : len;
337
338 switch (hval)
339 {
340 default:
341 hval += hash_assoc_values[str[10]];
342 /*FALLTHROUGH*/
343 case 10:
344 hval += hash_assoc_values[str[9]];
345 /*FALLTHROUGH*/
346 case 9:
347 hval += hash_assoc_values[str[8]];
348 /*FALLTHROUGH*/
349 case 8:
350 hval += hash_assoc_values[str[7]];
351 /*FALLTHROUGH*/
352 case 7:
353 hval += hash_assoc_values[str[6]];
354 /*FALLTHROUGH*/
355 case 6:
356 hval += hash_assoc_values[str[5]];
357 /*FALLTHROUGH*/
358 case 5:
359 hval += hash_assoc_values[str[4]];
360 /*FALLTHROUGH*/
361 case 4:
362 hval += hash_assoc_values[str[3]];
363 /*FALLTHROUGH*/
364 case 3:
365 hval += hash_assoc_values[str[2]];
366 /*FALLTHROUGH*/
367 case 2:
368 hval += hash_assoc_values[str[1]];
369 /*FALLTHROUGH*/
370 case 1:
371 hval += hash_assoc_values[str[0]];
372 break;
373 }
374 return hval;
375}
376
377static DWORD dt_hash_bstr(OLECHAR const* bstr, int len /* calculated if -1 */)
378{
379 DWORD hval = (len == -1)? lstrlenW(bstr) : len;
380
381 switch (hval)
382 {
383 default:
384 hval += (bstr[10] & 0xFF00)? 116 : hash_assoc_values[bstr[10]];
385 /*FALLTHROUGH*/
386 case 10:
387 hval += (bstr[9] & 0xFF00)? 116 : hash_assoc_values[bstr[9]];
388 /*FALLTHROUGH*/
389 case 9:
390 hval += (bstr[8] & 0xFF00)? 116 : hash_assoc_values[bstr[8]];
391 /*FALLTHROUGH*/
392 case 8:
393 hval += (bstr[7] & 0xFF00)? 116 : hash_assoc_values[bstr[7]];
394 /*FALLTHROUGH*/
395 case 7:
396 hval += (bstr[6] & 0xFF00)? 116 : hash_assoc_values[bstr[6]];
397 /*FALLTHROUGH*/
398 case 6:
399 hval += (bstr[5] & 0xFF00)? 116 : hash_assoc_values[bstr[5]];
400 /*FALLTHROUGH*/
401 case 5:
402 hval += (bstr[4] & 0xFF00)? 116 : hash_assoc_values[bstr[4]];
403 /*FALLTHROUGH*/
404 case 4:
405 hval += (bstr[3] & 0xFF00)? 116 : hash_assoc_values[bstr[3]];
406 /*FALLTHROUGH*/
407 case 3:
408 hval += (bstr[2] & 0xFF00)? 116 : hash_assoc_values[bstr[2]];
409 /*FALLTHROUGH*/
410 case 2:
411 hval += (bstr[1] & 0xFF00)? 116 : hash_assoc_values[bstr[1]];
412 /*FALLTHROUGH*/
413 case 1:
414 hval += (bstr[0] & 0xFF00)? 116 : hash_assoc_values[bstr[0]];
415 break;
416 }
417 return hval;
418}
419
420static const xmlChar *const DT_string_table[LAST_DT] =
421{
422 DT_bin_base64,
423 DT_bin_hex,
424 DT_boolean,
425 DT_char,
426 DT_date,
427 DT_date_tz,
428 DT_dateTime,
429 DT_dateTime_tz,
430 DT_entity,
431 DT_entities,
432 DT_enumeration,
433 DT_fixed_14_4,
434 DT_float,
435 DT_i1,
436 DT_i2,
437 DT_i4,
438 DT_i8,
439 DT_id,
440 DT_idref,
441 DT_idrefs,
442 DT_int,
443 DT_nmtoken,
444 DT_nmtokens,
445 DT_notation,
446 DT_number,
447 DT_r4,
448 DT_r8,
449 DT_string,
450 DT_time,
451 DT_time_tz,
452 DT_ui1,
453 DT_ui2,
454 DT_ui4,
455 DT_ui8,
456 DT_uri,
457 DT_uuid
458};
459
460static const WCHAR *const DT_wstring_table[LAST_DT] =
461{
462 wDT_bin_base64,
463 wDT_bin_hex,
464 wDT_boolean,
465 wDT_char,
466 wDT_date,
467 wDT_date_tz,
468 wDT_dateTime,
469 wDT_dateTime_tz,
470 wDT_entity,
471 wDT_entities,
472 wDT_enumeration,
473 wDT_fixed_14_4,
474 wDT_float,
475 wDT_i1,
476 wDT_i2,
477 wDT_i4,
478 wDT_i8,
479 wDT_id,
480 wDT_idref,
481 wDT_idrefs,
482 wDT_int,
483 wDT_nmtoken,
484 wDT_nmtokens,
485 wDT_notation,
486 wDT_number,
487 wDT_r4,
488 wDT_r8,
489 wDT_string,
490 wDT_time,
491 wDT_time_tz,
492 wDT_ui1,
493 wDT_ui2,
494 wDT_ui4,
495 wDT_ui8,
496 wDT_uri,
497 wDT_uuid
498};
499
500static const XDR_DT DT_lookup_table[] =
501{
502 -1, -1,
503 DT_I8,
504 DT_UI8,
505 DT_TIME,
506 -1, -1,
507 DT_I4,
508 DT_UI4,
509 -1, -1, -1,
510 DT_R8,
511 DT_URI,
512 -1,
513 DT_FLOAT,
514 -1,
515 DT_R4,
516 DT_INT,
517 DT_CHAR,
518 -1,
519 DT_ENTITY,
520 DT_ID,
522 DT_UUID,
523 -1, -1,
525 -1,
526 DT_DATE,
527 -1,
528 DT_NUMBER,
531 -1,
532 DT_IDREF,
533 DT_IDREFS,
535 -1, -1, -1,
536 DT_STRING,
539 -1,
541 -1,
542 DT_I2,
543 DT_UI2,
544 -1, -1, -1,
547 -1, -1,
549 DT_I1,
550 DT_UI1,
551 -1, -1,
553 -1, -1, -1, -1, -1, -1, -1, -1, -1,
554 -1, -1, -1, -1, -1, -1, -1, -1, -1,
555 -1, -1, -1, -1, -1, -1, -1, -1, -1,
556 -1, -1, -1, -1, -1, -1, -1, -1, -1,
557 -1, -1, -1, -1, -1, -1, -1, -1, -1,
558 -1, -1, -1, -1, -1, -1, -1, -1,
560};
561
562XDR_DT str_to_dt(xmlChar const* str, int len /* calculated if -1 */)
563{
564 DWORD hash = dt_hash(str, len);
565 XDR_DT dt = DT_INVALID;
566
567 if (hash <= DT_MAX_HASH_VALUE)
568 dt = DT_lookup_table[hash];
569
570 if (dt != DT_INVALID && xmlStrcasecmp(str, DT_string_table[dt]) == 0)
571 return dt;
572
573 return DT_INVALID;
574}
575
576XDR_DT bstr_to_dt(OLECHAR const* bstr, int len /* calculated if -1 */)
577{
578 DWORD hash = dt_hash_bstr(bstr, len);
579 XDR_DT dt = DT_INVALID;
580
581 if (hash <= DT_MAX_HASH_VALUE)
582 dt = DT_lookup_table[hash];
583
584 if (dt != DT_INVALID && lstrcmpiW(bstr, DT_wstring_table[dt]) == 0)
585 return dt;
586
587 return DT_INVALID;
588}
589
590xmlChar const* dt_to_str(XDR_DT dt)
591{
592 if (dt == DT_INVALID)
593 return NULL;
594
595 return DT_string_table[dt];
596}
597
598OLECHAR const* dt_to_bstr(XDR_DT dt)
599{
600 if (dt == DT_INVALID)
601 return NULL;
602
603 return DT_wstring_table[dt];
604}
605
606const char* debugstr_dt(XDR_DT dt)
607{
608 return debugstr_a(dt != DT_INVALID ? (const char*)DT_string_table[dt] : NULL);
609}
610
611HRESULT dt_validate(XDR_DT dt, xmlChar const* content)
612{
613 xmlDocPtr tmp_doc;
615 xmlNsPtr ns;
616 HRESULT hr;
617
618 TRACE("(dt:%s, %s)\n", debugstr_dt(dt), debugstr_a((char const*)content));
619
620 if (!datatypes_schema)
621 {
622 xmlSchemaParserCtxtPtr spctx;
623 assert(datatypes_src != NULL);
624 spctx = xmlSchemaNewMemParserCtxt((char const*)datatypes_src, datatypes_len);
625 datatypes_schema = Schema_parse(spctx);
626 xmlSchemaFreeParserCtxt(spctx);
627 }
628
629 switch (dt)
630 {
631 case DT_INVALID:
632 return E_FAIL;
633 case DT_BIN_BASE64:
634 case DT_BIN_HEX:
635 case DT_BOOLEAN:
636 case DT_CHAR:
637 case DT_DATE:
638 case DT_DATE_TZ:
639 case DT_DATETIME:
640 case DT_DATETIME_TZ:
641 case DT_FIXED_14_4:
642 case DT_FLOAT:
643 case DT_I1:
644 case DT_I2:
645 case DT_I4:
646 case DT_I8:
647 case DT_INT:
648 case DT_NMTOKEN:
649 case DT_NMTOKENS:
650 case DT_NUMBER:
651 case DT_R4:
652 case DT_R8:
653 case DT_STRING:
654 case DT_TIME:
655 case DT_TIME_TZ:
656 case DT_UI1:
657 case DT_UI2:
658 case DT_UI4:
659 case DT_UI8:
660 case DT_URI:
661 case DT_UUID:
662 if (!datatypes_schema)
663 {
664 ERR("failed to load schema for urn:schemas-microsoft-com:datatypes, "
665 "you're probably using an old version of libxml2: " LIBXML_DOTTED_VERSION "\n");
666
667 /* Hopefully they don't need much in the way of XDR datatypes support... */
668 return S_OK;
669 }
670
671 if (content && xmlStrlen(content))
672 {
673 tmp_doc = xmlNewDoc(NULL);
674 node = xmlNewChild((xmlNodePtr)tmp_doc, NULL, dt_to_str(dt), content);
675 ns = xmlNewNs(node, DT_nsURI, BAD_CAST "dt");
676 xmlSetNs(node, ns);
677 xmlDocSetRootElement(tmp_doc, node);
678
679 hr = Schema_validate_tree(datatypes_schema, (xmlNodePtr)tmp_doc);
680 xmlFreeDoc(tmp_doc);
681 }
682 else
683 { /* probably the node is being created manually and has no content yet */
684 hr = S_OK;
685 }
686 return hr;
687 default:
688 FIXME("need to handle dt:%s\n", debugstr_dt(dt));
689 return S_OK;
690 }
691}
692
693static inline xmlChar const* get_node_nsURI(xmlNodePtr node)
694{
695 return (node->ns != NULL)? node->ns->href : NULL;
696}
697
698static inline cache_entry* get_entry(schema_cache* This, xmlChar const* nsURI)
699{
700 return (!nsURI)? xmlHashLookup(This->cache, BAD_CAST "") :
701 xmlHashLookup(This->cache, nsURI);
702}
703
704static inline xmlSchemaPtr get_node_schema(schema_cache* This, xmlNodePtr node)
705{
706 cache_entry* entry = get_entry(This, get_node_nsURI(node));
707 return (!entry)? NULL : entry->schema;
708}
709
710static xmlExternalEntityLoader _external_entity_loader;
711
712static xmlParserInputPtr external_entity_loader(const char *URL, const char *ID,
713 xmlParserCtxtPtr ctxt)
714{
716
717 TRACE("(%s %s %p)\n", debugstr_a(URL), debugstr_a(ID), ctxt);
718
720 assert(datatypes_rsrc != NULL);
721 assert(datatypes_handle != NULL);
722 assert(datatypes_src != NULL);
723
724 /* TODO: if the desired schema is in the cache, load it from there */
725 if (lstrcmpA(URL, "urn:schemas-microsoft-com:datatypes") == 0)
726 {
727 TRACE("loading built-in schema for %s\n", URL);
728 input = xmlNewStringInputStream(ctxt, datatypes_src);
729 }
730 else
731 {
732 input = _external_entity_loader(URL, ID, ctxt);
733 }
734
735 return input;
736}
737
738void schemasInit(void)
739{
740 xmlChar* buf;
741 if (!(datatypes_rsrc = FindResourceA(MSXML_hInstance, "DATATYPES", "XML")))
742 {
743 FIXME("failed to find resource for %s\n", DT_nsURI);
744 return;
745 }
746
747 if (!(datatypes_handle = LoadResource(MSXML_hInstance, datatypes_rsrc)))
748 {
749 FIXME("failed to load resource for %s\n", DT_nsURI);
750 return;
751 }
752 buf = LockResource(datatypes_handle);
753 datatypes_len = SizeofResource(MSXML_hInstance, datatypes_rsrc);
754
755 /* Resource is loaded as raw data,
756 * need a null-terminated string */
757 while (buf[datatypes_len - 1] != '>') datatypes_len--;
758 datatypes_src = heap_alloc(datatypes_len + 1);
759 memcpy(datatypes_src, buf, datatypes_len);
760 datatypes_src[datatypes_len] = 0;
761
762 if (xmlGetExternalEntityLoader() != external_entity_loader)
763 {
764 _external_entity_loader = xmlGetExternalEntityLoader();
765 xmlSetExternalEntityLoader(external_entity_loader);
766 }
767}
768
769void schemasCleanup(void)
770{
771 xmlSchemaFree(datatypes_schema);
772 heap_free(datatypes_src);
773 xmlSetExternalEntityLoader(_external_entity_loader);
774}
775
776static LONG cache_entry_add_ref(cache_entry* entry)
777{
779 TRACE("(%p)->(%d)\n", entry, ref);
780 return ref;
781}
782
783static LONG cache_entry_release(cache_entry* entry)
784{
786 TRACE("(%p)->(%d)\n", entry, ref);
787
788 if (ref == 0)
789 {
790 if (entry->type == CacheEntryType_XSD)
791 {
792 xmldoc_release(entry->doc);
793 entry->schema->doc = NULL;
794 xmlSchemaFree(entry->schema);
795 }
796 else if (entry->type == CacheEntryType_XDR)
797 {
798 xmldoc_release(entry->doc);
799 xmldoc_release(entry->schema->doc);
800 entry->schema->doc = NULL;
801 xmlSchemaFree(entry->schema);
802 }
803
805 }
806 return ref;
807}
808
809static const struct IXMLDOMSchemaCollection2Vtbl XMLDOMSchemaCollection2Vtbl;
810
811static inline schema_cache* impl_from_IXMLDOMSchemaCollection2(IXMLDOMSchemaCollection2* iface)
812{
813 return CONTAINING_RECORD(iface, schema_cache, IXMLDOMSchemaCollection2_iface);
814}
815
816static inline schema_cache* impl_from_IXMLDOMSchemaCollection(IXMLDOMSchemaCollection* iface)
817{
818 return CONTAINING_RECORD((IXMLDOMSchemaCollection2 *)iface, schema_cache, IXMLDOMSchemaCollection2_iface);
819}
820
821static inline schema_cache* unsafe_impl_from_IXMLDOMSchemaCollection(IXMLDOMSchemaCollection *iface)
822{
823 return iface->lpVtbl == (void*)&XMLDOMSchemaCollection2Vtbl ? impl_from_IXMLDOMSchemaCollection(iface) : NULL;
824}
825
826static inline CacheEntryType cache_type_from_xmlDocPtr(xmlDocPtr schema)
827{
829 if (schema)
831 if (root && root->ns)
832 {
833
834 if (xmlStrEqual(root->name, XDR_schema) &&
835 xmlStrEqual(root->ns->href, XDR_nsURI))
836 {
837 return CacheEntryType_XDR;
838 }
839 else if (xmlStrEqual(root->name, XSD_schema) &&
840 xmlStrEqual(root->ns->href, XSD_nsURI))
841 {
842 return CacheEntryType_XSD;
843 }
844 }
845 return CacheEntryType_Invalid;
846}
847
848static BOOL link_datatypes(xmlDocPtr schema)
849{
851 xmlNsPtr ns;
852
853 assert(xmlGetExternalEntityLoader() == external_entity_loader);
855 if (!root)
856 return FALSE;
857
858 for (ns = root->nsDef; ns != NULL; ns = ns->next)
859 {
860 if (xmlStrEqual(ns->href, DT_nsURI))
861 break;
862 }
863
864 if (!ns)
865 return FALSE;
866
867 next = xmlFirstElementChild(root);
868 child = xmlNewChild(root, NULL, BAD_CAST "import", NULL);
869 if (next) child = xmlAddPrevSibling(next, child);
870 xmlSetProp(child, BAD_CAST "namespace", DT_nsURI);
871 xmlSetProp(child, BAD_CAST "schemaLocation", DT_nsURI);
872
873 return TRUE;
874}
875
876static cache_entry* cache_entry_from_xsd_doc(xmlDocPtr doc, xmlChar const* nsURI, MSXML_VERSION v)
877{
879 xmlSchemaParserCtxtPtr spctx;
880 xmlDocPtr new_doc = xmlCopyDoc(doc, 1);
881
882 link_datatypes(new_doc);
883
884 /* TODO: if the nsURI is different from the default xmlns or targetNamespace,
885 * do we need to do something special here? */
886 entry->type = CacheEntryType_XSD;
887 entry->ref = 0;
888 spctx = xmlSchemaNewDocParserCtxt(new_doc);
889
890 if ((entry->schema = Schema_parse(spctx)))
891 {
892 xmldoc_init(entry->schema->doc, v);
893 entry->doc = entry->schema->doc;
894 xmldoc_add_ref(entry->doc);
895 }
896 else
897 {
898 FIXME("failed to parse doc\n");
899 xmlFreeDoc(new_doc);
901 entry = NULL;
902 }
903 xmlSchemaFreeParserCtxt(spctx);
904 return entry;
905}
906
907static cache_entry* cache_entry_from_xdr_doc(xmlDocPtr doc, xmlChar const* nsURI, MSXML_VERSION version)
908{
910 xmlSchemaParserCtxtPtr spctx;
911 xmlDocPtr new_doc = xmlCopyDoc(doc, 1), xsd_doc = XDR_to_XSD_doc(doc, nsURI);
912
913 link_datatypes(xsd_doc);
914
915 entry->type = CacheEntryType_XDR;
916 entry->ref = 0;
917 spctx = xmlSchemaNewDocParserCtxt(xsd_doc);
918
919 if ((entry->schema = Schema_parse(spctx)))
920 {
921 entry->doc = new_doc;
922 xmldoc_init(entry->schema->doc, version);
923 xmldoc_init(entry->doc, version);
924 xmldoc_add_ref(entry->doc);
925 xmldoc_add_ref(entry->schema->doc);
926 }
927 else
928 {
929 FIXME("failed to parse doc\n");
930 xmlFreeDoc(new_doc);
931 xmlFreeDoc(xsd_doc);
933 entry = NULL;
934 }
935 xmlSchemaFreeParserCtxt(spctx);
936
937 return entry;
938}
939
940static cache_entry* cache_entry_from_url(VARIANT url, xmlChar const* nsURI, MSXML_VERSION version)
941{
943 IXMLDOMDocument3* domdoc = NULL;
944 xmlDocPtr doc = NULL;
945 HRESULT hr = DOMDocument_create(version, (void**)&domdoc);
946 VARIANT_BOOL b = VARIANT_FALSE;
947 CacheEntryType type = CacheEntryType_Invalid;
948
949 if (hr != S_OK)
950 {
951 FIXME("failed to create domdoc\n");
952 return NULL;
953 }
954 assert(domdoc != NULL);
955 assert(V_VT(&url) == VT_BSTR);
956
957 hr = IXMLDOMDocument3_load(domdoc, url, &b);
958 if (hr != S_OK)
959 {
960 ERR("IXMLDOMDocument3_load() returned 0x%08x\n", hr);
961 if (b != VARIANT_TRUE)
962 {
963 FIXME("Failed to load doc at %s\n", debugstr_w(V_BSTR(&url)));
964 IXMLDOMDocument3_Release(domdoc);
965 return NULL;
966 }
967 }
968 doc = xmlNodePtr_from_domnode((IXMLDOMNode*)domdoc, XML_DOCUMENT_NODE)->doc;
969 type = cache_type_from_xmlDocPtr(doc);
970
971 switch (type)
972 {
973 case CacheEntryType_XSD:
974 entry = cache_entry_from_xsd_doc(doc, nsURI, version);
975 break;
976 case CacheEntryType_XDR:
977 entry = cache_entry_from_xdr_doc(doc, nsURI, version);
978 break;
979 default:
980 entry = NULL;
981 FIXME("invalid schema\n");
982 break;
983 }
984 IXMLDOMDocument3_Release(domdoc);
985
986 return entry;
987}
988
989static void cache_free(void* data, XMLHASH_CONST xmlChar* name /* ignored */)
990{
991 cache_entry_release((cache_entry*)data);
992}
993
994/* returns index or -1 if not found */
995static int cache_free_uri(schema_cache *cache, const xmlChar *uri)
996{
997 int i;
998
999 for (i = 0; i < cache->count; i++)
1000 if (xmlStrEqual(cache->uris[i], uri))
1001 {
1002 heap_free(cache->uris[i]);
1003 return i;
1004 }
1005
1006 return -1;
1007}
1008
1009static void cache_add_entry(schema_cache *cache, const xmlChar *uri, cache_entry *entry)
1010{
1011 int i;
1012
1013 /* meaning no entry found with this name */
1014 if (xmlHashRemoveEntry(cache->cache, uri, cache_free))
1015 {
1016 if (cache->count == cache->allocated)
1017 {
1018 cache->allocated *= 2;
1019 cache->uris = heap_realloc(cache->uris, cache->allocated*sizeof(xmlChar*));
1020 }
1021 i = cache->count++;
1022 }
1023 else
1024 i = cache_free_uri(cache, uri);
1025
1026 cache->uris[i] = heap_strdupxmlChar(uri);
1027 xmlHashAddEntry(cache->cache, uri, entry);
1028}
1029
1030static void cache_remove_entry(schema_cache *cache, const xmlChar *uri)
1031{
1032 /* adjust index if entry was really removed */
1033 if (xmlHashRemoveEntry(cache->cache, uri, cache_free) == 0)
1034 {
1035 int i = cache_free_uri(cache, uri);
1036 if (i == -1) return;
1037 /* shift array */
1038 if (i != --cache->count)
1039 memmove(&cache->uris[i], &cache->uris[i+1], (cache->count-i)*sizeof(xmlChar*));
1040 }
1041}
1042
1043/* This one adds all namespaces defined in document to a cache, without anything
1044 associated with uri obviously.
1045 Unfortunately namespace:: axis implementation in libxml2 differs from what we need,
1046 it uses additional node type to describe namespace definition attribute while
1047 in msxml it's expected to be a normal attribute - as a workaround document is
1048 queried at libxml2 level here. */
1049HRESULT cache_from_doc_ns(IXMLDOMSchemaCollection2 *iface, xmlnode *node)
1050{
1051 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1052 static const xmlChar query[] = "//*/namespace::*";
1053 xmlXPathObjectPtr nodeset;
1054 xmlXPathContextPtr ctxt;
1055
1056 This->read_only = 1;
1057
1058 ctxt = xmlXPathNewContext(node->node->doc);
1059
1060 nodeset = xmlXPathEvalExpression(query, ctxt);
1061 xmlXPathFreeContext(ctxt);
1062
1063 if (nodeset)
1064 {
1065 int pos = 0, len = xmlXPathNodeSetGetLength(nodeset->nodesetval);
1066
1067 while (pos < len)
1068 {
1069 xmlNodePtr node = xmlXPathNodeSetItem(nodeset->nodesetval, pos);
1070 if (node->type == XML_NAMESPACE_DECL)
1071 {
1072 static const xmlChar defns[] = "http://www.w3.org/XML/1998/namespace";
1075
1076 /* filter out default uri */
1077 if (xmlStrEqual(ns->href, defns))
1078 {
1079 pos++;
1080 continue;
1081 }
1082
1083 entry = heap_alloc(sizeof(cache_entry));
1084 entry->type = CacheEntryType_NS;
1085 entry->ref = 1;
1086 entry->schema = NULL;
1087 entry->doc = NULL;
1088
1089 cache_add_entry(This, ns->href, entry);
1090 }
1091 pos++;
1092 }
1093
1094 xmlXPathFreeObject(nodeset);
1095 }
1096
1097 return S_OK;
1098}
1099
1100static HRESULT WINAPI schema_cache_QueryInterface(IXMLDOMSchemaCollection2* iface,
1101 REFIID riid, void** ppvObject)
1102{
1103 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1104
1105 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1106
1107 if ( IsEqualIID(riid, &IID_IUnknown) ||
1109 IsEqualIID(riid, &IID_IXMLDOMSchemaCollection) ||
1110 IsEqualIID(riid, &IID_IXMLDOMSchemaCollection2) )
1111 {
1112 *ppvObject = iface;
1113 }
1114 else if(This->version == MSXML6 && IsEqualIID(riid, &CLSID_XMLSchemaCache60))
1115 {
1116 /*
1117 * Version 6 can be queried for an interface with IID equal to CLSID.
1118 * There is no public interface with that IID and returned pointer
1119 * is equal to returned IXMLDOMSchemaCollection2 iface. We assume
1120 * that it's just another way for querying IXMLDOMSchemaCollection2
1121 * interface. Office 2013 ClickToRun installer uses this.
1122 */
1123 WARN("riid CLSID_XMLSchemaCache60, returning IXMLDOMSchemaCollection2 interface.\n");
1124 *ppvObject = iface;
1125 }
1126 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
1127 {
1128 return *ppvObject ? S_OK : E_NOINTERFACE;
1129 }
1130 else if(IsEqualGUID( riid, &IID_ISupportErrorInfo ))
1131 {
1132 return node_create_supporterrorinfo(schema_cache_se_tids, ppvObject);
1133 }
1134 else
1135 {
1136 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1137 *ppvObject = NULL;
1138 return E_NOINTERFACE;
1139 }
1140
1141 IXMLDOMSchemaCollection2_AddRef(iface);
1142
1143 return S_OK;
1144}
1145
1146static ULONG WINAPI schema_cache_AddRef(IXMLDOMSchemaCollection2* iface)
1147{
1148 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1150 TRACE("(%p)->(%d)\n", This, ref);
1151 return ref;
1152}
1153
1154static ULONG WINAPI schema_cache_Release(IXMLDOMSchemaCollection2* iface)
1155{
1156 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1158 TRACE("(%p)->(%d)\n", This, ref);
1159
1160 if (ref == 0)
1161 {
1162 int i;
1163
1164 for (i = 0; i < This->count; i++)
1165 heap_free(This->uris[i]);
1166 heap_free(This->uris);
1167 xmlHashFree(This->cache, cache_free);
1168 heap_free(This);
1169 }
1170
1171 return ref;
1172}
1173
1174static HRESULT WINAPI schema_cache_GetTypeInfoCount(IXMLDOMSchemaCollection2* iface,
1175 UINT* pctinfo)
1176{
1177 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1178 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1179}
1180
1181static HRESULT WINAPI schema_cache_GetTypeInfo(IXMLDOMSchemaCollection2* iface,
1182 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1183{
1184 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1185 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
1186 iTInfo, lcid, ppTInfo);
1187}
1188
1189static HRESULT WINAPI schema_cache_GetIDsOfNames(IXMLDOMSchemaCollection2* iface,
1190 REFIID riid, LPOLESTR* rgszNames,
1191 UINT cNames, LCID lcid, DISPID* rgDispId)
1192{
1193 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1194 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
1195 riid, rgszNames, cNames, lcid, rgDispId);
1196}
1197
1198static HRESULT WINAPI schema_cache_Invoke(IXMLDOMSchemaCollection2* iface,
1199 DISPID dispIdMember, REFIID riid, LCID lcid,
1200 WORD wFlags, DISPPARAMS* pDispParams,
1201 VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
1202 UINT* puArgErr)
1203{
1204 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1205 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
1206 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1207}
1208
1209static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri, VARIANT var)
1210{
1211 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1212 xmlChar* name;
1213
1214 TRACE("(%p)->(%s %s)\n", This, debugstr_w(uri), debugstr_variant(&var));
1215
1216 if (This->read_only) return E_FAIL;
1217
1218 name = uri ? xmlchar_from_wchar(uri) : xmlchar_from_wchar(emptyW);
1219
1220 switch (V_VT(&var))
1221 {
1222 case VT_NULL:
1223 {
1224 cache_remove_entry(This, name);
1225 }
1226 break;
1227
1228 case VT_BSTR:
1229 {
1230 cache_entry* entry = cache_entry_from_url(var, name, This->version);
1231
1232 if (entry)
1233 {
1234 cache_entry_add_ref(entry);
1235 }
1236 else
1237 {
1238 heap_free(name);
1239 return E_FAIL;
1240 }
1241
1242 cache_add_entry(This, name, entry);
1243 }
1244 break;
1245
1246 case VT_DISPATCH:
1247 case VT_UNKNOWN:
1248 {
1249 xmlDocPtr doc = NULL;
1251 CacheEntryType type;
1252 IXMLDOMNode* domnode = NULL;
1253 IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IXMLDOMNode, (void**)&domnode);
1254
1255 if (domnode)
1256 {
1258
1259 IXMLDOMNode_get_nodeType(domnode, &type);
1260 switch (type)
1261 {
1262 case NODE_ELEMENT:
1263 {
1264 IXMLDOMDocument *domdoc;
1266 BSTR xml;
1267
1268 IXMLDOMNode_get_xml(domnode, &xml);
1269 DOMDocument_create(This->version, (void**)&domdoc);
1270 IXMLDOMDocument_loadXML(domdoc, xml, &b);
1271 SysFreeString(xml);
1272 doc = xmlNodePtr_from_domnode((IXMLDOMNode*)domdoc, XML_DOCUMENT_NODE)->doc;
1273 break;
1274 }
1275 default:
1276 doc = xmlNodePtr_from_domnode(domnode, XML_DOCUMENT_NODE)->doc;
1277 break;
1278 }
1279 }
1280
1281 if (!doc)
1282 {
1283 IXMLDOMNode_Release(domnode);
1284 heap_free(name);
1285 return E_INVALIDARG;
1286 }
1287 type = cache_type_from_xmlDocPtr(doc);
1288
1289 if (type == CacheEntryType_XSD)
1290 {
1291 entry = cache_entry_from_xsd_doc(doc, name, This->version);
1292 }
1293 else if (type == CacheEntryType_XDR)
1294 {
1295 entry = cache_entry_from_xdr_doc(doc, name, This->version);
1296 }
1297 else
1298 {
1299 WARN("invalid schema!\n");
1300 entry = NULL;
1301 }
1302
1303 IXMLDOMNode_Release(domnode);
1304
1305 if (entry)
1306 {
1307 cache_entry_add_ref(entry);
1308 }
1309 else
1310 {
1311 heap_free(name);
1312 return E_FAIL;
1313 }
1314
1315 cache_add_entry(This, name, entry);
1316 }
1317 break;
1318
1319 default:
1320 FIXME("arg type is not supported, %s\n", debugstr_variant(&var));
1321 heap_free(name);
1322 return E_INVALIDARG;
1323 }
1324 heap_free(name);
1325 return S_OK;
1326}
1327
1328static HRESULT WINAPI schema_cache_get(IXMLDOMSchemaCollection2* iface, BSTR uri,
1329 IXMLDOMNode** node)
1330{
1331 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1333 xmlChar* name;
1334
1335 TRACE("(%p)->(%s %p)\n", This, debugstr_w(uri), node);
1336
1337 if (This->version == MSXML6)
1338 {
1339 if (node) *node = NULL;
1340 return E_NOTIMPL;
1341 }
1342
1343 if (!node)
1344 return E_POINTER;
1345
1346 *node = NULL;
1347
1348 name = uri ? xmlchar_from_wchar(uri) : xmlchar_from_wchar(emptyW);
1349 entry = (cache_entry*) xmlHashLookup(This->cache, name);
1350 heap_free(name);
1351
1352 /* TODO: this should be read-only */
1353 if (entry && entry->doc)
1354 return get_domdoc_from_xmldoc(entry->doc, (IXMLDOMDocument3**)node);
1355
1356 return S_OK;
1357}
1358
1359static HRESULT WINAPI schema_cache_remove(IXMLDOMSchemaCollection2* iface, BSTR uri)
1360{
1361 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1362 xmlChar* name;
1363
1364 TRACE("(%p)->(%s)\n", This, debugstr_w(uri));
1365
1366 if (This->version == MSXML6) return E_NOTIMPL;
1367
1368 name = uri ? xmlchar_from_wchar(uri) : xmlchar_from_wchar(emptyW);
1369 cache_remove_entry(This, name);
1370 heap_free(name);
1371 return S_OK;
1372}
1373
1374static HRESULT WINAPI schema_cache_get_length(IXMLDOMSchemaCollection2* iface, LONG* length)
1375{
1376 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1377 TRACE("(%p)->(%p)\n", This, length);
1378
1379 if (!length)
1380 return E_POINTER;
1381
1382 *length = This->count;
1383 return S_OK;
1384}
1385
1386static HRESULT WINAPI schema_cache_get_namespaceURI(IXMLDOMSchemaCollection2* iface,
1387 LONG index, BSTR* uri)
1388{
1389 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1390
1391 TRACE("(%p)->(%i %p)\n", This, index, uri);
1392
1393 if (!uri)
1394 return E_POINTER;
1395
1396 if (This->version == MSXML6)
1397 *uri = NULL;
1398
1399 if (index >= This->count)
1400 return E_FAIL;
1401
1402 *uri = bstr_from_xmlChar(This->uris[index]);
1403 return S_OK;
1404}
1405
1406static void cache_copy(void* data, void* dest, XMLHASH_CONST xmlChar* name)
1407{
1408 schema_cache* This = (schema_cache*) dest;
1410
1411 if (xmlHashLookup(This->cache, name) == NULL)
1412 {
1413 cache_entry_add_ref(entry);
1414 cache_add_entry(This, name, entry);
1415 }
1416}
1417
1418static HRESULT WINAPI schema_cache_addCollection(IXMLDOMSchemaCollection2* iface,
1419 IXMLDOMSchemaCollection* collection)
1420{
1421 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1422 schema_cache* That;
1423
1424 TRACE("(%p)->(%p)\n", This, collection);
1425
1426 if (!collection)
1427 return E_POINTER;
1428
1429 That = unsafe_impl_from_IXMLDOMSchemaCollection(collection);
1430 if (!That)
1431 {
1432 ERR("external collection implementation\n");
1433 return E_FAIL;
1434 }
1435
1436 /* TODO: detect errors while copying & return E_FAIL */
1437 xmlHashScan(That->cache, cache_copy, This);
1438
1439 return S_OK;
1440}
1441
1442static HRESULT WINAPI schema_cache_get__newEnum(IXMLDOMSchemaCollection2* iface, IUnknown** enumv)
1443{
1444 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1445 TRACE("(%p)->(%p)\n", This, enumv);
1446 return create_enumvariant((IUnknown*)iface, TRUE, &schemacache_enumvariant, (IEnumVARIANT**)enumv);
1447}
1448
1449static HRESULT WINAPI schema_cache_validate(IXMLDOMSchemaCollection2* iface)
1450{
1451 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1452 FIXME("(%p): stub\n", This);
1453 return E_NOTIMPL;
1454}
1455
1456static HRESULT WINAPI schema_cache_put_validateOnLoad(IXMLDOMSchemaCollection2* iface,
1458{
1459 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1460 FIXME("(%p)->(%d): stub\n", This, value);
1461
1462 This->validateOnLoad = value;
1463 /* it's ok to disable it, cause we don't validate on load anyway */
1464 if (value == VARIANT_FALSE) return S_OK;
1465
1466 return E_NOTIMPL;
1467}
1468
1469static HRESULT WINAPI schema_cache_get_validateOnLoad(IXMLDOMSchemaCollection2* iface,
1471{
1472 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1473 TRACE("(%p)->(%p)\n", This, value);
1474
1475 if (!value) return E_POINTER;
1476 *value = This->validateOnLoad;
1477
1478 return S_OK;
1479}
1480
1481static HRESULT WINAPI schema_cache_getSchema(IXMLDOMSchemaCollection2* iface,
1482 BSTR namespaceURI, ISchema** schema)
1483{
1484 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1485 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(namespaceURI), schema);
1486 if (schema)
1487 *schema = NULL;
1488 return E_NOTIMPL;
1489}
1490
1491static HRESULT WINAPI schema_cache_getDeclaration(IXMLDOMSchemaCollection2* iface,
1492 IXMLDOMNode* node, ISchemaItem** item)
1493{
1494 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1495 FIXME("(%p)->(%p %p): stub\n", This, node, item);
1496 if (item)
1497 *item = NULL;
1498 return E_NOTIMPL;
1499}
1500
1501static const struct IXMLDOMSchemaCollection2Vtbl XMLDOMSchemaCollection2Vtbl =
1502{
1503 schema_cache_QueryInterface,
1504 schema_cache_AddRef,
1505 schema_cache_Release,
1506 schema_cache_GetTypeInfoCount,
1507 schema_cache_GetTypeInfo,
1508 schema_cache_GetIDsOfNames,
1509 schema_cache_Invoke,
1510 schema_cache_add,
1511 schema_cache_get,
1512 schema_cache_remove,
1513 schema_cache_get_length,
1514 schema_cache_get_namespaceURI,
1515 schema_cache_addCollection,
1516 schema_cache_get__newEnum,
1517 schema_cache_validate,
1518 schema_cache_put_validateOnLoad,
1519 schema_cache_get_validateOnLoad,
1520 schema_cache_getSchema,
1521 schema_cache_getDeclaration
1522};
1523
1524static xmlSchemaElementPtr lookup_schema_elemDecl(xmlSchemaPtr schema, xmlNodePtr node)
1525{
1526 xmlSchemaElementPtr decl = NULL;
1527 xmlChar const* nsURI = get_node_nsURI(node);
1528
1529 TRACE("(%p, %p)\n", schema, node);
1530
1531 if (xmlStrEqual(nsURI, schema->targetNamespace))
1532 decl = xmlHashLookup(schema->elemDecl, node->name);
1533
1534 if (!decl && xmlHashSize(schema->schemasImports) > 1)
1535 {
1536 FIXME("declaration not found in main schema - need to check schema imports!\n");
1537 /*xmlSchemaImportPtr import;
1538 if (nsURI == NULL)
1539 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
1540 else
1541 import = xmlHashLookup(schema->schemasImports, node->ns->href);
1542
1543 if (import != NULL)
1544 decl = xmlHashLookup(import->schema->elemDecl, node->name);*/
1545 }
1546
1547 return decl;
1548}
1549
1550static inline xmlNodePtr lookup_schema_element(xmlSchemaPtr schema, xmlNodePtr node)
1551{
1552 xmlSchemaElementPtr decl = lookup_schema_elemDecl(schema, node);
1553 while (decl != NULL && decl->refDecl != NULL)
1554 decl = decl->refDecl;
1555 return (decl != NULL)? decl->node : NULL;
1556}
1557
1558HRESULT SchemaCache_validate_tree(IXMLDOMSchemaCollection2* iface, xmlNodePtr tree)
1559{
1560 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1561 xmlSchemaPtr schema;
1562
1563 TRACE("(%p, %p)\n", This, tree);
1564
1565 if (!tree)
1566 return E_POINTER;
1567
1568 if (tree->type == XML_DOCUMENT_NODE)
1570
1571 schema = get_node_schema(This, tree);
1572 /* TODO: if the ns is not in the cache, and it's a URL,
1573 * do we try to load from that? */
1574 if (schema)
1575 return Schema_validate_tree(schema, tree);
1576 else
1577 WARN("no schema found for xmlns=%s\n", get_node_nsURI(tree));
1578
1579 return E_FAIL;
1580}
1581
1582XDR_DT SchemaCache_get_node_dt(IXMLDOMSchemaCollection2* iface, xmlNodePtr node)
1583{
1584 schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1585 xmlSchemaPtr schema = get_node_schema(This, node);
1586 XDR_DT dt = DT_INVALID;
1587
1588 TRACE("(%p, %p)\n", This, node);
1589
1590 if (node->ns && xmlStrEqual(node->ns->href, DT_nsURI))
1591 {
1592 dt = str_to_dt(node->name, -1);
1593 }
1594 else if (schema)
1595 {
1596 xmlChar* str;
1597 xmlNodePtr schema_node = lookup_schema_element(schema, node);
1598
1599 str = xmlGetNsProp(schema_node, BAD_CAST "dt", DT_nsURI);
1600 if (str)
1601 {
1602 dt = str_to_dt(str, -1);
1603 xmlFree(str);
1604 }
1605 }
1606
1607 return dt;
1608}
1609
1610static const tid_t schemacache_iface_tids[] = {
1612 0
1613};
1614
1615static dispex_static_data_t schemacache_dispex = {
1616 NULL,
1618 NULL,
1619 schemacache_iface_tids
1620};
1621
1623{
1624 schema_cache* This = heap_alloc(sizeof(schema_cache));
1625 if (!This)
1626 return E_OUTOFMEMORY;
1627
1628 TRACE("(%d %p)\n", version, obj);
1629
1630 This->IXMLDOMSchemaCollection2_iface.lpVtbl = &XMLDOMSchemaCollection2Vtbl;
1631 This->cache = xmlHashCreate(DEFAULT_HASHTABLE_SIZE);
1632 This->allocated = 10;
1633 This->count = 0;
1634 This->uris = heap_alloc(This->allocated*sizeof(xmlChar*));
1635 This->ref = 1;
1636 This->version = version;
1637 This->validateOnLoad = VARIANT_TRUE;
1638 This->read_only = 0;
1639 init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMSchemaCollection2_iface, &schemacache_dispex);
1640
1641 *obj = &This->IXMLDOMSchemaCollection2_iface;
1642 return S_OK;
1643}
1644
1645#else
1646
1648{
1649 MESSAGE("This program tried to use a SchemaCache object, but\n"
1650 "libxml2 support was not present at compile time.\n");
1651 return E_NOTIMPL;
1652}
1653
1654#endif
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:71
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define msg(x)
Definition: auth_time.c:54
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
struct _root root
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
content
Definition: atl_ax.c:994
#define DT_STRING
Definition: datetime.c:117
WCHAR OLECHAR
Definition: compat.h:2292
OLECHAR * BSTR
Definition: compat.h:2293
short VARIANT_BOOL
Definition: compat.h:2290
@ VT_BSTR
Definition: compat.h:2303
@ VT_NULL
Definition: compat.h:2296
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_DISPATCH
Definition: compat.h:2304
#define lstrlenW
Definition: compat.h:750
static const WCHAR version[]
Definition: asmname.c:66
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj)
Definition: domdoc.c:3727
HINSTANCE MSXML_hInstance
Definition: main.c:62
HRESULT SchemaCache_create(MSXML_VERSION version, void **obj)
Definition: schema.c:1647
#define assert(x)
Definition: debug.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint index
Definition: glext.h:6031
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum GLsizei len
Definition: glext.h:6722
GLenum GLenum GLenum input
Definition: glext.h:9031
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static const WCHAR emptyW[]
Definition: navigate.c:40
tid_t
Definition: ieframe.h:311
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
uint32_t entry
Definition: isohybrid.c:63
HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype)
Definition: dispex.c:919
#define b
Definition: ke_i.h:79
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
int WINAPI lstrcmpA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:18
const WCHAR * schema
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define MESSAGE
Definition: options.h:86
static const WCHAR url[]
Definition: encode.c:1432
const char * var
Definition: shader.c:5666
static const char * debugstr_variant(const VARIANT *var)
Definition: container.c:46
static char * dest
Definition: rtl.c:135
static LPOLESTR
Definition: stg_prop.c:27
static ICollection collection
Definition: typelib.c:184
static VARIANTARG static DISPID
Definition: ordinal.c:52
const char * uri
Definition: sec_mgr.c:1588
static HWND child
Definition: cursoricon.c:298
static ATOM item
Definition: dde.c:856
BOOL dispex_query_interface(DispatchEx *This, REFIID riid, void **ppv)
Definition: dispex.c:1656
MSXML_VERSION
Definition: msxml_private.h:34
@ MSXML6
Definition: msxml_private.h:40
@ IXMLDOMSchemaCollection2_tid
Definition: msxml_private.h:63
@ NULL_tid
Definition: msxml_private.h:45
@ IXMLDOMSchemaCollection_tid
Definition: msxml_private.h:62
enum _XDR_DT XDR_DT
@ DT_I4
@ DT_NMTOKEN
@ DT_ID
@ DT_TIME_TZ
@ DT_NUMBER
@ DT_FIXED_14_4
@ DT_NMTOKENS
@ DT_URI
@ DT_DATE_TZ
@ DT_INVALID
Definition: msxml_private.h:94
@ DT_UI4
@ DT_R8
@ DT_DATETIME_TZ
@ DT_ENTITIES
@ DT_FLOAT
@ DT_DATETIME
@ DT_BIN_HEX
Definition: msxml_private.h:96
@ DT_I1
@ DT_UI8
@ DT_DATE
Definition: msxml_private.h:99
@ LAST_DT
@ DT_UI2
@ DT_BIN_BASE64
Definition: msxml_private.h:95
@ DT_I2
@ DT_ENTITY
@ DT_ENUMERATION
@ DT_IDREF
@ DT_R4
@ DT_UI1
@ DT_BOOLEAN
Definition: msxml_private.h:97
@ DT_CHAR
Definition: msxml_private.h:98
@ DT_TIME
@ DT_IDREFS
@ DT_NOTATION
@ DT_I8
@ DT_INT
@ DT_UUID
unsigned int UINT
Definition: ndis.h:50
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
#define V_UNKNOWN(A)
Definition: oleauto.h:281
#define V_VT(A)
Definition: oleauto.h:211
#define V_BSTR(A)
Definition: oleauto.h:226
const GUID IID_IDispatch
XMLPUBFUN xmlParserInputPtr XMLCALL xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer)
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
static unsigned __int64 next
Definition: rand_nt.c:6
#define err(...)
const WCHAR * str
#define ID
Definition: ruserpass.c:36
DWORD LCID
Definition: nls.h:13
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:322
XMLPUBFUN void *XMLCALL xmlHashLookup(xmlHashTablePtr table, const xmlChar *name)
Definition: hash.c:461
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate(int size)
Definition: hash.c:176
XMLPUBFUN int XMLCALL xmlHashSize(xmlHashTablePtr table)
Definition: hash.c:1034
XMLPUBFUN int XMLCALL xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata)
Definition: hash.c:389
XMLPUBFUN int XMLCALL xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, xmlHashDeallocator f)
Definition: hash.c:1052
XMLPUBFUN void XMLCALL xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data)
Definition: hash.c:859
XMLPUBFUN xmlExternalEntityLoader XMLCALL xmlGetExternalEntityLoader(void)
XMLPUBFUN void XMLCALL xmlSetExternalEntityLoader(xmlExternalEntityLoader f)
xmlParserInputPtr(* xmlExternalEntityLoader)(const char *URL, const char *ID, xmlParserCtxtPtr context)
Definition: parser.h:802
XMLPUBFUN xmlNodePtr XMLCALL xmlDocGetRootElement(const xmlDoc *doc)
XMLPUBFUN void XMLCALL xmlFreeDoc(xmlDocPtr cur)
XMLPUBFUN xmlDocPtr XMLCALL xmlNewDoc(const xmlChar *version)
XMLPUBFUN xmlChar *XMLCALL xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace)
XMLPUBFUN void XMLCALL xmlSetNs(xmlNodePtr node, xmlNsPtr ns)
@ XML_DOCUMENT_NODE
Definition: tree.h:168
@ XML_NAMESPACE_DECL
Definition: tree.h:177
xmlNs * xmlNsPtr
Definition: tree.h:388
XMLPUBFUN xmlNsPtr XMLCALL xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix)
void parser_error(const char *s)
Definition: utils.c:80
int parser_warning(const char *s,...)
Definition: utils.c:94
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
Definition: tree.h:551
struct _xmlDoc * doc
Definition: tree.h:560
Definition: tree.h:489
Definition: tree.h:389
Definition: svc_auth_des.c:77
Definition: cache.c:49
Definition: _hash_fun.h:40
Definition: name.c:39
Definition: mxnamespace.c:45
Definition: send.c:48
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
Definition: dlist.c:348
Definition: pdh_main.c:94
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:531
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD _Outptr_opt_ void ** ppvObject
Definition: wincrypt.h:6082
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_NOINTERFACE
Definition: winerror.h:2364
#define E_POINTER
Definition: winerror.h:2365
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36
enum tagDOMNodeType DOMNodeType
@ NODE_ELEMENT
Definition: xmldom.idl:53
__wchar_t WCHAR
Definition: xmlstorage.h:180
XMLPUBFUN int XMLCALL xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:275
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:426
unsigned char xmlChar
Definition: xmlstring.h:28
#define LIBXML_DOTTED_VERSION
Definition: xmlversion.h:32
unsigned char BYTE
Definition: xxhash.c:193