📄 com.c
字号:
ALLOC_COM(obj_prop); ALLOC_VARIANT(var_result); for (element=property_reference->elements_list->head; element != property_reference->elements_list->tail; element=element->next) { overloaded_property = (zend_overloaded_element *) element->data; switch (Z_TYPE_P(overloaded_property)) { case OE_IS_ARRAY: if (do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); FREE_COM(obj_prop); return FAILURE; } break; case OE_IS_OBJECT: if (do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); FREE_COM(obj_prop); return FAILURE; } break; case OE_IS_METHOD: /* this shouldn't happen */ return FAILURE; break; } if (V_VT(var_result) == VT_DISPATCH) { if (V_DISPATCH(var_result) == NULL) { FREE_VARIANT(var_result); FREE_COM(obj_prop); return FAILURE; } obj = obj_prop; php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC); } else { FREE_COM(obj_prop); FREE_VARIANT(var_result); return FAILURE; } VariantInit(var_result); /* to protect C_DISPATCH(obj) from being freed when var_result is destructed */ zval_dtor(&overloaded_property->element); } FREE_VARIANT(var_result); overloaded_property = (zend_overloaded_element *) element->data; do_COM_propput(NULL, obj, &overloaded_property->element, value TSRMLS_CC); FREE_COM(obj_prop); zval_dtor(&overloaded_property->element); return SUCCESS;}/* create an overloaded COM object from a dispatch pointer */PHPAPI zval *php_COM_object_from_dispatch(IDispatch *disp, zval *val TSRMLS_DC){ comval *obj; zval *zobj; ALLOC_COM(obj); MAKE_STD_ZVAL(zobj); php_COM_set(obj, &disp, FALSE TSRMLS_CC); ZVAL_COM_EX(zobj, obj, val); return zobj;}PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference){ pval property, **handle; pval *object = property_reference->object; zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data; comval *obj; int type; if (zend_llist_count(property_reference->elements_list)==1 && !strcmp(Z_STRVAL(function_name->element), "com")) { zval *tmp; /* constructor */ PHP_FN(com_load)(INTERNAL_FUNCTION_PARAM_PASSTHRU); zend_hash_index_find(Z_OBJPROP_P(return_value), 0, (void**)&handle); zend_list_addref(Z_RESVAL_PP(handle)); MAKE_STD_ZVAL(tmp); ZVAL_RESOURCE(tmp, Z_RESVAL_PP(handle)); zend_hash_index_update(Z_OBJPROP_P(object), 0, &tmp, sizeof(tmp), NULL); zval_dtor(&function_name->element); return; } RETVAL_NULL(); property = php_COM_get_property_handler(property_reference); if (Z_TYPE(property) != IS_OBJECT) { zval_dtor(&property); zval_dtor(&function_name->element); /* error message - function call on a non-object */ return; } zend_hash_index_find(Z_OBJPROP(property), 0, (void **) &handle); obj = (comval *)zend_list_find(Z_LVAL_PP(handle), &type); if (!obj || (type != IS_COM)) { zval_dtor(&property); zval_dtor(&function_name->element); return; } if (zend_llist_count(property_reference->elements_list)==1 && !strcmp(Z_STRVAL_P(&function_name->element), "release")) { RETVAL_LONG(php_COM_release(obj TSRMLS_CC)); } else if (zend_llist_count(property_reference->elements_list)==1 && !strcmp(Z_STRVAL_P(&function_name->element), "addref")) { RETVAL_LONG(php_COM_addref(obj TSRMLS_CC)); } else { pval **arguments; VARIANT *var_result; int arg_count = ZEND_NUM_ARGS(); ALLOC_VARIANT(var_result); arguments = (zval **) emalloc(sizeof(zval *)*arg_count); zend_get_parameters_array(ht, arg_count, arguments); if (do_COM_invoke(obj , DISPATCH_METHOD|DISPATCH_PROPERTYGET, &function_name->element, var_result, arguments, arg_count TSRMLS_CC) == SUCCESS) { RETVAL_VARIANT(var_result); } else { FREE_VARIANT(var_result); } efree(arguments); } zval_dtor(&property); zval_dtor(&function_name->element);}static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC){ ITypeLib *TypeLib = NULL; char *strtok_buf, *major, *minor; CLSID clsid; OLECHAR *p; /* Type Libraries: * The string we have is either: * a) a file name * b) a CLSID, major, minor e.g. "{00000200-0000-0010-8000-00AA006D2EA4},2,0" * c) a Type Library name e.g. "Microsoft OLE DB ActiveX Data Objects 1.0 Library" * Searching for the name will be more expensive that the * other two, so we will do that when both other attempts * fail. */ search_string = php_strtok_r(search_string, ",", &strtok_buf); if (search_string == NULL) return NULL; major = php_strtok_r(NULL, ",", &strtok_buf); minor = php_strtok_r(NULL, ",", &strtok_buf); p = php_char_to_OLECHAR(search_string, strlen(search_string), codepage TSRMLS_CC); /* Is the string a GUID ? */ if (!FAILED(CLSIDFromString(p, &clsid))) { HRESULT hr; WORD major_i = 1; WORD minor_i = 0; /* We have a valid GUID, check to see if a major/minor */ /* version was specified otherwise assume 1,0 */ if ((major != NULL) && (minor != NULL)) { major_i = (WORD) atoi(major); minor_i = (WORD) atoi(minor); } /* The GUID will either be a typelibrary or a CLSID */ hr = LoadRegTypeLib((REFGUID) &clsid, major_i, minor_i, LANG_NEUTRAL, &TypeLib); /* If the LoadRegTypeLib fails, let's try to instantiate */ /* the class itself and then QI for the TypeInfo and */ /* retrieve the type info from that interface */ if (FAILED(hr) && (!major || !minor)) { IDispatch *Dispatch; ITypeInfo *TypeInfo; int idx; if (FAILED(CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID *) &Dispatch))) { efree(p); return NULL; } if (FAILED(Dispatch->lpVtbl->GetTypeInfo(Dispatch, 0, LANG_NEUTRAL, &TypeInfo))) { Dispatch->lpVtbl->Release(Dispatch); efree(p); return NULL; } Dispatch->lpVtbl->Release(Dispatch); if (FAILED(TypeInfo->lpVtbl->GetContainingTypeLib(TypeInfo, &TypeLib, &idx))) { TypeInfo->lpVtbl->Release(TypeInfo); efree(p); return NULL; } TypeInfo->lpVtbl->Release(TypeInfo); } } else { if (FAILED(LoadTypeLib(p, &TypeLib))) { /* Walk HKCR/TypeLib looking for the string */ /* If that succeeds, call ourself recursively */ /* using the CLSID found, else give up and bail */ HKEY hkey, hsubkey; DWORD SubKeys, MaxSubKeyLength; char *keyname; register unsigned int ii, jj; DWORD VersionCount; char version[20]; /* All the version keys are 1.0, 4.6, ... */ char *libname; DWORD libnamelen; /* No Need for Unicode version any more */ efree(p); /* Starting at HKEY_CLASSES_ROOT/TypeLib */ /* Walk all subkeys (Typelib GUIDs) looking */ /* at each version for a string match to the */ /* supplied argument */ if (ERROR_SUCCESS != RegOpenKey(HKEY_CLASSES_ROOT, "TypeLib",&hkey)) { /* This is pretty bad - better bail */ return NULL; } if (ERROR_SUCCESS != RegQueryInfoKey(hkey, NULL, NULL, NULL, &SubKeys, &MaxSubKeyLength, NULL, NULL, NULL, NULL, NULL, NULL)) { RegCloseKey(hkey); return NULL; } MaxSubKeyLength++; /* \0 is not counted */ keyname = emalloc(MaxSubKeyLength); libname = emalloc(strlen(search_string)+1); for (ii=0;ii<SubKeys;ii++) { if (ERROR_SUCCESS != RegEnumKey(hkey, ii, keyname, MaxSubKeyLength)) { /* Failed - who cares */ continue; } if (ERROR_SUCCESS != RegOpenKey(hkey, keyname, &hsubkey)) { /* Failed - who cares */ continue; } if (ERROR_SUCCESS != RegQueryInfoKey(hsubkey, NULL, NULL, NULL, &VersionCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { /* Failed - who cares */ RegCloseKey(hsubkey); continue; } for (jj=0;jj<VersionCount;jj++) { if (ERROR_SUCCESS != RegEnumKey(hsubkey, jj, version, sizeof(version))) { /* Failed - who cares */ continue; } /* OK we just need to retrieve the default */ /* value for this key and see if it matches */ libnamelen = strlen(search_string)+1; if (ERROR_SUCCESS == RegQueryValue(hsubkey, version, libname, &libnamelen)) { if ((mode & CONST_CS) ? (strcmp(libname, search_string) == 0) : (stricmp(libname, search_string) == 0)) { char *str; int major, minor; /* Found it */ RegCloseKey(hkey); RegCloseKey(hsubkey); efree(libname); /* We can either open up the "win32" key and find the DLL name */ /* Or just parse the version string and pass that in */ /* The version string seems like a more portable solution */ /* Given that there is a COM on Unix */ if (2 != sscanf(version, "%d.%d", &major, &minor)) { major = 1; minor = 0; } str = emalloc(strlen(keyname)+strlen(version)+20); /* 18 == safety, 2 == extra comma and \0 */ sprintf(str, "%s,%d,%d", keyname, major, minor); efree(keyname); TypeLib = php_COM_find_typelib(str, mode TSRMLS_CC); efree(str); /* This is probbaly much harder to read and follow */ /* But it is MUCH more effiecient than trying to */ /* test for errors and leave through a single "return" */ return TypeLib; } } else { /* Failed - perhaps too small abuffer */ /* But if too small, then the name does not match */ } } RegCloseKey(hsubkey); } efree(keyname); efree(libname); return NULL; } } efree(p); return TypeLib;}PHPAPI int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC){ int i; int interfaces; if (NULL == TypeLib) { return FAILURE; } interfaces = ITypeLib_GetTypeInfoCount(TypeLib); for (i=0; i<interfaces; i++) { TYPEKIND pTKind; ITypeLib_GetTypeInfoType(TypeLib, i, &pTKind); if (pTKind == TKIND_ENUM) { ITypeInfo *TypeInfo; VARDESC *pVarDesc; UINT NameCount; int j; ITypeLib_GetTypeInfo(TypeLib, i, &TypeInfo); for (j = 0; ; j++) { BSTR bstr_ids; zend_constant c; zval exists, results, value; char *const_name; if (FAILED(ITypeInfo_GetVarDesc(TypeInfo, j, &pVarDesc))) { break; } ITypeInfo_GetNames(TypeInfo, pVarDesc->memid, &bstr_ids, 1, &NameCount); if (NameCount != 1) { ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); continue; } const_name = php_OLECHAR_to_char(bstr_ids, &c.name_len, codepage TSRMLS_CC); c.name = zend_strndup(const_name, c.name_len); efree(const_name); c.name_len++; /* length should include the NULL */ SysFreeString(bstr_ids); /* Before registering the contsnt, let's see if we can find it */ if (zend_get_constant(c.name, c.name_len - 1, &exists TSRMLS_CC)) { /* Oops, it already exists. No problem if it is defined as the same value */ /* Check to see if they are the same */ if (!compare_function(&results, &c.value, &exists TSRMLS_CC) && INI_INT("com.autoregister_verbose")) { php_error(E_WARNING, "%s(): Type library value %s is already defined and has a different value", get_active_function_name(TSRMLS_C), c.name); } free(c.name); ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); continue; } php_variant_to_pval(pVarDesc->lpvarValue, &value, codepage TSRMLS_CC); /* we only import enumerations (=int) */ if (Z_TYPE(value) == IS_LONG) { c.flags = mode; c.value.type = IS_LONG; c.value.value.lval = Z_LVAL(value); c.module_number = 0; /* the module number is not available here */ zend_register_constant(&c TSRMLS_CC); } ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); } ITypeInfo_Release(TypeInfo); } } return SUCCESS;}/* {{{ proto bool com_isenum(object com_module) Grabs an IEnumVariant */PHP_FUNCTION(com_isenum){ pval *object; comval *obj; if (ZEND_NUM_ARGS() != 1) { ZEND_WRONG_PARAM_COUNT(); } zend_get_parameters(ht, 1, &object); /* obtain IDispatch interface */ FETCH_COM_SAFE(object, obj); RETURN_BOOL(C_HASENUM(obj));}/* }}} */static void php_register_COM_class(TSRMLS_D){ INIT_OVERLOADED_CLASS_ENTRY(COM_class_entry, "COM", NULL, php_COM_call_function_handler, php_COM_get_property_handler, php_COM_set_property_handler); zend_register_internal_class(&COM_class_entry TSRMLS_CC);}static void php_COM_init(int module_number TSRMLS_DC){ le_comval = zend_register_list_destructors_ex(php_comval_destructor, NULL, "COM", module_number); php_register_COM_class(TSRMLS_C);}PHPAPI ZEND_DECLARE_MODULE_GLOBALS(com)static void php_com_init_globals(zend_com_globals *com_globals){}PHP_MINIT_FUNCTION(COM){ ZEND_INIT_MODULE_GLOBALS(com, php_com_init_globals, NULL); php_COM_init(module_number TSRMLS_CC); php_VARIANT_init(module_number TSRMLS_CC); php_COM_dispatch_init(module_number TSRMLS_CC); REGISTER_LONG_CONSTANT("CLSCTX_INPROC_SERVER", CLSCTX_INPROC_SERVER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CLSCTX_INPROC_HANDLER", CLSCTX_INPROC_HANDLER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CLSCTX_LOCAL_SERVER", CLSCTX_LOCAL_SERVER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CLSCTX_REMOTE_SERVER", CLSCTX_REMOTE_SERVER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CLSCTX_SERVER", CLSCTX_SERVER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CLSCTX_ALL", CLSCTX_ALL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DISPATCH_METHOD", DISPATCH_METHOD, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DISPATCH_PROPERTYGET", DISPATCH_PROPERTYGET, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DISPATCH_PROPERTYPUT", DISPATCH_PROPERTYPUT, CONST_CS | CONST_PERSISTENT); REGISTER_INI_ENTRIES(); return SUCCESS;}PHP_MSHUTDOWN_FUNCTION(COM){ UNREGISTER_INI_ENTRIES(); return SUCCESS;}/* exports for external object creation */zend_module_entry COM_module_entry = { STANDARD_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -