]> granicus.if.org Git - php/commitdiff
merged from EXPERIMENTAL
authorHarald Radi <phanto@php.net>
Mon, 13 Aug 2001 23:39:11 +0000 (23:39 +0000)
committerHarald Radi <phanto@php.net>
Mon, 13 Aug 2001 23:39:11 +0000 (23:39 +0000)
lots of cleanup work

16 files changed:
ext/com/COM.c
ext/com/VARIANT.c
ext/com/com.h
ext/com/conversion.c
ext/com/conversion.h
ext/com/php_COM.h
ext/com/php_VARIANT.h
ext/com/variant.h
ext/rpc/com/com_wrapper.c
ext/rpc/com/com_wrapper.h
ext/rpc/com/conversion.c
ext/rpc/com/conversion.h
ext/rpc/com/php_com.h
ext/rpc/com/php_variant.h
ext/rpc/com/variant.c
ext/rpc/com/variant.h

index ee1fbc8c6cea4619ec5f4900674bdf50866daf74..0063f426b1834195ff21be7f407fbd0ba256e7df 100644 (file)
@@ -14,6 +14,7 @@
    +----------------------------------------------------------------------+
    | Author: Zeev Suraski <zeev@zend.com>                                 |
    |         Harald Radi  <h.radi@nme.at>                                 |
+   |         Alan Brown   <abrown@pobox.com>                              |
    +----------------------------------------------------------------------+
  */
 
 #include "php.h"
 #include "php_ini.h"
 
-#include "com.h"
-#include "conversion.h"
+#include "php_COM.h"
 #include "php_VARIANT.h"
 
-zend_class_entry com_class_entry;
-
-PHP_FUNCTION(com_load);
-PHP_FUNCTION(com_invoke);
-PHP_FUNCTION(com_addref);
-PHP_FUNCTION(com_release);
-PHP_FUNCTION(com_propget);
-PHP_FUNCTION(com_propput);
-PHP_FUNCTION(com_load_typelib);
-PHP_FUNCTION(com_isenum);
-
-PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR* pVarResult);
-PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId);
-PHPAPI HRESULT php_COM_release(comval *obj);
-PHPAPI HRESULT php_COM_addref(comval *obj);
-PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup);
-PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup);
-
-PHPAPI int php_COM_get_le_comval();
-static ITypeLib *php_COM_find_typelib(char *search_string, int mode);
+static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC);
 static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC);
+static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup TSRMLS_DC);
+static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup TSRMLS_DC);
+static void php_register_COM_class(TSRMLS_D);
 
 static int le_comval;
 static int codepage;
@@ -118,19 +102,22 @@ static PHP_MINFO_FUNCTION(COM)
        DISPLAY_INI_ENTRIES();
 }
 
-PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR*  pVarResult)
+PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR*  pVarResult, char **ErrString TSRMLS_DC)
 {
        HRESULT hr;
        int failed = FALSE;
+       unsigned int ArgErr;
+       EXCEPINFO ExceptInfo;
 
+       *ErrString = NULL;
        if(C_ISREFD(obj))
        {
                if(C_HASTLIB(obj))
                {
-                       hr = C_TYPEINFO_VT(obj)->Invoke(C_TYPEINFO(obj), C_DISPATCH(obj), dispIdMember, wFlags, pDispParams, pVarResult, NULL, NULL);
+                       hr = C_TYPEINFO_VT(obj)->Invoke(C_TYPEINFO(obj), C_DISPATCH(obj), dispIdMember, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr);
                        if(FAILED(hr))
                        {
-                               hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, NULL, NULL);
+                               hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr);
                                if(SUCCEEDED(hr))
                                {
                                        /*
@@ -145,7 +132,34 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS
                }
                else
                {
-                       hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, NULL, NULL);
+                       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;
+                               case DISP_E_PARAMNOTFOUND:
+                               case DISP_E_TYPEMISMATCH:
+                                       *ErrString = pemalloc(25, 1);
+                                       sprintf(*ErrString, "<b>Argument</b>: %d", pDispParams->cArgs-ArgErr+1);
+                                       break;
+                       }
                }
 
                return hr;
@@ -156,7 +170,7 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS
        }
 }
 
-PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId)
+PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId TSRMLS_DC)
 {
        HRESULT hr;
 
@@ -195,8 +209,10 @@ PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames
        }
 }
 
-PHPAPI HRESULT php_COM_release(comval *obj)
+PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC)
 {
+       HRESULT hr;
+       
        if(obj->refcount > 1)
        {
                C_RELEASE(obj);
@@ -209,16 +225,16 @@ PHPAPI HRESULT php_COM_release(comval *obj)
                }
                if(C_HASENUM(obj))
                {
-                       C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj));
+                       hr = C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj));
                }
-               C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj));
+               hr = C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj));
                C_RELEASE(obj);
        }
 
        return obj->refcount;
 }
 
-PHPAPI HRESULT php_COM_addref(comval *obj)
+PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC)
 {
        if(C_ISREFD(obj))
        {
@@ -228,13 +244,19 @@ PHPAPI HRESULT php_COM_addref(comval *obj)
        return obj->refcount;
 }
 
-PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup)
+PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup TSRMLS_DC)
 {
        HRESULT hr = 1;
        DISPPARAMS dispparams;
-       VARIANT var_result;
+       VARIANT *var_result;
+       IDispatch FAR* pDisp;
 
-       VariantInit(&var_result);
+       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)));
@@ -244,22 +266,26 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup)
        dispparams.cArgs = 0;
        dispparams.cNamedArgs = 0;
 
+       ALLOC_VARIANT(var_result);
+
        if(C_HASENUM(obj) = SUCCEEDED(C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), DISPID_NEWENUM, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
-                                                                       DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, &var_result, NULL, NULL)))
+                                                                       DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result, NULL, NULL)))
        {
-               if (V_VT(&var_result) == VT_UNKNOWN)
+               if(V_VT(var_result) == VT_UNKNOWN)
                {
-                   C_HASENUM(obj) = SUCCEEDED(V_UNKNOWN(&var_result)->lpVtbl->QueryInterface(V_UNKNOWN(&var_result), &IID_IEnumVARIANT,
+                   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,
+                   C_HASENUM(obj) = SUCCEEDED(V_DISPATCH(var_result)->lpVtbl->QueryInterface(V_DISPATCH(var_result), &IID_IEnumVARIANT,
                                                                        (void**)&C_ENUMVARIANT(obj)));
                }
 
        }
 
+       FREE_VARIANT(var_result);
+
        if(!cleanup)
        {
                hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj));
@@ -272,7 +298,7 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup)
        return hr;
 }
 
-PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup)
+PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup TSRMLS_DC)
 {
        HRESULT hr;
 
@@ -307,7 +333,7 @@ PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup)
        return hr;
 }
 
-PHPAPI char *php_COM_error_message(HRESULT hr)
+PHPAPI char *php_COM_error_message(HRESULT hr TSRMLS_DC)
 {
        void *pMsgBuf;
 
@@ -323,28 +349,35 @@ PHPAPI char *php_COM_error_message(HRESULT hr)
        return pMsgBuf;
 }
 
-static char *php_string_from_clsid(const CLSID *clsid)
+static char *php_string_from_clsid(const CLSID *clsid TSRMLS_DC)
 {
        LPOLESTR ole_clsid;
        char *clsid_str;
 
        StringFromCLSID(clsid, &ole_clsid);
-       clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, 0, codepage);
+       clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, 0, codepage TSRMLS_CC);
        LocalFree(ole_clsid);
 
        return clsid_str;
 }
 
-static void php_comval_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC)
 {
-       comval *obj = (comval *)rsrc->ptr;
+       HRESULT hr = S_OK;
 
        if(C_ISREFD(obj)) 
        {
                C_REFCOUNT(obj) = 1;
-               php_COM_release(obj);
+               hr = php_COM_release(obj TSRMLS_CC);
        }
        efree(obj);
+
+       return hr;
+}
+
+static void php_comval_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+       php_COM_destruct(rsrc->ptr TSRMLS_CC);
 }
 
 static PHP_INI_MH(OnTypelibFileChange)
@@ -353,7 +386,6 @@ static PHP_INI_MH(OnTypelibFileChange)
        char *typelib_name_buffer;
        char *strtok_buf = NULL;
        int interactive;
-
        interactive = CG(interactive);
 
        if(!new_value || (typelib_file = VCWD_FOPEN(new_value, "r"))==NULL)
@@ -407,12 +439,12 @@ static PHP_INI_MH(OnTypelibFileChange)
                        ptr--;
                }
 
-
                if(interactive)
                {
                        printf("\rLoading %-60s\r", typelib_name);
                }
-               if((pTL = php_COM_find_typelib(typelib_name, mode)) != 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);
@@ -507,9 +539,9 @@ PHP_FUNCTION(com_load)
                }
        }
 
+       ALLOC_COM(obj);
        convert_to_string_ex(&module_name);
-       ProgID = php_char_to_OLECHAR(Z_STRVAL_P(module_name), Z_STRLEN_P(module_name), codepage);
-       obj = (comval *) emalloc(sizeof(comval));
+       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)))
@@ -542,9 +574,9 @@ PHP_FUNCTION(com_load)
                
                if(FAILED(hr))
                {
-                       efree(obj);
-                       error_message = php_COM_error_message(hr);  
-                       php_error(E_WARNING, "Invalid ProgID or Moniker:  %s\n", error_message);
+                       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;
                }
@@ -564,7 +596,7 @@ PHP_FUNCTION(com_load)
 
                        server_info.dwReserved1=0;
                        server_info.dwReserved2=0;
-                       server_info.pwszName = php_char_to_OLECHAR(Z_STRVAL_P(server_name), Z_STRLEN_P(server_name), codepage);
+                       server_info.pwszName = php_char_to_OLECHAR(Z_STRVAL_P(server_name), Z_STRLEN_P(server_name), codepage TSRMLS_CC);
                        server_info.pAuthInfo=NULL;
 
                        pResults.pIID = &IID_IDispatch;
@@ -581,17 +613,17 @@ PHP_FUNCTION(com_load)
 
                if(FAILED(hr))
                {
-                       error_message = php_COM_error_message(hr);
-                       clsid_str = php_string_from_clsid(&clsid);
-                       php_error(E_WARNING, "Unable to obtain IDispatch interface for CLSID %s:  %s", clsid_str, error_message);
+                       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);
                        LocalFree(error_message);
                        efree(clsid_str);
-                       efree(obj);
+                       php_COM_destruct(obj TSRMLS_CC);
                        RETURN_FALSE;
                }
        }
 
-       php_COM_set(obj, C_DISPATCH(obj), TRUE);
+       php_COM_set(obj, &C_DISPATCH(obj), TRUE TSRMLS_CC);
 
        if(INI_INT("com.autoregister_casesensitive"))
        {
@@ -617,7 +649,7 @@ PHP_FUNCTION(com_load)
                {
                        ITypeLib *pTL;
 
-                       if((pTL = php_COM_find_typelib(Z_STRVAL_P(typelib), mode)) != 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 */
@@ -635,7 +667,7 @@ PHP_FUNCTION(com_load)
 /* }}} */
 
 
-int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **arguments, int arg_count)
+int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **arguments, int arg_count TSRMLS_DC)
 {
        DISPID dispid;
        HRESULT hr;
@@ -667,8 +699,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                                break;
 
                        default:
-                               /* TODO: complain about wrong arg count */
-                               php_error(E_WARNING, "Wrong argument count to IEnumVariant::Next()\n");
+                               php_error(E_WARNING,"Wrong argument count to IEnumVariant::Next()");
 
                                return FAILURE;
                }
@@ -679,6 +710,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                if((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL)
                {
                        VariantInit(var_result);
+
                        return FAILURE;
                }
                else
@@ -689,11 +721,10 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
 
                if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Next(C_ENUMVARIANT(obj), count, pSA->pvData, &count)))
                {
-                       char *error_message = php_COM_error_message(hr);
-                       php_error(E_WARNING, "IEnumVariant::Next() failed:  %s\n", error_message);
+                       char *error_message = php_COM_error_message(hr TSRMLS_CC);
+                       php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message);
                        efree(error_message);
-                       SafeArrayDestroy(pSA);
-                       VariantInit(var_result);
+                       VariantClear(var_result);
                        return FAILURE;
                }
 
@@ -702,11 +733,10 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                        rgsabound[0].cElements = count;
                        if(FAILED(SafeArrayRedim(pSA, rgsabound)))
                        {
-                               char *error_message = php_COM_error_message(hr);
-                               php_error(E_WARNING, "IEnumVariant::Next() failed:  %s\n", error_message);
+                               char *error_message = php_COM_error_message(hr TSRMLS_CC);
+                               php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message);
                                efree(error_message);
-                               SafeArrayDestroy(pSA);
-                               VariantInit(var_result);
+                               VariantClear(var_result);
                                return FAILURE;
                        }
                }
@@ -717,8 +747,8 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
        {
                if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Reset(C_ENUMVARIANT(obj))))
                {
-                       char *error_message = php_COM_error_message(hr);
-                       php_error(E_WARNING, "IEnumVariant::Next() failed:  %s\n", error_message);
+                       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;
                }
@@ -740,13 +770,13 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                                break;
 
                        default:
-                               php_error(E_WARNING, "Wrong argument count to IEnumVariant::Skip()\n");
+                               php_error(E_WARNING,"Wrong argument count to IEnumVariant::Skip()");
                                return FAILURE;
                }
                if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Skip(C_ENUMVARIANT(obj), count)))
                {
-                       char *error_message = php_COM_error_message(hr);
-                       php_error(E_WARNING, "IEnumVariant::Next() failed:  %s\n", error_message);
+                       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;
                }
@@ -755,14 +785,16 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
        }
        else
        {
-               funcname = php_char_to_OLECHAR(Z_STRVAL_P(function_name), Z_STRLEN_P(function_name), codepage);
+               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);
+               hr = php_COM_get_ids_of_names(obj, &funcname, &dispid TSRMLS_CC);
 
                if(FAILED(hr))
                {
-                       error_message = php_COM_error_message(hr);
-                       php_error(E_WARNING, "Unable to lookup %s:  %s\n", Z_STRVAL_P(function_name), error_message);
+                       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);
                        efree(funcname);
                        return FAILURE;
@@ -773,7 +805,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                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);
+                       php_pval_to_variant(arguments[current_arg], &variant_args[current_variant], codepage TSRMLS_CC);
                }
 
                dispparams.rgvarg = variant_args;
@@ -781,15 +813,27 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                dispparams.cArgs = arg_count;
                dispparams.cNamedArgs = 0;
 
-               hr = php_COM_invoke(obj, dispid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result);
+               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]);
+               }
                efree(variant_args);
 
                if(FAILED(hr))
                {
-                       error_message = php_COM_error_message(hr);
-                       php_error(E_WARNING, "Invoke() failed:  %s\n", error_message);
+                       error_message = php_COM_error_message(hr TSRMLS_CC);
+                       if (ErrString)
+                       {
+                               php_error(E_WARNING,"Invoke() failed: %s %s", error_message, ErrString);
+                               pefree(ErrString, 1);
+                       }
+                       else
+                       {
+                               php_error(E_WARNING,"Invoke() failed: %s", error_message);
+                       }
                        LocalFree(error_message);
                        return FAILURE;
                }
@@ -807,14 +851,14 @@ PHP_FUNCTION(com_invoke)
        comval *obj;
        int type;
        int arg_count = ZEND_NUM_ARGS();
-       VARIANT var_result;
+       VARIANT *var_result;
 
        if(arg_count<2)
        {
                WRONG_PARAM_COUNT;
        }
        arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
-       if(getParametersArray(ht, arg_count, arguments)==FAILURE)
+       if(getParametersArray(ht, arg_count, arguments) == FAILURE)
        {
                RETURN_FALSE;
        }
@@ -827,20 +871,27 @@ PHP_FUNCTION(com_invoke)
        obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%d is not a COM object handler", Z_STRVAL_P(function_name));
+               php_error(E_WARNING,"%d is not a COM object handler", Z_STRVAL_P(function_name));
                RETURN_FALSE;
        }
 
        /* obtain property/method handler */
        convert_to_string_ex(&function_name);
 
-       if(do_COM_invoke(obj, function_name, &var_result, arguments+2, arg_count-2)==FAILURE)
+       ALLOC_VARIANT(var_result);
+
+       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;
        }
-       efree(arguments);
 
-       php_variant_to_pval(&var_result, return_value, 0, codepage);
+       php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC);
+
+       FREE_VARIANT(var_result);
+       efree(arguments);
 }
 /* }}} */
 
@@ -868,11 +919,11 @@ PHP_FUNCTION(com_release)
        obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%d is not a COM object handler");
+               php_error(E_WARNING,"%d is not a COM object handler");
                RETURN_FALSE;
        }
 
-       RETURN_LONG(php_COM_release(obj))
+       RETURN_LONG(php_COM_release(obj TSRMLS_CC))
 }
 /* }}} */
 
@@ -900,53 +951,52 @@ PHP_FUNCTION(com_addref)
        obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%d is not a COM object handler");
+               php_error(E_WARNING,"%d is not a COM object handler");
                RETURN_FALSE;
        }
 
-       RETURN_LONG(php_COM_addref(obj));
+       RETURN_LONG(php_COM_addref(obj TSRMLS_CC));
 }
 /* }}} */
 
-static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup)
+static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup TSRMLS_DC)
 {
        pval function_name;
        int retval;
 
        ZVAL_STRINGL(&function_name, "Item", 4, 0);
-       retval = do_COM_invoke(array, &function_name, result, &property, 1);
+       retval = do_COM_invoke(array, &function_name, result, &property, 1 TSRMLS_CC);
        if(cleanup)
        {
-               php_COM_release(array);
-               efree(array);
+               php_COM_destruct(array TSRMLS_CC);
        }
 
        return retval;
 }
 
-static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup)
+static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup TSRMLS_DC)
 {
        DISPID dispid;
        HRESULT hr;
        OLECHAR *propname;
        char *error_message;
        DISPPARAMS dispparams;
-
+       char *ErrString;
 
        /* obtain property handler */
-       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage);
+       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage TSRMLS_CC);
 
-       hr = php_COM_get_ids_of_names(obj, &propname, &dispid);
+       hr = php_COM_get_ids_of_names(obj, &propname, &dispid TSRMLS_CC);
 
        if(FAILED(hr))
        {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING, "Unable to lookup %s:  %s\n", Z_STRVAL_P(arg_property), error_message);
+               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)
                {
-                       php_COM_release(obj);
+                       php_COM_destruct(obj TSRMLS_CC);
                }
                return FAILURE;
        }
