diff options
author | Harald Radi <phanto@php.net> | 2001-09-10 09:58:23 +0000 |
---|---|---|
committer | Harald Radi <phanto@php.net> | 2001-09-10 09:58:23 +0000 |
commit | 1678bfa0ce5073e4b732a3ffba48337166df2109 (patch) | |
tree | f8eb73a61c2aabef1e02f312fa2602136f76ba4b | |
parent | b91ce755f376d6ab5a6590dc7051f3e0f03d5e44 (diff) | |
download | php-git-1678bfa0ce5073e4b732a3ffba48337166df2109.tar.gz |
MFH
-rw-r--r-- | ext/com/COM.c | 767 | ||||
-rw-r--r-- | ext/rpc/com/com_wrapper.c | 767 |
2 files changed, 618 insertions, 916 deletions
diff --git a/ext/com/COM.c b/ext/com/COM.c index 0063f426b1..70c77be0bf 100644 --- a/ext/com/COM.c +++ b/ext/com/COM.c @@ -91,12 +91,10 @@ function_entry COM_functions[] = { PHP_FALIAS(com_propset, com_propput, NULL) PHP_FALIAS(com_set, com_propput, NULL) - - { - NULL, NULL, NULL - } + { NULL, NULL, NULL } }; + static PHP_MINFO_FUNCTION(COM) { DISPLAY_INI_ENTRIES(); @@ -110,16 +108,13 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS EXCEPINFO ExceptInfo; *ErrString = NULL; - if(C_ISREFD(obj)) - { - if(C_HASTLIB(obj)) - { + /* @todo use DispInvoke here ? */ + if (C_ISREFD(obj)) { + if (C_HASTLIB(obj)) { hr = C_TYPEINFO_VT(obj)->Invoke(C_TYPEINFO(obj), C_DISPATCH(obj), dispIdMember, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr); - if(FAILED(hr)) - { + if (FAILED(hr)) { hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr); - if(SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { /* * ITypLib doesn't work * Release ITypeLib and fall back to IDispatch @@ -129,31 +124,27 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS C_HASTLIB(obj) = FALSE; } } - } - else - { + } else { 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: - { - int srclen; - char *src = php_OLECHAR_to_char(ExceptInfo.bstrSource, &srclen, 1, codepage TSRMLS_CC); - int desclen; - char *desc = php_OLECHAR_to_char(ExceptInfo.bstrDescription, &desclen, 1, codepage TSRMLS_CC); - *ErrString = pemalloc(srclen+desclen+50, 1); - sprintf(*ErrString, "<b>Source</b>: %s <b>Description</b>: %s", src, desc); - pefree(src, 1); - pefree(desc, 1); - SysFreeString(ExceptInfo.bstrSource); - SysFreeString(ExceptInfo.bstrDescription); - SysFreeString(ExceptInfo.bstrHelpFile); - } - break; + if (FAILED(hr)) { + switch (hr) { + case DISP_E_EXCEPTION: { + int srclen; + char *src = php_OLECHAR_to_char(ExceptInfo.bstrSource, &srclen, codepage TSRMLS_CC); + int desclen; + char *desc = php_OLECHAR_to_char(ExceptInfo.bstrDescription, &desclen, codepage TSRMLS_CC); + + *ErrString = pemalloc(srclen+desclen+50, 1); + sprintf(*ErrString, "<b>Source</b>: %s <b>Description</b>: %s", src, desc); + efree(src); + efree(desc); + SysFreeString(ExceptInfo.bstrSource); + SysFreeString(ExceptInfo.bstrDescription); + SysFreeString(ExceptInfo.bstrHelpFile); + } + break; case DISP_E_PARAMNOTFOUND: case DISP_E_TYPEMISMATCH: *ErrString = pemalloc(25, 1); @@ -162,10 +153,13 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS } } + if (pVarResult && (V_VT(pVarResult) == VT_EMPTY)) { + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = hr; + } + return hr; - } - else - { + } else { return DISP_E_UNKNOWNINTERFACE; } } @@ -174,18 +168,14 @@ PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames { HRESULT hr; - if(C_ISREFD(obj)) - { - if(C_HASTLIB(obj)) - { + if (C_ISREFD(obj)) { + if (C_HASTLIB(obj)) { hr = C_TYPEINFO_VT(obj)->GetIDsOfNames(C_TYPEINFO(obj), rgszNames, 1, rgDispId); - if(FAILED(hr)) - { + if (FAILED(hr)) { hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId); - if(SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { /* * ITypLib doesn't work * Release ITypeLib and fall back to IDispatch @@ -195,16 +185,12 @@ PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames C_HASTLIB(obj) = FALSE; } } - } - else - { + } else { hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId); } return hr; - } - else - { + } else { return DISP_E_UNKNOWNINTERFACE; } } @@ -213,18 +199,13 @@ PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC) { HRESULT hr; - if(obj->refcount > 1) - { + if (obj->refcount > 1) { C_RELEASE(obj); - } - else if(obj->refcount == 1) - { - if(C_HASTLIB(obj)) - { + } else if (obj->refcount == 1) { + if (C_HASTLIB(obj)) { C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj)); } - if(C_HASENUM(obj)) - { + if (C_HASENUM(obj)) { hr = C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj)); } hr = C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj)); @@ -236,8 +217,7 @@ PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC) PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC) { - if(C_ISREFD(obj)) - { + if (C_ISREFD(obj)) { C_ADDREF(obj); } @@ -257,6 +237,11 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup *ppDisp = NULL; } + 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))); @@ -268,26 +253,20 @@ 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))) - { - if(V_VT(var_result) == VT_UNKNOWN) - { + 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) - { + } 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) - { + if (!cleanup) { hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj)); } @@ -307,19 +286,14 @@ PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup TSRMLS_DC) C_DISPATCH(obj) = C_DISPATCH(clone); C_TYPEINFO(obj) = C_TYPEINFO(clone); - if(cleanup || !C_ISREFD(obj)) - { + if (cleanup || !C_ISREFD(obj)) { obj->refcount = clone->refcount; clone->refcount = 0; - } - else - { - if(C_HASTLIB(obj)) - { + } else { + if (C_HASTLIB(obj)) { C_TYPEINFO_VT(obj)->AddRef(C_TYPEINFO(obj)); } - if(C_HASENUM(obj)) - { + if (C_HASENUM(obj)) { C_ENUMVARIANT_VT(obj)->AddRef(C_ENUMVARIANT(obj)); } hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj)); @@ -337,9 +311,8 @@ 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)) - { + 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)); @@ -355,7 +328,7 @@ static char *php_string_from_clsid(const CLSID *clsid TSRMLS_DC) char *clsid_str; StringFromCLSID(clsid, &ole_clsid); - clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, 0, codepage TSRMLS_CC); + clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, codepage TSRMLS_CC); LocalFree(ole_clsid); return clsid_str; @@ -365,8 +338,7 @@ PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC) { HRESULT hr = S_OK; - if(C_ISREFD(obj)) - { + if (C_ISREFD(obj)) { C_REFCOUNT(obj) = 1; hr = php_COM_release(obj TSRMLS_CC); } @@ -375,11 +347,13 @@ PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC) 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; @@ -388,64 +362,53 @@ static PHP_INI_MH(OnTypelibFileChange) int interactive; interactive = CG(interactive); - if(!new_value || (typelib_file = VCWD_FOPEN(new_value, "r"))==NULL) - { + if (!new_value || (typelib_file = VCWD_FOPEN(new_value, "r"))==NULL) { return FAILURE; } - if(interactive) - { + if (interactive) { printf("Loading type libraries..."); fflush(stdout); } 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; - int mode = CONST_PERSISTENT|CONST_CS; + int mode = CONST_CS | CONST_PERSISTENT; /* CONST_PERSISTENT is ok here */ - if(typelib_name_buffer[0]==';') - { + 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) - { + 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")) - { + 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 */ - { + 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--; } - if(interactive) - { + if (interactive) { printf("\rLoading %-60s\r", typelib_name); } - if((pTL = php_COM_find_typelib(typelib_name, mode TSRMLS_CC)) != NULL) - { + if ((pTL = php_COM_find_typelib(typelib_name, mode TSRMLS_CC)) != NULL) { php_COM_load_typelib(pTL, mode TSRMLS_CC); pTL->lpVtbl->Release(pTL); } @@ -454,8 +417,7 @@ static PHP_INI_MH(OnTypelibFileChange) efree(typelib_name_buffer); fclose(typelib_file); - if(interactive) - { + if (interactive) { printf("\r%70s\r", ""); } @@ -472,7 +434,7 @@ 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]]]) +/* {{{ proto int com_load(string module_name [, string remote_host [, int codepage [, string typelib]]]) Loads a COM module */ PHP_FUNCTION(com_load) { @@ -483,31 +445,30 @@ PHP_FUNCTION(com_load) comval *obj; char *error_message; char *clsid_str; - int mode = CONST_PERSISTENT; + int mode = 0; ITypeLib *pTL; codepage = CP_ACP; - switch(ZEND_NUM_ARGS()) - { + switch (ZEND_NUM_ARGS()) { case 1: - getParameters(ht, 1, &module_name); + zend_get_parameters(ht, 1, &module_name); break; case 2: - getParameters(ht, 2, &module_name, &server_name); + zend_get_parameters(ht, 2, &module_name, &server_name); break; case 3: - getParameters(ht, 3, &module_name, &server_name, &code_page); + zend_get_parameters(ht, 3, &module_name, &server_name, &code_page); convert_to_long_ex(&code_page); codepage = code_page->value.lval; break; case 4: - getParameters(ht, 4, &module_name, &server_name, &code_page, &typelib); + zend_get_parameters(ht, 4, &module_name, &server_name, &code_page, &typelib); convert_to_string_ex(&typelib); convert_to_long_ex(&code_page); @@ -516,24 +477,18 @@ PHP_FUNCTION(com_load) break; default: - WRONG_PARAM_COUNT; + ZEND_WRONG_PARAM_COUNT(); } - if(server_name != NULL) + if (server_name != NULL) { - if(Z_TYPE_P(server_name) == IS_NULL) - { + if (Z_TYPE_P(server_name) == IS_NULL) { server_name = NULL; - } - else - { - if(!INI_INT("com.allow_dcom")) - { + } else { + if (!INI_INT("com.allow_dcom")) { php_error(E_WARNING, "DCOM is disabled"); RETURN_FALSE; - } - else - { + } else { convert_to_string_ex(&server_name); } } @@ -544,53 +499,47 @@ PHP_FUNCTION(com_load) ProgID = php_char_to_OLECHAR(Z_STRVAL_P(module_name), Z_STRLEN_P(module_name), codepage TSRMLS_CC); /* obtain CLSID */ - if(FAILED(CLSIDFromString(ProgID, &clsid))) - { + if (FAILED(CLSIDFromString(ProgID, &clsid))) { /* Perhaps this is a Moniker? */ IBindCtx *pBindCtx; IMoniker *pMoniker; ULONG ulEaten; - /* TODO: if(server_name) */ - - if(!server_name) - { - if(SUCCEEDED(hr = CreateBindCtx(0, &pBindCtx))) - { - if(SUCCEEDED(hr = MkParseDisplayName(pBindCtx, ProgID, &ulEaten, &pMoniker))) - { + /* @todo if (server_name) */ + + if (!server_name) { + /* @todo shouldn't the bind context be fetched on module startup and kept as a global shared instance ? + * all calls to BindToObject would deliver the same instance then (as desired) + * IBindCtx::RegisterObjectBound() should be called then after mkparsedisplayname() + * + * @todo use mkparsedisplaynameex() ? + */ + if (SUCCEEDED(hr = CreateBindCtx(0, &pBindCtx))) { + if (SUCCEEDED(hr = MkParseDisplayName(pBindCtx, ProgID, &ulEaten, &pMoniker))) { hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj)); pMoniker->lpVtbl->Release(pMoniker); } pBindCtx->lpVtbl->Release(pBindCtx); } - } - else - { + } else { hr = MK_E_SYNTAX; } efree(ProgID); - if(FAILED(hr)) - { + if (FAILED(hr)) { php_COM_destruct(obj TSRMLS_CC); error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"Invalid ProgID, GUID string, or Moniker: %s", error_message); LocalFree(error_message); RETURN_FALSE; } - } - else - { + } else { efree(ProgID); /* obtain IDispatch */ - if(!server_name) - { + if (!server_name) { hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj)); - } - else - { + } else { COSERVERINFO server_info; MULTI_QI pResults; @@ -603,16 +552,14 @@ PHP_FUNCTION(com_load) pResults.pItf = NULL; pResults.hr = S_OK; hr=CoCreateInstanceEx(&clsid, NULL, CLSCTX_SERVER, &server_info, 1, &pResults); - if(SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pResults.hr; C_DISPATCH(obj) = (IDispatch *) pResults.pItf; } efree(server_info.pwszName); } - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); clsid_str = php_string_from_clsid(&clsid TSRMLS_CC); php_error(E_WARNING,"Unable to obtain IDispatch interface for CLSID %s: %s",clsid_str,error_message); @@ -625,36 +572,28 @@ PHP_FUNCTION(com_load) php_COM_set(obj, &C_DISPATCH(obj), TRUE TSRMLS_CC); - if(INI_INT("com.autoregister_casesensitive")) - { + if (INI_INT("com.autoregister_casesensitive")) { mode |= CONST_CS; } - if(C_HASTLIB(obj)) - { - if(INI_INT("com.autoregister_typelib")) - { + if (C_HASTLIB(obj)) { + if (INI_INT("com.autoregister_typelib")) { unsigned int idx; - if(C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &pTL, &idx) == S_OK) - { + /* @todo check if typlib isn't already loaded */ + if (C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &pTL, &idx) == S_OK) { php_COM_load_typelib(pTL, mode TSRMLS_CC); pTL->lpVtbl->Release(pTL); } } - } - else - { - if(typelib != NULL) - { + } else { + if (typelib != NULL) { ITypeLib *pTL; - if((pTL = php_COM_find_typelib(Z_STRVAL_P(typelib), mode TSRMLS_CC)) != NULL) - { + if ((pTL = php_COM_find_typelib(Z_STRVAL_P(typelib), mode TSRMLS_CC)) != NULL) { C_HASTLIB(obj) = SUCCEEDED(pTL->lpVtbl->GetTypeInfo(pTL, 0, &C_TYPEINFO(obj))); /* idx 0 should deliver the ITypeInfo for the IDispatch Interface */ - if(INI_INT("com.autoregister_typelib")) - { + if (INI_INT("com.autoregister_typelib")) { php_COM_load_typelib(pTL, mode TSRMLS_CC); } pTL->lpVtbl->Release(pTL); @@ -678,8 +617,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** DISPPARAMS dispparams; SAFEARRAY *pSA; - if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "next")) - { + if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "next")) { /* Grab one argument off the stack, allocate enough * VARIANTs * Get the IEnumVariant interface and call ->Next(); @@ -687,8 +625,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** SAFEARRAYBOUND rgsabound[1]; unsigned long count; - switch(arg_count) - { + switch (arg_count) { case 0: count = 1; break; @@ -707,20 +644,16 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** rgsabound[0].lLbound = 0; rgsabound[0].cElements = count; - if((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL) - { + if ((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL) { VariantInit(var_result); return FAILURE; - } - else - { + } else { V_ARRAY(var_result) = pSA; V_VT(var_result) = VT_VARIANT|VT_ARRAY; } - if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Next(C_ENUMVARIANT(obj), count, pSA->pvData, &count))) - { + if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Next(C_ENUMVARIANT(obj), count, pSA->pvData, &count))) { char *error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); efree(error_message); @@ -728,11 +661,9 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** return FAILURE; } - if(count != rgsabound[0].cElements) - { + if (count != rgsabound[0].cElements) { rgsabound[0].cElements = count; - if(FAILED(SafeArrayRedim(pSA, rgsabound))) - { + if (FAILED(SafeArrayRedim(pSA, rgsabound))) { char *error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); efree(error_message); @@ -741,25 +672,27 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** } } + /* return a single element if next() was called without count */ + if ((arg_count == 0) && (count == 1)) { + long index[] = {0}; + + SafeArrayGetElement(pSA, index, var_result); + SafeArrayDestroy(pSA); + } + return SUCCESS; - } - else if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "reset")) - { - if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Reset(C_ENUMVARIANT(obj)))) - { + } else if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "reset")) { + if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Reset(C_ENUMVARIANT(obj)))) { char *error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); efree(error_message); return FAILURE; } return SUCCESS; - } - else if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "skip")) - { + } else if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "skip")) { unsigned long count; - switch(arg_count) - { + switch (arg_count) { case 0: count = 1; break; @@ -773,8 +706,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** php_error(E_WARNING,"Wrong argument count to IEnumVariant::Skip()"); return FAILURE; } - if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Skip(C_ENUMVARIANT(obj), count))) - { + if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Skip(C_ENUMVARIANT(obj), count))) { char *error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); efree(error_message); @@ -782,17 +714,13 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** } return SUCCESS; - } - else - { + } else { char *ErrString; funcname = php_char_to_OLECHAR(Z_STRVAL_P(function_name), Z_STRLEN_P(function_name), codepage TSRMLS_CC); - hr = php_COM_get_ids_of_names(obj, &funcname, &dispid TSRMLS_CC); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"Unable to lookup %s: %s", Z_STRVAL_P(function_name), error_message); LocalFree(error_message); @@ -802,8 +730,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** variant_args = (VARIANT *) emalloc(sizeof(VARIANT) * arg_count); - for(current_arg=0; current_arg<arg_count; current_arg++) - { + for (current_arg=0; current_arg<arg_count; current_arg++) { current_variant = arg_count - current_arg - 1; php_pval_to_variant(arguments[current_arg], &variant_args[current_variant], codepage TSRMLS_CC); } @@ -816,22 +743,21 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** hr = php_COM_invoke(obj, dispid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC); efree(funcname); - for (current_arg=0;current_arg<arg_count;current_arg++) - { - VariantClear(&variant_args[current_arg]); + for (current_arg=0;current_arg<arg_count;current_arg++) { + /* don't release IDispatch pointers as they are used afterwards */ + if (V_VT(&variant_args[current_arg]) != VT_DISPATCH) { + /* @todo review this: what happens to an array of IDispatchs or a VARIANT->IDispatch */ + VariantClear(&variant_args[current_arg]); + } } efree(variant_args); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); - if (ErrString) - { + if (ErrString) { php_error(E_WARNING,"Invoke() failed: %s %s", error_message, ErrString); pefree(ErrString, 1); - } - else - { + } else { php_error(E_WARNING,"Invoke() failed: %s", error_message); } LocalFree(error_message); @@ -853,13 +779,11 @@ PHP_FUNCTION(com_invoke) int arg_count = ZEND_NUM_ARGS(); VARIANT *var_result; - if(arg_count<2) - { - WRONG_PARAM_COUNT; + if (arg_count<2) { + ZEND_WRONG_PARAM_COUNT(); } arguments = (pval **) emalloc(sizeof(pval *)*arg_count); - if(getParametersArray(ht, arg_count, arguments) == FAILURE) - { + if (zend_get_parameters_array(ht, arg_count, arguments) == FAILURE) { RETURN_FALSE; } @@ -869,8 +793,7 @@ PHP_FUNCTION(com_invoke) /* obtain IDispatch interface */ convert_to_long(object); obj = (comval *)zend_list_find(Z_LVAL_P(object), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%d is not a COM object handler", Z_STRVAL_P(function_name)); RETURN_FALSE; } @@ -880,21 +803,20 @@ PHP_FUNCTION(com_invoke) ALLOC_VARIANT(var_result); - if(do_COM_invoke(obj, function_name, var_result, arguments+2, arg_count-2 TSRMLS_CC)==FAILURE) - { + 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; } - php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC); + RETVAL_VARIANT(var_result); - FREE_VARIANT(var_result); efree(arguments); } /* }}} */ + /* {{{ proto mixed com_invoke(int module) Releases a COM object */ PHP_FUNCTION(com_release) @@ -904,21 +826,18 @@ PHP_FUNCTION(com_release) int type; int arg_count = ZEND_NUM_ARGS(); - if(arg_count != 1) - { - WRONG_PARAM_COUNT; + if (arg_count != 1) { + ZEND_WRONG_PARAM_COUNT(); } - if(getParameters(ht, 1, &object)==FAILURE) - { + if (zend_get_parameters(ht, 1, &object)==FAILURE) { RETURN_FALSE; } /* obtain IDispatch interface */ convert_to_long_ex(&object); obj = (comval *)zend_list_find(Z_LVAL_P(object), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%d is not a COM object handler"); RETURN_FALSE; } @@ -927,6 +846,7 @@ PHP_FUNCTION(com_release) } /* }}} */ + /* {{{ proto mixed com_addref(int module) Increases the reference counter on a COM object */ PHP_FUNCTION(com_addref) @@ -936,20 +856,18 @@ PHP_FUNCTION(com_addref) int type; int arg_count = ZEND_NUM_ARGS(); - if(arg_count != 1) - { - WRONG_PARAM_COUNT; + if (arg_count != 1) { + ZEND_WRONG_PARAM_COUNT(); } - if(getParameters(ht, 1, &object)==FAILURE) - { + if (zend_get_parameters(ht, 1, &object)==FAILURE) { RETURN_FALSE; } /* obtain IDispatch interface */ convert_to_long_ex(&object); obj = (comval *)zend_list_find(Z_LVAL_P(object), &type); - if(!obj || (type != IS_COM)) + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%d is not a COM object handler"); RETURN_FALSE; @@ -966,8 +884,7 @@ static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cle ZVAL_STRINGL(&function_name, "Item", 4, 0); retval = do_COM_invoke(array, &function_name, result, &property, 1 TSRMLS_CC); - if(cleanup) - { + if (cleanup) { php_COM_destruct(array TSRMLS_CC); } @@ -988,16 +905,16 @@ static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, hr = php_COM_get_ids_of_names(obj, &propname, &dispid TSRMLS_CC); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"Unable to lookup %s: %s", Z_STRVAL_P(arg_property), error_message); LocalFree(error_message); efree(propname); - if(cleanup) - { + + if (cleanup) { php_COM_destruct(obj TSRMLS_CC); } + return FAILURE; } @@ -1006,32 +923,30 @@ static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); - if (ErrString) - { + if (ErrString) { php_error(E_WARNING,"PropGet() failed: %s %s", error_message, ErrString); pefree(ErrString, 1); - } - else - { + } else { php_error(E_WARNING,"PropGet() failed: %s", error_message); } + LocalFree(error_message); efree(propname); - if(cleanup) - { + + if (cleanup) { php_COM_destruct(obj TSRMLS_CC); } return FAILURE; } efree(propname); - if(cleanup) - { + + if (cleanup) { php_COM_destruct(obj TSRMLS_CC); } + return SUCCESS; } @@ -1055,8 +970,7 @@ static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, hr = php_COM_get_ids_of_names(obj, &propname, &dispid TSRMLS_CC); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"Unable to lookup %s: %s", Z_STRVAL_P(arg_property), error_message); LocalFree(error_message); @@ -1076,18 +990,15 @@ static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYPUT, &dispparams, NULL, &ErrString TSRMLS_CC); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); - if (ErrString) - { + if (ErrString) { php_error(E_WARNING,"PropPut() failed: %s %s", error_message, ErrString); pefree(ErrString, 1); - } - else - { + } else { php_error(E_WARNING,"PropPut() failed: %s", error_message); } + LocalFree(error_message); efree(propname); @@ -1102,18 +1013,14 @@ static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC); - if(SUCCEEDED(hr)) - { - php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC); - } - else - { + if (SUCCEEDED(hr)) { + php_variant_to_pval(var_result, return_value, codepage TSRMLS_CC); + } else { *return_value = *value; zval_copy_ctor(return_value); } - if (ErrString) - { + if (ErrString) { pefree(ErrString, 1); } @@ -1133,31 +1040,26 @@ PHP_FUNCTION(com_propget) comval *obj; VARIANT *var_result; - if((ZEND_NUM_ARGS() != 2) || (getParameters(ht, 2, &arg_comval, &arg_property) == FAILURE)) - { - WRONG_PARAM_COUNT; + if ((ZEND_NUM_ARGS() != 2) || (zend_get_parameters(ht, 2, &arg_comval, &arg_property) == FAILURE)) { + ZEND_WRONG_PARAM_COUNT(); } /* obtain IDispatch interface */ convert_to_long(arg_comval); obj = (comval *)zend_list_find(Z_LVAL_P(arg_comval), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_comval)); } convert_to_string_ex(&arg_property); ALLOC_VARIANT(var_result); - if(do_COM_propget(var_result, obj, arg_property, FALSE TSRMLS_CC) == FAILURE) - { + if (do_COM_propget(var_result, obj, arg_property, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); RETURN_FALSE; } - php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC); - - FREE_VARIANT(var_result); + RETVAL_VARIANT(var_result); } /* }}} */ @@ -1170,17 +1072,15 @@ PHP_FUNCTION(com_propput) int type; comval *obj; - if(ZEND_NUM_ARGS()!=3 || getParameters(ht, 3, &arg_comval, &arg_property, &arg_value)==FAILURE) - { - WRONG_PARAM_COUNT; + if (ZEND_NUM_ARGS()!=3 || zend_get_parameters(ht, 3, &arg_comval, &arg_property, &arg_value)==FAILURE) { + ZEND_WRONG_PARAM_COUNT(); } /* obtain comval interface */ convert_to_long(arg_comval); /* obtain comval interface */ obj = (comval *)zend_list_find(Z_LVAL_P(arg_comval), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_comval)); } convert_to_string_ex(&arg_property); @@ -1189,44 +1089,44 @@ PHP_FUNCTION(com_propput) } /* }}} */ -/* {{{ proto bool com_load_typelib(string typelib_name[, int case_insensitiv]) */ + +/* {{{ proto bool com_load_typelib(string typelib_name [, int case_insensitiv]) + Loads a Typelib */ PHP_FUNCTION(com_load_typelib) { pval *arg_typelib, *arg_cis; ITypeLib *pTL; - int mode; + int mode = CONST_CS; - switch(ZEND_NUM_ARGS()) - { + switch (ZEND_NUM_ARGS()) { case 1: - getParameters(ht, 1, &arg_typelib); - mode = CONST_PERSISTENT|CONST_CS; + zend_get_parameters(ht, 1, &arg_typelib); break; + case 2: - getParameters(ht, 2, &arg_typelib, &arg_cis); + zend_get_parameters(ht, 2, &arg_typelib, &arg_cis); convert_to_boolean_ex(&arg_cis); - if(arg_cis->value.lval) - { + if (arg_cis->value.lval) { mode &= ~CONST_CS; } + break; + default: - WRONG_PARAM_COUNT; + ZEND_WRONG_PARAM_COUNT(); } convert_to_string_ex(&arg_typelib); pTL = php_COM_find_typelib(Z_STRVAL_P(arg_typelib), mode TSRMLS_CC); - if(php_COM_load_typelib(pTL, mode TSRMLS_CC) == SUCCESS) - { + if (php_COM_load_typelib(pTL, mode TSRMLS_CC) == SUCCESS) { pTL->lpVtbl->Release(pTL); RETURN_TRUE; - } - else - { + } else { RETURN_FALSE; } } /* }}} */ + PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_reference) { zend_overloaded_element *overloaded_property; @@ -1245,22 +1145,19 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer /* fetch the IDispatch interface */ zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &comval_handle); obj = (comval *) zend_list_find(Z_LVAL_P(*comval_handle), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { return return_value; } ALLOC_COM(obj_prop); ALLOC_VARIANT(var_result); - for(element=property_reference->elements_list->head; element; element=element->next) - { + for (element=property_reference->elements_list->head; element; element=element->next) { overloaded_property = (zend_overloaded_element *) element->data; - switch(overloaded_property->type) - { + + switch (overloaded_property->type) { case OE_IS_ARRAY: - if(do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) - { + if (do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1269,8 +1166,7 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer break; case OE_IS_OBJECT: - if(do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) - { + if (do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1278,29 +1174,24 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer } break; - case OE_IS_METHOD: - { + case OE_IS_METHOD: { FREE_VARIANT(var_result); - if(obj != obj_prop) - { + if (obj != obj_prop) { FREE_COM(obj_prop); return_value = *object; ZVAL_ADDREF(&return_value); - } - else - { + } else { RETVAL_COM(obj); } + return return_value; } break; } - if(V_VT(var_result) == VT_DISPATCH) - { - if(V_DISPATCH(var_result) == NULL) - { + if (V_VT(var_result) == VT_DISPATCH) { + if (V_DISPATCH(var_result) == NULL) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1309,10 +1200,8 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer obj = obj_prop; php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC); - } - else - { - php_variant_to_pval(var_result, &return_value, FALSE, codepage TSRMLS_CC); + } else { + php_variant_to_pval(var_result, &return_value, codepage TSRMLS_CC); FREE_COM(obj_prop); obj_prop = NULL; @@ -1322,11 +1211,17 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer pval_destructor(&overloaded_property->element); } + if (obj_prop != NULL) { + RETVAL_COM(obj); + } + + FREE_VARIANT(var_result); return return_value; } + PHPAPI int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value) { pval result; @@ -1342,22 +1237,18 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere /* fetch the IDispatch interface */ zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &comval_handle); obj = (comval *)zend_list_find(Z_LVAL_P(*comval_handle), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { return FAILURE; } ALLOC_COM(obj_prop); ALLOC_VARIANT(var_result); - for(element=property_reference->elements_list->head; element != property_reference->elements_list->tail; element=element->next) - { + for (element=property_reference->elements_list->head; element != property_reference->elements_list->tail; element=element->next) { overloaded_property = (zend_overloaded_element *) element->data; - switch(overloaded_property->type) - { + switch (overloaded_property->type) { case OE_IS_ARRAY: - if(do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) - { + if (do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1366,8 +1257,7 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere break; case OE_IS_OBJECT: - if(do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) - { + if (do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1378,13 +1268,10 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere case OE_IS_METHOD: /* this shouldn't happen */ return FAILURE; - break; } - if(V_VT(var_result) == VT_DISPATCH) - { - if(V_DISPATCH(var_result) == NULL) - { + if (V_VT(var_result) == VT_DISPATCH) { + if (V_DISPATCH(var_result) == NULL) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1393,9 +1280,7 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere obj = obj_prop; php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC); - } - else - { + } else { FREE_COM(obj_prop); FREE_VARIANT(var_result); @@ -1416,6 +1301,7 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere return SUCCESS; } + PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference) { pval property, **handle; @@ -1424,14 +1310,13 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro comval *obj; int type; - if(zend_llist_count(property_reference->elements_list)==1 - && !strcmp(Z_STRVAL(function_name->element), "com")) - { /* constructor */ + if (zend_llist_count(property_reference->elements_list)==1 + && !strcmp(Z_STRVAL(function_name->element), "com")) { + /* constructor */ pval *object_handle; PHP_FN(com_load)(INTERNAL_FUNCTION_PARAM_PASSTHRU); - if(!zend_is_true(return_value)) - { + if (!zend_is_true(return_value)) { ZVAL_FALSE(object); return; } @@ -1446,10 +1331,8 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro } property = php_COM_get_property_handler(property_reference); - if(property.type == IS_NULL) - { - if(property.refcount == 1) - { + if (property.type == IS_NULL) { + if (property.refcount == 1) { pval_destructor(&property); } pval_destructor(&function_name->element); @@ -1458,25 +1341,19 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro 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)) - { + if (!obj || (type != IS_COM)) { pval_destructor(&property); pval_destructor(&function_name->element); return; } - if(zend_llist_count(property_reference->elements_list)==1 - && !strcmp(Z_STRVAL_P(&function_name->element), "release")) - { + 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")) - { + } 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 - { + } else { pval **arguments; VARIANT *var_result; int arg_count = ZEND_NUM_ARGS(); @@ -1484,23 +1361,19 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro ALLOC_VARIANT(var_result); arguments = (pval **) emalloc(sizeof(pval *)*arg_count); - getParametersArray(ht, arg_count, arguments); + zend_get_parameters_array(ht, arg_count, arguments); - if(do_COM_invoke(obj , &function_name->element, var_result, arguments, arg_count TSRMLS_CC) == FAILURE) - { + if (do_COM_invoke(obj , &function_name->element, var_result, arguments, arg_count TSRMLS_CC) == FAILURE) { RETVAL_FALSE; - } - else - { - php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC); + } else { + php_variant_to_pval(var_result, return_value, codepage TSRMLS_CC); } FREE_VARIANT(var_result); efree(arguments); } - if(property.refcount == 1) - { + if (property.refcount == 1) { pval_destructor(&property); } pval_destructor(&function_name->element); @@ -1530,16 +1403,14 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) p = php_char_to_OLECHAR(search_string, strlen(search_string), codepage TSRMLS_CC); /* Is the string a GUID ? */ - if(!FAILED(CLSIDFromString(p, &clsid))) - { + 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)) - { + if ((major != NULL) && (minor != NULL)) { major_i = (WORD) atoi(major); minor_i = (WORD) atoi(minor); } @@ -1550,37 +1421,30 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) /* 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)) - { + if (FAILED(hr) && (!major || !minor)) { IDispatch *Dispatch; ITypeInfo *TypeInfo; int idx; - if(FAILED(CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID *) &Dispatch))) - { + 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))) - { + 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))) - { + 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))) - { + } 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 */ @@ -1601,51 +1465,41 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) /* at each version for a string match to the */ /* supplied argument */ - if(ERROR_SUCCESS != RegOpenKey(HKEY_CLASSES_ROOT, "TypeLib",&hkey)) - { + 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)) - { + 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)) - { + 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)) - { + 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)) - { + 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))) - { + 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)) - { + 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; @@ -1658,8 +1512,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) /* 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)) - { + if (2 != sscanf(version, "%d.%d", &major, &minor)) { major = 1; minor = 0; } @@ -1673,9 +1526,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) /* test for errors and leave through a single "return" */ return TypeLib; } - } - else - { + } else { /* Failed - perhaps too small abuffer */ /* But if too small, then the name does not match */ } @@ -1697,21 +1548,18 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) int i; int interfaces; - if(NULL == TypeLib) - { + if (NULL == TypeLib) { return FAILURE; } interfaces = TypeLib->lpVtbl->GetTypeInfoCount(TypeLib); TypeLib->lpVtbl->GetTypeComp(TypeLib, &TypeComp); - for(i=0; i<interfaces; i++) - { + for (i=0; i<interfaces; i++) { TYPEKIND pTKind; TypeLib->lpVtbl->GetTypeInfoType(TypeLib, i, &pTKind); - if(pTKind==TKIND_ENUM) - { + if (pTKind==TKIND_ENUM) { ITypeInfo *TypeInfo; VARDESC *pVarDesc; UINT NameCount; @@ -1721,7 +1569,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) char *EnumId; TypeLib->lpVtbl->GetDocumentation(TypeLib, i, &bstr_EnumId, NULL, NULL, NULL); - EnumId = php_OLECHAR_to_char(bstr_EnumId, NULL, 0, codepage); + EnumId = php_OLECHAR_to_char(bstr_EnumId, NULL, codepage); printf("Enumeration %d - %s:\n", i, EnumId); efree(EnumId); #endif @@ -1729,43 +1577,47 @@ 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; - char *ids; zend_constant c; zval exists, results; + char *const_name; TypeInfo->lpVtbl->GetNames(TypeInfo, pVarDesc->memid, &bstr_ids, 1, &NameCount); - if(NameCount!=1) - { + if (NameCount!=1) { j++; continue; } - ids = php_OLECHAR_to_char(bstr_ids, NULL, 1, codepage TSRMLS_CC); + const_name = php_OLECHAR_to_char(bstr_ids, &c.name_len, codepage TSRMLS_CC); + + c.name = zend_strndup(const_name, c.name_len); + c.name_len++; /* length should include the NULL */ + + efree(const_name); SysFreeString(bstr_ids); - c.name_len = strlen(ids)+1; - c.name = ids; - if (zend_get_constant(c.name, c.name_len-1, &exists TSRMLS_CC)) - { + + /* Before registering the contant, 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")) - { + if (!compare_function(&results, &c.value, &exists TSRMLS_CC) && INI_INT("com.autoregister_verbose")) { php_error(E_WARNING,"Type library value %s is already defined and has a different value", c.name); } - free(ids); + + free(c.name); j++; continue; } - php_variant_to_pval(pVarDesc->lpvarValue, &c.value, FALSE, codepage TSRMLS_CC); + php_variant_to_pval(pVarDesc->lpvarValue, &c.value, codepage TSRMLS_CC); + if (mode & CONST_PERSISTENT) { + zval_persist(&c.value TSRMLS_CC); + mode |= CONST_EFREE_PERSISTENT; + } c.flags = mode; - /* Before registering the contsnt, let's see if we can find it */ - { - zend_register_constant(&c TSRMLS_CC); - } + zend_register_constant(&c TSRMLS_CC); + j++; } TypeInfo->lpVtbl->Release(TypeInfo); @@ -1775,6 +1627,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) return SUCCESS; } + /* {{{ proto bool com_isenum(com_module obj) Grabs an IEnumVariant */ PHP_FUNCTION(com_isenum) @@ -1784,18 +1637,16 @@ PHP_FUNCTION(com_isenum) comval *obj; int type; - if(ZEND_NUM_ARGS() != 1) - { - WRONG_PARAM_COUNT; + if (ZEND_NUM_ARGS() != 1) { + ZEND_WRONG_PARAM_COUNT(); } - getParameters(ht, 1, &object); + zend_get_parameters(ht, 1, &object); /* obtain IDispatch interface */ zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &comval_handle); obj = (comval *) zend_list_find(Z_LVAL_PP(comval_handle), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%s is not a COM object handler", ""); RETURN_FALSE; } @@ -1814,18 +1665,18 @@ static void php_register_COM_class(TSRMLS_D) zend_register_internal_class(&COM_class_entry TSRMLS_CC); } + PHP_MINIT_FUNCTION(COM) { - CoInitialize(NULL); le_comval = zend_register_list_destructors_ex(php_comval_destructor, NULL, "COM", module_number); php_register_COM_class(TSRMLS_C); REGISTER_INI_ENTRIES(); return SUCCESS; } + PHP_MSHUTDOWN_FUNCTION(COM) { - CoUninitialize(); UNREGISTER_INI_ENTRIES(); return SUCCESS; } diff --git a/ext/rpc/com/com_wrapper.c b/ext/rpc/com/com_wrapper.c index 0063f426b1..70c77be0bf 100644 --- a/ext/rpc/com/com_wrapper.c +++ b/ext/rpc/com/com_wrapper.c @@ -91,12 +91,10 @@ function_entry COM_functions[] = { PHP_FALIAS(com_propset, com_propput, NULL) PHP_FALIAS(com_set, com_propput, NULL) - - { - NULL, NULL, NULL - } + { NULL, NULL, NULL } }; + static PHP_MINFO_FUNCTION(COM) { DISPLAY_INI_ENTRIES(); @@ -110,16 +108,13 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS EXCEPINFO ExceptInfo; *ErrString = NULL; - if(C_ISREFD(obj)) - { - if(C_HASTLIB(obj)) - { + /* @todo use DispInvoke here ? */ + if (C_ISREFD(obj)) { + if (C_HASTLIB(obj)) { hr = C_TYPEINFO_VT(obj)->Invoke(C_TYPEINFO(obj), C_DISPATCH(obj), dispIdMember, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr); - if(FAILED(hr)) - { + if (FAILED(hr)) { hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr); - if(SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { /* * ITypLib doesn't work * Release ITypeLib and fall back to IDispatch @@ -129,31 +124,27 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS C_HASTLIB(obj) = FALSE; } } - } - else - { + } else { 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: - { - int srclen; - char *src = php_OLECHAR_to_char(ExceptInfo.bstrSource, &srclen, 1, codepage TSRMLS_CC); - int desclen; - char *desc = php_OLECHAR_to_char(ExceptInfo.bstrDescription, &desclen, 1, codepage TSRMLS_CC); - *ErrString = pemalloc(srclen+desclen+50, 1); - sprintf(*ErrString, "<b>Source</b>: %s <b>Description</b>: %s", src, desc); - pefree(src, 1); - pefree(desc, 1); - SysFreeString(ExceptInfo.bstrSource); - SysFreeString(ExceptInfo.bstrDescription); - SysFreeString(ExceptInfo.bstrHelpFile); - } - break; + if (FAILED(hr)) { + switch (hr) { + case DISP_E_EXCEPTION: { + int srclen; + char *src = php_OLECHAR_to_char(ExceptInfo.bstrSource, &srclen, codepage TSRMLS_CC); + int desclen; + char *desc = php_OLECHAR_to_char(ExceptInfo.bstrDescription, &desclen, codepage TSRMLS_CC); + + *ErrString = pemalloc(srclen+desclen+50, 1); + sprintf(*ErrString, "<b>Source</b>: %s <b>Description</b>: %s", src, desc); + efree(src); + efree(desc); + SysFreeString(ExceptInfo.bstrSource); + SysFreeString(ExceptInfo.bstrDescription); + SysFreeString(ExceptInfo.bstrHelpFile); + } + break; case DISP_E_PARAMNOTFOUND: case DISP_E_TYPEMISMATCH: *ErrString = pemalloc(25, 1); @@ -162,10 +153,13 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS } } + if (pVarResult && (V_VT(pVarResult) == VT_EMPTY)) { + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = hr; + } + return hr; - } - else - { + } else { return DISP_E_UNKNOWNINTERFACE; } } @@ -174,18 +168,14 @@ PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames { HRESULT hr; - if(C_ISREFD(obj)) - { - if(C_HASTLIB(obj)) - { + if (C_ISREFD(obj)) { + if (C_HASTLIB(obj)) { hr = C_TYPEINFO_VT(obj)->GetIDsOfNames(C_TYPEINFO(obj), rgszNames, 1, rgDispId); - if(FAILED(hr)) - { + if (FAILED(hr)) { hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId); - if(SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { /* * ITypLib doesn't work * Release ITypeLib and fall back to IDispatch @@ -195,16 +185,12 @@ PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames C_HASTLIB(obj) = FALSE; } } - } - else - { + } else { hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId); } return hr; - } - else - { + } else { return DISP_E_UNKNOWNINTERFACE; } } @@ -213,18 +199,13 @@ PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC) { HRESULT hr; - if(obj->refcount > 1) - { + if (obj->refcount > 1) { C_RELEASE(obj); - } - else if(obj->refcount == 1) - { - if(C_HASTLIB(obj)) - { + } else if (obj->refcount == 1) { + if (C_HASTLIB(obj)) { C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj)); } - if(C_HASENUM(obj)) - { + if (C_HASENUM(obj)) { hr = C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj)); } hr = C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj)); @@ -236,8 +217,7 @@ PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC) PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC) { - if(C_ISREFD(obj)) - { + if (C_ISREFD(obj)) { C_ADDREF(obj); } @@ -257,6 +237,11 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup *ppDisp = NULL; } + 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))); @@ -268,26 +253,20 @@ 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))) - { - if(V_VT(var_result) == VT_UNKNOWN) - { + 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) - { + } 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) - { + if (!cleanup) { hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj)); } @@ -307,19 +286,14 @@ PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup TSRMLS_DC) C_DISPATCH(obj) = C_DISPATCH(clone); C_TYPEINFO(obj) = C_TYPEINFO(clone); - if(cleanup || !C_ISREFD(obj)) - { + if (cleanup || !C_ISREFD(obj)) { obj->refcount = clone->refcount; clone->refcount = 0; - } - else - { - if(C_HASTLIB(obj)) - { + } else { + if (C_HASTLIB(obj)) { C_TYPEINFO_VT(obj)->AddRef(C_TYPEINFO(obj)); } - if(C_HASENUM(obj)) - { + if (C_HASENUM(obj)) { C_ENUMVARIANT_VT(obj)->AddRef(C_ENUMVARIANT(obj)); } hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj)); @@ -337,9 +311,8 @@ 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)) - { + 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)); @@ -355,7 +328,7 @@ static char *php_string_from_clsid(const CLSID *clsid TSRMLS_DC) char *clsid_str; StringFromCLSID(clsid, &ole_clsid); - clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, 0, codepage TSRMLS_CC); + clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, codepage TSRMLS_CC); LocalFree(ole_clsid); return clsid_str; @@ -365,8 +338,7 @@ PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC) { HRESULT hr = S_OK; - if(C_ISREFD(obj)) - { + if (C_ISREFD(obj)) { C_REFCOUNT(obj) = 1; hr = php_COM_release(obj TSRMLS_CC); } @@ -375,11 +347,13 @@ PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC) 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; @@ -388,64 +362,53 @@ static PHP_INI_MH(OnTypelibFileChange) int interactive; interactive = CG(interactive); - if(!new_value || (typelib_file = VCWD_FOPEN(new_value, "r"))==NULL) - { + if (!new_value || (typelib_file = VCWD_FOPEN(new_value, "r"))==NULL) { return FAILURE; } - if(interactive) - { + if (interactive) { printf("Loading type libraries..."); fflush(stdout); } 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; - int mode = CONST_PERSISTENT|CONST_CS; + int mode = CONST_CS | CONST_PERSISTENT; /* CONST_PERSISTENT is ok here */ - if(typelib_name_buffer[0]==';') - { + 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) - { + 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")) - { + 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 */ - { + 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--; } - if(interactive) - { + if (interactive) { printf("\rLoading %-60s\r", typelib_name); } - if((pTL = php_COM_find_typelib(typelib_name, mode TSRMLS_CC)) != NULL) - { + if ((pTL = php_COM_find_typelib(typelib_name, mode TSRMLS_CC)) != NULL) { php_COM_load_typelib(pTL, mode TSRMLS_CC); pTL->lpVtbl->Release(pTL); } @@ -454,8 +417,7 @@ static PHP_INI_MH(OnTypelibFileChange) efree(typelib_name_buffer); fclose(typelib_file); - if(interactive) - { + if (interactive) { printf("\r%70s\r", ""); } @@ -472,7 +434,7 @@ 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]]]) +/* {{{ proto int com_load(string module_name [, string remote_host [, int codepage [, string typelib]]]) Loads a COM module */ PHP_FUNCTION(com_load) { @@ -483,31 +445,30 @@ PHP_FUNCTION(com_load) comval *obj; char *error_message; char *clsid_str; - int mode = CONST_PERSISTENT; + int mode = 0; ITypeLib *pTL; codepage = CP_ACP; - switch(ZEND_NUM_ARGS()) - { + switch (ZEND_NUM_ARGS()) { case 1: - getParameters(ht, 1, &module_name); + zend_get_parameters(ht, 1, &module_name); break; case 2: - getParameters(ht, 2, &module_name, &server_name); + zend_get_parameters(ht, 2, &module_name, &server_name); break; case 3: - getParameters(ht, 3, &module_name, &server_name, &code_page); + zend_get_parameters(ht, 3, &module_name, &server_name, &code_page); convert_to_long_ex(&code_page); codepage = code_page->value.lval; break; case 4: - getParameters(ht, 4, &module_name, &server_name, &code_page, &typelib); + zend_get_parameters(ht, 4, &module_name, &server_name, &code_page, &typelib); convert_to_string_ex(&typelib); convert_to_long_ex(&code_page); @@ -516,24 +477,18 @@ PHP_FUNCTION(com_load) break; default: - WRONG_PARAM_COUNT; + ZEND_WRONG_PARAM_COUNT(); } - if(server_name != NULL) + if (server_name != NULL) { - if(Z_TYPE_P(server_name) == IS_NULL) - { + if (Z_TYPE_P(server_name) == IS_NULL) { server_name = NULL; - } - else - { - if(!INI_INT("com.allow_dcom")) - { + } else { + if (!INI_INT("com.allow_dcom")) { php_error(E_WARNING, "DCOM is disabled"); RETURN_FALSE; - } - else - { + } else { convert_to_string_ex(&server_name); } } @@ -544,53 +499,47 @@ PHP_FUNCTION(com_load) ProgID = php_char_to_OLECHAR(Z_STRVAL_P(module_name), Z_STRLEN_P(module_name), codepage TSRMLS_CC); /* obtain CLSID */ - if(FAILED(CLSIDFromString(ProgID, &clsid))) - { + if (FAILED(CLSIDFromString(ProgID, &clsid))) { /* Perhaps this is a Moniker? */ IBindCtx *pBindCtx; IMoniker *pMoniker; ULONG ulEaten; - /* TODO: if(server_name) */ - - if(!server_name) - { - if(SUCCEEDED(hr = CreateBindCtx(0, &pBindCtx))) - { - if(SUCCEEDED(hr = MkParseDisplayName(pBindCtx, ProgID, &ulEaten, &pMoniker))) - { + /* @todo if (server_name) */ + + if (!server_name) { + /* @todo shouldn't the bind context be fetched on module startup and kept as a global shared instance ? + * all calls to BindToObject would deliver the same instance then (as desired) + * IBindCtx::RegisterObjectBound() should be called then after mkparsedisplayname() + * + * @todo use mkparsedisplaynameex() ? + */ + if (SUCCEEDED(hr = CreateBindCtx(0, &pBindCtx))) { + if (SUCCEEDED(hr = MkParseDisplayName(pBindCtx, ProgID, &ulEaten, &pMoniker))) { hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj)); pMoniker->lpVtbl->Release(pMoniker); } pBindCtx->lpVtbl->Release(pBindCtx); } - } - else - { + } else { hr = MK_E_SYNTAX; } efree(ProgID); - if(FAILED(hr)) - { + if (FAILED(hr)) { php_COM_destruct(obj TSRMLS_CC); error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"Invalid ProgID, GUID string, or Moniker: %s", error_message); LocalFree(error_message); RETURN_FALSE; } - } - else - { + } else { efree(ProgID); /* obtain IDispatch */ - if(!server_name) - { + if (!server_name) { hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj)); - } - else - { + } else { COSERVERINFO server_info; MULTI_QI pResults; @@ -603,16 +552,14 @@ PHP_FUNCTION(com_load) pResults.pItf = NULL; pResults.hr = S_OK; hr=CoCreateInstanceEx(&clsid, NULL, CLSCTX_SERVER, &server_info, 1, &pResults); - if(SUCCEEDED(hr)) - { + if (SUCCEEDED(hr)) { hr = pResults.hr; C_DISPATCH(obj) = (IDispatch *) pResults.pItf; } efree(server_info.pwszName); } - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); clsid_str = php_string_from_clsid(&clsid TSRMLS_CC); php_error(E_WARNING,"Unable to obtain IDispatch interface for CLSID %s: %s",clsid_str,error_message); @@ -625,36 +572,28 @@ PHP_FUNCTION(com_load) php_COM_set(obj, &C_DISPATCH(obj), TRUE TSRMLS_CC); - if(INI_INT("com.autoregister_casesensitive")) - { + if (INI_INT("com.autoregister_casesensitive")) { mode |= CONST_CS; } - if(C_HASTLIB(obj)) - { - if(INI_INT("com.autoregister_typelib")) - { + if (C_HASTLIB(obj)) { + if (INI_INT("com.autoregister_typelib")) { unsigned int idx; - if(C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &pTL, &idx) == S_OK) - { + /* @todo check if typlib isn't already loaded */ + if (C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &pTL, &idx) == S_OK) { php_COM_load_typelib(pTL, mode TSRMLS_CC); pTL->lpVtbl->Release(pTL); } } - } - else - { - if(typelib != NULL) - { + } else { + if (typelib != NULL) { ITypeLib *pTL; - if((pTL = php_COM_find_typelib(Z_STRVAL_P(typelib), mode TSRMLS_CC)) != NULL) - { + if ((pTL = php_COM_find_typelib(Z_STRVAL_P(typelib), mode TSRMLS_CC)) != NULL) { C_HASTLIB(obj) = SUCCEEDED(pTL->lpVtbl->GetTypeInfo(pTL, 0, &C_TYPEINFO(obj))); /* idx 0 should deliver the ITypeInfo for the IDispatch Interface */ - if(INI_INT("com.autoregister_typelib")) - { + if (INI_INT("com.autoregister_typelib")) { php_COM_load_typelib(pTL, mode TSRMLS_CC); } pTL->lpVtbl->Release(pTL); @@ -678,8 +617,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** DISPPARAMS dispparams; SAFEARRAY *pSA; - if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "next")) - { + if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "next")) { /* Grab one argument off the stack, allocate enough * VARIANTs * Get the IEnumVariant interface and call ->Next(); @@ -687,8 +625,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** SAFEARRAYBOUND rgsabound[1]; unsigned long count; - switch(arg_count) - { + switch (arg_count) { case 0: count = 1; break; @@ -707,20 +644,16 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** rgsabound[0].lLbound = 0; rgsabound[0].cElements = count; - if((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL) - { + if ((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL) { VariantInit(var_result); return FAILURE; - } - else - { + } else { V_ARRAY(var_result) = pSA; V_VT(var_result) = VT_VARIANT|VT_ARRAY; } - if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Next(C_ENUMVARIANT(obj), count, pSA->pvData, &count))) - { + if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Next(C_ENUMVARIANT(obj), count, pSA->pvData, &count))) { char *error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); efree(error_message); @@ -728,11 +661,9 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** return FAILURE; } - if(count != rgsabound[0].cElements) - { + if (count != rgsabound[0].cElements) { rgsabound[0].cElements = count; - if(FAILED(SafeArrayRedim(pSA, rgsabound))) - { + if (FAILED(SafeArrayRedim(pSA, rgsabound))) { char *error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); efree(error_message); @@ -741,25 +672,27 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** } } + /* return a single element if next() was called without count */ + if ((arg_count == 0) && (count == 1)) { + long index[] = {0}; + + SafeArrayGetElement(pSA, index, var_result); + SafeArrayDestroy(pSA); + } + return SUCCESS; - } - else if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "reset")) - { - if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Reset(C_ENUMVARIANT(obj)))) - { + } else if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "reset")) { + if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Reset(C_ENUMVARIANT(obj)))) { char *error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); efree(error_message); return FAILURE; } return SUCCESS; - } - else if(C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "skip")) - { + } else if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "skip")) { unsigned long count; - switch(arg_count) - { + switch (arg_count) { case 0: count = 1; break; @@ -773,8 +706,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** php_error(E_WARNING,"Wrong argument count to IEnumVariant::Skip()"); return FAILURE; } - if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Skip(C_ENUMVARIANT(obj), count))) - { + if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Skip(C_ENUMVARIANT(obj), count))) { char *error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); efree(error_message); @@ -782,17 +714,13 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** } return SUCCESS; - } - else - { + } else { char *ErrString; funcname = php_char_to_OLECHAR(Z_STRVAL_P(function_name), Z_STRLEN_P(function_name), codepage TSRMLS_CC); - hr = php_COM_get_ids_of_names(obj, &funcname, &dispid TSRMLS_CC); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"Unable to lookup %s: %s", Z_STRVAL_P(function_name), error_message); LocalFree(error_message); @@ -802,8 +730,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** variant_args = (VARIANT *) emalloc(sizeof(VARIANT) * arg_count); - for(current_arg=0; current_arg<arg_count; current_arg++) - { + for (current_arg=0; current_arg<arg_count; current_arg++) { current_variant = arg_count - current_arg - 1; php_pval_to_variant(arguments[current_arg], &variant_args[current_variant], codepage TSRMLS_CC); } @@ -816,22 +743,21 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval ** hr = php_COM_invoke(obj, dispid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC); efree(funcname); - for (current_arg=0;current_arg<arg_count;current_arg++) - { - VariantClear(&variant_args[current_arg]); + for (current_arg=0;current_arg<arg_count;current_arg++) { + /* don't release IDispatch pointers as they are used afterwards */ + if (V_VT(&variant_args[current_arg]) != VT_DISPATCH) { + /* @todo review this: what happens to an array of IDispatchs or a VARIANT->IDispatch */ + VariantClear(&variant_args[current_arg]); + } } efree(variant_args); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); - if (ErrString) - { + if (ErrString) { php_error(E_WARNING,"Invoke() failed: %s %s", error_message, ErrString); pefree(ErrString, 1); - } - else - { + } else { php_error(E_WARNING,"Invoke() failed: %s", error_message); } LocalFree(error_message); @@ -853,13 +779,11 @@ PHP_FUNCTION(com_invoke) int arg_count = ZEND_NUM_ARGS(); VARIANT *var_result; - if(arg_count<2) - { - WRONG_PARAM_COUNT; + if (arg_count<2) { + ZEND_WRONG_PARAM_COUNT(); } arguments = (pval **) emalloc(sizeof(pval *)*arg_count); - if(getParametersArray(ht, arg_count, arguments) == FAILURE) - { + if (zend_get_parameters_array(ht, arg_count, arguments) == FAILURE) { RETURN_FALSE; } @@ -869,8 +793,7 @@ PHP_FUNCTION(com_invoke) /* obtain IDispatch interface */ convert_to_long(object); obj = (comval *)zend_list_find(Z_LVAL_P(object), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%d is not a COM object handler", Z_STRVAL_P(function_name)); RETURN_FALSE; } @@ -880,21 +803,20 @@ PHP_FUNCTION(com_invoke) ALLOC_VARIANT(var_result); - if(do_COM_invoke(obj, function_name, var_result, arguments+2, arg_count-2 TSRMLS_CC)==FAILURE) - { + 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; } - php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC); + RETVAL_VARIANT(var_result); - FREE_VARIANT(var_result); efree(arguments); } /* }}} */ + /* {{{ proto mixed com_invoke(int module) Releases a COM object */ PHP_FUNCTION(com_release) @@ -904,21 +826,18 @@ PHP_FUNCTION(com_release) int type; int arg_count = ZEND_NUM_ARGS(); - if(arg_count != 1) - { - WRONG_PARAM_COUNT; + if (arg_count != 1) { + ZEND_WRONG_PARAM_COUNT(); } - if(getParameters(ht, 1, &object)==FAILURE) - { + if (zend_get_parameters(ht, 1, &object)==FAILURE) { RETURN_FALSE; } /* obtain IDispatch interface */ convert_to_long_ex(&object); obj = (comval *)zend_list_find(Z_LVAL_P(object), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%d is not a COM object handler"); RETURN_FALSE; } @@ -927,6 +846,7 @@ PHP_FUNCTION(com_release) } /* }}} */ + /* {{{ proto mixed com_addref(int module) Increases the reference counter on a COM object */ PHP_FUNCTION(com_addref) @@ -936,20 +856,18 @@ PHP_FUNCTION(com_addref) int type; int arg_count = ZEND_NUM_ARGS(); - if(arg_count != 1) - { - WRONG_PARAM_COUNT; + if (arg_count != 1) { + ZEND_WRONG_PARAM_COUNT(); } - if(getParameters(ht, 1, &object)==FAILURE) - { + if (zend_get_parameters(ht, 1, &object)==FAILURE) { RETURN_FALSE; } /* obtain IDispatch interface */ convert_to_long_ex(&object); obj = (comval *)zend_list_find(Z_LVAL_P(object), &type); - if(!obj || (type != IS_COM)) + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%d is not a COM object handler"); RETURN_FALSE; @@ -966,8 +884,7 @@ static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cle ZVAL_STRINGL(&function_name, "Item", 4, 0); retval = do_COM_invoke(array, &function_name, result, &property, 1 TSRMLS_CC); - if(cleanup) - { + if (cleanup) { php_COM_destruct(array TSRMLS_CC); } @@ -988,16 +905,16 @@ static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, hr = php_COM_get_ids_of_names(obj, &propname, &dispid TSRMLS_CC); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"Unable to lookup %s: %s", Z_STRVAL_P(arg_property), error_message); LocalFree(error_message); efree(propname); - if(cleanup) - { + + if (cleanup) { php_COM_destruct(obj TSRMLS_CC); } + return FAILURE; } @@ -1006,32 +923,30 @@ static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); - if (ErrString) - { + if (ErrString) { php_error(E_WARNING,"PropGet() failed: %s %s", error_message, ErrString); pefree(ErrString, 1); - } - else - { + } else { php_error(E_WARNING,"PropGet() failed: %s", error_message); } + LocalFree(error_message); efree(propname); - if(cleanup) - { + + if (cleanup) { php_COM_destruct(obj TSRMLS_CC); } return FAILURE; } efree(propname); - if(cleanup) - { + + if (cleanup) { php_COM_destruct(obj TSRMLS_CC); } + return SUCCESS; } @@ -1055,8 +970,7 @@ static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, hr = php_COM_get_ids_of_names(obj, &propname, &dispid TSRMLS_CC); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); php_error(E_WARNING,"Unable to lookup %s: %s", Z_STRVAL_P(arg_property), error_message); LocalFree(error_message); @@ -1076,18 +990,15 @@ static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYPUT, &dispparams, NULL, &ErrString TSRMLS_CC); - if(FAILED(hr)) - { + if (FAILED(hr)) { error_message = php_COM_error_message(hr TSRMLS_CC); - if (ErrString) - { + if (ErrString) { php_error(E_WARNING,"PropPut() failed: %s %s", error_message, ErrString); pefree(ErrString, 1); - } - else - { + } else { php_error(E_WARNING,"PropPut() failed: %s", error_message); } + LocalFree(error_message); efree(propname); @@ -1102,18 +1013,14 @@ static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC); - if(SUCCEEDED(hr)) - { - php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC); - } - else - { + if (SUCCEEDED(hr)) { + php_variant_to_pval(var_result, return_value, codepage TSRMLS_CC); + } else { *return_value = *value; zval_copy_ctor(return_value); } - if (ErrString) - { + if (ErrString) { pefree(ErrString, 1); } @@ -1133,31 +1040,26 @@ PHP_FUNCTION(com_propget) comval *obj; VARIANT *var_result; - if((ZEND_NUM_ARGS() != 2) || (getParameters(ht, 2, &arg_comval, &arg_property) == FAILURE)) - { - WRONG_PARAM_COUNT; + if ((ZEND_NUM_ARGS() != 2) || (zend_get_parameters(ht, 2, &arg_comval, &arg_property) == FAILURE)) { + ZEND_WRONG_PARAM_COUNT(); } /* obtain IDispatch interface */ convert_to_long(arg_comval); obj = (comval *)zend_list_find(Z_LVAL_P(arg_comval), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_comval)); } convert_to_string_ex(&arg_property); ALLOC_VARIANT(var_result); - if(do_COM_propget(var_result, obj, arg_property, FALSE TSRMLS_CC) == FAILURE) - { + if (do_COM_propget(var_result, obj, arg_property, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); RETURN_FALSE; } - php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC); - - FREE_VARIANT(var_result); + RETVAL_VARIANT(var_result); } /* }}} */ @@ -1170,17 +1072,15 @@ PHP_FUNCTION(com_propput) int type; comval *obj; - if(ZEND_NUM_ARGS()!=3 || getParameters(ht, 3, &arg_comval, &arg_property, &arg_value)==FAILURE) - { - WRONG_PARAM_COUNT; + if (ZEND_NUM_ARGS()!=3 || zend_get_parameters(ht, 3, &arg_comval, &arg_property, &arg_value)==FAILURE) { + ZEND_WRONG_PARAM_COUNT(); } /* obtain comval interface */ convert_to_long(arg_comval); /* obtain comval interface */ obj = (comval *)zend_list_find(Z_LVAL_P(arg_comval), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_comval)); } convert_to_string_ex(&arg_property); @@ -1189,44 +1089,44 @@ PHP_FUNCTION(com_propput) } /* }}} */ -/* {{{ proto bool com_load_typelib(string typelib_name[, int case_insensitiv]) */ + +/* {{{ proto bool com_load_typelib(string typelib_name [, int case_insensitiv]) + Loads a Typelib */ PHP_FUNCTION(com_load_typelib) { pval *arg_typelib, *arg_cis; ITypeLib *pTL; - int mode; + int mode = CONST_CS; - switch(ZEND_NUM_ARGS()) - { + switch (ZEND_NUM_ARGS()) { case 1: - getParameters(ht, 1, &arg_typelib); - mode = CONST_PERSISTENT|CONST_CS; + zend_get_parameters(ht, 1, &arg_typelib); break; + case 2: - getParameters(ht, 2, &arg_typelib, &arg_cis); + zend_get_parameters(ht, 2, &arg_typelib, &arg_cis); convert_to_boolean_ex(&arg_cis); - if(arg_cis->value.lval) - { + if (arg_cis->value.lval) { mode &= ~CONST_CS; } + break; + default: - WRONG_PARAM_COUNT; + ZEND_WRONG_PARAM_COUNT(); } convert_to_string_ex(&arg_typelib); pTL = php_COM_find_typelib(Z_STRVAL_P(arg_typelib), mode TSRMLS_CC); - if(php_COM_load_typelib(pTL, mode TSRMLS_CC) == SUCCESS) - { + if (php_COM_load_typelib(pTL, mode TSRMLS_CC) == SUCCESS) { pTL->lpVtbl->Release(pTL); RETURN_TRUE; - } - else - { + } else { RETURN_FALSE; } } /* }}} */ + PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_reference) { zend_overloaded_element *overloaded_property; @@ -1245,22 +1145,19 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer /* fetch the IDispatch interface */ zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &comval_handle); obj = (comval *) zend_list_find(Z_LVAL_P(*comval_handle), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { return return_value; } ALLOC_COM(obj_prop); ALLOC_VARIANT(var_result); - for(element=property_reference->elements_list->head; element; element=element->next) - { + for (element=property_reference->elements_list->head; element; element=element->next) { overloaded_property = (zend_overloaded_element *) element->data; - switch(overloaded_property->type) - { + + switch (overloaded_property->type) { case OE_IS_ARRAY: - if(do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) - { + if (do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1269,8 +1166,7 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer break; case OE_IS_OBJECT: - if(do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) - { + if (do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1278,29 +1174,24 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer } break; - case OE_IS_METHOD: - { + case OE_IS_METHOD: { FREE_VARIANT(var_result); - if(obj != obj_prop) - { + if (obj != obj_prop) { FREE_COM(obj_prop); return_value = *object; ZVAL_ADDREF(&return_value); - } - else - { + } else { RETVAL_COM(obj); } + return return_value; } break; } - if(V_VT(var_result) == VT_DISPATCH) - { - if(V_DISPATCH(var_result) == NULL) - { + if (V_VT(var_result) == VT_DISPATCH) { + if (V_DISPATCH(var_result) == NULL) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1309,10 +1200,8 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer obj = obj_prop; php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC); - } - else - { - php_variant_to_pval(var_result, &return_value, FALSE, codepage TSRMLS_CC); + } else { + php_variant_to_pval(var_result, &return_value, codepage TSRMLS_CC); FREE_COM(obj_prop); obj_prop = NULL; @@ -1322,11 +1211,17 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer pval_destructor(&overloaded_property->element); } + if (obj_prop != NULL) { + RETVAL_COM(obj); + } + + FREE_VARIANT(var_result); return return_value; } + PHPAPI int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value) { pval result; @@ -1342,22 +1237,18 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere /* fetch the IDispatch interface */ zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &comval_handle); obj = (comval *)zend_list_find(Z_LVAL_P(*comval_handle), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { return FAILURE; } ALLOC_COM(obj_prop); ALLOC_VARIANT(var_result); - for(element=property_reference->elements_list->head; element != property_reference->elements_list->tail; element=element->next) - { + for (element=property_reference->elements_list->head; element != property_reference->elements_list->tail; element=element->next) { overloaded_property = (zend_overloaded_element *) element->data; - switch(overloaded_property->type) - { + switch (overloaded_property->type) { case OE_IS_ARRAY: - if(do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) - { + if (do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1366,8 +1257,7 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere break; case OE_IS_OBJECT: - if(do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) - { + if (do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1378,13 +1268,10 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere case OE_IS_METHOD: /* this shouldn't happen */ return FAILURE; - break; } - if(V_VT(var_result) == VT_DISPATCH) - { - if(V_DISPATCH(var_result) == NULL) - { + if (V_VT(var_result) == VT_DISPATCH) { + if (V_DISPATCH(var_result) == NULL) { FREE_VARIANT(var_result); FREE_COM(obj_prop); @@ -1393,9 +1280,7 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere obj = obj_prop; php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC); - } - else - { + } else { FREE_COM(obj_prop); FREE_VARIANT(var_result); @@ -1416,6 +1301,7 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere return SUCCESS; } + PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference) { pval property, **handle; @@ -1424,14 +1310,13 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro comval *obj; int type; - if(zend_llist_count(property_reference->elements_list)==1 - && !strcmp(Z_STRVAL(function_name->element), "com")) - { /* constructor */ + if (zend_llist_count(property_reference->elements_list)==1 + && !strcmp(Z_STRVAL(function_name->element), "com")) { + /* constructor */ pval *object_handle; PHP_FN(com_load)(INTERNAL_FUNCTION_PARAM_PASSTHRU); - if(!zend_is_true(return_value)) - { + if (!zend_is_true(return_value)) { ZVAL_FALSE(object); return; } @@ -1446,10 +1331,8 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro } property = php_COM_get_property_handler(property_reference); - if(property.type == IS_NULL) - { - if(property.refcount == 1) - { + if (property.type == IS_NULL) { + if (property.refcount == 1) { pval_destructor(&property); } pval_destructor(&function_name->element); @@ -1458,25 +1341,19 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro 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)) - { + if (!obj || (type != IS_COM)) { pval_destructor(&property); pval_destructor(&function_name->element); return; } - if(zend_llist_count(property_reference->elements_list)==1 - && !strcmp(Z_STRVAL_P(&function_name->element), "release")) - { + 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")) - { + } 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 - { + } else { pval **arguments; VARIANT *var_result; int arg_count = ZEND_NUM_ARGS(); @@ -1484,23 +1361,19 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro ALLOC_VARIANT(var_result); arguments = (pval **) emalloc(sizeof(pval *)*arg_count); - getParametersArray(ht, arg_count, arguments); + zend_get_parameters_array(ht, arg_count, arguments); - if(do_COM_invoke(obj , &function_name->element, var_result, arguments, arg_count TSRMLS_CC) == FAILURE) - { + if (do_COM_invoke(obj , &function_name->element, var_result, arguments, arg_count TSRMLS_CC) == FAILURE) { RETVAL_FALSE; - } - else - { - php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC); + } else { + php_variant_to_pval(var_result, return_value, codepage TSRMLS_CC); } FREE_VARIANT(var_result); efree(arguments); } - if(property.refcount == 1) - { + if (property.refcount == 1) { pval_destructor(&property); } pval_destructor(&function_name->element); @@ -1530,16 +1403,14 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) p = php_char_to_OLECHAR(search_string, strlen(search_string), codepage TSRMLS_CC); /* Is the string a GUID ? */ - if(!FAILED(CLSIDFromString(p, &clsid))) - { + 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)) - { + if ((major != NULL) && (minor != NULL)) { major_i = (WORD) atoi(major); minor_i = (WORD) atoi(minor); } @@ -1550,37 +1421,30 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) /* 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)) - { + if (FAILED(hr) && (!major || !minor)) { IDispatch *Dispatch; ITypeInfo *TypeInfo; int idx; - if(FAILED(CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID *) &Dispatch))) - { + 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))) - { + 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))) - { + 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))) - { + } 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 */ @@ -1601,51 +1465,41 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) /* at each version for a string match to the */ /* supplied argument */ - if(ERROR_SUCCESS != RegOpenKey(HKEY_CLASSES_ROOT, "TypeLib",&hkey)) - { + 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)) - { + 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)) - { + 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)) - { + 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)) - { + 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))) - { + 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)) - { + 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; @@ -1658,8 +1512,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) /* 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)) - { + if (2 != sscanf(version, "%d.%d", &major, &minor)) { major = 1; minor = 0; } @@ -1673,9 +1526,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) /* test for errors and leave through a single "return" */ return TypeLib; } - } - else - { + } else { /* Failed - perhaps too small abuffer */ /* But if too small, then the name does not match */ } @@ -1697,21 +1548,18 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) int i; int interfaces; - if(NULL == TypeLib) - { + if (NULL == TypeLib) { return FAILURE; } interfaces = TypeLib->lpVtbl->GetTypeInfoCount(TypeLib); TypeLib->lpVtbl->GetTypeComp(TypeLib, &TypeComp); - for(i=0; i<interfaces; i++) - { + for (i=0; i<interfaces; i++) { TYPEKIND pTKind; TypeLib->lpVtbl->GetTypeInfoType(TypeLib, i, &pTKind); - if(pTKind==TKIND_ENUM) - { + if (pTKind==TKIND_ENUM) { ITypeInfo *TypeInfo; VARDESC *pVarDesc; UINT NameCount; @@ -1721,7 +1569,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) char *EnumId; TypeLib->lpVtbl->GetDocumentation(TypeLib, i, &bstr_EnumId, NULL, NULL, NULL); - EnumId = php_OLECHAR_to_char(bstr_EnumId, NULL, 0, codepage); + EnumId = php_OLECHAR_to_char(bstr_EnumId, NULL, codepage); printf("Enumeration %d - %s:\n", i, EnumId); efree(EnumId); #endif @@ -1729,43 +1577,47 @@ 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; - char *ids; zend_constant c; zval exists, results; + char *const_name; TypeInfo->lpVtbl->GetNames(TypeInfo, pVarDesc->memid, &bstr_ids, 1, &NameCount); - if(NameCount!=1) - { + if (NameCount!=1) { j++; continue; } - ids = php_OLECHAR_to_char(bstr_ids, NULL, 1, codepage TSRMLS_CC); + const_name = php_OLECHAR_to_char(bstr_ids, &c.name_len, codepage TSRMLS_CC); + + c.name = zend_strndup(const_name, c.name_len); + c.name_len++; /* length should include the NULL */ + + efree(const_name); SysFreeString(bstr_ids); - c.name_len = strlen(ids)+1; - c.name = ids; - if (zend_get_constant(c.name, c.name_len-1, &exists TSRMLS_CC)) - { + + /* Before registering the contant, 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")) - { + if (!compare_function(&results, &c.value, &exists TSRMLS_CC) && INI_INT("com.autoregister_verbose")) { php_error(E_WARNING,"Type library value %s is already defined and has a different value", c.name); } - free(ids); + + free(c.name); j++; continue; } - php_variant_to_pval(pVarDesc->lpvarValue, &c.value, FALSE, codepage TSRMLS_CC); + php_variant_to_pval(pVarDesc->lpvarValue, &c.value, codepage TSRMLS_CC); + if (mode & CONST_PERSISTENT) { + zval_persist(&c.value TSRMLS_CC); + mode |= CONST_EFREE_PERSISTENT; + } c.flags = mode; - /* Before registering the contsnt, let's see if we can find it */ - { - zend_register_constant(&c TSRMLS_CC); - } + zend_register_constant(&c TSRMLS_CC); + j++; } TypeInfo->lpVtbl->Release(TypeInfo); @@ -1775,6 +1627,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) return SUCCESS; } + /* {{{ proto bool com_isenum(com_module obj) Grabs an IEnumVariant */ PHP_FUNCTION(com_isenum) @@ -1784,18 +1637,16 @@ PHP_FUNCTION(com_isenum) comval *obj; int type; - if(ZEND_NUM_ARGS() != 1) - { - WRONG_PARAM_COUNT; + if (ZEND_NUM_ARGS() != 1) { + ZEND_WRONG_PARAM_COUNT(); } - getParameters(ht, 1, &object); + zend_get_parameters(ht, 1, &object); /* obtain IDispatch interface */ zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &comval_handle); obj = (comval *) zend_list_find(Z_LVAL_PP(comval_handle), &type); - if(!obj || (type != IS_COM)) - { + if (!obj || (type != IS_COM)) { php_error(E_WARNING,"%s is not a COM object handler", ""); RETURN_FALSE; } @@ -1814,18 +1665,18 @@ static void php_register_COM_class(TSRMLS_D) zend_register_internal_class(&COM_class_entry TSRMLS_CC); } + PHP_MINIT_FUNCTION(COM) { - CoInitialize(NULL); le_comval = zend_register_list_destructors_ex(php_comval_destructor, NULL, "COM", module_number); php_register_COM_class(TSRMLS_C); REGISTER_INI_ENTRIES(); return SUCCESS; } + PHP_MSHUTDOWN_FUNCTION(COM) { - CoUninitialize(); UNREGISTER_INI_ENTRIES(); return SUCCESS; } |