HRESULT jsval_copy(jsval_t v, jsval_t *r) { switch(jsval_type(v)) { case JSV_UNDEFINED: case JSV_NULL: case JSV_NUMBER: case JSV_BOOL: *r = v; return S_OK; case JSV_OBJECT: if(get_object(v)) IDispatch_AddRef(get_object(v)); *r = v; return S_OK; case JSV_STRING: { jsstr_addref(get_string(v)); *r = v; return S_OK; } case JSV_VARIANT: return jsval_variant(r, get_variant(v)); } assert(0); return E_FAIL; }
static HRESULT WINAPI Test_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { ok(pspCaller != NULL, "pspCaller == NULL\n"); switch(id) { case DISPID_TEST_TESTARGCONV: CHECK_EXPECT(testArgConv); ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags); ok(pdp != NULL, "pdp == NULL\n"); ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); ok(!pvarRes, "pvarRes != NULL\n"); ok(pei != NULL, "pei == NULL\n"); ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg)); test_caller(pspCaller, V_DISPATCH(pdp->rgvarg)); stored_obj = V_DISPATCH(pdp->rgvarg); IDispatch_AddRef(stored_obj); break; default: ok(0, "unexpected call\n"); return E_NOTIMPL; } return S_OK; }
static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, LONG index, IDispatch **ppItem) { HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); nsIDOMNode *nsnode = NULL; HTMLDOMNode *node; PRUint32 length=0; nsresult nsres; HRESULT hres; TRACE("(%p)->(%d %p)\n", This, index, ppItem); if (ppItem) *ppItem = NULL; else return E_POINTER; nsIDOMNodeList_GetLength(This->nslist, &length); if(index < 0 || index >= length) return E_INVALIDARG; nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode); if(NS_FAILED(nsres) || !nsnode) { ERR("Item failed: %08x\n", nsres); return E_FAIL; } hres = get_node(This->doc, nsnode, TRUE, &node); if(FAILED(hres)) return hres; *ppItem = (IDispatch*)&node->IHTMLDOMNode_iface; IDispatch_AddRef(*ppItem); return S_OK; }
HRESULT attach_event(EventTarget *event_target, BSTR name, IDispatch *disp, VARIANT_BOOL *res) { event_target_t *data; eventid_t eid; DWORD i = 0; eid = attr_to_eid(name); if(eid == EVENTID_LAST) { WARN("Unknown event\n"); *res = VARIANT_TRUE; return S_OK; } data = get_event_target_data(event_target, TRUE); if(!data) return E_OUTOFMEMORY; if(data->event_table[eid]) { while(i < data->event_table[eid]->handler_cnt && data->event_table[eid]->handlers[i]) i++; if(i == data->event_table[eid]->handler_cnt && !alloc_handler_vector(data, eid, i+1)) return E_OUTOFMEMORY; }else if(!alloc_handler_vector(data, eid, i+1)) { return E_OUTOFMEMORY; } IDispatch_AddRef(disp); data->event_table[eid]->handlers[i] = disp; bind_event(event_target, eid); *res = VARIANT_TRUE; return S_OK; }
HRESULT attach_event(event_target_t **event_target_ptr, HTMLDocument *doc, BSTR name, IDispatch *disp, VARIANT_BOOL *res) { event_target_t *event_target; eventid_t eid; DWORD i = 0; eid = attr_to_eid(name); if(eid == EVENTID_LAST) { WARN("Unknown event\n"); *res = VARIANT_TRUE; return S_OK; } event_target = get_event_target(event_target_ptr); if(!event_target) return E_OUTOFMEMORY; if(event_target->event_table[eid]) { while(i < event_target->event_table[eid]->handler_cnt && event_target->event_table[eid]->handlers[i]) i++; if(i == event_target->event_table[eid]->handler_cnt && !alloc_handler_vector(event_target, eid, i+1)) return E_OUTOFMEMORY; }else if(!alloc_handler_vector(event_target, eid, i+1)) { return E_OUTOFMEMORY; } IDispatch_AddRef(disp); event_target->event_table[eid]->handlers[i] = disp; *res = VARIANT_TRUE; return ensure_nsevent_handler(doc->doc_node, event_target, eid); }
static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei) { HRESULT hres; switch(flags) { case DISPATCH_METHOD|DISPATCH_PROPERTYGET: if(!res) return E_INVALIDARG; /* fall through */ case DISPATCH_METHOD: hres = typeinfo_invoke(This, func, flags, dp, res, ei); break; case DISPATCH_PROPERTYGET: { dispex_dynamic_data_t *dynamic_data; if(func->id == DISPID_VALUE) { BSTR ret; ret = SysAllocString(objectW); if(!ret) return E_OUTOFMEMORY; V_VT(res) = VT_BSTR; V_BSTR(res) = ret; return S_OK; } dynamic_data = get_dynamic_data(This); if(!dynamic_data) return E_OUTOFMEMORY; if(!dynamic_data->func_disps) { dynamic_data->func_disps = heap_alloc_zero(This->data->data->func_disp_cnt * sizeof(func_disp_t*)); if(!dynamic_data->func_disps) return E_OUTOFMEMORY; } if(!dynamic_data->func_disps[func->func_disp_idx]) { dynamic_data->func_disps[func->func_disp_idx] = create_func_disp(This, func); if(!dynamic_data->func_disps[func->func_disp_idx]) return E_OUTOFMEMORY; } V_VT(res) = VT_DISPATCH; V_DISPATCH(res) = (IDispatch*)&dynamic_data->func_disps[func->func_disp_idx]->dispex.IDispatchEx_iface; IDispatch_AddRef(V_DISPATCH(res)); hres = S_OK; break; } default: FIXME("Unimplemented flags %x\n", flags); /* fall through */ case DISPATCH_PROPERTYPUT: hres = E_NOTIMPL; } return hres; }
HRESULT variant_to_jsval(VARIANT *var, jsval_t *r) { switch(V_VT(var)) { case VT_EMPTY: *r = jsval_undefined(); return S_OK; case VT_NULL: *r = jsval_null(); return S_OK; case VT_BOOL: *r = jsval_bool(V_BOOL(var)); return S_OK; case VT_I4: *r = jsval_number(V_I4(var)); return S_OK; case VT_R8: *r = jsval_number(V_R8(var)); return S_OK; case VT_BSTR: { jsstr_t *str; str = jsstr_alloc_len(V_BSTR(var), SysStringLen(V_BSTR(var))); if(!str) return E_OUTOFMEMORY; if(!V_BSTR(var)) str->length_flags |= JSSTR_FLAG_NULLBSTR; *r = jsval_string(str); return S_OK; } case VT_DISPATCH: { if(V_DISPATCH(var)) IDispatch_AddRef(V_DISPATCH(var)); *r = jsval_disp(V_DISPATCH(var)); return S_OK; } case VT_I2: *r = jsval_number(V_I2(var)); return S_OK; case VT_INT: *r = jsval_number(V_INT(var)); return S_OK; case VT_UNKNOWN: if(V_UNKNOWN(var)) { IDispatch *disp; HRESULT hres; hres = IUnknown_QueryInterface(V_UNKNOWN(var), &IID_IDispatch, (void**)&disp); if(SUCCEEDED(hres)) { *r = jsval_disp(disp); return S_OK; } } /* fall through */ default: return jsval_variant(r, var); } }
static HRESULT get_item_idx(HTMLElementCollection *This, UINT idx, IDispatch **ret) { if(idx < This->len) { *ret = (IDispatch*)This->elems[idx]; IDispatch_AddRef(*ret); } return S_OK; }
static HRESULT get_item_idx(HTMLElementCollection *This, UINT idx, IDispatch **ret) { if(idx < This->len) { *ret = (IDispatch*)&This->elems[idx]->node.event_target.dispex.IDispatchEx_iface; IDispatch_AddRef(*ret); } return S_OK; }
static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstrName, DWORD dwFlags) { JScript *This = impl_from_IActiveScript(iface); named_item_t *item; IDispatch *disp = NULL; HRESULT hres; TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags); if(This->thread_id != GetCurrentThreadId() || !This->ctx || This->ctx->state == SCRIPTSTATE_CLOSED) return E_UNEXPECTED; if(dwFlags & SCRIPTITEM_GLOBALMEMBERS) { IUnknown *unk; hres = IActiveScriptSite_GetItemInfo(This->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL); if(FAILED(hres)) { WARN("GetItemInfo failed: %08x\n", hres); return hres; } hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp); IUnknown_Release(unk); if(FAILED(hres)) { WARN("object does not implement IDispatch\n"); return hres; } if(This->ctx->host_global) IDispatch_Release(This->ctx->host_global); IDispatch_AddRef(disp); This->ctx->host_global = disp; } item = heap_alloc(sizeof(*item)); if(!item) { if(disp) IDispatch_Release(disp); return E_OUTOFMEMORY; } item->disp = disp; item->flags = dwFlags; item->name = heap_strdupW(pstrName); if(!item->name) { if(disp) IDispatch_Release(disp); heap_free(item); return E_OUTOFMEMORY; } item->next = This->ctx->named_items; This->ctx->named_items = item; return S_OK; }
static HRESULT WINAPI HTMLFormElement_get_elements(IHTMLFormElement *iface, IDispatch **p) { HTMLFormElement *This = impl_from_IHTMLFormElement(iface); TRACE("(%p)->(%p)\n", This, p); *p = (IDispatch*)&This->IHTMLFormElement_iface; IDispatch_AddRef(*p); return S_OK; }
HRESULT jsval_to_variant(jsval_t val, VARIANT *retv) { switch(jsval_type(val)) { case JSV_UNDEFINED: V_VT(retv) = VT_EMPTY; return S_OK; case JSV_NULL: V_VT(retv) = VT_NULL; return S_OK; case JSV_OBJECT: V_VT(retv) = VT_DISPATCH; if(get_object(val)) IDispatch_AddRef(get_object(val)); V_DISPATCH(retv) = get_object(val); return S_OK; case JSV_STRING: { jsstr_t *str = get_string(val); V_VT(retv) = VT_BSTR; if(str->length_flags & JSSTR_FLAG_NULLBSTR) { V_BSTR(retv) = NULL; } else { V_BSTR(retv) = SysAllocStringLen(NULL, jsstr_length(str)); if(V_BSTR(retv)) jsstr_flush(str, V_BSTR(retv)); else return E_OUTOFMEMORY; } return S_OK; } case JSV_NUMBER: { double n = get_number(val); if(is_int32(n)) { V_VT(retv) = VT_I4; V_I4(retv) = n; } else { V_VT(retv) = VT_R8; V_R8(retv) = n; } return S_OK; } case JSV_BOOL: V_VT(retv) = VT_BOOL; V_BOOL(retv) = get_bool(val) ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; case JSV_VARIANT: V_VT(retv) = VT_EMPTY; return VariantCopy(retv, get_variant(val)); } assert(0); return E_FAIL; }
static HRESULT WINAPI httprequest_put_onreadystatechange(IXMLHTTPRequest *iface, IDispatch *sink) { httprequest *This = impl_from_IXMLHTTPRequest( iface ); TRACE("(%p)->(%p)\n", This, sink); if (This->sink) IDispatch_Release(This->sink); if ((This->sink = sink)) IDispatch_AddRef(This->sink); return S_OK; }
HRESULT get_event_handler(event_target_t **event_target, eventid_t eid, VARIANT *var) { if(*event_target && (*event_target)->event_table[eid] && (*event_target)->event_table[eid]->handler_prop) { V_VT(var) = VT_DISPATCH; V_DISPATCH(var) = (*event_target)->event_table[eid]->handler_prop; IDispatch_AddRef(V_DISPATCH(var)); }else { V_VT(var) = VT_NULL; } return S_OK; }
static HRESULT HTMLIFrame_get_document(HTMLDOMNode *iface, IDispatch **p) { HTMLIFrame *This = impl_from_HTMLDOMNode(iface); if(!This->framebase.content_window || !This->framebase.content_window->doc) { *p = NULL; return S_OK; } *p = (IDispatch*)&This->framebase.content_window->doc->basedoc.IHTMLDocument2_iface; IDispatch_AddRef(*p); return S_OK; }
static HRESULT WINAPI WebBrowser_get_Application(IWebBrowser2 *iface, IDispatch **ppDisp) { WebBrowser *This = WEBBROWSER_THIS(iface); TRACE("(%p)->(%p)\n", This, ppDisp); if(!ppDisp) return E_POINTER; *ppDisp = (IDispatch*)WEBBROWSER2(This); IDispatch_AddRef(*ppDisp); return S_OK; }
static HRESULT WINAPI WebBrowser_get_Application(IWebBrowser2 *iface, IDispatch **ppDisp) { WebBrowser *This = impl_from_IWebBrowser2(iface); TRACE("(%p)->(%p)\n", This, ppDisp); if(!ppDisp) return E_POINTER; *ppDisp = (IDispatch*)&This->IWebBrowser2_iface; IDispatch_AddRef(*ppDisp); return S_OK; }
static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p) { HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface); TRACE("(%p)->(%p)\n", This, p); /* FIXME: Better check for document node */ if(This == &This->doc->node) { *p = NULL; }else { *p = (IDispatch*)&This->doc->basedoc.IHTMLDocument2_iface; IDispatch_AddRef(*p); } return S_OK; }
static HRESULT WINAPI dispevent_QueryInterface(IDispatch *iface, REFIID riid, void **ppvObject) { *ppvObject = NULL; if ( IsEqualGUID( riid, &IID_IDispatch) || IsEqualGUID( riid, &IID_IUnknown) ) { *ppvObject = iface; } else return E_NOINTERFACE; IDispatch_AddRef( iface ); return S_OK; }
static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp) { JScript *This = impl_from_IActiveScript(iface); TRACE("(%p)->(%p)\n", This, ppdisp); if(!ppdisp) return E_POINTER; if(This->thread_id != GetCurrentThreadId() || !This->ctx->global) { *ppdisp = NULL; return E_UNEXPECTED; } *ppdisp = to_disp(This->ctx->global); IDispatch_AddRef(*ppdisp); return S_OK; }
static HRESULT WINAPI HTMLElementCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) { HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface); ULONG fetched = 0; TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, pCeltFetched); while(This->iter+fetched < This->col->len && fetched < celt) { V_VT(rgVar+fetched) = VT_DISPATCH; V_DISPATCH(rgVar+fetched) = (IDispatch*)&This->col->elems[This->iter+fetched]->IHTMLElement_iface; IDispatch_AddRef(V_DISPATCH(rgVar+fetched)); fetched++; } This->iter += fetched; if(pCeltFetched) *pCeltFetched = fetched; return fetched == celt ? S_OK : S_FALSE; }
static HRESULT set_event_handler_disp(EventTarget *event_target, eventid_t eid, IDispatch *disp) { event_target_t *data; remove_event_handler(event_target, eid); if(!disp) return S_OK; data = get_event_target_data(event_target, TRUE); if(!data) return E_OUTOFMEMORY; if(!alloc_handler_vector(data, eid, 0)) return E_OUTOFMEMORY; data->event_table[eid]->handler_prop = disp; IDispatch_AddRef(disp); bind_event(event_target, eid); return S_OK; }
PHP_COM_DOTNET_API void php_com_wrap_dispatch(zval *z, IDispatch *disp, int codepage) { php_com_dotnet_object *obj; obj = emalloc(sizeof(*obj)); memset(obj, 0, sizeof(*obj)); obj->code_page = codepage; obj->ce = php_com_variant_class_entry; obj->zo.ce = php_com_variant_class_entry; VariantInit(&obj->v); V_VT(&obj->v) = VT_DISPATCH; V_DISPATCH(&obj->v) = disp; IDispatch_AddRef(V_DISPATCH(&obj->v)); IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo); zend_object_std_init(&obj->zo, php_com_variant_class_entry); obj->zo.handlers = &php_com_object_handlers; ZVAL_OBJ(z, &obj->zo); }
/* ECMA-262 3rd Edition 9.9 */ HRESULT to_object(exec_ctx_t *ctx, VARIANT *v, IDispatch **disp) { DispatchEx *dispex; HRESULT hres; switch(V_VT(v)) { case VT_BSTR: hres = create_string(ctx->parser->script, V_BSTR(v), SysStringLen(V_BSTR(v)), &dispex); if(FAILED(hres)) return hres; *disp = (IDispatch*)_IDispatchEx_(dispex); break; case VT_I4: case VT_R8: hres = create_number(ctx->parser->script, v, &dispex); if(FAILED(hres)) return hres; *disp = (IDispatch*)_IDispatchEx_(dispex); break; case VT_DISPATCH: IDispatch_AddRef(V_DISPATCH(v)); *disp = V_DISPATCH(v); break; case VT_BOOL: hres = create_bool(ctx->parser->script, V_BOOL(v), &dispex); if(FAILED(hres)) return hres; *disp = (IDispatch*)_IDispatchEx_(dispex); break; default: FIXME("unsupported vt %d\n", V_VT(v)); return E_NOTIMPL; } return S_OK; }
HRESULT get_event_handler(EventTarget *event_target, eventid_t eid, VARIANT *var) { event_target_t *data; VARIANT *v; HRESULT hres; hres = dispex_get_dprop_ref(&event_target->dispex, event_info[eid].attr_name, FALSE, &v); if(SUCCEEDED(hres) && V_VT(v) != VT_EMPTY) { V_VT(var) = VT_EMPTY; return VariantCopy(var, v); } data = get_event_target_data(event_target, FALSE); if(data && data->event_table[eid] && data->event_table[eid]->handler_prop) { V_VT(var) = VT_DISPATCH; V_DISPATCH(var) = data->event_table[eid]->handler_prop; IDispatch_AddRef(V_DISPATCH(var)); }else { V_VT(var) = VT_NULL; } return S_OK; }
static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, HTMLDocumentNode *doc, eventid_t eid, IDispatch *disp) { event_target_t *event_target; if(!disp) return remove_event_handler(event_target_ptr, eid); event_target = get_event_target(event_target_ptr); if(!event_target) return E_OUTOFMEMORY; if(!alloc_handler_vector(event_target, eid, 0)) return E_OUTOFMEMORY; if(event_target->event_table[eid]->handler_prop) IDispatch_Release(event_target->event_table[eid]->handler_prop); event_target->event_table[eid]->handler_prop = disp; IDispatch_AddRef(disp); return ensure_nsevent_handler(doc, event_target, eid); }
HRESULT get_plugin_disp(HTMLPluginContainer *plugin_container, IDispatch **ret) { PluginHost *host; host = plugin_container->plugin_host; if(!host) { ERR("No plugin host\n"); return E_UNEXPECTED; } if(!host->disp) { *ret = NULL; return S_OK; } if(!check_script_safety(host)) { FIXME("Insecure object\n"); return E_FAIL; } IDispatch_AddRef(host->disp); *ret = host->disp; return S_OK; }
static HRESULT WINAPI HTMLElementCollection_item(IHTMLElementCollection *iface, VARIANT name, VARIANT index, IDispatch **pdisp) { HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface); HRESULT hres = S_OK; TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(&name), debugstr_variant(&index), pdisp); *pdisp = NULL; switch(V_VT(&name)) { case VT_I4: case VT_INT: if(V_I4(&name) < 0) return E_INVALIDARG; hres = get_item_idx(This, V_I4(&name), pdisp); break; case VT_UI4: case VT_UINT: hres = get_item_idx(This, V_UINT(&name), pdisp); break; case VT_BSTR: { DWORD i; if(V_VT(&index) == VT_I4) { LONG idx = V_I4(&index); if(idx < 0) return E_INVALIDARG; for(i=0; i<This->len; i++) { if(is_elem_name(This->elems[i], V_BSTR(&name)) && !idx--) break; } if(i != This->len) { *pdisp = (IDispatch*)&This->elems[i]->IHTMLElement_iface; IDispatch_AddRef(*pdisp); } }else { elem_vector_t buf = {NULL, 0, 8}; buf.buf = heap_alloc(buf.size*sizeof(HTMLElement*)); for(i=0; i<This->len; i++) { if(is_elem_name(This->elems[i], V_BSTR(&name))) { node_addref(&This->elems[i]->node); elem_vector_add(&buf, This->elems[i]); } } if(buf.len > 1) { elem_vector_normalize(&buf); *pdisp = (IDispatch*)HTMLElementCollection_Create(buf.buf, buf.len); }else { if(buf.len == 1) { /* Already AddRef-ed */ *pdisp = (IDispatch*)&buf.buf[0]->IHTMLElement_iface; } heap_free(buf.buf); } } break; } default: FIXME("Unsupported name %s\n", debugstr_variant(&name)); hres = E_NOTIMPL; } if(SUCCEEDED(hres)) TRACE("returning %p\n", *pdisp); return hres; }
static HRESULT get_ie_elem_at(IDispatch *doc, int x, int y, IDispatch **ret_elem) { IDispatch *inner_doc; VARIANTARG args[2]; VARIANT var; HRESULT hres; inner_doc = doc; IDispatch_AddRef(inner_doc); { IDispatch *win; hres = get_property_dp(inner_doc, L"parentWindow", &win); if(FAILED(hres)) { IDispatch_Release(inner_doc); spr->log_hresult( LOG_LEVEL_NOTIFY, L"ie-scroll: Failed to get document.parentWindow", hres, 1); return hres; } { long sx = 0, sy = 0; get_property_long(win, L"screenLeft", &sx); get_property_long(win, L"screenTop", &sy); IDispatch_Release(win); x -= sx; y -= sy; } } while(1) { IDispatch *elem; args[0].vt = VT_I4; args[0].lVal = y; args[1].vt = VT_I4; args[1].lVal = x; hres = call_method_s(inner_doc, L"elementFromPoint", args, 2, &var); IDispatch_Release(inner_doc); if(FAILED(hres)) { spr->log_hresult( LOG_LEVEL_NOTIFY, L"ie-scroll: Failed to get document.elementFromPoint", hres, 1); return hres; } if(var.vt != VT_DISPATCH) { spr->log_printf( LOG_LEVEL_NOTIFY, L"ie-scroll: Failed to get document.elementFromPoint: " L"return value is not IDispatch\n"); return E_FAIL; } elem = var.pdispVal; if(elem == NULL) { spr->log_printf( LOG_LEVEL_NOTIFY, L"ie-scroll: Failed to get document.elementFromPoint: " L"return value is NULL\n"); return E_FAIL; } { BSTR str; hres = get_property_str(elem, L"tagName", &str); if(FAILED(hres)) { IDispatch_Release(elem); spr->log_hresult( LOG_LEVEL_NOTIFY, L"ie-scroll: Failed to get element.tagName", hres, 1); return hres; } spr->log_printf(LOG_LEVEL_DEBUG, L"ie-scroll: tagName of target element: %ls\n", str); if(str == NULL || wcsstr(str, L"FRAME") == NULL) { SysFreeString(str); *ret_elem = elem; break; } SysFreeString(str); } { static LPOLESTR props[] = {L"contentWindow", L"document", NULL}; hres = get_property_dpv(elem, props, &inner_doc); } if(FAILED(hres)) { *ret_elem = elem; spr->log_hresult( LOG_LEVEL_NOTIFY, L"ie-scroll: Failed to get " L"frameElement.contentWindow.document", hres, 1); break; } while(1) { IDispatch *parent = NULL; long ox = 0, oy = 0, cx = 0, cy = 0, sx = 0, sy = 0; BSTR tp = NULL; get_property_long(elem, L"clientLeft", &cx); get_property_long(elem, L"clientTop", &cy); get_property_long(elem, L"offsetLeft", &ox); get_property_long(elem, L"offsetTop", &oy); get_property_long(elem, L"scrollLeft", &sx); get_property_long(elem, L"scrollTop", &sy); x -= cx + ox - sx; y -= cy + oy - sy; hres = get_property_dp(elem, L"offsetParent", &parent); if(FAILED(hres) || parent == NULL) { break; } get_property_str(parent, L"tagName", &tp); if(tp != NULL && wcscmp(tp, L"FRAMESET") == 0) { SysFreeString(tp); IDispatch_Release(parent); break; } SysFreeString(tp); IDispatch_Release(elem); elem = parent; } while(1) { IDispatch *parent = NULL; long sx = 0, sy = 0; hres = get_property_dp(elem, L"parentElement", &parent); if(FAILED(hres) || parent == NULL) { break; } get_property_long(parent, L"scrollLeft", &sx); get_property_long(parent, L"scrollTop", &sy); x += sx; y += sy; IDispatch_Release(elem); elem = parent; } IDispatch_Release(elem); } return S_OK; }
static HRESULT get_scrollable_parent(IDispatch *elem, IDispatch **ret_elem) { HRESULT hres; IDispatch_AddRef(elem); while(1) { BSTR overflow = NULL, curoverflow = NULL, tagname = NULL; BSTR compatmode = NULL; static LPOLESTR props[] = {L"style", L"overflow", NULL}; static LPOLESTR curprops[] = {L"currentStyle", L"overflow", NULL}; static LPOLESTR compatmode_props[] = { L"ownerDocument", L"compatMode", NULL }; if(SUCCEEDED(get_property_strv(elem, props, &overflow)) && SUCCEEDED(get_property_strv(elem, curprops, &curoverflow)) && SUCCEEDED(get_property_str(elem, L"tagName", &tagname))) { if(overflow == NULL) { overflow = curoverflow; curoverflow = NULL; } if((tagname != NULL && (wcscmp(tagname, L"HTML") == 0 || wcscmp(tagname, L"BODY") == 0 || wcscmp(tagname, L"TEXTAREA") == 0) && (overflow == NULL || wcscmp(overflow, L"visible") == 0)) || (overflow != NULL && (wcscmp(overflow, L"auto") == 0 || wcscmp(overflow, L"scroll") == 0))) { long cw, ch, sw, sh; if(tagname != NULL && wcscmp(tagname, L"BODY") == 0 && SUCCEEDED(get_property_strv(elem, compatmode_props, &compatmode)) && compatmode != NULL && wcscmp(compatmode, L"CSS1Compat") == 0) { /* workaround for IE7: ignore BODY element if DOCTYPE is exists */ } else if( SUCCEEDED(get_property_long(elem, L"clientWidth", &cw)) && SUCCEEDED(get_property_long(elem, L"clientHeight", &ch)) && SUCCEEDED(get_property_long(elem, L"scrollWidth", &sw)) && SUCCEEDED(get_property_long(elem, L"scrollHeight", &sh))) { if(cw != 0 && ch != 0 && (cw < sw || ch < sh)) { spr->log_printf( LOG_LEVEL_DEBUG, L"ie-scroll: tagName of scroll target element: " L"%ls\n", tagname); SysFreeString(overflow); SysFreeString(curoverflow); SysFreeString(tagname); SysFreeString(compatmode); break; } } } } SysFreeString(overflow); SysFreeString(curoverflow); SysFreeString(tagname); SysFreeString(compatmode); { IDispatch *parent; hres = get_property_dp(elem, L"parentElement", &parent); IDispatch_Release(elem); if(FAILED(hres)) { spr->log_hresult( LOG_LEVEL_NOTIFY, L"ie-scroll: Failed to get element.parentElement", hres, 1); return hres; } if(parent == NULL) { spr->log_printf( LOG_LEVEL_DEBUG, L"ie-scroll: scroll target element is not found\n"); return E_FAIL; } elem = parent; } } *ret_elem = elem; return S_OK; }