@@ -954,17 +1004,25 @@ static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property,
        dispparams.cArgs = 0;
        dispparams.cNamedArgs = 0;
 
-       hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result);
+       hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC);
 
        if(FAILED(hr))
        {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING, "PropGet() failed:  %s\n", error_message);
+               error_message = php_COM_error_message(hr TSRMLS_CC);
+               if (ErrString)
+               {
+                       php_error(E_WARNING,"PropGet() failed: %s %s", error_message, ErrString);
+                       pefree(ErrString, 1);
+               }
+               else
+               {
+                       php_error(E_WARNING,"PropGet() failed: %s", error_message);
+               }
                LocalFree(error_message);
                efree(propname);
                if(cleanup)
                {
-                       php_COM_release(obj);
+                       php_COM_destruct(obj TSRMLS_CC);
                }
                return FAILURE;
        }
@@ -972,65 +1030,81 @@ static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property,
        efree(propname);
        if(cleanup)
        {
-               php_COM_release(obj);
+               php_COM_destruct(obj TSRMLS_CC);
        }
        return SUCCESS;
 }
 
 
-static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, pval *value)
+static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, pval *value TSRMLS_DC)
 {
        DISPID dispid;
        HRESULT hr;
        OLECHAR *propname;
        char *error_message;
-       VARIANT *var_result;
+       VARIANT *var_result, *new_value;
        DISPPARAMS dispparams;
-       VARIANT new_value;
        DISPID mydispid = DISPID_PROPERTYPUT;
-
+       char *ErrString;
 
        ALLOC_VARIANT(var_result);
+       ALLOC_VARIANT(new_value);
 
        /* obtain property handler */
-       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage);
+       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage TSRMLS_CC);
 
-       hr = php_COM_get_ids_of_names(obj, &propname, &dispid);
+       hr = php_COM_get_ids_of_names(obj, &propname, &dispid TSRMLS_CC);
 
        if(FAILED(hr))
        {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING, "Unable to lookup %s:  %s\n", Z_STRVAL_P(arg_property), error_message);
+               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);
+
+               FREE_VARIANT(var_result);
+               FREE_VARIANT(new_value);
+
                RETURN_FALSE;
        }
 
-       php_pval_to_variant(value, &new_value, codepage);
-       dispparams.rgvarg = &new_value;
+       php_pval_to_variant(value, new_value, codepage TSRMLS_CC);
+       dispparams.rgvarg = new_value;
        dispparams.rgdispidNamedArgs = &mydispid;
        dispparams.cArgs = 1;
        dispparams.cNamedArgs = 1;
 
-       hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYPUT, &dispparams, NULL);
+       hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYPUT, &dispparams, NULL, &ErrString TSRMLS_CC);
 
        if(FAILED(hr))
        {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING, "PropPut() failed:  %s\n", error_message);
+               error_message = php_COM_error_message(hr TSRMLS_CC);
+               if (ErrString)
+               {
+                       php_error(E_WARNING,"PropPut() failed: %s %s", error_message, ErrString);
+                       pefree(ErrString, 1);
+               }
+               else
+               {
+                       php_error(E_WARNING,"PropPut() failed: %s", error_message);
+               }
                LocalFree(error_message);
                efree(propname);
+
+               FREE_VARIANT(var_result);
+               FREE_VARIANT(new_value);
+
                RETURN_FALSE;
        }
 
        dispparams.cArgs = 0;
        dispparams.cNamedArgs = 0;
 
-       hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result);
+       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, 0, codepage);
+               php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC);
        }
        else
        {
@@ -1038,7 +1112,14 @@ static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property,
                zval_copy_ctor(return_value);
        }
 
-       efree(var_result);
+       if (ErrString)
+       {
+               pefree(ErrString, 1);
+       }
+
+       FREE_VARIANT(var_result);
+       FREE_VARIANT(new_value);
+
        efree(propname);
 }
 
@@ -1050,9 +1131,9 @@ PHP_FUNCTION(com_propget)
        pval *arg_comval, *arg_property;
        int type;
        comval *obj;
-       VARIANT var_result;
+       VARIANT *var_result;
 
-       if(ZEND_NUM_ARGS()!=2 || getParameters(ht, 2, &arg_comval, &arg_property)==FAILURE)
+       if((ZEND_NUM_ARGS() != 2) || (getParameters(ht, 2, &arg_comval, &arg_property) == FAILURE))
        {
                WRONG_PARAM_COUNT;
        }
@@ -1062,15 +1143,21 @@ PHP_FUNCTION(com_propget)
        obj = (comval *)zend_list_find(Z_LVAL_P(arg_comval), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%d is not a COM object handler", Z_LVAL_P(arg_comval));
+               php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_comval));
        }
        convert_to_string_ex(&arg_property);
 
-       if(do_COM_propget(&var_result, obj, arg_property, 0)==FAILURE)
+       ALLOC_VARIANT(var_result);
+
+       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, 0, codepage);
+
+       php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC);
+
+       FREE_VARIANT(var_result);
 }
 /* }}} */
 
@@ -1094,11 +1181,11 @@ PHP_FUNCTION(com_propput)
        obj = (comval *)zend_list_find(Z_LVAL_P(arg_comval), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%d is not a COM object handler", Z_LVAL_P(arg_comval));
+               php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_comval));
        }
        convert_to_string_ex(&arg_property);
 
-       do_COM_propput(return_value, obj, arg_property, arg_value);
+       do_COM_propput(return_value, obj, arg_property, arg_value TSRMLS_CC);
 }
 /* }}} */
 
@@ -1127,7 +1214,7 @@ PHP_FUNCTION(com_load_typelib)
        }
 
        convert_to_string_ex(&arg_typelib);
-       pTL = php_COM_find_typelib(Z_STRVAL_P(arg_typelib), mode);
+       pTL = php_COM_find_typelib(Z_STRVAL_P(arg_typelib), mode TSRMLS_CC);
        if(php_COM_load_typelib(pTL, mode TSRMLS_CC) == SUCCESS)
        {
                pTL->lpVtbl->Release(pTL);
@@ -1169,38 +1256,42 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer
        for(element=property_reference->elements_list->head; element; element=element->next)
        {
                overloaded_property = (zend_overloaded_element *) element->data;
-               VariantInit(var_result);
                switch(overloaded_property->type)
                {
                        case OE_IS_ARRAY:
-                               if(do_COM_offget(var_result, obj, &overloaded_property->element, FALSE) == FAILURE)
+                               if(do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE)
                                {
-                                       efree(var_result);
-                                       efree(obj_prop);
+                                       FREE_VARIANT(var_result);
+                                       FREE_COM(obj_prop);
+
                                        return return_value;
                                }
                                break;
 
                        case OE_IS_OBJECT:
-                               if(do_COM_propget(var_result, obj, &overloaded_property->element, FALSE) == FAILURE)
+                               if(do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE)
                                {
-                                       efree(var_result);
-                                       efree(obj_prop);
+                                       FREE_VARIANT(var_result);
+                                       FREE_COM(obj_prop);
+
                                        return return_value;
                                }
                                break;
 
                        case OE_IS_METHOD:
                                {
+                                       FREE_VARIANT(var_result);
                                        if(obj != obj_prop)
                                        {
-                                               efree(obj_prop);
+                                               FREE_COM(obj_prop);
+       
                                                return_value = *object;
                                                ZVAL_ADDREF(&return_value);
                                        }
-
-                                       efree(var_result);              
-
+                                       else
+                                       {
+                                               RETVAL_COM(obj);
+                                       }
                                        return return_value;
                                }
                                break;
@@ -1210,26 +1301,28 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer
                {
                        if(V_DISPATCH(var_result) == NULL)
                        {
-                               efree(var_result);
-                               efree(obj_prop);
+                               FREE_VARIANT(var_result);
+                               FREE_COM(obj_prop);
+                               
                                return return_value;
                        }
 
                        obj = obj_prop;
-                       php_COM_set(obj, V_DISPATCH(var_result), TRUE);
-
-                       RETVAL_COM(obj);
+                       php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC);
                }
                else
                {
-                       efree(obj_prop);
+                       php_variant_to_pval(var_result, &return_value, FALSE, codepage TSRMLS_CC);
+
+                       FREE_COM(obj_prop);
                        obj_prop = NULL;
-                       php_variant_to_pval(var_result, &return_value, FALSE, codepage);
                }
 
+               VariantInit(var_result);        // to protect C_DISPATCH(obj) from being freed when var_result is destructed
                pval_destructor(&overloaded_property->element);
        }
-       efree(var_result);              
+
+       FREE_VARIANT(var_result);              
 
        return return_value;
 }
@@ -1241,9 +1334,9 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere
        zend_llist_element *element;
        pval **comval_handle;
        pval *object = property_reference->object;
-       comval *obj;
+       comval *obj, *obj_prop;
        int type;
-       VARIANT var_result;
+       VARIANT *var_result;
        TSRMLS_FETCH();
 
        /* fetch the IDispatch interface */
@@ -1253,46 +1346,72 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere
        {
                return FAILURE;
        }
-       var_result.vt = VT_DISPATCH;
-       var_result.pdispVal = C_DISPATCH(obj);
+       
+       ALLOC_COM(obj_prop);
+       ALLOC_VARIANT(var_result);
 
-       for(element=property_reference->elements_list->head; element && 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)
                {
                        case OE_IS_ARRAY:
-                               break;
-                       case OE_IS_OBJECT:
-                               if(V_VT(&var_result) != VT_DISPATCH)
+                               if(do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE)
                                {
+                                       FREE_VARIANT(var_result);
+                                       FREE_COM(obj_prop);
+
                                        return FAILURE;
                                }
-                               else
+                               break;
+
+                       case OE_IS_OBJECT:
+                               if(do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE)
                                {
-                                       do_COM_propget(&var_result, obj, &overloaded_property->element, element!=property_reference->elements_list->head);
+                                       FREE_VARIANT(var_result);
+                                       FREE_COM(obj_prop);
+
+                                       return FAILURE;
                                }
                                break;
+
                        case OE_IS_METHOD:
                                /* this shouldn't happen */
                                return FAILURE;
+                               break;
                }
 
-               pval_destructor(&overloaded_property->element);
-       }
+               if(V_VT(var_result) == VT_DISPATCH)
+               {
+                       if(V_DISPATCH(var_result) == NULL)
+                       {
+                               FREE_VARIANT(var_result);
+                               FREE_COM(obj_prop);
 
-       if(V_VT(&var_result) != VT_DISPATCH)
-       {
-               return FAILURE;
-       }
-       obj = (comval *) emalloc(sizeof(comval));
-       C_HASTLIB(obj) = FALSE;
-       C_DISPATCH(obj) = V_DISPATCH(&var_result);
+                               return FAILURE;
+                       }
+
+                       obj = obj_prop;
+                       php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC);
+               }
+               else
+               {
+                       FREE_COM(obj_prop);
+                       FREE_VARIANT(var_result);
 
+                       return FAILURE;
+               }
+
+               VariantInit(var_result);        // to protect C_DISPATCH(obj) from being freed when var_result is destructed
+               pval_destructor(&overloaded_property->element);
+       }
+       FREE_VARIANT(var_result);
+       
        overloaded_property = (zend_overloaded_element *) element->data;
-       do_COM_propput(&result, obj, &overloaded_property->element, value);
+       do_COM_propput(&result, obj, &overloaded_property->element, value TSRMLS_CC);
+       FREE_COM(obj_prop);
+
        pval_destructor(&overloaded_property->element);
-       efree(obj);
 
        return SUCCESS;
 }
@@ -1349,12 +1468,12 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
        if(zend_llist_count(property_reference->elements_list)==1
           && !strcmp(Z_STRVAL_P(&function_name->element), "release"))
        {
-               RETVAL_LONG(php_COM_release(obj));
+               RETVAL_LONG(php_COM_release(obj TSRMLS_CC));
        }
        else if(zend_llist_count(property_reference->elements_list)==1
                        && !strcmp(Z_STRVAL_P(&function_name->element), "addref"))
        {
-               RETVAL_LONG(php_COM_addref(obj));
+               RETVAL_LONG(php_COM_addref(obj TSRMLS_CC));
        }
        else
        {
@@ -1363,22 +1482,21 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
                int arg_count = ZEND_NUM_ARGS();
 
                ALLOC_VARIANT(var_result);
-               VariantInit(var_result);
 
                arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
                getParametersArray(ht, arg_count, arguments);
 
-               if(do_COM_invoke(obj , &function_name->element, var_result, arguments, arg_count)==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, 0, codepage);
+                       php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC);
                }
 
+               FREE_VARIANT(var_result);
                efree(arguments);
-               efree(var_result);
        }
 
        if(property.refcount == 1)
@@ -1388,7 +1506,7 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
        pval_destructor(&function_name->element);
 }
 
-static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
+static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC)
 {
        ITypeLib *TypeLib = NULL;
        char *strtok_buf, *major, *minor;
@@ -1409,7 +1527,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
        major = php_strtok_r(NULL, ",", &strtok_buf);
        minor = php_strtok_r(NULL, ",", &strtok_buf);
 
-       p = php_char_to_OLECHAR(search_string, strlen(search_string), codepage);
+       p = php_char_to_OLECHAR(search_string, strlen(search_string), codepage TSRMLS_CC);
        /* Is the string a GUID ? */
 
        if(!FAILED(CLSIDFromString(p, &clsid)))
@@ -1483,7 +1601,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
                        /* 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;
@@ -1548,7 +1666,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
                                                        str = emalloc(strlen(keyname)+strlen(version)+20); /* 18 == safety, 2 == extra comma and \0 */
                                                        sprintf(str, "%s,%d,%d", keyname, major, minor);
                                                        efree(keyname);
-                                                       TypeLib = php_COM_find_typelib(str, mode);
+                                                       TypeLib = php_COM_find_typelib(str, mode TSRMLS_CC);
                                                        efree(str);
                                                        /* This is probbaly much harder to read and follow */
                                                        /* But it is MUCH more effiecient than trying to */
@@ -1611,7 +1729,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC)
                        TypeLib->lpVtbl->GetTypeInfo(TypeLib, i, &TypeInfo);
 
                        j=0;
-                       while(TypeInfo->lpVtbl->GetVarDesc(TypeInfo, j, &pVarDesc)==S_OK)
+                       while(SUCCEEDED(TypeInfo->lpVtbl->GetVarDesc(TypeInfo, j, &pVarDesc)))
                        {
                                BSTR bstr_ids;
                                char *ids;
@@ -1624,7 +1742,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC)
                                        j++;
                                        continue;
                                }
-                               ids = php_OLECHAR_to_char(bstr_ids, NULL, 1, codepage);
+                               ids = php_OLECHAR_to_char(bstr_ids, NULL, 1, codepage TSRMLS_CC);
                                SysFreeString(bstr_ids);
                                c.name_len = strlen(ids)+1;
                                c.name = ids;
@@ -1634,14 +1752,14 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC)
                                        /* Check to see if they are the same */
                                        if (!compare_function(&results, &c.value, &exists TSRMLS_CC) && INI_INT("com.autoregister_verbose"))
                                        {
-                                               php_error(E_WARNING, "Type library value %s is already defined and has a different value", c.name);
+                                               php_error(E_WARNING,"Type library value %s is already defined and has a different value", c.name);
                                        }
                                        free(ids);
                                        j++;
                                        continue;
                                }
 
-                               php_variant_to_pval(pVarDesc->lpvarValue, &c.value, FALSE, codepage);
+                               php_variant_to_pval(pVarDesc->lpvarValue, &c.value, FALSE, codepage TSRMLS_CC);
                                c.flags = mode;
 
                                /* Before registering the contsnt, let's see if we can find it */
@@ -1678,7 +1796,7 @@ PHP_FUNCTION(com_isenum)
        obj = (comval *) zend_list_find(Z_LVAL_PP(comval_handle), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%s is not a COM object handler", "");
+               php_error(E_WARNING,"%s is not a COM object handler", "");
                RETURN_FALSE;
        }
 
@@ -1686,14 +1804,14 @@ PHP_FUNCTION(com_isenum)
 }
 /* }}} */
 
-void php_register_COM_class(TSRMLS_D)
+static void php_register_COM_class(TSRMLS_D)
 {
-       INIT_OVERLOADED_CLASS_ENTRY(com_class_entry, "COM", NULL,
+       INIT_OVERLOADED_CLASS_ENTRY(COM_class_entry, "COM", NULL,
                                                                php_COM_call_function_handler,
                                                                php_COM_get_property_handler,
                                                                php_COM_set_property_handler);
 
-       zend_register_internal_class(&com_class_entry TSRMLS_CC);
+       zend_register_internal_class(&COM_class_entry TSRMLS_CC);
 }
 
 PHP_MINIT_FUNCTION(COM)
index 5d61100d64c4194a91c17972047aa4861c1072dc..b8f2590101d77660ec0813e22dfda9bbfae3470a 100644 (file)
 
 #include "php.h"
 #include "php_ini.h"
-#include "variant.h"
-#include "conversion.h"
 #include "ext/standard/info.h"
+#include "php_VARIANT.h"
 
 #include <unknwn.h> 
 
-PHP_MINIT_FUNCTION(VARIANT);
-PHP_MSHUTDOWN_FUNCTION(VARIANT);
-
-int php_VARIANT_get_le_variant();
-void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
-pval php_VARIANT_get_property_handler(zend_property_reference *property_reference);
-static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value);
-void php_register_VARIANT_class(TSRMLS_D);
-static void php_variant_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
+static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value TSRMLS_DC);
+static int php_VARIANT_set_property_handler(zend_property_reference *property_reference, pval *value);
+static pval php_VARIANT_get_property_handler(zend_property_reference *property_reference);
+static void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
+static void php_VARIANT_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
+static void php_register_VARIANT_class(TSRMLS_D);
 
 static int le_variant;
 static int codepage;
-
 static zend_class_entry VARIANT_class_entry;
 
 function_entry VARIANT_functions[] = {
@@ -66,7 +61,7 @@ zend_module_entry VARIANT_module_entry = {
 
 PHP_MINIT_FUNCTION(VARIANT)
 {
-       le_variant = zend_register_list_destructors_ex(php_variant_destructor, NULL, "VARIANT", module_number);
+       le_variant = zend_register_list_destructors_ex(php_VARIANT_destructor, NULL, "VARIANT", module_number);
 
        /* variant datatypes */
        REGISTER_LONG_CONSTANT("VT_NULL", VT_NULL, CONST_CS | CONST_PERSISTENT);
@@ -97,10 +92,18 @@ PHP_MINIT_FUNCTION(VARIANT)
        REGISTER_LONG_CONSTANT("CP_ACP", CP_ACP, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("CP_MACCP", CP_MACCP, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("CP_OEMCP", CP_OEMCP, CONST_CS | CONST_PERSISTENT);
-       REGISTER_LONG_CONSTANT("CP_SYMBOL", CP_SYMBOL, CONST_CS | CONST_PERSISTENT);
-       REGISTER_LONG_CONSTANT("CP_THREAD_ACP", CP_THREAD_ACP, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("CP_UTF7", CP_UTF7, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("CP_UTF8", CP_UTF8, CONST_CS | CONST_PERSISTENT);
+#ifdef CP_SYMBOL
+       REGISTER_LONG_CONSTANT("CP_SYMBOL", CP_SYMBOL, CONST_CS | CONST_PERSISTENT);
+#else
+#      error   "CP_SYMBOL undefined"
+#endif
+#ifdef CP_THREAD_ACP
+       REGISTER_LONG_CONSTANT("CP_THREAD_ACP", CP_THREAD_ACP, CONST_CS | CONST_PERSISTENT);
+#else
+#      error   "CP_THREAD_ACP undefined"
+#endif
 
        php_register_VARIANT_class(TSRMLS_C);
        return SUCCESS;
@@ -111,12 +114,12 @@ PHP_MSHUTDOWN_FUNCTION(VARIANT)
        return SUCCESS;
 }
 
-int php_VARIANT_get_le_variant()
+PHPAPI int php_VARIANT_get_le_variant()
 {
        return le_variant;
 }
 
-void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
+static void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
 {
        pval *object = property_reference->object;
        zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data;
@@ -137,17 +140,17 @@ void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_proper
                                break;
                        case 1:
                                getParameters(ht, 1, &data);
-                               php_pval_to_variant(data, pVar, codepage);
+                               php_pval_to_variant(data, pVar, codepage TSRMLS_CC);
                                codepage = CP_ACP;
                                break;
                        case 2:
                                getParameters(ht, 2, &data, &type);
-                               php_pval_to_variant_ex(data, pVar, type, codepage);
+                               php_pval_to_variant_ex(data, pVar, type, codepage TSRMLS_CC);
                                codepage = CP_ACP;
                                break;
                        case 3:
                                getParameters(ht, 3, &data, &type, &code_page);
-                               php_pval_to_variant_ex(data, pVar, type, codepage);
+                               php_pval_to_variant_ex(data, pVar, type, codepage TSRMLS_CC);
                                convert_to_long(code_page);
                                codepage = code_page->value.lval;
                                break;
@@ -173,14 +176,14 @@ void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_proper
        }
 }
 
-
-pval php_VARIANT_get_property_handler(zend_property_reference *property_reference)
+static pval php_VARIANT_get_property_handler(zend_property_reference *property_reference)
 {
        zend_overloaded_element *overloaded_property;
        int type;
+       TSRMLS_FETCH();
+
        pval result, **var_handle, *object = property_reference->object;
        VARIANT *var_arg;
-       TSRMLS_FETCH();
 
        /* fetch the VARIANT structure */
        zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &var_handle);
@@ -202,7 +205,7 @@ pval php_VARIANT_get_property_handler(zend_property_reference *property_referenc
                        case OE_IS_OBJECT:
                                if(!strcmp(overloaded_property->element.value.str.val, "value"))
                                {
-                                       php_variant_to_pval(var_arg, &result, 0, codepage);
+                                       php_variant_to_pval(var_arg, &result, 0, codepage TSRMLS_CC);
                                }
                                else if(!strcmp(Z_STRVAL(overloaded_property->element), "type"))
                                {
@@ -226,13 +229,14 @@ pval php_VARIANT_get_property_handler(zend_property_reference *property_referenc
        return result;
 }
 
-int php_VARIANT_set_property_handler(zend_property_reference *property_reference, pval *value)
+static int php_VARIANT_set_property_handler(zend_property_reference *property_reference, pval *value)
 {
        zend_overloaded_element *overloaded_property;
        int type;
+       TSRMLS_FETCH();
+
        pval **var_handle, *object = property_reference->object;
        VARIANT *var_arg;
-       TSRMLS_FETCH();
 
        /* fetch the VARIANT structure */
        zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &var_handle);
@@ -242,12 +246,12 @@ int php_VARIANT_set_property_handler(zend_property_reference *property_reference
                return FAILURE;
 
        overloaded_property = (zend_overloaded_element *) property_reference->elements_list->head->data;
-       do_VARIANT_propset(var_arg, &overloaded_property->element, value);
+       do_VARIANT_propset(var_arg, &overloaded_property->element, value TSRMLS_CC);
        zval_dtor(&overloaded_property->element);
        return SUCCESS;
 }
 
-static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value)
+static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value TSRMLS_DC)
 {
        pval type;
 
@@ -415,17 +419,17 @@ static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value)
                return FAILURE;
        }
 
-       php_pval_to_variant_ex(value, var_arg, &type, codepage);
+       php_pval_to_variant_ex(value, var_arg, &type, codepage TSRMLS_CC);
 
        return SUCCESS;
 }
 
-static void php_variant_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+static void php_VARIANT_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 {
-       efree(rsrc);
+       FREE_VARIANT(rsrc->ptr);
 }
 
-void php_register_VARIANT_class(TSRMLS_D)
+static void php_register_VARIANT_class(TSRMLS_D)
 {
        INIT_OVERLOADED_CLASS_ENTRY(VARIANT_class_entry, "VARIANT", NULL,
                                                                php_VARIANT_call_function_handler,
index 13ac1d68b857728fc9d4cdc825d101fcc8287fa4..99c17782dfda07b382594d316386a7da32930b9f 100644 (file)
@@ -3,7 +3,9 @@
 
 #if PHP_WIN32
 
-#include "oleauto.h"
+BEGIN_EXTERN_C()
+
+#include <oleauto.h>
 
 typedef struct comval_ {
 #ifdef _DEBUG
@@ -19,6 +21,8 @@ typedef struct comval_ {
        } i;
 } comval;
 
+END_EXTERN_C()
+
 #define ZVAL_COM(z,o) {                                                                                                                                \
                        zval *handle;                                                                                                                   \
                        HashTable *properties;                                                                                                  \
@@ -32,14 +36,18 @@ typedef struct comval_ {
                                                                                                                                                                        \
                        zval_copy_ctor(handle);                                                                                                 \
                        zend_hash_index_update(properties, 0, &handle, sizeof(zval *), NULL);   \
-                       object_and_properties_init(z, &com_class_entry, properties);                    \
+                       object_and_properties_init(z, &COM_class_entry, properties);                    \
                }
 
-#define RETVAL_COM(o)  ZVAL_COM(&return_value, o)
+#define RETVAL_COM(o)  ZVAL_COM(&return_value, o);
 #define RETURN_COM(o)  RETVAL_COM(o)                                                                                           \
                                                return;
 
-#define ALLOC_COM(z)   (z) = (comval *) emalloc(sizeof(comval))
+#define ALLOC_COM(z)   (z) = (comval *) emalloc(sizeof(comval));                                       \
+                                               C_REFCOUNT(z) = 0;
+
+#define FREE_COM(z)            efree(z);
+
 #define IS_COM                 php_COM_get_le_comval()
 
 #define C_HASTLIB(x)   ((x)->typelib)
index 0f9bcbd32b7a59cf60ac94ecf25725db0d336735..21dace5c188a80566e91fa13e96358fe022d1766 100644 (file)
 
 /* prototypes */
 
-PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage TSRMLS_DC);
-PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage TSRMLS_DC);
-PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent, int codepage);
-PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage);
-PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent, int codepage);
-
 static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int codepage TSRMLS_DC);
 static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC);
 
@@ -50,7 +44,7 @@ static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC);
 PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage TSRMLS_DC)
 {
        int type = VT_EMPTY;    /* default variant type */
-       
+
        switch(Z_TYPE_P(pval_arg))
        {
                case IS_NULL:
@@ -64,7 +58,7 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage T
                case IS_OBJECT:
                        if(!strcmp(Z_OBJCE_P(pval_arg)->name, "VARIANT"))
                        {
-                               type = VT_VARIANT;
+                               type = VT_VARIANT|VT_BYREF;
                        }
                        else if(!strcmp(Z_OBJCE_P(pval_arg)->name, "COM"))
                        {
@@ -93,10 +87,10 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage T
                case IS_STRING:
                        type = VT_BSTR;
                        break;
-                       }
+       }
 
        if(pval_arg->is_ref)    /* deprecated, implemented for downwards compatiblity */
-                       {
+       {
                type |= VT_BYREF;
        }
 
@@ -116,22 +110,22 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
        V_VT(var_arg) = type;
 
        if(V_VT(var_arg) & VT_ARRAY)
-                       {
-                               /* For now we'll just handle single dimension arrays, we'll use the data type of the first element for the
-                                  output data type */
-                               HashTable *ht = Z_ARRVAL(*pval_arg);
-                               int numberOfElements = zend_hash_num_elements(ht);
-                               SAFEARRAY *safeArray;
-                               SAFEARRAYBOUND bounds[1];
-                               VARIANT *v;
-                               zval       **entry;        /* An entry in the input array */
-                               
+       {
+               /* For now we'll just handle single dimension arrays, we'll use the data type of the first element for the
+                  output data type */
+               HashTable *ht = Z_ARRVAL(*pval_arg);
+               int numberOfElements = zend_hash_num_elements(ht);
+               SAFEARRAY *safeArray;
+               SAFEARRAYBOUND bounds[1];
+               VARIANT *v;
+               zval **entry;        /* An entry in the input array */
+               
                type &= ~VT_ARRAY;
 
                if(V_VT(var_arg) == (VT_ARRAY|VT_BYREF))                /* == is intended, because VT_*|VT_BYREF|VT_ARRAY means something diffrent */
                {
                        type &= ~VT_BYREF;
-                                       ALLOC_VARIANT(V_VARIANTREF(var_arg));
+                       ALLOC_VARIANT(V_VARIANTREF(var_arg));
                        var_arg = V_VARIANTREF(var_arg);                /* put the array in that VARIANT */
                }
 
@@ -141,7 +135,7 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
                
                if(NULL == safeArray)
                {
-                       php_error( E_WARNING, "Unable to convert php array to VARIANT array - %s", numberOfElements ? "" : "(Empty input array)");
+                       php_error( E_WARNING,"Unable to convert php array to VARIANT array - %s", numberOfElements ? "" : "(Empty input array)");
                        ZVAL_FALSE(pval_arg);
                }
                else
@@ -158,20 +152,20 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
                                        if((zend_hash_get_current_data(ht, (void **)&entry) == SUCCESS) && (entry != NULL)) /* Get a pointer to the php array element */
                                        {
                                                /* Add another value to the safe array */
-                                               if(SUCCEEDED(SafeArrayPtrOfIndex( safeArray, &i, &v)))/* Pointer to output element entry retrieved successfully */
+                                               if(SUCCEEDED(SafeArrayPtrOfIndex( safeArray, &i, &v)))          /* Pointer to output element entry retrieved successfully */
                                                {
-                                                  if(type)     /* explicit type */
-                                                  {
+                                                       if(type)        /* explicit type */
+                                                       {
                                                           pval_to_variant_ex(*entry, v, type, codepage TSRMLS_CC);             /* Do the required conversion */
-                                                  }
-                                                  else
-                                                  {
+                                                       }
+                                                       else
+                                                       {
                                                                php_pval_to_variant(*entry, v, codepage TSRMLS_CC);                    /* Do the required conversion */
                                                        }
                                                }
                                                else
                                                {
-                                                       php_error( E_WARNING, "phpArrayToSafeArray() - Unable to retrieve pointer to output element number (%d)", i);
+                                                       php_error( E_WARNING,"phpArrayToSafeArray() - Unable to retrieve pointer to output element number (%d)", i);
                                                }
                                        }
                                        zend_hash_move_forward(ht);
@@ -180,207 +174,210 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
                        }
                        else
                        {
-                               php_error( E_WARNING, "phpArrayToSafeArray() - Unable to lock safeArray");
+                               php_error( E_WARNING,"phpArrayToSafeArray() - Unable to lock safeArray");
                        }
                }
        }
        else
-   {
-          switch(V_VT(var_arg))
-          {
-                  case VT_UI1:
-                          convert_to_long_ex(&pval_arg);
-                          V_UI1(var_arg) = (unsigned char)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_I2:
-                          convert_to_long_ex(&pval_arg);
-                          V_I2(var_arg) = (short)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_I4:
-                          convert_to_long_ex(&pval_arg);
-                          V_I4(var_arg) = Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_R4:
-                          convert_to_double_ex(&pval_arg);
-                          V_R4(var_arg) = (float)Z_DVAL_P(pval_arg);
-                          break;
-   
-                  case VT_R8:
-                          convert_to_double_ex(&pval_arg);
-                          V_R8(var_arg) = Z_DVAL_P(pval_arg);
-                          break;
-   
-                  case VT_BOOL:
-                          convert_to_boolean_ex(&pval_arg);
-                          V_BOOL(var_arg) = (short)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_ERROR:
-                          convert_to_long_ex(&pval_arg);
-                          V_ERROR(var_arg) = Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_CY:
-                          convert_to_double_ex(&pval_arg);
-                          VarCyFromR8(Z_DVAL_P(pval_arg), &V_CY(var_arg));
-                          break;
-   
-                  case VT_DATE:
-                          {
-                                  SYSTEMTIME wintime;
-                                  struct tm *phptime;
-   
-                                  phptime = gmtime(&(pval_arg->value.lval));
-                                  memset(&wintime, 0, sizeof(wintime));
-   
-                                  wintime.wYear = phptime->tm_year + 1900;
-                                  wintime.wMonth = phptime->tm_mon + 1;
-                                  wintime.wDay = phptime->tm_mday;
-                                  wintime.wHour = phptime->tm_hour;
-                                  wintime.wMinute = phptime->tm_min;
-                                  wintime.wSecond = phptime->tm_sec;
-   
-                                  SystemTimeToVariantTime(&wintime, &V_DATE(var_arg));
-                          }
-                          break;
-   
-                  case VT_BSTR:
-                          convert_to_string_ex(&pval_arg);
-                          unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage);
-                          V_BSTR(var_arg) = SysAllocString(unicode_str);
-                          efree(unicode_str);
-                          break;
-   
-                  case VT_DECIMAL:
-                          convert_to_string_ex(&pval_arg);
-                          unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage);
-                          VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, &V_DECIMAL(var_arg));
-                          break;
-   
-                  case VT_DECIMAL|VT_BYREF:
-                          convert_to_string_ex(&pval_arg);
-                          unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage);
-                          VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, V_DECIMALREF(var_arg));
-                          break;
-   
-                  case VT_UNKNOWN:
+       {
+               switch(V_VT(var_arg))
+               {
+                       case VT_UI1:
+                               convert_to_long_ex(&pval_arg);
+                               V_UI1(var_arg) = (unsigned char)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_I2:
+                               convert_to_long_ex(&pval_arg);
+                               V_I2(var_arg) = (short)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_I4:
+                               convert_to_long_ex(&pval_arg);
+                               V_I4(var_arg) = Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_R4:
+                               convert_to_double_ex(&pval_arg);
+                               V_R4(var_arg) = (float)Z_DVAL_P(pval_arg);
+                               break;
+
+                       case VT_R8:
+                               convert_to_double_ex(&pval_arg);
+                               V_R8(var_arg) = Z_DVAL_P(pval_arg);
+                               break;
+
+                       case VT_BOOL:
+                               convert_to_boolean_ex(&pval_arg);
+                               V_BOOL(var_arg) = (short)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_ERROR:
+                               convert_to_long_ex(&pval_arg);
+                               V_ERROR(var_arg) = Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_CY:
+                               convert_to_double_ex(&pval_arg);
+                               VarCyFromR8(Z_DVAL_P(pval_arg), &V_CY(var_arg));
+                               break;
+
+                       case VT_DATE:
+                               {
+                                       SYSTEMTIME wintime;
+                                       struct tm *phptime;
+
+                                       phptime = gmtime(&(pval_arg->value.lval));
+                                       memset(&wintime, 0, sizeof(wintime));
+
+                                       wintime.wYear = phptime->tm_year + 1900;
+                                       wintime.wMonth = phptime->tm_mon + 1;
+                                       wintime.wDay = phptime->tm_mday;
+                                       wintime.wHour = phptime->tm_hour;
+                                       wintime.wMinute = phptime->tm_min;
+                                       wintime.wSecond = phptime->tm_sec;
+
+                                       SystemTimeToVariantTime(&wintime, &V_DATE(var_arg));
+                               }
+                               break;
+
+                       case VT_BSTR:
+                               convert_to_string_ex(&pval_arg);
+                               unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
+                               V_BSTR(var_arg) = SysAllocString(unicode_str);
+                               efree(unicode_str);
+                               break;
+
+                       case VT_DECIMAL:
+                               convert_to_string_ex(&pval_arg);
+                               unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
+                               VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, &V_DECIMAL(var_arg));
+                               break;
+
+                       case VT_DECIMAL|VT_BYREF:
+                               convert_to_string_ex(&pval_arg);
+                               unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
+                               VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, V_DECIMALREF(var_arg));
+                               break;
+
+                       case VT_UNKNOWN:
                        comval_to_variant(pval_arg, var_arg TSRMLS_CC);
-                          if(V_VT(var_arg) != VT_DISPATCH)
-                          {
-                                  VariantInit(var_arg);
-                          }
-                          else
-                          {
-                                  V_VT(var_arg) = VT_UNKNOWN;
-                                  V_UNKNOWN(var_arg) = (IUnknown *) V_DISPATCH(var_arg);
-                          }
-                          break;
-   
-                  case VT_DISPATCH:
+                               if(V_VT(var_arg) != VT_DISPATCH)
+                               {
+                                       VariantInit(var_arg);
+                               }
+                               else
+                               {
+                                       V_VT(var_arg) = VT_UNKNOWN;
+                                       V_UNKNOWN(var_arg) = (IUnknown *) V_DISPATCH(var_arg);
+                               }
+                               break;
+
+                       case VT_DISPATCH:
                                comval_to_variant(pval_arg, var_arg TSRMLS_CC);
-                          if(V_VT(var_arg) != VT_DISPATCH)
-                          {
-                                  VariantInit(var_arg);
-                          }
-                          break;
-   
-                  case VT_UI1|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_UI1REF(var_arg) = (unsigned char FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_I2|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_I2REF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_I4|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_I4REF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_R4|VT_BYREF:
-                          convert_to_double(pval_arg);
-                          V_R4REF(var_arg) = (float FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_R8|VT_BYREF:
-                          convert_to_double(pval_arg);
-                          V_R8REF(var_arg) = (double FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_BOOL|VT_BYREF:
-                          convert_to_boolean(pval_arg);
-                          V_BOOLREF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_ERROR|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_ERRORREF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_CY|VT_BYREF:
-                          convert_to_double_ex(&pval_arg);
-                          VarCyFromR8(pval_arg->value.dval, var_arg->pcyVal);
-                          break;
-   
-                  case VT_DATE|VT_BYREF:
-                          {
-                                  SYSTEMTIME wintime;
-                                  struct tm *phptime;
-   
-                                  phptime = gmtime(&(pval_arg->value.lval));
-                                  memset(&wintime, 0, sizeof(wintime));
-   
-                                  wintime.wYear   = phptime->tm_year + 1900;
-                                  wintime.wMonth  = phptime->tm_mon + 1;
-                                  wintime.wDay    = phptime->tm_mday;
-                                  wintime.wHour   = phptime->tm_hour;
-                                  wintime.wMinute = phptime->tm_min;
-                                  wintime.wSecond = phptime->tm_sec;
-   
-                                  SystemTimeToVariantTime(&wintime, var_arg->pdate);
-                          }
-                          break;
-   
-                  case VT_BSTR|VT_BYREF:
-                          convert_to_string(pval_arg);
-                          V_BSTRREF(var_arg) = (BSTR FAR*) emalloc(sizeof(BSTR FAR*));
-                          unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage);
-                          *V_BSTRREF(var_arg) = SysAllocString(unicode_str);
-                          efree(unicode_str);
-                          break;
-   
-                  case VT_UNKNOWN|VT_BYREF:
+                               if(V_VT(var_arg) != VT_DISPATCH)
+                               {
+                                       VariantInit(var_arg);
+                               }
+                               break;
+
+                       case VT_UI1|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_UI1REF(var_arg) = (unsigned char FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_I2|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_I2REF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_I4|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_I4REF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_R4|VT_BYREF:
+                               convert_to_double(pval_arg);
+                               V_R4REF(var_arg) = (float FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_R8|VT_BYREF:
+                               convert_to_double(pval_arg);
+                               V_R8REF(var_arg) = (double FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_BOOL|VT_BYREF:
+                               convert_to_boolean(pval_arg);
+                               V_BOOLREF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_ERROR|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_ERRORREF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_CY|VT_BYREF:
+                               convert_to_double_ex(&pval_arg);
+                               VarCyFromR8(pval_arg->value.dval, var_arg->pcyVal);
+                               break;
+
+                       case VT_DATE|VT_BYREF:
+                               {
+                                       SYSTEMTIME wintime;
+                                       struct tm *phptime;
+
+                                       phptime = gmtime(&(pval_arg->value.lval));
+                                       memset(&wintime, 0, sizeof(wintime));
+
+                                       wintime.wYear   = phptime->tm_year + 1900;
+                                       wintime.wMonth  = phptime->tm_mon + 1;
+                                       wintime.wDay    = phptime->tm_mday;
+                                       wintime.wHour   = phptime->tm_hour;
+                                       wintime.wMinute = phptime->tm_min;
+                                       wintime.wSecond = phptime->tm_sec;
+
+                                       SystemTimeToVariantTime(&wintime, var_arg->pdate);
+                               }
+                               break;
+
+                       case VT_BSTR|VT_BYREF:
+                               convert_to_string(pval_arg);
+                               V_BSTRREF(var_arg) = (BSTR FAR*) emalloc(sizeof(BSTR FAR*));
+                               unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
+                               *V_BSTRREF(var_arg) = SysAllocString(unicode_str);
+                               efree(unicode_str);
+                               break;
+
+                       case VT_UNKNOWN|VT_BYREF:
                                comval_to_variant(pval_arg, var_arg TSRMLS_CC);
-                          if(V_VT(var_arg) != VT_DISPATCH)
-                          {
-                                  VariantInit(var_arg);
-                          }
-                          else
-                          {
-                                  V_VT(var_arg) = VT_UNKNOWN|VT_BYREF;
+                               if(V_VT(var_arg) != VT_DISPATCH)
+                               {
+                                       VariantInit(var_arg);
+                               }
+                               else
+                               {
+                                       V_VT(var_arg) = VT_UNKNOWN|VT_BYREF;
                                        V_UNKNOWNREF(var_arg) = (IUnknown **) &V_DISPATCH(var_arg);
-                          }
-                          break;
-   
-                  case VT_DISPATCH|VT_BYREF:
+                               }
+                               break;
+
+                       case VT_DISPATCH|VT_BYREF:
                                comval_to_variant(pval_arg, var_arg TSRMLS_CC);
-                          if(V_VT(var_arg) != VT_DISPATCH)
-                          {
-                                  VariantInit(var_arg);
-                          }
-                          else
-                          {
+                               if(V_VT(var_arg) != VT_DISPATCH)
+                               {
+                                       VariantInit(var_arg);
+                               }
+                               else
+                               {
                                        V_VT(var_arg) = VT_DISPATCH|VT_BYREF;
                                        V_DISPATCHREF(var_arg) = &V_DISPATCH(var_arg);
-                          }
-                          break;
-   
-                  case VT_VARIANT|VT_BYREF:
+                               }
+                               break;
+
+                       case VT_VARIANT:
+                               php_error(E_WARNING,"VT_VARIANT is invalid. Use VT_VARIANT|VT_BYREF instead.");
+                               /* break missing intentionally */
+                       case VT_VARIANT|VT_BYREF:
                                {
                                        int tp;
                                        pval **var_handle;
@@ -392,9 +389,9 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
                                        V_VARIANTREF(var_arg) = (VARIANT FAR*) zend_list_find(Z_LVAL_P(*var_handle), &tp);
 
                                        if(!V_VARIANTREF(var_arg) && (tp != IS_VARIANT))
-                             {
-                                     VariantInit(var_arg);
-                             }
+                                       {
+                                               VariantInit(var_arg);
+                                       }
                                }
                        /*
                                should be, but isn't :)
@@ -404,65 +401,65 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
                                        VariantInit(var_arg);
                                }
                        */
-                          break;
-   
-                  case VT_I1:
-                          convert_to_long_ex(&pval_arg);
-                          V_I1(var_arg) = (char)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UI2:
-                          convert_to_long_ex(&pval_arg);
-                          V_UI2(var_arg) = (unsigned short)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UI4:
-                          convert_to_long_ex(&pval_arg);
-                          V_UI4(var_arg) = (unsigned long)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_INT:
-                          convert_to_long_ex(&pval_arg);
-                          V_INT(var_arg) = (int)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UINT:
-                          convert_to_long_ex(&pval_arg);
-                          V_UINT(var_arg) = (unsigned int)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_I1|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_I1REF(var_arg) = (char FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UI2|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_UI2REF(var_arg) = (unsigned short FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UI4|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_UI4REF(var_arg) = (unsigned long FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_INT|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_INTREF(var_arg) = (int FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UINT|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_UINTREF(var_arg) = (unsigned int FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  default:
-                          php_error(E_WARNING, "Type not supported or not yet implemented.");
-          }
-   }
+                               break;
+
+                       case VT_I1:
+                               convert_to_long_ex(&pval_arg);
+                               V_I1(var_arg) = (char)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UI2:
+                               convert_to_long_ex(&pval_arg);
+                               V_UI2(var_arg) = (unsigned short)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UI4:
+                               convert_to_long_ex(&pval_arg);
+                               V_UI4(var_arg) = (unsigned long)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_INT:
+                               convert_to_long_ex(&pval_arg);
+                               V_INT(var_arg) = (int)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UINT:
+                               convert_to_long_ex(&pval_arg);
+                               V_UINT(var_arg) = (unsigned int)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_I1|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_I1REF(var_arg) = (char FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UI2|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_UI2REF(var_arg) = (unsigned short FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UI4|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_UI4REF(var_arg) = (unsigned long FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_INT|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_INTREF(var_arg) = (int FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UINT|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_UINTREF(var_arg) = (unsigned int FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       default:
+                               php_error(E_WARNING, "Type not supported or not yet implemented.");
+               }
+       }
 }
 
-PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent, int codepage)
+PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent, int codepage TSRMLS_DC)
 {
        /* Changed the function to return a value for recursive error testing */
        /* Existing calls will be unaffected by the change - so it */
@@ -488,7 +485,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                /* For now just validate that the SafeArray has one dimension */
                if (1 != (Dims = SafeArrayGetDim(array)))
                {
-                       php_error(E_WARNING, "Unsupported: multi-dimensional (%d) SafeArrays", Dims);
+                       php_error(E_WARNING,"Unsupported: multi-dimensional (%d) SafeArrays", Dims);
                        ZVAL_NULL(pval_arg);
                        return FAILURE;
                }
@@ -529,18 +526,18 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                hr = SafeArrayGetElement(array, indices, (VOID *) &(vv.lVal));
                        }
                        if (FAILED(hr))
-            {
+                       {
                                /* Failure to retieve an element probably means the array is sparse */
                                /* So leave the php array sparse too */
                                continue;
-            }
+                       }
                        /* Create an element to be added to the array */
                        ALLOC_ZVAL(element);
                        /* Call ourself again to handle the base type conversion */
                        /* If SafeArrayGetElement proclaims to allocate */
                        /* memory for a BSTR, so the recursive call frees */
                        /* the string correctly */
-                       if (FAILURE == php_variant_to_pval(&vv, element, persistent, codepage))
+                       if (FAILURE == php_variant_to_pval(&vv, element, persistent, codepage TSRMLS_CC))
                        {
                                /* Error occurred setting up array element */
                                /* Error was displayed by the recursive call */
@@ -560,10 +557,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                add_index_zval(pval_arg, ii, element);
                        }
                }
-        SafeArrayUnlock(array);
-               /* Clean up the SafeArray since that is our responsibility */
-               SafeArrayDestroyData(array);
-               SafeArrayDestroyDescriptor(array);
+               SafeArrayUnlock(array);
        }
        else switch(var_arg->vt & ~VT_BYREF)
        {               
@@ -633,7 +627,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                switch(VarBstrFromDec(&V_DECIMAL(var_arg), LOCALE_SYSTEM_DEFAULT, 0, &unicode_str))
                                {
                                        case S_OK:
-                                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(unicode_str, &Z_STRLEN_P(pval_arg), persistent, codepage);
+                                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(unicode_str, &Z_STRLEN_P(pval_arg), persistent, codepage TSRMLS_CC);
                                                Z_TYPE_P(pval_arg) = IS_STRING;
                                                break;
 
@@ -676,20 +670,18 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                case VT_VARIANT:
-                       php_variant_to_pval(V_VARIANTREF(var_arg), pval_arg, persistent, codepage);
+                       php_variant_to_pval(V_VARIANTREF(var_arg), pval_arg, persistent, codepage TSRMLS_CC);
                        break;
 
                case VT_BSTR:
                        if(V_ISBYREF(var_arg))
                        {
-                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(*V_BSTRREF(var_arg), &Z_STRLEN_P(pval_arg), persistent, codepage);
-                               SysFreeString(*V_BSTRREF(var_arg));
+                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(*V_BSTRREF(var_arg), &Z_STRLEN_P(pval_arg), persistent, codepage TSRMLS_CC);
                                efree(V_BSTRREF(var_arg));
                        }
                        else
                        {
-                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(V_BSTR(var_arg), &Z_STRLEN_P(pval_arg), persistent, codepage);
-                               SysFreeString(V_BSTR(var_arg));
+                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(V_BSTR(var_arg), &Z_STRLEN_P(pval_arg), persistent, codepage TSRMLS_CC);
                        }
 
                        Z_TYPE_P(pval_arg) = IS_STRING;
@@ -739,8 +731,8 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                {
                                        char *error_message;
 
-                                       error_message = php_COM_error_message(hr);
-                                       php_error(E_WARNING, "Unable to obtain IDispatch interface:  %s", error_message);
+                                       error_message = php_COM_error_message(hr TSRMLS_CC);
+                                       php_error(E_WARNING,"Unable to obtain IDispatch interface:  %s", error_message);
                                        LocalFree(error_message);
 
                                        V_DISPATCH(var_arg) = NULL;
@@ -758,11 +750,9 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                }
                                else
                                {
-                                       TSRMLS_FETCH();
-
                                        ALLOC_COM(obj);
-                                       php_COM_set(obj, V_DISPATCH(var_arg), TRUE);
-
+                                       php_COM_set(obj, &V_DISPATCH(var_arg), TRUE TSRMLS_CC);
+                                       
                                        ZVAL_COM(pval_arg, obj);
                                }
                        }
@@ -824,7 +814,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                default:
-                       php_error(E_WARNING, "Unsupported variant type: %d (0x%X)", V_VT(var_arg), V_VT(var_arg));
+                       php_error(E_WARNING,"Unsupported variant type: %d (0x%X)", V_VT(var_arg), V_VT(var_arg));
                        ZVAL_NULL(pval_arg);
                        ret = FAILURE;
                        break;
@@ -832,7 +822,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
        return ret;
 }
 
-PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage)
+PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage TSRMLS_DC)
 {
        OLECHAR *unicode_str;
 
@@ -854,17 +844,17 @@ PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage)
                switch(GetLastError())
                {
                        case ERROR_NO_UNICODE_TRANSLATION:
-                               php_error(E_WARNING, "No unicode translation available for the specified string");
+                               php_error(E_WARNING,"No unicode translation available for the specified string");
                                break;
                        default:
-                               php_error(E_WARNING, "Error in php_char_to_OLECHAR()");
+                               php_error(E_WARNING,"Error in php_char_to_OLECHAR()");
                }
        }
 
        return unicode_str;
 }
 
-PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent, int codepage)
+PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent, int codepage TSRMLS_DC)
 {
        char *C_str;
        uint length = 0;
@@ -884,7 +874,7 @@ PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int per
                C_str = (char *) pemalloc(sizeof(char), persistent);
                *C_str = 0;
 
-               php_error(E_WARNING, "Error in php_OLECHAR_to_char()");
+               php_error(E_WARNING,"Error in php_OLECHAR_to_char()");
        }
 
        if(out_length)
@@ -903,7 +893,7 @@ static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC)
 
        /* fetch the comval structure */
        zend_hash_index_find(Z_OBJPROP_P(pval_arg), 0, (void **) &comval_handle);
-       obj = (comval *) zend_list_find(Z_LVAL_P(*comval_handle), &type);
+       obj = (comval *)zend_list_find(Z_LVAL_P(*comval_handle), &type);
        if(!obj || (type != IS_COM) || !C_ISREFD(obj))
        {
                VariantInit(var_arg);
@@ -915,4 +905,4 @@ static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC)
        }
 }
 
-#endif /* PHP_WIN32 */
+#endif /* PHP_WIN32 */
\ No newline at end of file
index 53d19a21dee4e16a1191da95b8062ecc6a503253..a55d66c57b3141030c979a8cf56898856397fb22 100644 (file)
@@ -3,11 +3,11 @@
 
 BEGIN_EXTERN_C()
 
-extern void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage);
-extern void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage);
-extern int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent, int codepage);
-extern OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage);
-extern char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent, int codepage);
+PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage TSRMLS_DC);
+PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage TSRMLS_DC);
+PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent, int codepage TSRMLS_DC);
+PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage TSRMLS_DC);
+PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent, int codepage TSRMLS_DC);
 
 END_EXTERN_C()
 
index 3a2108f4153f2ce219c95facc99ae58bb8cdba5f..c44c808fe04f834f29af7c01a3ce60ac3d40d54c 100644 (file)
@@ -10,22 +10,30 @@ BEGIN_EXTERN_C()
 PHP_MINIT_FUNCTION(COM);
 PHP_MSHUTDOWN_FUNCTION(COM);
 
-PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR* pVarResult);
-PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId);
-PHPAPI HRESULT php_COM_release(comval *obj);
-PHPAPI HRESULT php_COM_addref(comval *obj);
-PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup);
-PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup);
-
-int php_COM_get_le_comval();
+PHP_FUNCTION(com_load);
+PHP_FUNCTION(com_invoke);
+PHP_FUNCTION(com_addref);
+PHP_FUNCTION(com_release);
+PHP_FUNCTION(com_propget);
+PHP_FUNCTION(com_propput);
+PHP_FUNCTION(com_load_typelib);
+PHP_FUNCTION(com_isenum);
+
+PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR* pVarResult, char **ErrString TSRMLS_DC);
+PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId TSRMLS_DC);
+PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC);
+PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC);
+PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC);
+PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* pDisp, int cleanup TSRMLS_DC);
+PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup TSRMLS_DC);
+PHPAPI char *php_COM_error_message(HRESULT hr TSRMLS_DC);
+PHPAPI int php_COM_get_le_comval();
+PHPAPI int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value);
+PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_reference);
+PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
 
 zend_module_entry COM_module_entry;
-zend_class_entry com_class_entry;
-
-pval php_COM_get_property_handler(zend_property_reference *property_reference);
-int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value);
-char *php_COM_error_message(HRESULT hr);
-void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
+zend_class_entry COM_class_entry;
 
 #ifdef DEBUG
        extern int resourcecounter;
index 5e6d51f82180943bd55dbfd755ac3bf85a5a46a9..2447d066ad66a20ff6897af9e4955d4ed75f427a 100644 (file)
@@ -3,14 +3,19 @@
 
 #if PHP_WIN32
 
-#include "variant.h"
+BEGIN_EXTERN_C()
 
-extern int php_VARIANT_get_le_variant();
+#include "conversion.h"
+#include "variant.h"
 
 PHP_MINIT_FUNCTION(VARIANT);
 PHP_MSHUTDOWN_FUNCTION(VARIANT);
 
-extern zend_module_entry VARIANT_module_entry;
+PHPAPI int php_VARIANT_get_le_variant();
+
+zend_module_entry VARIANT_module_entry;
+
+END_EXTERN_C()
 
 #define VARIANT_module_ptr &VARIANT_module_entry
 
index ec25ee4e4b8272edceef85db599e67e68eb6ba97..ce5b4e66ae959714a091a3fc81c3ea26600f2540 100644 (file)
@@ -3,7 +3,13 @@
 
 #if PHP_WIN32
 
-#define ALLOC_VARIANT(v)       (v) = (VARIANT *) emalloc(sizeof(VARIANT))
+#define ALLOC_VARIANT(v)       (v) = (VARIANT *) emalloc(sizeof(VARIANT));             \
+                                                       VariantInit(v);
+
+#define FREE_VARIANT(v)                VariantClear(v);                                                                \
+                                                       efree(v);
+
+
 #define IS_VARIANT                     php_VARIANT_get_le_variant()
 
 #endif  /* PHP_WIN32 */
