1 /* 2 * Copyright 2011 Jacek Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "mshtml_private.h" 20 21 static inline HTMLDOMAttribute *impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute *iface) 22 { 23 return CONTAINING_RECORD(iface, HTMLDOMAttribute, IHTMLDOMAttribute_iface); 24 } 25 26 static HRESULT WINAPI HTMLDOMAttribute_QueryInterface(IHTMLDOMAttribute *iface, 27 REFIID riid, void **ppv) 28 { 29 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 30 31 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); 32 33 if(IsEqualGUID(&IID_IUnknown, riid)) { 34 *ppv = &This->IHTMLDOMAttribute_iface; 35 }else if(IsEqualGUID(&IID_IHTMLDOMAttribute, riid)) { 36 *ppv = &This->IHTMLDOMAttribute_iface; 37 }else if(IsEqualGUID(&IID_IHTMLDOMAttribute2, riid)) { 38 *ppv = &This->IHTMLDOMAttribute2_iface; 39 }else if(dispex_query_interface(&This->dispex, riid, ppv)) { 40 return *ppv ? S_OK : E_NOINTERFACE; 41 }else { 42 WARN("%s not supported\n", debugstr_mshtml_guid(riid)); 43 *ppv = NULL; 44 return E_NOINTERFACE; 45 } 46 47 IUnknown_AddRef((IUnknown*)*ppv); 48 return S_OK; 49 } 50 51 static ULONG WINAPI HTMLDOMAttribute_AddRef(IHTMLDOMAttribute *iface) 52 { 53 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 54 LONG ref = InterlockedIncrement(&This->ref); 55 56 TRACE("(%p) ref=%d\n", This, ref); 57 58 return ref; 59 } 60 61 static ULONG WINAPI HTMLDOMAttribute_Release(IHTMLDOMAttribute *iface) 62 { 63 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 64 LONG ref = InterlockedDecrement(&This->ref); 65 66 TRACE("(%p) ref=%d\n", This, ref); 67 68 if(!ref) { 69 assert(!This->elem); 70 release_dispex(&This->dispex); 71 heap_free(This->name); 72 heap_free(This); 73 } 74 75 return ref; 76 } 77 78 static HRESULT WINAPI HTMLDOMAttribute_GetTypeInfoCount(IHTMLDOMAttribute *iface, UINT *pctinfo) 79 { 80 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 81 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); 82 } 83 84 static HRESULT WINAPI HTMLDOMAttribute_GetTypeInfo(IHTMLDOMAttribute *iface, UINT iTInfo, 85 LCID lcid, ITypeInfo **ppTInfo) 86 { 87 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 88 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); 89 } 90 91 static HRESULT WINAPI HTMLDOMAttribute_GetIDsOfNames(IHTMLDOMAttribute *iface, REFIID riid, 92 LPOLESTR *rgszNames, UINT cNames, 93 LCID lcid, DISPID *rgDispId) 94 { 95 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 96 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames, 97 lcid, rgDispId); 98 } 99 100 static HRESULT WINAPI HTMLDOMAttribute_Invoke(IHTMLDOMAttribute *iface, DISPID dispIdMember, 101 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, 102 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 103 { 104 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 105 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, 106 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 107 } 108 109 static HRESULT WINAPI HTMLDOMAttribute_get_nodeName(IHTMLDOMAttribute *iface, BSTR *p) 110 { 111 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 112 113 TRACE("(%p)->(%p)\n", This, p); 114 115 if(!This->elem) { 116 if(!This->name) { 117 FIXME("No name available\n"); 118 return E_FAIL; 119 } 120 121 *p = SysAllocString(This->name); 122 return *p ? S_OK : E_OUTOFMEMORY; 123 } 124 125 return IDispatchEx_GetMemberName(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, p); 126 } 127 128 static HRESULT WINAPI HTMLDOMAttribute_put_nodeValue(IHTMLDOMAttribute *iface, VARIANT v) 129 { 130 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 131 DISPID dispidNamed = DISPID_PROPERTYPUT; 132 DISPPARAMS dp = {&v, &dispidNamed, 1, 1}; 133 EXCEPINFO ei; 134 VARIANT ret; 135 136 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v)); 137 138 if(!This->elem) { 139 FIXME("NULL This->elem\n"); 140 return E_UNEXPECTED; 141 } 142 143 memset(&ei, 0, sizeof(ei)); 144 145 return IDispatchEx_InvokeEx(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, LOCALE_SYSTEM_DEFAULT, 146 DISPATCH_PROPERTYPUT, &dp, &ret, &ei, NULL); 147 } 148 149 static HRESULT WINAPI HTMLDOMAttribute_get_nodeValue(IHTMLDOMAttribute *iface, VARIANT *p) 150 { 151 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 152 153 TRACE("(%p)->(%p)\n", This, p); 154 155 if(!This->elem) { 156 FIXME("NULL This->elem\n"); 157 return E_UNEXPECTED; 158 } 159 160 return get_elem_attr_value_by_dispid(This->elem, This->dispid, 0, p); 161 } 162 163 static HRESULT WINAPI HTMLDOMAttribute_get_specified(IHTMLDOMAttribute *iface, VARIANT_BOOL *p) 164 { 165 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface); 166 nsIDOMAttr *nsattr; 167 nsAString nsname; 168 BSTR name; 169 nsresult nsres; 170 HRESULT hres; 171 172 TRACE("(%p)->(%p)\n", This, p); 173 174 if(!This->elem || !This->elem->nselem) { 175 FIXME("NULL This->elem\n"); 176 return E_UNEXPECTED; 177 } 178 179 if(get_dispid_type(This->dispid) != DISPEXPROP_BUILTIN) { 180 *p = VARIANT_TRUE; 181 return S_OK; 182 } 183 184 hres = IDispatchEx_GetMemberName(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, &name); 185 if(FAILED(hres)) 186 return hres; 187 188 /* FIXME: This is not exactly right, we have some attributes that don't map directly to Gecko attributes. */ 189 nsAString_InitDepend(&nsname, name); 190 nsres = nsIDOMHTMLElement_GetAttributeNode(This->elem->nselem, &nsname, &nsattr); 191 nsAString_Finish(&nsname); 192 SysFreeString(name); 193 if(NS_FAILED(nsres)) 194 return E_FAIL; 195 196 /* If the Gecko attribute node can be found, we know that the attribute is specified. 197 There is no point in calling GetSpecified */ 198 if(nsattr) { 199 nsIDOMAttr_Release(nsattr); 200 *p = VARIANT_TRUE; 201 }else { 202 *p = VARIANT_FALSE; 203 } 204 return S_OK; 205 } 206 207 static const IHTMLDOMAttributeVtbl HTMLDOMAttributeVtbl = { 208 HTMLDOMAttribute_QueryInterface, 209 HTMLDOMAttribute_AddRef, 210 HTMLDOMAttribute_Release, 211 HTMLDOMAttribute_GetTypeInfoCount, 212 HTMLDOMAttribute_GetTypeInfo, 213 HTMLDOMAttribute_GetIDsOfNames, 214 HTMLDOMAttribute_Invoke, 215 HTMLDOMAttribute_get_nodeName, 216 HTMLDOMAttribute_put_nodeValue, 217 HTMLDOMAttribute_get_nodeValue, 218 HTMLDOMAttribute_get_specified 219 }; 220 221 static inline HTMLDOMAttribute *impl_from_IHTMLDOMAttribute2(IHTMLDOMAttribute2 *iface) 222 { 223 return CONTAINING_RECORD(iface, HTMLDOMAttribute, IHTMLDOMAttribute2_iface); 224 } 225 226 static HRESULT WINAPI HTMLDOMAttribute2_QueryInterface(IHTMLDOMAttribute2 *iface, REFIID riid, void **ppv) 227 { 228 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 229 return IHTMLDOMAttribute_QueryInterface(&This->IHTMLDOMAttribute_iface, riid, ppv); 230 } 231 232 static ULONG WINAPI HTMLDOMAttribute2_AddRef(IHTMLDOMAttribute2 *iface) 233 { 234 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 235 return IHTMLDOMAttribute_AddRef(&This->IHTMLDOMAttribute_iface); 236 } 237 238 static ULONG WINAPI HTMLDOMAttribute2_Release(IHTMLDOMAttribute2 *iface) 239 { 240 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 241 return IHTMLDOMAttribute_Release(&This->IHTMLDOMAttribute_iface); 242 } 243 244 static HRESULT WINAPI HTMLDOMAttribute2_GetTypeInfoCount(IHTMLDOMAttribute2 *iface, UINT *pctinfo) 245 { 246 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 247 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); 248 } 249 250 static HRESULT WINAPI HTMLDOMAttribute2_GetTypeInfo(IHTMLDOMAttribute2 *iface, UINT iTInfo, 251 LCID lcid, ITypeInfo **ppTInfo) 252 { 253 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 254 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); 255 } 256 257 static HRESULT WINAPI HTMLDOMAttribute2_GetIDsOfNames(IHTMLDOMAttribute2 *iface, REFIID riid, 258 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) 259 { 260 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 261 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames, 262 lcid, rgDispId); 263 } 264 265 static HRESULT WINAPI HTMLDOMAttribute2_Invoke(IHTMLDOMAttribute2 *iface, DISPID dispIdMember, 266 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, 267 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 268 { 269 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 270 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, 271 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 272 } 273 274 static HRESULT WINAPI HTMLDOMAttribute2_get_name(IHTMLDOMAttribute2 *iface, BSTR *p) 275 { 276 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 277 FIXME("(%p)->(%p)\n", This, p); 278 return E_NOTIMPL; 279 } 280 281 static HRESULT WINAPI HTMLDOMAttribute2_put_value(IHTMLDOMAttribute2 *iface, BSTR v) 282 { 283 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 284 FIXME("(%p)->(%s)\n", This, debugstr_w(v)); 285 return E_NOTIMPL; 286 } 287 288 static HRESULT WINAPI HTMLDOMAttribute2_get_value(IHTMLDOMAttribute2 *iface, BSTR *p) 289 { 290 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 291 VARIANT val; 292 HRESULT hres; 293 294 TRACE("(%p)->(%p)\n", This, p); 295 296 if(!This->elem) { 297 FIXME("NULL This->elem\n"); 298 return E_UNEXPECTED; 299 } 300 301 hres = get_elem_attr_value_by_dispid(This->elem, This->dispid, ATTRFLAG_ASSTRING, &val); 302 if(FAILED(hres)) 303 return hres; 304 305 assert(V_VT(&val) == VT_BSTR); 306 *p = V_BSTR(&val); 307 if(!*p && !(*p = SysAllocStringLen(NULL, 0))) 308 return E_OUTOFMEMORY; 309 return S_OK; 310 } 311 312 static HRESULT WINAPI HTMLDOMAttribute2_get_expando(IHTMLDOMAttribute2 *iface, VARIANT_BOOL *p) 313 { 314 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 315 316 TRACE("(%p)->(%p)\n", This, p); 317 318 *p = get_dispid_type(This->dispid) == DISPEXPROP_BUILTIN ? VARIANT_FALSE : VARIANT_TRUE; 319 return S_OK; 320 } 321 322 static HRESULT WINAPI HTMLDOMAttribute2_get_nodeType(IHTMLDOMAttribute2 *iface, LONG *p) 323 { 324 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 325 FIXME("(%p)->(%p)\n", This, p); 326 return E_NOTIMPL; 327 } 328 329 static HRESULT WINAPI HTMLDOMAttribute2_get_parentNode(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p) 330 { 331 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 332 FIXME("(%p)->(%p)\n", This, p); 333 return E_NOTIMPL; 334 } 335 336 static HRESULT WINAPI HTMLDOMAttribute2_get_childNodes(IHTMLDOMAttribute2 *iface, IDispatch **p) 337 { 338 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 339 FIXME("(%p)->(%p)\n", This, p); 340 return E_NOTIMPL; 341 } 342 343 static HRESULT WINAPI HTMLDOMAttribute2_get_firstChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p) 344 { 345 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 346 FIXME("(%p)->(%p)\n", This, p); 347 return E_NOTIMPL; 348 } 349 350 static HRESULT WINAPI HTMLDOMAttribute2_get_lastChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p) 351 { 352 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 353 FIXME("(%p)->(%p)\n", This, p); 354 return E_NOTIMPL; 355 } 356 357 static HRESULT WINAPI HTMLDOMAttribute2_get_previousSibling(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p) 358 { 359 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 360 FIXME("(%p)->(%p)\n", This, p); 361 return E_NOTIMPL; 362 } 363 364 static HRESULT WINAPI HTMLDOMAttribute2_get_nextSibling(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p) 365 { 366 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 367 FIXME("(%p)->(%p)\n", This, p); 368 return E_NOTIMPL; 369 } 370 371 static HRESULT WINAPI HTMLDOMAttribute2_get_attributes(IHTMLDOMAttribute2 *iface, IDispatch **p) 372 { 373 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 374 FIXME("(%p)->(%p)\n", This, p); 375 return E_NOTIMPL; 376 } 377 378 static HRESULT WINAPI HTMLDOMAttribute2_get_ownerDocument(IHTMLDOMAttribute2 *iface, IDispatch **p) 379 { 380 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 381 FIXME("(%p)->(%p)\n", This, p); 382 return E_NOTIMPL; 383 } 384 385 static HRESULT WINAPI HTMLDOMAttribute2_insertBefore(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *newChild, 386 VARIANT refChild, IHTMLDOMNode **node) 387 { 388 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 389 FIXME("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node); 390 return E_NOTIMPL; 391 } 392 393 static HRESULT WINAPI HTMLDOMAttribute2_replaceChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *newChild, 394 IHTMLDOMNode *oldChild, IHTMLDOMNode **node) 395 { 396 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 397 FIXME("(%p)->(%p %p %p)\n", This, newChild, oldChild, node); 398 return E_NOTIMPL; 399 } 400 401 static HRESULT WINAPI HTMLDOMAttribute2_removeChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *oldChild, 402 IHTMLDOMNode **node) 403 { 404 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 405 FIXME("(%p)->(%p %p)\n", This, oldChild, node); 406 return E_NOTIMPL; 407 } 408 409 static HRESULT WINAPI HTMLDOMAttribute2_appendChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *newChild, 410 IHTMLDOMNode **node) 411 { 412 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 413 FIXME("(%p)->(%p %p)\n", This, newChild, node); 414 return E_NOTIMPL; 415 } 416 417 static HRESULT WINAPI HTMLDOMAttribute2_hasChildNodes(IHTMLDOMAttribute2 *iface, VARIANT_BOOL *fChildren) 418 { 419 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 420 FIXME("(%p)->(%p)\n", This, fChildren); 421 return E_NOTIMPL; 422 } 423 424 static HRESULT WINAPI HTMLDOMAttribute2_cloneNode(IHTMLDOMAttribute2 *iface, VARIANT_BOOL fDeep, 425 IHTMLDOMAttribute **clonedNode) 426 { 427 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface); 428 FIXME("(%p)->(%x %p)\n", This, fDeep, clonedNode); 429 return E_NOTIMPL; 430 } 431 432 static const IHTMLDOMAttribute2Vtbl HTMLDOMAttribute2Vtbl = { 433 HTMLDOMAttribute2_QueryInterface, 434 HTMLDOMAttribute2_AddRef, 435 HTMLDOMAttribute2_Release, 436 HTMLDOMAttribute2_GetTypeInfoCount, 437 HTMLDOMAttribute2_GetTypeInfo, 438 HTMLDOMAttribute2_GetIDsOfNames, 439 HTMLDOMAttribute2_Invoke, 440 HTMLDOMAttribute2_get_name, 441 HTMLDOMAttribute2_put_value, 442 HTMLDOMAttribute2_get_value, 443 HTMLDOMAttribute2_get_expando, 444 HTMLDOMAttribute2_get_nodeType, 445 HTMLDOMAttribute2_get_parentNode, 446 HTMLDOMAttribute2_get_childNodes, 447 HTMLDOMAttribute2_get_firstChild, 448 HTMLDOMAttribute2_get_lastChild, 449 HTMLDOMAttribute2_get_previousSibling, 450 HTMLDOMAttribute2_get_nextSibling, 451 HTMLDOMAttribute2_get_attributes, 452 HTMLDOMAttribute2_get_ownerDocument, 453 HTMLDOMAttribute2_insertBefore, 454 HTMLDOMAttribute2_replaceChild, 455 HTMLDOMAttribute2_removeChild, 456 HTMLDOMAttribute2_appendChild, 457 HTMLDOMAttribute2_hasChildNodes, 458 HTMLDOMAttribute2_cloneNode 459 }; 460 461 static const tid_t HTMLDOMAttribute_iface_tids[] = { 462 IHTMLDOMAttribute_tid, 463 IHTMLDOMAttribute2_tid, 464 0 465 }; 466 static dispex_static_data_t HTMLDOMAttribute_dispex = { 467 NULL, 468 DispHTMLDOMAttribute_tid, 469 0, 470 HTMLDOMAttribute_iface_tids 471 }; 472 473 HRESULT HTMLDOMAttribute_Create(const WCHAR *name, HTMLElement *elem, DISPID dispid, HTMLDOMAttribute **attr) 474 { 475 HTMLAttributeCollection *col; 476 HTMLDOMAttribute *ret; 477 HRESULT hres; 478 479 ret = heap_alloc_zero(sizeof(*ret)); 480 if(!ret) 481 return E_OUTOFMEMORY; 482 483 ret->IHTMLDOMAttribute_iface.lpVtbl = &HTMLDOMAttributeVtbl; 484 ret->IHTMLDOMAttribute2_iface.lpVtbl = &HTMLDOMAttribute2Vtbl; 485 ret->ref = 1; 486 ret->dispid = dispid; 487 ret->elem = elem; 488 489 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLDOMAttribute_iface, 490 &HTMLDOMAttribute_dispex); 491 492 /* For attributes attached to an element, (elem,dispid) pair should be valid used for its operation. */ 493 if(elem) { 494 hres = HTMLElement_get_attr_col(&elem->node, &col); 495 if(FAILED(hres)) { 496 IHTMLDOMAttribute_Release(&ret->IHTMLDOMAttribute_iface); 497 return hres; 498 } 499 IHTMLAttributeCollection_Release(&col->IHTMLAttributeCollection_iface); 500 501 list_add_tail(&elem->attrs->attrs, &ret->entry); 502 } 503 504 /* For detached attributes we may still do most operations if we have its name available. */ 505 if(name) { 506 ret->name = heap_strdupW(name); 507 if(!ret->name) { 508 IHTMLDOMAttribute_Release(&ret->IHTMLDOMAttribute_iface); 509 return E_OUTOFMEMORY; 510 } 511 } 512 513 *attr = ret; 514 return S_OK; 515 } 516