📄 com.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Zeev Suraski <zeev@zend.com> | | Harald Radi <h.radi@nme.at> | | Alan Brown <abrown@pobox.com> | | Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ *//* $Id: COM.c,v 1.90.2.11.2.2 2007/01/01 09:46:40 sebastian Exp $ *//* * This module implements support for COM components that support the IDispatch * interface. Both local (COM) and remote (DCOM) components can be accessed. * * Type libraries can be loaded (in order for PHP to recognize automation constants) * by specifying a typelib_file in the PHP .ini file. That file should contain * paths to type libraries, one in every line. By default, constants are registered * as case-sensitive. If you want them to be defined as case-insensitive, add * #case_insensitive or #cis at the end of the type library path. * * This is also the first module to demonstrate Zend's OO syntax overloading * capabilities. CORBA coders are invited to write a CORBA module as well! * * Zeev *//* * 28.12.2000 * unicode conversion fixed by Harald Radi <h.radi@nme.at> * * now all these strange '?'s should be disapeared *//* * 28.1.2001 * VARIANT datatype and pass_by_reference support *//* * 03.6.2001 * Enhanced Typelib support to include a search by name */#ifdef PHP_WIN32#define _WIN32_DCOM#define COBJMACROS#include <iostream.h>#include <math.h>#include <ocidl.h>#include "php.h"#include "php_ini.h"#include "php_COM.h"#include "php_VARIANT.h"static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC);static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup TSRMLS_DC);static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup TSRMLS_DC);static void php_register_COM_class(TSRMLS_D);static void php_COM_init(int module_number TSRMLS_DC);static char *php_string_from_clsid(const CLSID *clsid TSRMLS_DC);static int com_enable_events(comval *obj, int enable);static int le_comval;static int codepage;#ifdef _DEBUGint resourcecounter = 1;#endifstatic unsigned char arg1and2_force_ref[] = { 2, BYREF_FORCE, BYREF_FORCE };function_entry COM_functions[] = { PHP_FE(com_load, NULL) PHP_FE(com_invoke, NULL) PHP_FE(com_invoke_ex, NULL) PHP_FE(com_addref, NULL) PHP_FE(com_release, NULL) PHP_FE(com_propget, NULL) PHP_FE(com_propput, NULL) PHP_FE(com_load_typelib, NULL) PHP_FE(com_isenum, NULL) PHP_FE(com_event_sink, arg1and2_force_ref) PHP_FE(com_message_pump, NULL) PHP_FE(com_print_typeinfo, NULL) PHP_FALIAS(com_get, com_propget, NULL) PHP_FALIAS(com_propset, com_propput, NULL) PHP_FALIAS(com_set, com_propput, NULL) { NULL, NULL, NULL }};static PHP_MINFO_FUNCTION(COM){ DISPLAY_INI_ENTRIES();}PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, char **ErrString TSRMLS_DC){ HRESULT hr; int failed = FALSE; unsigned int ArgErr; EXCEPINFO ExceptInfo; *ErrString = NULL; /* @todo use DispInvoke here ? */ if (C_ISREFD(obj)) { hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr); if (FAILED(hr)) { switch (hr) { case DISP_E_EXCEPTION: { char *src = NULL; int srclen = 0; char *desc = NULL; int desclen = 0; if (ExceptInfo.bstrSource) { src = php_OLECHAR_to_char(ExceptInfo.bstrSource, &srclen, codepage TSRMLS_CC); SysFreeString(ExceptInfo.bstrSource); } else { src = estrdup("Unavailable"); srclen = strlen(src); } if (ExceptInfo.bstrDescription) { desc = php_OLECHAR_to_char(ExceptInfo.bstrDescription, &desclen, codepage TSRMLS_CC); SysFreeString(ExceptInfo.bstrDescription); } else { desc = estrdup("Unavailable"); desclen = strlen(desc); } *ErrString = pemalloc(srclen+desclen+50, 1); sprintf(*ErrString, "<b>Source</b>: %s <b>Description</b>: %s", src, desc); efree(src); efree(desc); if (ExceptInfo.bstrHelpFile) { SysFreeString(ExceptInfo.bstrHelpFile); } } break; case DISP_E_PARAMNOTFOUND: case DISP_E_TYPEMISMATCH: *ErrString = pemalloc(25, 1); sprintf(*ErrString, "<b>Argument</b>: %d", pDispParams->cArgs-ArgErr+1); break; } } if (pVarResult && (V_VT(pVarResult) == VT_EMPTY)) { V_VT(pVarResult) = VT_I4; V_I4(pVarResult) = hr; } return hr; } else { return DISP_E_UNKNOWNINTERFACE; }}PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId TSRMLS_DC){ HRESULT hr; if (C_ISREFD(obj)) { if (C_HASTLIB(obj)) { hr = C_TYPEINFO_VT(obj)->GetIDsOfNames(C_TYPEINFO(obj), rgszNames, 1, rgDispId); if (FAILED(hr)) { hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId); if (SUCCEEDED(hr)) { /* * ITypLib doesn't work * Release ITypeLib and fall back to IDispatch */ C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj)); C_HASTLIB(obj) = FALSE; C_TYPEINFO(obj) = NULL; } } } else { hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId); } return hr; } else { return DISP_E_UNKNOWNINTERFACE; }}PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC){ HRESULT hr; if (obj->refcount > 1) { C_RELEASE(obj); } else if (obj->refcount == 1) { if (C_HASTLIB(obj)) { C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj)); C_TYPEINFO(obj) = NULL; C_HASTLIB(obj) = FALSE; } if (C_HASENUM(obj)) { hr = C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj)); C_ENUMVARIANT(obj) = NULL; C_HASENUM(obj) = FALSE; } hr = C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj)); C_RELEASE(obj); C_DISPATCH(obj) = NULL; } return obj->refcount;}PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC){ if (C_ISREFD(obj)) { C_ADDREF(obj); } return obj->refcount;}PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup TSRMLS_DC){ HRESULT hr = 1; DISPPARAMS dispparams; VARIANT *var_result; IDispatch FAR* pDisp; pDisp = *ppDisp; if (cleanup) { *ppDisp = NULL; } C_REFCOUNT(obj) = 1; C_DISPATCH(obj) = pDisp; C_HASTLIB(obj) = SUCCEEDED(C_DISPATCH_VT(obj)->GetTypeInfo(C_DISPATCH(obj), 0, LANG_NEUTRAL, &C_TYPEINFO(obj))); dispparams.rgvarg = NULL; dispparams.rgdispidNamedArgs = NULL; dispparams.cArgs = 0; dispparams.cNamedArgs = 0; ALLOC_VARIANT(var_result); if (C_HASENUM(obj) = SUCCEEDED(C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), DISPID_NEWENUM, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result, NULL, NULL))) { if (V_VT(var_result) == VT_UNKNOWN) { C_HASENUM(obj) = SUCCEEDED(V_UNKNOWN(var_result)->lpVtbl->QueryInterface(V_UNKNOWN(var_result), &IID_IEnumVARIANT, (void**)&C_ENUMVARIANT(obj))); } else if (V_VT(var_result) == VT_DISPATCH) { C_HASENUM(obj) = SUCCEEDED(V_DISPATCH(var_result)->lpVtbl->QueryInterface(V_DISPATCH(var_result), &IID_IEnumVARIANT, (void**)&C_ENUMVARIANT(obj))); } } FREE_VARIANT(var_result); if (!cleanup) { hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj)); }#ifdef _DEBUG obj->resourceindex = resourcecounter++;#endif return hr;}PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup TSRMLS_DC){ HRESULT hr; C_HASTLIB(obj) = C_HASTLIB(clone); C_HASENUM(obj) = C_HASENUM(obj); C_DISPATCH(obj) = C_DISPATCH(clone); C_TYPEINFO(obj) = C_TYPEINFO(clone); if (cleanup || !C_ISREFD(obj)) { obj->refcount = clone->refcount; clone->refcount = 0; } else { if (C_HASTLIB(obj)) { C_TYPEINFO_VT(obj)->AddRef(C_TYPEINFO(obj)); } if (C_HASENUM(obj)) { C_ENUMVARIANT_VT(obj)->AddRef(C_ENUMVARIANT(obj)); } hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj)); obj->refcount = 1; }#ifdef _DEBUG obj->resourceindex = resourcecounter++;#endif return hr;}PHPAPI char *php_COM_error_message(HRESULT hr TSRMLS_DC){ void *pMsgBuf; if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pMsgBuf, 0, NULL)) { char error_string[] = "No description available"; pMsgBuf = LocalAlloc(LMEM_FIXED, sizeof(error_string)); memcpy(pMsgBuf, error_string, sizeof(error_string)); } return pMsgBuf;}static char *php_string_from_clsid(const CLSID *clsid TSRMLS_DC){ LPOLESTR ole_clsid; char *clsid_str; StringFromCLSID(clsid, &ole_clsid); clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, codepage TSRMLS_CC); LocalFree(ole_clsid); return clsid_str;}PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC){ HRESULT hr = S_OK; com_enable_events(obj, FALSE); if (obj->sinkdispatch) obj->sinkdispatch->lpVtbl->Release(obj->sinkdispatch); if (C_ISREFD(obj)) { C_REFCOUNT(obj) = 1; hr = php_COM_release(obj TSRMLS_CC); } efree(obj); return hr;}static void php_comval_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC){ php_COM_destruct(rsrc->ptr TSRMLS_CC);}static PHP_INI_MH(OnTypelibFileChange){ FILE *typelib_file; char *typelib_name_buffer; char *strtok_buf = NULL; int interactive; interactive = CG(interactive); if (!new_value || (typelib_file = VCWD_FOPEN(new_value, "r"))==NULL) { return FAILURE; } if (interactive) { printf("Loading type libraries..."); fflush(stdout); } typelib_name_buffer = (char *) emalloc(sizeof(char)*1024); while (fgets(typelib_name_buffer, 1024, typelib_file)) { ITypeLib *pTL; char *typelib_name; char *modifier, *ptr; int mode = CONST_CS | CONST_PERSISTENT; /* CONST_PERSISTENT is ok here */ if (typelib_name_buffer[0]==';') { continue; } typelib_name = php_strtok_r(typelib_name_buffer, "\r\n", &strtok_buf); /* get rid of newlines */ if (typelib_name == NULL) { continue; } typelib_name = php_strtok_r(typelib_name, "#", &strtok_buf); modifier = php_strtok_r(NULL, "#", &strtok_buf); if (modifier != NULL) { if (!strcmp(modifier, "cis") || !strcmp(modifier, "case_insensitive")) { mode &= ~CONST_CS; } } /* Remove leading/training white spaces on search_string */ while (isspace(*typelib_name)) {/* Ends on '\0' in worst case */ typelib_name ++; } ptr = typelib_name + strlen(typelib_name) - 1; while ((ptr != typelib_name) && isspace(*ptr)) { *ptr = '\0'; ptr--; } if (interactive) { printf("\rLoading %-60s\r", typelib_name); } if ((pTL = php_COM_find_typelib(typelib_name, mode TSRMLS_CC)) != NULL) { php_COM_load_typelib(pTL, mode TSRMLS_CC); pTL->lpVtbl->Release(pTL); } } efree(typelib_name_buffer); fclose(typelib_file); if (interactive) { printf("\r%70s\r", ""); } return SUCCESS;}PHP_INI_BEGIN()PHP_INI_ENTRY_EX("com.allow_dcom", "0", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb)PHP_INI_ENTRY_EX("com.autoregister_typelib", "0", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb)PHP_INI_ENTRY_EX("com.autoregister_verbose", "0", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb)PHP_INI_ENTRY_EX("com.autoregister_casesensitive", "1", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb)PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypelibFileChange)PHP_INI_END()/* {{{ proto int com_load(string module_name [, string remote_host [, int codepage [, string typelib]]]) Loads a COM module */PHP_FUNCTION(com_load){ pval *module_name, *code_page, *typelib = NULL, *server_name = NULL, *user_name=NULL, *password=NULL, *domain=NULL; CLSID clsid; HRESULT hr; OLECHAR *ProgID; comval *obj; char *error_message;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -