ReactOS  0.4.14-dev-998-g623dd26
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>
32 # include <libxml/schemasInternals.h>
33 # include <libxml/hash.h>
34 # include <libxml/parser.h>
35 # include <libxml/parserInternals.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 
69 xmlDocPtr XDR_to_XSD_doc(xmlDocPtr xdr_doc, xmlChar const* nsURI);
70 
71 static const xmlChar XSD_schema[] = "schema";
72 static const xmlChar XSD_nsURI[] = "http://www.w3.org/2001/XMLSchema";
73 static const xmlChar XDR_schema[] = "Schema";
74 static const xmlChar XDR_nsURI[] = "urn:schemas-microsoft-com:xml-data";
75 static const xmlChar DT_nsURI[] = "urn:schemas-microsoft-com:datatypes";
76 
77 static xmlChar * datatypes_src;
78 static int datatypes_len;
79 static HGLOBAL datatypes_handle;
80 static HRSRC datatypes_rsrc;
81 static xmlSchemaPtr datatypes_schema;
82 
83 static 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  */
94 typedef enum {
95  CacheEntryType_Invalid,
96  CacheEntryType_XDR,
97  CacheEntryType_XSD,
98  CacheEntryType_NS
99 } CacheEntryType;
100 
101 typedef 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 
117 typedef struct
118 {
119  CacheEntryType type;
120  xmlSchemaPtr schema;
121  xmlDocPtr doc;
122  LONG ref;
123 } cache_entry;
124 
125 static const tid_t schema_cache_se_tids[] = {
128  NULL_tid
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 
138 static const xmlChar DT_bin_base64[] = "bin.base64";
139 static const xmlChar DT_bin_hex[] = "bin.hex";
140 static const xmlChar DT_boolean[] = "boolean";
141 static const xmlChar DT_char[] = "char";
142 static const xmlChar DT_date[] = "date";
143 static const xmlChar DT_date_tz[] = "date.tz";
144 static const xmlChar DT_dateTime[] = "dateTime";
145 static const xmlChar DT_dateTime_tz[] = "dateTime.tz";
146 static const xmlChar DT_entity[] = "entity";
147 static const xmlChar DT_entities[] = "entities";
148 static const xmlChar DT_enumeration[] = "enumeration";
149 static const xmlChar DT_fixed_14_4[] = "fixed.14.4";
150 static const xmlChar DT_float[] = "float";
151 static const xmlChar DT_i1[] = "i1";
152 static const xmlChar DT_i2[] = "i2";
153 static const xmlChar DT_i4[] = "i4";
154 static const xmlChar DT_i8[] = "i8";
155 static const xmlChar DT_id[] = "id";
156 static const xmlChar DT_idref[] = "idref";
157 static const xmlChar DT_idrefs[] = "idrefs";
158 static const xmlChar DT_int[] = "int";
159 static const xmlChar DT_nmtoken[] = "nmtoken";
160 static const xmlChar DT_nmtokens[] = "nmtokens";
161 static const xmlChar DT_notation[] = "notation";
162 static const xmlChar DT_number[] = "number";
163 static const xmlChar DT_r4[] = "r4";
164 static const xmlChar DT_r8[] = "r8";
165 static const xmlChar DT_string[] = "string";
166 static const xmlChar DT_time[] = "time";
167 static const xmlChar DT_time_tz[] = "time.tz";
168 static const xmlChar DT_ui1[] = "ui1";
169 static const xmlChar DT_ui2[] = "ui2";
170 static const xmlChar DT_ui4[] = "ui4";
171 static const xmlChar DT_ui8[] = "ui8";
172 static const xmlChar DT_uri[] = "uri";
173 static const xmlChar DT_uuid[] = "uuid";
174 
175 static const OLECHAR wDT_bin_base64[] = {'b','i','n','.','b','a','s','e','6','4',0};
176 static const OLECHAR wDT_bin_hex[] = {'b','i','n','.','h','e','x',0};
177 static const OLECHAR wDT_boolean[] = {'b','o','o','l','e','a','n',0};
178 static const OLECHAR wDT_char[] = {'c','h','a','r',0};
179 static const OLECHAR wDT_date[] = {'d','a','t','e',0};
180 static const OLECHAR wDT_date_tz[] = {'d','a','t','e','.','t','z',0};
181 static const OLECHAR wDT_dateTime[] = {'d','a','t','e','T','i','m','e',0};
182 static const OLECHAR wDT_dateTime_tz[] = {'d','a','t','e','T','i','m','e','.','t','z',0};
183 static const OLECHAR wDT_entity[] = {'e','n','t','i','t','y',0};
184 static const OLECHAR wDT_entities[] = {'e','n','t','i','t','i','e','s',0};
185 static const OLECHAR wDT_enumeration[] = {'e','n','u','m','e','r','a','t','i','o','n',0};
186 static const OLECHAR wDT_fixed_14_4[] = {'f','i','x','e','d','.','1','4','.','4',0};
187 static const OLECHAR wDT_float[] = {'f','l','o','a','t',0};
188 static const OLECHAR wDT_i1[] = {'i','1',0};
189 static const OLECHAR wDT_i2[] = {'i','2',0};
190 static const OLECHAR wDT_i4[] = {'i','4',0};
191 static const OLECHAR wDT_i8[] = {'i','8',0};
192 static const OLECHAR wDT_id[] = {'i','d',0};
193 static const OLECHAR wDT_idref[] = {'i','d','r','e','f',0};
194 static const OLECHAR wDT_idrefs[] = {'i','d','r','e','f','s',0};
195 static const OLECHAR wDT_int[] = {'i','n','t',0};
196 static const OLECHAR wDT_nmtoken[] = {'n','m','t','o','k','e','n',0};
197 static const OLECHAR wDT_nmtokens[] = {'n','m','t','o','k','e','n','s',0};
198 static const OLECHAR wDT_notation[] = {'n','o','t','a','t','i','o','n',0};
199 static const OLECHAR wDT_number[] = {'n','u','m','b','e','r',0};
200 static const OLECHAR wDT_r4[] = {'r','4',0};
201 static const OLECHAR wDT_r8[] = {'r','8',0};
202 static const OLECHAR wDT_string[] = {'s','t','r','i','n','g',0};
203 static const OLECHAR wDT_time[] = {'t','i','m','e',0};
204 static const OLECHAR wDT_time_tz[] = {'t','i','m','e','.','t','z',0};
205 static const OLECHAR wDT_ui1[] = {'u','i','1',0};
206 static const OLECHAR wDT_ui2[] = {'u','i','2',0};
207 static const OLECHAR wDT_ui4[] = {'u','i','4',0};
208 static const OLECHAR wDT_ui8[] = {'u','i','8',0};
209 static const OLECHAR wDT_uri[] = {'u','r','i',0};
210 static const OLECHAR wDT_uuid[] = {'u','u','i','d',0};
211 
212 static 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 
242 static 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 
250 static 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
259 static void parser_serror(void* ctx, xmlErrorPtr err)
260 {
261  LIBXML2_CALLBACK_SERROR(Schema_parse, err);
262 }
263 #endif
264 
265 static 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 
277 static 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 
285 static 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
294 static void validate_serror(void* ctx, xmlErrorPtr err)
295 {
296  LIBXML2_CALLBACK_SERROR(Schema_validate_tree, err);
297 }
298 #endif
299 
300 static 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 
306 static const struct enumvariant_funcs schemacache_enumvariant = {
307  schema_cache_get_item,
308  NULL
309 };
310 
311 static 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 
334 static 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 
377 static 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 
420 static 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 
460 static 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 
500 static 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,
521  DT_ENTITIES,
522  DT_UUID,
523  -1, -1,
524  DT_TIME_TZ,
525  -1,
526  DT_DATE,
527  -1,
528  DT_NUMBER,
529  DT_BIN_HEX,
530  DT_DATETIME,
531  -1,
532  DT_IDREF,
533  DT_IDREFS,
534  DT_BOOLEAN,
535  -1, -1, -1,
536  DT_STRING,
537  DT_NMTOKEN,
538  DT_NMTOKENS,
539  -1,
541  -1,
542  DT_I2,
543  DT_UI2,
544  -1, -1, -1,
545  DT_DATE_TZ,
546  DT_NOTATION,
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 
562 XDR_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 
576 XDR_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 
590 xmlChar 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 
598 OLECHAR 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 
606 const char* debugstr_dt(XDR_DT dt)
607 {
608  return debugstr_a(dt != DT_INVALID ? (const char*)DT_string_table[dt] : NULL);
609 }
610 
611 HRESULT 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 
693 static inline xmlChar const* get_node_nsURI(xmlNodePtr node)
694 {
695  return (node->ns != NULL)? node->ns->href : NULL;
696 }
697 
698 static 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 
704 static 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 
710 static xmlExternalEntityLoader _external_entity_loader;
711 
712 static 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 
738 void 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 
769 void schemasCleanup(void)
770 {
771  xmlSchemaFree(datatypes_schema);
772  heap_free(datatypes_src);
773  xmlSetExternalEntityLoader(_external_entity_loader);
774 }
775 
776 static LONG cache_entry_add_ref(cache_entry* entry)
777 {
779  TRACE("(%p)->(%d)\n", entry, ref);
780  return ref;
781 }
782 
783 static 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 
804  heap_free(entry);
805  }
806  return ref;
807 }
808 
809 static const struct IXMLDOMSchemaCollection2Vtbl XMLDOMSchemaCollection2Vtbl;
810 
811 static inline schema_cache* impl_from_IXMLDOMSchemaCollection2(IXMLDOMSchemaCollection2* iface)
812 {
813  return CONTAINING_RECORD(iface, schema_cache, IXMLDOMSchemaCollection2_iface);
814 }
815 
816 static inline schema_cache* impl_from_IXMLDOMSchemaCollection(IXMLDOMSchemaCollection* iface)
817 {
818  return CONTAINING_RECORD((IXMLDOMSchemaCollection2 *)iface, schema_cache, IXMLDOMSchemaCollection2_iface);
819 }
820 
821 static inline schema_cache* unsafe_impl_from_IXMLDOMSchemaCollection(IXMLDOMSchemaCollection *iface)
822 {
823  return iface->lpVtbl == (void*)&XMLDOMSchemaCollection2Vtbl ? impl_from_IXMLDOMSchemaCollection(iface) : NULL;
824 }
825 
826 static inline CacheEntryType cache_type_from_xmlDocPtr(xmlDocPtr schema)
827 {
828  xmlNodePtr root = NULL;
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 
848 static 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 
876 static 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);
900  heap_free(entry);
901  entry = NULL;
902  }
903  xmlSchemaFreeParserCtxt(spctx);
904  return entry;
905 }
906 
907 static 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);
932  heap_free(entry);
933  entry = NULL;
934  }
935  xmlSchemaFreeParserCtxt(spctx);
936 
937  return entry;
938 }
939 
940 static 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 
989 static 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 */
995 static 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 
1009 static 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 
1030 static 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. */
1049 HRESULT 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";
1073  xmlNsPtr ns = (xmlNsPtr)node;
1074  cache_entry *entry;
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 
1100 static 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 
1146 static ULONG WINAPI schema_cache_AddRef(IXMLDOMSchemaCollection2* iface)
1147 {
1148  schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1149  LONG ref = InterlockedIncrement(&This->ref);
1150  TRACE("(%p)->(%d)\n", This, ref);
1151  return ref;
1152 }
1153 
1154 static ULONG WINAPI schema_cache_Release(IXMLDOMSchemaCollection2* iface)
1155 {
1156  schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1157  LONG ref = InterlockedDecrement(&This->ref);
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 
1174 static 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 
1181 static 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 
1189 static 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 
1198 static 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 
1209 static 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;
1250  cache_entry* entry;
1251  CacheEntryType type;
1252  IXMLDOMNode* domnode = NULL;
1253  IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IXMLDOMNode, (void**)&domnode);
1254 
1255  if (domnode)
1256  {
1257  DOMNodeType type;
1258 
1259  IXMLDOMNode_get_nodeType(domnode, &type);
1260  switch (type)
1261  {
1262  case NODE_ELEMENT:
1263  {
1264  IXMLDOMDocument *domdoc;
1265  VARIANT_BOOL b;
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 
1328 static HRESULT WINAPI schema_cache_get(IXMLDOMSchemaCollection2* iface, BSTR uri,
1329  IXMLDOMNode** node)
1330 {
1331  schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
1332  cache_entry* entry;
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 
1359 static 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 
1374 static 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 
1386 static 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 
1406 static 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 
1418 static 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 
1442 static 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 
1449 static 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 
1456 static 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 
1469 static 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 
1481 static 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 
1491 static 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 
1501 static 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 
1524 static 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 
1550 static 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 
1558 HRESULT 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)
1569  tree = xmlDocGetRootElement(tree->doc);
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 
1582 XDR_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 
1610 static const tid_t schemacache_iface_tids[] = {
1612  0
1613 };
1614 
1615 static 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
Definition: cache.c:48
WCHAR OLECHAR
Definition: compat.h:1941
XMLPUBFUN int XMLCALL xmlHashSize(xmlHashTablePtr table)
Definition: hash.c:1032
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
XMLPUBFUN int XMLCALL xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, xmlHashDeallocator f)
Definition: hash.c:1050
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
XMLPUBFUN void XMLCALL xmlSetExternalEntityLoader(xmlExternalEntityLoader f)
#define E_NOINTERFACE
Definition: winerror.h:2364
static int parser_error(parser_ctx_t *, const char *)
Definition: parser.tab.c:4263
XMLPUBFUN void XMLCALL xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data)
Definition: hash.c:857
HRESULT hr
Definition: shlfolder.c:183
#define MESSAGE
Definition: options.h:86
XMLPUBFUN xmlParserInputPtr XMLCALL xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer)
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
const char * uri
Definition: sec_mgr.c:1594
REFIID riid
Definition: precomp.h:44
Definition: tree.h:389
GLuint GLuint GLsizei count
Definition: gl.h:1545
tid_t
Definition: ieframe.h:311
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:422
struct _root root
#define WARN(fmt,...)
Definition: debug.h:111
xmlNs * xmlNsPtr
Definition: tree.h:388
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
int WINAPI lstrcmpA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:18
#define assert(x)
Definition: debug.h:53
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
XMLPUBFUN int XMLCALL xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata)
Definition: hash.c:387
XMLPUBFUN xmlExternalEntityLoader XMLCALL xmlGetExternalEntityLoader(void)
DWORD LCID
Definition: nls.h:13
OLECHAR * BSTR
Definition: compat.h:1942
Definition: svc_auth_des.c:77
static LPOLESTR
Definition: stg_prop.c:27
#define lstrlenW
Definition: compat.h:415
#define E_FAIL
Definition: ddrawi.h:102
short VARIANT_BOOL
Definition: compat.h:1939
Definition: send.c:47
static HWND child
Definition: cursoricon.c:298
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:70
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
struct _xmlDoc * doc
Definition: tree.h:560
struct node node
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
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define va_end(ap)
Definition: acmsvcex.h:90
int hash
Definition: main.c:58
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:320
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define debugstr_w
Definition: kernel32.h:32
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:110
content
Definition: atl_ax.c:993
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:66
char * va_list
Definition: acmsvcex.h:78
#define BAD_CAST
Definition: xmlstring.h:35
GLuint index
Definition: glext.h:6031
#define LIBXML_DOTTED_VERSION
Definition: xmlversion.h:32
#define debugstr_guid
Definition: kernel32.h:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define b
Definition: ke_i.h:79
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define debugstr_a
Definition: kernel32.h:31
LONG HRESULT
Definition: typedefs.h:78
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static const WCHAR url[]
Definition: encode.c:1432
const GUID IID_IUnknown
#define WINAPI
Definition: msvc.h:6
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
XMLPUBFUN void XMLCALL xmlFreeDoc(xmlDocPtr cur)
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:250
XMLPUBFUN xmlChar *XMLCALL xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate(int size)
Definition: hash.c:174
Definition: tree.h:489
const GUID IID_IDispatch
Definition: mxnamespace.c:44
#define InterlockedDecrement
Definition: armddk.h:52
static IOleCache * cache
Definition: ole2.c:75
#define V_VT(A)
Definition: oleauto.h:211
uint32_t entry
Definition: isohybrid.c:63
unsigned char xmlChar
Definition: xmlstring.h:28
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
REFIID LPVOID * ppvObject
Definition: precomp.h:44
#define ID
Definition: ruserpass.c:36
MSXML_VERSION
Definition: msxml_private.h:34
#define err(...)
#define V_UNKNOWN(A)
Definition: oleauto.h:281
GLsizei const GLfloat * value
Definition: glext.h:6069
#define V_BSTR(A)
Definition: oleauto.h:226
XMLPUBFUN xmlNsPtr XMLCALL xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix)
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:534
#define ERR(fmt,...)
Definition: debug.h:109
struct stdole::EXCEPINFO EXCEPINFO
static const char * debugstr_variant(const VARIANT *var)
Definition: container.c:46
static VARIANTARG static DISPID
Definition: ordinal.c:49
#define S_OK
Definition: intsafe.h:59
static unsigned __int64 next
Definition: rand_nt.c:6
#define InterlockedIncrement
Definition: armddk.h:53
static ATOM item
Definition: dde.c:856
GLenum GLenum GLenum input
Definition: glext.h:9031
const GLdouble * v
Definition: gl.h:2040
static const WCHAR emptyW[]
Definition: navigate.c:40
BOOL dispex_query_interface(DispatchEx *This, REFIID riid, void **ppv)
Definition: dispex.c:1656
enum _XDR_DT XDR_DT
static ICollection collection
Definition: typelib.c:184
#define E_NOTIMPL
Definition: ddrawi.h:99
#define va_start(ap, A)
Definition: acmsvcex.h:91
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
const WCHAR * schema
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype)
Definition: dispex.c:919
Definition: tree.h:551
HINSTANCE MSXML_hInstance
Definition: main.c:62
#define msg(x)
Definition: auth_time.c:54
xmlParserInputPtr(* xmlExternalEntityLoader)(const char *URL, const char *ID, xmlParserCtxtPtr context)
Definition: parser.h:802
Definition: name.c:38
void int int ULONGLONG int va_list * ap
Definition: winesup.h:32
struct stdole::DISPPARAMS DISPPARAMS
XMLPUBFUN xmlNodePtr XMLCALL xmlDocGetRootElement(const xmlDoc *doc)
XMLPUBFUN void XMLCALL xmlSetNs(xmlNodePtr node, xmlNsPtr ns)
unsigned int ULONG
Definition: retypes.h:1
XMLPUBFUN void *XMLCALL xmlHashLookup(xmlHashTablePtr table, const xmlChar *name)
Definition: hash.c:459
HRESULT SchemaCache_create(MSXML_VERSION version, void **obj)
Definition: schema.c:1647
static char * dest
Definition: rtl.c:135
__MSXML_DOMNODETYPE_DEFINED enum tagDOMNodeType DOMNodeType
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:157
#define E_POINTER
Definition: winerror.h:2365
Definition: _hash_fun.h:40
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
XMLPUBFUN xmlDocPtr XMLCALL xmlNewDoc(const xmlChar *version)
XMLPUBFUN int XMLCALL xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:271
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
int parser_warning(const char *s,...)
Definition: utils.c:94
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
Definition: dlist.c:348
HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj)
Definition: domdoc.c:3727
GLuint const GLchar * name
Definition: glext.h:6031