index ee1fbc8c6cea4619ec5f4900674bdf50866daf74..0063f426b1834195ff21be7f407fbd0ba256e7df 100644 (file)
@@ -14,6 +14,7 @@
    +----------------------------------------------------------------------+
    | Author: Zeev Suraski <zeev@zend.com>                                 |
    |         Harald Radi  <h.radi@nme.at>                                 |
+   |         Alan Brown   <abrown@pobox.com>                              |
    +----------------------------------------------------------------------+
  */
 
 #include "php.h"
 #include "php_ini.h"
 
-#include "com.h"
-#include "conversion.h"
+#include "php_COM.h"
 #include "php_VARIANT.h"
 
-zend_class_entry com_class_entry;
-
-PHP_FUNCTION(com_load);
-PHP_FUNCTION(com_invoke);
-PHP_FUNCTION(com_addref);
-PHP_FUNCTION(com_release);
-PHP_FUNCTION(com_propget);
-PHP_FUNCTION(com_propput);
-PHP_FUNCTION(com_load_typelib);
-PHP_FUNCTION(com_isenum);
-
-PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR* pVarResult);
-PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId);
-PHPAPI HRESULT php_COM_release(comval *obj);
-PHPAPI HRESULT php_COM_addref(comval *obj);
-PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup);
-PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup);
-
-PHPAPI int php_COM_get_le_comval();
-static ITypeLib *php_COM_find_typelib(char *search_string, int mode);
+static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC);
 static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC);
+static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup TSRMLS_DC);
+static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup TSRMLS_DC);
+static void php_register_COM_class(TSRMLS_D);
 
 static int le_comval;
 static int codepage;
@@ -118,19 +102,22 @@ static PHP_MINFO_FUNCTION(COM)
        DISPLAY_INI_ENTRIES();
 }
 
-PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR*  pVarResult)
+PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR*  pVarResult, char **ErrString TSRMLS_DC)
 {
        HRESULT hr;
        int failed = FALSE;
+       unsigned int ArgErr;
+       EXCEPINFO ExceptInfo;
 
+       *ErrString = NULL;
        if(C_ISREFD(obj))
        {
                if(C_HASTLIB(obj))
                {
-                       hr = C_TYPEINFO_VT(obj)->Invoke(C_TYPEINFO(obj), C_DISPATCH(obj), dispIdMember, wFlags, pDispParams, pVarResult, NULL, NULL);
+                       hr = C_TYPEINFO_VT(obj)->Invoke(C_TYPEINFO(obj), C_DISPATCH(obj), dispIdMember, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr);
                        if(FAILED(hr))
                        {
-                               hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, NULL, NULL);
+                               hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr);
                                if(SUCCEEDED(hr))
                                {
                                        /*
@@ -145,7 +132,34 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS
                }
                else
                {
-                       hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, NULL, NULL);
+                       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;
+                               case DISP_E_PARAMNOTFOUND:
+                               case DISP_E_TYPEMISMATCH:
+                                       *ErrString = pemalloc(25, 1);
+                                       sprintf(*ErrString, "<b>Argument</b>: %d", pDispParams->cArgs-ArgErr+1);
+                                       break;
+                       }
                }
 
                return hr;
@@ -156,7 +170,7 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS
        }
 }
 
-PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId)
+PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId TSRMLS_DC)
 {
        HRESULT hr;
 
@@ -195,8 +209,10 @@ PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames
        }
 }
 
-PHPAPI HRESULT php_COM_release(comval *obj)
+PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC)
 {
+       HRESULT hr;
+       
        if(obj->refcount > 1)
        {
                C_RELEASE(obj);
@@ -209,16 +225,16 @@ PHPAPI HRESULT php_COM_release(comval *obj)
                }
                if(C_HASENUM(obj))
                {
-                       C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj));
+                       hr = C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj));
                }
-               C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj));
+               hr = C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj));
                C_RELEASE(obj);
        }
 
        return obj->refcount;
 }
 
-PHPAPI HRESULT php_COM_addref(comval *obj)
+PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC)
 {
        if(C_ISREFD(obj))
        {
@@ -228,13 +244,19 @@ PHPAPI HRESULT php_COM_addref(comval *obj)
        return obj->refcount;
 }
 
-PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup)
+PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup TSRMLS_DC)
 {
        HRESULT hr = 1;
        DISPPARAMS dispparams;
-       VARIANT var_result;
+       VARIANT *var_result;
+       IDispatch FAR* pDisp;
 
-       VariantInit(&var_result);
+       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)));
@@ -244,22 +266,26 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup)
        dispparams.cArgs = 0;
        dispparams.cNamedArgs = 0;
 
+       ALLOC_VARIANT(var_result);
+
        if(C_HASENUM(obj) = SUCCEEDED(C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), DISPID_NEWENUM, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
-                                                                       DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, &var_result, NULL, NULL)))
+                                                                       DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result, NULL, NULL)))
        {
-               if (V_VT(&var_result) == VT_UNKNOWN)
+               if(V_VT(var_result) == VT_UNKNOWN)
                {
-                   C_HASENUM(obj) = SUCCEEDED(V_UNKNOWN(&var_result)->lpVtbl->QueryInterface(V_UNKNOWN(&var_result), &IID_IEnumVARIANT,
+                   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,
+                   C_HASENUM(obj) = SUCCEEDED(V_DISPATCH(var_result)->lpVtbl->QueryInterface(V_DISPATCH(var_result), &IID_IEnumVARIANT,
                                                                        (void**)&C_ENUMVARIANT(obj)));
                }
 
        }
 
+       FREE_VARIANT(var_result);
+
        if(!cleanup)
        {
                hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj));
@@ -272,7 +298,7 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup)
        return hr;
 }
 
-PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup)
+PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup TSRMLS_DC)
 {
        HRESULT hr;
 
@@ -307,7 +333,7 @@ PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup)
        return hr;
 }
 
-PHPAPI char *php_COM_error_message(HRESULT hr)
+PHPAPI char *php_COM_error_message(HRESULT hr TSRMLS_DC)
 {
        void *pMsgBuf;
 
@@ -323,28 +349,35 @@ PHPAPI char *php_COM_error_message(HRESULT hr)
        return pMsgBuf;
 }
 
-static char *php_string_from_clsid(const CLSID *clsid)
+static char *php_string_from_clsid(const CLSID *clsid TSRMLS_DC)
 {
        LPOLESTR ole_clsid;
        char *clsid_str;
 
        StringFromCLSID(clsid, &ole_clsid);
-       clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, 0, codepage);
+       clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, 0, codepage TSRMLS_CC);
        LocalFree(ole_clsid);
 
        return clsid_str;
 }
 
-static void php_comval_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC)
 {
-       comval *obj = (comval *)rsrc->ptr;
+       HRESULT hr = S_OK;
 
        if(C_ISREFD(obj)) 
        {
                C_REFCOUNT(obj) = 1;
-               php_COM_release(obj);
+               hr = php_COM_release(obj TSRMLS_CC);
        }
        efree(obj);
+
+       return hr;
+}
+
+static void php_comval_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+       php_COM_destruct(rsrc->ptr TSRMLS_CC);
 }
 
 static PHP_INI_MH(OnTypelibFileChange)
@@ -353,7 +386,6 @@ static PHP_INI_MH(OnTypelibFileChange)
        char *typelib_name_buffer;
        char *strtok_buf = NULL;
        int interactive;
-
        interactive = CG(interactive);
 
        if(!new_value || (typelib_file = VCWD_FOPEN(new_value, "r"))==NULL)
@@ -407,12 +439,12 @@ static PHP_INI_MH(OnTypelibFileChange)
                        ptr--;
                }
 
-
                if(interactive)
                {
                        printf("\rLoading %-60s\r", typelib_name);
                }
-               if((pTL = php_COM_find_typelib(typelib_name, mode)) != 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);
@@ -507,9 +539,9 @@ PHP_FUNCTION(com_load)
                }
        }
 
+       ALLOC_COM(obj);
        convert_to_string_ex(&module_name);
-       ProgID = php_char_to_OLECHAR(Z_STRVAL_P(module_name), Z_STRLEN_P(module_name), codepage);
-       obj = (comval *) emalloc(sizeof(comval));
+       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)))
@@ -542,9 +574,9 @@ PHP_FUNCTION(com_load)
                
                if(FAILED(hr))
                {
-                       efree(obj);
-                       error_message = php_COM_error_message(hr);  
-                       php_error(E_WARNING, "Invalid ProgID or Moniker:  %s\n", error_message);
+                       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;
                }
@@ -564,7 +596,7 @@ PHP_FUNCTION(com_load)
 
                        server_info.dwReserved1=0;
                        server_info.dwReserved2=0;
-                       server_info.pwszName = php_char_to_OLECHAR(Z_STRVAL_P(server_name), Z_STRLEN_P(server_name), codepage);
+                       server_info.pwszName = php_char_to_OLECHAR(Z_STRVAL_P(server_name), Z_STRLEN_P(server_name), codepage TSRMLS_CC);
                        server_info.pAuthInfo=NULL;
 
                        pResults.pIID = &IID_IDispatch;
@@ -581,17 +613,17 @@ PHP_FUNCTION(com_load)
 
                if(FAILED(hr))
                {
-                       error_message = php_COM_error_message(hr);
-                       clsid_str = php_string_from_clsid(&clsid);
-                       php_error(E_WARNING, "Unable to obtain IDispatch interface for CLSID %s:  %s", clsid_str, error_message);
+                       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);
                        LocalFree(error_message);
                        efree(clsid_str);
-                       efree(obj);
+                       php_COM_destruct(obj TSRMLS_CC);
                        RETURN_FALSE;
                }
        }
 
-       php_COM_set(obj, C_DISPATCH(obj), TRUE);
+       php_COM_set(obj, &C_DISPATCH(obj), TRUE TSRMLS_CC);
 
        if(INI_INT("com.autoregister_casesensitive"))
        {
@@ -617,7 +649,7 @@ PHP_FUNCTION(com_load)
                {
                        ITypeLib *pTL;
 
-                       if((pTL = php_COM_find_typelib(Z_STRVAL_P(typelib), mode)) != 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 */
@@ -635,7 +667,7 @@ PHP_FUNCTION(com_load)
 /* }}} */
 
 
-int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **arguments, int arg_count)
+int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **arguments, int arg_count TSRMLS_DC)
 {
        DISPID dispid;
        HRESULT hr;
@@ -667,8 +699,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                                break;
 
                        default:
-                               /* TODO: complain about wrong arg count */
-                               php_error(E_WARNING, "Wrong argument count to IEnumVariant::Next()\n");
+                               php_error(E_WARNING,"Wrong argument count to IEnumVariant::Next()");
 
                                return FAILURE;
                }
@@ -679,6 +710,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                if((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL)
                {
                        VariantInit(var_result);
+
                        return FAILURE;
                }
                else
@@ -689,11 +721,10 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
 
                if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Next(C_ENUMVARIANT(obj), count, pSA->pvData, &count)))
                {
-                       char *error_message = php_COM_error_message(hr);
-                       php_error(E_WARNING, "IEnumVariant::Next() failed:  %s\n", error_message);
+                       char *error_message = php_COM_error_message(hr TSRMLS_CC);
+                       php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message);
                        efree(error_message);
-                       SafeArrayDestroy(pSA);
-                       VariantInit(var_result);
+                       VariantClear(var_result);
                        return FAILURE;
                }
 
@@ -702,11 +733,10 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                        rgsabound[0].cElements = count;
                        if(FAILED(SafeArrayRedim(pSA, rgsabound)))
                        {
-                               char *error_message = php_COM_error_message(hr);
-                               php_error(E_WARNING, "IEnumVariant::Next() failed:  %s\n", error_message);
+                               char *error_message = php_COM_error_message(hr TSRMLS_CC);
+                               php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message);
                                efree(error_message);
-                               SafeArrayDestroy(pSA);
-                               VariantInit(var_result);
+                               VariantClear(var_result);
                                return FAILURE;
                        }
                }
@@ -717,8 +747,8 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
        {
                if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Reset(C_ENUMVARIANT(obj))))
                {
-                       char *error_message = php_COM_error_message(hr);
-                       php_error(E_WARNING, "IEnumVariant::Next() failed:  %s\n", error_message);
+                       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;
                }
@@ -740,13 +770,13 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                                break;
 
                        default:
-                               php_error(E_WARNING, "Wrong argument count to IEnumVariant::Skip()\n");
+                               php_error(E_WARNING,"Wrong argument count to IEnumVariant::Skip()");
                                return FAILURE;
                }
                if(FAILED(hr = C_ENUMVARIANT_VT(obj)->Skip(C_ENUMVARIANT(obj), count)))
                {
-                       char *error_message = php_COM_error_message(hr);
-                       php_error(E_WARNING, "IEnumVariant::Next() failed:  %s\n", error_message);
+                       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;
                }
@@ -755,14 +785,16 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
        }
        else
        {
-               funcname = php_char_to_OLECHAR(Z_STRVAL_P(function_name), Z_STRLEN_P(function_name), codepage);
+               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);
+               hr = php_COM_get_ids_of_names(obj, &funcname, &dispid TSRMLS_CC);
 
                if(FAILED(hr))
                {
-                       error_message = php_COM_error_message(hr);
-                       php_error(E_WARNING, "Unable to lookup %s:  %s\n", Z_STRVAL_P(function_name), error_message);
+                       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);
                        efree(funcname);
                        return FAILURE;
@@ -773,7 +805,7 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                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);
+                       php_pval_to_variant(arguments[current_arg], &variant_args[current_variant], codepage TSRMLS_CC);
                }
 
                dispparams.rgvarg = variant_args;
@@ -781,15 +813,27 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
                dispparams.cArgs = arg_count;
                dispparams.cNamedArgs = 0;
 
-               hr = php_COM_invoke(obj, dispid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result);
+               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]);
+               }
                efree(variant_args);
 
                if(FAILED(hr))
                {
-                       error_message = php_COM_error_message(hr);
-                       php_error(E_WARNING, "Invoke() failed:  %s\n", error_message);
+                       error_message = php_COM_error_message(hr TSRMLS_CC);
+                       if (ErrString)
+                       {
+                               php_error(E_WARNING,"Invoke() failed: %s %s", error_message, ErrString);
+                               pefree(ErrString, 1);
+                       }
+                       else
+                       {
+                               php_error(E_WARNING,"Invoke() failed: %s", error_message);
+                       }
                        LocalFree(error_message);
                        return FAILURE;
                }
@@ -807,14 +851,14 @@ PHP_FUNCTION(com_invoke)
        comval *obj;
        int type;
        int arg_count = ZEND_NUM_ARGS();
-       VARIANT var_result;
+       VARIANT *var_result;
 
        if(arg_count<2)
        {
                WRONG_PARAM_COUNT;
        }
        arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
-       if(getParametersArray(ht, arg_count, arguments)==FAILURE)
+       if(getParametersArray(ht, arg_count, arguments) == FAILURE)
        {
                RETURN_FALSE;
        }
@@ -827,20 +871,27 @@ PHP_FUNCTION(com_invoke)
        obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%d is not a COM object handler", Z_STRVAL_P(function_name));
+               php_error(E_WARNING,"%d is not a COM object handler", Z_STRVAL_P(function_name));
                RETURN_FALSE;
        }
 
        /* obtain property/method handler */
        convert_to_string_ex(&function_name);
 
-       if(do_COM_invoke(obj, function_name, &var_result, arguments+2, arg_count-2)==FAILURE)
+       ALLOC_VARIANT(var_result);
+
+       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;
        }
-       efree(arguments);
 
-       php_variant_to_pval(&var_result, return_value, 0, codepage);
+       php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC);
+
+       FREE_VARIANT(var_result);
+       efree(arguments);
 }
 /* }}} */
 
@@ -868,11 +919,11 @@ PHP_FUNCTION(com_release)
        obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%d is not a COM object handler");
+               php_error(E_WARNING,"%d is not a COM object handler");
                RETURN_FALSE;
        }
 
-       RETURN_LONG(php_COM_release(obj))
+       RETURN_LONG(php_COM_release(obj TSRMLS_CC))
 }
 /* }}} */
 
@@ -900,53 +951,52 @@ PHP_FUNCTION(com_addref)
        obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%d is not a COM object handler");
+               php_error(E_WARNING,"%d is not a COM object handler");
                RETURN_FALSE;
        }
 
-       RETURN_LONG(php_COM_addref(obj));
+       RETURN_LONG(php_COM_addref(obj TSRMLS_CC));
 }
 /* }}} */
 
-static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup)
+static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup TSRMLS_DC)
 {
        pval function_name;
        int retval;
 
        ZVAL_STRINGL(&function_name, "Item", 4, 0);
-       retval = do_COM_invoke(array, &function_name, result, &property, 1);
+       retval = do_COM_invoke(array, &function_name, result, &property, 1 TSRMLS_CC);
        if(cleanup)
        {
-               php_COM_release(array);
-               efree(array);
+               php_COM_destruct(array TSRMLS_CC);
        }
 
        return retval;
 }
 
-static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup)
+static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup TSRMLS_DC)
 {
        DISPID dispid;
        HRESULT hr;
        OLECHAR *propname;
        char *error_message;
        DISPPARAMS dispparams;
-
+       char *ErrString;
 
        /* obtain property handler */
-       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage);
+       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage TSRMLS_CC);
 
-       hr = php_COM_get_ids_of_names(obj, &propname, &dispid);
+       hr = php_COM_get_ids_of_names(obj, &propname, &dispid TSRMLS_CC);
 
        if(FAILED(hr))
        {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING, "Unable to lookup %s:  %s\n", Z_STRVAL_P(arg_property), error_message);
+               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)
                {
-                       php_COM_release(obj);
+                       php_COM_destruct(obj TSRMLS_CC);
                }
                return FAILURE;
        }
@@ -954,17 +1004,25 @@ static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property,
        dispparams.cArgs = 0;
        dispparams.cNamedArgs = 0;
 
-       hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result);
+       hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC);
 
        if(FAILED(hr))
        {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING, "PropGet() failed:  %s\n", error_message);
+               error_message = php_COM_error_message(hr TSRMLS_CC);
+               if (ErrString)
+               {
+                       php_error(E_WARNING,"PropGet() failed: %s %s", error_message, ErrString);
+                       pefree(ErrString, 1);
+               }
+               else
+               {
+                       php_error(E_WARNING,"PropGet() failed: %s", error_message);
+               }
                LocalFree(error_message);
                efree(propname);
                if(cleanup)
                {
-                       php_COM_release(obj);
+                       php_COM_destruct(obj TSRMLS_CC);
                }
                return FAILURE;
        }
