ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dispex.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.