Release 1.5.29.
[wine] / dlls / xmllite / reader.c
1 /*
2  * IXmlReader implementation
3  *
4  * Copyright 2010, 2012-2013 Nikolay Sivov
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22
23 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "initguid.h"
27 #include "objbase.h"
28 #include "xmllite.h"
29 #include "xmllite_private.h"
30
31 #include "wine/debug.h"
32 #include "wine/list.h"
33 #include "wine/unicode.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(xmllite);
36
37 /* not defined in public headers */
38 DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
39
40 typedef enum
41 {
42     XmlEncoding_UTF16,
43     XmlEncoding_UTF8,
44     XmlEncoding_Unknown
45 } xml_encoding;
46
47 typedef enum
48 {
49     XmlReadInState_Initial,
50     XmlReadInState_XmlDecl,
51     XmlReadInState_Misc_DTD,
52     XmlReadInState_DTD,
53     XmlReadInState_DTD_Misc,
54     XmlReadInState_Element,
55     XmlReadInState_Content,
56     XmlReadInState_MiscEnd
57 } XmlReaderInternalState;
58
59 /* This state denotes where parsing was interrupted by input problem.
60    Reader resumes parsing using this information. */
61 typedef enum
62 {
63     XmlReadResumeState_Initial,
64     XmlReadResumeState_PITarget,
65     XmlReadResumeState_PIBody,
66     XmlReadResumeState_CDATA,
67     XmlReadResumeState_Comment,
68     XmlReadResumeState_STag
69 } XmlReaderResumeState;
70
71 /* saved pointer index to resume from particular input position */
72 typedef enum
73 {
74     XmlReadResume_Name,  /* PITarget, name for NCName, prefix for QName */
75     XmlReadResume_Local, /* local for QName */
76     XmlReadResume_Body,  /* PI body, comment text, CDATA text */
77     XmlReadResume_Last
78 } XmlReaderResume;
79
80 typedef enum
81 {
82     StringValue_LocalName,
83     StringValue_QualifiedName,
84     StringValue_Value,
85     StringValue_Last
86 } XmlReaderStringValue;
87
88 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0};
89 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
90
91 static const WCHAR dblquoteW[] = {'\"',0};
92 static const WCHAR quoteW[] = {'\'',0};
93 static const WCHAR ltW[] = {'<',0};
94 static const WCHAR gtW[] = {'>',0};
95 static const WCHAR commentW[] = {'<','!','-','-',0};
96 static const WCHAR piW[] = {'<','?',0};
97
98 struct xml_encoding_data
99 {
100     const WCHAR *name;
101     xml_encoding enc;
102     UINT cp;
103 };
104
105 static const struct xml_encoding_data xml_encoding_map[] = {
106     { utf16W, XmlEncoding_UTF16, ~0 },
107     { utf8W,  XmlEncoding_UTF8,  CP_UTF8 }
108 };
109
110 typedef struct
111 {
112     char *data;
113     char *cur;
114     unsigned int allocated;
115     unsigned int written;
116 } encoded_buffer;
117
118 typedef struct input_buffer input_buffer;
119
120 typedef struct
121 {
122     IXmlReaderInput IXmlReaderInput_iface;
123     LONG ref;
124     /* reference passed on IXmlReaderInput creation, is kept when input is created */
125     IUnknown *input;
126     IMalloc *imalloc;
127     xml_encoding encoding;
128     BOOL hint;
129     WCHAR *baseuri;
130     /* stream reference set after SetInput() call from reader,
131        stored as sequential stream, cause currently
132        optimizations possible with IStream aren't implemented */
133     ISequentialStream *stream;
134     input_buffer *buffer;
135     unsigned int pending : 1;
136 } xmlreaderinput;
137
138 static const struct IUnknownVtbl xmlreaderinputvtbl;
139
140 /* Structure to hold parsed string of specific length.
141
142    Reader stores node value as 'start' pointer, on request
143    a null-terminated version of it is allocated.
144
145    To init a strval variable use reader_init_strval(),
146    to set strval as a reader value use reader_set_strval().
147  */
148 typedef struct
149 {
150     WCHAR *start; /* input position where value starts */
151     UINT len;     /* length in WCHARs, altered after ReadValueChunk */
152     WCHAR *str;   /* allocated null-terminated string */
153 } strval;
154
155 static WCHAR emptyW[] = {0};
156 static const strval strval_empty = {emptyW, 0, emptyW};
157
158 struct attribute
159 {
160     struct list entry;
161     strval localname;
162     strval value;
163 };
164
165 struct element
166 {
167     struct list entry;
168     strval qname;
169 };
170
171 typedef struct
172 {
173     IXmlReader IXmlReader_iface;
174     LONG ref;
175     xmlreaderinput *input;
176     IMalloc *imalloc;
177     XmlReadState state;
178     XmlReaderInternalState instate;
179     XmlReaderResumeState resumestate;
180     XmlNodeType nodetype;
181     DtdProcessing dtdmode;
182     UINT line, pos;           /* reader position in XML stream */
183     struct list attrs; /* attributes list for current node */
184     struct attribute *attr; /* current attribute */
185     UINT attr_count;
186     struct list elements;
187     strval strvalues[StringValue_Last];
188     UINT depth;
189     WCHAR *resume[XmlReadResume_Last]; /* pointers used to resume reader */
190 } xmlreader;
191
192 struct input_buffer
193 {
194     encoded_buffer utf16;
195     encoded_buffer encoded;
196     UINT code_page;
197     xmlreaderinput *input;
198 };
199
200 static inline xmlreader *impl_from_IXmlReader(IXmlReader *iface)
201 {
202     return CONTAINING_RECORD(iface, xmlreader, IXmlReader_iface);
203 }
204
205 static inline xmlreaderinput *impl_from_IXmlReaderInput(IXmlReaderInput *iface)
206 {
207     return CONTAINING_RECORD(iface, xmlreaderinput, IXmlReaderInput_iface);
208 }
209
210 static inline void *m_alloc(IMalloc *imalloc, size_t len)
211 {
212     if (imalloc)
213         return IMalloc_Alloc(imalloc, len);
214     else
215         return heap_alloc(len);
216 }
217
218 static inline void *m_realloc(IMalloc *imalloc, void *mem, size_t len)
219 {
220     if (imalloc)
221         return IMalloc_Realloc(imalloc, mem, len);
222     else
223         return heap_realloc(mem, len);
224 }
225
226 static inline void m_free(IMalloc *imalloc, void *mem)
227 {
228     if (imalloc)
229         IMalloc_Free(imalloc, mem);
230     else
231         heap_free(mem);
232 }
233
234 /* reader memory allocation functions */
235 static inline void *reader_alloc(xmlreader *reader, size_t len)
236 {
237     return m_alloc(reader->imalloc, len);
238 }
239
240 static inline void reader_free(xmlreader *reader, void *mem)
241 {
242     m_free(reader->imalloc, mem);
243 }
244
245 static HRESULT reader_strvaldup(xmlreader *reader, const strval *src, strval *dest)
246 {
247     *dest = *src;
248
249     if (src->str != strval_empty.str)
250     {
251         dest->str = reader_alloc(reader, (dest->len+1)*sizeof(WCHAR));
252         if (!dest->str) return E_OUTOFMEMORY;
253         memcpy(dest->str, src->str, dest->len*sizeof(WCHAR));
254         dest->str[dest->len] = 0;
255     }
256
257     return S_OK;
258 }
259
260 /* reader input memory allocation functions */
261 static inline void *readerinput_alloc(xmlreaderinput *input, size_t len)
262 {
263     return m_alloc(input->imalloc, len);
264 }
265
266 static inline void *readerinput_realloc(xmlreaderinput *input, void *mem, size_t len)
267 {
268     return m_realloc(input->imalloc, mem, len);
269 }
270
271 static inline void readerinput_free(xmlreaderinput *input, void *mem)
272 {
273     m_free(input->imalloc, mem);
274 }
275
276 static inline WCHAR *readerinput_strdupW(xmlreaderinput *input, const WCHAR *str)
277 {
278     LPWSTR ret = NULL;
279
280     if(str) {
281         DWORD size;
282
283         size = (strlenW(str)+1)*sizeof(WCHAR);
284         ret = readerinput_alloc(input, size);
285         if (ret) memcpy(ret, str, size);
286     }
287
288     return ret;
289 }
290
291 static void reader_clear_attrs(xmlreader *reader)
292 {
293     struct attribute *attr, *attr2;
294     LIST_FOR_EACH_ENTRY_SAFE(attr, attr2, &reader->attrs, struct attribute, entry)
295     {
296         reader_free(reader, attr);
297     }
298     list_init(&reader->attrs);
299     reader->attr_count = 0;
300 }
301
302 /* attribute data holds pointers to buffer data, so buffer shrink is not possible
303    while we are on a node with attributes */
304 static HRESULT reader_add_attr(xmlreader *reader, strval *localname, strval *value)
305 {
306     struct attribute *attr;
307
308     attr = reader_alloc(reader, sizeof(*attr));
309     if (!attr) return E_OUTOFMEMORY;
310
311     attr->localname = *localname;
312     attr->value = *value;
313     list_add_tail(&reader->attrs, &attr->entry);
314     reader->attr_count++;
315
316     return S_OK;
317 }
318
319 /* This one frees stored string value if needed */
320 static void reader_free_strvalued(xmlreader *reader, strval *v)
321 {
322     if (v->str != strval_empty.str)
323     {
324         reader_free(reader, v->str);
325         *v = strval_empty;
326     }
327 }
328
329 static inline void reader_init_strvalue(WCHAR *str, UINT len, strval *v)
330 {
331     v->start = v->str = str;
332     v->len = len;
333 }
334
335 static void reader_free_strvalue(xmlreader *reader, XmlReaderStringValue type)
336 {
337     reader_free_strvalued(reader, &reader->strvalues[type]);
338 }
339
340 static void reader_free_strvalues(xmlreader *reader)
341 {
342     int type;
343     for (type = 0; type < StringValue_Last; type++)
344         reader_free_strvalue(reader, type);
345 }
346
347 /* This helper should only be used to test if strings are the same,
348    it doesn't try to sort. */
349 static inline int strval_eq(const strval *str1, const strval *str2)
350 {
351     if (str1->len != str2->len) return 0;
352     return !memcmp(str1->str, str2->str, str1->len*sizeof(WCHAR));
353 }
354
355 static void reader_clear_elements(xmlreader *reader)
356 {
357     struct element *elem, *elem2;
358     LIST_FOR_EACH_ENTRY_SAFE(elem, elem2, &reader->elements, struct element, entry)
359     {
360         reader_free_strvalued(reader, &elem->qname);
361         reader_free(reader, elem);
362     }
363     list_init(&reader->elements);
364 }
365
366 static HRESULT reader_inc_depth(xmlreader *reader)
367 {
368     /* FIXME: handle XmlReaderProperty_MaxElementDepth property */
369     reader->depth++;
370     return S_OK;
371 }
372
373 static HRESULT reader_push_element(xmlreader *reader, strval *qname)
374 {
375     struct element *elem;
376     HRESULT hr;
377
378     elem = reader_alloc(reader, sizeof(*elem));
379     if (!elem) return E_OUTOFMEMORY;
380
381     hr = reader_strvaldup(reader, qname, &elem->qname);
382     if (FAILED(hr)) return hr;
383
384     if (!list_empty(&reader->elements))
385     {
386         hr = reader_inc_depth(reader);
387         if (FAILED(hr)) return hr;
388     }
389
390     list_add_head(&reader->elements, &elem->entry);
391     return hr;
392 }
393
394 static void reader_pop_element(xmlreader *reader)
395 {
396     struct element *elem = LIST_ENTRY(list_head(&reader->elements), struct element, entry);
397
398     if (elem)
399     {
400         list_remove(&elem->entry);
401         reader_free_strvalued(reader, &elem->qname);
402         reader_free(reader, elem);
403     }
404 }
405
406 /* Always make a copy, cause strings are supposed to be null terminated. Null pointer for 'value'
407    means node value is to be determined. */
408 static void reader_set_strvalue(xmlreader *reader, XmlReaderStringValue type, const strval *value)
409 {
410     strval *v = &reader->strvalues[type];
411
412     reader_free_strvalue(reader, type);
413     if (!value)
414     {
415         v->str = NULL;
416         v->start = NULL;
417         v->len = 0;
418         return;
419     }
420
421     if (value->str == strval_empty.str)
422         *v = *value;
423     else
424     {
425         if (type == StringValue_Value)
426         {
427             /* defer allocation for value string */
428             v->str = NULL;
429             v->start = value->start;
430             v->len = value->len;
431         }
432         else
433         {
434             v->str = reader_alloc(reader, (value->len + 1)*sizeof(WCHAR));
435             memcpy(v->str, value->start, value->len*sizeof(WCHAR));
436             v->str[value->len] = 0;
437             v->len = value->len;
438         }
439     }
440 }
441
442 static inline int is_reader_pending(xmlreader *reader)
443 {
444     return reader->input->pending;
445 }
446
447 static HRESULT init_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer)
448 {
449     const int initial_len = 0x2000;
450     buffer->data = readerinput_alloc(input, initial_len);
451     if (!buffer->data) return E_OUTOFMEMORY;
452
453     memset(buffer->data, 0, 4);
454     buffer->cur = buffer->data;
455     buffer->allocated = initial_len;
456     buffer->written = 0;
457
458     return S_OK;
459 }
460
461 static void free_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer)
462 {
463     readerinput_free(input, buffer->data);
464 }
465
466 static HRESULT get_code_page(xml_encoding encoding, UINT *cp)
467 {
468     if (encoding == XmlEncoding_Unknown)
469     {
470         FIXME("unsupported encoding %d\n", encoding);
471         return E_NOTIMPL;
472     }
473
474     *cp = xml_encoding_map[encoding].cp;
475
476     return S_OK;
477 }
478
479 static xml_encoding parse_encoding_name(const WCHAR *name, int len)
480 {
481     int min, max, n, c;
482
483     if (!name) return XmlEncoding_Unknown;
484
485     min = 0;
486     max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1;
487
488     while (min <= max)
489     {
490         n = (min+max)/2;
491
492         if (len != -1)
493             c = strncmpiW(xml_encoding_map[n].name, name, len);
494         else
495             c = strcmpiW(xml_encoding_map[n].name, name);
496         if (!c)
497             return xml_encoding_map[n].enc;
498
499         if (c > 0)
500             max = n-1;
501         else
502             min = n+1;
503     }
504
505     return XmlEncoding_Unknown;
506 }
507
508 static HRESULT alloc_input_buffer(xmlreaderinput *input)
509 {
510     input_buffer *buffer;
511     HRESULT hr;
512
513     input->buffer = NULL;
514
515     buffer = readerinput_alloc(input, sizeof(*buffer));
516     if (!buffer) return E_OUTOFMEMORY;
517
518     buffer->input = input;
519     buffer->code_page = ~0; /* code page is unknown at this point */
520     hr = init_encoded_buffer(input, &buffer->utf16);
521     if (hr != S_OK) {
522         readerinput_free(input, buffer);
523         return hr;
524     }
525
526     hr = init_encoded_buffer(input, &buffer->encoded);
527     if (hr != S_OK) {
528         free_encoded_buffer(input, &buffer->utf16);
529         readerinput_free(input, buffer);
530         return hr;
531     }
532
533     input->buffer = buffer;
534     return S_OK;
535 }
536
537 static void free_input_buffer(input_buffer *buffer)
538 {
539     free_encoded_buffer(buffer->input, &buffer->encoded);
540     free_encoded_buffer(buffer->input, &buffer->utf16);
541     readerinput_free(buffer->input, buffer);
542 }
543
544 static void readerinput_release_stream(xmlreaderinput *readerinput)
545 {
546     if (readerinput->stream) {
547         ISequentialStream_Release(readerinput->stream);
548         readerinput->stream = NULL;
549     }
550 }
551
552 /* Queries already stored interface for IStream/ISequentialStream.
553    Interface supplied on creation will be overwritten */
554 static HRESULT readerinput_query_for_stream(xmlreaderinput *readerinput)
555 {
556     HRESULT hr;
557
558     readerinput_release_stream(readerinput);
559     hr = IUnknown_QueryInterface(readerinput->input, &IID_IStream, (void**)&readerinput->stream);
560     if (hr != S_OK)
561         hr = IUnknown_QueryInterface(readerinput->input, &IID_ISequentialStream, (void**)&readerinput->stream);
562
563     return hr;
564 }
565
566 /* reads a chunk to raw buffer */
567 static HRESULT readerinput_growraw(xmlreaderinput *readerinput)
568 {
569     encoded_buffer *buffer = &readerinput->buffer->encoded;
570     /* to make sure aligned length won't exceed allocated length */
571     ULONG len = buffer->allocated - buffer->written - 4;
572     ULONG read;
573     HRESULT hr;
574
575     /* always try to get aligned to 4 bytes, so the only case we can get partially read characters is
576        variable width encodings like UTF-8 */
577     len = (len + 3) & ~3;
578     /* try to use allocated space or grow */
579     if (buffer->allocated - buffer->written < len)
580     {
581         buffer->allocated *= 2;
582         buffer->data = readerinput_realloc(readerinput, buffer->data, buffer->allocated);
583         len = buffer->allocated - buffer->written;
584     }
585
586     read = 0;
587     hr = ISequentialStream_Read(readerinput->stream, buffer->data + buffer->written, len, &read);
588     TRACE("requested %d, read %d, ret 0x%08x\n", len, read, hr);
589     readerinput->pending = hr == E_PENDING;
590     if (FAILED(hr)) return hr;
591     buffer->written += read;
592
593     return hr;
594 }
595
596 /* grows UTF-16 buffer so it has at least 'length' bytes free on return */
597 static void readerinput_grow(xmlreaderinput *readerinput, int length)
598 {
599     encoded_buffer *buffer = &readerinput->buffer->utf16;
600
601     /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
602     if (buffer->allocated < buffer->written + length + 4)
603     {
604         int grown_size = max(2*buffer->allocated, buffer->allocated + length);
605         buffer->data = readerinput_realloc(readerinput, buffer->data, grown_size);
606         buffer->allocated = grown_size;
607     }
608 }
609
610 static inline int readerinput_is_utf8(xmlreaderinput *readerinput)
611 {
612     static char startA[] = {'<','?'};
613     static char commentA[] = {'<','!'};
614     encoded_buffer *buffer = &readerinput->buffer->encoded;
615     unsigned char *ptr = (unsigned char*)buffer->data;
616
617     return !memcmp(buffer->data, startA, sizeof(startA)) ||
618            !memcmp(buffer->data, commentA, sizeof(commentA)) ||
619            /* test start byte */
620            (ptr[0] == '<' &&
621             (
622              (ptr[1] && (ptr[1] <= 0x7f)) ||
623              (buffer->data[1] >> 5) == 0x6  || /* 2 bytes */
624              (buffer->data[1] >> 4) == 0xe  || /* 3 bytes */
625              (buffer->data[1] >> 3) == 0x1e)   /* 4 bytes */
626            );
627 }
628
629 static HRESULT readerinput_detectencoding(xmlreaderinput *readerinput, xml_encoding *enc)
630 {
631     encoded_buffer *buffer = &readerinput->buffer->encoded;
632     static WCHAR startW[] = {'<','?'};
633     static WCHAR commentW[] = {'<','!'};
634     static char utf8bom[] = {0xef,0xbb,0xbf};
635     static char utf16lebom[] = {0xff,0xfe};
636
637     *enc = XmlEncoding_Unknown;
638
639     if (buffer->written <= 3)
640     {
641         HRESULT hr = readerinput_growraw(readerinput);
642         if (FAILED(hr)) return hr;
643         if (buffer->written <= 3) return MX_E_INPUTEND;
644     }
645
646     /* try start symbols if we have enough data to do that, input buffer should contain
647        first chunk already */
648     if (readerinput_is_utf8(readerinput))
649         *enc = XmlEncoding_UTF8;
650     else if (!memcmp(buffer->data, startW, sizeof(startW)) ||
651              !memcmp(buffer->data, commentW, sizeof(commentW)))
652         *enc = XmlEncoding_UTF16;
653     /* try with BOM now */
654     else if (!memcmp(buffer->data, utf8bom, sizeof(utf8bom)))
655     {
656         buffer->cur += sizeof(utf8bom);
657         *enc = XmlEncoding_UTF8;
658     }
659     else if (!memcmp(buffer->data, utf16lebom, sizeof(utf16lebom)))
660     {
661         buffer->cur += sizeof(utf16lebom);
662         *enc = XmlEncoding_UTF16;
663     }
664
665     return S_OK;
666 }
667
668 static int readerinput_get_utf8_convlen(xmlreaderinput *readerinput)
669 {
670     encoded_buffer *buffer = &readerinput->buffer->encoded;
671     int len = buffer->written;
672
673     /* complete single byte char */
674     if (!(buffer->data[len-1] & 0x80)) return len;
675
676     /* find start byte of multibyte char */
677     while (--len && !(buffer->data[len] & 0xc0))
678         ;
679
680     return len;
681 }
682
683 /* Returns byte length of complete char sequence for buffer code page,
684    it's relative to current buffer position which is currently used for BOM handling
685    only. */
686 static int readerinput_get_convlen(xmlreaderinput *readerinput)
687 {
688     encoded_buffer *buffer = &readerinput->buffer->encoded;
689     int len;
690
691     if (readerinput->buffer->code_page == CP_UTF8)
692         len = readerinput_get_utf8_convlen(readerinput);
693     else
694         len = buffer->written;
695
696     TRACE("%d\n", len - (int)(buffer->cur - buffer->data));
697     return len - (buffer->cur - buffer->data);
698 }
699
700 /* It's possible that raw buffer has some leftovers from last conversion - some char
701    sequence that doesn't represent a full code point. Length argument should be calculated with
702    readerinput_get_convlen(), if it's -1 it will be calculated here. */
703 static void readerinput_shrinkraw(xmlreaderinput *readerinput, int len)
704 {
705     encoded_buffer *buffer = &readerinput->buffer->encoded;
706
707     if (len == -1)
708         len = readerinput_get_convlen(readerinput);
709
710     memmove(buffer->data, buffer->cur + (buffer->written - len), len);
711     /* everything below cur is lost too */
712     buffer->written -= len + (buffer->cur - buffer->data);
713     /* after this point we don't need cur pointer really,
714        it's used only to mark where actual data begins when first chunk is read */
715     buffer->cur = buffer->data;
716 }
717
718 /* note that raw buffer content is kept */
719 static void readerinput_switchencoding(xmlreaderinput *readerinput, xml_encoding enc)
720 {
721     encoded_buffer *src = &readerinput->buffer->encoded;
722     encoded_buffer *dest = &readerinput->buffer->utf16;
723     int len, dest_len;
724     HRESULT hr;
725     WCHAR *ptr;
726     UINT cp;
727
728     hr = get_code_page(enc, &cp);
729     if (FAILED(hr)) return;
730
731     readerinput->buffer->code_page = cp;
732     len = readerinput_get_convlen(readerinput);
733
734     TRACE("switching to cp %d\n", cp);
735
736     /* just copy in this case */
737     if (enc == XmlEncoding_UTF16)
738     {
739         readerinput_grow(readerinput, len);
740         memcpy(dest->data, src->cur, len);
741         dest->written += len*sizeof(WCHAR);
742         return;
743     }
744
745     dest_len = MultiByteToWideChar(cp, 0, src->cur, len, NULL, 0);
746     readerinput_grow(readerinput, dest_len);
747     ptr = (WCHAR*)dest->data;
748     MultiByteToWideChar(cp, 0, src->cur, len, ptr, dest_len);
749     ptr[dest_len] = 0;
750     dest->written += dest_len*sizeof(WCHAR);
751 }
752
753 /* shrinks parsed data a buffer begins with */
754 static void reader_shrink(xmlreader *reader)
755 {
756     encoded_buffer *buffer = &reader->input->buffer->utf16;
757
758     /* avoid to move too often using threshold shrink length */
759     if (buffer->cur - buffer->data > buffer->written / 2)
760     {
761         buffer->written -= buffer->cur - buffer->data;
762         memmove(buffer->data, buffer->cur, buffer->written);
763         buffer->cur = buffer->data;
764         *(WCHAR*)&buffer->cur[buffer->written] = 0;
765     }
766 }
767
768 /* This is a normal way for reader to get new data converted from raw buffer to utf16 buffer.
769    It won't attempt to shrink but will grow destination buffer if needed */
770 static HRESULT reader_more(xmlreader *reader)
771 {
772     xmlreaderinput *readerinput = reader->input;
773     encoded_buffer *src = &readerinput->buffer->encoded;
774     encoded_buffer *dest = &readerinput->buffer->utf16;
775     UINT cp = readerinput->buffer->code_page;
776     int len, dest_len;
777     HRESULT hr;
778     WCHAR *ptr;
779
780     /* get some raw data from stream first */
781     hr = readerinput_growraw(readerinput);
782     len = readerinput_get_convlen(readerinput);
783
784     /* just copy for UTF-16 case */
785     if (cp == ~0)
786     {
787         readerinput_grow(readerinput, len);
788         memcpy(dest->data, src->cur, len);
789         dest->written += len*sizeof(WCHAR);
790         return hr;
791     }
792
793     dest_len = MultiByteToWideChar(cp, 0, src->cur, len, NULL, 0);
794     readerinput_grow(readerinput, dest_len);
795     ptr = (WCHAR*)dest->data;
796     MultiByteToWideChar(cp, 0, src->cur, len, ptr, dest_len);
797     ptr[dest_len] = 0;
798     dest->written += dest_len*sizeof(WCHAR);
799     /* get rid of processed data */
800     readerinput_shrinkraw(readerinput, len);
801
802     return hr;
803 }
804
805 static inline WCHAR *reader_get_cur(xmlreader *reader)
806 {
807     WCHAR *ptr = (WCHAR*)reader->input->buffer->utf16.cur;
808     if (!*ptr) reader_more(reader);
809     return ptr;
810 }
811
812 static int reader_cmp(xmlreader *reader, const WCHAR *str)
813 {
814     const WCHAR *ptr = reader_get_cur(reader);
815     return strncmpW(str, ptr, strlenW(str));
816 }
817
818 /* moves cursor n WCHARs forward */
819 static void reader_skipn(xmlreader *reader, int n)
820 {
821     encoded_buffer *buffer = &reader->input->buffer->utf16;
822     const WCHAR *ptr = reader_get_cur(reader);
823
824     while (*ptr++ && n--)
825     {
826         buffer->cur += sizeof(WCHAR);
827         reader->pos++;
828     }
829 }
830
831 static inline int is_wchar_space(WCHAR ch)
832 {
833     return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
834 }
835
836 /* [3] S ::= (#x20 | #x9 | #xD | #xA)+ */
837 static int reader_skipspaces(xmlreader *reader)
838 {
839     encoded_buffer *buffer = &reader->input->buffer->utf16;
840     const WCHAR *ptr = reader_get_cur(reader), *start = ptr;
841
842     while (is_wchar_space(*ptr))
843     {
844         buffer->cur += sizeof(WCHAR);
845         if (*ptr == '\r')
846             reader->pos = 0;
847         else if (*ptr == '\n')
848         {
849             reader->line++;
850             reader->pos = 0;
851         }
852         else
853             reader->pos++;
854         ptr++;
855     }
856
857     return ptr - start;
858 }
859
860 /* [26] VersionNum ::= '1.' [0-9]+ */
861 static HRESULT reader_parse_versionnum(xmlreader *reader, strval *val)
862 {
863     WCHAR *ptr, *ptr2, *start = reader_get_cur(reader);
864     static const WCHAR onedotW[] = {'1','.',0};
865
866     if (reader_cmp(reader, onedotW)) return WC_E_XMLDECL;
867     /* skip "1." */
868     reader_skipn(reader, 2);
869
870     ptr2 = ptr = reader_get_cur(reader);
871     while (*ptr >= '0' && *ptr <= '9')
872         ptr++;
873
874     if (ptr2 == ptr) return WC_E_DIGIT;
875     TRACE("version=%s\n", debugstr_wn(start, ptr-start));
876     reader_init_strvalue(start, ptr-start, val);
877     reader_skipn(reader, ptr-ptr2);
878     return S_OK;
879 }
880
881 /* [25] Eq ::= S? '=' S? */
882 static HRESULT reader_parse_eq(xmlreader *reader)
883 {
884     static const WCHAR eqW[] = {'=',0};
885     reader_skipspaces(reader);
886     if (reader_cmp(reader, eqW)) return WC_E_EQUAL;
887     /* skip '=' */
888     reader_skipn(reader, 1);
889     reader_skipspaces(reader);
890     return S_OK;
891 }
892
893 /* [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') */
894 static HRESULT reader_parse_versioninfo(xmlreader *reader)
895 {
896     static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
897     strval val, name;
898     HRESULT hr;
899
900     if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
901
902     if (reader_cmp(reader, versionW)) return WC_E_XMLDECL;
903     reader_init_strvalue(reader_get_cur(reader), 7, &name);
904     /* skip 'version' */
905     reader_skipn(reader, 7);
906
907     hr = reader_parse_eq(reader);
908     if (FAILED(hr)) return hr;
909
910     if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
911         return WC_E_QUOTE;
912     /* skip "'"|'"' */
913     reader_skipn(reader, 1);
914
915     hr = reader_parse_versionnum(reader, &val);
916     if (FAILED(hr)) return hr;
917
918     if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
919         return WC_E_QUOTE;
920
921     /* skip "'"|'"' */
922     reader_skipn(reader, 1);
923
924     return reader_add_attr(reader, &name, &val);
925 }
926
927 /* ([A-Za-z0-9._] | '-') */
928 static inline int is_wchar_encname(WCHAR ch)
929 {
930     return ((ch >= 'A' && ch <= 'Z') ||
931             (ch >= 'a' && ch <= 'z') ||
932             (ch >= '0' && ch <= '9') ||
933             (ch == '.') || (ch == '_') ||
934             (ch == '-'));
935 }
936
937 /* [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* */
938 static HRESULT reader_parse_encname(xmlreader *reader, strval *val)
939 {
940     WCHAR *start = reader_get_cur(reader), *ptr;
941     xml_encoding enc;
942     int len;
943
944     if ((*start < 'A' || *start > 'Z') && (*start < 'a' || *start > 'z'))
945         return WC_E_ENCNAME;
946
947     ptr = start;
948     while (is_wchar_encname(*++ptr))
949         ;
950
951     len = ptr - start;
952     enc = parse_encoding_name(start, len);
953     TRACE("encoding name %s\n", debugstr_wn(start, len));
954     val->str = start;
955     val->len = len;
956
957     if (enc == XmlEncoding_Unknown)
958         return WC_E_ENCNAME;
959
960     /* skip encoding name */
961     reader_skipn(reader, len);
962     return S_OK;
963 }
964
965 /* [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" ) */
966 static HRESULT reader_parse_encdecl(xmlreader *reader)
967 {
968     static const WCHAR encodingW[] = {'e','n','c','o','d','i','n','g',0};
969     strval name, val;
970     HRESULT hr;
971
972     if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
973
974     if (reader_cmp(reader, encodingW)) return S_FALSE;
975     name.str = reader_get_cur(reader);
976     name.len = 8;
977     /* skip 'encoding' */
978     reader_skipn(reader, 8);
979
980     hr = reader_parse_eq(reader);
981     if (FAILED(hr)) return hr;
982
983     if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
984         return WC_E_QUOTE;
985     /* skip "'"|'"' */
986     reader_skipn(reader, 1);
987
988     hr = reader_parse_encname(reader, &val);
989     if (FAILED(hr)) return hr;
990
991     if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
992         return WC_E_QUOTE;
993
994     /* skip "'"|'"' */
995     reader_skipn(reader, 1);
996
997     return reader_add_attr(reader, &name, &val);
998 }
999
1000 /* [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) */
1001 static HRESULT reader_parse_sddecl(xmlreader *reader)
1002 {
1003     static const WCHAR standaloneW[] = {'s','t','a','n','d','a','l','o','n','e',0};
1004     static const WCHAR yesW[] = {'y','e','s',0};
1005     static const WCHAR noW[] = {'n','o',0};
1006     WCHAR *start, *ptr;
1007     strval name, val;
1008     HRESULT hr;
1009
1010     if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
1011
1012     if (reader_cmp(reader, standaloneW)) return S_FALSE;
1013     reader_init_strvalue(reader_get_cur(reader), 10, &name);
1014     /* skip 'standalone' */
1015     reader_skipn(reader, 10);
1016
1017     hr = reader_parse_eq(reader);
1018     if (FAILED(hr)) return hr;
1019
1020     if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
1021         return WC_E_QUOTE;
1022     /* skip "'"|'"' */
1023     reader_skipn(reader, 1);
1024
1025     if (reader_cmp(reader, yesW) && reader_cmp(reader, noW))
1026         return WC_E_XMLDECL;
1027
1028     start = reader_get_cur(reader);
1029     /* skip 'yes'|'no' */
1030     reader_skipn(reader, reader_cmp(reader, yesW) ? 2 : 3);
1031     ptr = reader_get_cur(reader);
1032     TRACE("standalone=%s\n", debugstr_wn(start, ptr-start));
1033     val.str = start;
1034     val.len = ptr-start;
1035
1036     if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW))
1037         return WC_E_QUOTE;
1038     /* skip "'"|'"' */
1039     reader_skipn(reader, 1);
1040
1041     return reader_add_attr(reader, &name, &val);
1042 }
1043
1044 /* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
1045 static HRESULT reader_parse_xmldecl(xmlreader *reader)
1046 {
1047     static const WCHAR xmldeclW[] = {'<','?','x','m','l',' ',0};
1048     static const WCHAR declcloseW[] = {'?','>',0};
1049     HRESULT hr;
1050
1051     /* check if we have "<?xml " */
1052     if (reader_cmp(reader, xmldeclW)) return S_FALSE;
1053
1054     reader_skipn(reader, 5);
1055     hr = reader_parse_versioninfo(reader);
1056     if (FAILED(hr))
1057         return hr;
1058
1059     hr = reader_parse_encdecl(reader);
1060     if (FAILED(hr))
1061         return hr;
1062
1063     hr = reader_parse_sddecl(reader);
1064     if (FAILED(hr))
1065         return hr;
1066
1067     reader_skipspaces(reader);
1068     if (reader_cmp(reader, declcloseW)) return WC_E_XMLDECL;
1069     reader_skipn(reader, 2);
1070
1071     reader->nodetype = XmlNodeType_XmlDeclaration;
1072     reader_set_strvalue(reader, StringValue_LocalName, &strval_empty);
1073     reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty);
1074     reader_set_strvalue(reader, StringValue_Value, &strval_empty);
1075
1076     return S_OK;
1077 }
1078
1079 /* [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->' */
1080 static HRESULT reader_parse_comment(xmlreader *reader)
1081 {
1082     WCHAR *start, *ptr;
1083
1084     if (reader->resume[XmlReadResume_Body])
1085     {
1086         start = reader->resume[XmlReadResume_Body];
1087         ptr = reader_get_cur(reader);
1088     }
1089     else
1090     {
1091         /* skip '<!--' */
1092         reader_skipn(reader, 4);
1093         reader_shrink(reader);
1094         ptr = start = reader_get_cur(reader);
1095         reader->nodetype = XmlNodeType_Comment;
1096         reader->resume[XmlReadResume_Body] = start;
1097         reader->resumestate = XmlReadResumeState_Comment;
1098         reader_set_strvalue(reader, StringValue_LocalName, NULL);
1099         reader_set_strvalue(reader, StringValue_QualifiedName, NULL);
1100         reader_set_strvalue(reader, StringValue_Value, NULL);
1101     }
1102
1103     /* will exit when there's no more data, it won't attempt to
1104        read more from stream */
1105     while (*ptr)
1106     {
1107         if (ptr[0] == '-')
1108         {
1109             if (ptr[1] == '-')
1110             {
1111                 if (ptr[2] == '>')
1112                 {
1113                     strval value;
1114
1115                     TRACE("%s\n", debugstr_wn(start, ptr-start));
1116                     /* skip '-->' */
1117                     reader_skipn(reader, 3);
1118                     reader_init_strvalue(start, ptr-start, &value);
1119                     reader_set_strvalue(reader, StringValue_LocalName, &strval_empty);
1120                     reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty);
1121                     reader_set_strvalue(reader, StringValue_Value, &value);
1122                     reader->resume[XmlReadResume_Body] = NULL;
1123                     reader->resumestate = XmlReadResumeState_Initial;
1124                     return S_OK;
1125                 }
1126                 else
1127                     return WC_E_COMMENT;
1128             }
1129             else
1130                 ptr++;
1131         }
1132         else
1133         {
1134             reader_skipn(reader, 1);
1135             ptr++;
1136         }
1137     }
1138
1139     return S_OK;
1140 }
1141
1142 /* [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] */
1143 static inline int is_char(WCHAR ch)
1144 {
1145     return (ch == '\t') || (ch == '\r') || (ch == '\n') ||
1146            (ch >= 0x20 && ch <= 0xd7ff) ||
1147            (ch >= 0xd800 && ch <= 0xdbff) || /* high surrogate */
1148            (ch >= 0xdc00 && ch <= 0xdfff) || /* low surrogate */
1149            (ch >= 0xe000 && ch <= 0xfffd);
1150 }
1151
1152 /* [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] */
1153 static inline int is_pubchar(WCHAR ch)
1154 {
1155     return (ch == ' ') ||
1156            (ch >= 'a' && ch <= 'z') ||
1157            (ch >= 'A' && ch <= 'Z') ||
1158            (ch >= '0' && ch <= '9') ||
1159            (ch >= '-' && ch <= ';') || /* '()*+,-./:; */
1160            (ch == '=') || (ch == '?') ||
1161            (ch == '@') || (ch == '!') ||
1162            (ch >= '#' && ch <= '%') || /* #$% */
1163            (ch == '_') || (ch == '\r') || (ch == '\n');
1164 }
1165
1166 static inline int is_namestartchar(WCHAR ch)
1167 {
1168     return (ch == ':') || (ch >= 'A' && ch <= 'Z') ||
1169            (ch == '_') || (ch >= 'a' && ch <= 'z') ||
1170            (ch >= 0xc0   && ch <= 0xd6)   ||
1171            (ch >= 0xd8   && ch <= 0xf6)   ||
1172            (ch >= 0xf8   && ch <= 0x2ff)  ||
1173            (ch >= 0x370  && ch <= 0x37d)  ||
1174            (ch >= 0x37f  && ch <= 0x1fff) ||
1175            (ch >= 0x200c && ch <= 0x200d) ||
1176            (ch >= 0x2070 && ch <= 0x218f) ||
1177            (ch >= 0x2c00 && ch <= 0x2fef) ||
1178            (ch >= 0x3001 && ch <= 0xd7ff) ||
1179            (ch >= 0xd800 && ch <= 0xdbff) || /* high surrogate */
1180            (ch >= 0xdc00 && ch <= 0xdfff) || /* low surrogate */
1181            (ch >= 0xf900 && ch <= 0xfdcf) ||
1182            (ch >= 0xfdf0 && ch <= 0xfffd);
1183 }
1184
1185 /* [4 NS] NCName ::= Name - (Char* ':' Char*) */
1186 static inline int is_ncnamechar(WCHAR ch)
1187 {
1188     return (ch >= 'A' && ch <= 'Z') ||
1189            (ch == '_') || (ch >= 'a' && ch <= 'z') ||
1190            (ch == '-') || (ch == '.') ||
1191            (ch >= '0'    && ch <= '9')    ||
1192            (ch == 0xb7)                   ||
1193            (ch >= 0xc0   && ch <= 0xd6)   ||
1194            (ch >= 0xd8   && ch <= 0xf6)   ||
1195            (ch >= 0xf8   && ch <= 0x2ff)  ||
1196            (ch >= 0x300  && ch <= 0x36f)  ||
1197            (ch >= 0x370  && ch <= 0x37d)  ||
1198            (ch >= 0x37f  && ch <= 0x1fff) ||
1199            (ch >= 0x200c && ch <= 0x200d) ||
1200            (ch >= 0x203f && ch <= 0x2040) ||
1201            (ch >= 0x2070 && ch <= 0x218f) ||
1202            (ch >= 0x2c00 && ch <= 0x2fef) ||
1203            (ch >= 0x3001 && ch <= 0xd7ff) ||
1204            (ch >= 0xd800 && ch <= 0xdbff) || /* high surrogate */
1205            (ch >= 0xdc00 && ch <= 0xdfff) || /* low surrogate */
1206            (ch >= 0xf900 && ch <= 0xfdcf) ||
1207            (ch >= 0xfdf0 && ch <= 0xfffd);
1208 }
1209
1210 static inline int is_namechar(WCHAR ch)
1211 {
1212     return (ch == ':') || is_ncnamechar(ch);
1213 }
1214
1215 /* [4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] |
1216                             [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] |
1217                             [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
1218    [4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
1219    [5]  Name     ::= NameStartChar (NameChar)* */
1220 static HRESULT reader_parse_name(xmlreader *reader, strval *name)
1221 {
1222     WCHAR *ptr, *start;
1223
1224     if (reader->resume[XmlReadResume_Name])
1225     {
1226         start = reader->resume[XmlReadResume_Name];
1227         ptr = reader_get_cur(reader);
1228     }
1229     else
1230     {
1231         ptr = start = reader_get_cur(reader);
1232         if (!is_namestartchar(*ptr)) return WC_E_NAMECHARACTER;
1233     }
1234
1235     while (is_namechar(*ptr))
1236     {
1237         reader_skipn(reader, 1);
1238         ptr = reader_get_cur(reader);
1239     }
1240
1241     if (is_reader_pending(reader))
1242     {
1243         reader->resume[XmlReadResume_Name] = start;
1244         return E_PENDING;
1245     }
1246     else
1247         reader->resume[XmlReadResume_Name] = NULL;
1248
1249     TRACE("name %s:%d\n", debugstr_wn(start, ptr-start), (int)(ptr-start));
1250     reader_init_strvalue(start, ptr-start, name);
1251
1252     return S_OK;
1253 }
1254
1255 /* [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) */
1256 static HRESULT reader_parse_pitarget(xmlreader *reader, strval *target)
1257 {
1258     static const WCHAR xmlW[] = {'x','m','l'};
1259     strval name;
1260     HRESULT hr;
1261     UINT i;
1262
1263     hr = reader_parse_name(reader, &name);
1264     if (FAILED(hr)) return is_reader_pending(reader) ? E_PENDING : WC_E_PI;
1265
1266     /* now that we got name check for illegal content */
1267     if (name.len == 3 && !strncmpiW(name.str, xmlW, 3))
1268         return WC_E_LEADINGXML;
1269
1270     /* PITarget can't be a qualified name */
1271     for (i = 0; i < name.len; i++)
1272         if (name.str[i] == ':')
1273             return i ? NC_E_NAMECOLON : WC_E_PI;
1274
1275     TRACE("pitarget %s:%d\n", debugstr_wn(name.str, name.len), name.len);
1276     *target = name;
1277     return S_OK;
1278 }
1279
1280 /* [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>' */
1281 static HRESULT reader_parse_pi(xmlreader *reader)
1282 {
1283     WCHAR *ptr, *start;
1284     strval target;
1285     HRESULT hr;
1286
1287     switch (reader->resumestate)
1288     {
1289     case XmlReadResumeState_Initial:
1290         /* skip '<?' */
1291         reader_skipn(reader, 2);
1292         reader_shrink(reader);
1293         reader->resumestate = XmlReadResumeState_PITarget;
1294     case XmlReadResumeState_PITarget:
1295         hr = reader_parse_pitarget(reader, &target);
1296         if (FAILED(hr)) return hr;
1297         reader->resumestate = XmlReadResumeState_PIBody;
1298     default:
1299         ;
1300     }
1301
1302     ptr = reader_get_cur(reader);
1303     /* exit earlier if there's no content */
1304     if (ptr[0] == '?' && ptr[1] == '>')
1305     {
1306         /* skip '?>' */
1307         reader_skipn(reader, 2);
1308         reader->nodetype = XmlNodeType_ProcessingInstruction;
1309         reader->resumestate = XmlReadResumeState_Initial;
1310         reader_set_strvalue(reader, StringValue_LocalName, &target);
1311         reader_set_strvalue(reader, StringValue_QualifiedName, &target);
1312         reader_set_strvalue(reader, StringValue_Value, &strval_empty);
1313         return S_OK;
1314     }
1315
1316     if (!reader->resume[XmlReadResume_Body])
1317     {
1318         /* now at least a single space char should be there */
1319         if (!is_wchar_space(*ptr)) return WC_E_WHITESPACE;
1320         reader_skipspaces(reader);
1321         ptr = start = reader_get_cur(reader);
1322         reader->resume[XmlReadResume_Body] = start;
1323     }
1324     else
1325     {
1326         start = reader->resume[XmlReadResume_Body];
1327         ptr = reader_get_cur(reader);
1328     }
1329
1330     while (*ptr)
1331     {
1332         if (ptr[0] == '?')
1333         {
1334             if (ptr[1] == '>')
1335             {
1336                 strval value;
1337
1338                 TRACE("%s\n", debugstr_wn(start, ptr-start));
1339                 /* skip '?>' */
1340                 reader_skipn(reader, 2);
1341                 reader->nodetype = XmlNodeType_ProcessingInstruction;
1342                 reader->resumestate = XmlReadResumeState_Initial;
1343                 reader->resume[XmlReadResume_Body] = NULL;
1344                 reader_init_strvalue(start, ptr-start, &value);
1345                 reader_set_strvalue(reader, StringValue_LocalName, &target);
1346                 reader_set_strvalue(reader, StringValue_QualifiedName, &target);
1347                 reader_set_strvalue(reader, StringValue_Value, &value);
1348                 return S_OK;
1349             }
1350             else
1351             {
1352                 ptr++;
1353                 reader_more(reader);
1354             }
1355         }
1356         else
1357         {
1358             reader_skipn(reader, 1);
1359             ptr = reader_get_cur(reader);
1360         }
1361     }
1362
1363     return S_OK;
1364 }
1365
1366 /* This one is used to parse significant whitespace nodes, like in Misc production */
1367 static HRESULT reader_parse_whitespace(xmlreader *reader)
1368 {
1369     WCHAR *start, *ptr;
1370
1371     reader_shrink(reader);
1372     start = reader_get_cur(reader);
1373
1374     reader_skipspaces(reader);
1375     ptr = reader_get_cur(reader);
1376     TRACE("%s\n", debugstr_wn(start, ptr-start));
1377
1378     reader->nodetype = XmlNodeType_Whitespace;
1379     reader_set_strvalue(reader, StringValue_LocalName, &strval_empty);
1380     reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty);
1381     reader_set_strvalue(reader, StringValue_Value, &strval_empty);
1382     return S_OK;
1383 }
1384
1385 /* [27] Misc ::= Comment | PI | S */
1386 static HRESULT reader_parse_misc(xmlreader *reader)
1387 {
1388     HRESULT hr = S_FALSE;
1389
1390     if (reader->resumestate != XmlReadResumeState_Initial)
1391     {
1392         hr = reader_more(reader);
1393         if (FAILED(hr)) return hr;
1394
1395         /* finish current node */
1396         switch (reader->resumestate)
1397         {
1398         case XmlReadResumeState_PITarget:
1399         case XmlReadResumeState_PIBody:
1400             return reader_parse_pi(reader);
1401         case XmlReadResumeState_Comment:
1402             return reader_parse_comment(reader);
1403         default:
1404             ERR("unknown resume state %d\n", reader->resumestate);
1405         }
1406     }
1407
1408     while (1)
1409     {
1410         const WCHAR *cur = reader_get_cur(reader);
1411
1412         if (is_wchar_space(*cur))
1413             hr = reader_parse_whitespace(reader);
1414         else if (!reader_cmp(reader, commentW))
1415             hr = reader_parse_comment(reader);
1416         else if (!reader_cmp(reader, piW))
1417             hr = reader_parse_pi(reader);
1418         else
1419             break;
1420
1421         if (hr != S_FALSE) return hr;
1422     }
1423
1424     return hr;
1425 }
1426
1427 /* [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") */
1428 static HRESULT reader_parse_sys_literal(xmlreader *reader, strval *literal)
1429 {
1430     WCHAR *start = reader_get_cur(reader), *cur, quote;
1431
1432     if (*start != '"' && *start != '\'') return WC_E_QUOTE;
1433
1434     quote = *start;
1435     reader_skipn(reader, 1);
1436
1437     cur = start = reader_get_cur(reader);
1438     while (is_char(*cur) && *cur != quote)
1439     {
1440         reader_skipn(reader, 1);
1441         cur = reader_get_cur(reader);
1442     }
1443     if (*cur == quote) reader_skipn(reader, 1);
1444
1445     literal->str = start;
1446     literal->len = cur-start;
1447     TRACE("%s\n", debugstr_wn(start, cur-start));
1448     return S_OK;
1449 }
1450
1451 /* [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
1452    [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] */
1453 static HRESULT reader_parse_pub_literal(xmlreader *reader, strval *literal)
1454 {
1455     WCHAR *start = reader_get_cur(reader), *cur, quote;
1456
1457     if (*start != '"' && *start != '\'') return WC_E_QUOTE;
1458
1459     quote = *start;
1460     reader_skipn(reader, 1);
1461
1462     cur = start;
1463     while (is_pubchar(*cur) && *cur != quote)
1464     {
1465         reader_skipn(reader, 1);
1466         cur = reader_get_cur(reader);
1467     }
1468
1469     reader_init_strvalue(start, cur-start, literal);
1470     TRACE("%s\n", debugstr_wn(start, cur-start));
1471     return S_OK;
1472 }
1473
1474 /* [75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral */
1475 static HRESULT reader_parse_externalid(xmlreader *reader)
1476 {
1477     static WCHAR systemW[] = {'S','Y','S','T','E','M',0};
1478     static WCHAR publicW[] = {'P','U','B','L','I','C',0};
1479     strval name;
1480     HRESULT hr;
1481     int cnt;
1482
1483     if (reader_cmp(reader, systemW))
1484     {
1485         if (reader_cmp(reader, publicW))
1486             return S_FALSE;
1487         else
1488         {
1489             strval pub;
1490
1491             /* public id */
1492             reader_skipn(reader, 6);
1493             cnt = reader_skipspaces(reader);
1494             if (!cnt) return WC_E_WHITESPACE;
1495
1496             hr = reader_parse_pub_literal(reader, &pub);
1497             if (FAILED(hr)) return hr;
1498
1499             reader_init_strvalue(publicW, strlenW(publicW), &name);
1500             return reader_add_attr(reader, &name, &pub);
1501         }
1502     }
1503     else
1504     {
1505         strval sys;
1506
1507         /* system id */
1508         reader_skipn(reader, 6);
1509         cnt = reader_skipspaces(reader);
1510         if (!cnt) return WC_E_WHITESPACE;
1511
1512         hr = reader_parse_sys_literal(reader, &sys);
1513         if (FAILED(hr)) return hr;
1514
1515         reader_init_strvalue(systemW, strlenW(systemW), &name);
1516         return reader_add_attr(reader, &name, &sys);
1517     }
1518
1519     return hr;
1520 }
1521
1522 /* [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>' */
1523 static HRESULT reader_parse_dtd(xmlreader *reader)
1524 {
1525     static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',0};
1526     strval name;
1527     WCHAR *cur;
1528     HRESULT hr;
1529
1530     /* check if we have "<!DOCTYPE" */
1531     if (reader_cmp(reader, doctypeW)) return S_FALSE;
1532     reader_shrink(reader);
1533
1534     /* DTD processing is not allowed by default */
1535     if (reader->dtdmode == DtdProcessing_Prohibit) return WC_E_DTDPROHIBITED;
1536
1537     reader_skipn(reader, 9);
1538     if (!reader_skipspaces(reader)) return WC_E_WHITESPACE;
1539
1540     /* name */
1541     hr = reader_parse_name(reader, &name);
1542     if (FAILED(hr)) return WC_E_DECLDOCTYPE;
1543
1544     reader_skipspaces(reader);
1545
1546     hr = reader_parse_externalid(reader);
1547     if (FAILED(hr)) return hr;
1548
1549     reader_skipspaces(reader);
1550
1551     cur = reader_get_cur(reader);
1552     if (*cur != '>')
1553     {
1554         FIXME("internal subset parsing not implemented\n");
1555         return E_NOTIMPL;
1556     }
1557
1558     /* skip '>' */
1559     reader_skipn(reader, 1);
1560
1561     reader->nodetype = XmlNodeType_DocumentType;
1562     reader_set_strvalue(reader, StringValue_LocalName, &name);
1563     reader_set_strvalue(reader, StringValue_QualifiedName, &name);
1564
1565     return S_OK;
1566 }
1567
1568 /* [11 NS] LocalPart ::= NCName */
1569 static HRESULT reader_parse_local(xmlreader *reader, strval *local)
1570 {
1571     WCHAR *ptr, *start;
1572
1573     if (reader->resume[XmlReadResume_Local])
1574     {
1575         start = reader->resume[XmlReadResume_Local];
1576         ptr = reader_get_cur(reader);
1577     }
1578     else
1579     {
1580         ptr = start = reader_get_cur(reader);
1581     }
1582
1583     while (is_ncnamechar(*ptr))
1584     {
1585         reader_skipn(reader, 1);
1586         ptr = reader_get_cur(reader);
1587     }
1588
1589     if (is_reader_pending(reader))
1590     {
1591          reader->resume[XmlReadResume_Local] = start;
1592          return E_PENDING;
1593     }
1594     else
1595          reader->resume[XmlReadResume_Local] = NULL;
1596
1597     reader_init_strvalue(start, ptr-start, local);
1598
1599     return S_OK;
1600 }
1601
1602 /* [7 NS]  QName ::= PrefixedName | UnprefixedName
1603    [8 NS]  PrefixedName ::= Prefix ':' LocalPart
1604    [9 NS]  UnprefixedName ::= LocalPart
1605    [10 NS] Prefix ::= NCName */
1606 static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *local, strval *qname)
1607 {
1608     WCHAR *ptr, *start;
1609     HRESULT hr;
1610
1611     if (reader->resume[XmlReadResume_Name])
1612     {
1613         start = reader->resume[XmlReadResume_Name];
1614         ptr = reader_get_cur(reader);
1615     }
1616     else
1617     {
1618         ptr = start = reader_get_cur(reader);
1619         reader->resume[XmlReadResume_Name] = start;
1620         if (!is_ncnamechar(*ptr)) return NC_E_QNAMECHARACTER;
1621     }
1622
1623     if (reader->resume[XmlReadResume_Local])
1624     {
1625         hr = reader_parse_local(reader, local);
1626         if (FAILED(hr)) return hr;
1627
1628         reader_init_strvalue(reader->resume[XmlReadResume_Name],
1629                              local->start - reader->resume[XmlReadResume_Name] - 1,
1630                              prefix);
1631     }
1632     else
1633     {
1634         /* skip prefix part */
1635         while (is_ncnamechar(*ptr))
1636         {
1637             reader_skipn(reader, 1);
1638             ptr = reader_get_cur(reader);
1639         }
1640
1641         if (is_reader_pending(reader)) return E_PENDING;
1642
1643         /* got a qualified name */
1644         if (*ptr == ':')
1645         {
1646             reader_init_strvalue(start, ptr-start, prefix);
1647
1648             /* skip ':' */
1649             reader_skipn(reader, 1);
1650             hr = reader_parse_local(reader, local);
1651             if (FAILED(hr)) return hr;
1652         }
1653         else
1654         {
1655             reader_init_strvalue(reader->resume[XmlReadResume_Name], ptr-reader->resume[XmlReadResume_Name], local);
1656             reader_init_strvalue(NULL, 0, prefix);
1657         }
1658     }
1659
1660     reader_init_strvalue(start, ptr-start, local);
1661
1662     if (prefix->len)
1663         TRACE("qname %s:%s\n", debugstr_wn(prefix->start, prefix->len), debugstr_wn(local->start, local->len));
1664     else
1665         TRACE("ncname %s\n", debugstr_wn(local->start, local->len));
1666
1667     reader_init_strvalue(prefix->start ? prefix->start : local->start,
1668                         /* count ':' too */
1669                         (prefix->len ? prefix->len + 1 : 0) + local->len,
1670                          qname);
1671
1672     reader->resume[XmlReadResume_Name] = NULL;
1673     reader->resume[XmlReadResume_Local] = NULL;
1674
1675     return S_OK;
1676 }
1677
1678 /* [12 NS] STag ::= '<' QName (S Attribute)* S? '>'
1679    [14 NS] EmptyElemTag ::= '<' QName (S Attribute)* S? '/>' */
1680 static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *local, strval *qname, int *empty)
1681 {
1682     static const WCHAR endW[] = {'/','>',0};
1683     HRESULT hr;
1684
1685     hr = reader_parse_qname(reader, prefix, local, qname);
1686     if (FAILED(hr)) return hr;
1687
1688     reader_skipspaces(reader);
1689
1690     /* empty element */
1691     if ((*empty = !reader_cmp(reader, endW)))
1692     {
1693         /* skip '/>' */
1694         reader_skipn(reader, 2);
1695         return S_OK;
1696     }
1697
1698     /* got a start tag */
1699     if (!reader_cmp(reader, gtW))
1700     {
1701         /* skip '>' */
1702         reader_skipn(reader, 1);
1703         return reader_push_element(reader, qname);
1704     }
1705
1706     FIXME("only empty elements/start tags without attribute list supported\n");
1707     return E_NOTIMPL;
1708 }
1709
1710 /* [39] element ::= EmptyElemTag | STag content ETag */
1711 static HRESULT reader_parse_element(xmlreader *reader)
1712 {
1713     HRESULT hr;
1714
1715     switch (reader->resumestate)
1716     {
1717     case XmlReadResumeState_Initial:
1718         /* check if we are really on element */
1719         if (reader_cmp(reader, ltW)) return S_FALSE;
1720
1721         /* skip '<' */
1722         reader_skipn(reader, 1);
1723
1724         reader_shrink(reader);
1725         reader->resumestate = XmlReadResumeState_STag;
1726     case XmlReadResumeState_STag:
1727     {
1728         strval qname, prefix, local;
1729         int empty = 0;
1730
1731         /* this handles empty elements too */
1732         hr = reader_parse_stag(reader, &prefix, &local, &qname, &empty);
1733         if (FAILED(hr)) return hr;
1734
1735         /* FIXME: need to check for defined namespace to reject invalid prefix,
1736            currently reject all prefixes */
1737         if (prefix.len) return NC_E_UNDECLAREDPREFIX;
1738
1739         /* if we got empty element and stack is empty go straight to Misc */
1740         if (empty && list_empty(&reader->elements))
1741             reader->instate = XmlReadInState_MiscEnd;
1742         else
1743             reader->instate = XmlReadInState_Content;
1744
1745         reader->nodetype = XmlNodeType_Element;
1746         reader->resumestate = XmlReadResumeState_Initial;
1747         reader_set_strvalue(reader, StringValue_LocalName, &local);
1748         reader_set_strvalue(reader, StringValue_QualifiedName, &qname);
1749         break;
1750     }
1751     default:
1752         hr = E_FAIL;
1753     }
1754
1755     return hr;
1756 }
1757
1758 /* [13 NS] ETag ::= '</' QName S? '>' */
1759 static HRESULT reader_parse_endtag(xmlreader *reader)
1760 {
1761     strval prefix, local, qname;
1762     struct element *elem;
1763     HRESULT hr;
1764
1765     /* skip '</' */
1766     reader_skipn(reader, 2);
1767
1768     hr = reader_parse_qname(reader, &prefix, &local, &qname);
1769     if (FAILED(hr)) return hr;
1770
1771     reader_skipspaces(reader);
1772
1773     if (reader_cmp(reader, gtW)) return WC_E_GREATERTHAN;
1774
1775     /* skip '>' */
1776     reader_skipn(reader, 1);
1777
1778     /* Element stack should never be empty at this point, cause we shouldn't get to
1779        content parsing if it's empty. */
1780     elem = LIST_ENTRY(list_head(&reader->elements), struct element, entry);
1781     if (!strval_eq(&elem->qname, &qname)) return WC_E_ELEMENTMATCH;
1782
1783     reader_pop_element(reader);
1784
1785     reader->nodetype = XmlNodeType_EndElement;
1786     reader_set_strvalue(reader, StringValue_LocalName, &local);
1787     reader_set_strvalue(reader, StringValue_QualifiedName, &qname);
1788
1789     return S_OK;
1790 }
1791
1792 /* [18] CDSect ::= CDStart CData CDEnd
1793    [19] CDStart ::= '<![CDATA['
1794    [20] CData ::= (Char* - (Char* ']]>' Char*))
1795    [21] CDEnd ::= ']]>' */
1796 static HRESULT reader_parse_cdata(xmlreader *reader)
1797 {
1798     WCHAR *start, *ptr;
1799
1800     if (reader->resume[XmlReadResume_Body])
1801     {
1802         start = reader->resume[XmlReadResume_Body];
1803         ptr = reader_get_cur(reader);
1804     }
1805     else
1806     {
1807         /* skip markup '<![CDATA[' */
1808         reader_skipn(reader, 9);
1809         reader_shrink(reader);
1810         ptr = start = reader_get_cur(reader);
1811         reader->nodetype = XmlNodeType_CDATA;
1812         reader->resume[XmlReadResume_Body] = start;
1813         reader->resumestate = XmlReadResumeState_CDATA;
1814         reader_set_strvalue(reader, StringValue_LocalName, NULL);
1815         reader_set_strvalue(reader, StringValue_QualifiedName, NULL);
1816         reader_set_strvalue(reader, StringValue_Value, NULL);
1817     }
1818
1819     while (*ptr)
1820     {
1821         if (*ptr == ']' && *(ptr+1) == ']' && *(ptr+2) == '>')
1822         {
1823             strval value;
1824
1825             TRACE("%s\n", debugstr_wn(start, ptr-start));
1826             /* skip ']]>' */
1827             reader_skipn(reader, 3);
1828             reader_init_strvalue(start, ptr-start, &value);
1829             reader_set_strvalue(reader, StringValue_LocalName, &strval_empty);
1830             reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty);
1831             reader_set_strvalue(reader, StringValue_Value, &value);
1832             reader->resume[XmlReadResume_Body] = NULL;
1833             reader->resumestate = XmlReadResumeState_Initial;
1834             return S_OK;
1835         }
1836         else
1837         {
1838             /* Value normalization is not fully implemented, rules are:
1839
1840                - single '\r' -> '\n';
1841                - sequence '\r\n' -> '\n', in this case value length changes;
1842             */
1843             if (*ptr == '\r') *ptr = '\n';
1844             reader_skipn(reader, 1);
1845             ptr++;
1846         }
1847     }
1848
1849     return S_OK;
1850 }
1851
1852 /* [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
1853    [67] Reference ::= EntityRef | CharRef
1854    [68] EntityRef ::= '&' Name ';' */
1855 static HRESULT reader_parse_reference(xmlreader *reader)
1856 {
1857     FIXME("References not supported\n");
1858     return E_NOTIMPL;
1859 }
1860
1861 /* [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) */
1862 static HRESULT reader_parse_chardata(xmlreader *reader)
1863 {
1864     FIXME("CharData not supported\n");
1865     return E_NOTIMPL;
1866 }
1867
1868 /* [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* */
1869 static HRESULT reader_parse_content(xmlreader *reader)
1870 {
1871     static const WCHAR cdstartW[] = {'<','!','[','C','D','A','T','A','[',0};
1872     static const WCHAR etagW[] = {'<','/',0};
1873     static const WCHAR ampW[] = {'&',0};
1874
1875     if (reader->resumestate != XmlReadResumeState_Initial)
1876     {
1877         switch (reader->resumestate)
1878         {
1879         case XmlReadResumeState_CDATA:
1880             return reader_parse_cdata(reader);
1881         case XmlReadResumeState_Comment:
1882             return reader_parse_comment(reader);
1883         case XmlReadResumeState_PIBody:
1884         case XmlReadResumeState_PITarget:
1885             return reader_parse_pi(reader);
1886         default:
1887             ERR("unknown resume state %d\n", reader->resumestate);
1888         }
1889     }
1890
1891     reader_shrink(reader);
1892
1893     /* handle end tag here, it indicates end of content as well */
1894     if (!reader_cmp(reader, etagW))
1895         return reader_parse_endtag(reader);
1896
1897     if (!reader_cmp(reader, commentW))
1898         return reader_parse_comment(reader);
1899
1900     if (!reader_cmp(reader, piW))
1901         return reader_parse_pi(reader);
1902
1903     if (!reader_cmp(reader, cdstartW))
1904         return reader_parse_cdata(reader);
1905
1906     if (!reader_cmp(reader, ampW))
1907         return reader_parse_reference(reader);
1908
1909     if (!reader_cmp(reader, ltW))
1910         return reader_parse_element(reader);
1911
1912     /* what's left must be CharData */
1913     return reader_parse_chardata(reader);
1914 }
1915
1916 static HRESULT reader_parse_nextnode(xmlreader *reader)
1917 {
1918     HRESULT hr;
1919
1920     while (1)
1921     {
1922         switch (reader->instate)
1923         {
1924         /* if it's a first call for a new input we need to detect stream encoding */
1925         case XmlReadInState_Initial:
1926             {
1927                 xml_encoding enc;
1928
1929                 hr = readerinput_growraw(reader->input);
1930                 if (FAILED(hr)) return hr;
1931
1932                 /* try to detect encoding by BOM or data and set input code page */
1933                 hr = readerinput_detectencoding(reader->input, &enc);
1934                 TRACE("detected encoding %s, 0x%08x\n", debugstr_w(xml_encoding_map[enc].name), hr);
1935                 if (FAILED(hr)) return hr;
1936
1937                 /* always switch first time cause we have to put something in */
1938                 readerinput_switchencoding(reader->input, enc);
1939
1940                 /* parse xml declaration */
1941                 hr = reader_parse_xmldecl(reader);
1942                 if (FAILED(hr)) return hr;
1943
1944                 readerinput_shrinkraw(reader->input, -1);
1945                 reader->instate = XmlReadInState_Misc_DTD;
1946                 if (hr == S_OK) return hr;
1947             }
1948             break;
1949         case XmlReadInState_Misc_DTD:
1950             hr = reader_parse_misc(reader);
1951             if (FAILED(hr)) return hr;
1952
1953             if (hr == S_FALSE)
1954                 reader->instate = XmlReadInState_DTD;
1955             else
1956                 return hr;
1957             break;
1958         case XmlReadInState_DTD:
1959             hr = reader_parse_dtd(reader);
1960             if (FAILED(hr)) return hr;
1961
1962             if (hr == S_OK)
1963             {
1964                 reader->instate = XmlReadInState_DTD_Misc;
1965                 return hr;
1966             }
1967             else
1968                 reader->instate = XmlReadInState_Element;
1969             break;
1970         case XmlReadInState_DTD_Misc:
1971             hr = reader_parse_misc(reader);
1972             if (FAILED(hr)) return hr;
1973
1974             if (hr == S_FALSE)
1975                 reader->instate = XmlReadInState_Element;
1976             else
1977                 return hr;
1978             break;
1979         case XmlReadInState_Element:
1980             return reader_parse_element(reader);
1981         case XmlReadInState_Content:
1982             return reader_parse_content(reader);
1983         default:
1984             FIXME("internal state %d not handled\n", reader->instate);
1985             return E_NOTIMPL;
1986         }
1987     }
1988
1989     return E_NOTIMPL;
1990 }
1991
1992 static HRESULT WINAPI xmlreader_QueryInterface(IXmlReader *iface, REFIID riid, void** ppvObject)
1993 {
1994     xmlreader *This = impl_from_IXmlReader(iface);
1995
1996     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1997
1998     if (IsEqualGUID(riid, &IID_IUnknown) ||
1999         IsEqualGUID(riid, &IID_IXmlReader))
2000     {
2001         *ppvObject = iface;
2002     }
2003     else
2004     {
2005         FIXME("interface %s not implemented\n", debugstr_guid(riid));
2006         *ppvObject = NULL;
2007         return E_NOINTERFACE;
2008     }
2009
2010     IXmlReader_AddRef(iface);
2011
2012     return S_OK;
2013 }
2014
2015 static ULONG WINAPI xmlreader_AddRef(IXmlReader *iface)
2016 {
2017     xmlreader *This = impl_from_IXmlReader(iface);
2018     ULONG ref = InterlockedIncrement(&This->ref);
2019     TRACE("(%p)->(%d)\n", This, ref);
2020     return ref;
2021 }
2022
2023 static ULONG WINAPI xmlreader_Release(IXmlReader *iface)
2024 {
2025     xmlreader *This = impl_from_IXmlReader(iface);
2026     LONG ref = InterlockedDecrement(&This->ref);
2027
2028     TRACE("(%p)->(%d)\n", This, ref);
2029
2030     if (ref == 0)
2031     {
2032         IMalloc *imalloc = This->imalloc;
2033         if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface);
2034         reader_clear_attrs(This);
2035         reader_clear_elements(This);
2036         reader_free_strvalues(This);
2037         reader_free(This, This);
2038         if (imalloc) IMalloc_Release(imalloc);
2039     }
2040
2041     return ref;
2042 }
2043
2044 static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input)
2045 {
2046     xmlreader *This = impl_from_IXmlReader(iface);
2047     IXmlReaderInput *readerinput;
2048     HRESULT hr;
2049
2050     TRACE("(%p)->(%p)\n", This, input);
2051
2052     if (This->input)
2053     {
2054         readerinput_release_stream(This->input);
2055         IUnknown_Release(&This->input->IXmlReaderInput_iface);
2056         This->input = NULL;
2057     }
2058
2059     This->line = This->pos = 0;
2060     reader_clear_elements(This);
2061     This->depth = 0;
2062     This->resumestate = XmlReadResumeState_Initial;
2063     memset(This->resume, 0, sizeof(This->resume));
2064
2065     /* just reset current input */
2066     if (!input)
2067     {
2068         This->state = XmlReadState_Initial;
2069         return S_OK;
2070     }
2071
2072     /* now try IXmlReaderInput, ISequentialStream, IStream */
2073     hr = IUnknown_QueryInterface(input, &IID_IXmlReaderInput, (void**)&readerinput);
2074     if (hr == S_OK)
2075     {
2076         if (readerinput->lpVtbl == &xmlreaderinputvtbl)
2077             This->input = impl_from_IXmlReaderInput(readerinput);
2078         else
2079         {
2080             ERR("got external IXmlReaderInput implementation: %p, vtbl=%p\n",
2081                 readerinput, readerinput->lpVtbl);
2082             IUnknown_Release(readerinput);
2083             return E_FAIL;
2084
2085         }
2086     }
2087
2088     if (hr != S_OK || !readerinput)
2089     {
2090         /* create IXmlReaderInput basing on supplied interface */
2091         hr = CreateXmlReaderInputWithEncodingName(input,
2092                                          NULL, NULL, FALSE, NULL, &readerinput);
2093         if (hr != S_OK) return hr;
2094         This->input = impl_from_IXmlReaderInput(readerinput);
2095     }
2096
2097     /* set stream for supplied IXmlReaderInput */
2098     hr = readerinput_query_for_stream(This->input);
2099     if (hr == S_OK)
2100     {
2101         This->state = XmlReadState_Initial;
2102         This->instate = XmlReadInState_Initial;
2103     }
2104
2105     return hr;
2106 }
2107
2108 static HRESULT WINAPI xmlreader_GetProperty(IXmlReader* iface, UINT property, LONG_PTR *value)
2109 {
2110     xmlreader *This = impl_from_IXmlReader(iface);
2111
2112     TRACE("(%p %u %p)\n", This, property, value);
2113
2114     if (!value) return E_INVALIDARG;
2115
2116     switch (property)
2117     {
2118         case XmlReaderProperty_DtdProcessing:
2119             *value = This->dtdmode;
2120             break;
2121         case XmlReaderProperty_ReadState:
2122             *value = This->state;
2123             break;
2124         default:
2125             FIXME("Unimplemented property (%u)\n", property);
2126             return E_NOTIMPL;
2127     }
2128
2129     return S_OK;
2130 }
2131
2132 static HRESULT WINAPI xmlreader_SetProperty(IXmlReader* iface, UINT property, LONG_PTR value)
2133 {
2134     xmlreader *This = impl_from_IXmlReader(iface);
2135
2136     TRACE("(%p %u %lu)\n", iface, property, value);
2137
2138     switch (property)
2139     {
2140         case XmlReaderProperty_DtdProcessing:
2141             if (value < 0 || value > _DtdProcessing_Last) return E_INVALIDARG;
2142             This->dtdmode = value;
2143             break;
2144         default:
2145             FIXME("Unimplemented property (%u)\n", property);
2146             return E_NOTIMPL;
2147     }
2148
2149     return S_OK;
2150 }
2151
2152 static HRESULT WINAPI xmlreader_Read(IXmlReader* iface, XmlNodeType *nodetype)
2153 {
2154     xmlreader *This = impl_from_IXmlReader(iface);
2155     XmlNodeType oldtype = This->nodetype;
2156     HRESULT hr;
2157
2158     TRACE("(%p)->(%p)\n", This, nodetype);
2159
2160     if (This->state == XmlReadState_Closed) return S_FALSE;
2161
2162     hr = reader_parse_nextnode(This);
2163     if (oldtype == XmlNodeType_None && This->nodetype != oldtype)
2164         This->state = XmlReadState_Interactive;
2165     if (hr == S_OK) *nodetype = This->nodetype;
2166
2167     return hr;
2168 }
2169
2170 static HRESULT WINAPI xmlreader_GetNodeType(IXmlReader* iface, XmlNodeType *node_type)
2171 {
2172     xmlreader *This = impl_from_IXmlReader(iface);
2173     TRACE("(%p)->(%p)\n", This, node_type);
2174
2175     /* When we're on attribute always return attribute type, container node type is kept.
2176        Note that container is not necessarily an element, and attribute doesn't mean it's
2177        an attribute in XML spec terms. */
2178     *node_type = This->attr ? XmlNodeType_Attribute : This->nodetype;
2179     return This->state == XmlReadState_Closed ? S_FALSE : S_OK;
2180 }
2181
2182 static HRESULT WINAPI xmlreader_MoveToFirstAttribute(IXmlReader* iface)
2183 {
2184     xmlreader *This = impl_from_IXmlReader(iface);
2185
2186     TRACE("(%p)\n", This);
2187
2188     if (!This->attr_count) return S_FALSE;
2189     This->attr = LIST_ENTRY(list_head(&This->attrs), struct attribute, entry);
2190     return S_OK;
2191 }
2192
2193 static HRESULT WINAPI xmlreader_MoveToNextAttribute(IXmlReader* iface)
2194 {
2195     xmlreader *This = impl_from_IXmlReader(iface);
2196     const struct list *next;
2197
2198     TRACE("(%p)\n", This);
2199
2200     if (!This->attr_count) return S_FALSE;
2201
2202     if (!This->attr)
2203         return IXmlReader_MoveToFirstAttribute(iface);
2204
2205     next = list_next(&This->attrs, &This->attr->entry);
2206     if (next)
2207         This->attr = LIST_ENTRY(next, struct attribute, entry);
2208
2209     return next ? S_OK : S_FALSE;
2210 }
2211
2212 static HRESULT WINAPI xmlreader_MoveToAttributeByName(IXmlReader* iface,
2213                                                       LPCWSTR local_name,
2214                                                       LPCWSTR namespaceUri)
2215 {
2216     FIXME("(%p %p %p): stub\n", iface, local_name, namespaceUri);
2217     return E_NOTIMPL;
2218 }
2219
2220 static HRESULT WINAPI xmlreader_MoveToElement(IXmlReader* iface)
2221 {
2222     xmlreader *This = impl_from_IXmlReader(iface);
2223
2224     TRACE("(%p)\n", This);
2225
2226     if (!This->attr_count) return S_FALSE;
2227     This->attr = NULL;
2228     return S_OK;
2229 }
2230
2231 static HRESULT WINAPI xmlreader_GetQualifiedName(IXmlReader* iface, LPCWSTR *name, UINT *len)
2232 {
2233     xmlreader *This = impl_from_IXmlReader(iface);
2234
2235     TRACE("(%p)->(%p %p)\n", This, name, len);
2236     *name = This->strvalues[StringValue_QualifiedName].str;
2237     *len  = This->strvalues[StringValue_QualifiedName].len;
2238     return S_OK;
2239 }
2240
2241 static HRESULT WINAPI xmlreader_GetNamespaceUri(IXmlReader* iface,
2242                                                 LPCWSTR *namespaceUri,
2243                                                 UINT *namespaceUri_length)
2244 {
2245     FIXME("(%p %p %p): stub\n", iface, namespaceUri, namespaceUri_length);
2246     return E_NOTIMPL;
2247 }
2248
2249 static HRESULT WINAPI xmlreader_GetLocalName(IXmlReader* iface, LPCWSTR *name, UINT *len)
2250 {
2251     xmlreader *This = impl_from_IXmlReader(iface);
2252
2253     TRACE("(%p)->(%p %p)\n", This, name, len);
2254     *name = This->strvalues[StringValue_LocalName].str;
2255     *len  = This->strvalues[StringValue_LocalName].len;
2256     return S_OK;
2257 }
2258
2259 static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface,
2260                                           LPCWSTR *prefix,
2261                                           UINT *prefix_length)
2262 {
2263     FIXME("(%p %p %p): stub\n", iface, prefix, prefix_length);
2264     return E_NOTIMPL;
2265 }
2266
2267 static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface, const WCHAR **value, UINT *len)
2268 {
2269     xmlreader *reader = impl_from_IXmlReader(iface);
2270     strval *val = &reader->strvalues[StringValue_Value];
2271
2272     TRACE("(%p)->(%p %p)\n", reader, value, len);
2273
2274     *value = NULL;
2275
2276     if ((reader->nodetype == XmlNodeType_Comment && !val->str) || is_reader_pending(reader))
2277     {
2278         XmlNodeType type;
2279         HRESULT hr;
2280
2281         hr = IXmlReader_Read(iface, &type);
2282         if (FAILED(hr)) return hr;
2283
2284         /* return if still pending, partially read values are not reported */
2285         if (is_reader_pending(reader)) return E_PENDING;
2286     }
2287
2288     if (!val->str)
2289     {
2290         val->str = reader_alloc(reader, (val->len+1)*sizeof(WCHAR));
2291         if (!val->str) return E_OUTOFMEMORY;
2292         memcpy(val->str, val->start, val->len*sizeof(WCHAR));
2293         val->str[val->len] = 0;
2294     }
2295
2296     *value = val->str;
2297     if (len) *len = val->len;
2298     return S_OK;
2299 }
2300
2301 static HRESULT WINAPI xmlreader_ReadValueChunk(IXmlReader* iface, WCHAR *buffer, UINT chunk_size, UINT *read)
2302 {
2303     xmlreader *reader = impl_from_IXmlReader(iface);
2304     strval *val = &reader->strvalues[StringValue_Value];
2305     UINT len;
2306
2307     TRACE("(%p)->(%p %u %p)\n", reader, buffer, chunk_size, read);
2308
2309     /* Value is already allocated, chunked reads are not possible. */
2310     if (val->str) return S_FALSE;
2311
2312     if (val->len)
2313     {
2314         len = min(chunk_size, val->len);
2315         memcpy(buffer, val->start, len);
2316         val->start += len;
2317         val->len -= len;
2318         if (read) *read = len;
2319     }
2320
2321     return S_OK;
2322 }
2323
2324 static HRESULT WINAPI xmlreader_GetBaseUri(IXmlReader* iface,
2325                                            LPCWSTR *baseUri,
2326                                            UINT *baseUri_length)
2327 {
2328     FIXME("(%p %p %p): stub\n", iface, baseUri, baseUri_length);
2329     return E_NOTIMPL;
2330 }
2331
2332 static BOOL WINAPI xmlreader_IsDefault(IXmlReader* iface)
2333 {
2334     FIXME("(%p): stub\n", iface);
2335     return E_NOTIMPL;
2336 }
2337
2338 static BOOL WINAPI xmlreader_IsEmptyElement(IXmlReader* iface)
2339 {
2340     FIXME("(%p): stub\n", iface);
2341     return E_NOTIMPL;
2342 }
2343
2344 static HRESULT WINAPI xmlreader_GetLineNumber(IXmlReader* iface, UINT *lineNumber)
2345 {
2346     xmlreader *This = impl_from_IXmlReader(iface);
2347
2348     TRACE("(%p %p)\n", This, lineNumber);
2349
2350     if (!lineNumber) return E_INVALIDARG;
2351
2352     *lineNumber = This->line;
2353
2354     return S_OK;
2355 }
2356
2357 static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *linePosition)
2358 {
2359     xmlreader *This = impl_from_IXmlReader(iface);
2360
2361     TRACE("(%p %p)\n", This, linePosition);
2362
2363     if (!linePosition) return E_INVALIDARG;
2364
2365     *linePosition = This->pos;
2366
2367     return S_OK;
2368 }
2369
2370 static HRESULT WINAPI xmlreader_GetAttributeCount(IXmlReader* iface, UINT *count)
2371 {
2372     xmlreader *This = impl_from_IXmlReader(iface);
2373
2374     TRACE("(%p)->(%p)\n", This, count);
2375
2376     if (!count) return E_INVALIDARG;
2377
2378     *count = This->attr_count;
2379     return S_OK;
2380 }
2381
2382 static HRESULT WINAPI xmlreader_GetDepth(IXmlReader* iface, UINT *depth)
2383 {
2384     xmlreader *This = impl_from_IXmlReader(iface);
2385     TRACE("(%p)->(%p)\n", This, depth);
2386     *depth = This->depth;
2387     return S_OK;
2388 }
2389
2390 static BOOL WINAPI xmlreader_IsEOF(IXmlReader* iface)
2391 {
2392     FIXME("(%p): stub\n", iface);
2393     return E_NOTIMPL;
2394 }
2395
2396 static const struct IXmlReaderVtbl xmlreader_vtbl =
2397 {
2398     xmlreader_QueryInterface,
2399     xmlreader_AddRef,
2400     xmlreader_Release,
2401     xmlreader_SetInput,
2402     xmlreader_GetProperty,
2403     xmlreader_SetProperty,
2404     xmlreader_Read,
2405     xmlreader_GetNodeType,
2406     xmlreader_MoveToFirstAttribute,
2407     xmlreader_MoveToNextAttribute,
2408     xmlreader_MoveToAttributeByName,
2409     xmlreader_MoveToElement,
2410     xmlreader_GetQualifiedName,
2411     xmlreader_GetNamespaceUri,
2412     xmlreader_GetLocalName,
2413     xmlreader_GetPrefix,
2414     xmlreader_GetValue,
2415     xmlreader_ReadValueChunk,
2416     xmlreader_GetBaseUri,
2417     xmlreader_IsDefault,
2418     xmlreader_IsEmptyElement,
2419     xmlreader_GetLineNumber,
2420     xmlreader_GetLinePosition,
2421     xmlreader_GetAttributeCount,
2422     xmlreader_GetDepth,
2423     xmlreader_IsEOF
2424 };
2425
2426 /** IXmlReaderInput **/
2427 static HRESULT WINAPI xmlreaderinput_QueryInterface(IXmlReaderInput *iface, REFIID riid, void** ppvObject)
2428 {
2429     xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
2430
2431     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
2432
2433     if (IsEqualGUID(riid, &IID_IXmlReaderInput) ||
2434         IsEqualGUID(riid, &IID_IUnknown))
2435     {
2436         *ppvObject = iface;
2437     }
2438     else
2439     {
2440         WARN("interface %s not implemented\n", debugstr_guid(riid));
2441         *ppvObject = NULL;
2442         return E_NOINTERFACE;
2443     }
2444
2445     IUnknown_AddRef(iface);
2446
2447     return S_OK;
2448 }
2449
2450 static ULONG WINAPI xmlreaderinput_AddRef(IXmlReaderInput *iface)
2451 {
2452     xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
2453     ULONG ref = InterlockedIncrement(&This->ref);
2454     TRACE("(%p)->(%d)\n", This, ref);
2455     return ref;
2456 }
2457
2458 static ULONG WINAPI xmlreaderinput_Release(IXmlReaderInput *iface)
2459 {
2460     xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
2461     LONG ref = InterlockedDecrement(&This->ref);
2462
2463     TRACE("(%p)->(%d)\n", This, ref);
2464
2465     if (ref == 0)
2466     {
2467         IMalloc *imalloc = This->imalloc;
2468         if (This->input) IUnknown_Release(This->input);
2469         if (This->stream) ISequentialStream_Release(This->stream);
2470         if (This->buffer) free_input_buffer(This->buffer);
2471         readerinput_free(This, This->baseuri);
2472         readerinput_free(This, This);
2473         if (imalloc) IMalloc_Release(imalloc);
2474     }
2475
2476     return ref;
2477 }
2478
2479 static const struct IUnknownVtbl xmlreaderinputvtbl =
2480 {
2481     xmlreaderinput_QueryInterface,
2482     xmlreaderinput_AddRef,
2483     xmlreaderinput_Release
2484 };
2485
2486 HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
2487 {
2488     xmlreader *reader;
2489     int i;
2490
2491     TRACE("(%s, %p, %p)\n", wine_dbgstr_guid(riid), obj, imalloc);
2492
2493     if (!IsEqualGUID(riid, &IID_IXmlReader))
2494     {
2495         ERR("Unexpected IID requested -> (%s)\n", wine_dbgstr_guid(riid));
2496         return E_FAIL;
2497     }
2498
2499     if (imalloc)
2500         reader = IMalloc_Alloc(imalloc, sizeof(*reader));
2501     else
2502         reader = heap_alloc(sizeof(*reader));
2503     if(!reader) return E_OUTOFMEMORY;
2504
2505     reader->IXmlReader_iface.lpVtbl = &xmlreader_vtbl;
2506     reader->ref = 1;
2507     reader->input = NULL;
2508     reader->state = XmlReadState_Closed;
2509     reader->instate = XmlReadInState_Initial;
2510     reader->resumestate = XmlReadResumeState_Initial;
2511     reader->dtdmode = DtdProcessing_Prohibit;
2512     reader->line  = reader->pos = 0;
2513     reader->imalloc = imalloc;
2514     if (imalloc) IMalloc_AddRef(imalloc);
2515     reader->nodetype = XmlNodeType_None;
2516     list_init(&reader->attrs);
2517     reader->attr_count = 0;
2518     reader->attr = NULL;
2519     list_init(&reader->elements);
2520     reader->depth = 0;
2521     memset(reader->resume, 0, sizeof(reader->resume));
2522
2523     for (i = 0; i < StringValue_Last; i++)
2524         reader->strvalues[i] = strval_empty;
2525
2526     *obj = &reader->IXmlReader_iface;
2527
2528     TRACE("returning iface %p\n", *obj);
2529
2530     return S_OK;
2531 }
2532
2533 HRESULT WINAPI CreateXmlReaderInputWithEncodingName(IUnknown *stream,
2534                                                     IMalloc *imalloc,
2535                                                     LPCWSTR encoding,
2536                                                     BOOL hint,
2537                                                     LPCWSTR base_uri,
2538                                                     IXmlReaderInput **ppInput)
2539 {
2540     xmlreaderinput *readerinput;
2541     HRESULT hr;
2542
2543     TRACE("%p %p %s %d %s %p\n", stream, imalloc, wine_dbgstr_w(encoding),
2544                                        hint, wine_dbgstr_w(base_uri), ppInput);
2545
2546     if (!stream || !ppInput) return E_INVALIDARG;
2547
2548     if (imalloc)
2549         readerinput = IMalloc_Alloc(imalloc, sizeof(*readerinput));
2550     else
2551         readerinput = heap_alloc(sizeof(*readerinput));
2552     if(!readerinput) return E_OUTOFMEMORY;
2553
2554     readerinput->IXmlReaderInput_iface.lpVtbl = &xmlreaderinputvtbl;
2555     readerinput->ref = 1;
2556     readerinput->imalloc = imalloc;
2557     readerinput->stream = NULL;
2558     if (imalloc) IMalloc_AddRef(imalloc);
2559     readerinput->encoding = parse_encoding_name(encoding, -1);
2560     readerinput->hint = hint;
2561     readerinput->baseuri = readerinput_strdupW(readerinput, base_uri);
2562     readerinput->pending = 0;
2563
2564     hr = alloc_input_buffer(readerinput);
2565     if (hr != S_OK)
2566     {
2567         readerinput_free(readerinput, readerinput->baseuri);
2568         readerinput_free(readerinput, readerinput);
2569         if (imalloc) IMalloc_Release(imalloc);
2570         return hr;
2571     }
2572     IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&readerinput->input);
2573
2574     *ppInput = &readerinput->IXmlReaderInput_iface;
2575
2576     TRACE("returning iface %p\n", *ppInput);
2577
2578     return S_OK;
2579 }