Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenqueryresult.c
Go to the documentation of this file.
00001 /* 00002 * XPath query result node list implementation (TODO: XSLPattern support) 00003 * 00004 * Copyright 2005 Mike McCormack 00005 * Copyright 2007 Mikolaj Zalewski 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #define COBJMACROS 00023 00024 #include "config.h" 00025 00026 #include <stdarg.h> 00027 #include "windef.h" 00028 #include "winbase.h" 00029 #include "winuser.h" 00030 #include "ole2.h" 00031 #include "msxml2.h" 00032 00033 #include "msxml_private.h" 00034 00035 #include "wine/debug.h" 00036 00037 /* This file implements the object returned by a XPath query. Note that this is 00038 * not the IXMLDOMNodeList returned by childNodes - it's implemented in nodelist.c. 00039 * They are different because the list returned by XPath queries: 00040 * - is static - gives the results for the XML tree as it existed during the 00041 * execution of the query 00042 * - supports IXMLDOMSelection (TODO) 00043 * 00044 * TODO: XSLPattern support 00045 */ 00046 00047 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 00048 00049 #ifdef HAVE_LIBXML2 00050 00051 #include <libxml/xpath.h> 00052 00053 typedef struct _queryresult 00054 { 00055 DispatchEx dispex; 00056 const struct IXMLDOMNodeListVtbl *lpVtbl; 00057 LONG ref; 00058 xmlNodePtr node; 00059 xmlXPathObjectPtr result; 00060 int resultPos; 00061 } queryresult; 00062 00063 static inline queryresult *impl_from_IXMLDOMNodeList( IXMLDOMNodeList *iface ) 00064 { 00065 return (queryresult *)((char*)iface - FIELD_OFFSET(queryresult, lpVtbl)); 00066 } 00067 00068 #define XMLQUERYRES(x) ((IXMLDOMNodeList*)&(x)->lpVtbl) 00069 00070 static HRESULT WINAPI queryresult_QueryInterface( 00071 IXMLDOMNodeList *iface, 00072 REFIID riid, 00073 void** ppvObject ) 00074 { 00075 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00076 00077 TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject); 00078 00079 if(!ppvObject) 00080 return E_INVALIDARG; 00081 00082 if ( IsEqualGUID( riid, &IID_IUnknown ) || 00083 IsEqualGUID( riid, &IID_IXMLDOMNodeList ) ) 00084 { 00085 *ppvObject = iface; 00086 } 00087 else if(dispex_query_interface(&This->dispex, riid, ppvObject)) 00088 { 00089 return *ppvObject ? S_OK : E_NOINTERFACE; 00090 } 00091 else 00092 { 00093 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 00094 *ppvObject = NULL; 00095 return E_NOINTERFACE; 00096 } 00097 00098 IXMLDOMNodeList_AddRef( iface ); 00099 00100 return S_OK; 00101 } 00102 00103 static ULONG WINAPI queryresult_AddRef( 00104 IXMLDOMNodeList *iface ) 00105 { 00106 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00107 return InterlockedIncrement( &This->ref ); 00108 } 00109 00110 static ULONG WINAPI queryresult_Release( 00111 IXMLDOMNodeList *iface ) 00112 { 00113 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00114 ULONG ref; 00115 00116 ref = InterlockedDecrement(&This->ref); 00117 if ( ref == 0 ) 00118 { 00119 xmlXPathFreeObject(This->result); 00120 xmldoc_release(This->node->doc); 00121 heap_free(This); 00122 } 00123 00124 return ref; 00125 } 00126 00127 static HRESULT WINAPI queryresult_GetTypeInfoCount( 00128 IXMLDOMNodeList *iface, 00129 UINT* pctinfo ) 00130 { 00131 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00132 00133 TRACE("(%p)->(%p)\n", This, pctinfo); 00134 00135 *pctinfo = 1; 00136 00137 return S_OK; 00138 } 00139 00140 static HRESULT WINAPI queryresult_GetTypeInfo( 00141 IXMLDOMNodeList *iface, 00142 UINT iTInfo, 00143 LCID lcid, 00144 ITypeInfo** ppTInfo ) 00145 { 00146 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00147 HRESULT hr; 00148 00149 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); 00150 00151 hr = get_typeinfo(IXMLDOMNodeList_tid, ppTInfo); 00152 00153 return hr; 00154 } 00155 00156 static HRESULT WINAPI queryresult_GetIDsOfNames( 00157 IXMLDOMNodeList *iface, 00158 REFIID riid, 00159 LPOLESTR* rgszNames, 00160 UINT cNames, 00161 LCID lcid, 00162 DISPID* rgDispId ) 00163 { 00164 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00165 ITypeInfo *typeinfo; 00166 HRESULT hr; 00167 00168 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, 00169 lcid, rgDispId); 00170 00171 if(!rgszNames || cNames == 0 || !rgDispId) 00172 return E_INVALIDARG; 00173 00174 hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo); 00175 if(SUCCEEDED(hr)) 00176 { 00177 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); 00178 ITypeInfo_Release(typeinfo); 00179 } 00180 00181 return hr; 00182 } 00183 00184 static HRESULT WINAPI queryresult_Invoke( 00185 IXMLDOMNodeList *iface, 00186 DISPID dispIdMember, 00187 REFIID riid, 00188 LCID lcid, 00189 WORD wFlags, 00190 DISPPARAMS* pDispParams, 00191 VARIANT* pVarResult, 00192 EXCEPINFO* pExcepInfo, 00193 UINT* puArgErr ) 00194 { 00195 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00196 ITypeInfo *typeinfo; 00197 HRESULT hr; 00198 00199 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), 00200 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 00201 00202 hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo); 00203 if(SUCCEEDED(hr)) 00204 { 00205 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams, 00206 pVarResult, pExcepInfo, puArgErr); 00207 ITypeInfo_Release(typeinfo); 00208 } 00209 00210 return hr; 00211 } 00212 00213 static HRESULT WINAPI queryresult_get_item( 00214 IXMLDOMNodeList* iface, 00215 LONG index, 00216 IXMLDOMNode** listItem) 00217 { 00218 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00219 00220 TRACE("(%p)->(%d %p)\n", This, index, listItem); 00221 00222 if(!listItem) 00223 return E_INVALIDARG; 00224 00225 *listItem = NULL; 00226 00227 if (index < 0 || index >= xmlXPathNodeSetGetLength(This->result->nodesetval)) 00228 return S_FALSE; 00229 00230 *listItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, index)); 00231 This->resultPos = index + 1; 00232 00233 return S_OK; 00234 } 00235 00236 static HRESULT WINAPI queryresult_get_length( 00237 IXMLDOMNodeList* iface, 00238 LONG* listLength) 00239 { 00240 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00241 00242 TRACE("(%p)->(%p)\n", This, listLength); 00243 00244 if(!listLength) 00245 return E_INVALIDARG; 00246 00247 *listLength = xmlXPathNodeSetGetLength(This->result->nodesetval); 00248 return S_OK; 00249 } 00250 00251 static HRESULT WINAPI queryresult_nextNode( 00252 IXMLDOMNodeList* iface, 00253 IXMLDOMNode** nextItem) 00254 { 00255 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00256 00257 TRACE("(%p)->(%p)\n", This, nextItem ); 00258 00259 if(!nextItem) 00260 return E_INVALIDARG; 00261 00262 *nextItem = NULL; 00263 00264 if (This->resultPos >= xmlXPathNodeSetGetLength(This->result->nodesetval)) 00265 return S_FALSE; 00266 00267 *nextItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, This->resultPos)); 00268 This->resultPos++; 00269 return S_OK; 00270 } 00271 00272 static HRESULT WINAPI queryresult_reset( 00273 IXMLDOMNodeList* iface) 00274 { 00275 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00276 00277 TRACE("%p\n", This); 00278 This->resultPos = 0; 00279 return S_OK; 00280 } 00281 00282 static HRESULT WINAPI queryresult__newEnum( 00283 IXMLDOMNodeList* iface, 00284 IUnknown** ppUnk) 00285 { 00286 queryresult *This = impl_from_IXMLDOMNodeList( iface ); 00287 FIXME("(%p)->(%p)\n", This, ppUnk); 00288 return E_NOTIMPL; 00289 } 00290 00291 00292 static const struct IXMLDOMNodeListVtbl queryresult_vtbl = 00293 { 00294 queryresult_QueryInterface, 00295 queryresult_AddRef, 00296 queryresult_Release, 00297 queryresult_GetTypeInfoCount, 00298 queryresult_GetTypeInfo, 00299 queryresult_GetIDsOfNames, 00300 queryresult_Invoke, 00301 queryresult_get_item, 00302 queryresult_get_length, 00303 queryresult_nextNode, 00304 queryresult_reset, 00305 queryresult__newEnum, 00306 }; 00307 00308 static HRESULT queryresult_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid) 00309 { 00310 queryresult *This = impl_from_IXMLDOMNodeList( (IXMLDOMNodeList*)iface ); 00311 WCHAR *ptr; 00312 int idx = 0; 00313 00314 for(ptr = name; *ptr && isdigitW(*ptr); ptr++) 00315 idx = idx*10 + (*ptr-'0'); 00316 if(*ptr) 00317 return DISP_E_UNKNOWNNAME; 00318 00319 if(idx >= xmlXPathNodeSetGetLength(This->result->nodesetval)) 00320 return DISP_E_UNKNOWNNAME; 00321 00322 *dispid = MSXML_DISPID_CUSTOM_MIN + idx; 00323 TRACE("ret %x\n", *dispid); 00324 return S_OK; 00325 } 00326 00327 static HRESULT queryresult_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, 00328 VARIANT *res, EXCEPINFO *ei) 00329 { 00330 queryresult *This = impl_from_IXMLDOMNodeList( (IXMLDOMNodeList*)iface ); 00331 00332 TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei); 00333 00334 V_VT(res) = VT_DISPATCH; 00335 V_DISPATCH(res) = NULL; 00336 00337 switch(flags) 00338 { 00339 case INVOKE_PROPERTYGET: 00340 { 00341 IXMLDOMNode *disp = NULL; 00342 00343 queryresult_get_item(XMLQUERYRES(This), id - MSXML_DISPID_CUSTOM_MIN, &disp); 00344 V_DISPATCH(res) = (IDispatch*)disp; 00345 break; 00346 } 00347 default: 00348 { 00349 FIXME("unimplemented flags %x\n", flags); 00350 break; 00351 } 00352 } 00353 00354 TRACE("ret %p\n", V_DISPATCH(res)); 00355 00356 return S_OK; 00357 } 00358 00359 static const dispex_static_data_vtbl_t queryresult_dispex_vtbl = { 00360 queryresult_get_dispid, 00361 queryresult_invoke 00362 }; 00363 00364 static const tid_t queryresult_iface_tids[] = { 00365 IXMLDOMNodeList_tid, 00366 0 00367 }; 00368 static dispex_static_data_t queryresult_dispex = { 00369 &queryresult_dispex_vtbl, 00370 IXMLDOMSelection_tid, 00371 NULL, 00372 queryresult_iface_tids 00373 }; 00374 00375 HRESULT queryresult_create(xmlNodePtr node, LPWSTR szQuery, IXMLDOMNodeList **out) 00376 { 00377 queryresult *This = heap_alloc_zero(sizeof(queryresult)); 00378 xmlXPathContextPtr ctxt = xmlXPathNewContext(node->doc); 00379 xmlChar *str = xmlChar_from_wchar(szQuery); 00380 HRESULT hr; 00381 00382 TRACE("(%p, %s, %p)\n", node, wine_dbgstr_w(szQuery), out); 00383 00384 *out = NULL; 00385 if (This == NULL || ctxt == NULL || str == NULL) 00386 { 00387 hr = E_OUTOFMEMORY; 00388 goto cleanup; 00389 } 00390 00391 This->lpVtbl = &queryresult_vtbl; 00392 This->ref = 1; 00393 This->resultPos = 0; 00394 This->node = node; 00395 xmldoc_add_ref(This->node->doc); 00396 00397 ctxt->node = node; 00398 This->result = xmlXPathEval(str, ctxt); 00399 if (!This->result || This->result->type != XPATH_NODESET) 00400 { 00401 hr = E_FAIL; 00402 goto cleanup; 00403 } 00404 00405 init_dispex(&This->dispex, (IUnknown*)&This->lpVtbl, &queryresult_dispex); 00406 00407 *out = (IXMLDOMNodeList *) &This->lpVtbl; 00408 hr = S_OK; 00409 TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This->result->nodesetval)); 00410 00411 cleanup: 00412 if (This != NULL && FAILED(hr)) 00413 IXMLDOMNodeList_Release( (IXMLDOMNodeList*) &This->lpVtbl ); 00414 xmlXPathFreeContext(ctxt); 00415 heap_free(str); 00416 return hr; 00417 } 00418 00419 #endif Generated on Sat May 26 2012 04:23:57 for ReactOS by
1.7.6.1
|