@@ -972,65 +1030,81 @@ static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property,
        efree(propname);
        if(cleanup)
        {
-               php_COM_release(obj);
+               php_COM_destruct(obj TSRMLS_CC);
        }
        return SUCCESS;
 }
 
 
-static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, pval *value)
+static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, pval *value TSRMLS_DC)
 {
        DISPID dispid;
        HRESULT hr;
        OLECHAR *propname;
        char *error_message;
-       VARIANT *var_result;
+       VARIANT *var_result, *new_value;
        DISPPARAMS dispparams;
-       VARIANT new_value;
        DISPID mydispid = DISPID_PROPERTYPUT;
-
+       char *ErrString;
 
        ALLOC_VARIANT(var_result);
+       ALLOC_VARIANT(new_value);
 
        /* obtain property handler */
-       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage);
+       propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage TSRMLS_CC);
 
-       hr = php_COM_get_ids_of_names(obj, &propname, &dispid);
+       hr = php_COM_get_ids_of_names(obj, &propname, &dispid TSRMLS_CC);
 
        if(FAILED(hr))
        {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING, "Unable to lookup %s:  %s\n", Z_STRVAL_P(arg_property), error_message);
+               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);
+
+               FREE_VARIANT(var_result);
+               FREE_VARIANT(new_value);
+
                RETURN_FALSE;
        }
 
-       php_pval_to_variant(value, &new_value, codepage);
-       dispparams.rgvarg = &new_value;
+       php_pval_to_variant(value, new_value, codepage TSRMLS_CC);
+       dispparams.rgvarg = new_value;
        dispparams.rgdispidNamedArgs = &mydispid;
        dispparams.cArgs = 1;
        dispparams.cNamedArgs = 1;
 
-       hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYPUT, &dispparams, NULL);
+       hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYPUT, &dispparams, NULL, &ErrString TSRMLS_CC);
 
        if(FAILED(hr))
        {
-               error_message = php_COM_error_message(hr);
-               php_error(E_WARNING, "PropPut() failed:  %s\n", error_message);
+               error_message = php_COM_error_message(hr TSRMLS_CC);
+               if (ErrString)
+               {
+                       php_error(E_WARNING,"PropPut() failed: %s %s", error_message, ErrString);
+                       pefree(ErrString, 1);
+               }
+               else
+               {
+                       php_error(E_WARNING,"PropPut() failed: %s", error_message);
+               }
                LocalFree(error_message);
                efree(propname);
+
+               FREE_VARIANT(var_result);
+               FREE_VARIANT(new_value);
+
                RETURN_FALSE;
        }
 
        dispparams.cArgs = 0;
        dispparams.cNamedArgs = 0;
 
-       hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result);
+       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, 0, codepage);
+               php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC);
        }
        else
        {
@@ -1038,7 +1112,14 @@ static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property,
                zval_copy_ctor(return_value);
        }
 
-       efree(var_result);
+       if (ErrString)
+       {
+               pefree(ErrString, 1);
+       }
+
+       FREE_VARIANT(var_result);
+       FREE_VARIANT(new_value);
+
        efree(propname);
 }
 
@@ -1050,9 +1131,9 @@ PHP_FUNCTION(com_propget)
        pval *arg_comval, *arg_property;
        int type;
        comval *obj;
-       VARIANT var_result;
+       VARIANT *var_result;
 
-       if(ZEND_NUM_ARGS()!=2 || getParameters(ht, 2, &arg_comval, &arg_property)==FAILURE)
+       if((ZEND_NUM_ARGS() != 2) || (getParameters(ht, 2, &arg_comval, &arg_property) == FAILURE))
        {
                WRONG_PARAM_COUNT;
        }
@@ -1062,15 +1143,21 @@ PHP_FUNCTION(com_propget)
        obj = (comval *)zend_list_find(Z_LVAL_P(arg_comval), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%d is not a COM object handler", Z_LVAL_P(arg_comval));
+               php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_comval));
        }
        convert_to_string_ex(&arg_property);
 
-       if(do_COM_propget(&var_result, obj, arg_property, 0)==FAILURE)
+       ALLOC_VARIANT(var_result);
+
+       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, 0, codepage);
+
+       php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC);
+
+       FREE_VARIANT(var_result);
 }
 /* }}} */
 
@@ -1094,11 +1181,11 @@ PHP_FUNCTION(com_propput)
        obj = (comval *)zend_list_find(Z_LVAL_P(arg_comval), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%d is not a COM object handler", Z_LVAL_P(arg_comval));
+               php_error(E_WARNING,"%d is not a COM object handler", Z_LVAL_P(arg_comval));
        }
        convert_to_string_ex(&arg_property);
 
-       do_COM_propput(return_value, obj, arg_property, arg_value);
+       do_COM_propput(return_value, obj, arg_property, arg_value TSRMLS_CC);
 }
 /* }}} */
 
@@ -1127,7 +1214,7 @@ PHP_FUNCTION(com_load_typelib)
        }
 
        convert_to_string_ex(&arg_typelib);
-       pTL = php_COM_find_typelib(Z_STRVAL_P(arg_typelib), mode);
+       pTL = php_COM_find_typelib(Z_STRVAL_P(arg_typelib), mode TSRMLS_CC);
        if(php_COM_load_typelib(pTL, mode TSRMLS_CC) == SUCCESS)
        {
                pTL->lpVtbl->Release(pTL);
@@ -1169,38 +1256,42 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer
        for(element=property_reference->elements_list->head; element; element=element->next)
        {
                overloaded_property = (zend_overloaded_element *) element->data;
-               VariantInit(var_result);
                switch(overloaded_property->type)
                {
                        case OE_IS_ARRAY:
-                               if(do_COM_offget(var_result, obj, &overloaded_property->element, FALSE) == FAILURE)
+                               if(do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE)
                                {
-                                       efree(var_result);
-                                       efree(obj_prop);
+                                       FREE_VARIANT(var_result);
+                                       FREE_COM(obj_prop);
+
                                        return return_value;
                                }
                                break;
 
                        case OE_IS_OBJECT:
-                               if(do_COM_propget(var_result, obj, &overloaded_property->element, FALSE) == FAILURE)
+                               if(do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE)
                                {
-                                       efree(var_result);
-                                       efree(obj_prop);
+                                       FREE_VARIANT(var_result);
+                                       FREE_COM(obj_prop);
+
                                        return return_value;
                                }
                                break;
 
                        case OE_IS_METHOD:
                                {
+                                       FREE_VARIANT(var_result);
                                        if(obj != obj_prop)
                                        {
-                                               efree(obj_prop);
+                                               FREE_COM(obj_prop);
+       
                                                return_value = *object;
                                                ZVAL_ADDREF(&return_value);
                                        }
-
-                                       efree(var_result);              
-
+                                       else
+                                       {
+                                               RETVAL_COM(obj);
+                                       }
                                        return return_value;
                                }
                                break;
@@ -1210,26 +1301,28 @@ PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_refer
                {
                        if(V_DISPATCH(var_result) == NULL)
                        {
-                               efree(var_result);
-                               efree(obj_prop);
+                               FREE_VARIANT(var_result);
+                               FREE_COM(obj_prop);
+                               
                                return return_value;
                        }
 
                        obj = obj_prop;
-                       php_COM_set(obj, V_DISPATCH(var_result), TRUE);
-
-                       RETVAL_COM(obj);
+                       php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC);
                }
                else
                {
-                       efree(obj_prop);
+                       php_variant_to_pval(var_result, &return_value, FALSE, codepage TSRMLS_CC);
+
+                       FREE_COM(obj_prop);
                        obj_prop = NULL;
-                       php_variant_to_pval(var_result, &return_value, FALSE, codepage);
                }
 
+               VariantInit(var_result);        // to protect C_DISPATCH(obj) from being freed when var_result is destructed
                pval_destructor(&overloaded_property->element);
        }
-       efree(var_result);              
+
+       FREE_VARIANT(var_result);              
 
        return return_value;
 }
@@ -1241,9 +1334,9 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere
        zend_llist_element *element;
        pval **comval_handle;
        pval *object = property_reference->object;
-       comval *obj;
+       comval *obj, *obj_prop;
        int type;
-       VARIANT var_result;
+       VARIANT *var_result;
        TSRMLS_FETCH();
 
        /* fetch the IDispatch interface */
@@ -1253,46 +1346,72 @@ PHPAPI int php_COM_set_property_handler(zend_property_reference *property_refere
        {
                return FAILURE;
        }
-       var_result.vt = VT_DISPATCH;
-       var_result.pdispVal = C_DISPATCH(obj);
+       
+       ALLOC_COM(obj_prop);
+       ALLOC_VARIANT(var_result);
 
-       for(element=property_reference->elements_list->head; element && 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)
                {
                        case OE_IS_ARRAY:
-                               break;
-                       case OE_IS_OBJECT:
-                               if(V_VT(&var_result) != VT_DISPATCH)
+                               if(do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE)
                                {
+                                       FREE_VARIANT(var_result);
+                                       FREE_COM(obj_prop);
+
                                        return FAILURE;
                                }
-                               else
+                               break;
+
+                       case OE_IS_OBJECT:
+                               if(do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE)
                                {
-                                       do_COM_propget(&var_result, obj, &overloaded_property->element, element!=property_reference->elements_list->head);
+                                       FREE_VARIANT(var_result);
+                                       FREE_COM(obj_prop);
+
+                                       return FAILURE;
                                }
                                break;
+
                        case OE_IS_METHOD:
                                /* this shouldn't happen */
                                return FAILURE;
+                               break;
                }
 
-               pval_destructor(&overloaded_property->element);
-       }
+               if(V_VT(var_result) == VT_DISPATCH)
+               {
+                       if(V_DISPATCH(var_result) == NULL)
+                       {
+                               FREE_VARIANT(var_result);
+                               FREE_COM(obj_prop);
 
-       if(V_VT(&var_result) != VT_DISPATCH)
-       {
-               return FAILURE;
-       }
-       obj = (comval *) emalloc(sizeof(comval));
-       C_HASTLIB(obj) = FALSE;
-       C_DISPATCH(obj) = V_DISPATCH(&var_result);
+                               return FAILURE;
+                       }
+
+                       obj = obj_prop;
+                       php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC);
+               }
+               else
+               {
+                       FREE_COM(obj_prop);
+                       FREE_VARIANT(var_result);
 
+                       return FAILURE;
+               }
+
+               VariantInit(var_result);        // to protect C_DISPATCH(obj) from being freed when var_result is destructed
+               pval_destructor(&overloaded_property->element);
+       }
+       FREE_VARIANT(var_result);
+       
        overloaded_property = (zend_overloaded_element *) element->data;
-       do_COM_propput(&result, obj, &overloaded_property->element, value);
+       do_COM_propput(&result, obj, &overloaded_property->element, value TSRMLS_CC);
+       FREE_COM(obj_prop);
+
        pval_destructor(&overloaded_property->element);
-       efree(obj);
 
        return SUCCESS;
 }
@@ -1349,12 +1468,12 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
        if(zend_llist_count(property_reference->elements_list)==1
           && !strcmp(Z_STRVAL_P(&function_name->element), "release"))
        {
-               RETVAL_LONG(php_COM_release(obj));
+               RETVAL_LONG(php_COM_release(obj TSRMLS_CC));
        }
        else if(zend_llist_count(property_reference->elements_list)==1
                        && !strcmp(Z_STRVAL_P(&function_name->element), "addref"))
        {
-               RETVAL_LONG(php_COM_addref(obj));
+               RETVAL_LONG(php_COM_addref(obj TSRMLS_CC));
        }
        else
        {
@@ -1363,22 +1482,21 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
                int arg_count = ZEND_NUM_ARGS();
 
                ALLOC_VARIANT(var_result);
-               VariantInit(var_result);
 
                arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
                getParametersArray(ht, arg_count, arguments);
 
-               if(do_COM_invoke(obj , &function_name->element, var_result, arguments, arg_count)==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, 0, codepage);
+                       php_variant_to_pval(var_result, return_value, FALSE, codepage TSRMLS_CC);
                }
 
+               FREE_VARIANT(var_result);
                efree(arguments);
-               efree(var_result);
        }
 
        if(property.refcount == 1)
@@ -1388,7 +1506,7 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
        pval_destructor(&function_name->element);
 }
 
-static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
+static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC)
 {
        ITypeLib *TypeLib = NULL;
        char *strtok_buf, *major, *minor;
@@ -1409,7 +1527,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
        major = php_strtok_r(NULL, ",", &strtok_buf);
        minor = php_strtok_r(NULL, ",", &strtok_buf);
 
-       p = php_char_to_OLECHAR(search_string, strlen(search_string), codepage);
+       p = php_char_to_OLECHAR(search_string, strlen(search_string), codepage TSRMLS_CC);
        /* Is the string a GUID ? */
 
        if(!FAILED(CLSIDFromString(p, &clsid)))
@@ -1483,7 +1601,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
                        /* 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;
@@ -1548,7 +1666,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode)
                                                        str = emalloc(strlen(keyname)+strlen(version)+20); /* 18 == safety, 2 == extra comma and \0 */
                                                        sprintf(str, "%s,%d,%d", keyname, major, minor);
                                                        efree(keyname);
-                                                       TypeLib = php_COM_find_typelib(str, mode);
+                                                       TypeLib = php_COM_find_typelib(str, mode TSRMLS_CC);
                                                        efree(str);
                                                        /* This is probbaly much harder to read and follow */
                                                        /* But it is MUCH more effiecient than trying to */
@@ -1611,7 +1729,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC)
                        TypeLib->lpVtbl->GetTypeInfo(TypeLib, i, &TypeInfo);
 
                        j=0;
-                       while(TypeInfo->lpVtbl->GetVarDesc(TypeInfo, j, &pVarDesc)==S_OK)
+                       while(SUCCEEDED(TypeInfo->lpVtbl->GetVarDesc(TypeInfo, j, &pVarDesc)))
                        {
                                BSTR bstr_ids;
                                char *ids;
@@ -1624,7 +1742,7 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC)
                                        j++;
                                        continue;
                                }
-                               ids = php_OLECHAR_to_char(bstr_ids, NULL, 1, codepage);
+                               ids = php_OLECHAR_to_char(bstr_ids, NULL, 1, codepage TSRMLS_CC);
                                SysFreeString(bstr_ids);
                                c.name_len = strlen(ids)+1;
                                c.name = ids;
@@ -1634,14 +1752,14 @@ static int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC)
                                        /* Check to see if they are the same */
                                        if (!compare_function(&results, &c.value, &exists TSRMLS_CC) && INI_INT("com.autoregister_verbose"))
                                        {
-                                               php_error(E_WARNING, "Type library value %s is already defined and has a different value", c.name);
+                                               php_error(E_WARNING,"Type library value %s is already defined and has a different value", c.name);
                                        }
                                        free(ids);
                                        j++;
                                        continue;
                                }
 
-                               php_variant_to_pval(pVarDesc->lpvarValue, &c.value, FALSE, codepage);
+                               php_variant_to_pval(pVarDesc->lpvarValue, &c.value, FALSE, codepage TSRMLS_CC);
                                c.flags = mode;
 
                                /* Before registering the contsnt, let's see if we can find it */
@@ -1678,7 +1796,7 @@ PHP_FUNCTION(com_isenum)
        obj = (comval *) zend_list_find(Z_LVAL_PP(comval_handle), &type);
        if(!obj || (type != IS_COM))
        {
-               php_error(E_WARNING, "%s is not a COM object handler", "");
+               php_error(E_WARNING,"%s is not a COM object handler", "");
                RETURN_FALSE;
        }
 
@@ -1686,14 +1804,14 @@ PHP_FUNCTION(com_isenum)
 }
 /* }}} */
 
-void php_register_COM_class(TSRMLS_D)
+static void php_register_COM_class(TSRMLS_D)
 {
-       INIT_OVERLOADED_CLASS_ENTRY(com_class_entry, "COM", NULL,
+       INIT_OVERLOADED_CLASS_ENTRY(COM_class_entry, "COM", NULL,
                                                                php_COM_call_function_handler,
                                                                php_COM_get_property_handler,
                                                                php_COM_set_property_handler);
 
-       zend_register_internal_class(&com_class_entry TSRMLS_CC);
+       zend_register_internal_class(&COM_class_entry TSRMLS_CC);
 }
 
 PHP_MINIT_FUNCTION(COM)
index 13ac1d68b857728fc9d4cdc825d101fcc8287fa4..99c17782dfda07b382594d316386a7da32930b9f 100644 (file)
@@ -3,7 +3,9 @@
 
 #if PHP_WIN32
 
-#include "oleauto.h"
+BEGIN_EXTERN_C()
+
+#include <oleauto.h>
 
 typedef struct comval_ {
 #ifdef _DEBUG
@@ -19,6 +21,8 @@ typedef struct comval_ {
        } i;
 } comval;
 
+END_EXTERN_C()
+
 #define ZVAL_COM(z,o) {                                                                                                                                \
                        zval *handle;                                                                                                                   \
                        HashTable *properties;                                                                                                  \
@@ -32,14 +36,18 @@ typedef struct comval_ {
                                                                                                                                                                        \
                        zval_copy_ctor(handle);                                                                                                 \
                        zend_hash_index_update(properties, 0, &handle, sizeof(zval *), NULL);   \
-                       object_and_properties_init(z, &com_class_entry, properties);                    \
+                       object_and_properties_init(z, &COM_class_entry, properties);                    \
                }
 
-#define RETVAL_COM(o)  ZVAL_COM(&return_value, o)
+#define RETVAL_COM(o)  ZVAL_COM(&return_value, o);
 #define RETURN_COM(o)  RETVAL_COM(o)                                                                                           \
                                                return;
 
-#define ALLOC_COM(z)   (z) = (comval *) emalloc(sizeof(comval))
+#define ALLOC_COM(z)   (z) = (comval *) emalloc(sizeof(comval));                                       \
+                                               C_REFCOUNT(z) = 0;
+
+#define FREE_COM(z)            efree(z);
+
 #define IS_COM                 php_COM_get_le_comval()
 
 #define C_HASTLIB(x)   ((x)->typelib)
index 0f9bcbd32b7a59cf60ac94ecf25725db0d336735..21dace5c188a80566e91fa13e96358fe022d1766 100644 (file)
 
 /* prototypes */
 
-PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage TSRMLS_DC);
-PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage TSRMLS_DC);
-PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent, int codepage);
-PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage);
-PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent, int codepage);
-
 static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int codepage TSRMLS_DC);
 static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC);
 
