jscript: Return BOOL instead of VARIANT_BOOL from jsdisp_is_own_prop.
[wine] / dlls / xmllite / reader.c
1 /*
2  * IXmlReader implementation
3  *
4  * Copyright 2010 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
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(xmllite);
33
34 /* not defined in public headers */
35 DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
36
37 static HRESULT xmlreaderinput_query_for_stream(IXmlReaderInput *iface, void **pObj);
38
39 typedef struct _xmlreader
40 {
41     IXmlReader IXmlReader_iface;
42     LONG ref;
43     IXmlReaderInput *input;
44     ISequentialStream *stream;/* stored as sequential stream, cause currently
45                                  optimizations possible with IStream aren't implemented */
46     XmlReadState state;
47     DtdProcessing dtdmode;
48     UINT line, pos;           /* reader position in XML stream */
49 } xmlreader;
50
51 typedef struct _xmlreaderinput
52 {
53     IXmlReaderInput IXmlReaderInput_iface;
54     LONG ref;
55     IUnknown *input;          /* reference passed on IXmlReaderInput creation */
56 } xmlreaderinput;
57
58 static inline xmlreader *impl_from_IXmlReader(IXmlReader *iface)
59 {
60     return CONTAINING_RECORD(iface, xmlreader, IXmlReader_iface);
61 }
62
63 static inline xmlreaderinput *impl_from_IXmlReaderInput(IXmlReaderInput *iface)
64 {
65     return CONTAINING_RECORD(iface, xmlreaderinput, IXmlReaderInput_iface);
66 }
67
68 static HRESULT WINAPI xmlreader_QueryInterface(IXmlReader *iface, REFIID riid, void** ppvObject)
69 {
70     xmlreader *This = impl_from_IXmlReader(iface);
71
72     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
73
74     if (IsEqualGUID(riid, &IID_IUnknown) ||
75         IsEqualGUID(riid, &IID_IXmlReader))
76     {
77         *ppvObject = iface;
78     }
79     else
80     {
81         FIXME("interface %s not implemented\n", debugstr_guid(riid));
82         return E_NOINTERFACE;
83     }
84
85     IXmlReader_AddRef(iface);
86
87     return S_OK;
88 }
89
90 static ULONG WINAPI xmlreader_AddRef(IXmlReader *iface)
91 {
92     xmlreader *This = impl_from_IXmlReader(iface);
93     TRACE("%p\n", This);
94     return InterlockedIncrement(&This->ref);
95 }
96
97 static ULONG WINAPI xmlreader_Release(IXmlReader *iface)
98 {
99     xmlreader *This = impl_from_IXmlReader(iface);
100     LONG ref;
101
102     TRACE("%p\n", This);
103
104     ref = InterlockedDecrement(&This->ref);
105     if (ref == 0)
106     {
107         if (This->input)  IUnknown_Release(This->input);
108         if (This->stream) ISequentialStream_Release(This->stream);
109         HeapFree(GetProcessHeap(), 0, This);
110     }
111
112     return ref;
113 }
114
115 static HRESULT WINAPI xmlreader_SetInput(IXmlReader* iface, IUnknown *input)
116 {
117     xmlreader *This = impl_from_IXmlReader(iface);
118     HRESULT hr;
119
120     TRACE("(%p %p)\n", This, input);
121
122     if (This->input)
123     {
124         IUnknown_Release(This->input);
125         This->input  = NULL;
126     }
127
128     if (This->stream)
129     {
130         ISequentialStream_Release(This->stream);
131         This->stream = NULL;
132     }
133
134     This->line = This->pos = 0;
135
136     /* just reset current input */
137     if (!input)
138     {
139         This->state = XmlReadState_Initial;
140         return S_OK;
141     }
142
143     /* now try IXmlReaderInput, ISequentialStream, IStream */
144     hr = IUnknown_QueryInterface(input, &IID_IXmlReaderInput, (void**)&This->input);
145     if (hr != S_OK)
146     {
147         /* create IXmlReaderInput basing on supplied interface */
148         hr = CreateXmlReaderInputWithEncodingName(input,
149                                          NULL, NULL, FALSE, NULL, &This->input);
150         if (hr != S_OK) return hr;
151     }
152
153     /* set stream for supplied IXmlReaderInput */
154     hr = xmlreaderinput_query_for_stream(This->input, (void**)&This->stream);
155     if (hr == S_OK)
156         This->state = XmlReadState_Initial;
157
158     return hr;
159 }
160
161 static HRESULT WINAPI xmlreader_GetProperty(IXmlReader* iface, UINT property, LONG_PTR *value)
162 {
163     xmlreader *This = impl_from_IXmlReader(iface);
164
165     TRACE("(%p %u %p)\n", This, property, value);
166
167     if (!value) return E_INVALIDARG;
168
169     switch (property)
170     {
171         case XmlReaderProperty_DtdProcessing:
172             *value = This->dtdmode;
173             break;
174         case XmlReaderProperty_ReadState:
175             *value = This->state;
176             break;
177         default:
178             FIXME("Unimplemented property (%u)\n", property);
179             return E_NOTIMPL;
180     }
181
182     return S_OK;
183 }
184
185 static HRESULT WINAPI xmlreader_SetProperty(IXmlReader* iface, UINT property, LONG_PTR value)
186 {
187     xmlreader *This = impl_from_IXmlReader(iface);
188
189     TRACE("(%p %u %lu)\n", iface, property, value);
190
191     switch (property)
192     {
193         case XmlReaderProperty_DtdProcessing:
194             if (value < 0 || value > _DtdProcessing_Last) return E_INVALIDARG;
195             This->dtdmode = value;
196             break;
197         default:
198             FIXME("Unimplemented property (%u)\n", property);
199             return E_NOTIMPL;
200     }
201
202     return S_OK;
203 }
204
205 static HRESULT WINAPI xmlreader_Read(IXmlReader* iface, XmlNodeType *node_type)
206 {
207     FIXME("(%p %p): stub\n", iface, node_type);
208     return E_NOTIMPL;
209 }
210
211 static HRESULT WINAPI xmlreader_GetNodeType(IXmlReader* iface, XmlNodeType *node_type)
212 {
213     FIXME("(%p %p): stub\n", iface, node_type);
214     return E_NOTIMPL;
215 }
216
217 static HRESULT WINAPI xmlreader_MoveToFirstAttribute(IXmlReader* iface)
218 {
219     FIXME("(%p): stub\n", iface);
220     return E_NOTIMPL;
221 }
222
223 static HRESULT WINAPI xmlreader_MoveToNextAttribute(IXmlReader* iface)
224 {
225     FIXME("(%p): stub\n", iface);
226     return E_NOTIMPL;
227 }
228
229 static HRESULT WINAPI xmlreader_MoveToAttributeByName(IXmlReader* iface,
230                                                       LPCWSTR local_name,
231                                                       LPCWSTR namespaceUri)
232 {
233     FIXME("(%p %p %p): stub\n", iface, local_name, namespaceUri);
234     return E_NOTIMPL;
235 }
236
237 static HRESULT WINAPI xmlreader_MoveToElement(IXmlReader* iface)
238 {
239     FIXME("(%p): stub\n", iface);
240     return E_NOTIMPL;
241 }
242
243 static HRESULT WINAPI xmlreader_GetQualifiedName(IXmlReader* iface, LPCWSTR *qualifiedName,
244                                                  UINT *qualifiedName_length)
245 {
246     FIXME("(%p %p %p): stub\n", iface, qualifiedName, qualifiedName_length);
247     return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI xmlreader_GetNamespaceUri(IXmlReader* iface,
251                                                 LPCWSTR *namespaceUri,
252                                                 UINT *namespaceUri_length)
253 {
254     FIXME("(%p %p %p): stub\n", iface, namespaceUri, namespaceUri_length);
255     return E_NOTIMPL;
256 }
257
258 static HRESULT WINAPI xmlreader_GetLocalName(IXmlReader* iface,
259                                              LPCWSTR *local_name,
260                                              UINT *local_name_length)
261 {
262     FIXME("(%p %p %p): stub\n", iface, local_name, local_name_length);
263     return E_NOTIMPL;
264 }
265
266 static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface,
267                                           LPCWSTR *prefix,
268                                           UINT *prefix_length)
269 {
270     FIXME("(%p %p %p): stub\n", iface, prefix, prefix_length);
271     return E_NOTIMPL;
272 }
273
274 static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface,
275                                          LPCWSTR *value,
276                                          UINT *value_length)
277 {
278     FIXME("(%p %p %p): stub\n", iface, value, value_length);
279     return E_NOTIMPL;
280 }
281
282 static HRESULT WINAPI xmlreader_ReadValueChunk(IXmlReader* iface,
283                                                WCHAR *buffer,
284                                                UINT   chunk_size,
285                                                UINT  *read)
286 {
287     FIXME("(%p %p %u %p): stub\n", iface, buffer, chunk_size, read);
288     return E_NOTIMPL;
289 }
290
291 static HRESULT WINAPI xmlreader_GetBaseUri(IXmlReader* iface,
292                                            LPCWSTR *baseUri,
293                                            UINT *baseUri_length)
294 {
295     FIXME("(%p %p %p): stub\n", iface, baseUri, baseUri_length);
296     return E_NOTIMPL;
297 }
298
299 static BOOL WINAPI xmlreader_IsDefault(IXmlReader* iface)
300 {
301     FIXME("(%p): stub\n", iface);
302     return E_NOTIMPL;
303 }
304
305 static BOOL WINAPI xmlreader_IsEmptyElement(IXmlReader* iface)
306 {
307     FIXME("(%p): stub\n", iface);
308     return E_NOTIMPL;
309 }
310
311 static HRESULT WINAPI xmlreader_GetLineNumber(IXmlReader* iface, UINT *lineNumber)
312 {
313     xmlreader *This = impl_from_IXmlReader(iface);
314
315     TRACE("(%p %p)\n", This, lineNumber);
316
317     if (!lineNumber) return E_INVALIDARG;
318
319     *lineNumber = This->line;
320
321     return S_OK;
322 }
323
324 static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *linePosition)
325 {
326     xmlreader *This = impl_from_IXmlReader(iface);
327
328     TRACE("(%p %p)\n", This, linePosition);
329
330     if (!linePosition) return E_INVALIDARG;
331
332     *linePosition = This->pos;
333
334     return S_OK;
335 }
336
337 static HRESULT WINAPI xmlreader_GetAttributeCount(IXmlReader* iface, UINT *attributeCount)
338 {
339     FIXME("(%p %p): stub\n", iface, attributeCount);
340     return E_NOTIMPL;
341 }
342
343 static HRESULT WINAPI xmlreader_GetDepth(IXmlReader* iface, UINT *depth)
344 {
345     FIXME("(%p %p): stub\n", iface, depth);
346     return E_NOTIMPL;
347 }
348
349 static BOOL WINAPI xmlreader_IsEOF(IXmlReader* iface)
350 {
351     FIXME("(%p): stub\n", iface);
352     return E_NOTIMPL;
353 }
354
355 static const struct IXmlReaderVtbl xmlreader_vtbl =
356 {
357     xmlreader_QueryInterface,
358     xmlreader_AddRef,
359     xmlreader_Release,
360     xmlreader_SetInput,
361     xmlreader_GetProperty,
362     xmlreader_SetProperty,
363     xmlreader_Read,
364     xmlreader_GetNodeType,
365     xmlreader_MoveToFirstAttribute,
366     xmlreader_MoveToNextAttribute,
367     xmlreader_MoveToAttributeByName,
368     xmlreader_MoveToElement,
369     xmlreader_GetQualifiedName,
370     xmlreader_GetNamespaceUri,
371     xmlreader_GetLocalName,
372     xmlreader_GetPrefix,
373     xmlreader_GetValue,
374     xmlreader_ReadValueChunk,
375     xmlreader_GetBaseUri,
376     xmlreader_IsDefault,
377     xmlreader_IsEmptyElement,
378     xmlreader_GetLineNumber,
379     xmlreader_GetLinePosition,
380     xmlreader_GetAttributeCount,
381     xmlreader_GetDepth,
382     xmlreader_IsEOF
383 };
384
385 /** IXmlReaderInput **/
386
387 /* Queries already stored interface for IStream/ISequentialStream.
388    Interface supplied on creation will be overwritten */
389 static HRESULT xmlreaderinput_query_for_stream(IXmlReaderInput *iface, void **pObj)
390 {
391     xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
392     HRESULT hr;
393
394     hr = IUnknown_QueryInterface(This->input, &IID_IStream, pObj);
395     if (hr != S_OK)
396         hr = IUnknown_QueryInterface(This->input, &IID_ISequentialStream, pObj);
397
398     return hr;
399 }
400
401 static HRESULT WINAPI xmlreaderinput_QueryInterface(IXmlReaderInput *iface, REFIID riid, void** ppvObject)
402 {
403     xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
404
405     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
406
407     if (IsEqualGUID(riid, &IID_IXmlReaderInput) ||
408         IsEqualGUID(riid, &IID_IUnknown))
409     {
410         *ppvObject = iface;
411     }
412     else
413     {
414         FIXME("interface %s not implemented\n", debugstr_guid(riid));
415         return E_NOINTERFACE;
416     }
417
418     IUnknown_AddRef(iface);
419
420     return S_OK;
421 }
422
423 static ULONG WINAPI xmlreaderinput_AddRef(IXmlReaderInput *iface)
424 {
425     xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
426     TRACE("%p\n", This);
427     return InterlockedIncrement(&This->ref);
428 }
429
430 static ULONG WINAPI xmlreaderinput_Release(IXmlReaderInput *iface)
431 {
432     xmlreaderinput *This = impl_from_IXmlReaderInput(iface);
433     LONG ref;
434
435     TRACE("%p\n", This);
436
437     ref = InterlockedDecrement(&This->ref);
438     if (ref == 0)
439     {
440         if (This->input) IUnknown_Release(This->input);
441         HeapFree(GetProcessHeap(), 0, This);
442     }
443
444     return ref;
445 }
446
447 static const struct IUnknownVtbl xmlreaderinput_vtbl =
448 {
449     xmlreaderinput_QueryInterface,
450     xmlreaderinput_AddRef,
451     xmlreaderinput_Release
452 };
453
454 HRESULT WINAPI CreateXmlReader(REFIID riid, void **pObject, IMalloc *pMalloc)
455 {
456     xmlreader *reader;
457
458     TRACE("(%s, %p, %p)\n", wine_dbgstr_guid(riid), pObject, pMalloc);
459
460     if (pMalloc) FIXME("custom IMalloc not supported yet\n");
461
462     if (!IsEqualGUID(riid, &IID_IXmlReader))
463     {
464         ERR("Unexpected IID requested -> (%s)\n", wine_dbgstr_guid(riid));
465         return E_FAIL;
466     }
467
468     reader = HeapAlloc(GetProcessHeap(), 0, sizeof (*reader));
469     if(!reader) return E_OUTOFMEMORY;
470
471     reader->IXmlReader_iface.lpVtbl = &xmlreader_vtbl;
472     reader->ref = 1;
473     reader->stream = NULL;
474     reader->input = NULL;
475     reader->state = XmlReadState_Closed;
476     reader->dtdmode = DtdProcessing_Prohibit;
477     reader->line  = reader->pos = 0;
478
479     *pObject = &reader->IXmlReader_iface;
480
481     TRACE("returning iface %p\n", *pObject);
482
483     return S_OK;
484 }
485
486 HRESULT WINAPI CreateXmlReaderInputWithEncodingName(IUnknown *stream,
487                                                     IMalloc *pMalloc,
488                                                     LPCWSTR encoding,
489                                                     BOOL hint,
490                                                     LPCWSTR base_uri,
491                                                     IXmlReaderInput **ppInput)
492 {
493     xmlreaderinput *readerinput;
494
495     FIXME("%p %p %s %d %s %p: stub\n", stream, pMalloc, wine_dbgstr_w(encoding),
496                                        hint, wine_dbgstr_w(base_uri), ppInput);
497
498     if (!stream || !ppInput) return E_INVALIDARG;
499
500     readerinput = HeapAlloc(GetProcessHeap(), 0, sizeof (*readerinput));
501     if(!readerinput) return E_OUTOFMEMORY;
502
503     readerinput->IXmlReaderInput_iface.lpVtbl = &xmlreaderinput_vtbl;
504     readerinput->ref = 1;
505     IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&readerinput->input);
506
507     *ppInput = &readerinput->IXmlReaderInput_iface;
508
509     TRACE("returning iface %p\n", *ppInput);
510
511     return S_OK;
512 }