xmllite: Store remaining reader input parameters.
[wine/multimedia.git] / dlls / xmllite / reader.c
blob3f2215226dd449b63978857b3d2f4b6fbe1a66c9
1 /*
2 * IXmlReader implementation
4 * Copyright 2010 Nikolay Sivov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include <stdarg.h>
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"
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(xmllite);
36 /* not defined in public headers */
37 DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
39 typedef enum
41 XmlEncoding_UTF16,
42 XmlEncoding_UTF8,
43 XmlEncoding_Unknown
44 } xml_encoding;
46 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0};
47 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
49 struct xml_encoding_data
51 const WCHAR *encoding;
52 xml_encoding enc;
53 UINT cp;
56 static const struct xml_encoding_data xml_encoding_map[] = {
57 { utf16W, XmlEncoding_UTF16, ~0 },
58 { utf8W, XmlEncoding_UTF8, CP_UTF8 }
61 typedef struct
63 char *data;
64 unsigned int allocated;
65 unsigned int written;
66 } encoded_buffer;
68 typedef struct input_buffer input_buffer;
70 typedef struct _xmlreaderinput
72 IXmlReaderInput IXmlReaderInput_iface;
73 LONG ref;
74 /* reference passed on IXmlReaderInput creation, is kept when input is created */
75 IUnknown *input;
76 IMalloc *imalloc;
77 xml_encoding encoding;
78 BOOL hint;
79 WCHAR *baseuri;
80 /* stream reference set after SetInput() call from reader,
81 stored as sequential stream, cause currently
82 optimizations possible with IStream aren't implemented */
83 ISequentialStream *stream;
84 input_buffer *buffer;
85 } xmlreaderinput;
87 typedef struct _xmlreader
89 IXmlReader IXmlReader_iface;
90 LONG ref;
91 xmlreaderinput *input;
92 IMalloc *imalloc;
93 XmlReadState state;
94 XmlNodeType nodetype;
95 DtdProcessing dtdmode;
96 UINT line, pos; /* reader position in XML stream */
97 } xmlreader;
99 struct input_buffer
101 encoded_buffer utf16;
102 encoded_buffer encoded;
103 UINT code_page;
104 xmlreaderinput *input;
107 static inline xmlreader *impl_from_IXmlReader(IXmlReader *iface)
109 return CONTAINING_RECORD(iface, xmlreader, IXmlReader_iface);
112 static inline xmlreaderinput *impl_from_IXmlReaderInput(IXmlReaderInput *iface)
114 return CONTAINING_RECORD(iface, xmlreaderinput, IXmlReaderInput_iface);
117 static inline void *m_alloc(IMalloc *imalloc, size_t len)
119 if (imalloc)
120 return IMalloc_Alloc(imalloc, len);
121 else
122 return heap_alloc(len);
125 static inline void *m_realloc(IMalloc *imalloc, void *mem, size_t len)
127 if (imalloc)
128 return IMalloc_Realloc(imalloc, mem, len);
129 else
130 return heap_realloc(mem, len);
133 static inline void m_free(IMalloc *imalloc, void *mem)
135 if (imalloc)
136 IMalloc_Free(imalloc, mem);
137 else
138 heap_free(mem);
141 /* reader memory allocation functions */
142 static inline void *reader_alloc(xmlreader *reader, size_t len)
144 return m_alloc(reader->imalloc, len);
147 static inline void reader_free(xmlreader *reader, void *mem)
149 return m_free(reader->imalloc, mem);
152 /* reader input memory allocation functions */
153 static inline void *readerinput_alloc(xmlreaderinput *input, size_t len)
155 return m_alloc(input->imalloc, len);
158 static inline void *readerinput_realloc(xmlreaderinput *input, void *mem, size_t len)
160 return m_realloc(input->imalloc, mem, len);
163 static inline void readerinput_free(xmlreaderinput *input, void *mem)
165 return m_free(input->imalloc, mem);
168 static inline WCHAR *readerinput_strdupW(xmlreaderinput *input, const WCHAR *str)
170 LPWSTR ret = NULL;
172 if(str) {
173 DWORD size;
175 size = (strlenW(str)+1)*sizeof(WCHAR);
176 ret = readerinput_alloc(input, size);
177 if (ret) memcpy(ret, str, size);
180 return ret;
183 static HRESULT init_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer)
185 const int initial_len = 0x2000;
186 buffer->data = readerinput_alloc(input, initial_len);
187 if (!buffer->data) return E_OUTOFMEMORY;
189 memset(buffer->data, 0, 4);
190 buffer->allocated = initial_len;
191 buffer->written = 0;
193 return S_OK;
196 static void free_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer)
198 readerinput_free(input, buffer->data);
201 static HRESULT get_code_page(xml_encoding encoding, xmlreaderinput *input)
203 const struct xml_encoding_data *data;
205 if (encoding == XmlEncoding_Unknown)
207 FIXME("unsupported encoding %d\n", encoding);
208 return E_NOTIMPL;
211 data = &xml_encoding_map[encoding];
212 input->buffer->code_page = data->cp;
214 return S_OK;
217 static xml_encoding parse_encoding_name(const WCHAR *encoding)
219 int min, max, n, c;
221 if (!encoding) return XmlEncoding_Unknown;
223 min = 0;
224 max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1;
226 while (min <= max)
228 n = (min+max)/2;
230 c = strcmpiW(xml_encoding_map[n].encoding, encoding);
231 if (!c)
232 return xml_encoding_map[n].enc;
234 if (c > 0)
235 max = n-1;
236 else
237 min = n+1;
240 return XmlEncoding_Unknown;
243 static HRESULT alloc_input_buffer(xmlreaderinput *input)
245 input_buffer *buffer;
246 HRESULT hr;
248 input->buffer = NULL;
250 buffer = readerinput_alloc(input, sizeof(*buffer));
251 if (!buffer) return E_OUTOFMEMORY;
253 buffer->input = input;
254 buffer->code_page = ~0; /* code page is unknown at this point */
255 hr = init_encoded_buffer(input, &buffer->utf16);
256 if (hr != S_OK) {
257 readerinput_free(input, buffer);
258 return hr;
261 hr = init_encoded_buffer(input, &buffer->encoded);
262 if (hr != S_OK) {
263 free_encoded_buffer(input, &buffer->utf16);
264 readerinput_free(input, buffer);
265 return hr;
268 input->buffer = buffer;
269 return S_OK;
272 static void free_input_buffer(input_buffer *buffer)
274 free_encoded_buffer(buffer->input, &buffer->encoded);
275 free_encoded_buffer(buffer->input, &buffer->utf16);
276 readerinput_free(buffer->input, buffer);
279 static void readerinput_release_stream(xmlreaderinput *readerinput)
281 if (readerinput->stream) {
282 ISequentialStream_Release(readerinput->stream);
283 readerinput->stream = NULL;
287 /* Queries already stored interface for IStream/ISequentialStream.
288 Interface supplied on creation will be overwritten */
289 static HRESULT readerinput_query_for_stream(xmlreaderinput *readerinput)
291 HRESULT hr;
293 readerinput_release_stream(readerinput);
294 hr = IUnknown_QueryInterface(readerinput->input, &IID_IStream, (void**)&readerinput->stream);
295 if (hr != S_OK)
296 hr = IUnknown_QueryInterface(readerinput->input, &IID_ISequentialStream, (void**)&readerinput->stream);
298 return hr;
301 /* reads a chunk to raw buffer */
302 static HRESULT readerinput_growraw(xmlreaderinput *readerinput)
304 encoded_buffer *buffer = &readerinput->buffer->encoded;
305 ULONG len = buffer->allocated - buffer->written, read;
306 HRESULT hr;
308 /* always try to get aligned to 4 bytes, so the only case we can get partialy read characters is
309 variable width encodings like UTF-8 */
310 len = (len + 3) & ~3;
311 /* try to use allocated space or grow */
312 if (buffer->allocated - buffer->written < len)
314 buffer->allocated *= 2;
315 buffer->data = readerinput_realloc(readerinput, buffer->data, buffer->allocated);
316 len = buffer->allocated - buffer->written;
319 hr = ISequentialStream_Read(readerinput->stream, buffer->data + buffer->written, len, &read);
320 if (FAILED(hr)) return hr;
321 TRACE("requested %d, read %d, ret 0x%08x\n", len, read, hr);
322 buffer->written += read;
324 return hr;
327 static xml_encoding readerinput_detectencoding(xmlreaderinput *readerinput)
329 encoded_buffer *buffer = &readerinput->buffer->encoded;
331 /* try start symbols if we have enough data to do that, input buffer should contain
332 first chunk already */
333 if (buffer->written >= 4)
335 static char startA[] = {'<','?','x','m'};
336 static WCHAR startW[] = {'<','?'};
338 if (!memcmp(buffer->data, startA, sizeof(startA))) return XmlEncoding_UTF8;
339 if (!memcmp(buffer->data, startW, sizeof(startW))) return XmlEncoding_UTF16;
342 /* try with BOM now */
343 if (buffer->written >= 3)
345 static char utf8bom[] = {0xef,0xbb,0xbf};
346 static char utf16lebom[] = {0xff,0xfe};
347 if (!memcmp(buffer->data, utf8bom, sizeof(utf8bom))) return XmlEncoding_UTF8;
348 if (!memcmp(buffer->data, utf16lebom, sizeof(utf16lebom))) return XmlEncoding_UTF16;
351 return XmlEncoding_Unknown;
354 static HRESULT WINAPI xmlreader_QueryInterface(IXmlReader *iface, REFIID riid, void** ppvObject)
356 xmlreader *This = impl_from_IXmlReader(iface);
358 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
360 if (IsEqualGUID(riid, &IID_IUnknown) ||
361 IsEqualGUID(riid, &IID_IXmlReader))
363 *ppvObject = iface;
365 else
367 FIXME("interface %s not implemented\n", debugstr_guid(riid));
368 return E_NOINTERFACE;
371 IXmlReader_AddRef(iface);
373 return S_OK;
376 static ULONG WINAPI xmlreader_AddRef(IXmlReader *iface)
378 xmlreader *This = impl_from_IXmlReader(iface);
379 ULONG ref = InterlockedIncrement(&This->ref);
380 TRACE("(%p)->(%d)\n", This, ref);
381 return ref;
384 static ULONG WINAPI xmlreader_Release(IXmlReader *iface)
386 xmlreader *This = impl_from_IXmlReader(iface);
387 LONG ref = InterlockedDecrement(&This->ref);
389 TRACE("(%p)->(%d)\n", This, ref);
391 if (ref == 0)
393 IMalloc *imalloc = This->imalloc;
394 if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface);
395 reader_free(This, This);
396 if (imalloc) IMalloc_Release(imalloc);
399 return ref;
402 static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input)
404 xmlreader *This = impl_from_IXmlReader(iface);
405 HRESULT hr;
407 TRACE("(%p %p)\n", This, input);
409 if (This->input)
411 readerinput_release_stream(This->input);
412 IUnknown_Release(&This->input->IXmlReaderInput_iface);
413 This->input = NULL;
416 This->line = This->pos = 0;
418 /* just reset current input */
419 if (!input)
421 This->state = XmlReadState_Initial;
422 return S_OK;
425 /* now try IXmlReaderInput, ISequentialStream, IStream */
426 hr = IUnknown_QueryInterface(input, &IID_IXmlReaderInput, (void**)&This->input);
427 if (hr != S_OK)
429 IXmlReaderInput *readerinput;
431 /* create IXmlReaderInput basing on supplied interface */
432 hr = CreateXmlReaderInputWithEncodingName(input,
433 NULL, NULL, FALSE, NULL, &readerinput);
434 if (hr != S_OK) return hr;
435 This->input = impl_from_IXmlReaderInput(readerinput);
438 /* set stream for supplied IXmlReaderInput */
439 hr = readerinput_query_for_stream(This->input);
440 if (hr == S_OK)
441 This->state = XmlReadState_Initial;
443 return hr;
446 static HRESULT WINAPI xmlreader_GetProperty(IXmlReader* iface, UINT property, LONG_PTR *value)
448 xmlreader *This = impl_from_IXmlReader(iface);
450 TRACE("(%p %u %p)\n", This, property, value);
452 if (!value) return E_INVALIDARG;
454 switch (property)
456 case XmlReaderProperty_DtdProcessing:
457 *value = This->dtdmode;
458 break;
459 case XmlReaderProperty_ReadState:
460 *value = This->state;
461 break;
462 default:
463 FIXME("Unimplemented property (%u)\n", property);
464 return E_NOTIMPL;
467 return S_OK;
470 static HRESULT WINAPI xmlreader_SetProperty(IXmlReader* iface, UINT property, LONG_PTR value)
472 xmlreader *This = impl_from_IXmlReader(iface);
474 TRACE("(%p %u %lu)\n", iface, property, value);
476 switch (property)
478 case XmlReaderProperty_DtdProcessing:
479 if (value < 0 || value > _DtdProcessing_Last) return E_INVALIDARG;
480 This->dtdmode = value;
481 break;
482 default:
483 FIXME("Unimplemented property (%u)\n", property);
484 return E_NOTIMPL;
487 return S_OK;
490 static HRESULT WINAPI xmlreader_Read(IXmlReader* iface, XmlNodeType *node_type)
492 xmlreader *This = impl_from_IXmlReader(iface);
494 FIXME("(%p)->(%p): stub\n", This, node_type);
496 if (This->state == XmlReadState_Closed) return S_FALSE;
498 /* if it's a first call for a new input we need to detect stream encoding */
499 if (This->state == XmlReadState_Initial)
501 xml_encoding enc;
502 HRESULT hr;
504 hr = readerinput_growraw(This->input);
505 if (FAILED(hr)) return hr;
507 /* try to detect encoding by BOM or data and set input code page */
508 enc = readerinput_detectencoding(This->input);
509 TRACE("detected encoding %d\n", enc);
510 get_code_page(enc, This->input);
513 return E_NOTIMPL;
516 static HRESULT WINAPI xmlreader_GetNodeType(IXmlReader* iface, XmlNodeType *node_type)
518 xmlreader *This = impl_from_IXmlReader(iface);
519 TRACE("(%p)->(%p)\n", This, node_type);
520 *node_type = This->nodetype;
521 return This->state == XmlReadState_Closed ? S_FALSE : S_OK;
524 static HRESULT WINAPI xmlreader_MoveToFirstAttribute(IXmlReader* iface)
526 FIXME("(%p): stub\n", iface);
527 return E_NOTIMPL;
530 static HRESULT WINAPI xmlreader_MoveToNextAttribute(IXmlReader* iface)
532 FIXME("(%p): stub\n", iface);
533 return E_NOTIMPL;
536 static HRESULT WINAPI xmlreader_MoveToAttributeByName(IXmlReader* iface,
537 LPCWSTR local_name,
538 LPCWSTR namespaceUri)
540 FIXME("(%p %p %p): stub\n", iface, local_name, namespaceUri);
541 return E_NOTIMPL;
544 static HRESULT WINAPI xmlreader_MoveToElement(IXmlReader* iface)
546 FIXME("(%p): stub\n", iface);
547 return E_NOTIMPL;
550 static HRESULT WINAPI xmlreader_GetQualifiedName(IXmlReader* iface, LPCWSTR *qualifiedName,
551 UINT *qualifiedName_length)
553 FIXME("(%p %p %p): stub\n", iface, qualifiedName, qualifiedName_length);
554 return E_NOTIMPL;
557 static HRESULT WINAPI xmlreader_GetNamespaceUri(IXmlReader* iface,
558 LPCWSTR *namespaceUri,
559 UINT *namespaceUri_length)
561 FIXME("(%p %p %p): stub\n", iface, namespaceUri, namespaceUri_length);
562 return E_NOTIMPL;
565 static HRESULT WINAPI xmlreader_GetLocalName(IXmlReader* iface,
566 LPCWSTR *local_name,
567 UINT *local_name_length)
569 FIXME("(%p %p %p): stub\n", iface, local_name, local_name_length);
570 return E_NOTIMPL;
573 static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface,
574 LPCWSTR *prefix,
575 UINT *prefix_length)
577 FIXME("(%p %p %p): stub\n", iface, prefix, prefix_length);
578 return E_NOTIMPL;
581 static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface,
582 LPCWSTR *value,
583 UINT *value_length)
585 FIXME("(%p %p %p): stub\n", iface, value, value_length);
586 return E_NOTIMPL;
589 static HRESULT WINAPI xmlreader_ReadValueChunk(IXmlReader* iface,
590 WCHAR *buffer,
591 UINT chunk_size,
592 UINT *read)
594 FIXME("(%p %p %u %p): stub\n", iface, buffer, chunk_size, read);
595 return E_NOTIMPL;
598 static HRESULT WINAPI xmlreader_GetBaseUri(IXmlReader* iface,
599 LPCWSTR *baseUri,
600 UINT *baseUri_length)
602 FIXME("(%p %p %p): stub\n", iface, baseUri, baseUri_length);
603 return E_NOTIMPL;
606 static BOOL WINAPI xmlreader_IsDefault(IXmlReader* iface)
608 FIXME("(%p): stub\n", iface);
609 return E_NOTIMPL;
612 static BOOL WINAPI xmlreader_IsEmptyElement(IXmlReader* iface)
614 FIXME("(%p): stub\n", iface);
615 return E_NOTIMPL;
618 static HRESULT WINAPI xmlreader_GetLineNumber(IXmlReader* iface, UINT *lineNumber)
620 xmlreader *This = impl_from_IXmlReader(iface);
622 TRACE("(%p %p)\n", This, lineNumber);
624 if (!lineNumber) return E_INVALIDARG;
626 *lineNumber = This->line;
628 return S_OK;
631 static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *linePosition)
633 xmlreader *This = impl_from_IXmlReader(iface);
635 TRACE("(%p %p)\n", This, linePosition);
637 if (!linePosition) return E_INVALIDARG;
639 *linePosition = This->pos;
641 return S_OK;
644 static HRESULT WINAPI xmlreader_GetAttributeCount(IXmlReader* iface, UINT *attributeCount)
646 FIXME("(%p %p): stub\n", iface, attributeCount);
647 return E_NOTIMPL;
650 static HRESULT WINAPI xmlreader_GetDepth(IXmlReader* iface, UINT *depth)
652 FIXME("(%p %p): stub\n", iface, depth);
653 return E_NOTIMPL;
656 static BOOL WINAPI xmlreader_IsEOF(IXmlReader* iface)
658 FIXME("(%p): stub\n", iface);
659 return E_NOTIMPL;
662 static const struct IXmlReaderVtbl xmlreader_vtbl =
664 xmlreader_QueryInterface,
665 xmlreader_AddRef,
666 xmlreader_Release,
667 xmlreader_SetInput,
668 xmlreader_GetProperty,
669 xmlreader_SetProperty,
670 xmlreader_Read,
671 xmlreader_GetNodeType,
672 xmlreader_MoveToFirstAttribute,
673 xmlreader_MoveToNextAttribute,
674 xmlreader_MoveToAttributeByName,
675 xmlreader_MoveToElement,
676 xmlreader_GetQualifiedName,
677 xmlreader_GetNamespaceUri,
678 xmlreader_GetLocalName,
679 xmlreader_GetPrefix,
680 xmlreader_GetValue,
681 xmlreader_ReadValueChunk,
682 xmlreader_GetBaseUri,
683 xmlreader_IsDefault,
684 xmlreader_IsEmptyElement,
685 xmlreader_GetLineNumber,
686 xmlreader_GetLinePosition,
687 xmlreader_GetAttributeCount,
688 xmlreader_GetDepth,
689 xmlreader_IsEOF
692 /** IXmlReaderInput **/
693 static HRESULT WINAPI xmlreaderinput_QueryInterface(IXmlReaderInput *iface, REFIID riid, void** ppvObject)
695 xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
697 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
699 if (IsEqualGUID(riid, &IID_IXmlReaderInput) ||
700 IsEqualGUID(riid, &IID_IUnknown))
702 *ppvObject = iface;
704 else
706 WARN("interface %s not implemented\n", debugstr_guid(riid));
707 return E_NOINTERFACE;
710 IUnknown_AddRef(iface);
712 return S_OK;
715 static ULONG WINAPI xmlreaderinput_AddRef(IXmlReaderInput *iface)
717 xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
718 ULONG ref = InterlockedIncrement(&This->ref);
719 TRACE("(%p)->(%d)\n", This, ref);
720 return ref;
723 static ULONG WINAPI xmlreaderinput_Release(IXmlReaderInput *iface)
725 xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
726 LONG ref = InterlockedDecrement(&This->ref);
728 TRACE("(%p)->(%d)\n", This, ref);
730 if (ref == 0)
732 IMalloc *imalloc = This->imalloc;
733 if (This->input) IUnknown_Release(This->input);
734 if (This->stream) ISequentialStream_Release(This->stream);
735 if (This->buffer) free_input_buffer(This->buffer);
736 readerinput_free(This, This->baseuri);
737 readerinput_free(This, This);
738 if (imalloc) IMalloc_Release(imalloc);
741 return ref;
744 static const struct IUnknownVtbl xmlreaderinput_vtbl =
746 xmlreaderinput_QueryInterface,
747 xmlreaderinput_AddRef,
748 xmlreaderinput_Release
751 HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
753 xmlreader *reader;
755 TRACE("(%s, %p, %p)\n", wine_dbgstr_guid(riid), obj, imalloc);
757 if (!IsEqualGUID(riid, &IID_IXmlReader))
759 ERR("Unexpected IID requested -> (%s)\n", wine_dbgstr_guid(riid));
760 return E_FAIL;
763 if (imalloc)
764 reader = IMalloc_Alloc(imalloc, sizeof(*reader));
765 else
766 reader = heap_alloc(sizeof(*reader));
767 if(!reader) return E_OUTOFMEMORY;
769 reader->IXmlReader_iface.lpVtbl = &xmlreader_vtbl;
770 reader->ref = 1;
771 reader->input = NULL;
772 reader->state = XmlReadState_Closed;
773 reader->dtdmode = DtdProcessing_Prohibit;
774 reader->line = reader->pos = 0;
775 reader->imalloc = imalloc;
776 if (imalloc) IMalloc_AddRef(imalloc);
777 reader->nodetype = XmlNodeType_None;
779 *obj = &reader->IXmlReader_iface;
781 TRACE("returning iface %p\n", *obj);
783 return S_OK;
786 HRESULT WINAPI CreateXmlReaderInputWithEncodingName(IUnknown *stream,
787 IMalloc *imalloc,
788 LPCWSTR encoding,
789 BOOL hint,
790 LPCWSTR base_uri,
791 IXmlReaderInput **ppInput)
793 xmlreaderinput *readerinput;
794 HRESULT hr;
796 TRACE("%p %p %s %d %s %p\n", stream, imalloc, wine_dbgstr_w(encoding),
797 hint, wine_dbgstr_w(base_uri), ppInput);
799 if (!stream || !ppInput) return E_INVALIDARG;
801 if (imalloc)
802 readerinput = IMalloc_Alloc(imalloc, sizeof(*readerinput));
803 else
804 readerinput = heap_alloc(sizeof(*readerinput));
805 if(!readerinput) return E_OUTOFMEMORY;
807 readerinput->IXmlReaderInput_iface.lpVtbl = &xmlreaderinput_vtbl;
808 readerinput->ref = 1;
809 readerinput->imalloc = imalloc;
810 readerinput->stream = NULL;
811 if (imalloc) IMalloc_AddRef(imalloc);
812 readerinput->encoding = parse_encoding_name(encoding);
813 readerinput->hint = hint;
814 readerinput->baseuri = readerinput_strdupW(readerinput, base_uri);
816 hr = alloc_input_buffer(readerinput);
817 if (hr != S_OK)
819 readerinput_free(readerinput, readerinput);
820 return hr;
822 IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&readerinput->input);
824 *ppInput = &readerinput->IXmlReaderInput_iface;
826 TRACE("returning iface %p\n", *ppInput);
828 return S_OK;