Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendispex.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2008-2009 Jacek Caban for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include <stdarg.h> 00020 00021 #define COBJMACROS 00022 00023 #include "windef.h" 00024 #include "winbase.h" 00025 #include "winuser.h" 00026 #include "ole2.h" 00027 00028 #include "wine/debug.h" 00029 00030 #include "mshtml_private.h" 00031 00032 WINE_DEFAULT_DEBUG_CHANNEL(mshtml); 00033 00034 static const WCHAR objectW[] = {'[','o','b','j','e','c','t',']',0}; 00035 00036 typedef struct { 00037 DISPID id; 00038 BSTR name; 00039 tid_t tid; 00040 int func_disp_idx; 00041 } func_info_t; 00042 00043 struct dispex_data_t { 00044 DWORD func_cnt; 00045 func_info_t *funcs; 00046 func_info_t **name_table; 00047 DWORD func_disp_cnt; 00048 00049 struct list entry; 00050 }; 00051 00052 typedef struct { 00053 VARIANT var; 00054 LPWSTR name; 00055 DWORD flags; 00056 } dynamic_prop_t; 00057 00058 #define DYNPROP_DELETED 0x01 00059 00060 typedef struct { 00061 DispatchEx dispex; 00062 const IUnknownVtbl *lpIUnknownVtbl; 00063 DispatchEx *obj; 00064 func_info_t *info; 00065 } func_disp_t; 00066 00067 #define FUNCUNKNOWN(x) ((IUnknown*) &(x)->lpIUnknownVtbl) 00068 00069 struct dispex_dynamic_data_t { 00070 DWORD buf_size; 00071 DWORD prop_cnt; 00072 dynamic_prop_t *props; 00073 func_disp_t **func_disps; 00074 }; 00075 00076 #define DISPID_DYNPROP_0 0x50000000 00077 #define DISPID_DYNPROP_MAX 0x5fffffff 00078 00079 #define FDEX_VERSION_MASK 0xf0000000 00080 00081 static ITypeLib *typelib; 00082 static ITypeInfo *typeinfos[LAST_tid]; 00083 static struct list dispex_data_list = LIST_INIT(dispex_data_list); 00084 00085 static REFIID tid_ids[] = { 00086 &IID_NULL, 00087 &DIID_DispCEventObj, 00088 &DIID_DispDOMChildrenCollection, 00089 &DIID_DispHTMLAnchorElement, 00090 &DIID_DispHTMLBody, 00091 &DIID_DispHTMLCommentElement, 00092 &DIID_DispHTMLCurrentStyle, 00093 &DIID_DispHTMLDocument, 00094 &DIID_DispHTMLDOMTextNode, 00095 &DIID_DispHTMLElementCollection, 00096 &DIID_DispHTMLFormElement, 00097 &DIID_DispHTMLGenericElement, 00098 &DIID_DispHTMLFrameElement, 00099 &DIID_DispHTMLIFrame, 00100 &DIID_DispHTMLImg, 00101 &DIID_DispHTMLInputElement, 00102 &DIID_DispHTMLLocation, 00103 &DIID_DispHTMLNavigator, 00104 &DIID_DispHTMLOptionElement, 00105 &DIID_DispHTMLScreen, 00106 &DIID_DispHTMLScriptElement, 00107 &DIID_DispHTMLSelectElement, 00108 &DIID_DispHTMLStyle, 00109 &DIID_DispHTMLTable, 00110 &DIID_DispHTMLTableRow, 00111 &DIID_DispHTMLTextAreaElement, 00112 &DIID_DispHTMLUnknownElement, 00113 &DIID_DispHTMLWindow2, 00114 &DIID_HTMLDocumentEvents, 00115 &IID_IHTMLAnchorElement, 00116 &IID_IHTMLBodyElement, 00117 &IID_IHTMLBodyElement2, 00118 &IID_IHTMLCommentElement, 00119 &IID_IHTMLCurrentStyle, 00120 &IID_IHTMLCurrentStyle2, 00121 &IID_IHTMLCurrentStyle3, 00122 &IID_IHTMLCurrentStyle4, 00123 &IID_IHTMLDocument2, 00124 &IID_IHTMLDocument3, 00125 &IID_IHTMLDocument4, 00126 &IID_IHTMLDocument5, 00127 &IID_IHTMLDOMChildrenCollection, 00128 &IID_IHTMLDOMNode, 00129 &IID_IHTMLDOMNode2, 00130 &IID_IHTMLDOMTextNode, 00131 &IID_IHTMLElement, 00132 &IID_IHTMLElement2, 00133 &IID_IHTMLElement3, 00134 &IID_IHTMLElement4, 00135 &IID_IHTMLElementCollection, 00136 &IID_IHTMLEventObj, 00137 &IID_IHTMLFiltersCollection, 00138 &IID_IHTMLFormElement, 00139 &IID_IHTMLFrameBase, 00140 &IID_IHTMLFrameBase2, 00141 &IID_IHTMLGenericElement, 00142 &IID_IHTMLFrameElement3, 00143 &IID_IHTMLIFrameElement, 00144 &IID_IHTMLImageElementFactory, 00145 &IID_IHTMLImgElement, 00146 &IID_IHTMLInputElement, 00147 &IID_IHTMLLocation, 00148 &IID_IHTMLOptionElement, 00149 &IID_IHTMLRect, 00150 &IID_IHTMLScreen, 00151 &IID_IHTMLScriptElement, 00152 &IID_IHTMLSelectElement, 00153 &IID_IHTMLStyle, 00154 &IID_IHTMLStyle2, 00155 &IID_IHTMLStyle3, 00156 &IID_IHTMLStyle4, 00157 &IID_IHTMLTable, 00158 &IID_IHTMLTableRow, 00159 &IID_IHTMLTextAreaElement, 00160 &IID_IHTMLTextContainer, 00161 &IID_IHTMLUniqueName, 00162 &IID_IHTMLWindow2, 00163 &IID_IHTMLWindow3, 00164 &IID_IHTMLWindow4, 00165 &IID_IOmNavigator 00166 }; 00167 00168 static HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo) 00169 { 00170 HRESULT hres; 00171 00172 if(!typelib) { 00173 ITypeLib *tl; 00174 00175 hres = LoadRegTypeLib(&LIBID_MSHTML, 4, 0, LOCALE_SYSTEM_DEFAULT, &tl); 00176 if(FAILED(hres)) { 00177 ERR("LoadRegTypeLib failed: %08x\n", hres); 00178 return hres; 00179 } 00180 00181 if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL)) 00182 ITypeLib_Release(tl); 00183 } 00184 00185 if(!typeinfos[tid]) { 00186 ITypeInfo *typeinfo; 00187 00188 hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &typeinfo); 00189 if(FAILED(hres)) { 00190 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres); 00191 return hres; 00192 } 00193 00194 if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), typeinfo, NULL)) 00195 ITypeInfo_Release(typeinfo); 00196 } 00197 00198 *typeinfo = typeinfos[tid]; 00199 return S_OK; 00200 } 00201 00202 void release_typelib(void) 00203 { 00204 dispex_data_t *iter; 00205 unsigned i; 00206 00207 while(!list_empty(&dispex_data_list)) { 00208 iter = LIST_ENTRY(list_head(&dispex_data_list), dispex_data_t, entry); 00209 list_remove(&iter->entry); 00210 00211 for(i=0; i < iter->func_cnt; i++) 00212 SysFreeString(iter->funcs[i].name); 00213 00214 heap_free(iter->funcs); 00215 heap_free(iter->name_table); 00216 heap_free(iter); 00217 } 00218 00219 if(!typelib) 00220 return; 00221 00222 for(i=0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++) 00223 if(typeinfos[i]) 00224 ITypeInfo_Release(typeinfos[i]); 00225 00226 ITypeLib_Release(typelib); 00227 } 00228 00229 static void add_func_info(dispex_data_t *data, DWORD *size, tid_t tid, const FUNCDESC *desc, ITypeInfo *dti) 00230 { 00231 HRESULT hres; 00232 00233 if(data->func_cnt && data->funcs[data->func_cnt-1].id == desc->memid) 00234 return; 00235 00236 if(data->func_cnt == *size) 00237 data->funcs = heap_realloc(data->funcs, (*size <<= 1)*sizeof(func_info_t)); 00238 00239 hres = ITypeInfo_GetDocumentation(dti, desc->memid, &data->funcs[data->func_cnt].name, NULL, NULL, NULL); 00240 if(FAILED(hres)) 00241 return; 00242 00243 data->funcs[data->func_cnt].id = desc->memid; 00244 data->funcs[data->func_cnt].tid = tid; 00245 data->funcs[data->func_cnt].func_disp_idx = (desc->invkind & DISPATCH_METHOD) ? data->func_disp_cnt++ : -1; 00246 00247 data->func_cnt++; 00248 } 00249 00250 static int dispid_cmp(const void *p1, const void *p2) 00251 { 00252 return ((const func_info_t*)p1)->id - ((const func_info_t*)p2)->id; 00253 } 00254 00255 static int func_name_cmp(const void *p1, const void *p2) 00256 { 00257 return strcmpiW((*(func_info_t* const*)p1)->name, (*(func_info_t* const*)p2)->name); 00258 } 00259 00260 static dispex_data_t *preprocess_dispex_data(DispatchEx *This) 00261 { 00262 const tid_t *tid = This->data->iface_tids; 00263 FUNCDESC *funcdesc; 00264 dispex_data_t *data; 00265 DWORD size = 16, i; 00266 ITypeInfo *ti, *dti; 00267 HRESULT hres; 00268 00269 TRACE("(%p)\n", This); 00270 00271 if(This->data->disp_tid) { 00272 hres = get_typeinfo(This->data->disp_tid, &dti); 00273 if(FAILED(hres)) { 00274 ERR("Could not get disp type info: %08x\n", hres); 00275 return NULL; 00276 } 00277 } 00278 00279 data = heap_alloc(sizeof(dispex_data_t)); 00280 data->func_cnt = 0; 00281 data->func_disp_cnt = 0; 00282 data->funcs = heap_alloc(size*sizeof(func_info_t)); 00283 list_add_tail(&dispex_data_list, &data->entry); 00284 00285 while(*tid) { 00286 hres = get_typeinfo(*tid, &ti); 00287 if(FAILED(hres)) 00288 break; 00289 00290 i=7; 00291 while(1) { 00292 hres = ITypeInfo_GetFuncDesc(ti, i++, &funcdesc); 00293 if(FAILED(hres)) 00294 break; 00295 00296 add_func_info(data, &size, *tid, funcdesc, dti); 00297 ITypeInfo_ReleaseFuncDesc(ti, funcdesc); 00298 } 00299 00300 tid++; 00301 } 00302 00303 if(!data->func_cnt) { 00304 heap_free(data->funcs); 00305 data->funcs = NULL; 00306 }else if(data->func_cnt != size) { 00307 data->funcs = heap_realloc(data->funcs, data->func_cnt * sizeof(func_info_t)); 00308 } 00309 00310 qsort(data->funcs, data->func_cnt, sizeof(func_info_t), dispid_cmp); 00311 00312 if(data->funcs) { 00313 data->name_table = heap_alloc(data->func_cnt * sizeof(func_info_t*)); 00314 for(i=0; i < data->func_cnt; i++) 00315 data->name_table[i] = data->funcs+i; 00316 qsort(data->name_table, data->func_cnt, sizeof(func_info_t*), func_name_cmp); 00317 }else { 00318 data->name_table = NULL; 00319 } 00320 00321 return data; 00322 } 00323 00324 static int id_cmp(const void *p1, const void *p2) 00325 { 00326 return *(const DISPID*)p1 - *(const DISPID*)p2; 00327 } 00328 00329 HRESULT get_dispids(tid_t tid, DWORD *ret_size, DISPID **ret) 00330 { 00331 unsigned i, func_cnt; 00332 FUNCDESC *funcdesc; 00333 ITypeInfo *ti; 00334 TYPEATTR *attr; 00335 DISPID *ids; 00336 HRESULT hres; 00337 00338 hres = get_typeinfo(tid, &ti); 00339 if(FAILED(hres)) 00340 return hres; 00341 00342 hres = ITypeInfo_GetTypeAttr(ti, &attr); 00343 if(FAILED(hres)) { 00344 ITypeInfo_Release(ti); 00345 return hres; 00346 } 00347 00348 func_cnt = attr->cFuncs; 00349 ITypeInfo_ReleaseTypeAttr(ti, attr); 00350 00351 ids = heap_alloc(func_cnt*sizeof(DISPID)); 00352 if(!ids) { 00353 ITypeInfo_Release(ti); 00354 return E_OUTOFMEMORY; 00355 } 00356 00357 for(i=0; i < func_cnt; i++) { 00358 hres = ITypeInfo_GetFuncDesc(ti, i, &funcdesc); 00359 if(FAILED(hres)) 00360 break; 00361 00362 ids[i] = funcdesc->memid; 00363 ITypeInfo_ReleaseFuncDesc(ti, funcdesc); 00364 } 00365 00366 ITypeInfo_Release(ti); 00367 if(FAILED(hres)) { 00368 heap_free(ids); 00369 return hres; 00370 } 00371 00372 qsort(ids, func_cnt, sizeof(DISPID), id_cmp); 00373 00374 *ret_size = func_cnt; 00375 *ret = ids; 00376 return S_OK; 00377 } 00378 00379 static CRITICAL_SECTION cs_dispex_static_data; 00380 static CRITICAL_SECTION_DEBUG cs_dispex_static_data_dbg = 00381 { 00382 0, 0, &cs_dispex_static_data, 00383 { &cs_dispex_static_data_dbg.ProcessLocksList, &cs_dispex_static_data_dbg.ProcessLocksList }, 00384 0, 0, { (DWORD_PTR)(__FILE__ ": dispex_static_data") } 00385 }; 00386 static CRITICAL_SECTION cs_dispex_static_data = { &cs_dispex_static_data_dbg, -1, 0, 0, 0, 0 }; 00387 00388 00389 static dispex_data_t *get_dispex_data(DispatchEx *This) 00390 { 00391 if(This->data->data) 00392 return This->data->data; 00393 00394 EnterCriticalSection(&cs_dispex_static_data); 00395 00396 if(!This->data->data) 00397 This->data->data = preprocess_dispex_data(This); 00398 00399 LeaveCriticalSection(&cs_dispex_static_data); 00400 00401 return This->data->data; 00402 } 00403 00404 HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp) 00405 { 00406 EXCEPINFO ei; 00407 IDispatchEx *dispex; 00408 VARIANT res; 00409 HRESULT hres; 00410 00411 VariantInit(&res); 00412 memset(&ei, 0, sizeof(ei)); 00413 00414 hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); 00415 if(SUCCEEDED(hres)) { 00416 hres = IDispatchEx_InvokeEx(dispex, 0, GetUserDefaultLCID(), DISPATCH_METHOD, dp, &res, &ei, NULL); 00417 IDispatchEx_Release(dispex); 00418 }else { 00419 TRACE("Could not get IDispatchEx interface: %08x\n", hres); 00420 hres = IDispatch_Invoke(disp, 0, &IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, 00421 dp, &res, &ei, NULL); 00422 } 00423 00424 VariantClear(&res); 00425 return hres; 00426 } 00427 00428 static inline BOOL is_custom_dispid(DISPID id) 00429 { 00430 return MSHTML_DISPID_CUSTOM_MIN <= id && id <= MSHTML_DISPID_CUSTOM_MAX; 00431 } 00432 00433 static inline BOOL is_dynamic_dispid(DISPID id) 00434 { 00435 return DISPID_DYNPROP_0 <= id && id <= DISPID_DYNPROP_MAX; 00436 } 00437 00438 static inline dispex_dynamic_data_t *get_dynamic_data(DispatchEx *This, BOOL alloc) 00439 { 00440 return !alloc || This->dynamic_data 00441 ? This->dynamic_data 00442 : (This->dynamic_data = heap_alloc_zero(sizeof(dispex_dynamic_data_t))); 00443 } 00444 00445 static HRESULT get_dynamic_prop(DispatchEx *This, const WCHAR *name, DWORD flags, dynamic_prop_t **ret) 00446 { 00447 const BOOL alloc = flags & fdexNameEnsure; 00448 dispex_dynamic_data_t *data; 00449 dynamic_prop_t *prop; 00450 00451 data = get_dynamic_data(This, alloc); 00452 if(!data) { 00453 if(alloc) 00454 return E_OUTOFMEMORY; 00455 00456 TRACE("not found %s\n", debugstr_w(name)); 00457 return DISP_E_UNKNOWNNAME; 00458 } 00459 00460 for(prop = data->props; prop < data->props+data->prop_cnt; prop++) { 00461 if(flags & fdexNameCaseInsensitive ? !strcmpiW(prop->name, name) : !strcmpW(prop->name, name)) { 00462 if(prop->flags & DYNPROP_DELETED) { 00463 if(!alloc) 00464 return DISP_E_UNKNOWNNAME; 00465 prop->flags &= ~DYNPROP_DELETED; 00466 } 00467 *ret = prop; 00468 return S_OK; 00469 } 00470 } 00471 00472 if(!alloc) 00473 return DISP_E_UNKNOWNNAME; 00474 00475 TRACE("creating dynamic prop %s\n", debugstr_w(name)); 00476 00477 if(!data->buf_size) { 00478 data->props = heap_alloc(sizeof(dynamic_prop_t)*4); 00479 if(!data->props) 00480 return E_OUTOFMEMORY; 00481 data->buf_size = 4; 00482 }else if(data->buf_size == data->prop_cnt) { 00483 dynamic_prop_t *new_props; 00484 00485 new_props = heap_realloc(data->props, sizeof(dynamic_prop_t)*(data->buf_size<<1)); 00486 if(!new_props) 00487 return E_OUTOFMEMORY; 00488 00489 data->props = new_props; 00490 data->buf_size <<= 1; 00491 } 00492 00493 prop = data->props + data->prop_cnt; 00494 00495 prop->name = heap_strdupW(name); 00496 if(!prop->name) 00497 return E_OUTOFMEMORY; 00498 00499 VariantInit(&prop->var); 00500 prop->flags = 0; 00501 data->prop_cnt++; 00502 *ret = prop; 00503 return S_OK; 00504 } 00505 00506 HRESULT dispex_get_dprop_ref(DispatchEx *This, const WCHAR *name, BOOL alloc, VARIANT **ret) 00507 { 00508 dynamic_prop_t *prop; 00509 HRESULT hres; 00510 00511 hres = get_dynamic_prop(This, name, alloc ? fdexNameEnsure : 0, &prop); 00512 if(FAILED(hres)) 00513 return hres; 00514 00515 *ret = &prop->var; 00516 return S_OK; 00517 } 00518 00519 static HRESULT dispex_value(DispatchEx *This, LCID lcid, WORD flags, DISPPARAMS *params, 00520 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) 00521 { 00522 if(This->data->vtbl && This->data->vtbl->value) 00523 return This->data->vtbl->value(This->outer, lcid, flags, params, res, ei, caller); 00524 00525 switch(flags) { 00526 case DISPATCH_PROPERTYGET: 00527 V_VT(res) = VT_BSTR; 00528 V_BSTR(res) = SysAllocString(objectW); 00529 if(!V_BSTR(res)) 00530 return E_OUTOFMEMORY; 00531 break; 00532 default: 00533 FIXME("Unimplemented flags %x\n", flags); 00534 return E_NOTIMPL; 00535 } 00536 00537 return S_OK; 00538 } 00539 00540 static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, 00541 EXCEPINFO *ei) 00542 { 00543 ITypeInfo *ti; 00544 IUnknown *unk; 00545 UINT argerr=0; 00546 HRESULT hres; 00547 00548 hres = get_typeinfo(func->tid, &ti); 00549 if(FAILED(hres)) { 00550 ERR("Could not get type info: %08x\n", hres); 00551 return hres; 00552 } 00553 00554 hres = IUnknown_QueryInterface(This->outer, tid_ids[func->tid], (void**)&unk); 00555 if(FAILED(hres)) { 00556 ERR("Could not get iface %s: %08x\n", debugstr_guid(tid_ids[func->tid]), hres); 00557 return E_FAIL; 00558 } 00559 00560 hres = ITypeInfo_Invoke(ti, unk, func->id, flags, dp, res, ei, &argerr); 00561 00562 IUnknown_Release(unk); 00563 return hres; 00564 } 00565 00566 #define FUNCTION_THIS(iface) DEFINE_THIS(func_disp_t, IUnknown, iface) 00567 00568 static HRESULT WINAPI Function_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 00569 { 00570 func_disp_t *This = FUNCTION_THIS(iface); 00571 00572 if(IsEqualGUID(&IID_IUnknown, riid)) { 00573 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 00574 *ppv = FUNCUNKNOWN(This); 00575 }else if(dispex_query_interface(&This->dispex, riid, ppv)) { 00576 return *ppv ? S_OK : E_NOINTERFACE; 00577 }else { 00578 *ppv = NULL; 00579 return E_NOINTERFACE; 00580 } 00581 00582 IUnknown_AddRef((IUnknown*)*ppv); 00583 return S_OK; 00584 } 00585 00586 static ULONG WINAPI Function_AddRef(IUnknown *iface) 00587 { 00588 func_disp_t *This = FUNCTION_THIS(iface); 00589 00590 TRACE("(%p)\n", This); 00591 00592 return IDispatchEx_AddRef(DISPATCHEX(This->obj)); 00593 } 00594 00595 static ULONG WINAPI Function_Release(IUnknown *iface) 00596 { 00597 func_disp_t *This = FUNCTION_THIS(iface); 00598 00599 TRACE("(%p)\n", This); 00600 00601 return IDispatchEx_Release(DISPATCHEX(This->obj)); 00602 } 00603 00604 static HRESULT function_value(IUnknown *iface, LCID lcid, WORD flags, DISPPARAMS *params, 00605 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) 00606 { 00607 func_disp_t *This = FUNCTION_THIS(iface); 00608 HRESULT hres; 00609 00610 switch(flags) { 00611 case DISPATCH_METHOD|DISPATCH_PROPERTYGET: 00612 if(!res) 00613 return E_INVALIDARG; 00614 case DISPATCH_METHOD: 00615 hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei); 00616 break; 00617 default: 00618 FIXME("Unimplemented flags %x\n", flags); 00619 hres = E_NOTIMPL; 00620 } 00621 00622 return hres; 00623 } 00624 00625 #undef FUNCTION_THIS 00626 00627 static const IUnknownVtbl FunctionUnkVtbl = { 00628 Function_QueryInterface, 00629 Function_AddRef, 00630 Function_Release 00631 }; 00632 00633 static const dispex_static_data_vtbl_t function_dispex_vtbl = { 00634 function_value, 00635 NULL, 00636 NULL 00637 }; 00638 00639 static const tid_t function_iface_tids[] = {0}; 00640 00641 static dispex_static_data_t function_dispex = { 00642 &function_dispex_vtbl, 00643 NULL_tid, 00644 NULL, 00645 function_iface_tids 00646 }; 00647 00648 static func_disp_t *create_func_disp(DispatchEx *obj, func_info_t *info) 00649 { 00650 func_disp_t *ret; 00651 00652 ret = heap_alloc_zero(sizeof(func_disp_t)); 00653 if(!ret) 00654 return NULL; 00655 00656 ret->lpIUnknownVtbl = &FunctionUnkVtbl; 00657 init_dispex(&ret->dispex, FUNCUNKNOWN(ret), &function_dispex); 00658 ret->obj = obj; 00659 ret->info = info; 00660 00661 return ret; 00662 } 00663 00664 static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, 00665 EXCEPINFO *ei) 00666 { 00667 HRESULT hres; 00668 00669 switch(flags) { 00670 case DISPATCH_METHOD|DISPATCH_PROPERTYGET: 00671 if(!res) 00672 return E_INVALIDARG; 00673 case DISPATCH_METHOD: 00674 hres = typeinfo_invoke(This, func, flags, dp, res, ei); 00675 break; 00676 case DISPATCH_PROPERTYGET: { 00677 dispex_dynamic_data_t *dynamic_data; 00678 00679 if(func->id == DISPID_VALUE) { 00680 BSTR ret; 00681 00682 ret = SysAllocString(objectW); 00683 if(!ret) 00684 return E_OUTOFMEMORY; 00685 00686 V_VT(res) = VT_BSTR; 00687 V_BSTR(res) = ret; 00688 return S_OK; 00689 } 00690 00691 dynamic_data = get_dynamic_data(This, TRUE); 00692 if(!dynamic_data) 00693 return E_OUTOFMEMORY; 00694 00695 if(!dynamic_data->func_disps) { 00696 dynamic_data->func_disps = heap_alloc_zero(This->data->data->func_disp_cnt * sizeof(func_disp_t*)); 00697 if(!dynamic_data->func_disps) 00698 return E_OUTOFMEMORY; 00699 } 00700 00701 if(!dynamic_data->func_disps[func->func_disp_idx]) { 00702 dynamic_data->func_disps[func->func_disp_idx] = create_func_disp(This, func); 00703 if(!dynamic_data->func_disps[func->func_disp_idx]) 00704 return E_OUTOFMEMORY; 00705 } 00706 00707 V_VT(res) = VT_DISPATCH; 00708 V_DISPATCH(res) = (IDispatch*)DISPATCHEX(&dynamic_data->func_disps[func->func_disp_idx]->dispex); 00709 IDispatch_AddRef(V_DISPATCH(res)); 00710 hres = S_OK; 00711 break; 00712 } 00713 default: 00714 FIXME("Unimplemented flags %x\n", flags); 00715 case DISPATCH_PROPERTYPUT: 00716 hres = E_NOTIMPL; 00717 } 00718 00719 return hres; 00720 } 00721 00722 static HRESULT get_builtin_func(dispex_data_t *data, DISPID id, func_info_t **ret) 00723 { 00724 int min, max, n; 00725 00726 min = 0; 00727 max = data->func_cnt-1; 00728 00729 while(min <= max) { 00730 n = (min+max)/2; 00731 00732 if(data->funcs[n].id == id) { 00733 *ret = data->funcs+n; 00734 return S_OK; 00735 } 00736 00737 if(data->funcs[n].id < id) 00738 min = n+1; 00739 else 00740 max = n-1; 00741 } 00742 00743 WARN("invalid id %x\n", id); 00744 return DISP_E_UNKNOWNNAME; 00745 } 00746 00747 static HRESULT get_builtin_id(DispatchEx *This, BSTR name, DWORD grfdex, DISPID *ret) 00748 { 00749 dispex_data_t *data; 00750 int min, max, n, c; 00751 00752 data = get_dispex_data(This); 00753 if(!data) 00754 return E_FAIL; 00755 00756 min = 0; 00757 max = data->func_cnt-1; 00758 00759 while(min <= max) { 00760 n = (min+max)/2; 00761 00762 c = strcmpiW(data->name_table[n]->name, name); 00763 if(!c) { 00764 if((grfdex & fdexNameCaseSensitive) && strcmpW(data->name_table[n]->name, name)) 00765 break; 00766 00767 *ret = data->name_table[n]->id; 00768 return S_OK; 00769 } 00770 00771 if(c > 0) 00772 max = n-1; 00773 else 00774 min = n+1; 00775 } 00776 00777 if(This->data->vtbl && This->data->vtbl->get_dispid) { 00778 HRESULT hres; 00779 00780 hres = This->data->vtbl->get_dispid(This->outer, name, grfdex, ret); 00781 if(hres != DISP_E_UNKNOWNNAME) 00782 return hres; 00783 } 00784 00785 return DISP_E_UNKNOWNNAME; 00786 } 00787 00788 static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, 00789 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) 00790 { 00791 dispex_data_t *data; 00792 func_info_t *func; 00793 HRESULT hres; 00794 00795 data = get_dispex_data(This); 00796 if(!data) 00797 return E_FAIL; 00798 00799 hres = get_builtin_func(data, id, &func); 00800 if(id == DISPID_VALUE && hres == DISP_E_UNKNOWNNAME) 00801 return dispex_value(This, lcid, flags, dp, res, ei, caller); 00802 if(FAILED(hres)) 00803 return hres; 00804 00805 if(func->func_disp_idx == -1) 00806 hres = typeinfo_invoke(This, func, flags, dp, res, ei); 00807 else 00808 hres = function_invoke(This, func, flags, dp, res, ei); 00809 00810 return hres; 00811 } 00812 00813 HRESULT remove_prop(DispatchEx *This, BSTR name, VARIANT_BOOL *success) 00814 { 00815 dynamic_prop_t *prop; 00816 DISPID id; 00817 HRESULT hres; 00818 00819 hres = get_builtin_id(This, name, 0, &id); 00820 if(hres == S_OK) { 00821 DISPID named_id = DISPID_PROPERTYPUT; 00822 VARIANT var; 00823 DISPPARAMS dp = {&var,&named_id,1,1}; 00824 EXCEPINFO ei; 00825 00826 V_VT(&var) = VT_EMPTY; 00827 memset(&ei, 0, sizeof(ei)); 00828 hres = invoke_builtin_prop(This, id, 0, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL); 00829 if(FAILED(hres)) 00830 return hres; 00831 00832 *success = VARIANT_TRUE; 00833 return S_OK; 00834 } 00835 00836 hres = get_dynamic_prop(This, name, 0, &prop); 00837 if(FAILED(hres)) { 00838 if(hres != DISP_E_UNKNOWNNAME) 00839 return hres; 00840 *success = VARIANT_FALSE; 00841 return S_OK; 00842 } 00843 00844 VariantClear(&prop->var); 00845 prop->flags |= DYNPROP_DELETED; 00846 *success = VARIANT_TRUE; 00847 return S_OK; 00848 } 00849 00850 #define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface) 00851 00852 static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) 00853 { 00854 DispatchEx *This = DISPATCHEX_THIS(iface); 00855 00856 return IUnknown_QueryInterface(This->outer, riid, ppv); 00857 } 00858 00859 static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) 00860 { 00861 DispatchEx *This = DISPATCHEX_THIS(iface); 00862 00863 return IUnknown_AddRef(This->outer); 00864 } 00865 00866 static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) 00867 { 00868 DispatchEx *This = DISPATCHEX_THIS(iface); 00869 00870 return IUnknown_Release(This->outer); 00871 } 00872 00873 static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) 00874 { 00875 DispatchEx *This = DISPATCHEX_THIS(iface); 00876 00877 TRACE("(%p)->(%p)\n", This, pctinfo); 00878 00879 *pctinfo = 1; 00880 return S_OK; 00881 } 00882 00883 static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, 00884 LCID lcid, ITypeInfo **ppTInfo) 00885 { 00886 DispatchEx *This = DISPATCHEX_THIS(iface); 00887 HRESULT hres; 00888 00889 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); 00890 00891 hres = get_typeinfo(This->data->disp_tid, ppTInfo); 00892 if(FAILED(hres)) 00893 return hres; 00894 00895 ITypeInfo_AddRef(*ppTInfo); 00896 return S_OK; 00897 } 00898 00899 static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, 00900 LPOLESTR *rgszNames, UINT cNames, 00901 LCID lcid, DISPID *rgDispId) 00902 { 00903 DispatchEx *This = DISPATCHEX_THIS(iface); 00904 UINT i; 00905 HRESULT hres; 00906 00907 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, 00908 lcid, rgDispId); 00909 00910 for(i=0; i < cNames; i++) { 00911 hres = IDispatchEx_GetDispID(DISPATCHEX(This), rgszNames[i], 0, rgDispId+i); 00912 if(FAILED(hres)) 00913 return hres; 00914 } 00915 00916 return S_OK; 00917 } 00918 00919 static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, 00920 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, 00921 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 00922 { 00923 DispatchEx *This = DISPATCHEX_THIS(iface); 00924 00925 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), 00926 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 00927 00928 return IDispatchEx_InvokeEx(DISPATCHEX(This), dispIdMember, lcid, wFlags, 00929 pDispParams, pVarResult, pExcepInfo, NULL); 00930 } 00931 00932 static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) 00933 { 00934 DispatchEx *This = DISPATCHEX_THIS(iface); 00935 dynamic_prop_t *dprop; 00936 HRESULT hres; 00937 00938 TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid); 00939 00940 if(grfdex & ~(fdexNameCaseSensitive|fdexNameCaseInsensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK)) 00941 FIXME("Unsupported grfdex %x\n", grfdex); 00942 00943 hres = get_builtin_id(This, bstrName, grfdex, pid); 00944 if(hres != DISP_E_UNKNOWNNAME) 00945 return hres; 00946 00947 hres = get_dynamic_prop(This, bstrName, grfdex, &dprop); 00948 if(FAILED(hres)) 00949 return hres; 00950 00951 *pid = DISPID_DYNPROP_0 + (dprop - This->dynamic_data->props); 00952 return S_OK; 00953 } 00954 00955 static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, 00956 VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) 00957 { 00958 DispatchEx *This = DISPATCHEX_THIS(iface); 00959 HRESULT hres; 00960 00961 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); 00962 00963 if(is_custom_dispid(id) && This->data->vtbl && This->data->vtbl->invoke) 00964 return This->data->vtbl->invoke(This->outer, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); 00965 00966 if(wFlags == DISPATCH_CONSTRUCT) { 00967 if(id == DISPID_VALUE) { 00968 if(This->data->vtbl && This->data->vtbl->value) { 00969 return This->data->vtbl->value(This->outer, lcid, wFlags, pdp, 00970 pvarRes, pei, pspCaller); 00971 } 00972 FIXME("DISPATCH_CONSTRUCT flag but missing value function\n"); 00973 return E_FAIL; 00974 } 00975 FIXME("DISPATCH_CONSTRUCT flag without DISPID_VALUE\n"); 00976 return E_FAIL; 00977 } 00978 00979 if(is_dynamic_dispid(id)) { 00980 DWORD idx = id - DISPID_DYNPROP_0; 00981 dynamic_prop_t *prop; 00982 00983 if(!This->dynamic_data || This->dynamic_data->prop_cnt <= idx) 00984 return DISP_E_UNKNOWNNAME; 00985 00986 prop = This->dynamic_data->props+idx; 00987 00988 switch(wFlags) { 00989 case DISPATCH_METHOD|DISPATCH_PROPERTYGET: 00990 if(!pvarRes) 00991 return E_INVALIDARG; 00992 case DISPATCH_METHOD: { 00993 DISPID named_arg = DISPID_THIS; 00994 DISPPARAMS dp = {NULL, &named_arg, 0, 1}; 00995 IDispatchEx *dispex; 00996 00997 if(V_VT(&prop->var) != VT_DISPATCH) { 00998 FIXME("invoke %s\n", debugstr_variant(&prop->var)); 00999 return E_NOTIMPL; 01000 } 01001 01002 if(pdp->cNamedArgs) { 01003 FIXME("named args not supported\n"); 01004 return E_NOTIMPL; 01005 } 01006 01007 dp.rgvarg = heap_alloc((pdp->cArgs+1)*sizeof(VARIANTARG)); 01008 if(!dp.rgvarg) 01009 return E_OUTOFMEMORY; 01010 01011 dp.cArgs = pdp->cArgs+1; 01012 memcpy(dp.rgvarg+1, pdp->rgvarg, pdp->cArgs*sizeof(VARIANTARG)); 01013 01014 V_VT(dp.rgvarg) = VT_DISPATCH; 01015 V_DISPATCH(dp.rgvarg) = (IDispatch*)DISPATCHEX(This); 01016 01017 hres = IDispatch_QueryInterface(V_DISPATCH(&prop->var), &IID_IDispatchEx, (void**)&dispex); 01018 TRACE("%s call\n", debugstr_w(This->dynamic_data->props[idx].name)); 01019 if(SUCCEEDED(hres)) { 01020 hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, lcid, wFlags, &dp, pvarRes, pei, pspCaller); 01021 IDispatchEx_Release(dispex); 01022 }else { 01023 ULONG err = 0; 01024 hres = IDispatch_Invoke(V_DISPATCH(&prop->var), DISPID_VALUE, &IID_NULL, lcid, wFlags, pdp, pvarRes, pei, &err); 01025 } 01026 TRACE("%s ret %08x\n", debugstr_w(This->dynamic_data->props[idx].name), hres); 01027 01028 heap_free(dp.rgvarg); 01029 return hres; 01030 } 01031 case DISPATCH_PROPERTYGET: 01032 if(prop->flags & DYNPROP_DELETED) 01033 return DISP_E_UNKNOWNNAME; 01034 return VariantCopy(pvarRes, &prop->var); 01035 case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF: 01036 case DISPATCH_PROPERTYPUT: 01037 if(pdp->cArgs != 1 || (pdp->cNamedArgs == 1 && *pdp->rgdispidNamedArgs != DISPID_PROPERTYPUT) 01038 || pdp->cNamedArgs > 1) { 01039 FIXME("invalid args\n"); 01040 return E_INVALIDARG; 01041 } 01042 01043 TRACE("put %s\n", debugstr_variant(pdp->rgvarg)); 01044 VariantClear(&prop->var); 01045 hres = VariantCopy(&prop->var, pdp->rgvarg); 01046 if(FAILED(hres)) 01047 return hres; 01048 01049 prop->flags &= ~DYNPROP_DELETED; 01050 return S_OK; 01051 default: 01052 FIXME("unhandled wFlags %x\n", wFlags); 01053 return E_NOTIMPL; 01054 } 01055 } 01056 01057 return invoke_builtin_prop(This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); 01058 } 01059 01060 static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) 01061 { 01062 DispatchEx *This = DISPATCHEX_THIS(iface); 01063 01064 TRACE("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex); 01065 01066 /* Not implemented by IE */ 01067 return E_NOTIMPL; 01068 } 01069 01070 static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) 01071 { 01072 DispatchEx *This = DISPATCHEX_THIS(iface); 01073 FIXME("(%p)->(%x)\n", This, id); 01074 return E_NOTIMPL; 01075 } 01076 01077 static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) 01078 { 01079 DispatchEx *This = DISPATCHEX_THIS(iface); 01080 FIXME("(%p)->(%x %x %p)\n", This, id, grfdexFetch, pgrfdex); 01081 return E_NOTIMPL; 01082 } 01083 01084 static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) 01085 { 01086 DispatchEx *This = DISPATCHEX_THIS(iface); 01087 dispex_data_t *data; 01088 func_info_t *func; 01089 HRESULT hres; 01090 01091 TRACE("(%p)->(%x %p)\n", This, id, pbstrName); 01092 01093 if(is_dynamic_dispid(id)) { 01094 DWORD idx = id - DISPID_DYNPROP_0; 01095 01096 if(!This->dynamic_data || This->dynamic_data->prop_cnt <= idx) 01097 return DISP_E_UNKNOWNNAME; 01098 01099 *pbstrName = SysAllocString(This->dynamic_data->props[idx].name); 01100 if(!*pbstrName) 01101 return E_OUTOFMEMORY; 01102 01103 return S_OK; 01104 } 01105 01106 data = get_dispex_data(This); 01107 if(!data) 01108 return E_FAIL; 01109 01110 hres = get_builtin_func(data, id, &func); 01111 if(FAILED(hres)) 01112 return hres; 01113 01114 *pbstrName = SysAllocString(func->name); 01115 if(!*pbstrName) 01116 return E_OUTOFMEMORY; 01117 return S_OK; 01118 } 01119 01120 static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) 01121 { 01122 DispatchEx *This = DISPATCHEX_THIS(iface); 01123 dispex_data_t *data; 01124 func_info_t *func; 01125 HRESULT hres; 01126 01127 TRACE("(%p)->(%x %x %p)\n", This, grfdex, id, pid); 01128 01129 if(is_dynamic_dispid(id)) { 01130 DWORD idx = id - DISPID_DYNPROP_0; 01131 01132 if(!This->dynamic_data || This->dynamic_data->prop_cnt <= idx) 01133 return DISP_E_UNKNOWNNAME; 01134 01135 while(++idx < This->dynamic_data->prop_cnt && This->dynamic_data->props[idx].flags & DYNPROP_DELETED); 01136 01137 if(idx == This->dynamic_data->prop_cnt) { 01138 *pid = DISPID_STARTENUM; 01139 return S_FALSE; 01140 } 01141 01142 *pid = DISPID_DYNPROP_0+idx; 01143 return S_OK; 01144 } 01145 01146 data = get_dispex_data(This); 01147 if(!data) 01148 return E_FAIL; 01149 01150 if(id == DISPID_STARTENUM) { 01151 func = data->funcs; 01152 }else { 01153 hres = get_builtin_func(data, id, &func); 01154 if(FAILED(hres)) 01155 return hres; 01156 func++; 01157 } 01158 01159 while(func < data->funcs+data->func_cnt) { 01160 /* FIXME: Skip hidden properties */ 01161 if(func->func_disp_idx == -1) { 01162 *pid = func->id; 01163 return S_OK; 01164 } 01165 func++; 01166 } 01167 01168 if(This->dynamic_data && This->dynamic_data->prop_cnt) { 01169 *pid = DISPID_DYNPROP_0; 01170 return S_OK; 01171 } 01172 01173 *pid = DISPID_STARTENUM; 01174 return S_FALSE; 01175 } 01176 01177 static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) 01178 { 01179 DispatchEx *This = DISPATCHEX_THIS(iface); 01180 FIXME("(%p)->(%p)\n", This, ppunk); 01181 return E_NOTIMPL; 01182 } 01183 01184 #undef DISPATCHEX_THIS 01185 01186 static IDispatchExVtbl DispatchExVtbl = { 01187 DispatchEx_QueryInterface, 01188 DispatchEx_AddRef, 01189 DispatchEx_Release, 01190 DispatchEx_GetTypeInfoCount, 01191 DispatchEx_GetTypeInfo, 01192 DispatchEx_GetIDsOfNames, 01193 DispatchEx_Invoke, 01194 DispatchEx_GetDispID, 01195 DispatchEx_InvokeEx, 01196 DispatchEx_DeleteMemberByName, 01197 DispatchEx_DeleteMemberByDispID, 01198 DispatchEx_GetMemberProperties, 01199 DispatchEx_GetMemberName, 01200 DispatchEx_GetNextDispID, 01201 DispatchEx_GetNameSpaceParent 01202 }; 01203 01204 BOOL dispex_query_interface(DispatchEx *This, REFIID riid, void **ppv) 01205 { 01206 static const IID IID_UndocumentedScriptIface = 01207 {0x719c3050,0xf9d3,0x11cf,{0xa4,0x93,0x00,0x40,0x05,0x23,0xa8,0xa0}}; 01208 static const IID IID_IDispatchJS = 01209 {0x719c3050,0xf9d3,0x11cf,{0xa4,0x93,0x00,0x40,0x05,0x23,0xa8,0xa6}}; 01210 01211 if(IsEqualGUID(&IID_IDispatch, riid)) { 01212 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv); 01213 *ppv = DISPATCHEX(This); 01214 }else if(IsEqualGUID(&IID_IDispatchEx, riid)) { 01215 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv); 01216 *ppv = DISPATCHEX(This); 01217 }else if(IsEqualGUID(&IID_IDispatchJS, riid)) { 01218 TRACE("(%p)->(IID_IDispatchJS %p) returning NULL\n", This, ppv); 01219 *ppv = NULL; 01220 }else if(IsEqualGUID(&IID_UndocumentedScriptIface, riid)) { 01221 TRACE("(%p)->(IID_UndocumentedScriptIface %p) returning NULL\n", This, ppv); 01222 *ppv = NULL; 01223 }else { 01224 return FALSE; 01225 } 01226 01227 if(*ppv) 01228 IUnknown_AddRef((IUnknown*)*ppv); 01229 return TRUE; 01230 } 01231 01232 void release_dispex(DispatchEx *This) 01233 { 01234 dynamic_prop_t *prop; 01235 01236 if(!This->dynamic_data) 01237 return; 01238 01239 for(prop = This->dynamic_data->props; prop < This->dynamic_data->props + This->dynamic_data->prop_cnt; prop++) { 01240 VariantClear(&prop->var); 01241 heap_free(prop->name); 01242 } 01243 01244 heap_free(This->dynamic_data->props); 01245 01246 if(This->dynamic_data->func_disps) { 01247 unsigned i; 01248 01249 for(i=0; i < This->data->data->func_disp_cnt; i++) { 01250 if(This->dynamic_data->func_disps[i]) { 01251 release_dispex(&This->dynamic_data->func_disps[i]->dispex); 01252 heap_free(This->dynamic_data->func_disps[i]); 01253 } 01254 } 01255 01256 heap_free(This->dynamic_data->func_disps); 01257 } 01258 01259 heap_free(This->dynamic_data); 01260 } 01261 01262 void init_dispex(DispatchEx *dispex, IUnknown *outer, dispex_static_data_t *data) 01263 { 01264 dispex->lpIDispatchExVtbl = &DispatchExVtbl; 01265 dispex->outer = outer; 01266 dispex->data = data; 01267 dispex->dynamic_data = NULL; 01268 } Generated on Sun May 27 2012 04:24:19 for ReactOS by
1.7.6.1
|