@@ -50,7 +44,7 @@ static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC);
 PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage TSRMLS_DC)
 {
        int type = VT_EMPTY;    /* default variant type */
-       
+
        switch(Z_TYPE_P(pval_arg))
        {
                case IS_NULL:
@@ -64,7 +58,7 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage T
                case IS_OBJECT:
                        if(!strcmp(Z_OBJCE_P(pval_arg)->name, "VARIANT"))
                        {
-                               type = VT_VARIANT;
+                               type = VT_VARIANT|VT_BYREF;
                        }
                        else if(!strcmp(Z_OBJCE_P(pval_arg)->name, "COM"))
                        {
@@ -93,10 +87,10 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage T
                case IS_STRING:
                        type = VT_BSTR;
                        break;
-                       }
+       }
 
        if(pval_arg->is_ref)    /* deprecated, implemented for downwards compatiblity */
-                       {
+       {
                type |= VT_BYREF;
        }
 
@@ -116,22 +110,22 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
        V_VT(var_arg) = type;
 
        if(V_VT(var_arg) & VT_ARRAY)
-                       {
-                               /* For now we'll just handle single dimension arrays, we'll use the data type of the first element for the
-                                  output data type */
-                               HashTable *ht = Z_ARRVAL(*pval_arg);
-                               int numberOfElements = zend_hash_num_elements(ht);
-                               SAFEARRAY *safeArray;
-                               SAFEARRAYBOUND bounds[1];
-                               VARIANT *v;
-                               zval       **entry;        /* An entry in the input array */
-                               
+       {
+               /* For now we'll just handle single dimension arrays, we'll use the data type of the first element for the
+                  output data type */
+               HashTable *ht = Z_ARRVAL(*pval_arg);
+               int numberOfElements = zend_hash_num_elements(ht);
+               SAFEARRAY *safeArray;
+               SAFEARRAYBOUND bounds[1];
+               VARIANT *v;
+               zval **entry;        /* An entry in the input array */
+               
                type &= ~VT_ARRAY;
 
                if(V_VT(var_arg) == (VT_ARRAY|VT_BYREF))                /* == is intended, because VT_*|VT_BYREF|VT_ARRAY means something diffrent */
                {
                        type &= ~VT_BYREF;
-                                       ALLOC_VARIANT(V_VARIANTREF(var_arg));
+                       ALLOC_VARIANT(V_VARIANTREF(var_arg));
                        var_arg = V_VARIANTREF(var_arg);                /* put the array in that VARIANT */
                }
 
@@ -141,7 +135,7 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
                
                if(NULL == safeArray)
                {
-                       php_error( E_WARNING, "Unable to convert php array to VARIANT array - %s", numberOfElements ? "" : "(Empty input array)");
+                       php_error( E_WARNING,"Unable to convert php array to VARIANT array - %s", numberOfElements ? "" : "(Empty input array)");
                        ZVAL_FALSE(pval_arg);
                }
                else
@@ -158,20 +152,20 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
                                        if((zend_hash_get_current_data(ht, (void **)&entry) == SUCCESS) && (entry != NULL)) /* Get a pointer to the php array element */
                                        {
                                                /* Add another value to the safe array */
-                                               if(SUCCEEDED(SafeArrayPtrOfIndex( safeArray, &i, &v)))/* Pointer to output element entry retrieved successfully */
+                                               if(SUCCEEDED(SafeArrayPtrOfIndex( safeArray, &i, &v)))          /* Pointer to output element entry retrieved successfully */
                                                {
-                                                  if(type)     /* explicit type */
-                                                  {
+                                                       if(type)        /* explicit type */
+                                                       {
                                                           pval_to_variant_ex(*entry, v, type, codepage TSRMLS_CC);             /* Do the required conversion */
-                                                  }
-                                                  else
-                                                  {
+                                                       }
+                                                       else
+                                                       {
                                                                php_pval_to_variant(*entry, v, codepage TSRMLS_CC);                    /* Do the required conversion */
                                                        }
                                                }
                                                else
                                                {
-                                                       php_error( E_WARNING, "phpArrayToSafeArray() - Unable to retrieve pointer to output element number (%d)", i);
+                                                       php_error( E_WARNING,"phpArrayToSafeArray() - Unable to retrieve pointer to output element number (%d)", i);
                                                }
                                        }
                                        zend_hash_move_forward(ht);
@@ -180,207 +174,210 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
                        }
                        else
                        {
-                               php_error( E_WARNING, "phpArrayToSafeArray() - Unable to lock safeArray");
+                               php_error( E_WARNING,"phpArrayToSafeArray() - Unable to lock safeArray");
                        }
                }
        }
        else
-   {
-          switch(V_VT(var_arg))
-          {
-                  case VT_UI1:
-                          convert_to_long_ex(&pval_arg);
-                          V_UI1(var_arg) = (unsigned char)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_I2:
-                          convert_to_long_ex(&pval_arg);
-                          V_I2(var_arg) = (short)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_I4:
-                          convert_to_long_ex(&pval_arg);
-                          V_I4(var_arg) = Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_R4:
-                          convert_to_double_ex(&pval_arg);
-                          V_R4(var_arg) = (float)Z_DVAL_P(pval_arg);
-                          break;
-   
-                  case VT_R8:
-                          convert_to_double_ex(&pval_arg);
-                          V_R8(var_arg) = Z_DVAL_P(pval_arg);
-                          break;
-   
-                  case VT_BOOL:
-                          convert_to_boolean_ex(&pval_arg);
-                          V_BOOL(var_arg) = (short)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_ERROR:
-                          convert_to_long_ex(&pval_arg);
-                          V_ERROR(var_arg) = Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_CY:
-                          convert_to_double_ex(&pval_arg);
-                          VarCyFromR8(Z_DVAL_P(pval_arg), &V_CY(var_arg));
-                          break;
-   
-                  case VT_DATE:
-                          {
-                                  SYSTEMTIME wintime;
-                                  struct tm *phptime;
-   
-                                  phptime = gmtime(&(pval_arg->value.lval));
-                                  memset(&wintime, 0, sizeof(wintime));
-   
-                                  wintime.wYear = phptime->tm_year + 1900;
-                                  wintime.wMonth = phptime->tm_mon + 1;
-                                  wintime.wDay = phptime->tm_mday;
-                                  wintime.wHour = phptime->tm_hour;
-                                  wintime.wMinute = phptime->tm_min;
-                                  wintime.wSecond = phptime->tm_sec;
-   
-                                  SystemTimeToVariantTime(&wintime, &V_DATE(var_arg));
-                          }
-                          break;
-   
-                  case VT_BSTR:
-                          convert_to_string_ex(&pval_arg);
-                          unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage);
-                          V_BSTR(var_arg) = SysAllocString(unicode_str);
-                          efree(unicode_str);
-                          break;
-   
-                  case VT_DECIMAL:
-                          convert_to_string_ex(&pval_arg);
-                          unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage);
-                          VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, &V_DECIMAL(var_arg));
-                          break;
-   
-                  case VT_DECIMAL|VT_BYREF:
-                          convert_to_string_ex(&pval_arg);
-                          unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage);
-                          VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, V_DECIMALREF(var_arg));
-                          break;
-   
-                  case VT_UNKNOWN:
+       {
+               switch(V_VT(var_arg))
+               {
+                       case VT_UI1:
+                               convert_to_long_ex(&pval_arg);
+                               V_UI1(var_arg) = (unsigned char)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_I2:
+                               convert_to_long_ex(&pval_arg);
+                               V_I2(var_arg) = (short)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_I4:
+                               convert_to_long_ex(&pval_arg);
+                               V_I4(var_arg) = Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_R4:
+                               convert_to_double_ex(&pval_arg);
+                               V_R4(var_arg) = (float)Z_DVAL_P(pval_arg);
+                               break;
+
+                       case VT_R8:
+                               convert_to_double_ex(&pval_arg);
+                               V_R8(var_arg) = Z_DVAL_P(pval_arg);
+                               break;
+
+                       case VT_BOOL:
+                               convert_to_boolean_ex(&pval_arg);
+                               V_BOOL(var_arg) = (short)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_ERROR:
+                               convert_to_long_ex(&pval_arg);
+                               V_ERROR(var_arg) = Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_CY:
+                               convert_to_double_ex(&pval_arg);
+                               VarCyFromR8(Z_DVAL_P(pval_arg), &V_CY(var_arg));
+                               break;
+
+                       case VT_DATE:
+                               {
+                                       SYSTEMTIME wintime;
+                                       struct tm *phptime;
+
+                                       phptime = gmtime(&(pval_arg->value.lval));
+                                       memset(&wintime, 0, sizeof(wintime));
+
+                                       wintime.wYear = phptime->tm_year + 1900;
+                                       wintime.wMonth = phptime->tm_mon + 1;
+                                       wintime.wDay = phptime->tm_mday;
+                                       wintime.wHour = phptime->tm_hour;
+                                       wintime.wMinute = phptime->tm_min;
+                                       wintime.wSecond = phptime->tm_sec;
+
+                                       SystemTimeToVariantTime(&wintime, &V_DATE(var_arg));
+                               }
+                               break;
+
+                       case VT_BSTR:
+                               convert_to_string_ex(&pval_arg);
+                               unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
+                               V_BSTR(var_arg) = SysAllocString(unicode_str);
+                               efree(unicode_str);
+                               break;
+
+                       case VT_DECIMAL:
+                               convert_to_string_ex(&pval_arg);
+                               unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
+                               VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, &V_DECIMAL(var_arg));
+                               break;
+
+                       case VT_DECIMAL|VT_BYREF:
+                               convert_to_string_ex(&pval_arg);
+                               unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
+                               VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, V_DECIMALREF(var_arg));
+                               break;
+
+                       case VT_UNKNOWN:
                        comval_to_variant(pval_arg, var_arg TSRMLS_CC);
-                          if(V_VT(var_arg) != VT_DISPATCH)
-                          {
-                                  VariantInit(var_arg);
-                          }
-                          else
-                          {
-                                  V_VT(var_arg) = VT_UNKNOWN;
-                                  V_UNKNOWN(var_arg) = (IUnknown *) V_DISPATCH(var_arg);
-                          }
-                          break;
-   
-                  case VT_DISPATCH:
+                               if(V_VT(var_arg) != VT_DISPATCH)
+                               {
+                                       VariantInit(var_arg);
+                               }
+                               else
+                               {
+                                       V_VT(var_arg) = VT_UNKNOWN;
+                                       V_UNKNOWN(var_arg) = (IUnknown *) V_DISPATCH(var_arg);
+                               }
+                               break;
+
+                       case VT_DISPATCH:
                                comval_to_variant(pval_arg, var_arg TSRMLS_CC);
-                          if(V_VT(var_arg) != VT_DISPATCH)
-                          {
-                                  VariantInit(var_arg);
-                          }
-                          break;
-   
-                  case VT_UI1|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_UI1REF(var_arg) = (unsigned char FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_I2|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_I2REF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_I4|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_I4REF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_R4|VT_BYREF:
-                          convert_to_double(pval_arg);
-                          V_R4REF(var_arg) = (float FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_R8|VT_BYREF:
-                          convert_to_double(pval_arg);
-                          V_R8REF(var_arg) = (double FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_BOOL|VT_BYREF:
-                          convert_to_boolean(pval_arg);
-                          V_BOOLREF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_ERROR|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_ERRORREF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_CY|VT_BYREF:
-                          convert_to_double_ex(&pval_arg);
-                          VarCyFromR8(pval_arg->value.dval, var_arg->pcyVal);
-                          break;
-   
-                  case VT_DATE|VT_BYREF:
-                          {
-                                  SYSTEMTIME wintime;
-                                  struct tm *phptime;
-   
-                                  phptime = gmtime(&(pval_arg->value.lval));
-                                  memset(&wintime, 0, sizeof(wintime));
-   
-                                  wintime.wYear   = phptime->tm_year + 1900;
-                                  wintime.wMonth  = phptime->tm_mon + 1;
-                                  wintime.wDay    = phptime->tm_mday;
-                                  wintime.wHour   = phptime->tm_hour;
-                                  wintime.wMinute = phptime->tm_min;
-                                  wintime.wSecond = phptime->tm_sec;
-   
-                                  SystemTimeToVariantTime(&wintime, var_arg->pdate);
-                          }
-                          break;
-   
-                  case VT_BSTR|VT_BYREF:
-                          convert_to_string(pval_arg);
-                          V_BSTRREF(var_arg) = (BSTR FAR*) emalloc(sizeof(BSTR FAR*));
-                          unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage);
-                          *V_BSTRREF(var_arg) = SysAllocString(unicode_str);
-                          efree(unicode_str);
-                          break;
-   
-                  case VT_UNKNOWN|VT_BYREF:
+                               if(V_VT(var_arg) != VT_DISPATCH)
+                               {
+                                       VariantInit(var_arg);
+                               }
+                               break;
+
+                       case VT_UI1|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_UI1REF(var_arg) = (unsigned char FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_I2|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_I2REF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_I4|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_I4REF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_R4|VT_BYREF:
+                               convert_to_double(pval_arg);
+                               V_R4REF(var_arg) = (float FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_R8|VT_BYREF:
+                               convert_to_double(pval_arg);
+                               V_R8REF(var_arg) = (double FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_BOOL|VT_BYREF:
+                               convert_to_boolean(pval_arg);
+                               V_BOOLREF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_ERROR|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_ERRORREF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_CY|VT_BYREF:
+                               convert_to_double_ex(&pval_arg);
+                               VarCyFromR8(pval_arg->value.dval, var_arg->pcyVal);
+                               break;
+
+                       case VT_DATE|VT_BYREF:
+                               {
+                                       SYSTEMTIME wintime;
+                                       struct tm *phptime;
+
+                                       phptime = gmtime(&(pval_arg->value.lval));
+                                       memset(&wintime, 0, sizeof(wintime));
+
+                                       wintime.wYear   = phptime->tm_year + 1900;
+                                       wintime.wMonth  = phptime->tm_mon + 1;
+                                       wintime.wDay    = phptime->tm_mday;
+                                       wintime.wHour   = phptime->tm_hour;
+                                       wintime.wMinute = phptime->tm_min;
+                                       wintime.wSecond = phptime->tm_sec;
+
+                                       SystemTimeToVariantTime(&wintime, var_arg->pdate);
+                               }
+                               break;
+
+                       case VT_BSTR|VT_BYREF:
+                               convert_to_string(pval_arg);
+                               V_BSTRREF(var_arg) = (BSTR FAR*) emalloc(sizeof(BSTR FAR*));
+                               unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
+                               *V_BSTRREF(var_arg) = SysAllocString(unicode_str);
+                               efree(unicode_str);
+                               break;
+
+                       case VT_UNKNOWN|VT_BYREF:
                                comval_to_variant(pval_arg, var_arg TSRMLS_CC);
-                          if(V_VT(var_arg) != VT_DISPATCH)
-                          {
-                                  VariantInit(var_arg);
-                          }
-                          else
-                          {
-                                  V_VT(var_arg) = VT_UNKNOWN|VT_BYREF;
+                               if(V_VT(var_arg) != VT_DISPATCH)
+                               {
+                                       VariantInit(var_arg);
+                               }
+                               else
+                               {
+                                       V_VT(var_arg) = VT_UNKNOWN|VT_BYREF;
                                        V_UNKNOWNREF(var_arg) = (IUnknown **) &V_DISPATCH(var_arg);
-                          }
-                          break;
-   
-                  case VT_DISPATCH|VT_BYREF:
+                               }
+                               break;
+
+                       case VT_DISPATCH|VT_BYREF:
                                comval_to_variant(pval_arg, var_arg TSRMLS_CC);
-                          if(V_VT(var_arg) != VT_DISPATCH)
-                          {
-                                  VariantInit(var_arg);
-                          }
-                          else
-                          {
+                               if(V_VT(var_arg) != VT_DISPATCH)
+                               {
+                                       VariantInit(var_arg);
+                               }
+                               else
+                               {
                                        V_VT(var_arg) = VT_DISPATCH|VT_BYREF;
                                        V_DISPATCHREF(var_arg) = &V_DISPATCH(var_arg);
-                          }
-                          break;
-   
-                  case VT_VARIANT|VT_BYREF:
+                               }
+                               break;
+
+                       case VT_VARIANT:
+                               php_error(E_WARNING,"VT_VARIANT is invalid. Use VT_VARIANT|VT_BYREF instead.");
+                               /* break missing intentionally */
+                       case VT_VARIANT|VT_BYREF:
                                {
                                        int tp;
                                        pval **var_handle;
@@ -392,9 +389,9 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
                                        V_VARIANTREF(var_arg) = (VARIANT FAR*) zend_list_find(Z_LVAL_P(*var_handle), &tp);
 
                                        if(!V_VARIANTREF(var_arg) && (tp != IS_VARIANT))
-                             {
-                                     VariantInit(var_arg);
-                             }
+                                       {
+                                               VariantInit(var_arg);
+                                       }
                                }
                        /*
                                should be, but isn't :)
@@ -404,65 +401,65 @@ static void pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, int type, int c
                                        VariantInit(var_arg);
                                }
                        */
-                          break;
-   
-                  case VT_I1:
-                          convert_to_long_ex(&pval_arg);
-                          V_I1(var_arg) = (char)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UI2:
-                          convert_to_long_ex(&pval_arg);
-                          V_UI2(var_arg) = (unsigned short)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UI4:
-                          convert_to_long_ex(&pval_arg);
-                          V_UI4(var_arg) = (unsigned long)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_INT:
-                          convert_to_long_ex(&pval_arg);
-                          V_INT(var_arg) = (int)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UINT:
-                          convert_to_long_ex(&pval_arg);
-                          V_UINT(var_arg) = (unsigned int)Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_I1|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_I1REF(var_arg) = (char FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UI2|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_UI2REF(var_arg) = (unsigned short FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UI4|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_UI4REF(var_arg) = (unsigned long FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_INT|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_INTREF(var_arg) = (int FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  case VT_UINT|VT_BYREF:
-                          convert_to_long(pval_arg);
-                          V_UINTREF(var_arg) = (unsigned int FAR*) &Z_LVAL_P(pval_arg);
-                          break;
-   
-                  default:
-                          php_error(E_WARNING, "Type not supported or not yet implemented.");
-          }
-   }
+                               break;
+
+                       case VT_I1:
+                               convert_to_long_ex(&pval_arg);
+                               V_I1(var_arg) = (char)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UI2:
+                               convert_to_long_ex(&pval_arg);
+                               V_UI2(var_arg) = (unsigned short)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UI4:
+                               convert_to_long_ex(&pval_arg);
+                               V_UI4(var_arg) = (unsigned long)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_INT:
+                               convert_to_long_ex(&pval_arg);
+                               V_INT(var_arg) = (int)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UINT:
+                               convert_to_long_ex(&pval_arg);
+                               V_UINT(var_arg) = (unsigned int)Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_I1|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_I1REF(var_arg) = (char FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UI2|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_UI2REF(var_arg) = (unsigned short FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UI4|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_UI4REF(var_arg) = (unsigned long FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_INT|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_INTREF(var_arg) = (int FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       case VT_UINT|VT_BYREF:
+                               convert_to_long(pval_arg);
+                               V_UINTREF(var_arg) = (unsigned int FAR*) &Z_LVAL_P(pval_arg);
+                               break;
+
+                       default:
+                               php_error(E_WARNING, "Type not supported or not yet implemented.");
+               }
+       }
 }
 
-PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent, int codepage)
+PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent, int codepage TSRMLS_DC)
 {
        /* Changed the function to return a value for recursive error testing */
        /* Existing calls will be unaffected by the change - so it */
@@ -488,7 +485,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                /* For now just validate that the SafeArray has one dimension */
                if (1 != (Dims = SafeArrayGetDim(array)))
                {
-                       php_error(E_WARNING, "Unsupported: multi-dimensional (%d) SafeArrays", Dims);
+                       php_error(E_WARNING,"Unsupported: multi-dimensional (%d) SafeArrays", Dims);
                        ZVAL_NULL(pval_arg);
                        return FAILURE;
                }
@@ -529,18 +526,18 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                hr = SafeArrayGetElement(array, indices, (VOID *) &(vv.lVal));
                        }
                        if (FAILED(hr))
-            {
+                       {
                                /* Failure to retieve an element probably means the array is sparse */
                                /* So leave the php array sparse too */
                                continue;
-            }
+                       }
                        /* Create an element to be added to the array */
                        ALLOC_ZVAL(element);
                        /* Call ourself again to handle the base type conversion */
                        /* If SafeArrayGetElement proclaims to allocate */
                        /* memory for a BSTR, so the recursive call frees */
                        /* the string correctly */
-                       if (FAILURE == php_variant_to_pval(&vv, element, persistent, codepage))
+                       if (FAILURE == php_variant_to_pval(&vv, element, persistent, codepage TSRMLS_CC))
                        {
                                /* Error occurred setting up array element */
                                /* Error was displayed by the recursive call */
@@ -560,10 +557,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                add_index_zval(pval_arg, ii, element);
                        }
                }
-        SafeArrayUnlock(array);
-               /* Clean up the SafeArray since that is our responsibility */
-               SafeArrayDestroyData(array);
-               SafeArrayDestroyDescriptor(array);
+               SafeArrayUnlock(array);
        }
        else switch(var_arg->vt & ~VT_BYREF)
        {               
@@ -633,7 +627,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                switch(VarBstrFromDec(&V_DECIMAL(var_arg), LOCALE_SYSTEM_DEFAULT, 0, &unicode_str))
                                {
                                        case S_OK:
-                                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(unicode_str, &Z_STRLEN_P(pval_arg), persistent, codepage);
+                                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(unicode_str, &Z_STRLEN_P(pval_arg), persistent, codepage TSRMLS_CC);
                                                Z_TYPE_P(pval_arg) = IS_STRING;
                                                break;
 
@@ -676,20 +670,18 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                case VT_VARIANT:
-                       php_variant_to_pval(V_VARIANTREF(var_arg), pval_arg, persistent, codepage);
+                       php_variant_to_pval(V_VARIANTREF(var_arg), pval_arg, persistent, codepage TSRMLS_CC);
                        break;
 
                case VT_BSTR:
                        if(V_ISBYREF(var_arg))
                        {
-                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(*V_BSTRREF(var_arg), &Z_STRLEN_P(pval_arg), persistent, codepage);
-                               SysFreeString(*V_BSTRREF(var_arg));
+                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(*V_BSTRREF(var_arg), &Z_STRLEN_P(pval_arg), persistent, codepage TSRMLS_CC);
                                efree(V_BSTRREF(var_arg));
                        }
                        else
                        {
-                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(V_BSTR(var_arg), &Z_STRLEN_P(pval_arg), persistent, codepage);
-                               SysFreeString(V_BSTR(var_arg));
+                               Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(V_BSTR(var_arg), &Z_STRLEN_P(pval_arg), persistent, codepage TSRMLS_CC);
                        }
 
                        Z_TYPE_P(pval_arg) = IS_STRING;
@@ -739,8 +731,8 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                {
                                        char *error_message;
 
-                                       error_message = php_COM_error_message(hr);
-                                       php_error(E_WARNING, "Unable to obtain IDispatch interface:  %s", error_message);
+                                       error_message = php_COM_error_message(hr TSRMLS_CC);
+                                       php_error(E_WARNING,"Unable to obtain IDispatch interface:  %s", error_message);
                                        LocalFree(error_message);
 
                                        V_DISPATCH(var_arg) = NULL;
@@ -758,11 +750,9 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                                }
                                else
                                {
-                                       TSRMLS_FETCH();
-
                                        ALLOC_COM(obj);
-                                       php_COM_set(obj, V_DISPATCH(var_arg), TRUE);
-
+                                       php_COM_set(obj, &V_DISPATCH(var_arg), TRUE TSRMLS_CC);
+                                       
                                        ZVAL_COM(pval_arg, obj);
                                }
                        }
@@ -824,7 +814,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
                        break;
 
                default:
-                       php_error(E_WARNING, "Unsupported variant type: %d (0x%X)", V_VT(var_arg), V_VT(var_arg));
+                       php_error(E_WARNING,"Unsupported variant type: %d (0x%X)", V_VT(var_arg), V_VT(var_arg));
                        ZVAL_NULL(pval_arg);
                        ret = FAILURE;
                        break;
@@ -832,7 +822,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent,
        return ret;
 }
 
-PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage)
+PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage TSRMLS_DC)
 {
        OLECHAR *unicode_str;
 
@@ -854,17 +844,17 @@ PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage)
                switch(GetLastError())
                {
                        case ERROR_NO_UNICODE_TRANSLATION:
-                               php_error(E_WARNING, "No unicode translation available for the specified string");
+                               php_error(E_WARNING,"No unicode translation available for the specified string");
                                break;
                        default:
-                               php_error(E_WARNING, "Error in php_char_to_OLECHAR()");
+                               php_error(E_WARNING,"Error in php_char_to_OLECHAR()");
                }
        }
 
        return unicode_str;
 }
 
-PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent, int codepage)
+PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent, int codepage TSRMLS_DC)
 {
        char *C_str;
        uint length = 0;
@@ -884,7 +874,7 @@ PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int per
                C_str = (char *) pemalloc(sizeof(char), persistent);
                *C_str = 0;
 
-               php_error(E_WARNING, "Error in php_OLECHAR_to_char()");
+               php_error(E_WARNING,"Error in php_OLECHAR_to_char()");
        }
 
        if(out_length)
@@ -903,7 +893,7 @@ static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC)
 
        /* fetch the comval structure */
        zend_hash_index_find(Z_OBJPROP_P(pval_arg), 0, (void **) &comval_handle);
-       obj = (comval *) zend_list_find(Z_LVAL_P(*comval_handle), &type);
+       obj = (comval *)zend_list_find(Z_LVAL_P(*comval_handle), &type);
        if(!obj || (type != IS_COM) || !C_ISREFD(obj))
        {
                VariantInit(var_arg);
@@ -915,4 +905,4 @@ static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC)
        }
 }
 
-#endif /* PHP_WIN32 */
+#endif /* PHP_WIN32 */
\ No newline at end of file
index 53d19a21dee4e16a1191da95b8062ecc6a503253..a55d66c57b3141030c979a8cf56898856397fb22 100644 (file)
@@ -3,11 +3,11 @@
 
 BEGIN_EXTERN_C()
 
-extern void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage);
-extern void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage);
-extern int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent, int codepage);
-extern OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage);
-extern char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent, int codepage);
+PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage TSRMLS_DC);
+PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage TSRMLS_DC);
+PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int persistent, int codepage TSRMLS_DC);
+PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage TSRMLS_DC);
+PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent, int codepage TSRMLS_DC);
 
 END_EXTERN_C()
 
index 3a2108f4153f2ce219c95facc99ae58bb8cdba5f..c44c808fe04f834f29af7c01a3ce60ac3d40d54c 100644 (file)
@@ -10,22 +10,30 @@ BEGIN_EXTERN_C()
 PHP_MINIT_FUNCTION(COM);
 PHP_MSHUTDOWN_FUNCTION(COM);
 
-PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR* pVarResult);
-PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId);
-PHPAPI HRESULT php_COM_release(comval *obj);
-PHPAPI HRESULT php_COM_addref(comval *obj);
-PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* pDisp, int cleanup);
-PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup);
-
-int php_COM_get_le_comval();
+PHP_FUNCTION(com_load);
+PHP_FUNCTION(com_invoke);
+PHP_FUNCTION(com_addref);
+PHP_FUNCTION(com_release);
+PHP_FUNCTION(com_propget);
+PHP_FUNCTION(com_propput);
+PHP_FUNCTION(com_load_typelib);
+PHP_FUNCTION(com_isenum);
+
+PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR*  pDispParams, VARIANT FAR* pVarResult, char **ErrString TSRMLS_DC);
+PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId TSRMLS_DC);
+PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC);
+PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC);
+PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC);
+PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* pDisp, int cleanup TSRMLS_DC);
+PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup TSRMLS_DC);
+PHPAPI char *php_COM_error_message(HRESULT hr TSRMLS_DC);
+PHPAPI int php_COM_get_le_comval();
+PHPAPI int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value);
+PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_reference);
+PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
 
 zend_module_entry COM_module_entry;
-zend_class_entry com_class_entry;
-
-pval php_COM_get_property_handler(zend_property_reference *property_reference);
-int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value);
-char *php_COM_error_message(HRESULT hr);
-void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
+zend_class_entry COM_class_entry;
 
 #ifdef DEBUG
        extern int resourcecounter;
index 5e6d51f82180943bd55dbfd755ac3bf85a5a46a9..2447d066ad66a20ff6897af9e4955d4ed75f427a 100644 (file)
@@ -3,14 +3,19 @@
 
 #if PHP_WIN32
 
-#include "variant.h"
+BEGIN_EXTERN_C()
 
-extern int php_VARIANT_get_le_variant();
+#include "conversion.h"
+#include "variant.h"
 
 PHP_MINIT_FUNCTION(VARIANT);
 PHP_MSHUTDOWN_FUNCTION(VARIANT);
 
-extern zend_module_entry VARIANT_module_entry;
+PHPAPI int php_VARIANT_get_le_variant();
+
+zend_module_entry VARIANT_module_entry;
+
+END_EXTERN_C()
 
 #define VARIANT_module_ptr &VARIANT_module_entry
 
index 5d61100d64c4194a91c17972047aa4861c1072dc..b8f2590101d77660ec0813e22dfda9bbfae3470a 100644 (file)
 
 #include "php.h"
 #include "php_ini.h"
-#include "variant.h"
-#include "conversion.h"
 #include "ext/standard/info.h"
+#include "php_VARIANT.h"
 
 #include <unknwn.h> 
 
-PHP_MINIT_FUNCTION(VARIANT);
-PHP_MSHUTDOWN_FUNCTION(VARIANT);
-
-int php_VARIANT_get_le_variant();
-void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
-pval php_VARIANT_get_property_handler(zend_property_reference *property_reference);
-static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value);
-void php_register_VARIANT_class(TSRMLS_D);
-static void php_variant_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
+static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value TSRMLS_DC);
+static int php_VARIANT_set_property_handler(zend_property_reference *property_reference, pval *value);
+static pval php_VARIANT_get_property_handler(zend_property_reference *property_reference);
+static void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
+static void php_VARIANT_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
+static void php_register_VARIANT_class(TSRMLS_D);
 
 static int le_variant;
 static int codepage;
-
 static zend_class_entry VARIANT_class_entry;
 
 function_entry VARIANT_functions[] = {
@@ -66,7 +61,7 @@ zend_module_entry VARIANT_module_entry = {
 
 PHP_MINIT_FUNCTION(VARIANT)
 {
-       le_variant = zend_register_list_destructors_ex(php_variant_destructor, NULL, "VARIANT", module_number);
+       le_variant = zend_register_list_destructors_ex(php_VARIANT_destructor, NULL, "VARIANT", module_number);
 
        /* variant datatypes */
        REGISTER_LONG_CONSTANT("VT_NULL", VT_NULL, CONST_CS | CONST_PERSISTENT);
@@ -97,10 +92,18 @@ PHP_MINIT_FUNCTION(VARIANT)
        REGISTER_LONG_CONSTANT("CP_ACP", CP_ACP, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("CP_MACCP", CP_MACCP, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("CP_OEMCP", CP_OEMCP, CONST_CS | CONST_PERSISTENT);
-       REGISTER_LONG_CONSTANT("CP_SYMBOL", CP_SYMBOL, CONST_CS | CONST_PERSISTENT);
-       REGISTER_LONG_CONSTANT("CP_THREAD_ACP", CP_THREAD_ACP, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("CP_UTF7", CP_UTF7, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("CP_UTF8", CP_UTF8, CONST_CS | CONST_PERSISTENT);
+#ifdef CP_SYMBOL
+       REGISTER_LONG_CONSTANT("CP_SYMBOL", CP_SYMBOL, CONST_CS | CONST_PERSISTENT);
+#else
+#      error   "CP_SYMBOL undefined"
+#endif
+#ifdef CP_THREAD_ACP
+       REGISTER_LONG_CONSTANT("CP_THREAD_ACP", CP_THREAD_ACP, CONST_CS | CONST_PERSISTENT);
+#else
+#      error   "CP_THREAD_ACP undefined"
+#endif
 
        php_register_VARIANT_class(TSRMLS_C);
        return SUCCESS;
@@ -111,12 +114,12 @@ PHP_MSHUTDOWN_FUNCTION(VARIANT)
        return SUCCESS;
 }
 
-int php_VARIANT_get_le_variant()
+PHPAPI int php_VARIANT_get_le_variant()
 {
        return le_variant;
 }
 
-void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
+static void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
 {
        pval *object = property_reference->object;
        zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data;
@@ -137,17 +140,17 @@ void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_proper
                                break;
                        case 1:
                                getParameters(ht, 1, &data);
-                               php_pval_to_variant(data, pVar, codepage);
+                               php_pval_to_variant(data, pVar, codepage TSRMLS_CC);
                                codepage = CP_ACP;
                                break;
                        case 2:
                                getParameters(ht, 2, &data, &type);
-                               php_pval_to_variant_ex(data, pVar, type, codepage);
+                               php_pval_to_variant_ex(data, pVar, type, codepage TSRMLS_CC);
                                codepage = CP_ACP;
                                break;
                        case 3:
                                getParameters(ht, 3, &data, &type, &code_page);
-                               php_pval_to_variant_ex(data, pVar, type, codepage);
+                               php_pval_to_variant_ex(data, pVar, type, codepage TSRMLS_CC);
                                convert_to_long(code_page);
                                codepage = code_page->value.lval;
                                break;
@@ -173,14 +176,14 @@ void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_proper
        }
 }
 
-
-pval php_VARIANT_get_property_handler(zend_property_reference *property_reference)
+static pval php_VARIANT_get_property_handler(zend_property_reference *property_reference)
 {
        zend_overloaded_element *overloaded_property;
        int type;
+       TSRMLS_FETCH();
+
        pval result, **var_handle, *object = property_reference->object;
        VARIANT *var_arg;
-       TSRMLS_FETCH();
 
        /* fetch the VARIANT structure */
        zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &var_handle);
@@ -202,7 +205,7 @@ pval php_VARIANT_get_property_handler(zend_property_reference *property_referenc
                        case OE_IS_OBJECT:
                                if(!strcmp(overloaded_property->element.value.str.val, "value"))
                                {
-                                       php_variant_to_pval(var_arg, &result, 0, codepage);
+                                       php_variant_to_pval(var_arg, &result, 0, codepage TSRMLS_CC);
                                }
                                else if(!strcmp(Z_STRVAL(overloaded_property->element), "type"))
                                {
@@ -226,13 +229,14 @@ pval php_VARIANT_get_property_handler(zend_property_reference *property_referenc
        return result;
 }
 
-int php_VARIANT_set_property_handler(zend_property_reference *property_reference, pval *value)
+static int php_VARIANT_set_property_handler(zend_property_reference *property_reference, pval *value)
 {
        zend_overloaded_element *overloaded_property;
        int type;
+       TSRMLS_FETCH();
+
        pval **var_handle, *object = property_reference->object;
        VARIANT *var_arg;
-       TSRMLS_FETCH();
 
        /* fetch the VARIANT structure */
        zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &var_handle);
@@ -242,12 +246,12 @@ int php_VARIANT_set_property_handler(zend_property_reference *property_reference
                return FAILURE;
 
        overloaded_property = (zend_overloaded_element *) property_reference->elements_list->head->data;
-       do_VARIANT_propset(var_arg, &overloaded_property->element, value);
+       do_VARIANT_propset(var_arg, &overloaded_property->element, value TSRMLS_CC);
        zval_dtor(&overloaded_property->element);
        return SUCCESS;
 }
 
-static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value)
+static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value TSRMLS_DC)
 {
        pval type;
 
@@ -415,17 +419,17 @@ static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value)
                return FAILURE;
        }
 
-       php_pval_to_variant_ex(value, var_arg, &type, codepage);
+       php_pval_to_variant_ex(value, var_arg, &type, codepage TSRMLS_CC);
 
        return SUCCESS;
 }
 
-static void php_variant_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+static void php_VARIANT_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 {
-       efree(rsrc);
+       FREE_VARIANT(rsrc->ptr);
 }
 
-void php_register_VARIANT_class(TSRMLS_D)
+static void php_register_VARIANT_class(TSRMLS_D)
 {
        INIT_OVERLOADED_CLASS_ENTRY(VARIANT_class_entry, "VARIANT", NULL,
                                                                php_VARIANT_call_function_handler,
index ec25ee4e4b8272edceef85db599e67e68eb6ba97..ce5b4e66ae959714a091a3fc81c3ea26600f2540 100644 (file)
@@ -3,7 +3,13 @@
 
 #if PHP_WIN32
 
-#define ALLOC_VARIANT(v)       (v) = (VARIANT *) emalloc(sizeof(VARIANT))
+#define ALLOC_VARIANT(v)       (v) = (VARIANT *) emalloc(sizeof(VARIANT));             \
+                                                       VariantInit(v);
+
+#define FREE_VARIANT(v)                VariantClear(v);                                                                \
+                                                       efree(v);
+
+
 #define IS_VARIANT                     php_VARIANT_get_le_variant()
 
 #endif  /* PHP_WIN32 */