1 /* 2 * Node map implementation 3 * 4 * Copyright 2005 Mike McCormack 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 #include "config.h" 22 23 #define COBJMACROS 24 25 #include <stdarg.h> 26 #ifdef HAVE_LIBXML2 27 # include <libxml/parser.h> 28 # include <libxml/xmlerror.h> 29 #endif 30 31 #include "windef.h" 32 #include "winbase.h" 33 #include "winuser.h" 34 #include "winnls.h" 35 #include "ole2.h" 36 #include "msxml6.h" 37 #include "msxml2did.h" 38 39 #include "msxml_private.h" 40 41 #include "wine/debug.h" 42 43 #ifdef HAVE_LIBXML2 44 45 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 46 47 typedef struct 48 { 49 DispatchEx dispex; 50 IXMLDOMNamedNodeMap IXMLDOMNamedNodeMap_iface; 51 ISupportErrorInfo ISupportErrorInfo_iface; 52 LONG ref; 53 54 xmlNodePtr node; 55 LONG iterator; 56 IEnumVARIANT *enumvariant; 57 58 const struct nodemap_funcs *funcs; 59 } xmlnodemap; 60 61 static HRESULT nodemap_get_item(IUnknown *iface, LONG index, VARIANT *item) 62 { 63 V_VT(item) = VT_DISPATCH; 64 return IXMLDOMNamedNodeMap_get_item((IXMLDOMNamedNodeMap*)iface, index, (IXMLDOMNode**)&V_DISPATCH(item)); 65 } 66 67 static const struct enumvariant_funcs nodemap_enumvariant = { 68 nodemap_get_item, 69 NULL 70 }; 71 72 static inline xmlnodemap *impl_from_IXMLDOMNamedNodeMap( IXMLDOMNamedNodeMap *iface ) 73 { 74 return CONTAINING_RECORD(iface, xmlnodemap, IXMLDOMNamedNodeMap_iface); 75 } 76 77 static inline xmlnodemap *impl_from_ISupportErrorInfo( ISupportErrorInfo *iface ) 78 { 79 return CONTAINING_RECORD(iface, xmlnodemap, ISupportErrorInfo_iface); 80 } 81 82 static HRESULT WINAPI xmlnodemap_QueryInterface( 83 IXMLDOMNamedNodeMap *iface, 84 REFIID riid, void** ppvObject ) 85 { 86 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 87 TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject); 88 89 if( IsEqualGUID( riid, &IID_IUnknown ) || 90 IsEqualGUID( riid, &IID_IDispatch ) || 91 IsEqualGUID( riid, &IID_IXMLDOMNamedNodeMap ) ) 92 { 93 *ppvObject = iface; 94 } 95 else if (IsEqualGUID( riid, &IID_IEnumVARIANT )) 96 { 97 if (!This->enumvariant) 98 { 99 HRESULT hr = create_enumvariant((IUnknown*)iface, FALSE, &nodemap_enumvariant, &This->enumvariant); 100 if (FAILED(hr)) return hr; 101 } 102 103 return IEnumVARIANT_QueryInterface(This->enumvariant, &IID_IEnumVARIANT, ppvObject); 104 } 105 else if (dispex_query_interface(&This->dispex, riid, ppvObject)) 106 { 107 return *ppvObject ? S_OK : E_NOINTERFACE; 108 } 109 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo )) 110 { 111 *ppvObject = &This->ISupportErrorInfo_iface; 112 } 113 else 114 { 115 TRACE("interface %s not implemented\n", debugstr_guid(riid)); 116 *ppvObject = NULL; 117 return E_NOINTERFACE; 118 } 119 120 IXMLDOMNamedNodeMap_AddRef( iface ); 121 122 return S_OK; 123 } 124 125 static ULONG WINAPI xmlnodemap_AddRef( 126 IXMLDOMNamedNodeMap *iface ) 127 { 128 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 129 ULONG ref = InterlockedIncrement( &This->ref ); 130 TRACE("(%p)->(%d)\n", This, ref); 131 return ref; 132 } 133 134 static ULONG WINAPI xmlnodemap_Release( 135 IXMLDOMNamedNodeMap *iface ) 136 { 137 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 138 ULONG ref = InterlockedDecrement( &This->ref ); 139 140 TRACE("(%p)->(%d)\n", This, ref); 141 if ( ref == 0 ) 142 { 143 xmlnode_release( This->node ); 144 xmldoc_release( This->node->doc ); 145 if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant); 146 heap_free( This ); 147 } 148 149 return ref; 150 } 151 152 static HRESULT WINAPI xmlnodemap_GetTypeInfoCount( 153 IXMLDOMNamedNodeMap *iface, 154 UINT* pctinfo ) 155 { 156 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 157 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); 158 } 159 160 static HRESULT WINAPI xmlnodemap_GetTypeInfo( 161 IXMLDOMNamedNodeMap *iface, 162 UINT iTInfo, LCID lcid, 163 ITypeInfo** ppTInfo ) 164 { 165 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 166 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, 167 iTInfo, lcid, ppTInfo); 168 } 169 170 static HRESULT WINAPI xmlnodemap_GetIDsOfNames( 171 IXMLDOMNamedNodeMap *iface, 172 REFIID riid, LPOLESTR* rgszNames, 173 UINT cNames, LCID lcid, DISPID* rgDispId ) 174 { 175 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 176 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, 177 riid, rgszNames, cNames, lcid, rgDispId); 178 } 179 180 static HRESULT WINAPI xmlnodemap_Invoke( 181 IXMLDOMNamedNodeMap *iface, 182 DISPID dispIdMember, REFIID riid, LCID lcid, 183 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, 184 EXCEPINFO* pExcepInfo, UINT* puArgErr ) 185 { 186 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 187 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, 188 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 189 } 190 191 static HRESULT WINAPI xmlnodemap_getNamedItem( 192 IXMLDOMNamedNodeMap *iface, 193 BSTR name, 194 IXMLDOMNode** item) 195 { 196 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 197 198 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), item ); 199 200 return This->funcs->get_named_item(This->node, name, item); 201 } 202 203 static HRESULT WINAPI xmlnodemap_setNamedItem( 204 IXMLDOMNamedNodeMap *iface, 205 IXMLDOMNode* newItem, 206 IXMLDOMNode** namedItem) 207 { 208 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 209 210 TRACE("(%p)->(%p %p)\n", This, newItem, namedItem ); 211 212 return This->funcs->set_named_item(This->node, newItem, namedItem); 213 } 214 215 static HRESULT WINAPI xmlnodemap_removeNamedItem( 216 IXMLDOMNamedNodeMap *iface, 217 BSTR name, 218 IXMLDOMNode** namedItem) 219 { 220 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 221 222 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), namedItem ); 223 224 return This->funcs->remove_named_item(This->node, name, namedItem); 225 } 226 227 static HRESULT WINAPI xmlnodemap_get_item( 228 IXMLDOMNamedNodeMap *iface, 229 LONG index, 230 IXMLDOMNode** item) 231 { 232 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 233 234 TRACE("(%p)->(%d %p)\n", This, index, item); 235 236 return This->funcs->get_item(This->node, index, item); 237 } 238 239 static HRESULT WINAPI xmlnodemap_get_length( 240 IXMLDOMNamedNodeMap *iface, 241 LONG *length) 242 { 243 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 244 245 TRACE("(%p)->(%p)\n", This, length); 246 247 return This->funcs->get_length(This->node, length); 248 } 249 250 static HRESULT WINAPI xmlnodemap_getQualifiedItem( 251 IXMLDOMNamedNodeMap *iface, 252 BSTR baseName, 253 BSTR namespaceURI, 254 IXMLDOMNode** item) 255 { 256 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 257 258 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(baseName), debugstr_w(namespaceURI), item); 259 260 return This->funcs->get_qualified_item(This->node, baseName, namespaceURI, item); 261 } 262 263 static HRESULT WINAPI xmlnodemap_removeQualifiedItem( 264 IXMLDOMNamedNodeMap *iface, 265 BSTR baseName, 266 BSTR namespaceURI, 267 IXMLDOMNode** item) 268 { 269 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 270 271 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(baseName), debugstr_w(namespaceURI), item); 272 273 return This->funcs->remove_qualified_item(This->node, baseName, namespaceURI, item); 274 } 275 276 static HRESULT WINAPI xmlnodemap_nextNode( 277 IXMLDOMNamedNodeMap *iface, 278 IXMLDOMNode** nextItem) 279 { 280 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 281 282 TRACE("(%p)->(%p: %d)\n", This, nextItem, This->iterator); 283 284 return This->funcs->next_node(This->node, &This->iterator, nextItem); 285 } 286 287 static HRESULT WINAPI xmlnodemap_reset( 288 IXMLDOMNamedNodeMap *iface ) 289 { 290 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 291 292 TRACE("(%p)->(%d)\n", This, This->iterator); 293 294 This->iterator = 0; 295 296 return S_OK; 297 } 298 299 static HRESULT WINAPI xmlnodemap__newEnum( 300 IXMLDOMNamedNodeMap *iface, 301 IUnknown** enumv) 302 { 303 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); 304 TRACE("(%p)->(%p)\n", This, enumv); 305 return create_enumvariant((IUnknown*)iface, TRUE, &nodemap_enumvariant, (IEnumVARIANT**)enumv); 306 } 307 308 static const struct IXMLDOMNamedNodeMapVtbl XMLDOMNamedNodeMapVtbl = 309 { 310 xmlnodemap_QueryInterface, 311 xmlnodemap_AddRef, 312 xmlnodemap_Release, 313 xmlnodemap_GetTypeInfoCount, 314 xmlnodemap_GetTypeInfo, 315 xmlnodemap_GetIDsOfNames, 316 xmlnodemap_Invoke, 317 xmlnodemap_getNamedItem, 318 xmlnodemap_setNamedItem, 319 xmlnodemap_removeNamedItem, 320 xmlnodemap_get_item, 321 xmlnodemap_get_length, 322 xmlnodemap_getQualifiedItem, 323 xmlnodemap_removeQualifiedItem, 324 xmlnodemap_nextNode, 325 xmlnodemap_reset, 326 xmlnodemap__newEnum, 327 }; 328 329 static HRESULT WINAPI support_error_QueryInterface( 330 ISupportErrorInfo *iface, 331 REFIID riid, void** ppvObject ) 332 { 333 xmlnodemap *This = impl_from_ISupportErrorInfo( iface ); 334 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); 335 return IXMLDOMNamedNodeMap_QueryInterface(&This->IXMLDOMNamedNodeMap_iface, riid, ppvObject); 336 } 337 338 static ULONG WINAPI support_error_AddRef( 339 ISupportErrorInfo *iface ) 340 { 341 xmlnodemap *This = impl_from_ISupportErrorInfo( iface ); 342 return IXMLDOMNamedNodeMap_AddRef(&This->IXMLDOMNamedNodeMap_iface); 343 } 344 345 static ULONG WINAPI support_error_Release( 346 ISupportErrorInfo *iface ) 347 { 348 xmlnodemap *This = impl_from_ISupportErrorInfo( iface ); 349 return IXMLDOMNamedNodeMap_Release(&This->IXMLDOMNamedNodeMap_iface); 350 } 351 352 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo( 353 ISupportErrorInfo *iface, 354 REFIID riid ) 355 { 356 xmlnodemap *This = impl_from_ISupportErrorInfo( iface ); 357 TRACE("(%p)->(%s)\n", This, debugstr_guid(riid)); 358 return IsEqualGUID(riid, &IID_IXMLDOMNamedNodeMap) ? S_OK : S_FALSE; 359 } 360 361 static const struct ISupportErrorInfoVtbl SupportErrorInfoVtbl = 362 { 363 support_error_QueryInterface, 364 support_error_AddRef, 365 support_error_Release, 366 support_error_InterfaceSupportsErrorInfo 367 }; 368 369 static HRESULT xmlnodemap_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid) 370 { 371 WCHAR *ptr; 372 int idx = 0; 373 374 for(ptr = name; *ptr && isdigitW(*ptr); ptr++) 375 idx = idx*10 + (*ptr-'0'); 376 if(*ptr) 377 return DISP_E_UNKNOWNNAME; 378 379 *dispid = DISPID_DOM_COLLECTION_BASE + idx; 380 TRACE("ret %x\n", *dispid); 381 return S_OK; 382 } 383 384 static HRESULT xmlnodemap_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, 385 VARIANT *res, EXCEPINFO *ei) 386 { 387 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( (IXMLDOMNamedNodeMap*)iface ); 388 389 TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei); 390 391 V_VT(res) = VT_DISPATCH; 392 V_DISPATCH(res) = NULL; 393 394 if (id < DISPID_DOM_COLLECTION_BASE || id > DISPID_DOM_COLLECTION_MAX) 395 return DISP_E_UNKNOWNNAME; 396 397 switch(flags) 398 { 399 case INVOKE_PROPERTYGET: 400 { 401 IXMLDOMNode *disp = NULL; 402 403 IXMLDOMNamedNodeMap_get_item(&This->IXMLDOMNamedNodeMap_iface, id - DISPID_DOM_COLLECTION_BASE, &disp); 404 V_DISPATCH(res) = (IDispatch*)disp; 405 break; 406 } 407 default: 408 { 409 FIXME("unimplemented flags %x\n", flags); 410 break; 411 } 412 } 413 414 TRACE("ret %p\n", V_DISPATCH(res)); 415 416 return S_OK; 417 } 418 419 static const dispex_static_data_vtbl_t xmlnodemap_dispex_vtbl = { 420 xmlnodemap_get_dispid, 421 xmlnodemap_invoke 422 }; 423 424 static const tid_t xmlnodemap_iface_tids[] = { 425 IXMLDOMNamedNodeMap_tid, 426 0 427 }; 428 429 static dispex_static_data_t xmlnodemap_dispex = { 430 &xmlnodemap_dispex_vtbl, 431 IXMLDOMNamedNodeMap_tid, 432 NULL, 433 xmlnodemap_iface_tids 434 }; 435 436 IXMLDOMNamedNodeMap *create_nodemap(xmlNodePtr node, const struct nodemap_funcs *funcs) 437 { 438 xmlnodemap *This; 439 440 This = heap_alloc( sizeof *This ); 441 if ( !This ) 442 return NULL; 443 444 This->IXMLDOMNamedNodeMap_iface.lpVtbl = &XMLDOMNamedNodeMapVtbl; 445 This->ISupportErrorInfo_iface.lpVtbl = &SupportErrorInfoVtbl; 446 This->node = node; 447 This->ref = 1; 448 This->iterator = 0; 449 This->enumvariant = NULL; 450 This->funcs = funcs; 451 452 init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNamedNodeMap_iface, &xmlnodemap_dispex); 453 454 xmlnode_add_ref(node); 455 xmldoc_add_ref(node->doc); 456 457 return &This->IXMLDOMNamedNodeMap_iface; 458 } 459 460 #endif 461