diff options
Diffstat (limited to 'ext/com/COM.c')
-rw-r--r-- | ext/com/COM.c | 171 |
1 files changed, 139 insertions, 32 deletions
diff --git a/ext/com/COM.c b/ext/com/COM.c index 93f296280d..6e5361a8f3 100644 --- a/ext/com/COM.c +++ b/ext/com/COM.c @@ -69,6 +69,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, 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 int le_comval; static int codepage; @@ -130,7 +131,7 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS } if (FAILED(hr)) { - switch (hr) { + switch (hr) { case DISP_E_EXCEPTION: { int srclen; char *src = php_OLECHAR_to_char(ExceptInfo.bstrSource, &srclen, codepage TSRMLS_CC); @@ -201,7 +202,7 @@ PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC) { HRESULT hr; - + if (obj->refcount > 1) { C_RELEASE(obj); } else if (obj->refcount == 1) { @@ -240,7 +241,7 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup 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))); @@ -253,13 +254,13 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup 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))) { + 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))); + 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))); + C_HASENUM(obj) = SUCCEEDED(V_DISPATCH(var_result)->lpVtbl->QueryInterface(V_DISPATCH(var_result), &IID_IEnumVARIANT, + (void**)&C_ENUMVARIANT(obj))); } } @@ -313,7 +314,7 @@ 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)) { + hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pMsgBuf, 0, NULL)) { char error_string[] = "No description available"; pMsgBuf = LocalAlloc(LMEM_FIXED, sizeof(error_string)); @@ -376,7 +377,7 @@ static PHP_INI_MH(OnTypelibFileChange) typelib_name_buffer = (char *) emalloc(sizeof(char)*1024); - while(fgets(typelib_name_buffer, 1024, typelib_file)) { + while (fgets(typelib_name_buffer, 1024, typelib_file)) { ITypeLib *pTL; char *typelib_name; char *modifier, *ptr; @@ -398,11 +399,11 @@ static PHP_INI_MH(OnTypelibFileChange) } /* Remove leading/training white spaces on search_string */ - while(isspace(*typelib_name)) {/* Ends on '\0' in worst case */ + 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)) { + while ((ptr != typelib_name) && isspace(*ptr)) { *ptr = '\0'; ptr--; } @@ -410,7 +411,7 @@ static PHP_INI_MH(OnTypelibFileChange) 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); @@ -441,7 +442,7 @@ PHP_INI_END() Loads a COM module */ PHP_FUNCTION(com_load) { - pval *module_name, *code_page, *typelib = NULL, *server_name = NULL; + pval *module_name, *code_page, *typelib = NULL, *server_name = NULL, *user_name=NULL, *password=NULL, *domain=NULL; CLSID clsid; HRESULT hr; OLECHAR *ProgID; @@ -450,7 +451,7 @@ PHP_FUNCTION(com_load) char *clsid_str; int mode = 0; ITypeLib *pTL; - + CLSCTX flags = CLSCTX_SERVER; codepage = CP_ACP; @@ -483,8 +484,75 @@ PHP_FUNCTION(com_load) ZEND_WRONG_PARAM_COUNT(); } - if (server_name != NULL) - { + if (server_name != NULL) { + /* if a server is passed, one obviously wants to instanciate a + * remote server + */ + flags = CTX_REMOTE_SERVER; + + /* What is server name? A String or an array? */ + + if (Z_TYPE_P(server_name) == IS_ARRAY) { + pval **tmp; + /* DAB: 22 Sept 2001 */ + /* Aha - we have a number of possible */ + /* arguments. They are in the hash */ + /* By name: Server, Domain, Username, Password */ + /* Flags. */ + /* This has been crafted to maintian maximum backward */ + /* compatability, If the server name is specified as a */ + /* string, then the function shoule behave as before */ + /* by defaulting username and password and using the */ + /* (I believe) incorrect CLSCTX_SERVER instantiation */ + /* paramter. However if server is specified in this array */ + /* then we use either CLSCTX_REMOTE_SERVER or whatever */ + /* flags are specified in the array */ + HashTable *ht = Z_ARRVAL(*server_name); + if (FAILURE == zend_hash_find(ht, "Server", 7, (void **) &tmp)) { + server_name = NULL; + } else { + server_name = *tmp; + convert_to_string_ex(&server_name); + /* CLSCTX_SERVER includes INPROC and LOCAL */ + /* SERVER. This means that any local server */ + /* will be instantiated BEFORE even looking */ + /* on a remote server. Thus if we have a */ + /* server name, probably we want to access */ + /* a remote machine or we would not have */ + /* bothered specifying it. So it would be */ + /* wrong to to connect locally. Futher, */ + /* unless the name passed is a GUID, there has */ + /* to be something to map the Prog.Id to GUID */ + /* and unless that has been modified to remove */ + /* the information about local instantiation */ + /* CLSCTX_SERVER would force a local instantiation */ + /* This setting can be overridden below if the user */ + /* specifies a flags element */ + flags = CLSCTX_REMOTE_SERVER; + } + if (FAILURE == zend_hash_find(ht, "Username", 9, (void **) &tmp)) { + user_name = NULL; + } else { + user_name = *tmp; + convert_to_string_ex(&user_name); + } + if (FAILURE == zend_hash_find(ht, "Domain", 7, (void **) &tmp)) { + domain = NULL; + } else { + domain = *tmp; + convert_to_string_ex(&domain); + } + if (FAILURE == zend_hash_find(ht, "Password", 9, (void **) &tmp)) { + password=NULL; + } else { + password = *tmp; + convert_to_string_ex(&password); + } + if (SUCCESS == zend_hash_find(ht, "Flags", 6, (void **) &tmp)) { + convert_to_long_ex(tmp); + flags = (CLSCTX) Z_LVAL_P(tmp); + } + } if (Z_TYPE_P(server_name) == IS_NULL) { server_name = NULL; } else { @@ -527,9 +595,9 @@ PHP_FUNCTION(com_load) } else { hr = MK_E_SYNTAX; } - + efree(ProgID); - + if (FAILED(hr)) { php_COM_destruct(obj TSRMLS_CC); error_message = php_COM_error_message(hr TSRMLS_CC); @@ -541,20 +609,46 @@ PHP_FUNCTION(com_load) efree(ProgID); /* obtain IDispatch */ if (!server_name) { - hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj)); + hr = CoCreateInstance(&clsid, NULL, flags, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj)); } else { COSERVERINFO server_info; MULTI_QI pResults; + COAUTHIDENTITY authid; + COAUTHINFO authinfo = {RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, &authid, EOAC_NONE}; server_info.dwReserved1=0; server_info.dwReserved2=0; server_info.pwszName = php_char_to_OLECHAR(Z_STRVAL_P(server_name), Z_STRLEN_P(server_name), codepage TSRMLS_CC); - server_info.pAuthInfo=NULL; + if (user_name) { + /* Z_STRVAL_P(user_name); */ + /* Parse Username into domain\username */ + authid.User = (WCHAR *) Z_STRVAL_P(user_name); + authid.UserLength = Z_STRLEN_P(user_name); + if (password) { + authid.Password = (USHORT *) Z_STRVAL_P(password); + authid.PasswordLength = Z_STRLEN_P(password); + } else { + authid.Password = (USHORT *) ""; + authid.PasswordLength = 0; + } + if (domain) { + authid.Domain = (USHORT *) Z_STRVAL_P(domain); + authid.DomainLength = Z_STRLEN_P(domain); + } else { + authid.Domain = (USHORT *) ""; + authid.DomainLength = 0; + } + authid.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; + + server_info.pAuthInfo=&authinfo; + } else { + server_info.pAuthInfo=NULL; + } pResults.pIID = &IID_IDispatch; pResults.pItf = NULL; pResults.hr = S_OK; - hr = CoCreateInstanceEx(&clsid, NULL, CLSCTX_REMOTE_SERVER, &server_info, 1, &pResults); + hr=CoCreateInstanceEx(&clsid, NULL, flags, &server_info, 1, &pResults); if (SUCCEEDED(hr)) { hr = pResults.hr; C_DISPATCH(obj) = (IDispatch *) pResults.pItf; @@ -828,7 +922,7 @@ PHP_FUNCTION(com_invoke) if (do_COM_invoke(obj, function_name, var_result, arguments+2, arg_count-2 TSRMLS_CC)==FAILURE) { FREE_VARIANT(var_result); efree(arguments); - + RETURN_FALSE; } @@ -1194,7 +1288,7 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer FREE_VARIANT(var_result); if (obj != obj_prop) { FREE_COM(obj_prop); - + return_value = *object; ZVAL_ADDREF(&return_value); } else { @@ -1209,7 +1303,7 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer if (V_DISPATCH(var_result) == NULL) { FREE_VARIANT(var_result); FREE_COM(obj_prop); - + return return_value; } @@ -1255,7 +1349,7 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere if (!obj || (type != IS_COM)) { return FAILURE; } - + ALLOC_COM(obj_prop); ALLOC_VARIANT(var_result); @@ -1307,7 +1401,7 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere pval_destructor(&overloaded_property->element); } FREE_VARIANT(var_result); - + overloaded_property = (zend_overloaded_element *) element->data; do_COM_propput(&result, obj, &overloaded_property->element, value TSRMLS_CC); FREE_COM(obj_prop); @@ -1367,7 +1461,7 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro && !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")) { + && !strcmp(Z_STRVAL_P(&function_name->element), "addref")) { RETVAL_LONG(php_COM_addref(obj TSRMLS_CC)); } else { pval **arguments; @@ -1595,7 +1689,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) TypeLib->lpVtbl->GetTypeInfo(TypeLib, i, &TypeInfo); j=0; - while(SUCCEEDED(TypeInfo->lpVtbl->GetVarDesc(TypeInfo, j, &pVarDesc))) { + while (SUCCEEDED(TypeInfo->lpVtbl->GetVarDesc(TypeInfo, j, &pVarDesc))) { BSTR bstr_ids; zend_constant c; zval exists, results; @@ -1611,7 +1705,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) 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 */ @@ -1682,14 +1776,27 @@ static void php_register_COM_class(TSRMLS_D) } -PHP_MINIT_FUNCTION(COM) +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); +} - php_VARIANT_init(module_number, TSRMLS_C); + +PHP_MINIT_FUNCTION(COM) +{ + php_COM_init(module_number TSRMLS_CC); + php_VARIANT_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_INI_ENTRIES(); + return SUCCESS; } |