📄 dispatch.c
字号:
zval_ptr_dtor(params[i]); efree(params); /* return value */ if (retval) { if (pvarRes) { if (Z_TYPE_P(retval) == IS_OBJECT) { /* export the object using a dispatch like ourselves */ VariantInit(pvarRes); V_VT(pvarRes) = VT_DISPATCH; V_DISPATCH(pvarRes) = php_COM_export_object(retval TSRMLS_CC); } else { php_pval_to_variant(retval, pvarRes, codepage TSRMLS_CC); } } zval_ptr_dtor(&retval); } else if (pvarRes) { VariantInit(pvarRes); } } else { trace("InvokeEx: I don't support DISPID=%d\n", id); } return ret;}static HRESULT STDMETHODCALLTYPE disp_deletememberbyname( IDispatchEx *This, /* [in] */ BSTR bstrName, /* [in] */ DWORD grfdex){ FETCH_DISP("DeleteMemberByName"); return S_FALSE;}static HRESULT STDMETHODCALLTYPE disp_deletememberbydispid( IDispatchEx *This, /* [in] */ DISPID id){ FETCH_DISP("DeleteMemberByDispID"); return S_FALSE;}static HRESULT STDMETHODCALLTYPE disp_getmemberproperties( IDispatchEx *This, /* [in] */ DISPID id, /* [in] */ DWORD grfdexFetch, /* [out] */ DWORD *pgrfdex){ FETCH_DISP("GetMemberProperties"); return DISP_E_UNKNOWNNAME;}static HRESULT STDMETHODCALLTYPE disp_getmembername( IDispatchEx *This, /* [in] */ DISPID id, /* [out] */ BSTR *pbstrName){ zval *name; TSRMLS_FETCH(); FETCH_DISP("GetMemberName"); if (SUCCESS == zend_hash_index_find(disp->dispid_to_name, id, (void**)&name)) { OLECHAR *olestr = php_char_to_OLECHAR(Z_STRVAL_P(name), Z_STRLEN_P(name), CP_ACP TSRMLS_CC); *pbstrName = SysAllocString(olestr); efree(olestr); return S_OK; } else { return DISP_E_UNKNOWNNAME; }}static HRESULT STDMETHODCALLTYPE disp_getnextdispid( IDispatchEx *This, /* [in] */ DWORD grfdex, /* [in] */ DISPID id, /* [out] */ DISPID *pid){ ulong next = id+1; FETCH_DISP("GetNextDispID"); while(!zend_hash_index_exists(disp->dispid_to_name, next)) next++; if (zend_hash_index_exists(disp->dispid_to_name, next)) { *pid = next; return S_OK; } return S_FALSE;}static HRESULT STDMETHODCALLTYPE disp_getnamespaceparent( IDispatchEx *This, /* [out] */ IUnknown **ppunk){ FETCH_DISP("GetNameSpaceParent"); *ppunk = NULL; return E_NOTIMPL;} static struct IDispatchExVtbl php_dispatch_vtbl = { disp_queryinterface, disp_addref, disp_release, disp_gettypeinfocount, disp_gettypeinfo, disp_getidsofnames, disp_invoke, disp_getdispid, disp_invokeex, disp_deletememberbyname, disp_deletememberbydispid, disp_getmemberproperties, disp_getmembername, disp_getnextdispid, disp_getnamespaceparent};/* enumerate functions and properties of the object and assign * dispatch ids */static void generate_dispids(php_dispatchex *disp TSRMLS_DC){ HashPosition pos; char *name = NULL; zval *tmp; int namelen; int keytype; ulong pid; if (disp->dispid_to_name == NULL) { ALLOC_HASHTABLE(disp->dispid_to_name); ALLOC_HASHTABLE(disp->name_to_dispid); zend_hash_init(disp->name_to_dispid, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(disp->dispid_to_name, 0, NULL, ZVAL_PTR_DTOR, 0); } /* properties */ zend_hash_internal_pointer_reset_ex(Z_OBJPROP_PP(&disp->object), &pos); while (HASH_KEY_NON_EXISTANT != (keytype = zend_hash_get_current_key_ex(Z_OBJPROP_PP(&disp->object), &name, &namelen, &pid, 0, &pos))) { char namebuf[32]; if (keytype == HASH_KEY_IS_LONG) { sprintf(namebuf, "%d", pid); name = namebuf; namelen = strlen(namebuf); } zend_hash_move_forward_ex(Z_OBJPROP_PP(&disp->object), &pos); /* Find the existing id */ if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) continue; /* add the mappings */ MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, name, namelen, 1); zend_hash_index_update(disp->dispid_to_name, pid, (void*)&tmp, sizeof(zval *), NULL); MAKE_STD_ZVAL(tmp); ZVAL_LONG(tmp, pid); zend_hash_update(disp->name_to_dispid, name, namelen+1, (void*)&tmp, sizeof(zval *), NULL); } /* functions */ zend_hash_internal_pointer_reset_ex(&Z_OBJCE_PP(&disp->object)->function_table, &pos); while (HASH_KEY_NON_EXISTANT != (keytype = zend_hash_get_current_key_ex(&Z_OBJCE_PP(&disp->object)->function_table, &name, &namelen, &pid, 0, &pos))) { char namebuf[32]; if (keytype == HASH_KEY_IS_LONG) { sprintf(namebuf, "%d", pid); name = namebuf; namelen = strlen(namebuf); } zend_hash_move_forward_ex(Z_OBJPROP_PP(&disp->object), &pos); /* Find the existing id */ if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) continue; /* add the mappings */ MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, name, namelen, 1); zend_hash_index_update(disp->dispid_to_name, pid, (void*)&tmp, sizeof(zval *), NULL); MAKE_STD_ZVAL(tmp); ZVAL_LONG(tmp, pid); zend_hash_update(disp->name_to_dispid, name, namelen+1, (void*)&tmp, sizeof(zval *), NULL); }}static php_dispatchex *disp_constructor(zval *object TSRMLS_DC){ php_dispatchex *disp = (php_dispatchex*)CoTaskMemAlloc(sizeof(php_dispatchex)); trace("constructing a COM proxy\n"); if (disp == NULL) return NULL; memset(disp, 0, sizeof(php_dispatchex)); disp->engine_thread = tsrm_thread_id(); disp->lpVtbl = &php_dispatch_vtbl; disp->refcount = 1; if (object) ZVAL_ADDREF(object); disp->object = object; disp->id = zend_list_insert(disp, le_dispatch); return disp;}static void disp_destructor(php_dispatchex *disp){ TSRMLS_FETCH(); trace("destroying COM wrapper for PHP object %s\n", Z_OBJCE_P(disp->object)->name); disp->id = 0; if (disp->refcount > 0) CoDisconnectObject((IUnknown*)disp, 0); zend_hash_destroy(disp->dispid_to_name); zend_hash_destroy(disp->name_to_dispid); FREE_HASHTABLE(disp->dispid_to_name); FREE_HASHTABLE(disp->name_to_dispid); if (disp->object) zval_ptr_dtor(&disp->object); CoTaskMemFree(disp);}PHPAPI IDispatch *php_COM_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name TSRMLS_DC){ php_dispatchex *disp = disp_constructor(val TSRMLS_CC); HashPosition pos; char *name = NULL; zval *tmp, **ntmp; int namelen; int keytype; ulong pid; disp->dispid_to_name = id_to_name; memcpy(&disp->sinkid, sinkid, sizeof(disp->sinkid)); /* build up the reverse mapping */ ALLOC_HASHTABLE(disp->name_to_dispid); zend_hash_init(disp->name_to_dispid, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_internal_pointer_reset_ex(id_to_name, &pos); while (HASH_KEY_NON_EXISTANT != (keytype = zend_hash_get_current_key_ex(id_to_name, &name, &namelen, &pid, 0, &pos))) { if (keytype == HASH_KEY_IS_LONG) { zend_hash_get_current_data_ex(id_to_name, (void**)&ntmp, &pos); MAKE_STD_ZVAL(tmp); ZVAL_LONG(tmp, pid); zend_hash_update(disp->name_to_dispid, Z_STRVAL_PP(ntmp), Z_STRLEN_PP(ntmp)+1, (void*)&tmp, sizeof(zval *), NULL); } zend_hash_move_forward_ex(id_to_name, &pos); } return (IDispatch*)disp;}PHPAPI IDispatch *php_COM_export_object(zval *val TSRMLS_DC){ php_dispatchex *disp = NULL; if (Z_TYPE_P(val) != IS_OBJECT) return NULL; if (Z_OBJCE_P(val) == &COM_class_entry || !strcmp(Z_OBJCE_P(val)->name, "COM")) { /* pass back it's IDispatch directly */ zval **tmp; comval *obj; int type; zend_hash_index_find(Z_OBJPROP_P(val), 0, (void**)&tmp); obj = (comval *)zend_list_find(Z_LVAL_PP(tmp), &type); if (type != IS_COM) return NULL; C_DISPATCH(obj)->lpVtbl->AddRef(C_DISPATCH(obj)); return C_DISPATCH(obj); } disp = disp_constructor(val TSRMLS_CC); generate_dispids(disp TSRMLS_CC); return (IDispatch*)disp;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -