📄 com.c
字号:
RETVAL_VARIANT(var_result); efree(arguments);}/* }}} *//* {{{ proto mixed com_invoke(int module, string handler_name [, mixed arg [, mixed ...]]) Invokes a COM module */PHP_FUNCTION(com_invoke){ pval **arguments; pval *object, *function_name; comval *obj; int arg_count = ZEND_NUM_ARGS(); VARIANT *var_result; if (arg_count<2) { ZEND_WRONG_PARAM_COUNT(); } arguments = (pval **) emalloc(sizeof(pval *)*arg_count); if (zend_get_parameters_array(ht, arg_count, arguments) == FAILURE) { RETURN_NULL(); } object = arguments[0]; function_name = arguments[1]; /* obtain IDispatch interface */ FETCH_COM_SAFE(object, obj); /* obtain property/method handler */ convert_to_string_ex(&function_name); ALLOC_VARIANT(var_result); if (do_COM_invoke(obj, DISPATCH_METHOD|DISPATCH_PROPERTYGET, function_name, var_result, arguments+2, arg_count-2 TSRMLS_CC)==FAILURE) { FREE_VARIANT(var_result); efree(arguments); RETURN_NULL(); } RETVAL_VARIANT(var_result); efree(arguments);}/* }}} *//* {{{ proto mixed com_release(int module) Releases a COM object */PHP_FUNCTION(com_release){ pval *object; comval *obj; int arg_count = ZEND_NUM_ARGS(); if (arg_count != 1) { ZEND_WRONG_PARAM_COUNT(); } if (zend_get_parameters(ht, 1, &object)==FAILURE) { RETURN_FALSE; } /* obtain IDispatch interface */ FETCH_COM_SAFE(object, obj); RETURN_LONG(php_COM_release(obj TSRMLS_CC))}/* }}} *//* {{{ proto mixed com_addref(int module) Increases the reference counter on a COM object */PHP_FUNCTION(com_addref){ pval *object; comval *obj; int arg_count = ZEND_NUM_ARGS(); if (arg_count != 1) { ZEND_WRONG_PARAM_COUNT(); } if (zend_get_parameters(ht, 1, &object)==FAILURE) { RETURN_FALSE; } /* obtain IDispatch interface */ FETCH_COM_SAFE(object, obj); RETURN_LONG(php_COM_addref(obj TSRMLS_CC));}/* }}} *//* {{{ proto bool com_message_pump([int timeoutms]) Process COM messages, sleeping for up to timeoutms milliseconds */PHP_FUNCTION(com_message_pump){ long timeoutms = 0; MSG msg; DWORD result; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &timeoutms) == FAILURE) RETURN_FALSE; result = MsgWaitForMultipleObjects(0, NULL, FALSE, timeoutms, QS_ALLINPUT); if (result == WAIT_OBJECT_0) { while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } /* we processed messages */ RETVAL_TRUE; } else { /* we did not process messages (timed out) */ RETVAL_FALSE; }}/* }}} */static int com_enable_events(comval *obj, int enable){ if (obj->sinkdispatch) { IConnectionPointContainer *cont; IConnectionPoint *point; if (SUCCEEDED(C_DISPATCH_VT(obj)->QueryInterface(C_DISPATCH(obj), &IID_IConnectionPointContainer, (void**)&cont))) { if (SUCCEEDED(cont->lpVtbl->FindConnectionPoint(cont, &obj->sinkid, &point))) { if (enable) { point->lpVtbl->Advise(point, (IUnknown*)obj->sinkdispatch, &obj->sinkcookie); } else { point->lpVtbl->Unadvise(point, obj->sinkcookie); } point->lpVtbl->Release(point); } cont->lpVtbl->Release(cont); } } return 0;}static const struct { VARTYPE vt; const char *name;} vt_names[] = { { VT_NULL, "VT_NULL" }, { VT_EMPTY, "VT_EMPTY" }, { VT_UI1, "VT_UI1" }, { VT_I2, "VT_I2" }, { VT_I4, "VT_I4" }, { VT_R4, "VT_R4" }, { VT_R8, "VT_R8" }, { VT_BOOL, "VT_BOOL" }, { VT_ERROR, "VT_ERROR" }, { VT_CY, "VT_CY" }, { VT_DATE, "VT_DATE" }, { VT_BSTR, "VT_BSTR" }, { VT_DECIMAL, "VT_DECIMAL" }, { VT_UNKNOWN, "VT_UNKNOWN" }, { VT_DISPATCH, "VT_DISPATCH" }, { VT_VARIANT, "VT_VARIANT" }, { VT_I1, "VT_I1" }, { VT_UI2, "VT_UI2" }, { VT_UI4, "VT_UI4" }, { VT_INT, "VT_INT" }, { VT_UINT, "VT_UINT" }, { VT_ARRAY, "VT_ARRAY" }, { VT_BYREF, "VT_BYREF" }, { VT_VOID, "VT_VOID" }, { VT_PTR, "VT_PTR" }, { VT_HRESULT, "VT_HRESULT" }, { 0, NULL }};static inline const char *vt_to_string(VARTYPE vt){ int i; for (i = 0; vt_names[i].name != NULL; i++) { if (vt_names[i].vt == vt) return vt_names[i].name; } return "?";}static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int printdef, GUID *guid TSRMLS_DC){ TYPEATTR *attr; FUNCDESC *func; int i; OLECHAR *olename; char *ansiname = NULL; unsigned int ansinamelen; int ret = 0; if (FAILED(typeinfo->lpVtbl->GetTypeAttr(typeinfo, &attr))) return 0; /* verify that it is suitable */ if (id_to_name == NULL || attr->typekind == TKIND_DISPATCH) { if (guid) memcpy(guid, &attr->guid, sizeof(GUID)); if (printdef) { char *guidstring; typeinfo->lpVtbl->GetDocumentation(typeinfo, MEMBERID_NIL, &olename, NULL, NULL, NULL); ansiname = php_OLECHAR_to_char(olename, &ansinamelen, codepage TSRMLS_CC); SysFreeString(olename); guidstring = php_string_from_clsid(&attr->guid TSRMLS_CC); php_printf("class %s { /* GUID=%s */\n", ansiname, guidstring); efree(guidstring); efree(ansiname); } if (id_to_name) zend_hash_init(id_to_name, 0, NULL, ZVAL_PTR_DTOR, 0); /* So we've got the dispatch interface; lets list the event methods */ for (i = 0; i < attr->cFuncs; i++) { zval *tmp; DISPID lastid = 0; /* for props */ int isprop; if (FAILED(typeinfo->lpVtbl->GetFuncDesc(typeinfo, i, &func))) break; isprop = (func->invkind & DISPATCH_PROPERTYGET || func->invkind & DISPATCH_PROPERTYPUT); if (!isprop || lastid != func->memid) { lastid = func->memid; typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, &olename, NULL, NULL, NULL); ansiname = php_OLECHAR_to_char(olename, &ansinamelen, codepage TSRMLS_CC); SysFreeString(olename); if (printdef) { int j; char *funcdesc; unsigned int funcdesclen, cnames = 0; BSTR *names; names = (BSTR*)emalloc((func->cParams + 1) * sizeof(BSTR)); typeinfo->lpVtbl->GetNames(typeinfo, func->memid, names, func->cParams + 1, &cnames); /* first element is the function name */ SysFreeString(names[0]); php_printf("\t/* DISPID=%d */\n", func->memid); if (func->elemdescFunc.tdesc.vt != VT_VOID) { php_printf("\t/* %s [%d] */\n", vt_to_string(func->elemdescFunc.tdesc.vt), func->elemdescFunc.tdesc.vt ); } if (isprop) { typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL); if (olename) { funcdesc = php_OLECHAR_to_char(olename, &funcdesclen, codepage TSRMLS_CC); SysFreeString(olename); php_printf("\t/* %s */\n", funcdesc); efree(funcdesc); } php_printf("\tvar $%s;\n\n", ansiname); } else { /* a function */ php_printf("\tfunction %s(\n", ansiname); for (j = 0; j < func->cParams; j++) { ELEMDESC *elem = &func->lprgelemdescParam[j]; php_printf("\t\t/* %s [%d] ", vt_to_string(elem->tdesc.vt), elem->tdesc.vt); if (elem->paramdesc.wParamFlags & PARAMFLAG_FIN) php_printf("[in]"); if (elem->paramdesc.wParamFlags & PARAMFLAG_FOUT) php_printf("[out]"); if (elem->tdesc.vt == VT_PTR) { /* what does it point to ? */ php_printf(" --> %s [%d] ", vt_to_string(elem->tdesc.lptdesc->vt), elem->tdesc.lptdesc->vt ); } /* when we handle prop put and get, this will look nicer */ if (j+1 < (int)cnames) { funcdesc = php_OLECHAR_to_char(names[j+1], &funcdesclen, codepage TSRMLS_CC); SysFreeString(names[j+1]); } else { funcdesc = "???"; } php_printf(" */ %s%s%c\n", elem->tdesc.vt == VT_PTR ? "&$" : "$", funcdesc, j == func->cParams - 1 ? ' ' : ',' ); if (j+1 < (int)cnames) efree(funcdesc); } php_printf("\t\t)\n\t{\n"); typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL); if (olename) { funcdesc = php_OLECHAR_to_char(olename, &funcdesclen, codepage TSRMLS_CC); SysFreeString(olename); php_printf("\t\t/* %s */\n", funcdesc); efree(funcdesc); } php_printf("\t}\n"); } efree(names); } if (id_to_name) { zend_str_tolower(ansiname, ansinamelen); MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, ansiname, ansinamelen, 0); zend_hash_index_update(id_to_name, func->memid, (void*)&tmp, sizeof(zval *), NULL); } } typeinfo->lpVtbl->ReleaseFuncDesc(typeinfo, func); } if (printdef) php_printf("}\n"); ret = 1; } else { zend_error(E_WARNING, "Thats not a dispatchable interface!! type kind = %08x", attr->typekind); } typeinfo->lpVtbl->ReleaseTypeAttr(typeinfo, attr); return ret;}static ITypeInfo *locate_typeinfo(char *typelibname, comval *obj, char *dispname, int sink TSRMLS_DC){ ITypeInfo *typeinfo = NULL; ITypeLib *typelib = NULL; int gotguid = 0; GUID iid; if (obj) { if (dispname == NULL && sink) { IProvideClassInfo2 *pci2; IProvideClassInfo *pci; if (SUCCEEDED(C_DISPATCH_VT(obj)->QueryInterface(C_DISPATCH(obj), &IID_IProvideClassInfo2, (void**)&pci2))) { gotguid = SUCCEEDED(pci2->lpVtbl->GetGUID(pci2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, &iid)); pci2->lpVtbl->Release(pci2); } if (!gotguid && SUCCEEDED(C_DISPATCH_VT(obj)->QueryInterface(C_DISPATCH(obj), &IID_IProvideClassInfo, (void**)&pci))) { /* examine the available interfaces */ /* TODO: write some code here */ pci->lpVtbl->Release(pci); } } else if (dispname && C_HASTLIB(obj)) { unsigned int idx; /* get the library from the object; the rest will be dealt with later */ C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &typelib, &idx); } else if (typelibname == NULL) { C_DISPATCH_VT(obj)->GetTypeInfo(C_DISPATCH(obj), 0, LANG_NEUTRAL, &typeinfo); } } else if (typelibname) { /* Fetch the typelibrary and use that to look things up */ typelib = php_COM_find_typelib(typelibname, CONST_CS TSRMLS_CC); } if (!gotguid && dispname && typelib) { unsigned short cfound; MEMBERID memid; OLECHAR *olename = php_char_to_OLECHAR(dispname, strlen(dispname), CP_ACP TSRMLS_CC); cfound = 1; if (FAILED(typelib->lpVtbl->FindName(typelib, olename, 0, &typeinfo, &memid, &cfound)) || cfound == 0) { CLSID coclass; ITypeInfo *coinfo; /* assume that it might be a progid instead */ if (SUCCEEDED(CLSIDFromProgID(olename, &coclass)) && SUCCEEDED(typelib->lpVtbl->GetTypeInfoOfGuid(typelib, &coclass, &coinfo))) { /* enumerate implemented interfaces and pick the one as indicated by sink */ TYPEATTR *attr; int i; coinfo->lpVtbl->GetTypeAttr(coinfo, &attr); for (i = 0; i < attr->cImplTypes; i++) { HREFTYPE rt; int tf; if (FAILED(coinfo->lpVtbl->GetImplTypeFlags(coinfo, i, &tf))) continue; if ((sink && tf == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) || (!sink && (tf & IMPLTYPEFLAG_FSOURCE) == 0)) { /* flags match what we are looking for */ if (SUCCEEDED(coinfo->lpVtbl->GetRefTypeOfImplType(coinfo, i, &rt))) if (SUCCEEDED(coinfo->lpVtbl->GetRefTypeInfo(coinfo, rt, &typeinfo))) break; } } coinfo->lpVtbl->ReleaseTypeAttr(coinfo, attr); coinfo->lpVtbl->Release(coinfo); } } efree(olename); } else if (gotguid) { typelib->lpVtbl->GetTypeInfoOfGuid(typelib, &iid, &typeinfo); } if (typelib) typelib->lpVtbl->Release(typelib); return typeinfo;}/* {{{ proto bool com_print_typeinfo(mixed comobject | string typelib, string dispinterface, bool wantsink) Print out a PHP class definition for a dispatchable interface */PHP_FUNCTION(com_print_typeinfo){ zval *arg1; char *ifacename = NULL; char *typelibname = NULL; int ifacelen; zend_bool wantsink = 0; comval *obj = NULL; ITypeInfo *typeinfo; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/s!b", &arg1, &ifacename, &ifacelen, &wantsink)) { RETURN_FALSE; } if (Z_TYPE_P(arg1) == IS_OBJECT) { FETCH_COM_SAFE(arg1, obj); } else { convert_to_string(arg1); typelibname = Z_STRVAL_P(arg1); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -