ws2_32: Return a valid value for WSAIoctl SIO_IDEAL_SEND_BACKLOG_QUERY.
[wine.git] / dlls / msxml3 / selection.c
blobe7c63c7a2b2ef7c3c32aca43189d1480eeef37c6
1 /*
2 * XPath/XSLPattern query result node list implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2007 Mikolaj Zalewski
6 * Copyright 2010 Adam Martinson for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define COBJMACROS
25 #include <stdarg.h>
26 #include <libxml/parser.h>
27 #include <libxml/xmlerror.h>
28 #include <libxml/xpath.h>
29 #include <libxml/xpathInternals.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "msxml6.h"
36 #include "msxml2did.h"
38 #include "msxml_private.h"
40 #include "wine/debug.h"
42 /* This file implements the object returned by a XPath query. Note that this is
43 * not the IXMLDOMNodeList returned by childNodes - it's implemented in nodelist.c.
44 * They are different because the list returned by XPath queries:
45 * - is static - gives the results for the XML tree as it existed during the
46 * execution of the query
47 * - supports IXMLDOMSelection
51 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
53 int registerNamespaces(xmlXPathContextPtr ctxt);
54 xmlChar* XSLPattern_to_XPath(xmlXPathContextPtr ctxt, xmlChar const* xslpat_str);
56 typedef struct
58 IEnumVARIANT IEnumVARIANT_iface;
59 LONG ref;
61 IUnknown *outer;
62 BOOL own;
64 LONG pos;
66 const struct enumvariant_funcs *funcs;
67 } enumvariant;
69 typedef struct
71 DispatchEx dispex;
72 IXMLDOMSelection IXMLDOMSelection_iface;
73 LONG ref;
74 xmlNodePtr node;
75 xmlXPathObjectPtr result;
76 int resultPos;
77 IEnumVARIANT *enumvariant;
78 } domselection;
80 static HRESULT selection_get_item(IUnknown *iface, LONG index, VARIANT* item)
82 V_VT(item) = VT_DISPATCH;
83 return IXMLDOMSelection_get_item((IXMLDOMSelection*)iface, index, (IXMLDOMNode**)&V_DISPATCH(item));
86 static HRESULT selection_next(IUnknown *iface)
88 IXMLDOMNode *node;
89 HRESULT hr = IXMLDOMSelection_nextNode((IXMLDOMSelection*)iface, &node);
90 if (hr == S_OK) IXMLDOMNode_Release(node);
91 return hr;
94 static const struct enumvariant_funcs selection_enumvariant = {
95 selection_get_item,
96 selection_next
99 static inline domselection *impl_from_IXMLDOMSelection( IXMLDOMSelection *iface )
101 return CONTAINING_RECORD(iface, domselection, IXMLDOMSelection_iface);
104 static inline enumvariant *impl_from_IEnumVARIANT( IEnumVARIANT *iface )
106 return CONTAINING_RECORD(iface, enumvariant, IEnumVARIANT_iface);
109 static HRESULT WINAPI domselection_QueryInterface(
110 IXMLDOMSelection *iface,
111 REFIID riid,
112 void** ppvObject )
114 domselection *This = impl_from_IXMLDOMSelection( iface );
116 TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
118 if(!ppvObject)
119 return E_INVALIDARG;
121 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
122 IsEqualGUID( riid, &IID_IXMLDOMNodeList ) ||
123 IsEqualGUID( riid, &IID_IXMLDOMSelection ))
125 *ppvObject = &This->IXMLDOMSelection_iface;
127 else if (IsEqualGUID( riid, &IID_IEnumVARIANT ))
129 if (!This->enumvariant)
131 HRESULT hr = create_enumvariant((IUnknown*)iface, FALSE, &selection_enumvariant, &This->enumvariant);
132 if (FAILED(hr)) return hr;
135 return IEnumVARIANT_QueryInterface(This->enumvariant, &IID_IEnumVARIANT, ppvObject);
137 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
139 return *ppvObject ? S_OK : E_NOINTERFACE;
141 else
143 TRACE("interface %s not implemented\n", debugstr_guid(riid));
144 *ppvObject = NULL;
145 return E_NOINTERFACE;
148 IXMLDOMSelection_AddRef( iface );
150 return S_OK;
153 static ULONG WINAPI domselection_AddRef(
154 IXMLDOMSelection *iface )
156 domselection *This = impl_from_IXMLDOMSelection( iface );
157 ULONG ref = InterlockedIncrement( &This->ref );
158 TRACE("%p, refcount %lu.\n", iface, ref);
159 return ref;
162 static ULONG WINAPI domselection_Release(
163 IXMLDOMSelection *iface )
165 domselection *This = impl_from_IXMLDOMSelection( iface );
166 ULONG ref = InterlockedDecrement(&This->ref);
168 TRACE("%p, refcount %lu.\n", iface, ref);
169 if ( ref == 0 )
171 xmlXPathFreeObject(This->result);
172 xmldoc_release(This->node->doc);
173 if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
174 heap_free(This);
177 return ref;
180 static HRESULT WINAPI domselection_GetTypeInfoCount(
181 IXMLDOMSelection *iface,
182 UINT* pctinfo )
184 domselection *This = impl_from_IXMLDOMSelection( iface );
185 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
188 static HRESULT WINAPI domselection_GetTypeInfo(
189 IXMLDOMSelection *iface,
190 UINT iTInfo,
191 LCID lcid,
192 ITypeInfo** ppTInfo )
194 domselection *This = impl_from_IXMLDOMSelection( iface );
195 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
196 iTInfo, lcid, ppTInfo);
199 static HRESULT WINAPI domselection_GetIDsOfNames(
200 IXMLDOMSelection *iface,
201 REFIID riid,
202 LPOLESTR* rgszNames,
203 UINT cNames,
204 LCID lcid,
205 DISPID* rgDispId )
207 domselection *This = impl_from_IXMLDOMSelection( iface );
208 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
209 riid, rgszNames, cNames, lcid, rgDispId);
212 static HRESULT WINAPI domselection_Invoke(
213 IXMLDOMSelection *iface,
214 DISPID dispIdMember,
215 REFIID riid,
216 LCID lcid,
217 WORD wFlags,
218 DISPPARAMS* pDispParams,
219 VARIANT* pVarResult,
220 EXCEPINFO* pExcepInfo,
221 UINT* puArgErr )
223 domselection *This = impl_from_IXMLDOMSelection( iface );
224 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
225 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
228 static HRESULT WINAPI domselection_get_item(
229 IXMLDOMSelection* iface,
230 LONG index,
231 IXMLDOMNode** listItem)
233 domselection *This = impl_from_IXMLDOMSelection( iface );
235 TRACE("%p, %ld, %p.\n", iface, index, listItem);
237 if(!listItem)
238 return E_INVALIDARG;
240 *listItem = NULL;
242 if (index < 0 || index >= xmlXPathNodeSetGetLength(This->result->nodesetval))
243 return S_FALSE;
245 *listItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, index));
246 This->resultPos = index + 1;
248 return S_OK;
251 static HRESULT WINAPI domselection_get_length(
252 IXMLDOMSelection* iface,
253 LONG* listLength)
255 domselection *This = impl_from_IXMLDOMSelection( iface );
257 TRACE("(%p)->(%p)\n", This, listLength);
259 if(!listLength)
260 return E_INVALIDARG;
262 *listLength = xmlXPathNodeSetGetLength(This->result->nodesetval);
263 return S_OK;
266 static HRESULT WINAPI domselection_nextNode(
267 IXMLDOMSelection* iface,
268 IXMLDOMNode** nextItem)
270 domselection *This = impl_from_IXMLDOMSelection( iface );
272 TRACE("(%p)->(%p)\n", This, nextItem );
274 if(!nextItem)
275 return E_INVALIDARG;
277 *nextItem = NULL;
279 if (This->resultPos >= xmlXPathNodeSetGetLength(This->result->nodesetval))
280 return S_FALSE;
282 *nextItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, This->resultPos));
283 This->resultPos++;
284 return S_OK;
287 static HRESULT WINAPI domselection_reset(
288 IXMLDOMSelection* iface)
290 domselection *This = impl_from_IXMLDOMSelection( iface );
292 TRACE("%p\n", This);
293 This->resultPos = 0;
294 return S_OK;
297 static HRESULT WINAPI domselection_get__newEnum(
298 IXMLDOMSelection* iface,
299 IUnknown** enumv)
301 domselection *This = impl_from_IXMLDOMSelection( iface );
303 TRACE("(%p)->(%p)\n", This, enumv);
305 return create_enumvariant((IUnknown*)iface, TRUE, &selection_enumvariant, (IEnumVARIANT**)enumv);
308 static HRESULT WINAPI domselection_get_expr(
309 IXMLDOMSelection* iface,
310 BSTR *p)
312 domselection *This = impl_from_IXMLDOMSelection( iface );
313 FIXME("(%p)->(%p)\n", This, p);
314 return E_NOTIMPL;
317 static HRESULT WINAPI domselection_put_expr(
318 IXMLDOMSelection* iface,
319 BSTR p)
321 domselection *This = impl_from_IXMLDOMSelection( iface );
322 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
323 return E_NOTIMPL;
326 static HRESULT WINAPI domselection_get_context(
327 IXMLDOMSelection* iface,
328 IXMLDOMNode **node)
330 domselection *This = impl_from_IXMLDOMSelection( iface );
331 FIXME("(%p)->(%p)\n", This, node);
332 return E_NOTIMPL;
335 static HRESULT WINAPI domselection_putref_context(
336 IXMLDOMSelection* iface,
337 IXMLDOMNode *node)
339 domselection *This = impl_from_IXMLDOMSelection( iface );
340 FIXME("(%p)->(%p)\n", This, node);
341 return E_NOTIMPL;
344 static HRESULT WINAPI domselection_peekNode(
345 IXMLDOMSelection* iface,
346 IXMLDOMNode **node)
348 domselection *This = impl_from_IXMLDOMSelection( iface );
349 FIXME("(%p)->(%p)\n", This, node);
350 return E_NOTIMPL;
353 static HRESULT WINAPI domselection_matches(
354 IXMLDOMSelection* iface,
355 IXMLDOMNode *node,
356 IXMLDOMNode **out_node)
358 domselection *This = impl_from_IXMLDOMSelection( iface );
359 FIXME("(%p)->(%p %p)\n", This, node, out_node);
360 return E_NOTIMPL;
363 static HRESULT WINAPI domselection_removeNext(
364 IXMLDOMSelection* iface,
365 IXMLDOMNode **node)
367 domselection *This = impl_from_IXMLDOMSelection( iface );
368 FIXME("(%p)->(%p)\n", This, node);
369 return E_NOTIMPL;
372 static HRESULT WINAPI domselection_removeAll(
373 IXMLDOMSelection* iface)
375 domselection *This = impl_from_IXMLDOMSelection( iface );
376 FIXME("(%p)\n", This);
377 return E_NOTIMPL;
380 static HRESULT WINAPI domselection_clone(
381 IXMLDOMSelection* iface,
382 IXMLDOMSelection **node)
384 domselection *This = impl_from_IXMLDOMSelection( iface );
385 FIXME("(%p)->(%p)\n", This, node);
386 return E_NOTIMPL;
389 static HRESULT WINAPI domselection_getProperty(
390 IXMLDOMSelection* iface,
391 BSTR p,
392 VARIANT *var)
394 domselection *This = impl_from_IXMLDOMSelection( iface );
395 FIXME("(%p)->(%s %p)\n", This, debugstr_w(p), var);
396 return E_NOTIMPL;
399 static HRESULT WINAPI domselection_setProperty(
400 IXMLDOMSelection* iface,
401 BSTR p,
402 VARIANT var)
404 domselection *This = impl_from_IXMLDOMSelection( iface );
405 FIXME("(%p)->(%s %s)\n", This, debugstr_w(p), debugstr_variant(&var));
406 return E_NOTIMPL;
409 static const struct IXMLDOMSelectionVtbl domselection_vtbl =
411 domselection_QueryInterface,
412 domselection_AddRef,
413 domselection_Release,
414 domselection_GetTypeInfoCount,
415 domselection_GetTypeInfo,
416 domselection_GetIDsOfNames,
417 domselection_Invoke,
418 domselection_get_item,
419 domselection_get_length,
420 domselection_nextNode,
421 domselection_reset,
422 domselection_get__newEnum,
423 domselection_get_expr,
424 domselection_put_expr,
425 domselection_get_context,
426 domselection_putref_context,
427 domselection_peekNode,
428 domselection_matches,
429 domselection_removeNext,
430 domselection_removeAll,
431 domselection_clone,
432 domselection_getProperty,
433 domselection_setProperty
436 /* IEnumVARIANT support */
437 static HRESULT WINAPI enumvariant_QueryInterface(
438 IEnumVARIANT *iface,
439 REFIID riid,
440 void** ppvObject )
442 enumvariant *This = impl_from_IEnumVARIANT( iface );
444 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
446 *ppvObject = NULL;
448 if (IsEqualGUID( riid, &IID_IUnknown ))
450 if (This->own)
451 *ppvObject = &This->IEnumVARIANT_iface;
452 else
453 return IUnknown_QueryInterface(This->outer, riid, ppvObject);
455 else if (IsEqualGUID( riid, &IID_IEnumVARIANT ))
457 *ppvObject = &This->IEnumVARIANT_iface;
459 else
460 return IUnknown_QueryInterface(This->outer, riid, ppvObject);
462 IEnumVARIANT_AddRef( iface );
464 return S_OK;
467 static ULONG WINAPI enumvariant_AddRef(IEnumVARIANT *iface )
469 enumvariant *This = impl_from_IEnumVARIANT( iface );
470 ULONG ref = InterlockedIncrement( &This->ref );
471 TRACE("%p, refcount %lu.\n", iface, ref);
472 return ref;
475 static ULONG WINAPI enumvariant_Release(IEnumVARIANT *iface )
477 enumvariant *This = impl_from_IEnumVARIANT( iface );
478 ULONG ref = InterlockedDecrement(&This->ref);
480 TRACE("%p, refcount %lu.\n", iface, ref);
481 if ( ref == 0 )
483 if (This->own) IUnknown_Release(This->outer);
484 heap_free(This);
487 return ref;
490 static HRESULT WINAPI enumvariant_Next(
491 IEnumVARIANT *iface,
492 ULONG celt,
493 VARIANT *var,
494 ULONG *fetched)
496 enumvariant *This = impl_from_IEnumVARIANT( iface );
497 ULONG ret_count = 0;
499 TRACE("%p, %lu, %p, %p.\n", iface, celt, var, fetched);
501 if (fetched) *fetched = 0;
503 if (celt && !var) return E_INVALIDARG;
505 for (; celt > 0; celt--, var++, This->pos++)
507 HRESULT hr = This->funcs->get_item(This->outer, This->pos, var);
508 if (hr != S_OK)
510 V_VT(var) = VT_EMPTY;
511 break;
513 ret_count++;
516 if (fetched) *fetched = ret_count;
518 /* we need to advance one step more for some reason */
519 if (ret_count)
521 if (This->funcs->next)
522 This->funcs->next(This->outer);
525 return celt == 0 ? S_OK : S_FALSE;
528 static HRESULT WINAPI enumvariant_Skip(
529 IEnumVARIANT *iface,
530 ULONG celt)
532 FIXME("%p, %lu: stub\n", iface, celt);
534 return E_NOTIMPL;
537 static HRESULT WINAPI enumvariant_Reset(IEnumVARIANT *iface)
539 enumvariant *This = impl_from_IEnumVARIANT( iface );
541 TRACE("%p\n", This);
542 This->pos = 0;
543 return S_OK;
546 static HRESULT WINAPI enumvariant_Clone(
547 IEnumVARIANT *iface, IEnumVARIANT **ppenum)
549 enumvariant *This = impl_from_IEnumVARIANT( iface );
550 FIXME("(%p)->(%p): stub\n", This, ppenum);
551 return E_NOTIMPL;
554 static const struct IEnumVARIANTVtbl EnumVARIANTVtbl =
556 enumvariant_QueryInterface,
557 enumvariant_AddRef,
558 enumvariant_Release,
559 enumvariant_Next,
560 enumvariant_Skip,
561 enumvariant_Reset,
562 enumvariant_Clone
565 HRESULT create_enumvariant(IUnknown *outer, BOOL own, const struct enumvariant_funcs *funcs, IEnumVARIANT **penum)
567 enumvariant *This;
569 This = heap_alloc(sizeof(enumvariant));
570 if (!This) return E_OUTOFMEMORY;
572 This->IEnumVARIANT_iface.lpVtbl = &EnumVARIANTVtbl;
573 This->ref = 0;
574 This->outer = outer;
575 This->own = own;
576 This->pos = 0;
577 This->funcs = funcs;
579 if (This->own)
580 IUnknown_AddRef(This->outer);
582 *penum = &This->IEnumVARIANT_iface;
583 IEnumVARIANT_AddRef(*penum);
584 return S_OK;
587 static HRESULT domselection_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
589 WCHAR *ptr;
590 int idx = 0;
592 for(ptr = name; *ptr >= '0' && *ptr <= '9'; ptr++)
593 idx = idx*10 + (*ptr-'0');
594 if(*ptr)
595 return DISP_E_UNKNOWNNAME;
597 *dispid = DISPID_DOM_COLLECTION_BASE + idx;
598 TRACE("ret %lx\n", *dispid);
599 return S_OK;
602 static HRESULT domselection_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
603 VARIANT *res, EXCEPINFO *ei)
605 domselection *This = impl_from_IXMLDOMSelection( (IXMLDOMSelection*)iface );
607 TRACE("%p, %ld, %lx, %x, %p, %p, %p.\n", iface, id, lcid, flags, params, res, ei);
609 V_VT(res) = VT_DISPATCH;
610 V_DISPATCH(res) = NULL;
612 if (id < DISPID_DOM_COLLECTION_BASE || id > DISPID_DOM_COLLECTION_MAX)
613 return DISP_E_UNKNOWNNAME;
615 switch(flags)
617 case INVOKE_PROPERTYGET:
619 IXMLDOMNode *disp = NULL;
621 IXMLDOMSelection_get_item(&This->IXMLDOMSelection_iface, id - DISPID_DOM_COLLECTION_BASE, &disp);
622 V_DISPATCH(res) = (IDispatch*)disp;
623 break;
625 default:
627 FIXME("unimplemented flags %x\n", flags);
628 break;
632 TRACE("ret %p\n", V_DISPATCH(res));
634 return S_OK;
637 static const dispex_static_data_vtbl_t domselection_dispex_vtbl = {
638 domselection_get_dispid,
639 domselection_invoke
642 static const tid_t domselection_iface_tids[] = {
643 IXMLDOMSelection_tid,
646 static dispex_static_data_t domselection_dispex = {
647 &domselection_dispex_vtbl,
648 IXMLDOMSelection_tid,
649 NULL,
650 domselection_iface_tids
653 #define XSLPATTERN_CHECK_ARGS(n) \
654 if (nargs != n) { \
655 FIXME("XSLPattern syntax error: Expected %i arguments, got %i\n", n, nargs); \
656 xmlXPathSetArityError(pctx); \
657 return; \
661 static void XSLPattern_index(xmlXPathParserContextPtr pctx, int nargs)
663 XSLPATTERN_CHECK_ARGS(0);
665 xmlXPathPositionFunction(pctx, 0);
666 xmlXPathReturnNumber(pctx, xmlXPathPopNumber(pctx) - 1.0);
669 static void XSLPattern_end(xmlXPathParserContextPtr pctx, int nargs)
671 double pos, last;
672 XSLPATTERN_CHECK_ARGS(0);
674 xmlXPathPositionFunction(pctx, 0);
675 pos = xmlXPathPopNumber(pctx);
676 xmlXPathLastFunction(pctx, 0);
677 last = xmlXPathPopNumber(pctx);
678 xmlXPathReturnBoolean(pctx, pos == last);
681 static void XSLPattern_nodeType(xmlXPathParserContextPtr pctx, int nargs)
683 XSLPATTERN_CHECK_ARGS(0);
684 xmlXPathReturnNumber(pctx, pctx->context->node->type);
687 static void XSLPattern_OP_IEq(xmlXPathParserContextPtr pctx, int nargs)
689 xmlChar *arg1, *arg2;
690 XSLPATTERN_CHECK_ARGS(2);
692 arg2 = xmlXPathPopString(pctx);
693 arg1 = xmlXPathPopString(pctx);
694 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) == 0);
695 xmlFree(arg1);
696 xmlFree(arg2);
699 static void XSLPattern_OP_INEq(xmlXPathParserContextPtr pctx, int nargs)
701 xmlChar *arg1, *arg2;
702 XSLPATTERN_CHECK_ARGS(2);
704 arg2 = xmlXPathPopString(pctx);
705 arg1 = xmlXPathPopString(pctx);
706 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) != 0);
707 xmlFree(arg1);
708 xmlFree(arg2);
711 static void XSLPattern_OP_ILt(xmlXPathParserContextPtr pctx, int nargs)
713 xmlChar *arg1, *arg2;
714 XSLPATTERN_CHECK_ARGS(2);
716 arg2 = xmlXPathPopString(pctx);
717 arg1 = xmlXPathPopString(pctx);
718 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) < 0);
719 xmlFree(arg1);
720 xmlFree(arg2);
723 static void XSLPattern_OP_ILEq(xmlXPathParserContextPtr pctx, int nargs)
725 xmlChar *arg1, *arg2;
726 XSLPATTERN_CHECK_ARGS(2);
728 arg2 = xmlXPathPopString(pctx);
729 arg1 = xmlXPathPopString(pctx);
730 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) <= 0);
731 xmlFree(arg1);
732 xmlFree(arg2);
735 static void XSLPattern_OP_IGt(xmlXPathParserContextPtr pctx, int nargs)
737 xmlChar *arg1, *arg2;
738 XSLPATTERN_CHECK_ARGS(2);
740 arg2 = xmlXPathPopString(pctx);
741 arg1 = xmlXPathPopString(pctx);
742 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) > 0);
743 xmlFree(arg1);
744 xmlFree(arg2);
747 static void XSLPattern_OP_IGEq(xmlXPathParserContextPtr pctx, int nargs)
749 xmlChar *arg1, *arg2;
750 XSLPATTERN_CHECK_ARGS(2);
752 arg2 = xmlXPathPopString(pctx);
753 arg1 = xmlXPathPopString(pctx);
754 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) >= 0);
755 xmlFree(arg1);
756 xmlFree(arg2);
759 static void query_serror(void* ctx, xmlErrorPtr err)
761 LIBXML2_CALLBACK_SERROR(domselection_create, err);
764 HRESULT create_selection(xmlNodePtr node, xmlChar* query, IXMLDOMNodeList **out)
766 domselection *This = heap_alloc(sizeof(domselection));
767 xmlXPathContextPtr ctxt = xmlXPathNewContext(node->doc);
768 HRESULT hr;
770 TRACE("(%p, %s, %p)\n", node, debugstr_a((char const*)query), out);
772 *out = NULL;
773 if (!This || !ctxt || !query)
775 xmlXPathFreeContext(ctxt);
776 heap_free(This);
777 return E_OUTOFMEMORY;
780 This->IXMLDOMSelection_iface.lpVtbl = &domselection_vtbl;
781 This->ref = 1;
782 This->resultPos = 0;
783 This->node = node;
784 This->enumvariant = NULL;
785 init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMSelection_iface, &domselection_dispex);
786 xmldoc_add_ref(This->node->doc);
788 ctxt->error = query_serror;
789 ctxt->node = node;
790 registerNamespaces(ctxt);
792 if (is_xpathmode(This->node->doc))
794 xmlXPathRegisterAllFunctions(ctxt);
795 This->result = xmlXPathEvalExpression(query, ctxt);
797 else
799 xmlChar* pattern_query = XSLPattern_to_XPath(ctxt, query);
801 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"not", xmlXPathNotFunction);
802 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"boolean", xmlXPathBooleanFunction);
804 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"index", XSLPattern_index);
805 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"end", XSLPattern_end);
806 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"nodeType", XSLPattern_nodeType);
808 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IEq", XSLPattern_OP_IEq);
809 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_INEq", XSLPattern_OP_INEq);
810 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_ILt", XSLPattern_OP_ILt);
811 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_ILEq", XSLPattern_OP_ILEq);
812 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IGt", XSLPattern_OP_IGt);
813 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IGEq", XSLPattern_OP_IGEq);
815 This->result = xmlXPathEvalExpression(pattern_query, ctxt);
816 xmlFree(pattern_query);
819 if (!This->result || This->result->type != XPATH_NODESET)
821 hr = E_FAIL;
822 goto cleanup;
825 *out = (IXMLDOMNodeList*)&This->IXMLDOMSelection_iface;
826 hr = S_OK;
827 TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This->result->nodesetval));
829 cleanup:
830 if (FAILED(hr))
831 IXMLDOMSelection_Release( &This->IXMLDOMSelection_iface );
832 xmlXPathFreeContext(ctxt);
833 return hr;